OmniAICreator/Qiita-1.07M huggingface dataset:
@OFFSETをSQLプッシュバックさせる（Db2版）

SPSS Modelerで@OFFSETはSQLプッシュバックが行えない関数として代表的なものです。
これをSQLプッシュバックさせる方法を考えてみます。これは、産業技術総合研究所　本田様に教えていただいたアイディアをDb2のDB関数も使って実装したものです。


* テスト環境
    * Modeler 18.4
    * Db2 warehouse on cloud

* サンプルストリーム

https://github.com/hkwd/spsssample/raw/master/221115OFFSETpushback/OFFSET2.str

* サンプルデータ

https://raw.githubusercontent.com/hkwd/spsssample/master/221115OFFSETpushback/INDIV_DAILY_SALES.csv

用意したデータは以下のように顧客ごと日付ごとに購入金額と購入点数が記録されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ba8fa530-67c0-17a4-9916-2f0734236a43.png)

ここから1回前のトランザクションの購入金額と購入点数の列を＠OFFSETで追加します。


# 1. @OFFSETでの実現

まず、＠OFFSETでの実現方法を確認しておきます。
CUSTID（顧客ID）とDATE（購入日）でソートします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/9d1cf733-d9f8-c994-dd6d-6d59c71e73a0.png)



「フィールド作成」ノードで同じCUSTID（顧客ID）の1回前のAMOUNT（購入額）、NUMPURCHASE（購入点数）の値を取得しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/28955e89-df3c-810b-7da7-6081b178013b.png)

以下のようにひとつ前トランザクションの値を取得できます。これで前回からの購入金額の差などを計算することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/0ccd58b1-ba1d-c754-7f13-3972962ed324.png)


しかし、@OFFSETがSQLプッシュバックしません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/c0a3b1ec-6e50-433d-6b76-adf8517a893b.png)

# 2. SQLプッシュバックの実現

「フィールド作成」ノードでSYSIBM.ROWNUMBERを選びます。そしてCUSTIDでパーティション化して、DATEでソートして連番を振ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/8fba430c-b2ea-7a96-9e05-70d627c9ac33.png)

以下のようにCUSTIDごとにDATE順に連番が振られます（RDBの処理なので順序は保証されません。この表示と同じ準にするためにはCUSTIDとDATEでソートをして確認してください）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/c377d7df-8d52-d5bd-de28-8319f6d2945b.png)

内部的には以下のSQLがプッシュバックされています。

```sql
SYSIBM.ROWNUMBER() 
OVER( PARTITION BY T0.CUSTID ORDER BY T0."DATE" ASC) AS NUM
```

次に「置換」ノードで今作ったNUMに１足したデータを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/474c9295-55b7-ea41-b590-d1bb8a532f1a.png)

そして、これらをCUSTIDとNUMで部分外部結合します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/966768a6-3e3c-8fe3-dbdb-bde89b630d72.png)

フィルタータブで1トランザクション前のDATEは削除し、AMOUNTとNUMPRUCHASEには「_LAG」の接尾辞をつけました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/efb6be5d-1b9e-96cd-c766-bda7cd0a07d3.png)

最後にCUSTIDとDATEでソートをしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/bfdc0c98-23de-bffc-d0e0-91a7c1e5860f.png)

@OFFSETで得られた結果と同じ結果が得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/a6361ce0-c844-e8dd-4f03-069cb90da6f8.png)

これならSQLプッシュバックが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/de4a3e9b-cd53-622c-5797-3abb7b59d31b.png)

ここではDb2のデータベース関数のROWNUMBERをつかって実現していますが、もしこれに該当する関数が接続しているRDBにない場合は、いったん@INDEXなどで連番を振って一時表をRDBに作ってから行うということもできます（この処理だけならCUSTIDでパーティション化する必要はありません）。@INDEXもSQLプッシュバックが効きませんが、一時表以降はSQLプッシュバックが可能になります。


#### 参考：OLAP 指定 - IBM Documentation 

https://www.ibm.com/docs/ja/db2/11.5?topic=expressions-olap-specification
初めてのGithub操作

Githubを何のため使うかやコミットで何をしているのかなどは分かったものの、よく使うコマンドを忘れそうだったので備忘録を作りました。

# 前提

Gitのインストール、Gitの初期設定、Githubのアカウント作成は終わっているものとします。
後、私はMacユーザーなのでWindowsだとうまくいかない場所があるかもしれません。
共同開発をするのに必要なブランチの概念などについては、あまり触れていません。

# 1. PCにGitでバージョン管理する場所を作成する

Githubで管理したいフォルダをターミナルで作成し、そのフォルダまで移動する。
その後で、「このフォルダを管理する！」と宣言する。

```zsh
mkdir <フォルダ名>
cd <フォルダ名>
git init
```

すると.gitフォルダなるものが作成される。中にツリー構造やコミットの記録、設定などが入っている。

# 2. レポジトリ(リモート)を作成する

Githubにアクセスし、レポジトリを作成する。
リモートレポジトリを作成するとURLが表示されるのでコピーする。

その後ターミナルで以下のコマンドを入力する。

```zsh
git remote add origin <URL>
```

originとはデフォルトのレポジトリの場所の別名らしい。
新たにリモートレポジトリを作成したいときはoriginを他の名前に置き換えれば良い。

# 3. Githubにデータを送る

Githubにデータをあげるには三段階の工程が必要。

## a. 変更をステージに追加する

この段階ではまだGithub上に変更点が反映されていない。変更の準備をしている段階。

```zsh
git add <ファイル名>
```

## b. 変更を記録する(ローカル)

ローカルレポジトリに変更を記録する。

```zsh
git commit -m "コメント"
```

## c. Githubに変更を反映する

先にGithubにてPersonal access tokenを発行しておく。
初回はユーザーネームとトークンの入力が求められる。

```zsh
git push origin master
```

masterというのはレポジトリ下にあるデフォルトのブランチ名。
どうやらmasterではなくmainと入力しなくてはならないこともあるらしい(自動で生成されるブランチの名前がmainに変わったようだ)。

# 状況の確認

以下で現在のコミット状況などを確認できる。

```zsh
git status
```

# 参考文献
じゆう太. "【初心者向け】MacでGitHubを使う方法。始め方をとにかく簡単に説明". 自由帳. 2022/02/17. https://jiyuta.com/github/, (2022/11/15).

山浦清透. "Git： もう怖くないGit！チーム開発で必要なGitを完全マスター". udemy. 2022/10. https://www.udemy.com/course/unscared_git/?src=sac&kw=%E3%82%82%E3%81%86%E6%80%96%E3%81%8F%E3%81%AA%E3%81%84 , (2022/11/15).

@seri1234. "Git - originとmasterとは何か(初心者向け)". Qiita. 2021/10/01. https://qiita.com/seri1234/items/e651b3e108a695a92809, (2022/11/15).

株式会社Deepblue. "git push時のerror: src refspec master does not match anyについて". TechBlog. 2020/10/27. https://blog.deepblue-ts.co.jp/git/git-push-error/, (2022/11/15).
Accessで引数を渡しながらフォームを開きたい

# やり方

```DoCmd.OpenForm``` の第7引数で指定できる。

```vb:フォームを開く側のサンプル
DoCmd.OpenForm "開くフォーム名", , , , , , "引数の値"
```

```OpenArgs``` って変数に入る。

```vb:開かれるフォーム側で引数の値を確認サンプル
Debug.Print Me.OpenArgs
```

# 引数を複数渡したい時

* 引数は複数設定できない。
* 引数に文字列型以外（Dictionaryとか）は設定できない。

なので、やるとしたら『ほげ/ふが/ほにゃ』みたいな文字列を渡して、受け取った側でパースするしかない。

# 参考サイトさん

https://asbepartners.com/openargs/

# バージョン

Windows 10 Pro 21H2 OSビルド 19045.2251
Microsoft Access for Microsoft 365 MSO (バージョン 2209 ビルド 16.0.15726.20068) 32 ビット
ソースコード変えてないのにLambdaをデプロイしたら急にエラーになって焦った話

# 起きたこと
GitHub Actionsで毎朝自動デプロイを行っているServerless FrameworkのAPIサービス（API Gateway + Lambda）がある朝急にエラーを吐くようになった。

```
TypeError: _convert_to_request_dict() missing 1 required positional argument: 'endpoint_url'
```

# 試したこと、調査したこと
## どこでエラーになっているか
[PynamoDB](https://github.com/pynamodb/PynamoDB)というライブラリを使っていて、それが吐いているエラーだということは確認できた。
ただ、掘っていくのが大変で真因を突き止めるのに難航。
ライブラリのバージョンは固定していたのでライブラリが更新されているわけではないと判断。

## エラーが起きてなかった時点の昨日のソースに戻して再デプロイして解消するか試す
もしソースの変更が原因なら解消するはずなのだが解消しなかった。

不可解なことに時間差でほぼ同様のソースがデプロイされているはずの別環境ではエラーが起きていなかった。
そこの環境に対して昨日時点のソース再デプロイすると同様にエラー状態になるため、今度はデプロイを行っているGitHub ActionsのOSインスタンスバージョンを固定してみたが効果なし。

## 実際にデプロイパッケージにインストールされているライブラリの差分を調査
Lambda レイヤーを使っていたのでそこに入っているソースコードを落としてきてファイル差分を調査。
すると、botocoreに差分があることが分かった。

公式を調べるとbotocoreとboto3が丁度今日アップデートされていることが分かった。

https://github.com/boto/botocore/releases/tag/1.28.0

https://github.com/boto/boto3/releases/tag/1.25.0

# 結局何が原因だったか

ここまで調べてbotocoreのバージョンが上がったことによりPynamoDBの依存関係でエラーが起きたのではないかと推察して、公式のイシューを見に行ったらドンピシャ。

https://github.com/pynamodb/PynamoDB/releases/tag/5.2.2

既に有志によって対応リリースされていたので、こちらもバージョンを上げて再デプロイするだけでエラーを解消することができた。

# 今回の学び
## Lambdaの処理系にプリインストールされているライブラリはおそらくデプロイをすると最新化されてしまう
このため今回はタイトルにもあるようにソースを変えていないのにデプロイすると依存性エラーが起きるという不可解な現象にハマってしまった。

## 回避策はあるのか
今回はたまたま公式が光の速さで対応してくれたから大事にならなかったが、勝手にアップデートされること自体を止めれるのか。
結論はちゃんと使うライブラリを独自にバージョン固定してインストールしてあげれば大丈夫。

今回エラーになったPynamoDBのバージョンとエラーになる前のboto3のバージョンを指定してデプロイしたところエラーは発生しなかった。

---

Lambdaはサーバレスだから処理系の管理に気を配らなくていいやと油断していたら思いもよらない落とし穴でした。
React.jsを学ぶ際の準備

## 記事の趣旨
- React.jsを勉強しようとして、jsだけではconsole.logが見られず困った
- 同じ階層にhtmlを用意しておいて、そのconsoleを見ながら作業すればいい！と気づく
- テンプレートhtmlの備忘

## テンプレートhtml
```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Station 15</title>
  </head>
  <body>
    <p>load時点のコンソール確認</p>
    <button onclick="test-App.js()">ボタン</button>
    <p>ボタンを押したときのコンソールも確認</p>
    <script type="text/javascript" src="./test-App.js"></script>
  </body>
</html>
```

## jsの上下テンプレート
```js: above
// なくて良さそう？
```

```js:bottom
// なくて良さそう？
```
nil?、empty?の使い分け

# 一応自分用です。備忘録として残します。なので結論は出てません。

## nil?
```rb
変数.nil?
```
Rubyの標準メソッド。nilの場合のみtrueを返し、それ以外はfalse

### 下の時に使うのかな。
```rb
irb(main):001:0> a = Model.find_by(id: 100)
  TRANSACTION (0.2ms)  BEGIN
  Plant Load (0.7ms)  SELECT `models`.* FROM `models` WHERE `models`.`id` = 100 LIMIT 1
=> nil  
```
## empty?
```rb
変数.empty?
```
Rubyの標準メソッド。空の文字列や空の配列の場合にtrueを返す。nilに対して呼び出すとNoMethodErrorが発生
### したの時に使うのかな。
```rb
irb(main):007:0> a = Model.where("column LIKE ?", "#{Date.today.year}-#{Date.today.month}%").where(user_id: 100)
  Plant Load (0.6ms)  SELECT `mode.s`.* FROM `models` WHERE (column LIKE '2022-11%') AND `plants`.`user_id` = 100
=> []  
.
.
.
irb(main):008:0> a.class
=> Model::ActiveRecord_Relation
```
# 出典
https://railsdoc.com/active_support

https://qiita.com/somewhatgood@github/items/b74107480ee3821784e6
# 感想
簡単な気づきを書いています。
間違っているかもしれません。
しかし違いがあることに気がつけてよかった。
GASでGoogle翻訳が簡単に使えるという話

## はじめに
この記事はGoogle Apps Script Advent Calendar 2022の2日目の記事です！

https://qiita.com/advent-calendar/2022/google-apps-script

Google Apps Script（以降、GAS）は、Google　DocsやGoogle SheetsといったGoogle系のサービスとの連携が容易であることが知られています。Google系のサービスの中にGoogle 翻訳というサービスがありますが、こちらの機能も簡単にGASで使うことができます。

今回は、GASでGoogle 翻訳をどう使うかを解説しようと思います。

## GASでGoogle翻訳が簡単に使えるという話
GASには`LanguageApp`というクラスが用意されています。このクラスの`translate`メソッドを使うことで、Google 翻訳の機能を使うことが可能です。

### 使い方
```js
LanguageApp.translate(翻訳したいテキスト, 翻訳したいテキストの言語, 変換したい言語[, 返り値のオプション])
```

どの言語が対応しているかは、こちらのリストから確認が可能です。

https://cloud.google.com/translate/docs/languages

返り値のオプションとして、テキストとHTMLが選べるようになっており、デフォルトではテキストになっています。

### サンプル
実際に関数を使って、英語のテキストを日本語に変換するサンプルを書いてみます。

```js
const useTranslate = () => {
    const sourceText = 'How’s it going?';
    // sourceTextを英語(en)から日本語(ja)に変換する
    const translatedText = LanguageApp.translate(sourceText, 'en', 'ja', {contentType: 'text'});
    Logger.log(translatedText);

    // 翻訳結果 => 調子はどう？
}
```

今回は英語のテキストを日本語に変えるスクリプトを書いてみましたが、問題なく変換することができました！

## さいごに
今回は、GASでGoogle 翻訳を使う方法をまとめてみました！簡単に翻訳機能が使えるので、興味がある方は是非ご活用ください。
AWS CLIを使ってS3に大量のファイルを自動でアップロードする

# 目次
[事前準備](#事前準備)
[ファイルをS3にアップロードする](#ファイルをs3にアップロードする)

# 事前準備
・以下のURLを叩いてインストーラーをダウンロードし、AWS CLIをインストールする
https://awscli.amazonaws.com/AWSCLIV2.pkg

・インストールが終わったらターミナルで`$ which aws`を流してコマンドがつかえるか確認する

・`$ aws configure`を流してアクセスキー、シークレットアクセスキー、リージョン名を入力する
```
$ aws configure
AWS Access Key ID [None]: xxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]: 
```
アクセスキーは AWS -> IAM -> ユーザー で確認が可能。シークレットキーは作成時に表示またはダウンロードできるのみなので忘れずに保管しておくこと！

# ファイルをS3にアップロードする
以下のコマンドをターミナルから流すだけ。
```
aws s3 sync . s3://hoge_backet/s3/hoge/ --exclude "*.xlsx" --exclude "*.txt"
```

<b>コマンド解説</b>
`aws s3 sync`：ファイルをアップロードするためのコマンド。
`.`：現在のディレクトリ。
`s3://hoge_backet/s3/hoge/`：アップロードするs3のバケットのフォルダを指定する。
`--exclude "*.xlsx" --exclude "*.txt"`：現在のディレクトリのファイルのうち、拡張子がxlsx,txtは除いてアップせよ、というオプション。

以上をまとめると上記のコマンドは「現在のディレクトリに存在する拡張子xlsx,txtを除いた全てのファイルをアップロードする」という意味になる。


:::note warn
aws s3 cp コマンドでもアップロードは可能だが、s3バケットの中身がアップ元と同じになってしまうので注意
:::
<br>
情報システム戦略とシステム企画　共通フレーム(SLCPーJCF 2013)

# 共通フレーム(SLCP-JCF 2013）
共通フレームは、システム開発の作業全般に渡り、```開発作業の受注側と発注側の双方が共通認識を持つための枠組み```で、８つのプロセスで構成される。システム開発の各工程はこの中の```テクニカルプロセス```に含まれ、さらに6つのプロセスに分けて定義している。

### 企画プロセス
経営課題や現行の```業務・システムの問題点を分析```して、システム化の```対象となる業務を明確化```。システム導入後の業務の全体像を定義し、```業務機能と組織モデルを策定```、システム化の```優先順序と投資目標を決定```。さらに```工数、費用、投資効果、スケジュール```などをプロジェクト計画```としてまとめ、承認を得る。

### 要件定義プロセス
新システムの```利害関係者を識別```し、```利害関係者の要求と制約条件からの業務要件を定義```。その業務内の遂行に必要な機能要件と日機能要件を明確にして、評価を行い、合意を得る。
#### 業務要件
```業務手順```、業務遂行に必要な```情報と成果物```、業務上の```制約事項やルール```、組織内の```責任と権限の範囲```など。

#### 機能要件
```業務要件を実現するために、新システムが備えるべき機能```。

#### 非機能要件
システム化を行う```業務の範囲```、新システムが備えるべき```品質``、```開発方式```や```移行・運用の方法```と```必要なコストや人員```など。

### システム開発プロセス
```システム要件(機能と能力・制約条件など)を定義```し、```必要なハードとソフトの構成(システム要素)を決定```。```システム構成要素を順に結合```し、```システムを作り上げて、テスト、システム導入、システム受け入支援```などを行なっていく。

### ソフトウェア実装プロセス
システム開発プロセスで定義された```必要な機能・能力などをソフトウェア要件として定義```し、```ソフトウェア構築を行う```。単体でリリースする場合は、```ソフトウェア導入、受入支援```まで行う。

### ハードウェア実装プロセス
システムに必要な動作、```インタフェースや実装上の制約条件を満たすハードウェア```や```サービスを構築```または```選定し、設置及び設定```などを行う。

### 保守プロセス
導入されたシステムやソフトウェア製品が```定められた機能を果たし、性能を維持```できるように```メンテナンス```を行う。保守作業に関しては、```費用対効果が高い時期```と```保守方法```を選択する。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
LocalStack をさわってみた

# LocalStack をさわってみた

AWS のサービスをさわり始めるにあたって、利用費用を意識せずに実験がしたいなと思っていたところ、LocalStack の 1.0 が正式リリースされていたので、LocalStack を起動して、AWS-CLI を使って LocalStack に S3 バケットを作成するところまでをやってみました。

[2022 年 7 月に LocalStack 1.0 が正式リリースされた](https://www.publickey1.jp/blog/22/awslocalstack10.html)

## LocalStack とは

クラウドアプリケーションを開発するための、ローカルマシン上でクラウドサービスをエミュレートする機能を提供するツールです。

現時点で、AWS の主要サービスに対応しており無料で使える「Community」版でも基本的な API 群は利用することができるとのこと(※)。

※ 無料で使えるものとそうでないものは[AWS Service Feature Coverage](https://docs.localstack.cloud/aws/feature-coverage/)から確認することができます

## 起動

何はともあれ起動してみる。

```bash
$ docker run --rm -it -p 4566:4566 -p 4510-4559:4510-4559 localstack/localstack

# しばらくすると起動する
・
・
・
Digest: sha256:57c6252b73b29c1eb811b1cccebeb556a3640709bae5a477fbc0e141e4e795b1
Status: Downloaded newer image for localstack/localstack:latest
Waiting for all LocalStack services to be ready
2022-10-15 03:55:21,400 CRIT Supervisor is running as root.  Privileges were not dropped because no user is specified in the config file.  If you intend to run as root, you can set user=root in the config file to avoid this message.
2022-10-15 03:55:21,402 INFO supervisord started with pid 16
2022-10-15 03:55:22,406 INFO spawned: 'infra' with pid 21
2022-10-15 03:55:23,408 INFO success: infra entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

LocalStack version: 1.2.1.dev
LocalStack build date: 2022-10-19
LocalStack build git hash: 02e6c027

2022-10-15T03:55:23.819  WARN --- [-functhread3] hypercorn.error            : ASGI Framework Lifespan error, continuing without Lifespan support
2022-10-15T03:55:23.819  WARN --- [-functhread3] hypercorn.error            : ASGI Framework Lifespan error, continuing without Lifespan support
2022-10-15T03:55:23.820  INFO --- [-functhread3] hypercorn.error            : Running on https://0.0.0.0:4566 (CTRL + C to quit)
```

## 動作確認

AWS-CLI で利用するダミーの設定を作成する。

```bash
$ docker run -it --rm amazon/aws-cli configure --profile dummy
AWS Access Key ID [None]: dummy
AWS Secret Access Key [None]: dummy
Default region name [None]: ap-northeast-1
Default output format [None]: None
```

試しに、LocalStack 内にバケットを作成する。

```bash
# Dockerで立ち上げたLocalStackのCONTAINER IDを確認する
$ docker ps
# IPアドレスを確認する
$ docker inspect {CONTAINER ID} | grep IPAddress

$ docker run -it --rm -v ~/.aws:/root/.aws -v $(pwd):/aws amazon/aws-cli s3 mb s3://sample-bucket --endpoint-url=http://{IP ADDRESS}:4566 --profile dummy
```

LocalStack 内にバケットが作成されたことを確認する。

```bash
$ docker run -it --rm -v ~/.aws:/root/.aws -v $(pwd):/aws amazon/aws-cli s3 ls --endpoint-url=http://{IP ADDRESS}:4566 --profile dummy
```

## 参考

- [LocalStack](https://localstack.cloud/)
seleniumを使った、クローリングでのサイボウズログイン

### ■ サイボウズへの、ログイン用クラス
オブジェクトに、引数として「ログインID」「パスワード」を入れます。
```python:main.py

import requests

from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

import os


class Saibouzu:

    def __init__(self, s_username, s_password):
        self.s_username = s_username
        self.s_password = s_password

    def Saibouzu_Login(self):
        # selenium での　chrome の実行ファイル　指定
        driver = webdriver.Chrome(
            executable_path=r'C:\\chromedriver_win32\\chromedriver.exe')

        try:
            driver.get("https://hhj4p.cybozu.com/login")

            user_id_s = driver.find_element(
                By.NAME, 'username')  # name 属性取得
            pass_word_s = driver.find_element(
                By.NAME, 'password')  # name 属性取得

            user_id_s.clear()
            pass_word_s.clear()

            user_id_s.send_keys(self.s_username)  # name 属性に値をセット
            pass_word_s.send_keys(self.s_password)  # name 属性に値をセット

            user_id_s.submit()  # form を submit する。

            time.sleep(1.2)

            test = driver.find_element(By.CLASS_NAME, 'service-slash')
            test.click()

            time.sleep(1.2)

            driver.find_element(
                By.XPATH, "//*[@id ='appIconMenuFrame']/div[2]/nav/ul/li[2]/span/a").click()

            time.sleep(0.8)

            driver.get(driver.current_url)

        finally:
            os.kill(driver.service.process.pid, signal.SIGTERM)

# ========== サイボウズへログイン開始


Saibouz_Obj = Saibouzu('自分のサイボウズ ログインID 夏目 智徹', '自分のサイボウズの パスワード')
Saibouz_Obj.Saibouzu_Login()


```
vue-awesome-countdownでカウントダウンを実装する

Vue.jsでカウントダウンを実装するときに使ったのでメモ。

# 環境

vue@2.6.14
nuxt@2.15.8

# インストールする

```
yarn add vue-awesome-countdown
```

# 設定

### plugins/vue-awesome-countdown.jsを作成

``` js
import Vue from 'vue'
import VueAwesomeCountdown from 'vue-awesome-countdown'

Vue.use(VueAwesomeCountdown, 'vac')
```

### nuxt.config.jsを修正
`plugins`に追記する

```
{ src: '@/plugins/vue-awesome-countdown.js', mode: 'client' }
```

# 実装！

[vue-awesome-countdown#usage](https://vac.js.org/zh/guide/#usage)
上記のSSR (Nuxt)を参考に実装しました。
今回はミリ秒まで表示したかったので、表示や速度を変更しています。

`endTime`で時間をミリ秒で設定
`speed`で速度を指定。今回はミリ秒まで表示したかったので、10に。
`@finish`でカウントダウンが終了したら`afterFinish`の処理が実行されるように指定。

``` js
<no-ssr>
  <vac 
    :end-time="new Date().getTime() + 60000"
    :speed="10"
    @finish="afterFinish"
  >
    <span
      slot="process"
      slot-scope="{ timeObj }"
    >
      {{ `Lefttime: ${timeObj.m}:${timeObj.s}.${timeObj.ms}` }}
    </span>
    <span slot="finish">Done!</span>
  </vac>
</no-ssr>

<script>
export default {
 ...省略

  methods: {
     afterFinish () {
         // 終了後の処理
     }
  }
}
</script>
```

`timeObj`の中身はこんな風になってました！

``` js
{
  "endTime": 1668493899311,
  "speed": 10, 
  "leftTime": 55072, 
  "d": "0",
  "h": "00",
  "m": "00",
  "s": "55",
  "ms": "072",
  "org": { 
    "d": 0.0006374074074074074, 
    "h": 0.015297777777777778, 
    "m": 0.9178666666666667, 
    "s": 55.072, 
    "ms": 72
  },
  "ceil": { 
    "d": 1, 
    "h": 1, 
    "m": 1,
    "s": 56 
  } 
}
```

# ドキュメント

[vue-awesome-countdown](https://vac.js.org/)
[Github](https://github.com/mlinquan/vue-awesome-countdown)
Hugging Faceコースの日本語翻訳を始めました!

Hugging Faceコースの日本語翻訳を始めました。東北大学のStudent Ambassadorsの皆さんのお陰で第一章の翻訳が終了しました。
今後もコツコツと翻訳していきます。
是非コースを読んでHugging Face Tranformersについて学んで、使ってみてください！

https://huggingface.co/course/ja/chapter1/1
TypeScriptでFireBaseのTimeStamp型を扱う


# はじめに
FireBaseのTimeStamp型のデータ同士を計算したい時に変換で少し詰まったので簡単にまとめてみます。

# やりかた
これでいけました
```
    const newArray = [...datas, newData].sort(
      (a, b) => b.createdAt.toDate().getTime() - a.createdAt.toDate().getTime()
    );
```

# 細かく分解すると

createdAt(Firebaseで用意されているTimeStamp型)
```
nt {seconds: 1668498018, nanoseconds: 349000000}
```

toDate()でDate型に変換
```
Tue Nov 15 2022 16:40:18 GMT+0900 (日本標準時)
```

getTime()で日付と時刻の値を1970年1月1日 00:00:00 UTCからの経過ミリ秒の値に変換
```
1668498018349
```

# おわりに
時刻系の変換は毎回詰まるので慣れていきたいです。
情報システム戦略とシステム規格　情報システム戦略

# 情報システム戦略
1.経営戦略との整合性を取りつつ(経営戦略の確認)、
2.```業務環境の調査・分析
3.業務、情報システム、情報技術の```調査・分析```
4.基本戦略の策定
5.業務の新イメージの作成
6.対象と投資目標の策定
7.情報システム戦略案の策定
8.情報システム戦略の承認
といった順で行う。

## ITガバナンス
経営陣がステーホルダのニーズに基づいて```企業価値を高めるために実施する行動```。また、```情報システムをあるべき姿に導くために必要な組織能力を指す```。

### 情報システム化の基本計画
#### 全体最適化方針
経営戦略基づいて組織全体として```業務```と情報システムが進むべき方針を示す```指針```を策定する。システム化によって```変更される組織```や```業務の変更方針```を明らかにして情報システムのあるべき姿を明確にする。

#### 全体最適化計画
上記の方針に基づき、```情報システム投資の方針や確保すべき経営資源を明確化する```。また、```投資効果・リスクの算定方法```、```開発や運用方法の標準化```、```品質などのルール```を決定。```個々の開発計画の優先順位```などを決め、経営者の承認を得る。
##### 標準化とは？
```利害関係者間における利便性や意思疎通を目的```として、```物事や事柄を統一```したり、単純化、秩序化したりすることであり、```無秩序化や多様化、複雑化を防止する```規格を定めることである。
出典 https://www.sophia-it.com/content/%E6%A8%99%E6%BA%96%E5%8C%96#:~:text=%E6%A8%99%E6%BA%96%E5%8C%96%E3%81%A8%E3%81%AF%E3%80%81%E5%88%A9%E5%AE%B3%E9%96%A2%E4%BF%82,%E7%AD%96%E5%AE%9A%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%82%82%E3%81%82%E3%82%8B%E3%80%82

### 情報システム投資計画
経営戦略との整合性を考慮しながら、システム化計画の```効果、影響、期間、実現性を探っていく```。その際、```複数の選択肢を検討して計画を立案```する。

### システム化計画（個別計画）
上記計画に従い、個別のシステム化計画を立案していく。企業全体や個々の事業活動の統合化を実現し、```企業間の一体運営を可能にするシステム```となるよう考慮する。具体的には、
1.システム化の目的・範囲の定義
2.システムの主要機能の定義
3.システム概要の設計分析
4.開発工数の見積もり
5.開発スケジュールの作成
6.開発体制の立案
7.投資効果の分析
8.開発計画の承認

#### 関連記事
https://dxnavi.com/system-planning-keytosuccess/#toc

### システムの設計思想を表す用語
#### SoR(System of Records:記録のためのシステム)
```従来型の設計思想で確実性を重視```

#### SoE(System of Engagement:つながりのためのシステム)
```ユーザ視点で考え、変更、追加に柔軟に対応```

#### SoI(System of Insight: インサイトのためのシステム)
```SoRとSoEを結ぶ考え方で、双方のデータを分析して、見えない要求を引き出すこと```を重視。

# 問題を解いた時の気づき
### 業務モデルとは?
お仕事のやり方とか流れをまとめて図とか絵とかで表現したもの
出典 https://wa3.i-3-i.info/word17798.html

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
【sftp・expect】非対話方式でsftpコマンドを実行する方法 

# はじめに
sftp方式でファイルをダウンロード、接続先のファイル削除までを自動化したかったが、対話方式でしか通信を行ったことがなかった。今回非対話方式でsftpを行う方法知ったのでメモ。
なお、本記事はbashで書くことを目的としている。

# ダウンロード
以下でカレントディレクトリにファイルがダウンロードされる。
```
sftp -i [keyのフルパス] [ユーザ名]@[アクセス先]:[取得したいファイルのフルパス]
```

# アップロード/削除
```expect.sh
#!/bin/bash

user="[ユーザ]"
sftp_path="[接続先]"
key_path="[keyのフルパス]"

expect -c "
set timeout 3600 
spawn sftp -i ${key_path} ${user}@${sftp_path}
expect \"sftp>\"
send \"put /home/ubuntu/kobayashi/dammy\r\"
expect \"sftp>\"
send \"rm dammy\r\"
expect \"sftp>\"
send \"bye\r\"
expect eof
exit
"
```

ここでは非対話方式のsftpコマンドを使用するのではなく、expectを使用して対話を自動化している。

## expect
以下のQiitaを参考にさせていただいた。[
Linuxの対話がめんどくさい?そんな時こそ自動化だ！-expect編https://qiita.com › Linux](https://qiita.com/ine1127/items/cd6bc91174635016db9b)

一応ここでも簡単に解説する。
## 簡単な解説
expectは、簡潔にいうと対話方式のやり取りを自動でおこなってくれるモノ。
導入は
```
yum install expect
```
<br>

主な要素は以下。

|コマンド|動作|
|:--:|:--:|
|`expect -c "`|ここからexpectで自動化するよーっていうexpectの書き始め。<br>自動化の最後には必ず`"`で締める。|
|`set timeout`|１つのコマンドがタイムアウトするまでの秒数を設定。デフォルトで10秒。|
|`spawn`|自動化対象のコマンドのプロセスを生成。|
|`expect`|前のコマンドの応答を受け取る。<br>指定した文字列を応答が含む場合、次のコマンドを実行する。|
|`send`|実行したいコマンドを記述する。<br>コマンドの後ろに`\r`を書かないと、前の`expect`がタイムアウトするまで<b>実行されない</b>ため注意|
|`expect eof` <br> `exit`|操作の主導権をユーザに戻す。代わりに`interact`でも可。（筆者の好み）|

# メモ
これらを含んだbashはcronで夜間に動かしていたのだが、ユーザをrootにしていたので、sftpでダウンロードされるファイルの格納先がrootになってしまった。
sftpで取得する前にcdでカレントディレクトリを変更することで対応した。
（おそらくsftpコマンドでダウンロード先を指定することができるのだろうが、これで対応できたので調べていない）
mysqlが起動しない

# 環境
macOS Monterey(12.6)
MySQL 8.0.29(Home Brew)

# 現象
Mac本体を再起動したらrails sでサーバの起動ができなくなりました。
MySQLを単体で起動させようとしても
「ERROR! The server quit without updating PID file」というのが出ます。
（PID fileが無いというのは直接的な原因ではない）
```sh:
$ mysql.server start
Starting MySQL
./usr/local/Cellar/mysql/8.0.29_1/bin/mysqld_safe: line 199: 33199 Abort trap: 6           env MYSQLD_PARENT_PID=33088 nohup /usr/local/Cellar/mysql/8.0.29_1/bin/mysqld --basedir=/usr/local/Cellar/mysql/8.0.29_1 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/Cellar/mysql/8.0.29_1/lib/plugin --log-error=MacBook-Air.local.err --pid-file=/usr/local/var/mysql/MacBook-Air.local.pid < /dev/null >> /usr/local/var/mysql/MacBook-Air.local.err 2>&1
 ERROR! The server quit without updating PID file (/usr/local/var/mysql/MacBook-Air.local.pid).
```

### エラーログを見てみる
/usr/local/var/mysql/MacBook-Air.local.err
icu4cのlibicuuc.70.dylibというライブラリが見つからないとか。

```sh:/usr/local/var/mysql/MacBook-Air.local.err
Library not loaded: '/usr/local/opt/icu4c/lib/libicuuc.70.dylib'
  Referenced from: '/usr/local/Cellar/mysql/8.0.29_1/bin/mysqld'
  Reason: tried: '/usr/local/opt/icu4c/lib/libicuuc.70.dylib' (no such file), '/usr/local/lib/libicuuc.70.dylib' (no such file), '/usr/lib/libicuuc.70.dylib' (no such file), '/usr/local/Cellar/icu4c/71.1/lib/libicuuc.70.dylib' (no such file), '/usr/local/lib/libicuuc.70.dylib' (no such file), '/usr/lib/libicuuc.70.dylib' (no such file)
```

### /usr/local/opt/icu4c/lib/の中
```sh
$ ls -la /usr/local/opt/icu4c/lib/ | grep libicuuc
-r--r--r--   1 devzooiiooz  staff   1701880 11 15 14:40 libicuuc.71.1.dylib
lrwxr-xr-x   1 devzooiiooz  staff        19  4  8  2022 libicuuc.71.dylib -> libicuuc.71.1.dylib
-r--r--r--   1 devzooiiooz  staff   2678240  4  8  2022 libicuuc.a
lrwxr-xr-x   1 devzooiiooz  staff        19  4  8  2022 libicuuc.dylib -> libicuuc.71.1.dylib
```
要するにmysqlではlibicuucのバージョン70を見ようとしているのに71.1にバージョンアップされたので見つからない。

# 解決方法
色々とやったのですが、結局brewのupdateとicu4cの再インストールで解決しました。

```sh:
$ brew update && brew reinstall icu4c
==> Reinstalling icu4c 
==> Pouring icu4c--71.1.monterey.bottle.tar.gz
🍺  /usr/local/Cellar/icu4c/71.1: 262 files, 76.2MB
==> Running `brew cleanup icu4c`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Upgrading 3 dependents of upgraded formula:
Disable this behaviour by setting HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
mysql 8.0.29_1 -> 8.0.31, node 18.11.0 -> 19.0.1, postgresql@14 14.5_5 -> 14.6
以下略
```

### MySQLのアップデートが終わったら
rootのパスワード無しでMySQLがインストールされるので
brewのメッセージの通りに「mysql_secure_installation」を投入する。
（既存のDBには影響を与えません）

```sh:
==> mysql
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation
```
```sh:
$ mysql_secure_installation
..
略
..
All Done！
```

適宜質問に答えていく。
これで解決しました。午後がつぶれた…。

## 参考
ここの「icu4c をインストールし直す」が一番参考になりました。ありがたや。
[phpがdyld: Library not loaded: /usr/local/opt/icu4c/lib/libicuio.68.dylibエラーで動かなくなった](https://www.gaji.jp/blog/2022/08/03/10687/)
[忘備録][CentOS6]サーバーへsshアクセスを行うのにIP制限を行う

この記事は、もうとっくにCentOSが死んで長いのにさらにCentOS6で行ったもののため、この内容は最新の情報にマッチしないことがあります。

手元のサーバーで行う際は、十分に情報を確認の上行ってください。　

# はじめに

セキュリティのため、サーバーへsshアクセスを行うのにIP制限を行うようにすることにした。

適当に調べたところによると、/etc/security/access.confを編集し、/etc/pam.d/sshdファイルにaccess.confを確認するように記述してアクセス制限を行うらしいが、そのまま行うといくつかの落とし穴にハマってしまった。

この記事はそれら落とし穴にはまらないようにIP制限を行う手順書である。

# IP制限を書こう！

`/etc/security/access.conf`の中にはデフォルトでコメントの形で「どのように記述すればいいのか」が書いてある。
そのコメントを参考に記述内容を事前に決めておく。
なお、そのままコメントの下に記述を行うと、crontabコマンドにもアクセス制限がかかってしまうので、別ファイルを作成する。

```bash:/etc/security/sshd_access.conf
+ : ALL : 192.168.0.0 
- : ALL : ALL
```

もしも解禁したいIPが複数ある場合はスペースを挟んで書いたり、複数行並べることもできる。
.htaccessのように上から順に「まずすべて禁止して…」と書きたくなるが、access.confでは逆なので注意。

# IP制限を反映させよう！

実際にsshへのアクセス制限を記述しているファイルは`/etc/pam.d/sshd`である。
こちらも上から順に認証をかけているようなので、終了されてしまう前に制限をかけるようにする。
具体的には、`account include password-auth`が成功したら以降の処理をすべてスキップして処理終了の動きをしてしまっているので、それよりも前に記述する。

```bash:/etc/pam.d/sshd
#%PAM-1.0
auth       required     pam_sepermit.so
auth       include      password-auth
account    required     pam_nologin.so

#↓を追加
account    required     pam_access.so accessfile=/etc/security/sshd_access.conf

account    include      password-auth
password   include      password-auth

...以下色々書いてある

```

なおここのファイルは**記述ミスするとエラーメッセージ無しで全アクセスが不能になる**ので必ずチェックすること。

最後に`/etc/ssh/sshd_config`の中身を確認し、そもそもpam.dの設定が使えるかどうかを確認する。
以下の記述があれば利用できます。

```
UsePAM yes
```

以上で完了です。
最後に`service sshd reload`を忘れずに。

そしてセッションを切ってしまう前に別のbashでアクセスし、ちゃんと制限がかかっている（または余計な制限をかけてしまっていないか）確認すること。


# 最後に

この記事は以下のURLを参考にしました。

https://qiita.com/tjinjin/items/ca6f5518e881bdf5488c

https://atmarkit.itmedia.co.jp/bbs/phpBB/viewtopic.php?topic=38820&forum=10

https://kazmax.zpp.jp/linux/lin_pam.html
Firebaseから取得したデータを日付でソートする

# はじめに
firebaseから取得したデータをソートしたかったのですが、firebase上でのクエリの書き方やそもそもリファレンスやスナップショットの関係について理解していなかったので簡単にまとめてみます。
関係図などはこちらの記事を参考にしていました。

https://tenderfeel.xsrv.jp/javascript/4980/

# FireBaseを操作する基本的な流れ

①Firebaseからcollection()でCollectionReferenceを取得
②CollectionReferenceからget()でQuerySnapshotを取得
③QuerySnapshotからdoc()でQueryDocumentSnapshotを取得
④QueryDocumentSnapshotからdata()でDocumentDataを取得

# やりかた
query関数の第一引数にcollection,第二引数にqueryを渡し、getDocs()に渡す

```
  ~略~
  const db = getFirestore(app);
  const q = query(
    collection(db, "document"),
    orderBy("createdAt", "desc")
  ).withConverter(documentConverter);
  const snapshot = await getDocs(q);
  return snapshot.docs.map((doc) => doc.data());
}


```

# おわりに
typescriptを使っていたので型エラーと頻繁に戦っていました。
公式ドキュメントを読める力も大事なので慣れていきたいです。
(どうしても図解が欲しくなってしまいます)
WindowsでもHomebrew使えたらいいな。の解決策

<h1>結論:Scoopを使う</h1>
ChocolateyっていうHomebrewに似たものがあるみたいだが、私的にはcoopsのほうが簡単にインストールすることができた。以下リンク。

https://scoop.sh/

<h2>install過程</h2>

```
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex
```
ダウンロードできるおまじない。(PowerShell)
```
 scoop -v
```
バージョンの確認。

```
 nvm list available

|   CURRENT    |     LTS      |  OLD STABLE  | OLD UNSTABLE |
|--------------|--------------|--------------|--------------|
|    19.0.1    |   18.12.1    |   0.12.18    |   0.11.16    |
|    19.0.0    |   18.12.0    |   0.12.17    |   0.11.15    |
|   18.11.0    |   16.18.1    |   0.12.16    |   0.11.14    |
|   18.10.0    |   16.18.0    |   0.12.15    |   0.11.13    |
|    18.9.1    |   16.17.1    |   0.12.14    |   0.11.12    |
|    18.9.0    |   16.17.0    |   0.12.13    |   0.11.11    |
|    18.8.0    |   16.16.0    |   0.12.12    |   0.11.10    |
|    18.7.0    |   16.15.1    |   0.12.11    |    0.11.9    |
|    18.6.0    |   16.15.0    |   0.12.10    |    0.11.8    |
|    18.5.0    |   16.14.2    |    0.12.9    |    0.11.7    |
|    18.4.0    |   16.14.1    |    0.12.8    |    0.11.6    |
|    18.3.0    |   16.14.0    |    0.12.7    |    0.11.5    |
|    18.2.0    |   16.13.2    |    0.12.6    |    0.11.4    |
|    18.1.0    |   16.13.1    |    0.12.5    |    0.11.3    |
|    18.0.0    |   16.13.0    |    0.12.4    |    0.11.2    |
|    17.9.1    |   14.21.1    |    0.12.3    |    0.11.1    |
|    17.9.0    |   14.21.0    |    0.12.2    |    0.11.0    |
|    17.8.0    |   14.20.1    |    0.12.1    |    0.9.12    |
|    17.7.2    |   14.20.0    |    0.12.0    |    0.9.11    |
|    17.7.1    |   14.19.3    |   0.10.48    |    0.9.10    |
```
現在インストールできるバージョンを確認するコマンド。

```
nvm install 16.14.2
```
16.14.2をダウンロードするコマンド(バージョンはお好みで)

```
nvm list
```
現在ダウンロード済みのバージョンを確認できるコマンド。

```
nvm current
```
現在使用中のバージョンを確認するコマンド
【文字検出_備忘録】OpenCV X Python エッジ検出処理

続きをやっていきましょう。今日は2値化ファイルの画素値出力をした後、エッジ検出処理をやります。



### 画素値出力
```
#2値化ファイルの画素値出力
test_f = open(TEST_file_path,'w') #txtファイルを含めたパスを用意しました。

y_depth = img_gray_th_otsu.shape[0]
x_depth = img_gray_th_otsu.shape[1]

for y_num in range(y_depth):
	for x_num in range(x_depth):
		test_f.write("y_num["+str(y_num)+"] x_num["+str(x_num)+"]:"+str(img_gray_th_otsu[y_num][x_num])+"\n")

test_f.close()
```

としてみると、ちゃんと0か255になっていることがわかりました。
ヒストグラムみると若干違ったのでちょっと怪しんでましたが、まぁ良さそう。


### エッジ検出
Canny法でのエッジ検出をやってみます。

参考資料：Canny法について

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_canny/py_canny.html#canny


日本語がありがたい。
閾値を求めるのが難しそうだったのですが、一旦サンプル通り、100 200でやってみようと思います。

```
#Canny法を使ったエッジ検出処理
edges = cv2.Canny(img_gray_th_otsu,100,200)


#画像出力
plt.subplot(121),plt.imshow(img_gray_th_otsu,cmap='gray')
plt.title('original Image'),plt.xticks([]), plt.yticks([])

plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

plt.show()

```

すみません、今まで全然画像を見せてなかったんですがいい感じになりました。左がオリジナル画像で、右がエッジ検出後です。![Edge検出後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969158/96a3e199-a5fc-e545-5d30-6ec2cad6b439.png)
Microsoft Azure Data Fundamentals(DP-900)に合格するための勉強方法

先日、DP-900の試験に合格しましたので、忘れないうちに備忘録兼ねて勉強方法をまとめておきます。
下記内容は2022年11月現在の情報です。
今後試験内容が改訂されることもありますので、その点ご了承ください。

# 試験範囲
- 主要なデータ概念についての説明する (25–30%)
- Azureでのリレーショナルデータの考慮事項の特定 (20–25%)
- Azureでの非リレーショナルデータを扱う上での考慮事項についての説明 (15–20%)
- Azureでの分析ワークロードの説明 (25–30%)

# 試験形式
- 問題数 : 42問
- 時間 : 45分
- 合格点 : 700／1000点
※MSの公式情報では問題数：49問、時間：60分との記載だったので、鵜呑みにしてたら変わってました（汗）

# 回答形式
- 選択問題（はい／いいえ）※１問の中で複数問題あり
- 複数選択問題（チェックボックス型／コンボボックス型／ラジオボタン型）
- ドラッグアンドドロップ問題

# 受験時のスペック
20年以上SIerをやってます。
ですので、DBに関してはこれまで開発や運用で利用することが多く、リレーショナルデータベースについては基礎知識があります。
- SQLServer2000～SQLServer2016使用経験あり
- Oracle Gold、MCP資格(SQL Server)保持
- AZ-900取得済み

※以前投稿したAZ-900の合格体験についてはこちらを参照ください。

https://qiita.com/fsd-kozue/items/8b92ab1d82e74f5e8421


# 受験までにやるべきこと
合格のためにやるべきことは下記１～３、少し投資してもいいという方は４もおススメします。
<strong>1. Virtual Training Daysの受講</strong>
AZ-900の受験と同様に、<B>Data Fundamentals: データの基礎 - 【DP-900無料試験特典付き】</B>を受講して概要と試験範囲を抑え、無料のバウチャーチケットを入手しましょう。
ウェビナーは[こちらのURL](https://www.microsoft.com/ja-jp/events/top/training-days/azure?activetab=a1:primaryr6 "https://www.microsoft.com/ja-jp/events/top/training-days/azure?activetab=a1:primaryr6") から申し込めます。


<strong>2. Microsoft Learnのラーニングパスで勉強</strong>
試験範囲に対応した [ラーニングパス](https://learn.microsoft.com/ja-jp/certifications/azure-data-fundamentals/ "https://learn.microsoft.com/ja-jp/certifications/azure-data-fundamentals/")をじっくり読んでください。ラーニングパスで不足している内容は、モジュールで補うようにしましょう。それほどボリュームはないので、２～３日もあれば読み切れると思います。


<strong>3. 試験対策On Demand講座の問題を解く</strong>
MSのサイトから「DP-900 : Microsoft Azure Data Fundamentals 試験対策」を [ダウンロード](https://info.microsoft.com/JA-AzureSQL-WBNR-FY21-04Apr-14-MKTOFY21DP900PrepSessionOn-demandWebinar-SRDEM71243_LP02OnDemandRegistration-ForminBody.html "https://info.microsoft.com/JA-AzureSQL-WBNR-FY21-04Apr-14-MKTOFY21DP900PrepSessionOn-demandWebinar-SRDEM71243_LP02OnDemandRegistration-ForminBody.html")して、何度も復習します。
資料の隅々まで読んで問題と解答を覚えるぐらいまで繰り返し学習するのがいいと思います。
DP-900の試験は、この資料をどこまで読み込んで自分のものになっているかがキーとなります。

<strong>4. 過去問を解く(有料)</strong>
AZ-900受験の時と同様にUdemyのサイトで、[「絶対合格！Microsoft DP-900　模擬試験問題」](https://www.udemy.com/course/microsoft-dp-900-af_azurestudyacademy/")を買いました。
「この問題集で90点以上とれるようになったらDP-900の試験に合格できる」が謳い文句になっています。試験を受けるまでは疑ってたのですが(笑)、実際受けてみると70～80％程度は、同じ問題が出題されていましたので信憑性はあるかと！

# 感想など
私はMS Learnを3日ぐらい、オンデマンドの試験対策とUdemyの試験対策をあわせて5日間ぐらい勉強してから試験に臨みました。(ただ、オンデマンドの試験とUdemyの試験対策は同じような問題ばかりだったので、無理にUdemyまで手を出す必要はなかったかもしれません)
かなり入念に対策していったつもりでしたが、弱点対策していった問題が1問もでなかったり、過去問で見たことないなあと思う問題があったり、重箱の隅をつついてくる問題があったり。。。
そして、時間と問題数が想定外でしたので、開始直後は結構焦っておりました・・・(笑)

ですが、ちゃんと準備して試験に臨めば必ず合格できます!!
この記事がこれから試験を受ける方のお役に立てれば幸いです。
ASP.NET Core でPolicyベースの認可でOR判定したいとき

ASP.NET Core でRoleベースの認可でOR判定したいときは、以下のようにロールをカンマ区切りで指定すればよい。
```
[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
    public IActionResult Payslip() =>
                    Content("HRManager || Finance");
}
```

じゃあ、Policyベースの認可でOR判定したいときはどうすればよいのか。
同じように実施するとエラーになる。

```
[Authorize(Policy = "BadgeEntry,TemporarySticker")]
//InvalidOperationException: The AuthorizationPolicy named: 'BadgeEntry,TemporarySticker' was not found.
public IActionResult VacationBalance()
{
    return View();
}
```

Requirementを同じHandlerを複数作ってそのHandlerをDIコンテナに登録すれば、それがOR条件になる。
```
using Microsoft.AspNetCore.Authorization;
using AuthorizationPoliciesSample.Policies.Requirements;

public class BuildingEntryRequirement : IAuthorizationRequirement { }

public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context, BuildingEntryRequirement requirement)
    {
        if (context.User.HasClaim(
            c => c.Type == "BadgeId" && c.Issuer == "https://microsoftsecurity"))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

public class TemporaryStickerHandler : AuthorizationHandler<BuildingEntryRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context, BuildingEntryRequirement requirement)
    {
        if (context.User.HasClaim(
            c => c.Type == "TemporaryBadgeId" && c.Issuer == "https://microsoftsecurity"))
        {
            // Code to check expiration date omitted for brevity.
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}
```

```
builder.Services.AddSingleton<IAuthorizationHandler, BadgeEntryHandler>();
builder.Services.AddSingleton<IAuthorizationHandler, TemporaryStickerHandler>();
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("BadgeEntry,TemporarySticker", policy =>
        policy.Requirements.Add(new BuildingEntryRequirement));
});
```

https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-6.0


元ネタ：
https://learn.microsoft.com/ja-jp/aspnet/core/security/authorization/policies?view=aspnetcore-6.0#why-would-i-want-multiple-handlers-for-a-requirement
https://www.tektutorialshub.com/asp-net-core/policy-based-authorization-in-asp-net-core/

元ネタ参考ソース：
https://github.com/tekTutorialsHub/Authorization-in-ASP-NET-Core/tree/main/04.%20Policy%20based%20Authorization/AuthzExample
C# で カラーバー(HeatMap) を作ってみた

# 変更履歴
* 2022年11月22日：Ver0.2.0 リリースに伴い内容を修正
* 2022年11月29日：Ver0.3.0 リリースに伴いガンマ補正の記述を追加
* 2023年01月27日：Ver1.0.0 リリース（ColorBarLib自体に問題がなさそうなので）
* 2023年02月14日：Ver1.1.0 リリース (バグフィックス)
* 2023年11月08日：タグに heatmap を追加(ヒートマップて言うのか…)
* 2025年02月19日：Ver1.1.1 リリース
　　　　　　　　　 ・対象を「.net standard2.1 / net6.0 / net8.0」 に変更
　　　　　　　　　 ・NuGetに公開してみた。

## NuGet
https://www.nuget.org/packages/ColorBarLibrary/

## Github
https://github.com/pianyi/ColorBarLib

# 動機
元々 Gnuplot でサーモグラフィーみたいな2D画像を作成していました。
しかし出力データを「テキスト出力 → ProcessでGnuplot起動」の手順じゃないと出来ないため、とても遅いです。
どうにかならんかと思い作ってみました。

## 作成イメージ(OpenCVSharp4を利用)
|イメージ|RGB指定|
|:-:|:-:|
|![Sample1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717963/9abe5812-0346-2463-1349-ed0ae8dd4aad.png)|```#FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000```|
|![Sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717963/238b538d-5b92-791a-a0da-eea14f2ba5f7.png)|```#000090, #000FFF, #0090FF, #0FFFEE, #FFFFFF, #FFEE00, #FF7000, #EE0000, #7F0000```|
|![サーモグラフィー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717963/01690802-50cc-d6ff-4cc7-2eb26ba9e695.png)|```#000088,#0000FF,#00FFFF,#FFFF00,#FF0000,#FFFFFF```|

## 使い方
Githubソース内のExcample を見るのが早いと思います。
カラーバー作成と表示画像作成でやり方が微妙に事るので…

使い方の例：
```C#:グレースケール
colorPalette = new()
{
    MinValue = 0,
    MaxValue = 255
};
// 上記指定したプロパティ値を利用
Color color = colorPalette.GetRGBColor(value);
// または上記指定したプロパティ値を無視し、最大値・最小値を指定
// Color color = colorPalette.GetRGBColor(value, minValue, maxValue);
```
```C#:カラー
ColorPalette colorPalette = new("#FF0000, #FFFF00, #00FF00, #00FFFF, #0000FF, #FF00FF, #FF0000")
{
    MinValue = 0,
    MaxValue = 255
};
// 上記指定したプロパティ値を利用
Color color = colorPalette.GetRGBColor(value);
// または上記指定したプロパティ値を無視し、最大値・最小値を指定
// Color color = colorPalette.GetRGBColor(value, minValue, maxValue);
```

## 簡単な説明
1. コンストラクタでRGBカラーのリストからカラーパレットを作成します。
1. GetRGBColor() メソッドで実際の値がカラーパレットのどの色に該当するかを探し出します
1. コンストラクタの色指定無しにするとグレースケール（ガンマ補正有り）になります。
1. 色指定を「#000000,#FFFFFF」にするとグレースケール(ガンマ補正無し)になります。
1. 画像作成時の最大値・最小値は画像のビット単位最大・最小値を指定する
1. カラーバー作成時の最大値・最小値は表示位置（XまたはY軸）の最大・最小値を指定する

## その他
- 最大値・最小値はマイナス値も対応してます
- 最大値・最小値は小数点でも行けるはずです(サンプル画面では数値入力後にマイナスを付与)
- ライブラリ自体は Color を使っているので、.net3.5 レベルまで落としても動くのでは？(責任持ちません)
- 1つ1つは難しい事をしてないので、Java変換も行けるはず…
- なんでこれ系はPythonばっかりなんだよっ！

## 課題・問題点
1. ~~グレースケールのカラーバーは良いのですが、実際の画像を出力した場合Gnuplot よりも暗めになりました。何かが間違っているんだろうが…~~
　→　調べた結果Gnuplotでは「ガンマ補正」を行っているようなので、同じようにガンマ補正を行うように変更しました。数値はGnuplotと同じ1.5を利用しています。
1. ~~「ColorPalette」クラスの名前が、「System.Drawing.Imaging.ColorPalette」と被ってる…変更せねば…~~
　→　コメントの @albireoさん の提案に合わせてクラス名を「ColorBarPalette」に変更しました。
1. 【2022/11/21追記】HSLで作成しているから処理が複雑化してる？HSVにすればもっと簡単になるかも…？
1. ~~この後なにも無ければバージョン1.0にする。~~
　→　2023年01月27日リリース
1. RGB画像を対応するCSVファイルにする機能を入れるか…別EXEにするか…(ってかこれはその辺に落ちてるアプリで十分か……)
1. サンプル画面を英語で作るのが面倒になってきた…

# 終わりに
今回はサーモグラフィーのような画像作成を目的として探しましたが、グラフや画像作るコードを探すと Python ばっかりな気がする…
またはGnuplotのような実行形式のもので、DLL形式のものを見つけられなかった…
昔はたくさんあったのかもしれないが、どこへ行ったのか…

ちなみに、約3000 × 2000 (ピクセル)ぐらいの画像作成が、Gnuplot(テキストファイル出力～画像ファイル作成まで)で約8秒 だったのが、約2秒まで減らせました。
やはりファイルI/Oを無くすのは速度にとって重要ですね。


なお、初投稿なので良くない記載があれば教えて頂けると嬉しいです。
TypeScriptのnever型について

# TypeScriptの勉強中に遭遇した型エラー
プロを目指すTypeScriptを読み勉強していた所、関数のセクションで次のようなサンプルコードがありました。
~~~4.1 function.ts
function range(min: number, max: number): number[]{
  const result = [];
  for( let i = min; i <= max; i++){
    result.push(i);
  }
  return result;
}
console.log(range(5,10));
~~~~
しかし、この状態だと、
![スクリーンショット 2022-11-15 14.24.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402613/bc6bd8c8-7767-3c9f-bb3f-a8f6470d4506.png)
`return.push(i)`部分で赤波線がつき、ホバーすると、何やらiを空配列に入れることができないという主旨の説明が表示されました。

以下が、実際のエラー表示

:::note alert
型 'number' の引数を型 'never' のパラメーターに割り当てることはできません。
:::

## never型について調査した
調べていると、以下の記事でnever型について説明されていた。
[TypeScriptのNever型とは？
](https://qiita.com/macololidoll/items/1c948c1f1acb4db6459e)こちらを見ると、値を持たず、どんな値もいれれず、どんな型にも入れれない型だそう。
今回の場合だと、`result`変数が空配列のため、never型に相当しています。
そのため、`result.push(i)`で値を追加しようとすると、型違いでエラーが起きてしまったようです。
（参考にしている著書が2022年版のため、このnever型を考慮していないとは考えられないため、私の環境で、必要なパッケージが不足している可能性があります）

## エラーの解消方法
結果としては、`result`変数に明示的に型を追加することでエラーを解消することができた。
```diff_typescript:4.1 function.ts
function range(min: number, max: number): number[]{
- const result = [];
+ const result: number[] = [];
  for( let i = min; i <= max; i++){
    result.push(i);
  }
  return result;
}

console.log(range(5,10));
```
他にも、改善方法があれば、コメントなどで教えていただけると嬉しいです。
これからも、typeScriptを勉強していきます。
Leetcode 540. Single Element in a Sorted Array

# 540. Single Element in a Sorted Array

https://leetcode.com/problems/single-element-in-a-sorted-array/description/

## アプローチ
### Hashmap

```java
class Solution {
    public int singleNonDuplicate(int[] nums) {
        if(nums == null || nums.length == 0){
            return 0;
        }
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        for (int num : nums) {
            hashMap.put(num, hashMap.getOrDefault(num, -1) + 1);
        }

        return hashMap.keySet().stream().filter(key-> hashMap.get(key) == 0).findFirst().get();
    }
}
```
DDDがわからない～面倒くさいので手分けしよう～

# 面倒くさいので手分けしよう
人が作業をするとき作業手順が増えれば増えるほど、一度に覚えて置かなければならないことが増えて面倒くさいです。作業を分けることで人の作業を分散化して楽をしましょう。


# 一人でやらなくてもいいんじゃないか？
~~~text:手動配送システム
1. 伝票を全部確認して、今日の発注分の商品を紙にメモする
2. メモを地域ごとに分ける
3.商品カタログを確認して今日配送するすべての商品のサイズをメモする
4. 車庫に行き今日使える使えるトラックのサイズをメモする
5. 先ほどのメモを組み合わせて効率的な積み込み方を決めてメモする
6. 各トラックの運転手に積み込み方を決めたメモに配送先のメモを添えて渡す
~~~

この手動配送システムですが、これ一人の人間がやるのは手順が多くて大変だと思います。
なので、人を増やしてひとりひとりの手順を減らしましょう。

~~~text:手動配送システム
伝票担当
1. 伝票を全部確認して、今日の発注分の商品を地域ごとにメモする。(伝票メモ)
2. カタログ担当に伝票メモを渡す。

カタログ担当
1. 伝票担当のメモを見ながら商品カタログの今日必要な商品サイズをメモする(商品メモ)
2. 計算担当に伝票メモと商品メモを渡す。

車庫担当
1. 今日使えるトラックのサイズをメモする(車両メモ)
2. 計算担当に車両メモを渡す。

計算担当
1. 伝票メモと商品メモと車両メモを使ってトラックの効率的な積み込み方を決めてメモする(配送メモ)
2. それぞれのトラックの運転手に配送メモを渡す。 

~~~
ひとりひとりの作業はかなり楽になったと思います。

コンピューターの中では人件費なんて考えなくていいのですからどんどん人を増やしていきましょう。

# 面倒くさくないこと
例えば伝票担当をさらに３人に分けて伝票をめくる人、地域を確認する人、メモを書く人と分けたら逆に面倒くさいです。人件費がかからないといっても人を用意するのは大変です。バランスの割り振りをしましょう。
Android Studio エミュレータが立ち上がらない場合の対処

# 開発環境
OS: MacOS
Android Studio: Artic Fox | 2020.3.1 Patch4

# 再現手順
Android Studioでエミュレータを指定してアプリを起動
![スクリーンショット 2022-11-15 14.00.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980010/6ebd20f2-a35c-6fb1-f99a-43e95d0a37b3.png)

# 事象内容
・エミュレータが起動してくるはずだが、起動しない
　※対象のエミュレータについて、以前は起動できていた
・他のエミュレータを選択すると無事起動できる

# 原因
おそらく前回のエミュレータの終了処理がうまくいっていない。
筆者もMacが勝手にシャットダウンされてから該当の事象が発生した。

# 解決方法
①AVDマネージャーを開く
![スクリーンショット 2022-11-15 14.04.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980010/ed2699aa-d023-ad2d-2769-c99bfed0cb7b.png)
②対象のエミュレータの実行ボタンを押下する
![スクリーンショット 2022-11-15 14.05.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980010/ed7cbe40-3d8b-d992-6835-81f3a3dd2ab9.png)
③エラー文言とともに、対処内容が出てくる
![スクリーンショット 2022-11-15 14.06.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980010/6e5df3e8-c9ed-1a14-bfd0-127e4ac251dc.png)
④エラー文言に従って.lockファイルを削除する
このとき、対象のエミュレータのプルダウンメニューから「ディスクに表示」ボタンを押下すると対象のフォルダに簡単に飛べます
![スクリーンショット 2022-11-15 14.22.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980010/b541224c-7e28-4d4b-47c5-cca32c693da4.png)
筆者の場合ではPixcel_4_API_30.avd直下の.lockファイルを全部（2つ）削除します
![スクリーンショット 2022-11-15 14.25.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980010/86ee1bbb-5309-ea99-f83a-795a3d37408a.png)
無事エミュレータが起動できました。
![スクリーンショット 2022-11-15 14.27.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980010/76df14c4-c1d7-4ddd-5f48-4044cf29bda9.png)
# 最後に
ご覧頂きありがとうございました。
エミュレータは無事起動できましたでしょうか？
ご質問等あればコメント頂けると幸いです。

# 参考記事
https://e-yota.com/webservice/post-2476/
AE-ESP32-WROOM-32E-MINIのライブラリを作りました。

Autodesk Eagleで使えるライブラリを作成しました。

ESP32の開発者ボードになります。
通常の開発者ボードよりも小さいです。USB-シリアル変換モジュールがないと書き込みができません。
![AE-ESP32-WROOM-32E-MINI](https://akizukidenshi.com/img/goods/3/K-16108.jpg "AE-ESP32-WROOM-32E-MINI")
https://akizukidenshi.com/catalog/g/gK-16108/

## Githubにて配布します。
https://github.com/reolch/Eagle-Library
OUPC2022 K「Square」L「Re:Square」解説

# はじめに
「Square」writerのKowerKointです。
通常の全列挙で間に合わないので半分全列挙で高速化すると「Square」が突破でき、通常のbitDPで間に合わないので使うビットを工夫して減らすと「Re:Square」も含めて突破できるという問題でした。

この問題は当初半分全列挙のみを想定したのですが、testerのWA_TLEさんがより高速な解法を発見したため、それに対応した問題が「Re:Square」として採用されました。
# 解説
## 半分全列挙による解法(「Square」のみAC)
半分全列挙をします。
つまり、数列$A$を半分ずつに分けて、それぞれの中で作れる整数を列挙します。

$A_1,A_2,\dots A_{N/2}$から作れる整数の多重集合を$S$、$A_{N/2+1},A_{N/2+2},\dots A_{N}$から作れる整数の多重集合を$T$とします。
$S$の要素$s$のそれぞれについて、$s$と掛け合わせて平方数を作る$T$の要素の総和を取りたいです。

したがって、$s$が与えられたときにそれと掛け合わせて平方数をなすものを$T$の中でグループ化しておき、それぞれの$s\in S$について対応するグループに含まれる数の総和を$s$とかけ合わせればよいことがわかります。

平方数を作る$2$つ数の組の性質を考えます。
整数$x$を素因数分解したとき、すべての素因数の指数は偶数であることと$x$が平方数であることは同値です。
これを利用すると、$s$と$t$について$st$が平方数となる必要十分条件は$s$の素因数のうち指数が奇数のものの集合と$t$の素因数のうち指数が奇数のものの集合が一致することであるとわかります。

以上から、$S$と$T$を、「素因数分解したとき指数が奇数になる素因数の集合」でグループ分けしてその総和を予め計算しておけばうまくマージできます。

## 工夫したbitDPによる解法(「Square」と「Re:Square」をAC)
半分全列挙と同じように、素因数の指数の偶奇に着目します。
各素因数の指数の偶奇をビット列として扱い、`dp[i][j]`を「$A$の`i`番目までを使って素因数の指数の偶奇が`j`のようになるものの総和」とすればビット列の長さを$M$とした$O(N2^M)$時間でのbitDPでこの問題が解けます。

このままでは「Square」の制約では$46$種類、「Re:Square」の制約では$62$種類の素因数が登場し得るため、bitDPでは間に合いませんん。
しかし、$Y$以下の正の整数を素因数分解したとき、$\lceil\sqrt{Y}\rceil$以上の素因数はたかだか1種類しか存在しないことを考えると、$\lceil\sqrt{\max A}\rceil$以上の素因数ごとにグループ化してそれらを連続して処理することにすれば同時に必要な素因数は$\pi(\sqrt{\max A})$($\pi(x)$は$x$以下の素数の個数)程度ですむのです。

以上から、$O(N2^{\pi(\sqrt{\max A})})$時間のbitDPでこの問題が解けました。

ちなみに、おまけですが$A_i<=2000$の制約でもこの問題は解ける(testerのygussanyさんに教えていただきました)ので、余裕があれば考えてみてください。
さくらVPSのUbuntu初期設定覚え書き

# コントロールパネルでの再インストール
- OSインストール形式
    - 標準OS
- インストールOS
    - Ubuntu 22.04 amd64
- スタートアップスクリプト利用
    - 利用しない
- パケットフィルター設定
    - SSH
    - Web
    - Mail
- 初期ユーザーはubuntu

# 自分のユーザー作る
```bash
ubuntu@sakura:~$ sudo su -
[sudo] password for ubuntu:
root@sakura:~# adduser shimano
Adding user `shimano' ...
Adding new group `shimano' (1001) ...
Adding new user `shimano' (1001) with group `shimano' ...
Creating home directory `/home/shimano' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for shimano
Enter the new value, or press ENTER for the default
        Full Name []: shimano equipped
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y
root@sakura:~# gpasswd -a shimano sudo
```

# アップデート
```bash
root@sakura:~# apt update && apt -y upgrade
```

# カーネルupdateされたらrebootしとく
```bash
root@sakura:~# reboot now
```
【文字検出_備忘録】OpenCV X Python グレースケール画像の２値化

こんにちは。続きをやりましょう。

### グレースケール化の確認
グレースケール化までやったのでそれができてるかの確認をします。
せっかくなので、ndarrayの出力も試したいなと思って、以下のコードを書きました。
```
for y_num in range(0,5):
	for x_num in range(0,5):
			print("print["+str(y_num)+"]"+"["+str(x_num)+"]:"+str(img_gray[y_num][x_num]))

```
img_gray[y_num][x_num]の部分で、画素値の出力をしてます。
実行結果。
```
print[0][0]:251
print[0][1]:251
print[0][2]:251
print[0][3]:251
print[0][4]:251
print[1][0]:251
print[1][1]:251
print[1][2]:251
print[1][3]:251
print[1][4]:251
print[2][0]:251
print[2][1]:251
print[2][2]:251
print[2][3]:251
print[2][4]:251
print[3][0]:251
...
```
しっかり入ってますね。
では早速、これのヒストグラムでも書いてみましょう。

```
#ヒストグラム
fig = plt.figure()
ax = fig.add_subplot(1,1,1)

ax.hist(img_gray)
plt.show()

```



参考：ヒストグラムの出し方

https://qiita.com/supersaiakujin/items/be4a78809e7278c065e6

参考：plot関数について


https://www.yutaka-note.com/entry/matplotlib_figure#Matplotlibの描画領域Figureと座標軸Axes

出てきました。![Histogram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969158/57d84f9c-b645-b767-5558-4de86f8a9744.png)

多分、この一番右の多い群が白色かなぁとか思ったり。
大津の2値化を使って、やってみましょう。

### 2値化
```
#大津の２値化をって、閾値を求める+2値化
th, img_gray_th_otsu = cv2.threshold(img_gray,0,255,cv2.THRESH_OTSU)


#画像出力
plt.imshow(img_gray_th_otsu)
plt.gray()
plt.show()

```
thに閾値、img_gray_th_otsuに2値化後の画素値が入ります。
cv2.thresholdの引数、threshにはいったん０を入れてます。これが大津法によって最適化されてthに入ると考えてます。Maxは255にしときました。maxの画素値を入れてもいいですが、そこまでする必要はないかなと思いました。

cv2.thresholdの定義

https://docs.opencv.org/3.4/d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57