OmniAICreator/Qiita-1.07M huggingface dataset:
ノーコード／ローコードのServiceNow(サービスナウ)のご紹介 – Software as a Service (SaaS)

弊社が案件を複数をやらせていただいているノーコード／ローコードのソリューションのServiceNowのご紹介です。

## ServiceNowとは
ServiceNowとはSaaS クラウド上にあるソフトウェアを利用した製品の提供に基づいています。みなさんがソフトウェアを持っていなかったとしても、クラウドつまりインターネットを通じて自分に合った、企業向けのサービスをインターネット上で利用できます。

ServiceNowは、ワークフロー構築やサポートデスクの運用管理といった社内業務に関するシステムを一元化して運用・管理できるクラウドサービスです。デジタル化、DX（デジタルトランスフォーメンション）は企業の生産性や競争力を高めていくためには不可欠です。

## ServiceNowのすごい所！

![Picture 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6544/548f82de-9385-2519-acc3-223d5b9b8ec7.png)


ServiceNowは2018年に世界で最も革新的な企業というランキングでリストの対象となった最初の年ながら1位を獲りました。

ServiceNowは多くのパートナー企業を持ち、業務プロセスや業務アプリケーション、各種システムが孤立しているものを一つのデータベースに統合できます。

そして、私も学習をしたのですがServiceNowのFundamental コースが300ドルかかるところ、[期間限定無料](https://community.servicenow.com/community?id=community_blog&sys_id=db32f40adb7bcd901227db85ca9619c2)提供されています。

![servicenow2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6544/04addee9-ca9c-9d05-95cc-f0bc189cb203.png)


## 多くの企業で導入されている理由
では、なぜServiceNowがそこまで使われているのでしょうか？それは、以下のような便利な機能がServiceNowから標準で提供されているからです。その中でも今回はITSM(IT Service Management)という機能に触れていきます。

<ul>
 	<li>IT Service Management</li>
 	<li>IT Operations Management</li>
 	<li>IT Business Management</li>
 	<li>IT Asset Management</li>
 	<li>DevOps</li>
 	<li>Security Operations</li>
 	<li>Governance, Risk, and Compliance</li>
 	<li>Telecommunications Network Performance Management</li>
 	<li>Customer Service Management</li>
 	<li>Field Service Management</li>
 	<li>Connected Operations</li>
 	<li>Financial Services Operations</li>
 	<li>Telecommunications Network Performance Management</li>
 	<li>HR Service Delivery</li>
</ul>


IT Service Management：サービスの可視化や統合

![servicenow3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6544/405648a3-726a-6492-9987-6412c03004df.png)


インシデントを管理し重要度の高いインシデントの特定、追跡、解決を迅速に対応できます。まだまだペーパーワークが残っている時代、クラウドサービスを利用しワークフローの改善をServiceNowで管理し、今までやっていた従業員の複雑化していた作業を効率化することができます。

![servicenow4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6544/4e661d3e-3980-549c-ab60-c08425bab46f.png)


そして1週間かかっていた承認作業がPCまたはネイティブモバイルアプリを使いクラウド上で管理することによりリアルタイム対応で即時に対応することができます。さらにAIを活用することもできインシデントの解決策を提示してくれ即時解決してくれるなど色々な機能があります。

## 感想

ServiceNowによるワークフローの効率化は将来的コスト削減や従業員の働き方改革に役立つと思います。やっぱりゼロからシステム開発するのは時間とコストがかかると思います。さまざまな既存の良いシステム選択し、ServiceNowを通して繋げることによりその手間を省けるのは非常に大きいと思います。

ここでは紹介でききませんでしたがHRSD（HR Service Delivery）で人事でワークフロー：従業員のオンボーディング、給与、転勤、異動、退職などのプロセスを自動化する。などなどServiceNowで提供されているサービスでやれることは無限大です。

まだまだ私も学んでいる身であり、ServiceNow提供のCSA（Certified System Administrator）を知識を深めるために取得しないといけません。まだまだ日本語での情報が探しづらいServiceNowですが、この記事が少しでも役に立てば光栄です。

ServiceNow Course は無料で提供されているので皆さんもやってみてはどうでしょうか。
〇【PowerApps開発ポリシー（その２）】コレクション変数・グローバル変数の範囲は、サインインユーザ単位なのか調べてみた

変数には、コレクション変数・コンテキスト変数・グローバル変数があるが状況に応じて使い分けるポリシーが必要である。

・グローバル変数	　　アプリ全体で利用できる変数	
・コンテキスト変数	画面内で利用できる変数	
・コレクション変数　　アプリ全体で利用できる変数

と、ここまでは、ググればすぐわかる情報であるが
ユーザ単位（セッション単位）に、グローバル変数、コレクション変数は共通利用なのか情報がなかったので調べてみた

調べた結果はコレクション変数・グローバル変数の範囲は、サインインユーザ単位で保持されることがわかった。

＜検証方法＞
以下のアプリを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783140/86060958-a2e0-89b3-4402-c5cc40cc5ae1.png)
ボタン１：Set(_count, _count+1)
ボタン２：Collect(TestCol, {Itm:"a"});

変数がユーザを超えて共通利用されていれば、AさんBさん同じ値になるはずであるがならなかった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783140/07c4134f-46cc-9ad9-1fd4-138de02fb6a3.png)
M1MacのVMWareFusionでArm版Ubuntuを動かす！

仕事でRaspiを使用しているのだけど、Mac環境内で動作チェックするのにとりあえずUbuntu動けば何とかなりそうだな！と言う事でインストールして動かしてみた。
以前から何度かやっていたのだけど動かなかったので、今回デスクトップ環境の構築までをメモ

VVMWareFusionはTecプレビュー版が無料で利用可能。
ダウンロードにはVMWareアカウントが必要。

[VMware Fusion パブリック テック プレビュー 22H2](https://customerconnect.vmware.com/jp/downloads/get-download?downloadGroup=FUS-PUBTP-22H2)

Arm版のUbuntuは20.04.5を用意する。
最新の22.04.1はkernelの問題でブート出来ない。

[Ubuntu 20.04.5 LTS](https://releases.ubuntu.com/focal/)

上記組み合わせでインストール後、

`sudo apt update`
`sudo apt upgrade -y`
`sudo apt install open-vm-tools -y`

アップデートとVMWareツールをインストールして完了。

Ubuntuインストール時はEnglishしか選択出来ないので、必要に応じて日本語の設定を行う。

## 参考

[VMware Fusion for Apple Silicon (m1 CPU)にUbuntuをインストール](https://www.blog.slow-fire.net/2022/04/20/vmware-fusion-for-apple-silicon-m1-cpu%E3%81%ABubuntu%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/)
再帰と関数

# 問題１の気づき
この式を繰り返す。
ユーグリッドの互除法のことを知らなかった。

## ユーグリッドの互除法
2つの自然数の最大公約数について、次の定理が成り立ちます。

### 割り算と最大公約数
2つの自然数 𝑎, 𝑏 について，𝑎 を 𝑏 で割ったときの商を 𝑞，余りを 𝑟 とすると

「𝑎 と 𝑏 の最大公約数」は，「𝑏 と 𝑟 の最大公約数」に等しい。

この割り算と最大公約数の定理を使って、2つの自然数の最大公約数を求める方法が、次の ユークリッドの互除法 です。

### ユークリッドの互除法
次のように2つの自然数 𝑎, 𝑏 の最大公約数を求める方法を ユークリッドの互除法，または単に互除法という。

𝑎 を 𝑏 で割り，余り 𝑟 を求める
𝑏 を①で求めた余り 𝑟 で割り，その余り 𝑟1 を求める
𝑟 を②で求めた余り 𝑟1 で割り，その余り 𝑟2 を求める…
⋯⋯
この操作を繰り返すと余りが必ず0になる（割り切れる）。余りが0になったときの割る数が，求める最大公約数になる。

出典 https://rikeilabo.com/euclids-parity-method#1

### 気づき
算出された割った数で割ることを繰り返すことで最大公約数を求めることができるのか。
しかし
これも問題文を読み且つタイトルを見るとこれも再帰のことを言っていることに気づく。
これも問題の慣れが必要なのか。

# 出典 

https://gihyo.jp/book/2022/978-4-297-12375-8
docker-compose.ymlのbind mountsと(named) volumesのときのコンテナー内のファイルの扱いの違い

## bind mounts のとき
コンテナー内のファイルやディレクトリーは無視されて見えなくなる。イメージとしては Linux の mount コマンドを実行したときと同じ。

## (named) volumes のとき
空の (named) volumes をコンテナー内のディレクトリーにマウントしたとき、コンテナー内のファイルやディレクトリーは (named) volumes にコピーされる
空ではない (named) volumes をコンテナー内のディレクトリーにマウントしたときは、コンテナー内のファイルやディレクトリーは無視されて見えなくなる。イメージとしては Linux の mount コマンドを実行したときと同じ。

## 参考
https://docs.docker.com/storage/#tips-for-using-bind-mounts-or-volumes
[laravel phpunit] factoryで外部キーを設定する

## はじめに
外部キーのあるFactoryに対し、外部キーを設定し、リレーションする方法を調べてみました。
##
```php:QuestionFactory
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\User;

class QuestionFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
                'question' => $this->faker->text(),
                'answer' => $this->faker->text(),
                'share' => false,
                'user_id' => function() {
                    return User::factory()->create()->id;
                },
            ];
    }
}
```

```php:TestControllerTest

    public function setUp(): void
    {
        parent::setUp();
        //userFactory作成
        $this->user = User::factory()->create();
        //user_idを作成したuserFactoryのidで上書き
        $this->question = Question::factory()->create(['user_id' => $this->user->id]);
    }
```
## 参考

https://readouble.com/laravel/8.x/ja/database-testing.html
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その028

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: アプリケーションと活動
生産性とコラボレーションの学習

にある練習問題1問目をご紹介します

https://www.youtube.com/watch?v=CiyH4Ojg0Mc

<iframe width="560" height="315" src="https://www.youtube.com/embed/CiyH4Ojg0Mc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


問題はこちらです

![028.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/d7bf4d77-17e2-b3ca-dfab-52db3f9e4aa6.png)


正解はBですね

行動には終日行動という項目があります


この終日行動にチェックをつければ終日の行動が作成できますね

行動の動きは動画で説明していますのでぜひ動画も確認ください


https://www.youtube.com/watch?v=CiyH4Ojg0Mc

<iframe width="560" height="315" src="https://www.youtube.com/embed/CiyH4Ojg0Mc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
図解 Windowsでのターミナルとシェル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43992/e0de26f0-1c10-2aba-e258-15eb97448499.png)
## 結論
windows terminal 使え

## 解説

### cmd
古典的なコマンド実行環境（より古いのは割愛）。
cmd はターミナル（コンソール）なのかシェルなのか、が整理したかった発端。結論としては、一体化しているがシェルとしても実行できる、となる。

### powershell
マイクロソフトの新たなクロスプラットフォームコマンド実行環境、だそうな。確かにWindowsでもLinuxでもMacでも動く、のでシェルに分類はされる。実行バイナリは一体化している。

### windows terminal
疑似ターミナル。ストアからインストールする。インストール後 `*.bat` ファイルなどが windows terminal で実施されるようになる。たまに紐付けが壊れる。

### wsl2
Windows で Linux Subsystem を実行するプラットフォーム。任意のシェルを実行できる。

### msys2
Windows で Posix互換レイヤーを提供する。任意のシェルを実行できる。
オンライントランザクション処理(OLTP)  とは

## 勉強前イメージ

DBのなんか処理みたいなやつ？

## 調査

### オンライントランザクション処理 とは

On-Line Transaction Processing を略して OLTP とも呼ばれ、データ処理方法の一つです。
ホストコンピュータと端末間での一連の処理を行う仕組みです。

そもそも `トランザクション` とは、取引の一連の流れのことを指します。
例えばある人が別の銀行にお金を振り込む際はコンピュータ上では以下のような流れがあります。

1. 元の銀行からお金を引き出す
2. 振込先の銀行にお金を入金する

もし1が失敗したとしても2が成功というようなことが出来たらだめで、
1が失敗したら2も失敗するようなプロセスにならないといけません。
この一連の流れを不整合が起きないようにまとめて管理して処理することをトランザクション処理と言います。

それでは `オンライントランザクション処理` とはリアルタイム性があることを指しています。
ネット銀行で振込などしても翌営業日にしか反映されないことがあります、これはリアルタイム性があるとはいえません。
逆に銀行のATMなどはすぐにレスポンスが返ってくるので、リアルタイム性があるといえます。
すぐにユーザのレスポンスに答えるのが オンライントランザクション処理 になります。

## 勉強後イメージ

たしかにそうか・・・考えればわかるようなものね。

## 参考

- [OLTPとは？OLAPやDWHとの違いをわかりやすく解説](https://www.imkk.jp/blog/what-is-oltp.html)
- [データ分析初心者は押さえておきたいOLTPとは？OLAPと何が違うの？](https://data.wingarc.com/what-is-oltp-13329)
Vagrant：BOXとVMの保存場所を変更する

# やりたいこと
* VagrantのBOXとVMの保存場所を変更したい

デフォルトの保存場所はCドライブのユーザーディレクトリですが、容量が大きいのでDドライブに変更します。

# Vagrant Boxの保存場所の変更
Vagrantのホームディレクトリ（BOXのデフォルトの保存場所）は次のとおりです。
`C:\Users\ユーザー名\.vagrant.d`

こちらを変更していきます。

## 1. Vagrantのホームディレクトリの変更
この場所を変更するには、システム環境変数もしくはユーザー環境変数にBoxファイルを保存するパスを指定します。

1. Winマーク上で右クリック→「設定」→「システム」→「バージョン情報」→「システムの詳細設定」をクリックする
1. 「システムのプロパティ」が開くので、「詳細設定」タブ→「環境変数」をクリックする
1. 「ユーザー環境変数」もしくは「システム環境変数」の「新規」をクリックする
1. 「変数名」と「変数値」を記入する
	例：
	* 変数名：`VAGRANT_HOME`
	* 変数値：`D:\Vagrant\.vagrant.d`

	![USERPROFILE](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230850/76efd010-72f8-7199-87de-f1d7669c6e70.png)


## 2. Vagrant Boxの移動
Boxファイルを移動します。

1. Vagrantのホームディレクトリ `.vagrant.d` の中身を、新しいフォルダーに移動する

	例：
	* 移動元：`C:\Users\ユーザー名\.vagrant.d`
	* 移動先：`D:\Vagrant\.vagrant.d`

1. 移動がおわったら、移動元のフォルダーは削除するかリネームする

## 3. 確認
移動したBoxファイルが正しく認識されているか確認します。

1. 環境変数を反映するためにPCを再起動する
1. 次のコマンドを実行する

	```cmd
	vagrant box list
	```

Boxの一覧が正しく表示されれば保存場所の変更は完了です。
保存済みのBoxが表示されなかったり、削除もしくはリネームした `C:\Users\ユーザー名\.vagrant.d` フォルダーが再作成されていれば、環境変数が正しく登録できていない可能性があります。
タイプミスをしていないか、再起動し忘れていないか確認しましょう。

# VirtualBoxの保存場所の変更
VirtualBoxのデフォルトの仮想マシンフォルダーは次のとおりです。
`C:\Users\ユーザー名\VirtualBox VMs`

こちらを変更していきます。

## 1. VirtualBoxのデフォルトディレクトリの変更
「Oracle VM VirtualBox マネージャー」の設定でデフォルトディレクトリーを変更します。

1. 「Oracle VM VirtualBox マネージャー」を起動する
1. 「ファイル」→「環境設定」をクリックし、「一般」タブの「デフォルトの仮想マシンフォルダー」のパスを変更する

	![環境設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230850/fa2d64a5-c20b-b10d-276d-8365bc3677b9.png)

	![folder](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230850/4cf3f6ee-0b85-2ce8-030e-086668f4e42d.png)

## 2. VirtualBox VMsの移動
VMファイルを移動します。

1. `VirtualBox VMs` の中身を、新しいフォルダーに移動する
	例：
	* 移動元：`C:\Users\ユーザー名\VirtualBox VMs`
	* 移動先：`D:\VirtualBox\VirtualBox VMs`

1. 移動がおわったら、移動元のフォルダーは削除するかリネームする

## 3. VirtualBox VMsの再作成
新しいフォルダーを仮想マシンへ反映するために、「Oracle VM VirtualBox マネージャー」から仮想マシンを一度除去して、再作成します。
仮想マシンの電源はオフにしておいてください。

1. 「Oracle VM VirtualBox マネージャー」を起動する
1. 対象の仮想マシン上で右クリック→「除去」→「除去のみ」をクリックして仮想マシンを除去する
1. 「仮想マシン」→「追加」をクリックし、対象の移動先のフォルダーの `.vbox` ファイルを選択する
1. 対象マシンが再作成されるので、起動できるか確認する

# おわりに
これでVagrantのBOXとVMの保存場所が変更できます。
容量が大きいので、保存場所が変更できると便利です。


# 参考にしたサイト
<!-- * [Vagrant BOXとVMの保存先を変更する方法 【ブログ】 » 群馬県高崎市の写真撮影・ホームページ制作会社| Kiraba（キラバ）](https://kiraba.jp/change-save-point-vagrant-box-and-virtual-machine/)
* [vagrantのboxフォルダ変更手順メモ - Qiita](https://qiita.com/sugard12/items/85b2e70c87a354675a0e) -->
<!-- * [WindowsでVagrant環境を作ろう！容量足りない場合は作業フォルダ変更で対応 | サイト構築日記](http://memories.zal.jp/WP/blog/20160214_2707.html) -->
* [Vagrant関連ファイルの保存パスを変更する - Qiita](https://qiita.com/dhun/items/dd0e30f3109416028189)
* [VirtualBoxの仮想マシンフォルダ変更手順メモ - Qiita](https://qiita.com/sugard12/items/8b4f420b3afed79fe003)
情報処理安全確保支援士試験に合格しました

令和 4 年度の情報処理安全確保支援士試験に合格しましたので、体験記です。

得点は以下の通りでした。
![score.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178830/7ba06e84-1778-cbbb-2b34-0e93c5f5dccf.png)

## 受験者のスペック

- 高度試験は [NW](https://qiita.com/hugehoge/items/1013283c172dbfd6d0bc) → [DB](https://qiita.com/hugehoge/items/abad82a2a25e84fe39e6) ときて、今回 SC
- 本業は iOS エンジニア
- XSS 、 CSRF くらいは理解している

## 事前学習

2 週間程度の期間で、参考書は以下 1 冊で行きました。

https://www.shoeisha.co.jp/book/detail/9784798173191

ネットワークスペシャリスト受験時の勉強内容と一応仕事が Web 屋さんということもり、カバーできる領域が大きく、参考書についても不明点を重点的に抑える形で 1 周。その後は過去問を 3 年分ほど回しました。

過去問での得点自体も非常に良好で、これまでの高度試験に比較すると非常に手応えのある状態で本番を迎えられました。

## 試験当日
### 午前 Ⅱ

午前 Ⅰ は免除のため、午前 Ⅱ からのスタートでした。
基本的には躓くところもなく、快調なスタートを切れました。

### 午後 Ⅰ

大問 3 問を完答 + その中で自身のある 2 問を余裕をもって選べるという、今までの高度試験ではなかったほど時間的な余裕がありました。
(実際の点数は想定より低かったですが。。)

過去問を回していたときもそうだったのですが、情報処理安全確保支援士試験では時間的に追われるということが少なかったです。

### 午後 Ⅱ

午後 Ⅱ についても、終了後にある程度自信をもって合格しただろう程度の感触はありました。

ただ、片方の大問で個人的に完全に未知だった攻撃手法 (CDN を悪用したドメインフロスティング攻撃) に関する設問があったため、これだけ終了後に即ググりました。

https://teamt5.org/jp/posts/hiding-in-plain-sight-obscuring-c2s-by-abusing-cdn-services/

https://mymanfile.com/?p=2860

https://qiita.com/Isato-Hiyama/items/8798b144ae82957814ff

個人的な観測範囲から漏れていた攻撃手法について試験を通じて学ぶことができたので、ある意味お得な感覚でした。
(試験の大問選択では避けましたが。。。)

## 感想

セキュスペ時代からなんとなく聞いてはいたのですが、やはり NW や DB と比較するとだいぶ与し易いというのが正直な感想です。

特にフロント寄りのエンジニアからすると、領域としてもかなり近しい部分が多いため、高度試験の入門としては最適かなという気がします。
gpgコマンド、gpg-agent

●GnuPG（GNU Privacy Guard）
暗号化プログラム。ファイルの暗号化や復号を行う。

gpg [オプション]

主なオプション
・—gen-key公開鍵暗号方式の鍵ペアを生成する
・—export 公開鍵をエクスポートする
・—import 公開鍵をインポートする
・—list-keys 公開鍵を一覧表示する
・—sign ファイルに署名する
・—verify ファイルの署名を検証する
・-e ファイル名　暗号化データを受け取る側の公開鍵を使用してファイルを暗号化する
・-o ファイル名　出力ファイル名を指定する
・-r メールアドレス　暗号化に使用する公開鍵の持ち主のメールアドレスを指定する

※--gen-keyオプションを使用すると、「~/.gnupg/」ディレクトリの下に、公開鍵暗号方式の秘密鍵と公開鍵のキーペアなどが作成される

●GnuPGの暗号化アルゴリズムは共通鍵暗号方式や公開鍵暗号方式に対応

・共通鍵暗号方式
暗号化と復号に共通の鍵を用いる

・公開鍵暗号方式
公開鍵を使って暗号化したものをペアとなる秘密鍵で復号。
送信者は暗号化ファイルを送りたい相手の公開鍵でファイルを暗号化して相手に送り。暗号化ファイルを受け取った受信者は、自身の秘密鍵で復号を行う。

●・gpg-agent
gpg-agentというデーモンプログラムが、秘密鍵を管理し、パスフレーズによる認証状態を一定期間キャッシュ。SSHにおけるssh-agentと同様

※「ssh-add」コマンドで秘密鍵とペアになるパスフレーズを入力して鍵情報を登録する必要がある
[OpenCV]inRange(), floodFill()で取得したマスクの「座標」と「元の色」を取得する


inRange()で色範囲を絞ってマスクを取得したとき、
範囲内の色のピクセルの座標と、実際の各ピクセルのBGR情報の取得の、numpyを駆使した実装方法をご紹介します。

np.where()の戻り値は、条件を満たす**要素のインデックスのリスト**なので、今回のケースでは要素のインデックス＝y,x座標のため、簡単に座標が取得できちゃいます

また、**ファンシーインデックス**で配列の[]にリストを渡すことで複数の要素を取得可能なので
取得した座標のリストをそのまま渡すことで、たった一行でマスクしたピクセルの実際のBGRのリストを取得が可能！
この手の処理に多重forブン回さなくて済むpythonサイコー🤗


# inRange()で取得したマスクの座標・元の色を取得
```python
import cv2
import numpy as np

img = cv2.imread(r"src.bmp")
    
lower = (21, 61, 57)
upper = (21, 61 ,57)
mask = cv2.inRange(img, lower, upper)
    
idxs = np.where(mask == 255) # np.where()は条件満たす要素のインデックスを返す
    
ys = idxs[0]
xs = idxs[1]
    
color = img[ ys, xs ]
   
print("x座標", xs)
print("y座標", ys)
print("元の色", color)
```


# floodFill()で塗りつぶした座標・元の色を取得

```python
import cv2
import numpy as np

img = cv2.imread(r"src.bmp")

# フラッドフィル処理のため周囲1px膨張した空マスク作成
mask = np.zeros((img.shape[0] + 2, img.shape[1] + 2), dtype=np.uint8)
_, newImg, newMask, rect = cv2.floodFill(
    img,
    mask=mask,
    seedPoint=(x, y),
    newVal=(0, 0, 255), # red
    loDiff=(0, 0, 0),
    upDiff=(0, 0, 0),
    flags = 4 | 255 << 8,
)

idxs = np.where(newMask == 255)
idxs = np.array(idxs) - 1 # 膨張した分1px引く

ys = idxs[0]
xs = idxs[1]

color = img[ ys, xs ]
   
print("x座標", xs)
print("y座標", ys)
print("元の色", color)
```
【GitLab CI】Gitへの接続失敗でジョブが失敗するときの対処法

# 前提
私が確認した環境は次の通りです。

GitLabサーバ: WSL2上のdockerでローカルに構築
GitLab RunnerをインストールしたホストOS: Windows 10, Windows 11
利用したExecutor: docker

# ジョブが失敗した時のメッセージ
失敗した時のジョブの詳細は[CI/CD] > [ジョブ]から確認することができます。
次のようなエラーメッセージが出ていました。

```
fatal: unable to access 'http://localhost/*********/test.git/': Failed to connect to localhost port 80 after 0 ms: Connection refused
ERROR: Job failed: exit code 1
```

# 対処法
Runnerの設定ファイル「config.toml」の[[runners]]の設定のurl及びclone_urlの値をlocalhostからプライベートIPアドレスに変更する。（プライベートIPアドレスはご自分の環境に合わせて設定してください。）

```config.toml
concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "docker"
  url = "http://192.168.*.*/"
  clone_url = "http://192.168.*.*/"
```

私はWSL2のローカル上でGitLabサーバーを立てているので、元々は、http\://localhost/で登録していました。
しかし、Executorのdockerコンテナ内からだと、GitLabサーバーに対して、localhostのURLではアクセスできないようで、ホストOSのプライベートIPアドレスを明示的に指定する必要がありました。
テーブルごとの使用データサイズを取得するSQL


## dboだけしかテーブルスキーマを利用していない場合
``` sql
exec sp_MSforeachtable 'sp_spaceused "?"'
```

## dbo以外のテーブルスキーマを利用している場合
``` sql
drop table if exists #tmp;
drop table if exists #TableSize;

create table #tmp(
    Name         nvarchar(128) ,
    Rows         char(11)      ,
    Reserved     varchar(18)   ,
    Data         varchar(18)   ,
    Index_Size   varchar(18)   ,
    Unused       varchar(18)   
);

create table #TableSize(
    Name         nvarchar(128) default('')    NOT NULL,
    Rows         char(11)      default('')    NOT NULL,
    Reserved     varchar(18)   default('')    NOT NULL,
    Data         varchar(18)   default('')    NOT NULL,
    Index_Size   varchar(18)   default('')    NOT NULL,
    Unused       varchar(18)   default('')    NOT NULL,
);

declare @TableName     varchar(100);

declare crtable cursor for
    select    s.name+'.'+ t.name as TableName 
    from sys.tables  t
    join sys.Schemas s on t.schema_id = s.schema_id
    order by s.name,t.name

open crtable;
fetch next from crtable into @TableName;
while @@FETCH_STATUS = 0
begin
    
    delete from #tmp;
    insert into #tmp exec sp_spaceused @TableName;

    insert into #TableSize
    select 
        @TableName ,
        Rows       ,
        Reserved   ,
        Data       ,
        Index_Size ,
        Unused     
    from #tmp;

    fetch next from crtable into @TableName;
end

close crtable;
deallocate crtable;

select * from #TableSize
go

```
【GitLab CI】ジョブがタイムアウトになって失敗した時のトラブルシュート

# 前提
私が確認した環境は次の通りです。

GitLab RunnerをインストールしたホストOS: Windows 10, Windows 11
利用したExecutor: docker

# タイムアウトで失敗した時の様子
プロジェクトの[設定] > [Runner]の画面では利用可能なRunnerとして問題なく登録されていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/cb9141f4-010a-01d5-fac1-89a218fbca42.png)

失敗したジョブを見ると、「There has been a timeout failure or the job got stuck. Check your timeout limits or try again」というエラーメッセージが出ていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/497706d2-85ea-cfb5-7a3e-dac7295e8093.png)


# 対処法1
Runnerの設定画面を開き、「タグのないジョブの実行」にチェックを入れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/6143f983-1129-9e7c-48cc-04a6e919e057.png)

私の場合、この対処法で解決しました。
ネット上にもこの方法が結構案内されていたのですが、最初にこの方法で試しても解決しなかったので、違う問題なのではと思っていました。しかし、Runnerを何度も登録し直したせいで、Runnerの設定も変わっていたせいでした。

gitlab-ci.ymlファイルにはどのランナーでCIをまわすか、tagで設定できるのですが、そのtag設定がなくてもジョブを実行できるようにする設定です。そのため、ymlファイルにtagを記述する方法でも解決することができます。

# 対処法2
WSL2のUbuntuのファイアウォールを無効にする。

```
# ufw disable
Firewall stopped and disabled on system startup
# ufw status
Status: inactive
```

ファイアウォールがRunnerとGitLabサーバー間の通信を妨げている場合があるようです。
私の場合は、最初から無効になっていたので関係ありませんでした。
別件で以前、無効にした覚えがあるので、その時から無効になっていたと想います。

# 対処法3
GitLabのURL設定が間違っている場合があります。
URLがhttpかhttpsかでも接続できるかどうか変わってきます。

また、URLが間違っている場合、次のようなエラーが出ることがあります。

```
fatal: unable to access '...': Empty reply from server
```

config.tomlにURLの設定箇所があるので、URLが合っているか確認して修正します。
github:プルリクエストのテンプレートを設定する

チーム開発では読みやすいプルリクエストを書くため、プルリクエストのテンプレートを設定すると便利です。

レビューアが変更内容を把握しやすくなり、後から対応内容を見返す時にも役立ちます。

リポジトリの.github/pull_request_template.mdにテンプレートファイルを作成しておくと、プルリクエストを作成した時に必要な項目が設定されます。

## サンプル

```markdown
## 概要

## 対応内容

* xxxx

## スクリーンショット

## 関連PR
```

[サンプル](https://github.com/inushima/template/blob/main/.github/pull_request_template.md)
Blenderの「辺ループのブリッジ」

## 概要

Blenderの「辺ループのブリッジ」を紹介します。
2つの面を選んで辺ループのブリッジをすると、面をブリッジすることができます。
下図は、2つの球の面をランダムに選んでブリッジを作成したものです。30回繰り返しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/470034ff-a6fc-2033-2214-75e7debe164e.png" width=500">

## Pythonで実行

下記では、`bpy.ops.mesh.bridge_edge_loops(number_cuts=20)`で辺ループのブリッジをしています。`number_cuts`はブリッジの分割数です。最後にスムーズとサブディビジョンサーフェスをかけて紐っぽくしています。面の向きによっては内側を通るので穴が空いたようになります。

```py
import numpy as np
import bmesh
import bpy
import random

def center(face):
    return tuple(np.round(face.calc_center_median(), 4))

bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
bpy.ops.outliner.orphans_purge(do_recursive=True)

bpy.ops.mesh.primitive_uv_sphere_add()
bpy.ops.mesh.primitive_uv_sphere_add(location=(4, 0, 0))
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.join()
bpy.ops.object.transform_apply(location=True)
obj = bpy.context.object

st1, st2 = set(), set()

for _ in range(30):
    bpy.ops.object.mode_set(mode="OBJECT")
    bpy.ops.object.mode_set(mode="EDIT")
    bpy.ops.mesh.select_mode(type='FACE')
    bpy.ops.mesh.select_all(action="DESELECT")
    bm = bmesh.from_edit_mesh(obj.data)
    bm.faces.ensure_lookup_table()

    if not st1:
        for face in bm.faces:
            p = center(face)
            if abs(p[2]) < 0.8:
                if p[0] < 2:
                    st1.add(p)
                else:
                    st2.add(p)

    for st in [st1, st2]:
        while True:
            f = random.choice(bm.faces)
            p = center(f)
            if p in st:
                st.remove(p)
                f.select_set(True)
                break
    bpy.ops.mesh.bridge_edge_loops(number_cuts=20)
    bm.free()

bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.shade_smooth(use_auto_smooth=True)
bpy.ops.object.modifier_add(type='SUBSURF')
bpy.context.object.modifiers["Subdivision"].levels = 2
```

以上
cscの作法 その275

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

# 練習問題

フォームの位置を固定せよ。

# 方針

- WndProc使って、メッセージを捨てる。

# サンプルコード

```
using System;
using System.Windows.Forms;
using System.Drawing;

class form1: Form {
	form1() {
		Text = "hello";
		ClientSize = new Size(300, 300);
	}
	protected override void WndProc(ref Message m) {
		const int WM_SYSCOMMAND = 0x0112;
		const long SC_MOVE = 0xF010L;
		if (m.Msg == WM_SYSCOMMAND && (m.WParam.ToInt64() & 0xFFF0L) == SC_MOVE)
		{
			m.Result = IntPtr.Zero;
			return;
		}
		base.WndProc(ref m);
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}





```


以上。
cscの作法 その274

# 概要
cscの作法、調べてみた。
WndProc使ってみた。

# 参考にしたページ

https://qiita.com/kob58im/items/b800ccce8b2f230401be


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4e626065-b5f5-6c7a-4c02-4837855554d2.png)

# コンパイル手順

```
>set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%

>cd csc2


>csc scancode.cs

```

以上。
ケースにアップロードしたファイル(ContentDocument)の所有者をケースの所有者に変更したい。


[I want to change the owner of the file(ContentDocument) uploaded to a case to the owner of the case.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Jda8bSAB)


```
trigger ContentDocumentLinkTrigger on ContentDocumentLink (after insert) 
{
       
    List<ContentVersion> versionsToUpdate = new List<ContentVersion>();
    Map<Id,Id> contentDocIdToCaseId = new Map<Id,Id>();
    Map<Id, Case> mpCase = new Map<Id, Case>();
    Map<Id,ContentVersion> contentMap = new Map<Id,ContentVersion>();

    for(ContentDocumentLink cdl : Trigger.new )
    {
        System.debug('UAC cdl ' + cdl );
        if(String.valueOf(cdl.LinkedEntityId).startsWith('500'))
        {
            contentDocIdToCaseId.put(cdl.ContentDocumentId, cdl.LinkedEntityId);
        }
    }

    System.debug('UAC contentDocIdToCaseId ' + contentDocIdToCaseId ); 
    mpCase = new Map<Id, Case>([SELECT Id, OwnerId FROM Case WHERE Id IN: contentDocIdToCaseId.values()]);
    for(ContentVersion cv : [SELECT Id, OwnerId, ContentDocumentId FROM ContentVersion WHERE ContentDocumentId IN :contentDocIdToCaseId.keySet() AND IsLatest = True])
    {
        contentMap.put(cv.ContentDocumentId, cv);
    }

    System.debug('UAC mpCase ' + mpCase );
    System.debug('UAC contentMap ' + contentMap );

    for(ContentDocumentLink cdl : Trigger.new ) 
    {
        String caseId = cdl.LinkedEntityId ;
        if(mpCase.containsKey(caseId) && contentMap.containsKey(cdl.ContentDocumentId) )
        {
            ContentVersion cv = contentMap.get(cdl.ContentDocumentId);
            cv.OwnerId = mpCase.get(caseId).OwnerId ;
            versionsToUpdate.add(cv);
        }
    } 

    if(versionsToUpdate.size() > 0) update versionsToUpdate ;
}
```
WebArena Indigo環境設定11) ファイアウォールのポート設定

WebArena Indigo環境設定10)サーバ再起動時の設定
https://qiita.com/naga_kt/items/1ca459a172b114e562d4
の続き。

　ここまでの設定でWebArena Indigoのvpsはhttpdの設定でSELinuxを無効化したので、そのままでは不安がある。
　ここではファイアウォールのポート設定について述べる。

## コントロールパネルからのファイアウォールのポート設定(CentOS7/RockyLinux8)

　コントロールパネルからポートの設定を行う。
　「ネットワーク管理」－「ファイアーウォール」－「＋ファイアウォールの作成」をクリックすると、「ファイアウォールの作成」画面が開く。「ファイアウォール名」を入力する。
　「インバウンドルール」で「新規ルール」をクリックして「Custom」を選択する。「プロトコール」に「TCP」、ポートに開けたいポート番号、連番の時はハイフンでつないだもの例えば「12345-54321」を、IPアドレスに「0.0.0.0」を入力する。
　「新規ルール」をクリックして「Custom」を選択する。「プロトコール」に「TCP」、ポートにssh接続で用いる番号、IPアドレスに「0.0.0.0」を入力する。
　「新規ルール」をクリックして「HTTP」を選択する。IPアドレスに「0.0.0.0」を入力する。
「インスタンスの適用」にそのルールを適用したいインスタンスを選択して「更新」をクリックする。


---

WebArena Indigo環境設定12) 権限の最終的な設定
https://qiita.com/naga_kt/items/b7e092479453ffed3dc1
に続く。

---

### 参考記事

ファイアウォールの設定方法を知りたい（Indigo）
https://help.arena.ne.jp/hc/ja/articles/360048915573-%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95%E3%82%92%E7%9F%A5%E3%82%8A%E3%81%9F%E3%81%84-Indigo-
AzureAD Join した Windows 11 に RDP できる環境を Azure CLI で作ってみた

## 背景と目的

Azure Virtual Desktop とか Microsoft Dev Box とか、複数のデスクトップ環境を用意するのは数年前よりかなり簡単になりました。とはいえ、条件付きアクセスとかで制限はできるもののパブリックネットワークを経由してアクセスするのが好ましくないケースもあると思います。例えば、基盤を管理運用するための踏み台環境のケースで考えると、プライベートネットワーク経由で接続できる複数のマルチセッション仮想マシンを用意しておき、利用者が必要に応じて接続先を使い分ける方法で事足りたりします。そこで今回は、AzureAD Join した Windows 11 に RDP できる環境を Azure CLI で作ってみました。

## 検証環境を作成

```bash:bash
# 環境変数をセットします
region=japaneast
prefix=mnrdevvm
adgrp=mnrdevvm-group

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region
```

## 仮想マシンを作成

```bash:bash
# パスワードを生成します
vmpasswd=$(openssl rand -base64 16)
echo $vmpasswd

# 仮想マシンを作成します
az vm create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --os-disk-name ${prefix}-vmOSDisk \
  --image microsoftwindowsdesktop:windows-11:win11-21h2-avd:latest \
  --license-type Windows_Client \
  --size Standard_D2as_v4 \
  --storage-sku Standard_LRS \
  --admin-username azureuser \
  --admin-password $vmpasswd \
  --assign-identity \
  --nsg-rule NONE \
  --public-ip-address-dns-name ${prefix}

# RDP ポートを開けます
az network nsg rule create \
  --resource-group ${prefix}-rg \
  --name Allow-RDP \
  --nsg-name ${prefix}-vmNSG \
  --priority 100 \
  --source-address-prefixes $(curl -s inet-ip.info) \
  --destination-port-ranges 3389 \
  --access Allow \
  --protocol Tcp
```

## AzureAD Join の設定

```bash:bash
# AzureAD Join 拡張をインストールします
az vm extension set \
  --resource-group ${prefix}-rg \
  --vm-name ${prefix}-vm \
  --name AADLoginForWindows \
  --publisher Microsoft.Azure.ActiveDirectory

# セキュリティグループのユーザーに仮想マシンユーザー権限を付与します
az role assignment create \
  --assignee $(az ad group list \
  --display-name $adgrp \
  --query [0].id \
  --output tsv) \
  --role "Virtual Machine User Login" \
  --scope $(az vm show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --query id \
  --output tsv)

# NLA を無効にします
az vm run-command invoke \
  --command-id DisableNLA \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm
```

## AzureAD 資格情報を使用して RDP 接続

資格情報を AzureAD\UPN の形式で入力する必要があります (例: AzureAD\john@contoso.com)

## 検証環境を削除

```bash:bash
# リソースグループを削除します
az group delete \
  --name ${prefix}-rg \
  --yes
```

## 参考

https://learn.microsoft.com/ja-jp/azure/active-directory/devices/howto-vm-sign-in-azure-ad-windows

https://learn.microsoft.com/ja-jp/windows/client-management/connect-to-remote-aadj-pc
【TypeScript】ある型から変数プロパティを抽出するUtility Types

TypeScriptで実装をしてると、特定の型の変数プロパティだけ抽出した型を指定したくなることがたまにあります。
そういうときに使えるUtility Typesをつくりました。

# 前提

例えば次のようなクラスAがあって、コンストラクタの引数は自身と同じインターフェイスを持つオブジェクトにしたいとき、クラスAの持つメソッドも引数に指定しないといけません。

```TypeScript
class A {
  a: string;

  constructor(v: A) {
    this.a = v.a;
  }

  func () {
    //
  }
}

const c = new A({
  a: 'a',
  func: () => {}, // これはよくないので無くしたい
});

```

でもメソッドまで実際の引数に指定するのは無駄なので、メンバ変数だけを指定したくなります。
このクラスAの場合はメンバ変数が1つなので

```TypeScript
  constructor(v: { a: string }) {
```

このようにコンストラクタを指定してもいいですがメンバ変数が増えていくと辛い…
さてどうしましょ。

# Utility Typesを定義する

[Utility Types](https://www.typescriptlang.org/docs/handbook/utility-types.html)でクラスAからメンバ変数のaだけを抽出するようなものを実装します。

```TypeScript
type NonFuncPropNames<T> = {
  [K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];

type NonFuncProps<T> = Pick<T, NonFuncPropNames<T>>;
```

変数プロパティを抽出すると書いておきながら、実際はジェネリクスで指定された型から関数プロパティを除去してます。
なので名前も`NonFuncProps`。
こまけえこたぁ（略

# 実装を修正

で、この`NonFuncProps`にクラスAを指定すると最初のサンプルは次のように書けます。

```TypeScript
class A {
  a: string;

  constructor(v: NonFuncProps<A>) {
    this.a = v.a;
  }

  func () {
    //
  }
}

const c = new A({
  a: 'a',
});

```

こんな感じでメソッドは書かなくてよくなりました。
これでクラスにたくさんメンバ変数が増えても安心ですね。

もちろんこのUtility Typesはインターフェイスとかにも適用できます。あー便利
【UiPath】同じ構造のデータテーブル同士を比較して重複する行を抽出する

１．テーブルの全列で主キーを設定する
２．比較するテーブル同士をマージする
３．重複する行をDataRowStateから判定して抽出する
という処理で、重複する（完全に一致する）行だけを抽出します。
差分がある（一致しない）行だけを抽出することも可能です。

:::note warn
主キーを使う関係で、テーブル内にNullが含まれると使えません。
:::

### 処理全体
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/c32b4c4a-dc54-38ca-e858-59b67119cdb6.png)
①データテーブルの構築
②主キーの設定
③AcceptChangeしてテーブル１にテーブル２をマージ
④テーブル１からModifiedの行を抽出
⑤抽出結果をログ出力
の５つのシーケンスに分けています。
以下で一つずつ見ていきましょう。

### ①データテーブルの構築
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/ad7fb1c3-6058-a3a3-e583-cbe9ba90db5d.png)
同じ構造のデータテーブルを2つ作成します。
ここではわかりやすく「データテーブルの構築」アクティビティを使っていますが、
ExcelからReadRangeしたりWebからデータスクレイピングしてデータテーブルを作ってもOKです。

テーブルの内容は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/d486f111-7b0c-c500-551b-64ffa106ba9e.png)
赤枠で囲ったレコードがどちらのテーブルにも存在する（重複する）レコードです。
今回はこの赤色のレコードを抽出していきます。

### ②主キーの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/1c030c55-06d0-54df-a9f2-5f6ff6eb6372.png)
テーブル１の全ての列を使って主キー（正確には複合主キー）を設定します。

DataColumnを格納するコレクション型の変数 *dataColumn1* を宣言し、
繰り返しでこの変数にテーブル１の全てのDataColumnを追加、
テーブル１のPrimaryKey（主キー）に*dataColumn1* をToArrayで配列に変換し渡す、という流れです。

### ③AcceptChangeしてテーブル１にテーブル２をマージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/eba3dd5b-665c-fa3a-13be-9dcd780da478.png)
テーブル１にAcceptChangeメソッドを実行しDataRowStateを取れる状態にした上で、
テーブル１にテーブル２をマージします。

### ④テーブル１からModifiedの行を抽出
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/72f091f9-71d9-d2ec-40e3-458041e1cabd.png)
マージされた側のテーブル１はDataRowStateが以下の３つに分かれています。

- **Added**：追加されたレコード = テーブル２だけに存在するレコード
- **Modified**：変更されたレコード = 両方のテーブルに存在するレコード
- **Unchanged**：変更されていないレコード = テーブル１だけに存在するレコード

GetChangesメソッドでDataRowStateがModifiedのレコードを取得すれば、両方のテーブルに存在する（重複する）レコードを取れることになります。
差分があるレコードを取りたい場合は、DataRowStateがAddedとUnchangedのレコードを取得してマージすればOKです。

### ⑤抽出結果をログ出力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/d36c82dc-0918-1b27-5012-4d68600b12bf.png)
抽出したレコード（テーブル）を文字列に変換してログ出力しています。
結果は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/74355f7e-896f-003d-cc06-7c26f8fe31dc.png)
無事両方のテーブルに存在するレコードだけを抽出できています。
お疲れ様でした。

## 動作環境
UiPath.System.Activities 21.10.4

## 参考
https://docs.microsoft.com/ja-jp/dotnet/api/system.data.datarowstate?view=net-6.0

https://docs.microsoft.com/ja-jp/dotnet/api/system.data.datatable.acceptchanges?view=net-6.0#system-data-datatable-acceptchanges

https://docs.microsoft.com/ja-jp/dotnet/api/system.data.datatable.getchanges?source=recommendations&view=net-6.0
高専Wordleを作ってみた

こんちは現役JK[^1]のTrimsCashですだいぶん前に作ったやつ現実逃避のために書く
これはほぼ自分語りだと思ふ

https://github.com/trimscash/KosenWordle

https://trimscash.github.io/KosenWordle/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/8b70b2d2-5e69-210f-7d91-192d16c1c3b5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/e3b2d5c6-8711-0d26-e8ac-23ea5e2ff538.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/f9894590-19cb-3efa-7359-4b0f925e511d.png)



## これは
[Wodle](https://www.nytimes.com/games/wordle/index.html)の高専パロディ

## なぜ作ったのか
高専のTwitter界隈は結構盛んで，当時Wordleが流行っていた．私はその時間線的集合情報体をうつろな目で眺めていたのだがその時突如ラマヌジャン的ひらめきが舞い降りた，
**「高専の名前でWordle作ったらバズること間違いナシや！！！！」**[^2]
ってことで作った．

## 使用技術等
- 言語
javascript, html, css

- PWA
PWAというのはWebページをアプリのようにホーム画面に追加して使えるようにするやつ．

- Twitter intent
ツイッターで共有させるためリンクにより任意のツイートをさせることのできるTwitter intentを用いた．
[intentの例](https://twitter.com/intent/tweet?&text=%20%23%E9%AB%98%E5%B0%82Wordle%20%0A%F0%9F%9F%A9%E2%AC%9C%E2%AC%9C%E2%AC%9C%E2%AC%9C%F0%9F%9F%A9%F0%9F%9F%A9%0A%F0%9F%9F%A9%F0%9F%9F%A8%F0%9F%9F%A8%E2%AC%9C%F0%9F%9F%A9%F0%9F%9F%A9%F0%9F%9F%A9%0A%F0%9F%9F%A9%F0%9F%9F%A9%F0%9F%9F%A9%F0%9F%9F%A9%F0%9F%9F%A9%F0%9F%9F%A9%F0%9F%9F%A9%0A%0A%E7%AD%94%E3%81%88:%20%E3%81%A8%E3%81%8F%E3%82%84%E3%81%BE%0A%E5%BE%B3%E5%B1%B1%E9%AB%98%E5%B0%82%0A%0AWIN!%0A&url=https://trimscash.github.io/KosenWordle)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/869b86f5-787d-4d54-daff-4f2eb11c47a2.png)

技術ではないな！


## こだわり
- cssはよくわからないがこのカラフルトウモロコシみたいなデザインがこだわりや
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/51051e7b-e310-bf40-7f68-81dd62ba9b95.png)
- 読みにくいコード
実際に読みにくいかどうかは読んでみればわかるが一日で作ったので何も考えずに書いている．
このこだわりのためにバグがあったがとてもめんどくさかったので何日も直していなかった．

## デプロイ
- github-pagesで公開．
ツイッターで発表．
その結果2人の人に遊んでもらえた＼(^o^)／

(a few months later...)

ツイッターで
「バグあってまともに遊べないけどめんどくさいから直さない．けど遊んでね！！」
てな感じで呼びかけたらいろいろな人に遊んでもらえた．そしてなんとバグを直してもらえた（！！！！！）．

## 神のデバッグ
先述した通り，私のコードは結構あれだったのだが，そんなコードを直してくれる神がいた．

直してもらったのは，文字が一致しているかしていないかのアルゴリズム，ワードリストの誤植の修正．

ありがたや．．．

## 終
てな感じでKosen Wordleを作った話だった．
まったくバズることはなく何もなく終わった．
だいぶ前に作ったのでほとんど覚えていない．．今日ソースコードを見たが理解までに時間がかかった．

怖い人に見られたら怒られるコードかもしれない．．けど許して！ついでにタスクの進捗ないのも許して！！時計の短針と長針を見間違えて二度寝して2時間寝坊して会議に出られなかったのも，毎日怠惰な生活を送っているのも！

今はバグはないから，みんなも遊んでみてね！

https://trimscash.github.io/KosenWordle/

[^1]: 情報工学科高専生
[^2]: バズりませんでした
【SwiftUI】NavigationViewがNavigaitonStackへ（iOS16）

iOS16でNavigationStackが追加されNavigationViewがDeprecatedになりました。
対応バージョンの問題もある為、すぐに置き換えという訳に行かないと思いますが、
必要になった時の為に確認しておきましょう。

# NavigaitonStackの使い方

基本的な使い方はNavigationViewと同じです。

```swift
struct BasicNavigationStackView: View {
    var body: some View {
        NavigationStack{
            List{
                NavigationLink("LinkLabelText", destination: Text("Destination"))
                NavigationLink("LinkLabelText2", destination: Text("Destination2"))
            }
        }
    }
}
```

このようにNavigationStackでNavigationLinkの含まれるViewを囲います。
見ての通り、簡単なViewであればNavigationViewをそのまま置き換えても動作します。

navigaitonTitleやtoolbarなどもそのまま動きます。

# navigationDestination

NvavigationViewと違い遷移先をNavigationLinkと分離させて書く事が出来ます。

```swift
struct BasicNavigationStackView: View {
    var body: some View {
        NavigationStack{
            List{
                NavigationLink("LinkLabelText", value: "Destination")
                NavigationLink("LinkLabelText2", value: "Destination2")
            }
            .navigationDestination(for: String.self) { text in
                Text(text)
            }
        }
    }
}
```

NavigationLinkにはvalue引数に遷移先のViewに渡す値を書き、
navigationDestination Modifierで型を指定し値を受ける形になります。

# navigationDestinationと分岐

遷移先が複数ある場合は分岐が必要になります。
当然ですがnavigationDestination内で条件分岐が出来ますし、
valueの型が異なると対応した型のnavigationDestinationに振り分けられます。

```swift
struct BasicNavigationStackView: View {
    var body: some View {
        NavigationStack{
            List{
                NavigationLink("LinkLabelText", value: "Destination")
                NavigationLink("LinkLabelText2", value: "Destination2")
                NavigationLink("LinkLabelText3", value: 3)
            }
            .navigationDestination(for: String.self) { text in
                if text == "Destination" {
                    Text("Destination")
                }else{
                    Text("Not Destination")
                }
            }
            .navigationDestination(for: Int.self) { value in
                Text("Destination \(value)")
            }
        }
    }
}
```

# 注意点

## navigationDestinationの優先順位

navigationDestinationは基本的に先に読み込まれたものが優先されます。
同じ型のnavigationDestinationが複数あった場合、後のものは無効になります。

これは画面遷移後であっても同じで、ViewA→ViewB→ViewCと遷移したい時、
同じ型のnavigationDestinationをViewAとViewBに実装しても、
ViewAのnavigationDestinationしか有効になりません。
つまりViewAのnavigationDestinationひとつにViewBとViewCへの遷移を実装しなければなりません。

## NavigationStackは２重にしてはいけない

これは初心者にありがちなミスなのですが、
遷移後のViewにもNavigationStackを実装してします事があります。
NavigationViewの頃はデザインがイマイチ良くないものの、とりあえず動きはしました。
NavigationStackの場合は正常に動作しなくなっているので気をつけてください。

# ブログ紹介

今回、NavigationStackの基本を紹介しましたが、まだまだ語り尽くせていません。
ブログ記事には補足説明や画面遷移の制御についてなどがあります。

特にNavigationPathを使った画面遷移の制御などは重要ですので、
良ければこちらも確認してみてください。

https://thwork.net/2022/09/13/swiftui_navigationstack-ios16_ipados16/

https://thwork.net/2022/09/19/swiftui_navigationstack_control_navigationpath_ios16-ipados16/
STM32G071とSSD1306でデモ(Adafruit SSD1306,Adafruit GFX)



x ライブラリのインストール方法は、めんどいので省略
x I2CのIDアドレスは、3Dから3Cに変更した。
x サイズは、約55KB


x OLED096UNO-Aです。
x NUCLEO-G071RB

目的
OLEDのテスト


変更箇所


```c++


#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32



```


![o_con779.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/8df3775a-4052-f028-9e51-2de5fb572bc3.jpeg)


![o_con780.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d9d2480e-a6a4-66b3-7674-4eecd788574d.jpeg)
Google Colab環境でpystan3.3 (2) 

## はじめに

前回からの続きで、PyStan 3で結果の要約やのグラフ（Rstan教科書に出てくるやつ）の出し方のメモ。

[Google Colab環境でpyStan 3.3を利用する](https://qiita.com/msx222/items/37da015a06758a05c990)

## 結論
ArviZを利用する。
※google colabに初めからインストール済。
※pyMC3, NumPyro など他のライブラリも対応。

[ArviZ: Exploratory analysis of Bayesian models](https://python.arviz.org/en/latest/index.html)


```python
# Pystan 3.5 Quick Start
import stan

schools_code = """
data {
  int<lower=0> J;         // number of schools
  real y[J];              // estimated treatment effects
  real<lower=0> sigma[J]; // standard error of effect estimates
}
parameters {
  real mu;                // population treatment effect
  real<lower=0> tau;      // standard deviation in treatment effects
  vector[J] eta;          // unscaled deviation from mu by school
}
transformed parameters {
  vector[J] theta = mu + tau * eta;        // school treatment effects
}
model {
  target += normal_lpdf(eta | 0, 1);       // prior log-density
  target += normal_lpdf(y | theta, sigma); // log-likelihood
}
"""

schools_data = {"J": 8,
                "y": [28,  8, -3,  7, -1,  1, 18, 12],
                "sigma": [15, 10, 16, 11,  9, 11, 10, 18]}

posterior = stan.build(schools_code, data=schools_data)
fit = posterior.sample(num_chains=4, num_samples=1000)
eta = fit["eta"]  # array with shape (8, 4000)
df = fit.to_frame()  # pandas `DataFrame, requires pandas

```

ここまでは前回まで動いたので、収束具合を確認します。

Arvizのデータ形式へ変換
```python
# Arvizのデータ形式へ変換
import arviz as az
idata = az.from_pystan(posterior=fit, posterior_model=posterior)
```

結果の要約表示　r_hatの値が1で収束しています。
```python
az.summary(idata)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27979/845e92ce-3833-b8a2-8160-d9341b9a6fbb.png)

Trace Plot 交ざり具合を確認

```python
az.plot_trace(idata)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27979/04f5eb75-a917-1c1b-4324-52839817cb00.png)
DreamweaverとGithubを連携するまで


## Website作成といったらDreamweaverだよねと思ったらそうでもなかった
事業用のWebsiteを作ることになりました。
Adobe CCに会員なので、当然のようにDreamweaverをダウンロード。
ただ、情報源としてはWordpressやAdobe XDの方が多いので、こちらとの連携についても考えなから進めていくことに。

## さてGitをと思ったところで立ちはだかったもの

- GithubアカウントにPCからアクセスできるならPCにGitは入っている？
- そもそもGithubとGitって違うの？同じなの？
- このGit最新？
- 最新Gitってどうやってインストールするの？
- `git --version`で出てくるバージョンがインストールしたバージョンより古いんだけど…
- それでGitは結局普段どこにいるの？

お悩み解決で一つ記事がかけました。

https://qiita.com/SayCheeese/items/97149938e17930bd9ac1

# 本題: DreamWeaverとGithubの連携
目的：ソースコードをPC内よりオンライン(Github)上に残す。

公式Step.
https://helpx.adobe.com/jp/dreamweaver/using/git-support.html

##  Dreamweaverとの連携
1. GitのPATHの入手
`which git`。わからない方は上記記事をご参考ください。
1. Github上のリモートリポジトリを作成or選択。
`Code` -> `HTTPS` でURLが入手できます。
1. Dreamweaverの起動
DWを起動してからGitをインストールするとうまく反映されません。Gitをインストールしたら、一旦DWを再起動してください。
1. DWのTop画面上部メニューバーで、`サイト`->`新規サイト(orサイト管理)`->`サイト設定`ウィンドウを開く。
1. サイト名、ローカルフォルダは適宜記入
1. `このサイトにGitリポジトリを関連付ける`にチェック
1. `URLを利用して既存のリポジトリを複製`を選択
1. GithubのURLを貼り付け
1. Githubのユーザー名とパスワードを入力
1. `テスト`
1. 問題なければ`保存`で完了。


## 問題は起きた。GithubトークンにDWは非対応。
上記のStep.10でエラーが出ました。
```
Error: remote: Support for password authentification was removed ...
```

こちらのサイトを参考に修正しました。

https://note.kiriukun.com/entry/20210904-github-password-authentication-was-removed

できた！
Mac PC環境に最新Gitがあるか確認する

## PCへのGitのインストール

- GitとGithubの違いがわからない方 -> [こちら](https://kinsta.com/jp/knowledgebase/git-vs-github/)を参考。

### 自分のPCにgitがインストールされているか確認
確信のある人は飛ばしてください。
確信がない人は、ターミナルに下記を記載。
```shell
$ git --version
```
インストール済であれば、次のようにバージョンが出ます。
```shell:既にインストール済
$ git --version
git version 2.37.0
```
・「"git"コマンドを実行するには、コマンドライン・デベロッパー・ツールが必要です」などのポップアップが出た場合は、あなたのPC内にgitはありません。
・`git version 2.37.0 (Apple Git-136)`のように、`Apple Git`の記載があった場合、最新版ではない可能性が高いです。

### Gitのインストール:
インストール方法はWeb上に数多あるので割愛しますが、下記ご参考まで。

Macの場合: [コマンドライン・デベロッパー・ツールをダウンロード](https://qiita.com/SayCheeese/items/1b9db660917049bbad64)します。
Windowsの場合: https://gitforwindows.org/

https://qiita.com/SayCheeese/items/1b9db660917049bbad64

### Gitのアップグレード
[公式サイト](https://git-scm.com/)と比べてGitのバージョンが古いぞ？という場合。
Homebrewのダウンロードが済んでいる前提で備忘。

```shell:Homebrewの場合
$ brew upgrade git
```
ただし、Homebrewとgitが連携されていない場合はこんなエラーになります。
```diff_shell:Error例 1
$ brew upgrade git
- Error: git not installed
$ brew install git
+ (Download ~~~ が何行か書かれる）
+ zsh completions and functions have been installed to:
+ /usr/local/share/zsh/site-functions
```
```diff_shell:Error例 ２
$ brew upgrade git
- Warning: git 2.37.3 already installed
$ git --version
- git version 2.37.0 (Apple Git-136)
```
homebrewでは2.37.3がダウンロードされていないのに、gitコマンドでは2.37.0になっていることになります。
原因は、**HomebrewのGitにPATHが通っていない**こと。

直し方は[こちら](https://dev.classmethod.jp/articles/brew-git-upgrade-is-not-reflected/)を参考にしました。

https://dev.classmethod.jp/articles/brew-git-upgrade-is-not-reflected/

というわけで、早速PATHを通します。
```shell
$ echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.zshenv
$ source ~/.zshenv

# 確認
$ git --version
git version 2.37.3
```
gitコマンドで最新バージョンが表示されました。

### GitのPATHを確認する
```shell:Gitのパスを確認
$ which git
/usr/local/bin/git
```
astroでgithub.ioに公開する

# 最初に
ポートフォリオを作成しようと考え、Vueを使おうと思いましたが```astro```というものの存在を知り、こちらで作成しようと考えました。```astro```にはポートフォリオ作成用のテンプレートが用意されていて、なかなかにおしゃれです。
[公式ページ](https://docs.astro.build/ja/guides/deploy/)に載っている方法をそのまま行えばデプロイできますが、Qiitaに記事が存在しなかったので忘備録として本記事を作成しました。

## astro.config.mjsを編集
```buildOptions```に```site```を追加。自分のgithub.ioのURLを貼り付ける。
もしポートフォリオ用のリポジトリが```https://<GitHubのユーザー名>.github.io/```でない場合は```base```オプションを追加して、以下のようにリポジトリを指定しましょう。
```javascript
import { defineConfig } from 'astro/config';
import preact from '@astrojs/preact';

// https://astro.build/config
export default defineConfig({
	integrations: [preact()],
	buildOptions: {
		site: "https://masaki12-s.github.io/",
        // base: "https://github.com/masaki12-s/portfolio_astro"
	  },
});
```

## deploy用のymlファイル作成
プロジェクト内に```.github/workflows/deploy.yml```ファイルを作成する。そして以下の```yml```を貼り付ける。
```yml
name: Github Pages Astro CI

on:
  # `main`ブランチにプッシュするたびにワークフローを起動させる
  # 別のブランチ名を使う場合は`main`をあなたのブランチ名で置き換えてください。
  push:
    branches: [main]
  # GitHubのActionsタブから、このワークフローを手動で実行できるようにします。
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-20.04

    # このジョブがあなたのリポジトリに変更をプッシュすることを許可する
    permissions:
      contents: write

    steps:
      - name: Check out your repository using git
        uses: actions/checkout@v2

      - name: Use Node.js 16
        uses: actions/setup-node@v2
        with:
          node-version: 16

      # npmを使っていない場合、`npm ci`を`yarn install`や`pnpm i`に置き換えてください。
      - name: Install dependencies
        run: npm ci

      # npmを使っていない場合、`npm run build`を`yarn build`や`pnpm run build`に置き換えてください。
      - name: Build Astro
        run: npm run build

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          # `./dist`はAstroがデフォルトでアウトプットするディレクトリです。
          # 変更した場合は、こちらも更新してください。
          publish_dir: ./dist
```

## GitHubにpushする
ここまでの設定を```commit```して```push```する

## GitHubのpages設定を更新する
GitHubで**Settings** -> **Pages**に移動。
Branchを```gh-pages```に変更する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2805504/6888b2cc-ab21-df4c-c9df-abf8cc696c87.png)

## GitHubのActionsを確認
GitHubのActiionsを確認して、以下のように```build```～```deploy```まで正常にできていれば公開できていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2805504/010dc407-389e-9994-ca6f-0d7fcb9ce39a.png)

## 最後に
今回は```astro```で作成したポートフォリオをGitHub.ioに公開する方法を説明しました。まだポートフォリオ自体の作成はできていないのでここからはそちらに専念しようと思います。
2022/9/19主にITとかセキュリティの記事

Microsoft製品に緊急の脆弱性　早期のアップデート適用を(9/16)
https://www.zaikei.co.jp/article/20220916/689728.html

国内サプライチェーンリスクの具現化に警鐘、トレンドマイクロ2022年上半期レポート(9/16)
https://news.mynavi.jp/techplus/article/20220916-2456312/

LinuxとWindowsの古い脆弱性の活発な悪用を確認、更新を(9/17)
https://news.mynavi.jp/techplus/article/20220917-2456247/

Uberにサイバー攻撃、18歳ハッカー関与か(9/17)
https://www.nikkei.com/article/DGXZQOGN16DKN0W2A910C2000000/

チェック・ポイントの子会社Avanan、Amazonウェブサービスを利用したフィッシング攻撃の情報を公開(9/16)
https://www.jiji.com/jc/article?k=000000139.000021207&g=prt

りそな銀行・埼玉りそな銀行を偽るフィッシング確認、注意を(9/16)
https://news.infoseek.co.jp/article/mynavi_2480186/

画像からテキストを抽出、ファイル名を一括変更…Windowsを快適にする公式無料ツール「PowerToys」おすすめ機能7選(9/16)
https://news.infoseek.co.jp/article/bunshun_57360/?tpgnr=it

若者に人気の位置情報アプリ「zenly」がサービス終了を発表　「有料でも続けて」「監視されなくて嬉しい」など賛否(9/16)
https://news.infoseek.co.jp/article/itmedia_nlab_20220916194/

機密情報盗んだ中国のスパイ、iCloudのバックアップを消し忘れて有罪判決(9/17)
https://iphone-mania.jp/news-488019/

古いWi-Fiルーター、設定を変えずに使い続けるべきではない理由(9/16)
https://active.nikkeibp.co.jp/atcl/act/19/00375/091300009/

8割の企業で、過去1年以内に深刻なセキュリティインシデントが発生---Snyk調査(9/16)
https://japan.zdnet.com/article/35193360/

ITリーダーが把握しておくべき20のトレンド(9/16)
https://japan.zdnet.com/article/35193079/

ミドルマネジャーが主導する部門アンラーニング(9/16)
https://rc.persol-group.co.jp/learning/career/column/202209160000.html
超初心者がプログラムを書く環境を整えるまで（Mac）

## はじめに

教わるまで知らなかったんですが、ターミナルっていうあの黒画面白文字の謎のアプリでプログラムが書けるんだそう。
ターミナルより、iTerm2の方が使いやすいよ、というアドバイスをいただいたので、特に検証もせずiTerm2を導入してみることにしました。
私に教えてくださる方の環境がiTerm2だったのでそれに揃えたとも言います。

下記のサイトを参考にさせていただきました。

https://qiita.com/ryamate/items/075c34fcf29d0889c15a

## iTerm2とはなんぞや

私が学習する際につかっているターミナルの代わりのアプリケーションです。
初心者にもわかりやすく、使いやすいんだそう。
今まで気づいたメリットとしては、

- **キーワードが色分けできる**
    黒背景に白文字で慣れない言葉ばかりでは目も滑ります。
- **読みやすさ、書きやすさ重視**
    設定できる項目が多く、種類も豊富
- **画面を透過できる**
    手前で書きながら奥で実際の動きを見られるの、意外と便利です。

## ダウンロードの前に、ターミナルの超基本

1. ターミナル内では、まず場所(フォルダ)を指定して、そのフォルダやフォルダ内のファイルにたいして処理をする。
1. 場所
    1. `pwd` で現在地を表示
    1. `cd <場所>`で好きなフォルダへ移動
        1. `cd ..`で上の階層（フォルダ）へ
        1. `<場所>`部分はフォルダをFinderからドラッグしてきても記載できる
1. ファイル
    1. `ls -l`でそのフォルダ内のファイルを確認。（隠しファイルも確認したいときは`ls -la)
    1. `cat <file名>`で中身確認
    1. `vim <file名>`で中身編集
        1. vim画面に移るので、`i`でInsert(編集)モード、`esc`で通常モード、`:wq`でvimモード終了

これからダウンロードしていくiTerm2もターミナルの一種なので、
プリインストールされているターミナルと同じように操作できます。

## iTerm2のダウンロードから設定まで

Index
[1. iTerm2のインストール](#1iTerm2のインストール)

### 1. iTerm2のインストール

https://iterm2.com/

※ こちらの公式サイトからダウンロードします。
1. `Download`をクリック
1. ダウンロードされた**zipファイル**を開く
1. zipファイル内にあるiTerm2を**アプリケーション**に入れる
1. ダブルクリックかLaunchpadから開く

もしかしたら「このアプリケーションはダウンロードされたもので安全性が…」みたいな画面がでるかもしれませんが、大丈夫です。そのまま先に進みましょう。

…

以上です！
簡単。おしまい。
python、画像の読み込みと表示

# やること
- 画像の読み込み
- 画像の表示

# ライブラリ
- cv2 : python用のOpenCV

# コード
```py
import os
import cv2 # cv2のインポート

img_dir = "img_dir" # img_dir:画像データのディレクトリ
img_names = os.listdir(img_dir)

for img_name in img_names:
    img_path = os.path.join(img_dir, img_name)
    
    #画像の読み込み、-1は元画像のチャネルのまま読み込むフラグ
    img = cv2.imread(img_path, -1)
    
    #画像の表示
    cv2.imshow("img_title", img)
    cv2.waitKey(0) # 0の数字を変えると表示のタイミングが変わる。

#画像表示ウィンドウを閉じる
cv2.destroyAllWindows()

```