OmniAICreator/Qiita-1.07M huggingface dataset:
ViewBindingをonViewCreated以外でも使う時とonViewCreatedでしか使わない時

#使い分けが必要
`ViewBinding`を`onViewCreated`以外でも使う時と`onViewCreated`でしか使わない時とでは書き方が異なる。できるだけ、変数のスコープが狭くしたいという意図がある。また、今回はFragmentの`onViewCreated`においての話であるが、Activityの`onCreate`に関しても同様である。

## onViewCreated以外でも使う時

```kotlin
private var _binding: FragmentHomeAllBinding? = null
private val binding
   get() = _binding!!

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   super.onViewCreated(view, savedInstanceState)

   _binding = FragmentHomeAllBinding.bind(view)
   binding.allRecyclerView.adapter = homeAllAdapter
   viewModel.renderData.observe(viewLifecycleOwner) {
       homeAllAdapter.update(it, viewModel)
   }
}

override fun onDestroyView() {
   super.onDestroyView()
   _binding = null
}

```

## onViewCreatedだけで使う時
```kotlin
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    val binding = FragmentHomeShoesBinding.bind(view)
}
```
onViewCreatedだけで使う場合は、上記のように、`onViewCreated`内でbidingを宣言してしまいます。
GitHub Actionsを使ってSwaggerをGitHub Pagesにホスティングする

OpenAPI形式で書かれたAPI仕様書は、SwaggerUIでGitHub Pagesにホスティングできます。
今回は、そのGitHub Pagesへのホスティングを**GitHub Actionsを使って簡単にデプロイする方法**をまとめます。

## ディレクトリ構成

```
.
├── .github
│   └── workflows
│       └── deploy-to-github-pages.yml
└── openapi.yml
```

## Workflow

```yaml:.github/workflows/deploy-to-github-pages.yml
name: Deploy to GitHub Pages

on:
  pull_request:
    branches:
      - main
    types:
      - opened
      - synchronize
      - closed
    paths:
      - openapi.yml
      - .github/workflows/deploy-to-github-pages.yml

jobs:
  deploy-to-github-pages:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Install swagger-cli
        run: |
          npm install -g swagger-cli

      - name: Validate Swagger Files
        run: |
          swagger-cli validate -d openapi.yaml --type yaml

      - name: Generate Swagger UI
        if: github.event.pull_request.merged == true
        uses: Legion2/swagger-ui-action@v1
        with:
          output: swagger-ui
          spec-file: openapi.yaml

      - name: Deploy to GitHub Pages
        if: github.event.pull_request.merged == true
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: swagger-ui
```

### Legion2/swagger-ui-action
OpenAPIファイルからSwaggerUIを生成する処理。

https://github.com/Legion2/swagger-ui-action

### peaceiris/actions-gh-pages
生成したSwaggerUIをGitHub Pagesにホスティングする処理。

https://github.com/peaceiris/actions-gh-pages

|Options|Description|
|-|-|
|github_token|`GITHUB_TOKEN`はGitHub Actions runnerで自動生成されるトークンであり、 Personal Access Tokenではない。`${{ secrets.GITHUB_TOKEN }}`を設定しておけば問題なし。|
|publish_dir|オプション名が紛らわしいが、sourceディレクトリを指定する。|
|destination_dir|今回はリポジトリ直下に配置しているが、destinationディレクトリを指定することもできる。|
|publish_branch|publishブランチの指定。デフォルトでは`gh-pages`ブランチにpublishする。|
|external_repository|他のリポジトリにデプロイすることもできる。その場合`deploy_key `もしくは`personal_token`で権限を設定する必要がある。|

### 実行条件
onで設定しているWorkflowの実行条件：
以下2つとも条件が合致したとき。

* mainブランチへのプルリクエストを作成・更新・マージしたとき
* `openapi.yml`か`deploy-to-github-pages.yml`に変更があるとき

ifで設定しているStepの実行条件：

* `Generate Swagger UI`と`Deploy to GitHub Pages`を実行するのはマージした時のみ

## GitHub Pagesの設定
今回の場合、ブランチは`gh-pages`、ディレクトリは`/(root)`で設定する。
設定の詳細方法は下記参照。

https://docs.github.com/ja/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#choosing-a-publishing-source

## GitHub Pagesの確認
GitHub Pagesの設定完了後、生成されたURLからホスティングされたSwaggerUIを確認することができる。
設定反映までに最大10分かかることがある模様。詳細は下記参照。

https://docs.github.com/ja/pages/getting-started-with-github-pages/creating-a-github-pages-site#creating-your-site

## 参考文献
https://qiita.com/shiozaki/items/05c282a1f208b1f756ae
Nuxtのlayoutの挙動に関してメモ

# いろいろ調べた結果

ssr側でエラーが発生しているだけだった。

エラー時にはdefaultテンプレートが呼ばれるっぽい。

（ちなみに）エラーの原因はcore.jsによるもの

↓↓

# 基本

１．すべてのページはレイアウトdefault.vueでロードされる。
２．ページのレイアウトを指定した場合は、指定したレイアウトで読み込まれる。
３．指定されたレイアウトが利用できない場合は、default.vueが読み込まれる。

# ポイント

１で思ったような挙動をしなくなった。
default.vueに処理を入れていた場合、ページのレイアウト指定前に呼び出されてしまう。
すべてのページで呼び出されると思っておらず自動遷移処理を入れていた。

結果
ページリロード → なぜかページ遷移
みたいなことが発生。

# 参考
https://stackoverflow.com/questions/58134718/how-disable-default-layout-on-other-page
30代前半の地方公務員がプログラミングなどを学んでみた【はじめに】

# はじめに（自己紹介）

こんにちは！初めての投稿になります。
現在、年齢３０代前半で地方公務員（技術系「化学」というちょっと珍しい職種です。）をしています。
仕事の内容は環境系（水質や大気などの公害関係）の部署で企画・調整的なことをメインにやっています。

【略歴】
大学〜大学院：工学部の化学・生物系の修士課程修了
１社目：産業ガスメーカー（2年弱）
２社目：技術系公務員（現在5年目）

大学・大学院時代は「バイオセンシング」という分野の研究室に所属していて、電気化学や分析化学、MEMS技術みたいなナノテクノロジーを活用して、細胞みたいなウェットな物を「測る」ことをメインに研究していました。

大学院終了後は内定をいただけたということと、医療や農業など成長分野に裾野を広げていて、キャリアの中で色々な分野を経験できる可能性があるなと考え、大手産業ガスメーカーに入社しました。この会社では、大学の専門とは大きく違う分野（化学工学）のエンジアリングを担当し、ガス製造プラントのプロジェクトエンジニアリングから、実際の設計、試運転など幅広くやらせてもらいました。

もともと地元で学んだ技術を生かした仕事ができたらいいなということをぼやっと思っていて、公務員試験を受けてみたら、奇跡的に受かったため、転職を決意し、環境行政に携わりながら現在5年目という感じです。

# なぜ書いたか
目的は１つです！
#### プログラミング含むIT分野の「学習記録」をアウトプットし、スキルアップする！

公務員はとても安定した職業です。
新型コロナウイルス感染症が流行し、打撃を受けた業種では、ボーナスを削られた民間企業もあったと思います。ですが、公務員の給与にはほとんど影響がありませんでした。（民間企業の平均値を採用しているので少しだけボーナスは減りましたが…）

ですが、私自身のプライベートの環境変化や今後の仕事に対する価値観の変化から、新たなスキルを身につけて、あわよくば転職したいと思うようになりました。

私は新しいテクノロジーが大好きで、仕事でも積極的に取り入れたいと思っています。
特に今後はIT関連の技術（Webやプログラミング）の基礎や実装方法を知っておくことはプラスであることは間違い無いので、その記録としてQiitaも使っていこうと思います。

# どんなことを勉強するか
現在進行形で以下の技術を勉強しています。

#### Ruby on RailsによるWebアプリケーションやWeb技術全般
これまでProgateやドットインストールのサービスを利用して、HTMLやCSSの基礎、　JavaScript基礎、Ruby基礎をざっと勉強し、2021年12月末から「Railsチュートリアル」に手をつけました。

「Railsチュートリアル」は、解説動画も購入して、年末年始休暇＋αくらいで、ようやくSampleAppが完成しました。
ただ、テキストコードのコピペで完成させた感が否めなく、中身をほとんど理解できていないため、その後、ProgateのRails講座をひと通りやりました。（←イマココ）
今後は自分オリジナルのWebアプリ開発を行いたいため、QiitaやTwitterでアウトプットしながら作業記録をつけていきたいと思います。

#### IoT（RaspberryPi+センサー用いたセンシング）



構想段階ですが、センサー+ラズパイで取得したデータをAWSなどのクラウド上に構築したWebアプリケーション（データベースと連携させる）に転送し、さらに他のAPIなどと組み合わせて、センシングデータを活用したWebアプリ開発ができればいいなと思っています。

# 参考文献
記事のフォーマットを参考にさせていただきました。ありがとうございます。

[Qiitaで簡単に記事を書くためのフォーマット](https://qiita.com/kenseitogari1/items/1dcf4328d54e9f2c087c)

# 最後に


最後まで読んでいただきありがとうございます！今後ともよろしくお願いいたします。
（ちょっとお堅い文書感が抜けきれないので、次からはもっとフランクにしたいと思います笑）
【Salesforce】リストビューで選択したレコードを一括削除

欲しいのになぜかない一括削除ボタン。
１つ１つポチポチと消したくないので実装してみました。

#Classicの時と同じ手法が使えるか
一括削除を実行するためのカスタムボタンの作成：https://help.salesforce.com/apex/HTViewHelpDoc?id=sf.links_useful_custom_buttons_mass_delete.htm&language=ja

ClassicではJavaScriptカスタムボタンを作成して一括削除することができたみたいですが、残念ながらLightningには対応していませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/ac6fa14b-083c-a9fb-387c-301a8f308591.png)

念の為作成してリストビューに配置してみましたが、Classicでは表示されるもののLightningではボタン自体が表示されませんでした。

#「Mass Delete」を利用する
Mass Delete：https://appexchange.salesforce.com/appxListingDetail?listingId=a0N300000016YuDEAU

同名の古いアプリもあるので注意してください。

インストールすると下記のOBJに削除ボタン（Mass Delete）が作成されます。

- リード
- 商談
- 契約
- 商品
- ソリューション
- 納入商品
- キャンペーン
- 取引先
- 取引先責任者
- ケース

あとはボタンを配置すれば使用可能です。
削除したいレコードを選択してMass Deleteボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/bed70f47-aaca-4756-1c37-7ca446d4304d.png)
VFの確認画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/1a4a16ed-c4fd-cbc7-80af-220dc43cf94d.png)
削除ボタンを押すと選択したレコードが削除されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/a036bc7d-ef4f-2b12-d54f-f758cbf42ffa.png)

#「Mass Delete」のカスタマイズ
とはいえこのままだと上記の標準OBJしか使えず、ボタンや確認画面の表記も英語のままなので修正します。
未管理パッケージをイジることになるので気をつけてください。

##「Mass Delete」の中身
[インストール済みパッケージ]-[Lightning Mass Delete]-[コンポーネントを表示]から中身を確認できます。
これを基に追加・編集します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/536a34d5-d4be-dd4a-4b62-a64cbe702beb.png)

##Visualforceの作成＆日本語化
中身をコピーして編集してください。
特にこだわりがなければstandardControllerや文言の修正だけでOKです。

##ボタンの作成
中身のボタンを参考に作成してください。

##カスタムOBJで動作確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/a9a081ca-2055-7646-b11d-01514e93613c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/89ce93d2-8590-f16d-ceef-f077f6dee2a8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/d6f6c5cf-831f-33d0-4904-1b35d8de52bd.png)
削除＆日本語化がカスタムOBJでできました。

#まとめ
一部VFの作成や編集が必要なものの、簡単な変更なのでコードを書いたことがない方でも一括削除を実装できそうですね。

今回の方法以外にVFからフローに値を渡して処理するなどもできるので、そっちで実装するのもありだと思います。
NoSQL DB（特にfirestore）とRDBの違いをざっくり理解


### 動機
NoSQLの定義って？　RDBとの違いは？　ってところがわかってなかったので、ざっくり理解レベルですが調べたのでまとめてみました。

##RDB

レコード（行）とフィールド（列）でできたテーブルと呼ばれる表にデータを格納する。テーブルの各行はテーブル内で一意なキーを持っており、このキーと外部キーの関係を設定することで新しいテーブルを作ることができる。
CAP定理（Consistancy：一貫性、Availability：可用性、Partition tolerance：分断体制　の3つを同時に満たす分散システムは存在しない）のなかのCとAを保証する。Pは保証されていない。つまりデータは単一のサーバー内にある。

メリット：一貫性が保証されている。複雑なクエリを書ける
デメリット：大規模データになると処理が遅くなる事がある

__CAP定理__
![CAP定理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495868/471edcd7-7945-c52d-203d-78d7939788dc.png)

参考
https://www.teracloud.co.jp/special_cap-theorem.html
https://tech-blog.rakus.co.jp/entry/20180919/nosql/bigdata
https://www.geekly.co.jp/column/cat-technology/1904_005/


## NoSQL DB

No only SQLの略でSQL以外の技術を使ったDBのこと。キーバリュー型、カラム思考型、ドキュメント指向型などがある。
CAP定理のうち、Pを重視している。つまり、データを複数サーバーに分散して保管でき、1つのサーバーに障害があっても別のサーバーからデータを参照できることを重視する。これにより、1つのサーバーでは収容できない膨大なデータを扱うことができるなどのメリットが有る。

メリット：複数のサーバーに処理を水平分散できるため処理が早い。拡張しやすい。
デメリット：一貫性が保証されていない。複雑なクエリは書けない。

__firestoreはドキュメント指向のデータベース__
> Cloud Firestore は NoSQL ドキュメント指向データベースです。SQL データベースとは違い、テーブルや行はありません。代わりに、データは「ドキュメント」に格納し、それが「コレクション」にまとめられます。


参考
https://firebase.google.com/docs/firestore/data-model?hl=ja
Sleep性能評価(C++)

# 概要
Sleep関数は現スレッドに対して処理を一定時間停止させる機能である．Sleep関数に停止時間を設定して処理を止める．

Sleep関数には停止時間に誤差が発生していることもある．
そこで，C++のSleep関数のSleep時間を設定したとき，実際の停止時間の誤差がどのくらいあるのか評価してみた．

# 測定
C++で提供されている代表的なSleep関数に対して精度を評価した．
評価方法は，1ミリ秒の停止(Sleep)を2000回実行したときの平均時間を算出して精度の評価を行った．
実行時間測定はchrono::steady_clockを使用した．

**使用プログラム**


https://github.com/Ocean00000/SleepEvaluation


## Windows
WindowsのVisual Studio 2020 communityを用いて2種類のSleep関数に対して性能評価を行った．

Sleep関数|結果|備考
---|---|---
std::this_thread::sleep_for|15.559ミリ秒|
Sleep|15.573ミリ秒|
std::this_thread::sleep_for|2.010ミリ秒|timeBeginPeriod(1)を使用
Sleep|2.015ミリ秒|timeBeginPeriod(1)を使用

* 開発環境：
    * Visual Studio 2022 community
* PCスペック：
    * OS:Windows10 Pro(64bit)
    * CPU:Intel(R)Core(TM) i9-109000X 3.70GHz(物理コア数：10, 論理コア数：20)
    * メインメモリ:128GB

# 参考資料
1. cpprefjp - C++日本語リファレンス, https://cpprefjp.github.io
1. 性能評価プログラム, https://github.com/Ocean00000/SleepEvaluation
簡単なDAppを作ってみる 開発環境構築編

前回は簡単なDappを作ってみようということで、どのようなDAppを作るか考えました。
今回は作成するDAppを開発するための環境を作っていきたいと思います。

# 目次
(全て書き終わったら作成)

# 私の環境
OS: Windows 10 64bit
CPU: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz
RAM: 32.0 GB
ブラウザ: Google Chrome

# イーサリアムクライアント
自分のマシン上でイーサリアムノードを実行できるソフトウェアを指します。
まずは、このソフトウェアをインストールする必要があります。
イーサリアムクライアントにもGethやErigon, Besuなどいろいろ種類があるようです。
その中で今回は**[Geth](https://geth.ethereum.org/)**を使用します。
GethはGo Ethereumの略です。Go言語で作られ、現在最も多くのユーザがおり、ユーザや開発者向けのツールも豊富です。

[公式ページのDownloads](https://geth.ethereum.org/downloads/)で「Geth 1.10.15 for Windows」を選択し、インストーラ(2022/01/30現在のバージョンは1.10.15)をダウンロードし、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2499481/a5551fab-3f5e-c17f-5f48-e084d5dff0b5.png)
インストールが完了すれば、インストールパスにGeth.exeがあるので、環境変数PATHにインストールパスを加えてください。そうすれば、PowerShellなどのコンソールからGethコマンドを使用できるようになります。

# MetaMask
MetaMaskは人気のある仮想通貨ウォレットの一つです。
ウォレットがあればユーザがイーサリアムクライアントを実行しなくても、アプリケーションを利用することができます。
MetaMaskはChrome, Firefox, Opera, Braveで利用可能です。
以下から、ダウンロード/インストールができます。
https://metamask.io/
私はChromeを使用しているので、ChromeのMetaMask拡張機能をインストールしました。

# Node.js
DAppを作る際にJavaScriptの実行環境であるNode.jsを使用します。
以下にアクセスし推奨版(2022/01/30現在のバージョンは16.13.2LTS)をダウンロード/インストールします。
https://nodejs.org/ja/

# Truffle Suite(トリュフ スイート)
イーサリアムの開発用フレームワーク(?)です。Truffle Suiteの一部であるTruffleとGanacheをこれからインストールしていきます。
## Truffle
TruffleはDapp開発環境を提供してくれます。スマートコントラクトのコンパイルやテスト、デプロイなどを行ってくれます。
Truffleのグローバルインストールは以下のコマンドを実行します。

```powershell
$npm install -g truffle
```

バージョンも確認しておきます。

```powershell
$truffle version
Truffle v5.4.31 (core: 5.4.31)
Solidity - 0.8.11 (solc-js)
Node v16.13.2
Web3.js v1.5.3
```

Truffle以外にもSolidityやWeb3.jsなど、Dapp開発に必要なライブラリがインストールされていることがわかります。

## Ganache(ガナッシュ)
Ganacheはパーソナルブロックチェーンを実現するソフトウェアです。Ganacheを使うことで、パーソナルブロックチェーン上で迅速にDappの開発、テスト、デプロイができます。
以下からGanacheをダウンロード/インストールします。
https://trufflesuite.com/ganache/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2499481/5ef2d7b1-23fe-8c07-b227-5aad1722b69b.png)

# まとめ
Dapp開発環境構築のために以下をダウンロード/インストールしました。
色々インストールしたので、何がどのような役割なのか理解する必要があります。

* イーサリアムクライアント(Geth)  
イーサリアムノードを実行するためのソフトウェア。
* MetaMask  
仮想通貨ウォレット
* Node.js  
JavaScript実行環境
* Truffle Suite(Truffle, Ganache)  
TruffleはDapp開発環境で、Ganacheはパーソナルブロックチェーンを実現するソフトウェア

次回はDappのHello, Worldを作成する予定です。
Atmel製CPUのボード上で開発を行う

# 概要
Atmelと印字されているCPUが載った評価ボードを使う話。ターゲットボードは諸事情でぼかしておく。

## 開発環境
さすがにIDEがあるはずと探したら、Microchip Studioが出てきた。当初はAtmel Studioかと思っていたが、買収の関係で統合されている（されつつある？）とのことなので、Microchip Studioを使うことにする。

https://www.microchip.com/en-us/tools-resources/develop/microchip-studio

ページの下の方にあるリンクからインストーラーを取得してインストールする。途中でいくつか選択肢が出たが、全部入りで問題ないと思う。

## バイナリの書き込み
ターゲットボードにサンプルアプリが付属していて、バイナリもあったので書き込んでみることにした。
書き込みツールはTool > Device Programmingにあった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/13409b32-486c-c181-0eda-5f5f9e60c86e.png)
DeviceのCPUを選択し、SWDを選択（JTAGは使わずターゲットボードのEDBGを使った）、Applyを押すと下の段に色々と表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/6534bbee-8701-f8db-8eed-b726b6e44226.png)
Memoriesを選択すると、ファイル選択ができるようになるので、サンプルのバイナリのパスが表示されるようにする。その後、「Program」を押せば書き込みができる。

## 動作確認
UARTがあるボードだったので、UARTログをみたらInitializeとかそれっぽいものが表示されたので成功したようだ。

# プロジェクト作成
当然ながら、実際は自分の書いたコードを動作させなければならない。そこで、開発用のプロジェクト作成を試す。Atmel製CPU用とおぼしき「Atmel Start Project」があったので使うことにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/5f0afe4e-d73c-440b-74c9-33cbc3801a27.png)

CPUはAtmelのATSAMG55J19だったので、途中まで入れると候補に出てきた。Packageの違いで2種類表示されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/626943c2-9be8-49a2-fa89-a0a6a38990a8.png)

左側の「MIDDLEWARE」や「DRIVERS」で必要な機能の数を選択する。DRIVERSで存在しない数の機能を選択したらRESULTSからCPU一覧が消えたので、ありえない機能選択はできないようだ。
CPUを選択したら右下の「CREATE NEW PROJECT」を押してプロジェクト作成を行う。

### 設定内容の確認と確定
組み込んだ機能が図で表示されていてわかりやすい。左側のCLOCKSやPINMUXでクロックの分周状態や各ピンへの機能割り当ての状況が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/d9ecd504-795f-cc7e-3144-969620628ca6.png)
最後に「GENERATE PROJECT」でプロジェクト作成を完了する。

## ソースコード
プロジェクトの中にはmain.cができていて、基本的な初期化処理は行われている模様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/a3af5600-8969-a116-0668-afc988e3360b.png)

# 今後の予定
SPIとUARTを使って目的の処理を行えるように設定見直しやコード作成を行う。
Chartsのライブラリコンパイルエラー

# はじめに
Chartsを使うにあたってぶち当たったエラーの備忘録

![スクリーンショット 2022-01-30 16.18.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/429627ab-335f-5dde-46fb-787b8af8471b.png)

# 手順
## 1. ライブラリを一回消す
![スクリーンショット 2022-01-30 16.19.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/5f2a59db-2dbd-7a0a-e778-d64ecc2e133e.png)
-ボタンを押してライブラリを一回消す。

## 2. ライブラリを入れ直す
https://github.com/apple/swift-algorithms
https://github.com/danielgindi/Charts
この二つのライブラリをこの順番で入れる。
![スクリーンショット 2022-01-30 16.20.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/fdf5e5bc-43bb-e79e-58e4-f9400a3be2cd.png)
![スクリーンショット 2022-01-30 16.21.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/34d73b40-80d9-6bd3-35c2-166c3c6814dc.png)

## 3. ライブラリのバージョンを変更する
数字のところダブルクリックでバージョンの変更ができるので、**Charts**のバージョンを**3.0.0**に落とす。
![スクリーンショット 2022-01-30 16.22.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502701/2cda40b9-5e14-811f-c498-8c10cbadbc19.png)

# 原因
4.0.0にはタイピングミスが残ってる。（制作者は直したって言ってるんだけどなぁ...）
Teams会議で、主催者以外でもbreakout roomの管理ができるようにする

# はじめに
TeamsのBreakout room機能について、リリース当初は以下のような制約があったため、利用を躊躇われた方が一定数いらっしゃるように思われる。

- 主催者しかブレイクアウトルームの管理機能を利用できない
- 会議開始前にあらかじめブレイクアウトルームの割り振り作業を完了させることができない
 

実は、現在はこれらの制約がなくなっている。
しかしながら、1点目について、意外と知名度が高くないように思われるので、具体的な手順をシェアする。

 

# 手順
※Teamsの言語設定を英語にしています。日本語にしている方は適宜読み替えてください。

1. 対象となる会議をteamsカレンダー上で選択後、Breakout roomsをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684495/f357b787-dceb-efef-cfaf-08c6dee9efcc.png)

2. Create roomsをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684495/d281aee1-cf25-9f66-5fc9-012be4367f5e.png)

2. 右のほうにある歯車アイコンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684495/a85b4aa1-e4e2-15be-52d1-1b072d75aa09.png)

2. Assign presenters to manage roomsをクリックし、管理権限を与えたい人のメールアドレスを入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684495/05ffe2d0-3468-92e6-50dd-7b60f83b2f6c.png)
強化学習で作成した学習モデルを、別のPC環境で実行しようとしたときにエラー（`RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False...`）

強化学習で作成した学習モデルを、別のPC環境で実行しようとしたときにエラー（`RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False...`）

```
$ python do.py
...
RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device('cpu') to map your storages to the CPU.
...
```

エラーメッセージ記載の通り、
`please use torch.load with map_location=torch.device('cpu') `すればOK

before

```
def torch_load(file_name):
    with open(file_name, 'rb') as f:
        return torch.load(f)
```

after

```
def torch_load(file_name):
    with open(file_name, 'rb') as f:
        return torch.load(f, torch.device('cpu')) 
```

CPU環境なので性能は落ちるかもしれないが、これでひとまず動くので評価はできそう。

# 参考

https://teratail.com/questions/243283
プリンタ ジョブの直接削除

https://itojisan.xyz/trouble/26108/

##スプーラーファイルを直接削除する
>・「Windowsマーク」を右クリックして「ファイル名を指定して実行する」を選択
・「services.msc」と入力して「OK」をクリック
・サービスウィンドウが開いたら、サービスの一覧から「Print Spooler」を右クリックして「停止」を選択
・サービスウィンドウをそのままにした状態で、「Windows + E」キーを入力してエクスプローラーを起動
・アドレスバーに「%windir%\System32\spool\PRINTERS」と入力してEnterキー
・アクセス許可を求められた場合は「続行」
・「PRINTERS」フォルダが開いたら、フォルダ内の全てのスプーラーファイルを選択して右クリックし「削除」
・サービスウィンドウに戻って、サービスの一覧から「Print Spooler」を右クリックして「開始」を選択
Ubuntuでディレクトリが削除できなかったときの対処法

##1.経緯
Ubunu上で、git cloneでリポジトリを複製し、その中にコンテナを作成して作業をしようとしたところエラーが発生し、そのエラーを解決することができなかったため一度作業していたディレクトリごと削除しようとしました。

##2.エラーを解決する
まず、稼働しているコンテナを停止し、コンテナやイメージを削除しました。ここまではよかったのですが、その後GUI操作での削除やrmコマンドなどで削除しようとするとなぜか削除できませんでした。なので、いったんエラーを見ながら削除できなかった原因を探ることにしました。

```:エラーが発生したコマンド
$ rmdir -r [ディレクトリ名]
```

```:発生したエラー
rmdir: invalid option -- 'r'
Try 'rmdir --help' for more information.
```

このエラーを直訳すると
rmdir：無効なオプション-'r '
詳細については、「rmdir--help」を試してください。
となります。この文章では原因がよくわからなかったので発生したエラーで検索をして調べてみると、似たようなケースに陥った方がエラーを解決したコードには「sudo」がついているので、エラーの原因は権限がないコマンドを実行しようとしたことにあるのではと予想し、

```
$ sudo rm -r [ディレクトリ名]
```

を実行したところ削除することができました。しかし、ディレクトリの中には上記のコマンドでも削除できないものもありました。そこで、もう一度調べなおしてみたところ、削除できないディレクトリに移動してその場所で

```
$ rm -r ./*
```

を実行したところ、ディレクトリ内のファイルなどが削除されたことが確認できたため、伊階層上のディレクトリに戻り、もう一度「sudo rm -r [ディレクトリ名]」を実行すると今度は削除することができました。

##3.まとめ
同じディレクトリでも削除するために権限が必要だったり、先に中身をある程度削除しなければならないといったことがあるということを学びました。

##4.参考
参考:[【Ubuntu】ディレクトリを中身ごと削除する方法](https://qiita.com/udonkoneko55/items/110e541cf634a2bb0668)
【Hyperledger Fabric v2.4.1】動作環境の構築②

# 目的
仮想ソフトウェア（VirtualBox）を使用して、Linux ゲスト OS（Ubuntu）を導入し、その上に Hyperledger Fabric v2.4.1（執筆時の最新） の動作環境を構築します。
本ページでは、Hyperledger Fabric v2.4.1 のインストールに必要な準備までを記載しています。


# インストールするソフトウェア

* Hyperledger Fabric v2.4.1
* Hyperledger Fabric CA v1.5.2


# 作業ステップ
本ページでは、太字のステップのみ記載しています。

* ステップ①：Ubuntu Linux ゲストOSのインストールと初期設定
* ステップ②：必要なツールおよびソフトウェアのインストール
* **ステップ③：Hyperledger Fabric のインストール**


# インストール前の準備（ステップ①②）
以下を参照してください。

https://qiita.com/kbys7367/items/df6d8cb3b7d2b33aebfd

# ステップ③：Hyperledger Fabric のインストール

公式サイトの手順（ https://hyperledger-fabric.readthedocs.io/en/release-2.2/install.html ）に従って、インストール用のスクリプトをダウンロードして、実行します。

### インストール用のスクリプトの実行
```
~$ mkdir fabric
~$ cd fabric/
~/fabric$ curl -sSL https://bit.ly/2ysbOFE | bash -s

Clone hyperledger/fabric-samples repo
（中略）
hyperledger/fabric-ca        1.5.2     4ea287b75c63   4 months ago   69.8MB
hyperledger/fabric-ca        latest    4ea287b75c63   4 months ago   69.8MB
```

### コマンドの実行パスの設定
```
~/fabric$ ls $HOME/fabric/fabric-samples/bin
configtxgen    cryptogen  fabric-ca-client  ledgerutil  osnadmin
configtxlator  discover   fabric-ca-server  orderer     peer
~/fabric$ echo 'export PATH=$PATH:$HOME/fabric/fabric-samples/bin' >> ~/.profile
~/fabric$ . ~/.profile
```

### Docker イメージの登録確認
「docker images」コマンドで、インストールした Docker コンテナを確認します。

```
~/fabric$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
REPOSITORY                   TAG       SIZE
hyperledger/fabric-tools     2.4       458MB
hyperledger/fabric-tools     2.4.1     458MB
hyperledger/fabric-tools     latest    458MB
hyperledger/fabric-peer      2.4       63.3MB
hyperledger/fabric-peer      2.4.1     63.3MB
hyperledger/fabric-peer      latest    63.3MB
hyperledger/fabric-orderer   2.4       37.2MB
hyperledger/fabric-orderer   2.4.1     37.2MB
hyperledger/fabric-orderer   latest    37.2MB
hyperledger/fabric-ccenv     2.4       504MB
hyperledger/fabric-ccenv     2.4.1     504MB
hyperledger/fabric-ccenv     latest    504MB
hyperledger/fabric-baseos    2.4       6.94MB
hyperledger/fabric-baseos    2.4.1     6.94MB
hyperledger/fabric-baseos    latest    6.94MB
hyperledger/fabric-ca        1.5       69.8MB
hyperledger/fabric-ca        1.5.2     69.8MB
hyperledger/fabric-ca        latest    69.8MB
```
Clound Functionsで特定のAndroidアプリのみ許可する

# はじめに
こんにちは。Androidエンジニアのgottieです。
個人開発でCloud Functions(GCP)を使ってみたのですが、APIのアクセス制限の方法が少しやっかいだったため記事にしておきます。

# やりたいこと
特定のAndroidアプリからからのみ、GCPのAPI呼び出しを行えるようにしたいです。


# やったこと

**1 APIキーの作成**

GCPの「APIとサービス」から「認証情報」>「認証情報を作成」>「APIキー」を選択します。

| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2130833/d5f5c94a-5449-8dc9-7e4f-56afc54a7d5b.png)|
|:--|


作成したAPIキーの詳細に移動すると以下の画面が表示されます。


| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2130833/9ceb9088-5113-f0df-eeac-f20c43fb6105.png)|
|:--|


**2. アプリケーションを制限する(ここ重要)**

このステップで特定のAndroidアプリからのみ呼び出すことができるようにします。ラジオボタンの「Androidアプリ」を選択して、使用するアプリのパッケージ名とSHA-1証明書のフィンガープリントを入力します。

| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2130833/84f5d0c7-dfa8-5441-ca1c-3e5356ff1352.png)|
|:--|


画面右側に各OSでフィンガープリントを出力するコマンドが出ていますがここに罠があります。
試しに以下のコマンドを入力とその結果です。(結果は桁数以外は適当です。)

```
keytool -list -v -keystore debug.keystore -alias androiddebugkey -storepass android -keypass android

MD5:  33:01:38:7E:90:0A:C9:64:41:C8:B5:BE:CE:24:D2:D8:2D:2B:EE:41
SHA1: AB:CD:12:34:56:78:EF:F8:B9:C0:C5:8B:B0:E2:54:21:39:A3:73:BD:9B:62:87:4A:A9:D5:A2:5D:0D:6D:21:4D
SHA256: SHA256withRSA
```

このSHA1の結果をそのまま入力すると、`SHA-1 署名証明書フィンガープリントが無効です`と赤文字で表示されます。
実はこれ`keytool`のバグっぽくて[こちら](https://zenn.dev/kingu/articles/1fbf139dba004d)にも記載がありますが、MD5の場所にSHA-1が、SHA-1の場所にSHA-256が記載されているのかなと思われます。なのでGCP側のSHA-1の入力欄にはkeytoolで表示したMD5の方を入力しましょう。

まぁよく考えればSHA1は160bitなので桁数的におかしいですね。(いや、気づかねーよ！)
(SHA-256は256bitなのでSHA-1に表示されているものと一致しますね。)




**3.APIの制限**

こちらは今回の記事とは直接関係ないですが、設定しておいた方が良いと思われます。

| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2130833/e7c5c6a8-c171-e926-dec4-ea606167c42b.png)|
|:--|


**4.Androidからリクエストを投げる。**
ここまででGCP側の設定は終了です。GCP側はAndroidアプリの〇〇からのリクエストは許可するよ～っていう状態なので、Android側はリクエストの際、自分は〇〇っていうアプリだよってことを教えてあげないといけません。今回はOkHttpを使用します。
リクエストヘッダーに`X-Android-Package`と`X-Android-Cert`を追加し、それぞれパッケージ名とSHA-1を入れてあげればよいです。パッケージ名や署名のSHA-1の取得方法はいくつかあるようですが、[こちら](https://stackoverflow.com/questions/31589308/how-does-google-verify-android-sha1-fingerprints-and-packages)を参考にしました。
ちなみにsha1のフィンガープリントを入力する際はコロンは不要のようです。

```kotlin
val request = Request.Builer().apply { 
    url(YOUR_GCP_URL_WITH_API_KEY)
    addHeader("X-Android-Package", packageName)
    addHeader("X-Android-Cert", cert)
}.build()

val response = OkHttpClient().newCall(request).execute()
```

これで無事GCPのAPIを安全に特定のAndroidアプリからのみ呼び出せるようになりました！


# おわりに

パッケージ名とSHA-1をリクエストヘッダーに入れるのだろうな~と思ってはいたのですが、なかなかこの情報を見つけることができなくて、少し苦労しました。(GCPの公式に`X-Android-Package`や`X-Android-Cert`の情報あります？)
今回は触れなかったですが、もしかして、OAuthを使ったりするのかな？
とりあえずGCPの呼び出しをうまく制限できたのでやりたいことはできたということで以上です。ではまた。


# 参考

[API キーの使用 ](https://cloud.google.com/docs/authentication/api-keys?hl=JA&visit_id=637791198987232681-735317436&rd=1)
[keytoolの翻訳バグに遭遇した話](https://zenn.dev/kingu/articles/1fbf139dba004d)
[How does google verify Android SHA1 fingerprints and packages?](https://stackoverflow.com/questions/31589308/how-does-google-verify-android-sha1-fingerprints-and-packages)
[5分でわかるSSL通信　SHA-1、SHA-2の違いとは？](https://geechs-job.com/tips/details/37)
vistaでphotoshop その8

#概要

vistaでphotoshopやってみる。
キャンバス作って、jpg読んで、リサイズして、移動して、pngで出力やってみる。

#写真

![test7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a9a414f7-044a-0360-9b93-7747bddd5e3e.png)


#サンプルコード

```
preferences.rulerUnits = Units.PIXELS;
var docObj = app.documents.add(640, 480);
var fileObj = new File("/Users/ore/eki.jpg");
open(fileObj);
activeDocument.selection.selectAll();
activeDocument.activeLayer.copy();
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
docObj.paste();
activeDocument.activeLayer.resize(50, 50);
activeDocument.activeLayer.translate(-160, -120);
var pngOpt = new ExportOptionsSaveForWeb();
pngOpt.format = SaveDocumentType.PNG;
pngOpt.optimized = true;
pngOpt.interlaced = false;
pngOpt.PNG8 = false;
var filePath = new File("/Users/ore/test7.png");
app.activeDocument.exportDocument(filePath, ExportType.SAVEFORWEB, pngOpt);
alert("ok");



```


以上。
Wordpress SearchRegexの代わりに

WordpressプラグインであるSearchRegexが新バージョンで使えない状態でした。
それで、WEBサーバ上にphpファイルを上げて利用できるものとかもありましたが、公開済みのサイトだったり、
変更される内容を一応確認はしてみたいと思っていて、必要なものをWindowsプログラムとして、作ってみました。
急いで必要だったため、簡単に作り、よろしくは無いです。
今後余裕が有ったり、仕事で、追加する場合が有ったら、それに応じて、更新するかも知らないですが計画などは無いです。

ソースコード：
https://github.com/heedaily/SearchRegex
.net 5 なし
https://drive.google.com/file/d/1J5JIIhMDV1xCMVWTCq0mFgoJA4i18W_d/view?usp=sharing
.net 5 含め
https://drive.google.com/file/d/1ijMde7rioVB4qILK8kG0PgUJjcesFM3m/view?usp=sharing


利用に当たって重要ファイルはconfig.jsonとSearchRegex.exeです。

主ファイル：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/96bb7b49-f65e-3741-f4f6-cdd479695ab6.png)

１．config.jsonをメモ帳などから開いて、MySQLコネクション情報を入れてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/ea739159-a832-63b9-9084-455f48c0f8b5.png)

２．SearchRegex.exeをダブルクリックしてプログラムを実行してください。
もし、実行ができない場合や操作ができない場合はsetup.exeをダブルクリックして、インストールを行ってください。

３．URLタイプの変更で、ファイル名は残して、上のパスのみを正規表現にて探して、変更したい場合は「Type」から「LeaveFileName」を選択してください。一般的に正規表現で探した内容の入れ替えをしたい場合は「Type」から「Nomal」を選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/51ccef3d-2c19-2777-215e-60edbf4e4b47.png)

<各項目の説明>
・DB Connection：config.jsonに書かれていたコネクション情報の確認や実行時のみの変更が可能です。変更した場合は、「View」を押下することにより、変更された内容が適応されます。
・Table：対象のテーブル名
・KeyColumn：該当テーブルのキーカラムです。更新時に使われます。このバージョンでは、一つのみ指定が可能です。
・ValueColumn：該当テーブルから正規表現から探して変更対象になる値をもっているカラム名です。このバージョンでは、一つのみ指定が可能です。
・Where：取得対象を絞るWhere句を記載してください。指定をしない場合は、「1 = 1」を入れてください。
・Regex：対象にする文字を探す正規表現です。
・AfterUrl又はAfterText：変更される文字列です。「LeaveFileName」を選択した場合は、ファイル名は入れ替えません。
・テーブル
　Key：該当テーブルのキー値
　Context：対象カラムの値
　ChangeContext：正規表現から検索された値
　ChangeAfterContext：正規表現から検索された値を変換した値
　AfterContext：正規表現から変換され、更新される実の値（修正可）

４．各テキストボックスへ該当内容を入れてください。
５．「View」ボタンを押下して、正しくデータが取得されるかを確認してください。
６．「Change」ボタンを押下して、正規表現から正しく欲しい内容が取得されるか、正しく変換されたかを確認してください。
７．追加修正がやりたい場合は、該当行のAfterContextを修正してください。
８．確認が終わったら、「Save」ボタンを押下して、更新してください。
変換対象の内容が存在しない場合は、更新されません。
行ごとのコミットを行っているので、エラーが発生しても、その前の内容はロールバックされません。
９．明示的にテーブル内容をなくすためには「Clear」ボタンを押下してください。
vistaでphotoshop その7

#概要

vistaでphotoshopやってみる。
キャンバス作って、jpg読んで、リサイズして、pngで出力やってみる。

#写真

![test6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/03d63749-ff12-6508-2573-8c49e1e3acc4.png)


#サンプルコード

```
preferences.rulerUnits = Units.PIXELS;
var docObj = app.documents.add(640, 480);
var fileObj = new File("/Users/ore/eki.jpg");
open(fileObj);
activeDocument.selection.selectAll();
activeDocument.activeLayer.copy();
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
docObj.paste();
activeDocument.activeLayer.resize(50, 50);
var pngOpt = new ExportOptionsSaveForWeb();
pngOpt.format = SaveDocumentType.PNG;
pngOpt.optimized = true;
pngOpt.interlaced = false;
pngOpt.PNG8 = false;
var filePath = new File("/Users/ore/test6.png");
app.activeDocument.exportDocument(filePath, ExportType.SAVEFORWEB, pngOpt);
alert("ok");



```


以上。
vistaでphotoshop その6

#概要

vistaでphotoshopやってみる。
キャンバス作って、jpg読んで、pngで出力やってみる。

#写真

![test5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b00a65d4-85e1-96ef-b2e6-5a1d07357ac7.png)


#サンプルコード

```
preferences.rulerUnits = Units.PIXELS;
var docObj = app.documents.add(640, 480);
var fileObj = new File("/Users/ore/eki.jpg");
open(fileObj);
activeDocument.selection.selectAll();
activeDocument.activeLayer.copy();
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
docObj.paste();
var pngOpt = new ExportOptionsSaveForWeb();
pngOpt.format = SaveDocumentType.PNG;
pngOpt.optimized = true;
pngOpt.interlaced = false;
pngOpt.PNG8 = false;
var filePath = new File("/Users/ore/test5.png");
app.activeDocument.exportDocument(filePath, ExportType.SAVEFORWEB, pngOpt);
alert("ok");



```


以上。
Purviewと連携したメタデータ駆動パイプラインを開発してみる

## はじめに

Azureデータ基盤のベストプラクティスの一つに[自動インジェスト フレームワークが Azure でのデータ管理と分析のシナリオをサポートする方法](https://docs.microsoft.com/ja-jp/azure/cloud-adoption-framework/scenarios/data-management/best-practices/automated-ingestion-pattern)があります。

関連して、
「[データのコピー ツール (プレビュー) でメタデータ駆動型の方法を使用して大規模なデータ コピー パイプラインを作成する](https://docs.microsoft.com/ja-jp/azure/data-factory/copy-data-tool-metadata-driven)」を利用して、メタデータ駆動のデータ取り込みパイプラインの開発が可能ですが、これをPurviewと連携してみようと思います。

## ハンズオンリポジトリ

![2022-01-30-14-31-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/180b5111-a562-f196-c34d-589689a0ed7e.png)


https://github.com/ryoma-nagata/purview-data-catalog-driven-ingest


## Purviewのメタデータ取得パイプライン内容解説

![2022-01-30-15-19-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a6aac262-0f31-0b68-9ee6-5c1bf665e6b3.png)

### Delete Metadata

取り込みを実行するパイプライン名をキーにして制御テーブル内のレコードを削除します。

コード：
[usp_delete_metadata.sql](https://github.com/ryoma-nagata/purview-data-catalog-driven-ingest/blob/master/src/PipelineMetastoreDatabase/dbo/StoredProcedures/usp_delete_metadata.sql)

### Set Get QueryUrl～Query Ingest Target

Purviewのカタログ検索APIを利用して取り込み対象のアセットを検索します。

Set Get QueryUrl：
<Purviewアカウント名>.purview.azure.com/（PurviewのデータプレーンURI）＋「catalog/api/search/query」へのポスト用urlを生成

Set Query Body:
要求本文を生成

Query Ingest Target：
POSTメソッドでアセットの検索を実行

### For Each

アセットで繰り返します。Itemにはカタログの検索にひっかかったエンティティのguidなどが格納されます。

### Get_Entity～Get_Server_Entity

guidを使用してgetを叩くことで、テーブル名、スキーマ名、データベース名、Azure SQL サーバーホスト名を取得します。
参照エンティティ（テーブルの場合、被参照はカラム）は親のエンティティのguidが載ってますので、以下のような参照順にgetしています。
table entitiy→dbSchema→db→server

### Insert Metadata

取得したエンティティ情報および、シンク先のフォルダなどの情報を制御テーブルに書き込みます。

コード：
[usp_insert_metadata.sql](https://github.com/ryoma-nagata/purview-data-catalog-driven-ingest/blob/master/src/PipelineMetastoreDatabase/dbo/StoredProcedures/usp_insert_metadata.sql)


## 最後に

自動インジェストパターンは大量のデータ取り込みをするうえでは、考慮不可欠の概念になります。
あわせて、カタログとの統合で型情報を取得してデータ品質チェックを自動化するなど、メタデータを利用したパイプラインはこれからいろいろなソリューションが期待されます。

ぜひお試しください。
Laravelアプリをgit cloneした後にやったこと

#前提

MacOS バージョン11.2.3
CPU Apple M1

-----

git/github
MAMP
VScode 

以上、インストール済み

```
 % node -v
v14.17.5

% npm -v
6.14.14

% laravel -v
Laravel Installer 4.2.9

 % php -v
PHP 8.1.1
```
他に思い出して気が向けば追記します。

#git cloneの方法

まずはgit cloneです

```
ターミナル
cdコマンドで入れたいファイルに移動
% git clone https//<クローンしたいURL>.git

Cloning into '〇〇'...
Username for 'https://github.com': <自分のgithubのuser名>
Password for 'https://tsunodayuki0302@github.com': <パスワード(ターミナルには表示されません)>

成功したら↓
remote: Enumerating objects: 2754, done.
remote: Counting objects: 100% (2754/2754), done.
remote: Compressing objects: 100% (1321/1321), done.
remote: Total 2754 (delta 1683), reused 2401 (delta 1388), pack-reused 0
Receiving objects: 100% (2754/2754), 25.40 MiB | 5.08 MiB/s, done.
Resolving deltas: 100% (1683/1683), done.
```

#composerをインストール・update

```
composer.lockがあった場合
cdコマンドで入ったファイルに移動
 % composer install

composer.lockがない場合
 % composer update
```

取りあえず % composer installでいいらしいです。(他の記事参照)

#.env.exampleを書き換える

\\コメントでご指摘がありました！
ありがとうございます。
↓
.env.example -> .envに変更。

```
APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
```
こんな感じになります。
この後、PHPMyAdminに繋げたいので
MAMPを起動して http://localhost:8888/MAMP/ のMySQL通りに記述。

#migrateする
これでマイグレーションされます

```
% php artisan migrate:fresh
```

seedはこちら

```
% php artisan db:seed
```

再マイグレーション＆seed実行

```
% php artisan migrate:refresh --seed
```

以上になります。
M1Macでdockerでdocker-compose upがうまくいかないとき

.ymlファイルを作成しdocker-compose upでコンテナを立ち上げようとしたところ...
![スクリーンショット 2022-01-30 14.20.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/50149185-3bbf-e993-fd8b-1408653f1a12.png)

エラーが出ました。
原因は.ymlファイルの設定。

version: '3.7'
services:
php: ......(省略)
mysql:
image: mysql:8.0
container_name: mysql
ports:
- "4306:3306"
volumes:
- ./docker/db/data:/var/lib/mysql
- ./docker/db/my_conf:/etc/mysql/conf.d
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: laravel

これはNG。

正しくは

　version: '3.7'
　services:
　　php: ......(省略)
　　mysql:
　　　image: mysql:8.0
　　　container_name: mysql
　　　ports:
　　　　- "4306:3306"
　　　volumes:
　　　　- ./docker/db/data:/var/lib/mysql
　　　　- ./docker/db/my_conf:/etc/mysql/conf.d
　　　environment:
　　　　MYSQL_ROOT_PASSWORD: password
　　　　MYSQL_DATABASE: laravel

段落を守らないとダメらしい。

次のエラーはmysqlのコンテナを立ち上げたとき...
![スクリーンショット 2022-01-30 14.20.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/23a2ba4e-ebcb-1fc7-6fbc-9da62c98a29b.png)

これはAppleシリコンMac（M1）で起こるようで、解決法は

platform: linux/x86_64

を.ymlファイルに追加する。つまり...

version: '3.7'
　services:
　　php: ......(省略)
　　mysql:
　　　image: mysql:8.0
　　　container_name: mysql
　　　ports:
　　　　- "4306:3306"
　　　platform: linux/x86_64 ⇦※追加！！！
　　　volumes:
　　　　- ./docker/db/data:/var/lib/mysql
　　　　- ./docker/db/my_conf:/etc/mysql/conf.d
　　　environment:
　　　　MYSQL_ROOT_PASSWORD: password
　　　　MYSQL_DATABASE: laravel

これでうまくいきます。
vistaでphotoshop その5

#概要

vistaでphotoshopやってみる。
jpg読んで、pngで出力やってみる。

#写真

![test4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/af625be9-a93b-2da5-2604-6b4632edb3a6.png)


#サンプルコード

```

var fileObj = new File("/Users/ore/eki.jpg");
open(fileObj);
//alert(activeDocument);
var pngOpt = new ExportOptionsSaveForWeb();
pngOpt.format = SaveDocumentType.PNG;
pngOpt.optimized = true;
pngOpt.interlaced = false;
pngOpt.PNG8 = false;
var filePath = new File("/Users/ore/test4.png");
app.activeDocument.exportDocument(filePath, ExportType.SAVEFORWEB, pngOpt);
alert("ok");



```


以上。
Maven Central Repository にライブラリ公開する手順

備忘も兼ねて、 Maven Central Repository に Kotlin ライブラリを公開する際に参照したドキュメントや手順をまとめる。

詳細は以下の２つの資料に記載されている。
この資料はこれらの抜粋・再構成となる。

- [Publish - Sonatype](https://central.sonatype.org/publish/)
- [Publishing a project as module - Gradle](https://docs.gradle.org/current/userguide/publishing_setup.html)

# 準備

## Maven Central へのリポジトリ作成

https://central.sonatype.org/publish/publish-guide/ を参考に、 Maven Central にリポジトリを作成する。

1. Sonatype にアカウントを作成する
1. New Project チケットを作成する

New Project チケットを起票する際に、以下の情報が必要になる。

- Group ID
- 公開する予定のライブラリの URL
- 公開する予定のライブラリのソースコードをホストしている URL

私の場合は GitHub.com のアカウントを利用したので、 Group ID に `io.github.hmiyado` を指定した。
GitHub.com を利用する場合は `com.github.` 始まりでないことに注意する。

チケットを作成すると、アカウントの所有権確認のため、チケットに対応する名前（`OSSHR-XXXX`）の空リポジトリを作成するようコメントが来る。
それに対応すると、 Maven Central に自分のライブラリを公開するためのリポジトリを作成してもらえる。
このあたりのやりとりは Bot と行う。

## ライブラリを公開するためのコード実装

実装はすべて .kts を前提とする。
https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:complete_example に全体のサンプルがあるので、これを眺めると全体感を掴みやすい。
大きく2点対応する必要がある。

- Maven Plugin の設定
- Signing Plugin の設定

### Maven Plugin の設定

作成した Maven Central 上のリポジトリの認証情報も設定する必要がある。
GRADLE_HOME 下の `gradle.properties` 、デフォルトでは `~/.gradle/gradle.properties` に認証情報を置くと、複数のプロジェクトで再利用できる（ [参考](https://central.sonatype.org/publish/publish-gradle/#credentials) ）。

### Signing Plugin の設定

プラグインの設定と同時に、署名の設定も必要。

署名には GnuPG を使う。
https://central.sonatype.org/publish/requirements/gpg/ を参考に鍵の生成と公開鍵のサーバーへの登録を行う。

署名に必要な設定は Maven Plugin での設定と同様、 GRADLE_HOME 下の `gradle.properties` に記載しておく。

# 公開

1. リポジトリへのアップロード
1. Nexus Repository Manager 上での公開設定

## リポジトリへのアップロード

Maven Plugin および Signing Plugin の設定が適切に完了していれば、 `./gradlew publish` の実行のみでOK。

## Nexus Repository Manager 上での公開設定

https://central.sonatype.org/publish/release/ に詳細が記載されている。
大ざっぱな流れとしては以下の通り。

1. アップロードしたリポジトリを Close する
1. リポジトリの署名や内容が検証される
1. 検証に通ったら Release する

Release 後、リポジトリが利用できるようになるまでに30分程度、リポジトリが [Maven Central Repository Search](https://search.maven.org/) に反映されるまでに4時間程度かかる。

以上の手順でライブラリを公開できる。
Swift・CoreBluetoothで通信を行いメッセージアプリっぽいのを作った2

# 第二回の内容
前回の記事でBLEデバイスを検索する機能を実装したので、前回の続きから再開しBLEデバイスに接続の実装になります。
BLEデバイスの検索の記事を貼っておきますのでまだBLEデバイスの検索の機能を実装していない方はこちらからお願いします。
[Swift・CoreBluetoothで通信を行いメッセージアプリっぽいのを作った1](https://qiita.com/Crow/items/adfc39592c8e92587285)

# BLEデバイスへの接続
前回はセントラル側で周辺のBLEデバイス(ペリフェラル)の検索を実装しました。
今回はセントラル側でBLEデバイス(ペリフェラル)への接続を行います。

# プロパティの定義
![スクリーンショット 2022-01-30 15.05.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207076/6d53a1bb-8aac-9d45-7a8b-c8a76ee8cff2.png)
最初に発見したペリフェラルのオブジェクトを保持しておくプロパティを定義します。
ここでは接続するBLE端末の情報を持つ、という考え方でOKです。

# 接続を開始する
![スクリーンショット 2022-01-30 15.09.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207076/7e649521-fb51-47c6-266e-005c03c41366.png)
`self.peripheral = peripheral`で接続するBLEデバイスのオブジェクトを保持します
`self.centralManager.connect(self.peripheral,options:nil)`で上記で保持したBLEデバイスのオブジェクトを参照してBLEデバイスに接続します

# 接続結果を取得する
接続が成功するとCBCentralManagerDelegateのcentralManager:didConnectPeripheral:が、
失敗するとdidFailToConnectPeripheral:error:が呼ばれます
![スクリーンショット 2022-01-30 15.15.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207076/0419dd90-61c2-4f23-2526-559ec674051c.png)


以上の手順でBLEデバイスへ接続ができます。
今回の記事でペリフェラルという単語が出てきましたが、現段階では接続するBLEデバイスの情報があるもの程度の認識で問題ありません。
ペリフェラルについては次回説明していきたいと思います。
次回は接続したBLEデバイスのサービス・キャラクタリスティックを検索する記事を書きます。
来週の土曜日にアップする予定です。
【赤点回避】「n進数」を使って、赤点を言い訳しよう！Python

<h3>ご！あいさつ</h3>
<p>どうも、はっしらです。</p>
<p>現在中３なんですけど、明日定期テストあるんですよね。</p>
<p>内申点に関わるちょー大切なテストなので、ブログ書いている場合ではないですね。</p>
<h4>ところで、、、</h4>
<p>みなさん、赤点をとった経験はありますか？</p>
<p>赤点を取ってしまった時、まず先に親や塾の先生の言い訳を考えると思います。</p>
<p>しかし、言い訳のしようがない赤点を取ってしまうこともあるはず。</p>
<p><strong><em>そこで、「言い訳のしようがない時」用に、数学の力を使って言い訳を作ろうと思いました。</em></strong></p>
<h3>できたもの</h3>
<p>ここでは</p>
<p>点数：39点を40点以上に上げたいという場合を考えます。</p>
<p>このプログラムを実行し、</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/H/Hasshira/20211118/20211118125134.jpg" alt="f:id:Hasshira:20211118125134j:plain" width="1200" height="683" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p>「現在の点数」と「どれくらい上げたいか」を入力します。</p>
<p>このような結果になりました。</p>
<p> </p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/H/Hasshira/20211118/20211118125432.jpg" alt="f:id:Hasshira:20211118125432j:plain" width="1200" height="481" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p>つまり、39点でも9進数なら「43点」になります。すなわち赤点回避ということです。</p>
<p>やったね！！！！</p>
###コード

```python:main.py
def base10int(value, base):
    if (int(value / base)):
        return base10int(int(value / base), base) + str(value % base)
    return str(value % base)
x=int(input("数値を入力"))
y=int(input("目標値を入力"))
n=0
for i in range(8):
    i+=2
    z=(base10int(x, i))
    z,y=str(z),str(y)
    if z==y:
        print(f"{i}進数ですね")
        n=1
if n==0:
    print ("言い訳できません。")
```

<p> </p>
<h4>さいごに</h4>
<p>このプログラムの一部（というか重要な部分）は「理系のための備忘録」様の記事を参考にさせていただきました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fscience-log.com%2Fpython%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0tips%E9%9B%86%2F%E3%80%90python%E3%80%91%E8%A8%98%E6%95%B0%E6%B3%95%E3%81%AE%E5%A4%89%E6%8F%9B%2F" title="【Python】記数法の変換（10進数⇔n進数）" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://science-log.com/pythonプログラミングtips集/【python】記数法の変換/">science-log.com</a></cite></p>
<p>ありがとうございました。</p>
【数学＆Python】時計の針が直線になる時刻って？中学生が計算してみた



### 今回の記事について

#### 時計の針が直線になる時刻…？

みなさん、時計の針が直線になる時刻を考えたことはありますか？

例えば「6:00」とかですね。
[f:id:Hasshira:20211116131231j:plain]

また、何回直線になる時刻が存在するのでしょうか？

とても面白そうな話なので、考えてみることにしました。
<div class="boxinwaku"><span class="box-title">**今回の内容**</span>
<ul>
<p>** 時計の長針と短針が直線になる時刻を求めてみた！** </p>
</ul>
</div>

### どうやって計算する？

まず、このような手段で計算していこうと思います。

1. 数学を使ってどれか一つを求める（手作業）
2. Pythonを使って計算させる
3. 「1」「2」の繰り返し

### 完成したコード

忙しい人の為に、完成したコードを最初に乗っけておきます。

```python
import sympy
l=[]
x = sympy.Symbol('x')
y = sympy.Symbol('y')
t = sympy.Symbol('t')
t=0
while t<=12:
    if t>=6:
        t-=1
    expr1 = y-0.5*x-(30*t)
    #print(expr1)
    expr2 = y-6*x+180

    #print(sympy.solve([expr1, expr2]))
    n=sympy.solve([expr1,expr2])
    n=n[x]
    if n>59:
        while True:
            n-=60
            t+=1
            if n<60:
                break
    l.append(f"時計の長針と短針が直線になる時刻は、{t}時{round(n)}分です")
    t+=1
for l in l:
    print(l)
```

### 具体的な説明

#### １．数学を使って構想を練る

まず、時計について考えてみましょう。

時計の長針・短針が一分間に進む角度は、

長針：12時間で360度（一周）→360/12=30→1時間で30度。

＝30/60で［0.5］度！

短針：60分で360度（一周）→360/60=[6]度

#### ２．方程式を作ってみる

以上のことを考えて方程式を作ってみました。

【長針の角度と時刻を表す式】

x：時間（分）

y：角度

t：時刻の「時」の方（「分」ではない）

y=0.5x+(30t)$$

【短針の角度と時刻を表す式】

y=6x

【短針と長針が直線になったことを表す式（短針において）】

y+180=6x

### pythonで書き起こしてみる

```python
import sympy
l=[]
x = sympy.Symbol('x')
y = sympy.Symbol('y')
t = sympy.Symbol('t')
t=0
while t<=12:
    if t>=6:
        t-=1
    expr1 = y-0.5*x-(30*t)
    #print(expr1)
    expr2 = y-6*x+180

    #print(sympy.solve([expr1, expr2]))
    n=sympy.solve([expr1,expr2])
    n=n[x]
    if n>59:
        while True:
            n-=60
            t+=1
            if n<60:
                break
    l.append(f"時計の長針と短針が直線になる時刻は、{t}時{round(n)}分です")
    t+=1
for l in l:
    print(l)
```

1. sympyをインポート（方程式を解けるように）
2. 方程式を作る
3. 「長針」が12になるまで繰り返す

## 結果

```
時計の長針と短針が直線になる時刻は、0時33分です
時計の長針と短針が直線になる時刻は、1時38分です
時計の長針と短針が直線になる時刻は、2時44分です
時計の長針と短針が直線になる時刻は、3時49分です
時計の長針と短針が直線になる時刻は、4時55分です
時計の長針と短針が直線になる時刻は、6時0分です
時計の長針と短針が直線になる時刻は、7時5分です
時計の長針と短針が直線になる時刻は、8時11分です
時計の長針と短針が直線になる時刻は、9時16分です
時計の長針と短針が直線になる時刻は、10時22分です
時計の長針と短針が直線になる時刻は、11時27分です
時計の長針と短針が直線になる時刻は、12時33分です
```

### 最後に

ありがとうございました。
【フィルタリング解除】「学習用iPad」のフィルタリングを無効化する方法（アイフィルター）

<h3>はじめに</h3>
<div class="boxinwaku"><span class="box-title">ご注意</span>
<p>2021年11月22日現在、これから紹介する方法での成功を確認していますが、今後、対策されてしまう恐れがあります。そこだけご注意ください。</p>
</div>
<p>どうも、はっしらです。</p>
<p>学習用iPadのフォルタリンぐを無効化する方法を発見いたしました。</p>
<p>「方法だけ知りたいよ」という方も多いと思いますので、簡単に紹介します。</p>
<h4>結論</h4>
<div class="boxinwaku"><span class="box-title">無効化する方法</span>
<p>ブラウザの「キャッシュ」を使用する！</p>
</div>
<h4 class="boxinwaku">手順</h4>
<p>この「Qiita 」という私が愛用しているサイトで説明します。</p>
<p>まず、普通にアクセスすると、ブロックされてしまいます。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/H/Hasshira/20211122/20211122084008.jpg" alt="f:id:Hasshira:20211122084008j:plain" width="1200" height="830" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/H/Hasshira/20211122/20211122084006.jpg" alt="f:id:Hasshira:20211122084006j:plain" width="1200" height="786" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong><span style="font-size: 150%;">しかし、</span></strong></p>
<p>検索結果の上にあるアイコンをタップすることで、</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/H/Hasshira/20211122/20211122084127.jpg" alt="f:id:Hasshira:20211122084127j:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/H/Hasshira/20211122/20211122084144.png" alt="f:id:Hasshira:20211122084144p:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image" />簡単に入れてしまうんです。</p>
<h4>最後に</h4>
<p>時間が経てば対策されてしまうので、なるべく早いうちに使っておきましょう！</p>
<p>さいなら！</p>
Salesforceのカスタマイズ画面はフローのScreenで実装する（動的画像表示）

###要件
Salesforceのカスタマイズ画面はLWCまたLightningComponentの開発になりますが、できればノーコードまたローコードのFlowのScreenで解決したいです。今回はレコード関連の画像は画面に彫りこみたいです。
SFDCのFlowにDisplayImageは静的な画像しか表示できないです。レコード関連の動的に画像を表示する案です。
→表示テキストで、Image表示変数で画像を表示する
#####画像のContentVersionIdを取得する
ファイルのDocumentIdを求めて、それからContentVersionにIDを求める
ContentDocumentのId
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/b4f3ca49-665a-8d77-8148-6dee3536fe34.png)
あと、Select id from ContentVersion where ContentDocumentId = 'XXXX'
そのIDはContentVersionIDです。

###Screenに画像表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/375bd353-2339-a76a-5ec5-e15ffadb1f69.png)

####表示変数を定義
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/ec5eff5f-d5bb-46cc-6712-dd75cc8fd33a.png)

値：

```
<img src="/sfc/servlet.shepherd/version/download/{!GetStandardImage.img_file_id__c}", alt="画像", width="360" height="480" />

```
####表示テクスト（入力テクストではない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/16f08664-a05d-ce4c-6736-c2098ef07747.png)

####ページ編集にフローを配置する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/d590a790-3832-d5e4-ac15-da322cb65ab3.png)
効果：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/9d04fae5-35ac-7774-36de-5efaacb7f6eb.png)
FlutterでFirebaseへ接続したときのエラー対処メモ

FlutterをFirebaseへ接続したときにエラーで苦労したのでメモを残す。

##作業環境
Win10 home
Flutter 2.8.1
Dart 2.15.1
VSCode 1.63.2

##flutter runしたらエラーが出た

> Error:uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library

SDKのバージョンが19以上にのみ対応とのこと。
エラー文で検索かけてみたら**build.gradle**の**minSdkVersion 16**って書いてある箇所を**19**に変更しろとのことだが、残念ながら自分の**build.gradle**には**16**ではなく**flutter.minSdkVersion**と書いてあった。
これで正しいのか不安ではあったが、**flutter.minSdkVersion**を**19**へ変更してみる。

```:android/app/build.gradle【変更前】
minSdkVersion flutter.minSdkVersion
```

```:android/app/build.gradle【変更後】
minSdkVersion 19
```

##再度flutter runしたが、またエラーが出た

赤文字のエラーの後に白文字で下記の文が出た。
> [!] Your project requires a newer version of the Kotlin Gradle plugin.
>     Find the latest version on https://kotlinlang.org/docs/gradle.html#plugin-and-versions, then update
>     ext.kotlin_version = '\<latest-version\>'

Kotlinのヴァージョンを新しくしろとのこと
今回もエラー文で検索すると**ext.kotlin_version**を書き換える必要があるらしい。
先程の**build.gradle**より**１階層上の**build.gradleに**ext.kotlin_version**の記載があったので、最新のKotlinヴァージョン**1.6.10**へ書き換えてみる。

:::note warn
注意
先程のminSdkVersionのときと違う build.gradle なので気をつけて！
:::
```:android/build.gradle【変更前】
ext.kotlin_version = '1.3.50'
```

```:android/build.gradle【変更後】
ext.kotlin_version = '1.6.10'
```

##再度flutter runしたらビルド成功した

:::note info
これで正解なの？？
この対処で正しいかは疑問だが、とりあえずエラーは出ずにビルドすることができた。
正しい方法がわかる方は教えていただけるとありがたいです。
:::
NUnitで既存のプロジェクトのクラスを参照する

## 始めに
C#自体あまり経験はないのですが、タイトルそのままです。
NUnitの使い方を調べても大抵、NUnitプロジェクト内にテストするクラスを記載、
そのままテストコードを作る…という形のものが多かったです。
~~(普通既存のプロジェクトのクラスをテストしたくない？と思っていました)~~

忘れそうなので備忘録として残しておきます。
## NUnitのプロジェクトの追加
[Microsoft](https://docs.microsoft.com/ja-jp/dotnet/core/testing/unit-testing-with-nunit)のページにもドキュメントがあるので割愛
普通にNUnitのプロジェクトを追加するだけです。

## NUnitへ既存のプロジェクトの参照追加
ここがこの記事の全てではあります… 
ソリューションを右クリックして
![img.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173400/decf626d-a2c2-e6c8-100e-e9cfa86a6d11.jpeg)
メニューのプロジェクトの依存関係をクリック。
プロジェクトにNUnitのプロジェクト(画像ではNUnitTestProject)を選択します。
今回はMasterDataToolの中にあるプロジェクトをテストしたいので、
MasterDataToolの項目にチェックを入れます。
![img2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173400/2d68a0c5-260c-4c3b-ebf7-84bf27fe1c6f.jpeg)
VC++でいう追加のインクルードを設定するような感じですね。
これでNUnitの中でMasterDataToolの中のクラスがテストできるようになりました。
## テスト
![img3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173400/93b6376e-10d2-5552-a87b-3595bf269906.jpeg)
NUnitでMasterDataTool内にある
```Mhl.String.CheckEmpty```
というクラスがテストできています。

おわり。