OmniAICreator/Qiita-1.07M huggingface dataset:
Stable Diffusionで自分の描いたラフ画に色を塗ってもらう

# はじめに

自分が描いたラフ画にStable Diffusionで色を塗ってもらいます　

# 変換の対象の絵 

![IMG_F5F0774D5470-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136860/822a1a79-a2f9-fa26-bcd5-b6bad474dbc6.jpeg)

フラワーナイトガールというソーシャルゲームに登場する、ツツジ、という女の子を描いてみました 

## 変換対象の絵の特徴 
- 女の子はソファーに座っています
- 本を手に持っています
- 書斎にいます
- 衣装は中世ファンタジー世界風に描いています
ソファーも書斎もかなりラフ、AIが苦手としている指も描いています 
AIはどこまで綺麗に色を塗ってくれるのでしょうか？ 


# 使うツール 

## 導入しているツールその１　StableDiffusion
MacBookAirにStableDiffusionとそのWeb UIを導入しています　
ただし、StableDiffusionのimg2imgだとラフ画から元絵の構図をそのままに色を塗ってくれません 
というのも 
- Strengthを0.6以上にするとカラーにはなるが元絵を無視した絵が出力される
- Strengthを0.4以下にするとある程度維持した絵が出力されるが色を塗ってくれない
- 何より指とか手首が割と崩れる（ひどいときには無視することがある）

## 導入しているツールその２　ControlNet
上記の問題を解決するためにControlNetを導入します　
ControlNetとは元絵から輪郭抽出して物体認識するすごいやつです
導入方法とか使い方は
https://koneko3.com/how-to-use-controlnet/
をみてください　
私は白黒の線画に色を付けたいので 
- Preprocessorにはinvert(from white bg & black line)
- Modelにはcontrol_v11p_sd15s2_lineart_anime 
を指定しています 


## 導入しているツールその３　DeepDl 
promptに入れるコマンドを生成するためにDeepDlを使います 
今回は元絵が
「書斎で本を手に持ってソファーに座っている茶髪の少女」
という構図なので、それをそのままDeepDLに入れて翻訳してもらいます 
翻訳後の 
「Brown-haired girl sitting on a sofa in a study with a book in her hand」
をそのままtxt2txtのpromptに入れます 
シンプルな呪文でプロンプトを作れるっていうのも、自分で絵を描くメリットです 

# 実行手順
- StableDiffusionのtxt2txtのパネルを開く
- ControlNetのパネルを開いて色を塗りたい線画をドラック＆ドロップで読み込ませる
- Createボタンを押す
といたってシンプルです 

# 出力結果 

![00080-41777729.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136860/5946d707-555c-886f-411b-aa59052ae1bb.png)

元の線画を保ったまま色を塗ってくれています 
指の描写が若干気になるけど、他は思った以上に色を綺麗に塗ってくれていますね

# 最後に 
今回はStableDiffusion＋ControlNetを使って線画に色を塗るための基本的な方法を書いてみました 
twitterには他にも線画からのAI色塗りしたものをアップしているので、

https://twitter.com/fQBJZWizNB0xwSL/status/1684684472355336197

https://twitter.com/fQBJZWizNB0xwSL/status/1684518730565574656

https://twitter.com/fQBJZWizNB0xwSL/status/1683815136778403841

https://twitter.com/fQBJZWizNB0xwSL/status/1683107169619828736
zigbee写真伝送のフィールドテスト

開発動機:
ある地方都市で、道の駅の生産者コーナーの個別の在庫管理をうまく出来る解決策を募集していたことから起草し、例えば、農家の無人販売の在庫管理や、台風などの自然災害が接近しているときに、危険と思われる場所に一時的に監視のために置くことができるカメラが必要ではないか？と考えて、その仕組みを考えてみた。

要件:
そこで必要となる条件が、電源も無くWifiない場所に設置でき、操作条件もシステムの知識が無い人にも簡単に使えるように乾電池を電源として、特別な操作を必要としないものと考えた。
その一つの解決策としてZigBeeで画像を送る仕組みを考えて実験してみた。テストしたシステム構成は以下のようになります。ArduCamで撮った画像をRaspberry Pi Picoを通して、ZigBeeからRaspberryPi4Bに送ることにしました。

システム構成:
クライアント（カメラ側）
Digi XBee3 Zigbee 3.0 TH
Raspberry Pi Pico
Arducam Mini Module Camera Shield with OV2640 2 Megapixels Lens Compatible with Arduino UNO Mega2560 Board

![breadboard2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/6cf4becf-bf56-1106-0ddd-3a7f9ada59ac.png)


サーバーサイド
ZigBeeで送られてきた画像を保存。
Raspberry Pi 4B
ZigBee

![server_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/c8056f6d-cb54-f64a-768b-fa0edc1975d1.png)

詳細:
クライアントの実機は以下のようにしました。ブレッドボードだと、持ち運び時に部品が外れたり、振動にも弱いので、PCB基板をJCLで５枚で２どるほどでできるので、Fritzingで作ったブレッドボード図からプリント基板図を利用しては注してみました。できたものが以下のようになります。

![client01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/784d8b01-d154-f636-d3a3-f8daf59035e4.jpeg)

このクライアントから320x240のJPEG画像を1パケット80バイト程度にして分割して送ってみました。室内で実験したときには、1画像ごとに2、3件のチェックサムエラーが発生するために、再送機能も必要になりました。
サーバ側で画像の受け取り側は、Pythonを使って画像を受けとり、それを保存しました。

https://www.google.com/maps/dir/35.5979771,139.6392071/35.5958232,139.6425434/@35.5970503,139.6399631,321m/data=!3m1!1e3!4m2!4m1!3e2?authuser=0&entry=ttu

![map01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/1386da6b-678b-12e6-3479-5a54baa08d91.png)

結果:
上記にあるように、障害物がない状態で400メートルまでは画像の送受信ができました。まだ、受け取り側のPythonに少し改善の余地があるように感じたので、今回取れたログを分析して、プログラムの改善や、場所を変えてテストを重ねて実用性を確認したいと思います。
VBA PDF出力

Sub Merge_To_Individual_Files()
'Merges one record at a time to the folder containing the mailmerge main document.
' Sourced from: http://www.msofficeforums.com/mail-merge/21803-mailmerge-tips-tricks.html
Application.ScreenUpdating = False
Dim StrFolder As String, StrName As String, StrPwd As String, MainDoc As Document, i As Long, j As Long
Const StrNoChr As String = """*./\:?|"
Set MainDoc = ActiveDocument
With MainDoc
  StrFolder = .Path & Application.PathSeparator
  For i = 1 To .MailMerge.DataSource.RecordCount
    With .MailMerge
      .Destination = wdSendToNewDocument
      .SuppressBlankLines = True
      With .DataSource
        .FirstRecord = i
        .LastRecord = i
        .ActiveRecord = i
        If Trim(.DataFields("Last_Name")) = "" Then Exit For
        'StrFolder = .DataFields("Folder") & Application.PathSeparator
        StrName = .DataFields("Last_Name") & "_" & .DataFields("First_Name")
        StrPwd = .DataFields("date_of_birth ") & .DataFields("postcode")
      End With
      .Execute Pause:=False
    End With
      For j = 1 To Len(StrNoChr)
        StrName = Replace(StrName, Mid(StrNoChr, j, 1), "_")
        StrPwd = Replace(StrPwd, Mid(StrNoChr, j, 1), "_")
      Next
    StrName = Trim(StrName)
    With ActiveDocument
      .SaveAs2 FileName:=StrFolder & StrName & ".pdf", FileFormat:=wdFormatPDF, Password:=StrPwd, AddToRecentFiles:=False
      .Close SaveChanges:=False
    End With
  Next i
End With
Application.ScreenUpdating = True
End Sub

![名称未設定 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1285004/3b82e2c8-9f5e-7d67-2432-69ec1e1da919.png)
![名称未設定 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1285004/7de06b46-e7c9-cb3e-246b-6156fde839cd.png)
![名称未設定 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1285004/07cc74b5-8f5a-067d-83ae-0762f225d168.png)
wslでelixir その23

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
nxやってみた。
練習問題、やってみた。

# 練習問題
nxだけで、学習して推定せよ。

# 方針
- Nx.Defn使う
- grad使う

# サンプルコード

```
defmodule LinReg do
	import Nx.Defn
	defn init_random_params do
		key = Nx.Random.key(42)
		{m, new_key} = Nx.Random.normal(key, 0.0, 0.1, shape: {1, 1})
		{b, _new_key} = Nx.Random.normal(new_key, 0.0, 0.1, shape: {1})
		{m, b}
	end
	defn predict({m, b}, inp) do
		Nx.dot(inp, m) + b
	end
	defn loss({m, b}, inp, tar) do
		preds = predict({m, b}, inp)
		Nx.mean(Nx.power(tar - preds, 2))
	end
	defn update({m, b} = params, inp, tar, step) do
		{grad_m, grad_b} = grad(params, &loss(&1, inp, tar))
		{m - grad_m * step, b - grad_b * step}
	end
	def train(params, epochs, lin_fn) do
		data = Stream.repeatedly(fn -> 
				for _ <- 1..32, do: :rand.uniform() * 10 
			end)
			|> Stream.map(fn x -> 
				Enum.zip(x, Enum.map(x, lin_fn)) 
			end)
		for _ <- 1..epochs, reduce: params do
			acc ->
				data
				|> Enum.take(200)
				|> Enum.reduce(acc, fn batch, cur_params ->
					{inp, tar} = Enum.unzip(batch)
					x = Nx.reshape(Nx.tensor(inp), {32, 1})
					y = Nx.reshape(Nx.tensor(tar), {32, 1})
					update(cur_params, x, y, 0.001)
				end)
		end
	end
end


```

# 実行結果

```
$ iex -S mix
Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit:ns]

Compiling 1 file (.ex)
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> params = LinReg.init_random_params()
{#Nx.Tensor<
   f32[1][1]
   [
     [0.13694694638252258]
   ]
 >,
 #Nx.Tensor<
   f32[1]
   [-0.019947024062275887]
 >}
iex(2)> m = :rand.normal(0.0, 10.0)
4.458155128389648
iex(3)> b = :rand.normal(0.0, 5.0)
4.674045984609317
iex(4)> IO.puts("Target m: #{m} Target b: #{b}\n")
Target m: 4.458155128389648 Target b: 4.674045984609317

:ok
iex(5)> lin_fn = fn x -> m * x + b end
#Function<42.3316493/1 in :erl_eval.expr/6>
iex(6)> epochs = 100
100
iex(7)> {time, {trained_m, trained_b}} = :timer.tc(LinReg, :train, [params, epochs, lin_fn])
{99546223,
 {#Nx.Tensor<
    f32[1][1]
    [
      [4.458204746246338]
    ]
  >,
  #Nx.Tensor<
    f32[1]
    [4.6737189292907715]
  >}}
iex(8)> trained_m = trained_m |> Nx.squeeze() |> Nx.backend_transfer() |> Nx.to_number()
4.458204746246338
iex(9)> trained_b = trained_b |> Nx.squeeze() |> Nx.backend_transfer() |> Nx.to_number()
4.6737189292907715
iex(10)> IO.puts("Trained in #{time / 1_000_000} sec.")
Trained in 99.546223 sec.
:ok
iex(11)> IO.puts("Trained m: #{trained_m} Trained b: #{trained_b}\n")
Trained m: 4.458204746246338 Trained b: 4.6737189292907715

:ok
iex(12)> IO.puts("Accuracy m: #{m - trained_m} Accuracy b: #{b - trained_b}")
Accuracy m: -4.961785668999852e-5 Accuracy b: 3.2705531854571035e-4
:ok
iex(13)>


```

以上。
Reactで作るNetflixクローン - 使用したライブラリとTMDB APIの活用

# reactを使ったWebサイトの作成 テスト

## 目次
1. [Netflixをクローン](#netflixをクローン)
2. [実際に作成したもの](#実際に作成したもの)
3. [使用したライブラリ](#使用したライブラリ)
   - [react-dedux](#react-dedux)
   - [react-player](#react-player)
   - [react-slick](#react-slick)
   - [react-icons](#react-icons)
4. [取得したデータ TMDB](#取得したデータ-tmdb)
5. [参考文献](#参考文献)

## 1. Netflixをクローン

Netflixのような動画ストリーミングサービスのクローンを作成した。Reactの強力な機能と豊富なライブラリを活用して、見栄えの良いウェブサイトを構築。ほぼメモ書き。

## 2. 実際に作成したもの

React+TypeScriptを使ったNetflixの映画一覧を表示するアプリケーションを作成した。

成果物は以下
https://ty-gcp2-96f8b.web.app/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520671/1dd3fdb3-27e6-5c8c-ec08-51a0b0b7fbec.png)

Netflixの映画一覧を取得し、カテゴリー毎に表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520671/c18a38b4-22e7-2c30-7b5b-6c60fdf2ae3d.png)


ソースは以下
[GitHub](https://github.com/reduxjs/redux)

## 3. 使用したライブラリ

Reactをより便利に使うために、以下のライブラリを活用。

### 3-1. react-redux

ReactとReduxは相性が良く、状態管理やデータフローを効率的に管理できます。本プロジェクトでも、react-reduxを組み合わせて効果的にデータを管理。

Redux自体は独立したものなので単体で利用することも可能。


- [redux](https://github.com/reduxjs/redux)（GitHub）
- [Redux](https://redux.js.org/)（ドキュメント）

### 3-2. react-player

動画ストリーミングサービスを作成する際には、動画の再生機能が必要不可欠。react-playerはReact向けの優れた動画プレーヤーライブラリであり、シームレスな動画再生を実現。

とにかくブラウザ上でサウンドを再生したい、動画埋め込みコンポーネントを作りたたかったため使用
- [react-player](https://github.com/cookpete/react-player)（GitHub）

### 3-3. react-slick

ウェブサイトでのスライダーやカルーセル表示は、ユーザーエクスペリエンスを向上させる重要な要素の一つ。react-slickは使いやすくカスタマイズ性の高いスライダーライブラリで、Netflixクローンでも活用。

settingsにオプションを指定し、Sliderに渡すだけで
カスタムすることができる。
```php
import React from "react";
import Slider from "react-slick";

export default function SimpleSlider() {
  const settings = {
    dots: true,
    infinite: true,
    speed: 500,
  };

  const images = [image, image2, image3]
  return (
    <Slider {...settings}>
      {images.map(img)=>
        <div>
          <img src={img} alt="pictuer" />
        </div
      }
    </Slider>
  );
}
```

### 3-4. react-icons

アイコンはウェブサイトのデザインにおいて重要な役割を果たす。react-iconsは豊富なアイコンセットを提供し、簡単にアイコンを利用することができる。

## 4. 取得したデータ TMDB

Netflixクローンにおいては、映画やテレビ番組の情報を取得するために、TMDB（The Movie Database）APIを活用しました。TMDBは映画関連のデータを提供するAPIであり、Reactと組み合わせることでNetflixライクなコンテンツを表示することが可能となる。

具体的には、以下からAPIKEYを取得
[The Movie Database](https://www.themoviedb.org/?language=ja)

TMDBはエンタメ系の情報を多く抱えるデータベース。
postmanでAPIデータを送ってテスト。
## 5. 参考文献

- [React Slickをカスタマイズして矢印ボタンを表示させる方法 | Developers.IO](https://dev.classmethod.jp/articles/display-react-slick-arrow/)
- [Reactで始めるNetflixクローン作成 | Zenn](https://zenn.dev/gunners6518/books/4c4672f32dd100)

- [ react-player を使ってストリーミング動画ビューア画面をつくる](https://blog.usize-tech.com/react-player/)

- [React Slickの基礎知識](https://qiita.com/Masanori_N/items/839a9b5a97decd564c6f)

- [ 膨大なアイコンを収録！React Iconsでアイコンを手軽に配置してみよう](https://www.sukerou.com/2022/09/react-icons.html)

- [ TMDb API を利用して映画のポスターやあらすじを自分のサイトに表示する](https://chocolat5.com/ja/tips/tmdb-api/)

- [ GCPを使ってHTTPSのウェブサイトを公開す](https://zenn.dev/knockknock/articles/10aa24fde47c45)
プロキシサーバーTinyproxy と Squidの特徴の比較

### **Tinyproxy**

#### pros

1. 軽量: Tinyproxyはその名前の通り、非常に軽量でリソース消費が少ないです。小規模なシステムやエッジデバイスなど、リソースが限られている環境に適しています。
2. シンプル: 設定が簡単で、使い始めやすいです。設定オプションが比較的少ないため、シンプルなプロキシニーズに適しています。

#### cons

1. 機能の制限: TinyproxyはSquidよりも機能が制限されており、高度な機能やカスタマイズが必要な場合には不十分かもしれません。
2. 拡張性: Tinyproxyは拡張性が限られているため、大規模なネットワークや要件がある場合には向いていません。

### **Squid**

#### pros

1. フル機能: Squidは非常に高機能なプロキシサーバーであり、アクセス制御、キャッシュ、ログ記録、SSL対応など、さまざまな機能を備えています。
2. 拡張性: Squidは豊富な設定オプションと拡張性を持っており、複雑なネットワーク要件に対応できます。大規模な組織や要件のあるネットワークに適しています。

#### cons

1. リソース消費: SquidはTinyproxyよりもリソースを多く消費します。メモリやCPUに要求が高く、軽量な環境では適切でないかもしれません。
2. 設定の複雑さ: Squidは非常に多機能なため、初めてのユーザーにとっては設定が複雑で難しい場合があります。

### まとめ

要約すると、Tinyproxyは軽量でシンプルなプロキシサーバーであり、小規模な環境に適しています。一方、Squidは高機能で拡張性があり、大規模なネットワークや複雑な要件に適していますが、リソース消費が多く設定が複雑です。使用目的やネットワークの規模に応じて、適切なプロキシサーバーを選択することが重要です。
NetlifyとVercelの特徴と優位性について

NetlifyとVercelは、静的サイトのホスティングやデプロイを行うことができるクラウドサービスです。以下にそれぞれの違いや優位性をまとめてみました。

### Netlifyの特徴・優位性

‌

- デプロイやホスティングが非常に簡単で、初心者でも使いやすい。
- ビルド時に自動的に最適化された静的コンテンツを生成するため、サイトの読み込み速度が高速である。
- フロントエンドのフレームワーク（ReactやVue.jsなど）やCMS（Content Management System）との連携が簡単にできる。
- サーバーレス機能を提供しており、APIの作成やフォームの受信なども行うことができる。
- 無料プランでも高機能で、制限が比較的少ない。

### Vercelの特徴・優位性

- デプロイやホスティングが非常に高速で、秒単位での反映が可能である。
- 静的サイトのみならず、SSR（Server Side Rendering）やAPIのホスティングも行うことができるため、より柔軟な開発が可能である。
- デプロイ前にPreview URLを発行することができ、ビルド時の確認がしやすい。
- Next.jsやNuxt.jsなどのSSRに対応したフレームワークとの連携が簡単にできる。
- 無料プランでも高機能で、制限が比較的少ない。

### まとめ

以上のように、NetlifyとVercelはどちらも優れたクラウドサービスですが、細かな違いがあります。静的サイトのみの場合は、Netlifyがより使いやすいといえます。一方、SSRやAPIを含めたより柔軟な開発が必要な場合は、Vercelがおすすめです。それぞれのサービスの特徴を比較し、自分のニーズに合ったサービスを選ぶことが重要です。
[無料] Nuxt3アプリをインターネットで配信したい。おすすめのクラウド・ホスティングサービス４選

「Nuxt 3で作成したアプリケーションをインターネットで配信したい」
そんなニーズを満たす以下の無料のクラウドホスティングサービスを４つご紹介します。

### Netlify

Netlifyは静的サイトジェネレーターで構築されたサイトを簡単にホストできるクラウドプラットフォームです。Nuxt 3で作成したアプリをNetlifyにデプロイすることができます。無料プランでもHTTPSが使えるため、安全にサイトを配信することができます。

### Vercel

Vercelは、サーバーレスアーキテクチャを採用したウェブサイトやアプリケーションのホスティングを提供しています。Nuxt 3で作成したアプリをVercelにデプロイすることができ、簡単にスケーラブルなアプリを作成できます。無料プランでもHTTPSが使えるため、安全にサイトを配信することができます。

### Heroku

Herokuは、クラウドプラットフォームで、Node.jsアプリをデプロイすることができます。Nuxt 3で作成したアプリをHerokuにデプロイすることができます。無料プランでもHTTPSが使えるため、安全にサイトを配信することができます。

### Firebase Hosting

Firebase HostingはGoogleが提供するクラウドプラットフォームで、静的なコンテンツやWebアプリケーションをホストすることができます。Nuxt 3で作成したアプリをFirebase Hostingにデプロイすることができます。無料プランでもHTTPSが使えるため、安全にサイトを配信することができます。

### まとめ

以上のように、Netlify、Vercel、Heroku、Firebase Hostingなどのクラウドプラットフォームを利用することで、Nuxt 3で作成したアプリケーションを無料で簡単にインターネットで配信することができます。
Windows Terminal上で処理実行中にコンソールをクリック

コマンドプロンプト、PowerShellのコンソールを問わず。

Windowsのコンソール上で処理を実行中に、コンソールをクリックするとプロンプトが簡易編集モードとなり、実行している処理が停止してしまう。

これを知らずに、途中で処理を停止してしまう失敗話はWindowsではよく聞く話かと思います。

コマンドプロンプトやPowerShellで処理が停止するのを確認する方法としては `ping -t localhost` といった実行を繰り返すコマンドを実行して、コンソール上をクリックすると確認できます。（クリックすると簡易編集モードになり処理が停止）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/6ed46009-2a89-5ff9-4448-fc97e9998866.png)

いままでWindowsのコンソールはそういう物だといった理解をしていたのですが。

最近、`Windows Terminal`上で起動した`cmd.exe`や`PowerShell`はクリックや範囲選択をしても処理が停止しないことに気が付きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/42af1205-1057-e2cd-22ae-f15ab1c00363.png)


気づいた際の`Windows Terminal`バージョンは下記の通りとなっており。

- Windows ターミナル (プレビュー)
- バージョン: 1.18.1462.0

ここらへんの動作について何か記載されていないかと、[microsoft/terminal](https://github.com/microsoft/terminal) を検索した所、画面出力周りで下記が引っかかりました。

[terminal output freezes on click #408](https://github.com/microsoft/Terminal/issues/408)

[Feature Request: Pause output or scrolling on click (and make it a setting) #980](https://github.com/microsoft/terminal/issues/980)

[Feature Request: Preserve scroll position while not "at bottom" #3863](https://github.com/microsoft/terminal/issues/3863)

[Add a spec for output snapping #2529](https://github.com/microsoft/terminal/pull/2529)

[Implement preventing auto-scroll on new output #6062](https://github.com/microsoft/terminal/pull/6062)

[doc/specs/#980 - SnapOnOutput.md](https://github.com/microsoft/terminal/blob/main/doc/specs/%23980%20-%20SnapOnOutput.md)

なんとなく`Windows Terminal`では初期からコンソール処理中に画面をクリックしても現在のように処理が停止するといった事はなかったっぽい？

# 総評

Windows Terminalを使い始めてしばらくたちますが、いまさら気がつきました。
Desert Safari Abudhabi

Book your Desert Safari Abu Dhabi tour today and experience a credible adventure in the Arabian desert. Affordable prices and easy booking at Eatours. For more information visit: https://eatours.ae/

![IMG20220316132046-scaled-531x354.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521710/d2dd5435-5e0a-a602-511e-4556bd335900.jpeg)
nc（もしくはtelnet）を使ってmacOSやLinuxのコマンドラインからSMTP認証を通したメール送信を行う


```bash:send_mail.sh
#!/bin/bash
# SMTP認証を利用したメール送信を行います。

# set -xe

# 下記を書き換えてください。
HOST=example.com
PORT=587
USER=info@example.com # SMTP認証に利用されるメールアドレス
PASS=somethingpass
TO=yousan@example.com
FROM=info@exmaple.com

# SMTP認証用の文字列を作成します。
# @see https://www.tohoho-web.com/ex/draft/smtp-auth.htm
SMTP_AUTH_STR=$(printf "%s\0%s\0%s" $USER $USER $PASS | openssl base64 -e | tr -d '\n'; echo)

function mail_input {
  echo "EHLO localhost"
  sleep 1
  echo "auth plain $SMTP_AUTH_STR"
  echo "mail from: $FROM"
  echo "rcpt to: $TO"
  echo "data"
  echo "To: $TO"
  echo "From: $FROM"
  echo "Subject: Hello Mail Server"
  echo ""
  echo "test mail"
  echo "."
  echo "quit"
}

# send
mail_input | nc ${HOST} $PORT
```


下記のページを参考にしました。

https://qiita.com/awwa/items/dae1f8475c96b506edd0
ラズピコとMicroPythonでToF測距センサMTOF171000C0を動かす

# 概要
秋月電子で購入できる安価な測距センサ「**ToF測距センサMTOF171000C0**」を**MicroPython**でデータ取得するプログラムを紹介します。
ToF測距センサMTOF171000C0（以下、ToF測距センサ）はI2C通信機能とUART通信機能を有していますが、ここでは**I2C通信**を用いてデータ取得していきます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359003/558075b5-1ca7-02be-856f-26970f009978.jpeg" width=50%>
[ToF測距センサMTOF171000C0（秋月）](https://akizukidenshi.com/catalog/g/gM-14538/)
# ToF測距センサMTOF171000C0の性能
[MTOF171000C0のアプリケーションノート（秋月）](https://akizukidenshi.com/download/ds/socle/mtof171000c0_application_notes.pdf)を参照して、ToF測距センサの性能を簡単に示します。
- 一般性能

|項目|パラメータ|
|---|---|
|計測形式|ToF（光の反射時間で測距）|
|電源電圧|3.0~3.6 [V]|
|通信形式|I2C、UART|
|計測範囲|白色板：2~120 [cm]<br>灰色板：2~70 [cm]|
|計測精度|白色板：±4 [%]<br>灰色板：±7 [%]|
|動作サイクル時間|33 [ms]|

- I2C関連

|項目|パラメータ|
|---|---|
|I2Cアドレス|0x52（7bit）|
|I2C周波数|100 [kHz]|
|計測用コマンド|0xD3|
# 実装
## 配線
配線例を以下に示します。下表の「ピン番号」は、Raspberry Pi Picoの各ピンに振り分けられた番号と対応しています（GPIOの番号とは違うので注意）。
|MTOF171000C0のピン|接続先|ピン番号|
|:--:|:--:|:--:|
|赤（VDD）|3.3 [V]|pin 36|
|黒（GND）|GND|pin 3|
|白（TXD）|GND|pin 3|
|茶（RXD）|GND|pin 3|
|緑（SCL）|GPIO 3（I2C1 SCL）|pin 5|
|黄（SDA）|GPIO 2（I2C1 SDA）|pin 4|

:::note
もし複数台のToF測距センサを接続したい場合は、**RXD**をCS（チップセレクト）ピンとして利用できます。<br>**使用したいセンサのRXDにLOW**を印可し、**それ以外のセンサのRXDにHIGH**を印可することで、動作機器の切り替えが可能です。
:::
## MicroPythonプログラム
ToF測距センサから1秒おきにデータを取得するMicroPythonプログラムを紹介します。
開発環境としては[Thonny IDE](https://thonny.org/)を使いました。

```Python:main.py
from machine import Pin, I2C
import time

i2c = I2C(id=1, scl=3, sda=2, freq=100000)

while True:
    i2c.writeto(0x52, b'0xD3')
    data_bytes = i2c.readfrom(0x52, 2) # bytes型のデータを取得
    data = data_bytes[1]<<8 | data_bytes[0] # 距離に変換[単位：mm]
    print(data, ' mm')
    time.sleep(1)
```

これでミリメートル単位の距離が取得出来たら成功です。
Qiita-syncで記事を書いてみた

# はじめに

以下の記事を参考に、Qiita-syncを使ってGtHubにpushした内容を自動でQiitaに公開してみる試みです。<br>
https://qiita.com/ryokat3/items/d054b95f68810f70b136

# Qiita-sync用リポジトリの作成手順

記事の手順のみ実施し、詰まるポイントも無くすぐにできました。

# リポジトリ内で自分で書き換えた箇所

### cronの設定

Qiita-sync紹介記事でもcronの時間は変えることをおすすめされていたので以下のように変更しました。

```yml:qiita_sync_check.yml
name: Qiita Sync Check

on:
  schedule:
    - cron: "0 17 * * 1" # 17:00 毎週月曜 UTC = 02:00 毎週火曜 JST
  workflow_run:
    workflows: ["Qiita Sync"]

```

cronの時間の記法は以下を参考にしました。<br>
https://www.yoheim.net/blog.php?q=20190902


### README記載内容変更。

主に以下の内容を記載しました。
- Qiitaマークダウンチートシートをメモしておいた。
- 同期が失敗する場合の注意点をメモしておいた。
- ヘッダのidに関する注意点。

# 以上

これで問題なくQiitaに公開されれば、

- 基本は手元でメモを作成し、ある程度まとまった段階でQiitaで公開する。
- gitやSQLのチートシート系記事であれば、ローカルにファイルがあるのですぐに確認できる。

といったこともできるのでアウトプットが捗りますね（投稿頻度が上がるとは言ってない）

# 書いてみて気付いた点（追記）

qiita_sync_check.ymlの内容を記載しているコードブロックがうまく反映されていませんね。<br>
確かにmdファイル上では「\`\`\`」と書いているのですが「\`」と表記されており、コードブロック化されていません。<br>

↓（追記）<br>
少し修正してpushを繰り返したら反映された。<br>
コードブロックが反映されていなかった状態の場合、GitHubActionsの「Qiita Sync Check」がエラーになっていた。
データサイエンティストとしてなぜG検定を受けたのか

# はじめに
　こんにちは！私は現在、AI技術を活用した製品開発に従事しているデータサイエンティストです。G検定にも挑戦し合格することができました。今回は、私がなぜG検定に挑戦したのか、その理由と経緯についてお話ししたいと思います。
![general2023#2_regular.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356936/f2a5015b-185f-4c42-209c-638b6e3968a6.png)


# 私の経歴と業務内容
　私は、AI技術を活用した製品開発に従事しています。具体的には、AIを用いて様々な問題を解決するための新製品を開発しています。これには、データの収集、分析、モデルの設計と実装、そして最終的な製品の開発という一連のプロセスが含まれます。私の経歴については[こちら](https://qiita.com/yutut/items/d20aa4eb3660bf447fbb)、業務内容については[こちら](https://qiita.com/yutut/items/bbf5b946194cb9155012)をご覧ください。

# G検定とは
　G検定は、データサイエンティストとして必要な基礎知識を確認できる資格試験です。計学、確率論、情報理論、機械学習など、幅広い分野の知識が問われます。
※G検定特設サイトは[こちら](https://www.jdla.org/certificate/general/start/)

# G検定を受けようと思った理由
### 自己成長のため: 
　資格を取ることではなく、資格を取る過程でどれだけ有意義なものを得られるかが大事だと考えています。G検定は、その過程で得られる知識や経験が豊富であるため、自己成長の一環として挑戦し、合格することができました。
### 基礎知識の確認: 
　G検定は、自身の基礎知識を確認し、弱点を見つける絶好の機会です。これにより、自分の学習の方向性を見直すことができます。
### 新たな知識の獲得: 
　実務で使用していないAIの基礎知識を得ることができます。これにより、自分の知識の範囲を広げることができます。
※[AIマップより参照](https://www.ai-gakkai.or.jp/aimap/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356936/7e8e0a0e-e20d-1642-98a1-ccf34342d912.png)


### [CDLEコミュニティ](https://cdle.jp/about)への参加: 
　G検定を通じて、同じ境遇の仲間と情報交換をしたり、知識・経験が豊富な方と交流することで、視野を広げることができます。また、Hakkathonや勉強会に参加することで、自分が実務で使用しないデータやAI手法を使ったデータ分析の場に参加することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356936/81f0411b-9816-a47e-7247-b7fab4f8b1b5.png)
# G検定を受けることで得られるもの
　G検定を受けることで、自分自身の知識とスキルを確認し、さらには新たな知識を獲得することができます。また、G検定のコミュニティに参加することで、同じ目標を持つ仲間との交流や、新たな視点を得ることも可能です。これらは、データサイエンティストとしてのキャリアを進める上で非常に有益な経験となります。
【Flutter】FirebaseAuthで、「パスワードをお忘れの場合」のメールを送る

## やりたいこと
Flutter×FirebaseAuthでログイン管理をしているアプリで、メール認証のパスワードリセットのメールを送ることができるようにしたいです。
![Screenshot_20230728_001818.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/9cbea994-ca58-873f-4767-66615248cd55.png)

## 簡単にできました
FirebaseAuthでのログインはできるようになっている前提で、
以下を記載して、引数の "email" に送信先を渡すだけで、簡単にメールを送ることができました。メール送信はFirebaseAuth側で行なってくれるため、この部分だけであれば、メール送信の仕組みを作る必要がなく、パスワードの変更画面も、FirebaseAuthのデフォルトのものがあるので、これだけでパスワードリセットの仕組みができるようです。こちらはユーザーのパスワードを知らなくても良いのもとてもうれしいです。

```dart
FirebaseAuth.instance.sendPasswordResetEmail(email: targetEmail);
```

## メール文言を変更する
デフォルトのままですと、英語のデフォルトテンプレートで、メールが送信されてしまいます。
メールの内容をカスタマイズしたい場合は、Firebaseのプロジェクトで、
Authentication > Template > パスワードの再設定
から変更することができます。

## エラー処理を行う
存在しないユーザーの場合などの、エラー処理を行います。
パスワードリセットメールのメソッド（sendPasswordResetEmail）で発生するエラーコードの一覧は、こちらにまとまっています。

https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/sendPasswordResetEmail.html

私の場合は、以下のように、エラーコードによって、エラーメッセージをセットし、この後の部分でダイアログとして表示しています。

```dart
///パスワードリセットメール送信
    try {
      await FirebaseAuth.instance.sendPasswordResetEmail(email: targetEmail);
    } on FirebaseAuthException catch (e) {
      if (e.code == 'invalid-email') {
        ///無効なメールアドレス
        errorMessage = ErrorMessageList.inValidEmail;
      } else if (e.code == 'user-not-found') {
        ///ユーザーが存在しない
        errorMessage = ErrorMessageList.userNotFound;
      } else {
        ///その他の失敗
        errorMessage = ErrorMessageList.sendPasswordResetMailFail;
      }
    } on Exception {
      ///その他の失敗
      errorMessage = ErrorMessageList.sendPasswordResetMailFail;
    }
```



## 参考にさせていただいたサイト

https://zenn.dev/kazutxt/books/flutter_practice_introduction/viewer/30_chapter4_authentication

https://yaba-blog.com/flutter-firebase-password-reset/#:~:text=%E3%81%93%E3%81%AE%E6%99%82%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%82%8B%E3%83%A1%E3%83%BC%E3%83%AB%E3%81%AE%E6%96%87%E8%A8%80%E3%81%AFFirebase%E3%81%AE%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E7%94%BB%E9%9D%A2%E3%80%8CAuthentication%E2%86%92Templates%E2%86%92%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%81%AE%E5%86%8D%E8%A8%AD%E5%AE%9A%E3%80%8D%E3%81%A7%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82
Next.js+Goでキャリアの意思決定を投稿できるサービスをつくりました

# つくったもの
キャリアの意思決定があつまるサービス「Wellbi(ウェルビ)」をつくりました。
意思決定、入社・退職エントリ、ジョブチェンジ、転職体験談などキャリアに関するものならなんでも投稿できます。よかったら投稿してみてください〜〜><

https://wellbi.vercel.app

※PlanetScaleの無料プランの終了により今はトップページしか閲覧できなくなっておりますmm

# かかった期間
5ヶ月。
(企画〜デザイン〜開発〜リリース)

# つくってみてどうだった？
スポットでエンジニア友達に手伝ってもらったりはしたものの、ベース1人でサービスをつくりきるのは結構大変でした（もはや手伝ってもらった時点で個人開発ではないのかもしれない...）。つけたい機能があったり、UIをリッチにしたいなあと思ったりすることが多々ありますが、持ってるアセット・リソースとの相談なのでミニマムでリリースできるようにすることを心がけました。

# どこが大変だった？
フロント・バックエンドを1人で開発していくと自分の足りない技術が見えてくるので、そこのキャッチアップが大変でした。大変ですが「どうやって実装しよう？」と考え、自身の技術力と相談して形にしていくのは実際やってみると結構楽しいです。


# 使った技術を大公開！
## フロント： TypeScript+React+Next.js
特に理由はなかったのですが、せっかくReact使うならNext.jsにするか！くらいなノリです。Next.jsのルーティングは直感的なので結構好きです。あとはせっかくなのでTypeScriptにしました。

CSSフレームワークは最初は慣れていたStyledComponentsでしたが、emotionを経てtailwindに落ち着きました。

## バックエンド
### サーバーサイド言語: Go
バックエンドは慣れ親しんだ言語で実装しようと決めていました。RubyとGoは書いたことがありRuby暦の方が長いですが、もしスケールさせていきたいとなった時にやっぱり型があった方がいいなと思ったのでGoにしました。あとはGoの文法はシンプルを保ち表記揺れが起きにくく、書き手によってアウトプットに差が出にくいのでもしチーム開発することになっても有利だと思ったのも理由の１つです。

https://go.dev/

### サーバーサイドフレームワーク: echo
フレームワークはechoにしました。実務で使ったことがあったのでechoにしましたが特にこだわりはないです。他のフレームワークだとGinも気になります。

https://echo.labstack.com/

### DBライブラリ: GORM
使っていると意図しないSQLが生成されるケースに出くわし「なんでそういう挙動になるんだ？」ってなることがあり、個人的にはちょっと癖がある気がしていますが、なんだかんだ気に入っています。スターも多く、コミットも結構動きあります。

https://github.com/go-gorm/gorm


## インフラストラクチャー
### フロントのホスティング先: Vercel
Vercelは自分のWebサイト(Next.jsアプリ)を公開するときに使用したことがあり、デプロイがとても簡単でびっくりしました。Next.jsを開発しているのもVercel社ということもあり、相性を考えて一旦Vercelにしました。
Hobbyプランは無料なのでお手軽に始められるので便利です。

https://vercel.com/

### バックエンド(APIサーバ)のホスティング先: Render
デプロイが簡単で特別な構築も不要なので、開発に集中できます。

https://render.com/

Herokuが有料化しましたが、Renderには無料プランがあります。
以下の記事でHerokuとの比較・優位性について書いてありますが相当意識していることが分かりますね...！

https://render.com/render-vs-heroku-comparison

### データベース: PlanetScale
無料プランもありMySQLもいけます。
RDSだとお金かかっちゃうので選択肢としてPlanetScaleおすすめです。

https://planetscale.com/


### ファイルストレージ: Amazon S3
記事のヘッダー画像やプロフィール画像をアップロードする必要があり、そこまでコストがかからないS３にしました。

https://aws.amazon.com/jp/s3/

# 最後に
全部モダンなことやろうとしたり、慣れていない技術をたくさん選ぶとキャッチアップが大変でプロダクトをつくりきることハードルがぐっと上がるので、「1つだけ新しい技術を取り入れてみる」がちょうどいいんじゃないかなあと思います。
あとはつくってみて感じたことは自分自身まだまだ勉強が足りないなあと実感しました。やるぞ〜〜
最後までお読みくださりありがとうございました！！！
[Azure Databricks] コスト最適化の原則（翻訳）

# はじめに

https://learn.microsoft.com/ja-jp/azure/databricks/lakehouse-architecture/cost-optimization/

Azure Databricksのドキュメント（Microsoft Learn）で、本章がまだ日本語訳されていなかったため、DeepLで翻訳しました。

# コスト最適化の原則

この記事では、提供される価値を最大化する方法でコスト管理を可能にすることを目的とした、コスト最適化の柱のアーキテクチャ原則について説明します。予算がある場合、コスト効率はビジネス目標と投資収益率によって決定されます。コスト最適化の原則は、ビジネス目標とコスト正当化の両方を達成するのに役立ちます。

**Databricksのコスト最適化レイクハウスアーキテクチャ図**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/12544f2a-5c63-0732-c6e3-f0860cc2bae6.png)

## コスト最適化の原則

- 適切なリソースの選択

ビジネス目標に合致し、ワークロードのパフォーマンスを処理できる適切なリソースを選択します。新しいワークロードを導入する際には、さまざまな導入オプションを検討し、価格性能比が最も高いものを選択します。

- リソースの動的な割り当てと解放

パフォーマンス要件に合わせてリソースを動的に割り当て、解放します。未使用または使用率の低いリソースを特定し、再構成、統合、または停止します。

- コストの監視と制御

ワークロードのコストは、消費されるリソースの量と、それらのリソースに対して課金される料金に依存します。ワークロードのコストを把握するには、関係するリソースごとに監視します。これにより、消費とコストを制御するためのベースラインが得られます。

- 支出の分析と属性

レイクハウスでは、ワークロードの使用量とコストを簡単に正確に特定できます。これにより、個々のワークロード所有者への透明性の高いコスト配分が可能になります。これにより、投資収益率をメジャーで測定し、必要に応じてリソースを最適化してコストを削減できます。

- ワークロードを最適化し、スケーラブルなコストを実現

レイクハウスの主な利点は、ダイナミックに拡張できることです。まず、使用状況とパフォーマンス指標を分析し、インスタンスの初期数を決定します。自動スケーリングでは、変動が激しいワークロードに対してより小さなインスタンスを選択したり、必要なパフォーマンスレベルを達成するためにスケールアップではなくスケールアウトを行うことで、追加コストを削減できます。
【PHP】配列の1つ目のデータを取りたい

配列の中に値が1つ目の値を取得したい時どうしていますか？

## 配列の添え字
```php
echo $items[0];
```
### Reset関数
```php
echo reset($items);
```
### current関数
```php
echo current($items);
```
### ループ処理
正直する人いるのか不明ですが...
```php
foreach($items as $item) {
  echo $item;
  continue;
}
```
【Python】Bluetoothライブラリpybluezがインストールできないときの対処法

# import bluetoothを使いたい

どうやらC++の環境とWindows-SDKのインストールが必要らしい


https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/

1---↑のサイトからSDKをインストール

https://self-development.info/%E3%80%8Cmicrosoft-visual-c-14-0-or-greater-is-required-%E3%80%8D%E3%81%8C%E5%87%BA%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95/

2---↑のサイトを見てC++の環境とcl.exeの環境変数を設定する

https://github.com/pybluez/pybluez/releases

3---↑のサイトから生のライブラリをダウンロード

4---上記のライブラリのディレクトリにcdして
```console
python setup.py install
```
を実行する

5---
```python
import bluetooth
```
が使えるようになる
ESXiをvSphereの管理下に配置

## 環境情報
* ESXi 7.0.3
 6.3では配置出来なかったので、7.0.3にアップグレード行った。
* vCenter 8.0.1

左上のホストを右クリックするとメニューがプルダウンするので、新規データセンターをクリック。
名前を記載。
<img width="600" alt="vCenter下にESXi_1.PNG
" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/3dba9859-2601-87c1-da9b-13071f5a8754.png">

新規クラスタを作成する前にデポイメージをアップロードする。
左上の目次をプルダウンしてLifecycle Managerを選択。
アクションをプルダウンして「更新のインポート」をクリック。
<img width="600" alt="vCenter下にESXi_3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/121b420a-ac4e-8ef3-0e64-9f8d307c418e.png">

参照をクリックしてローカルからデポイメージを選択。
今回は「VMware-ESXi-8.0U1a-21813344-depot」をアップロード。
<img width="600" alt="vCenter下にESXi_4.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/90179d59-de5e-0c8d-ab49-97a70bbd1750.png">

アップロード完了
<img width="600" alt="vCenter下にESXi_5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/88c01368-e91f-2a17-b3eb-c7f9025edf92.png">

再びホスト画面に戻り
作成したデータセンターを右クリックしてメニューをプルダウンし、新規クラスタをクリック。
<img width="600" alt="vCenter下にESXi_2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/c19306d7-a145-37ad-856a-f20cb8871047.png">

名前だけを記載して、デフォルトのまま「次へ」をクリック。
<img width="600" alt="vCenter下にESXi_2.1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/db7d5472-f999-fd3c-f58a-c8090ba46794.png">

デフォルトのまま「次へ」をクリック。
<img width="600" alt="vCenter下にESXi_2.2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/2bd89356-cc10-67e0-5ebd-549427afd22d.png">

「完了」をクリック。
<img width="600" alt="vCenter下にESXi_2.3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/55a14bd7-4abc-b81e-b462-f49a7c4848f1.png">

クイックスタートは使わないため、左のスキップをクリック。
<img width="600" alt="vCenter下にESXi_7.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/8942e796-2b5a-9335-07b4-253c8d7a419a.png">

クラスタ編集の画面。マシンにあった設定に合わせる。
<img width="600" alt="vCenter下にESXi_8.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/4fadd027-c951-7178-d1ed-2218504cb5ca.png">

再びインベントリのホストの画面に戻り、クラスタを右クリックしてプルダウンした中から「ホストの追加」をクリック。
ここでvCenter管理下となるESXiのipアドレス、ユーザ名、パスワードを記載する。
<img width="600" alt="vCenter下にESXi_9.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/cfa9a494-8467-3ab0-9f08-2e5941830660.png">

無視してOK
<img width="600" alt="vCenter下にESXi_12.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/a7ff973e-a521-af88-d7b2-155ddf5b9aeb.png">

OKをクリック。
<img width="600" alt="vCenter下にESXi_13.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/38edb8e6-47f9-b839-e1a4-b5a0129e3b19.png">

「イメージをインポートしない」にチェックをいれて「次へ」をクリック。
<img width="600" alt="vCenter下にESXi_14.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/6c896216-566c-a8b9-f1b2-4d5abeb4ad37.png">

完了。
これでvCenterの管理下にESXiホストが配置される。
<img width="600" alt="vCenter下にESXi_15.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/c03bda2c-20ac-557f-58ac-8a3cd2ff94d5.png">
push時にJestを実行する【Lefthook】

## パッケージのインストール
以下のコマンドを実行して`Lefthook`をインストールします。
```:ターミナル
$ yarn add -D lefthook
```

## Lefthookの設定
Lefthookの設定をします。
`lefthook.yml`を作成し、以下のように記述します。
```lefthook.yml
pre-push:
  commands:
    jest:
      glob: 'src/*.{js,jsx,ts,tsx}'
      env:
        NODE_ENV: test
      run: yarn jest --findRelatedTests {push_files}
      fail_text: 'Read the report above.'
```

## 動作確認
以下のコマンドを実行し、正常に動作するか確認します。
```:ターミナル
＄ npx lefthook install && npx lefthook run pre-commit
```
Studio WebでZoomの会議を予約してみた～出力値ってどんな感じ？？？～

## はじめに
①本記事は、2023年7月開催の「UiPathブログ 発信チャレンジサマー」の27日目のブログです。
ブログの詳細、参加方法については以下のブログを参照ください。

https://note.com/shumpei_w/n/nd082bdf28853

②このブログ情報は、2023/7時点の情報です。
③UiPathはStudio Webを使用しています。
④ZoomのサポートのVersion？は1.888.799.9666です。
⑤本ブログで記載していますZoomのミーティングIDやURLが登場しますが、本記事内で紹介するために書いているだけで実際に接続することはできません。ご了承ください。

## 前回のあらすじ
Studio WebでZoomの会議設定ができるのか確かめたい！という筆者は、「1回のミーティングをスケジュール」アクティビティを使って実行した結果、会議予定を設定することができました。
おさらいはこちら↓

https://qiita.com/saosao885/items/8704400b9f715b8c0b26


スケジュールを設定して実行してみたら本当に会議スケジュールができた！すごっ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/555a147b-4704-aaff-ddfa-6732eedbdead.png)
証拠にZoomの画面を見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/e975f982-c321-ebdf-adf6-9959a31d9d1d.png)
確かに設定できていました！

では、「1回のミーティングをスケジュール」アクティビティの出力欄についてですが、前回の記事で長くなりそうだった為に触れることができなかったので今回は出力欄について覗いてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/f6d410d6-efe4-e1ac-e4ea-9e22359ee309.png)


## 出力できる値
現時点で出力できるのは以下の値です。
・ミーティングID
・パスコードまたは暗号化されたパスワード
・開始URL
・参加URL(招待URL)

まあ出力された値をログへ出力させてみる為、まずは会議の予約を入れてみましょう。
会議タイトル(トピック)は「MBA_研究計画書添削」、ほかに日時を設定して実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/c5287315-c0c9-cb66-cda0-a258a9a621f2.png)

結果は...できましたね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/451f3edd-5f4f-92e7-3f98-7aafd6abd619.png)

ということで中身があっているのか、ログの情報と出力の中身と照合してみましょう。
(セキュリティ上の都合により、パスワードは紹介のみで画像での表示はしません。ご了承ください。)

### ミーティングID
ミーティングIDですが、こちらはNullable型となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/45a18026-8432-751e-266d-a3f137d9a9bf.png)
Nullable？という方は馴染みがない！という人も多いと思いますが、簡単にいうとnull(値が無効になっている)ものを取得したいときに使いますという感じで覚えておきましょう。(筆者も調べたが説明が難しい...)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/f674da5d-cdba-f779-d2d9-70670027c2b7.png)
もしログに出したい場合はNullable変数(引数)に「.Value」で出せるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/70d96e83-3f4b-e544-1d13-04b2485e4e2e.png)

### パスワード(パスコード)、暗号化されたパスワード
セキュリティの兼ね合いで出しませんが、どちらもString型変数を設定できます。
(暗号化...のほうはSecureStringではない点に疑問は残りますが)


### 開始URL
ホスト(会議を設定した人とします)がミーティングを起動する際のURLですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/406c17d4-1a39-b6aa-697d-9e391588de52.png)


### 参加URL
これはZoomで言う"招待リンク"のことですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/eecb7661-cafa-e7da-39f7-ba649eb87d5c.png)

## まとめ
Zoomの出力にNullable型が出て「？」の人もいらっしゃると思います。Nullable型を詳しく&わかりやすい説明ができる方、ぜひ教えてください！
またミーティング開始と参加のURLも取得できますし、利便性はいいと思いました。

ミーティング周りのアクティビティはほかにもありますので、また調べてみます！
最後までお読みいただきありがとうございました。
WindowsでNuxt3のプロジェクトを始める

1. [nuxtのサイト](https://nuxt.com/)にアクセスする
1. FVエリアに「[Get Started](https://nuxt.com/docs/getting-started/installation)」とあるのでそこから始める
1. 気になっていたnodeバージョン、どうなっているのかと思うと、`Node.js - v16.10.0 or newer`の記載あり
    1. [nvm-windows](https://github.com/coreybutler/nvm-windows/releases)を使ってnode.js推奨版をインストールする
    1. `nvm install lts`これで推奨版インストールできる
1. あとは「2」にある通りに進むだけ

ふむ。
もう少し困るかと思っていたけれどスムーズにインストールできて良かった。
エラー読むのって大事。Laravelのコントローラのclassを重複していた話

### ユーザーがレビューを投稿できる様になった！嬉しい！

ということで本日はちょびっとしか進みませんでした。。
レビュー投稿画面の作成とデータベースへの投稿、ビューへの表示。
これが実装できましたが、、

それしか実装できなかったのじゃ。

### 今日はエラーを真剣に読んだ日
今まではエラーが出るとそっこーでググったり、GPTたんにぶち込んでいましたが、
「エラー読んでみっか！」
と思いGPTを封印してやってみました。

大変やで、、、GPTパワーすごかったんだなと。

これからはエラーを読む癖もつけていきますわ。

### 今日あったエラー
```
Target class [App\Http\Controllers\ReviewController] does not exist.
コントローラが存在していません。
```
というエラーで2時間くらい詰まっていました。

結論から言えば、
class Contorollerを別のファイルで2つ作っていたことが原因でした。

ですが、それに辿り着くまでに、
コードがおかしいのか、、、
文法のミスなのか、、、
ルートのミスなのか、、、
モデルなのか、、、
ビューなのか、、、
コントローラのなんか他のところなのか、、、

という感じにめちゃんこ遠回りして一服して帰ってきたらそっこー解決しました。

休憩大事！

### まとめ
## コントローラは存在してたじゃあねえか！！！


おわり
カメラのセンサーを自分で掃除した話

NIKON-D750を新品で購入してから7年が経過。
月に1度くらいの頻度で使用してきたが、
最近画像の汚れが目立ってきた。

なんでも自分でやらないと気が済まない性分なので、
クリーニングキットを購入して自分で掃除してみることに。

まずは、汚れ具合を確認。先人たちの記事を参考に、
適当なレンズを取り付けて以下の条件で白壁をパシャリ。

　・ISO感度低め（250くらい）
　・絞り値高め（F22くらい）
　・手振れ補正：OFF

こうすることで、真っ白な写真が撮れるわけだが、
センサ表面に付着したゴミだけが像として現れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521616/d1b52d90-1dfe-f652-4dad-f61ae9f63f65.png)
図1. クリーニング前のカメラで撮影した画像
（LightRoomの画像加工により汚れを強調している）

クリーニングキットとしては以下のものを用いた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521616/c7efe857-fea6-fbc7-184a-e56d17f5040b.png)

https://www.amazon.co.jp/gp/product/B09BFHDNQT/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&th=1

20本くらい入っていたスワブのほぼすべてを使用して
センサを清掃。「1本のスワブは1往復まで」が原則らしいが、
なかなかゴミが取り切れないので、ゴシゴシ...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521616/0582e1a9-19f5-aa39-bab2-38b6ae16fc9c.png)
図2. 使い終わったスワブたち


清掃後、白壁を撮影してもゴミの像が出ていないことがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521616/30947c3f-5fc7-86cf-e90f-df4efcb1a991.png)
図3. クリーニング後のカメラで撮影した画像
（図1と同じように画像を加工している）



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521616/a09816b2-ec52-b0cc-dc46-7caf52b6c8c1.png)
図4. 清掃後のカメラ

適当な写真を撮って、きれいに映っていることを確認できたので、
一応成功かな。

（おわり）
AiFlowと DAG内でできるタスク生成について超ざっくり書いてみる


# AirFlowとは？
一言で表すと　**実行タスクのワークフロー管理プラットフォーム**です。
対応言語はPythonのみです。（2023/07時点）

「DAG」と呼ばれる、AirFlow上でPythonコードを実行するための書き方を使用してます。
もう少し詳しく書くと、
Pythonコード内で処理タスクを生成し、各タスクに依存関係を持たせます。
AirFlowはワークフローを管理してるので、「DAG」で定義されたタスクを順番に実行している、ということです^^


# タスクの生成
処理したい内容によって、**動的**にタスクを生成、**静的**にタスクを生成することを使い分けましょう。

##### 静的にタスクを生成したい場合
主に日次で動かすチェック処理や、スナップショット作成や、簡単な単体テストで用いることが多いです。
　・処理の内容が固定で決まっている場合
　・処理するデータが単一の場合

##### 動的にタスクを生成したい場合
外部から複数データが連携される場合や、洗い替えDBの登録データ数に応じてなど、ユーザー起因で処理が実行されるケースで用いることが多いです。
　・処理の内容が固定ではなく変動的である場合
　・処理するデータが複数の場合
　
# AirFlow Operatorを使用しよう
DAG内でタスクを生成する際には、AirFlow Operatorを使用します。

##### AirFlow Operatorとは、
DAG内で定義できるOperatorです。
処理の用途ごとに様々なOperatorがあります。
ベースとなってくる基本Operatorは`BaseOperator`です。

多くのOperatorはBaseOperatorを継承しており、再帰的にメソッドの使用が可能です。

使用できるパラメーターや値などは公式ドキュメントをご参考ください。
https://airflow.apache.org/docs/apache-airflow/stable/_api/airflow/models/baseoperator/index.html

イメージとしては以下のような構成となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3389633/00389134-009c-109a-16fc-ab4dc9e6ad58.png)


# 依存関係を定義

DAG内にタスクを生成をしたら、どの順番でタスクを実行するのか定義します。

例）
```
# 依存関係

Check_task >> Data_Delete_task >> Data_Insert_task >> Create_File_task >> done_all_task
```

タスクとタスクの間は` >> `で繋げます。

またタスクの依存関係を定義する際にIF文を使用することも可能です。

例）
```
# 分岐結果による依存関係

# ファイルカウント数が0件以上の場合
IF file_count > 0:
    Data_Insert_task >> Create_File_task >> done_all_task

# ファイルカウント数が0件の場合
IF file_count = 0:
    done_all_task


```

依存関係を定義したら実際にAirFlowにアップロードして動作を確認しましょう。


以上がAirFlowDAGでできるタスク生成の大まかな流れとなります。
AirFlowDAGについてこれから少しずつ記事を書いていこうかと思います。
sqlxのバージョンを0.6 -> 0.7系にあげた

## 環境
- Rust 1.69
- sqlx 0.6
- actix-web 4

## 概要
sqlxの0.7系が最近公開された。  
バージョン上げてみたので、作業ログを残しておく。

## アップデートするメリット
### sqlx-data.jsonの廃止
sqlxでは `query!` のようなマクロを使ってクエリを書くと、マッピング型やSQLミスなどをチェックするためにビルド時にデータベースへ接続しにいって確認してくれる。エラーの場合はビルドエラーとなる。
CI時などは、直接データベースにつなぎにいくのは難しい(できなくはないが)ので、直接データベースつなぎにいくのではなく、クエリとテーブルの情報を `sqlx-data.json` のファイルに出力しておいて、データベースを直接参照できない場合は、自動的にそちらを参照しにいってくれる。

0.6系の場合は、この`sqlx-data.json`が1ファイルだったため、プロジェクト内の全クエリ(query!など)の内容がこのファイルに出力されてしまい、git上で激しく毎回コンフリクトを起こしている始末だった。
0.7では、このjsonファイルがクエリ毎にバラバラに `.sqlx`ディレクトリに出力されるようになり、git上でコンフリクトする確率がグッと減った。

## 変更箇所
0.6 -> 0.7は破壊的な変更が入っているようで、単純に0.7にしてもビルドエラーとなった。  
今回修正したところは以下となる。  
全容は[公式のChangeLog](https://github.com/launchbadge/sqlx/blob/main/CHANGELOG.md#070---2023-06-30)をみてください。

### cargo.toml
sqlxのfeaturesに指定する項目名が変わった。
- `decimal` -> `rust_decimal`
- `offline` -> 指定する必要がない(デフォルトでサポートされる)
- `runtime-actix-native-tls` -> `tls-native-tls`, `runtime-tokio` の2つになった

### コードの変更
コネクション、トランザクション周りが変わったようでそのあたりでエラーになった。  
とりあえずは `&mut *tx` や `&mut tx` のように渡していた箇所を `&mut **tx`や `tx.deref_mut()`のように1つ今までより多くderefしてあげればビルドエラーが解消された。

### .sqlxディレクトリの出力
```bash
$ cargo sqlx prepare --workspace
```
を実行する。  
~~wsl環境ではdocker側で上記実行してもうまくいかなかった。  
(しっかり検証していないが権限周りかもしれない)~~
動きました。
`.sqlx`ディレクトリはgit管理に含めること

## 備考
地味にderefするやつが変更箇所がすごい多くて大変。
SFTPのログ出力設定【Amazon Linux2】

# ■概要
Amazon Linux2にて行った設定です。
ご参考になれば！

# ■手順
#### 1.syslogに出力された内容をファイルへ出力するようにsyslogのコンフィグに追記する

```
# vi /etc/rsyslog.conf

# This rule to save the log output of sftp
local5.* /var/log/sftp.log
```

#### 2.出力先ファイルを予め作成しておく

```
touch /var/log/sftp.log
```

#### 3.rsyslog.confを反映させるためrsyslogのデーモンを再起動する

```
systemctl restart rsyslog
```

#### 4.opensshの設定ファイルを変更してsftpの操作ログをsyslogに出力するように編集する

```
# vi /etc/ssh/sshd_config
```

↓

```
Subsystem sftp /usr/libexec/openssh/sftp-server
```

という行があるので、 -f LOCAL5 -l VERBOSE、を後ろに追記して、

```
 Subsystem sftp /usr/libexec/openssh/sftp-server -f LOCAL5 -l VERBOSE
```

となるようにする。

#### 5.設定反映のためsshのデーモンを再起動する

ミスるとSSH出来なくなるので、下記の手順で構文チェックもしましょう。
まずsshdのフルパスをチェックする

```
# which sshd
/usr/sbin/sshd
```

以下実行して何も出なければOK
sshd_configファイルの構文チェックです。

```
# /usr/sbin/sshd -t
```

デーモン再起動

```
# systemctl restart sshd
```

#### 6.WinSCPでテスト接続、ログが出るか確認

接続しただけで以下のようなログが出ます。

```
[root@ip-172-31-3-xx log]# tail sftp.log
Jul 26 12:07:13 ip-172-31-3-xx sftp-server[32335]: session opened for local user ec2-user from [116.58.xxx.xxx]
Jul 26 12:07:13 ip-172-31-3-xx sftp-server[32335]: received client version 6
Jul 26 12:07:13 ip-172-31-3-xx sftp-server[32335]: realpath "."
Jul 26 12:07:13 ip-172-31-3-xx sftp-server[32335]: opendir "/home/ec2-user"
Jul 26 12:07:15 ip-172-31-3-xx sftp-server[32335]: closedir "/home/ec2-user"
```

#### 7.任意でログファイルのローテート設定を行う
かなり膨大になるので何かしら設定した方がよいでしょう。

```
# vi /etc/logrotate.d/syslog
/var/log/sftp.log
```

以上です！
Amazon Linux2のApacheにLet's Encrypt でHTTPS化

# 手順
### リポジトリとソフトウェアのインストール
amazon-linux-extrasでリポジトリのepel(Extra Package for Enterprise Linux)をインストールしました。
その後、certbot-apacheソフトウェアをインストールしました。
```bash
sudo amazon-linux-extras install epel
sudo yum install certbot-apache
```
> 参考
> https://serverfault.com/questions/903780/how-to-install-certbot-on-amazon-linux-ec2

### certbotの実行
```bash 
sudo certbot --apache #オプションでcertonlyをつけて書き換え自身は自分で行うようにすることもできるみたいです
```
上記で実行して質問に答えたら終了!!
と思ったら、、、
```bash
To fix these errors, please make sure that your domain name was entered correctly and the DNS A/AAAA record(s) for that domain contain(s) the right IP address. Additionally, please check that your computer has a publicly routable IP address and that no firewalls are preventing the server from communicating with the client. If you're using the webroot plugin, you should also verify that you are serving files from the webroot path you provided.    
```
エラー発生！！

### エラー解決
結論、EC2のインバウンドルールにHTTPのAnywhereを追加して誰でもアクセスできるようにすれば解決できました。

最初見たとき、EC2サーバ自身からドメインに対して問い合わせを行っていると思い、インバウンドルールにEC2のpublic IPを登録したのですが、そうではなく、Let's Encrypt 側からEC2にHTTPアクセスしているみたいです。

### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893794/c91fe045-da7e-1aca-1442-5d2bf19a4883.png)
上記のように中間証明書の署名とルート証明書の署名をもらうことができました。
[解説] なぜ、ソフトウェアアーキテクチャは重要なのか？ 基本原理と設計手法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521573/a5dfe3de-38aa-8a78-9c8a-1ff8b98a304f.png)
## ソフトウェアアーキテクチャの定義

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521573/78928204-ac0c-a8f1-b143-2bb788204b58.png)

ソフトウェアアーキテクチャとは、システムの構造、行動、品質属性や設計原理などを含んだ高レベルの設計であり、非機能要件を確保しながらシステムの要件を満たすための基盤です。これらは、一般的なアーキテクチャパターンやアーキテクチャスタイルをベースに、対象システムの要件に合わせてカスタマイズされることで設計されます。そして、アーキテクチャ設計の目指すところは、これらのパターンやスタイルを参考にし、さらに抽象化された要件に最適化したアーキテクチャを策定することです。

一部の人々は、この定義があいまいであると主張するかもしれません。それは、ソフトウェアアーキテクチャという用語が、特定の状況における設計の詳細な視点から、全体のシステム設計まで、非常に広範にわたる可能性があるからです。しかし、その多面性がソフトウェアアーキテクチャの価値と強さを表しています。

https://note.com/happyodangoo/n/nafb18cc59648

## ソフトウェアアーキテクチャの目的

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521573/f6445495-ed3d-4f50-9150-fc2a317374f6.png)

ソフトウェアアーキテクチャの主な目的は2つあります。1つ目は、将来的なシステムの変更や拡張を考慮に入れた設計を行い、変化への対応力を高めることです。これは、ソフトウェアが一度開発された後も常に進化し続けることを意識した考え方で、新たな要件や技術の進化に迅速に対応できるような柔軟性を保証するものです。

2つ目の目的は、ソフトウェアの品質を確保することです。これにはパフォーマンス、保守性、信頼性などの非機能要件が含まれます。アーキテクチャは初期の設計段階でこれらの品質を保証するための仕組みを提供します。

これらの目的を達成するためには、ソフトウェアアーキテクチャはシステム開発の初期段階で次のことを行います。

- 将来的な変更や拡張に対する柔軟性を確保する
- パフォーマンス、保守性、信頼性などのシステム品質を設計段階で担保する

## ソフトウェアアーキテクチャの構成要素

ソフトウェアアーキテクチャの構成要素を具体的に見ていきましょう。これらは品質属性（非機能要件）、構造、そしてルールとガイドラインの3つです。

品質属性は、パフォーマンスや保守性、拡張性といったシステムが備えるべき特性を定義します。例えば、どの程度のレスポンスタイムが必要なのか、どの程度の規模までシステムが拡張可能であるべきなのか、どのようなメンテナンスが可能であるべきなのか、といった品質を具体的に示します。

次に構造は、システムの論理的または物理的な配置を示します。これには、システムを構成するコンポーネントの設計や、それらの間の関連性、モジュールの分割といった要素が含まれます。

そして最後の要素はルールとガイドラインで、これはソフトウェア開発を遂行するための基本的な指針を示します。例えば、コーディング規約、テスト方針などがこれに該当します。

これら3つの要素を総合的に設計することが、ソフトウェアアーキテクチャ設計の本質と言えます。対象システムの目的と要件に合わせて、これら3つの要素を適切にバランスさせて設計することが求められます。

## アーキテクチャスタイルとの関係

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521573/6f75539e-069a-b22c-d26e-c5fb10dcbc98.png)

ソフトウェアアーキテクチャは、一般的にアーキテクチャスタイルを基に設計されます。アーキテクチャスタイルは一種のテンプレートで、設計パターンの一種とも考えられます。例えば、クライアント・サーバー、ピアツーピア、レイヤード、パイプ&フィルターなど、多くのアーキテクチャスタイルが存在します。

これらのスタイルを適切に選択し組み合わせることで、システムの特性や要件に合ったソフトウェアアーキテクチャを設計することができます。選択するアーキテクチャスタイルによって、ソフトウェアの振る舞いや品質属性が大きく影響を受けるため、慎重な選択と設計が求められます。

## ソフトウェアアーキテクチャの重要性

ソフトウェアアーキテクチャの重要性については、数々の実例があります。ここでは、一つの失敗談を共有しましょう。

ある企業が大規模なソフトウェアシステムの開発を進めていました。彼らの目標は、社内の複数の業務を一つのシステムで管理することで、業務効率を大幅に向上させることでした。しかし、このシステムの初期設計段階でソフトウェアアーキテクチャの重要性が見落とされてしまったため、結果的に大きな問題が発生しました。

このシステムの設計では、特定の業務に特化したモジュールが多数作られ、それぞれが別々に開発されました。しかし、全体のアーキテクチャ設計がなされていなかったため、これらのモジュールが互いに独立していて連携が取れず、統合したときに各モジュール間でデータの共有や通信がうまく行わないという問題が発生しました。

この問題を解決するために、追加のコードを書いて各モジュールを繋げようとしましたが、これによって新たな問題が発生。コードが複雑化し、バグが頻発するようになりました。結果的に、このシステムは大幅に遅延し、予算も大幅にオーバー。さらに、システムが完成したときには、その複雑さからメンテナンスや改修が難しく、期待されていた効率向上も実現できませんでした。

このエピソードから学べることは、ソフトウェアアーキテクチャがソフトウェア開発プロジェクト全体の成功に大きな影響を与えるということです。初期の設計段階で全体の構造や、各部分がどのように連携するかをしっかりと設計することで、開発の途中で発生する可能性のある問題を大幅に減らすことができます。また、保守性や拡張性を考慮したアーキテクチャ設計は、システムが完成した後も大きな価値を提供します。


https://note.com/happyodangoo/n/n2dea5122dfdc
インラインアセンブラ 小物 その1 w/Arduino  @ Nucleo G070RB

- Nucleo G070RB
- Arduino IDE 2.1.1
- STM32 MCU based boards 2.5.0
- Generic STM32G0 series

# PA5 を H にする

```cpp:main.ino
void setup() {
  pinMode(PA5, OUTPUT);

  const uint32_t bsrr = (uint32_t)&GPIOA->BSRR;

  asm volatile(
    "MOV r1, #(1 << 5) \r\n"
    "STR r1, [%[bsrr]] \r\n"
    :
    : [bsrr] "r"(bsrr)
    : "r1"
    );
}

void loop() {
}
```

- アセンブラ部分を最小にするため，ピン設定は Arduino で行いました。
- NUCLEOではLEDが点灯します。
- BSRRのアドレスは `stm32g071xx.h` の定義を拝借する方法を取りました。
- `STR`で即値を書く手段がないようです。なのでここでは `r1` を使用するレジスタとして宣言しています。

# PC13の値を読む

```cpp:main.ino
void setup() {

  Serial.begin(9600);
  while (!Serial) {}
  Serial.println("Boot NUCLEO G070");

  pinMode(PC13, INPUT);

  uint32_t out;

  asm volatile(
    "GPIOC_IDR = 0x50000810 \r\n" // GPIOC->IDR のアドレスになまえをつけておく
    "LDR r1, =GPIOC_IDR \r\n"     // r1 に GPIOC->IDR のアドレスを代入
    "LDR r1, [r1] \r\n"           // アドレス r1 の値を r1 にロード
    "LSR r1, #13 \r\n"            // r1 を 13ビット右シフト
    "MOV %[out], #1 \r\n"         // 0b1 と
    "AND %[out], r1 \r\n"         // AND をとって %[out] で返す
    : [out] "=r" (out) // 結果を収めるレジスタ
    : 
    : "r1"             // 使うレジスタ
    );
  
  Serial.print("Result: ");
  Serial.println(out,HEX);
}

void loop() {
}

```

- レジスタアドレスを指定する方法として，最初の例では `asm` の外から与えましたが，ここではインラインアセンブラ内で行ってみました。
- レジスタ r1 に定数を書くだけなら `MOV` とか使えそうですが，その場合は8ビットまでのようです。そのため，webで探して `LDR Rd,=const という疑似命令` を使ってみました。プログラミングマニュアル PM0223.pdf では見つからなかった...

思ったより長くなってしまいましたね...


参考：

- https://noritan-micon.blog.ss-blog.jp/2015-06-07
戻るボタン実装時の(popUpToやpopUpToInclusive)

## わからなかったこと
Android公式のトレーニング（[Android Kotlin Fundamentals: 03.2 Define navigation paths](https://developer.android.com/codelabs/kotlin-android-training-add-navigation#6)）
7. Task: Change the Back button's destination
のStep1

そこで、lose画面から戻るキーを押すと、なぜ、titleに行くのかわからない。
バックスタックから、title,gameが削除されたのであれば、アプリが終了するのでは？と思っていた。
	
## 解決
popUpToを設定すると、戻るを押したときにその画面に遷移するようになる。（＝指定したフラグメントの次以降のバックスタックをすべて削除）	

inclusiveを設定すると、popUpToで指定した画面の一つ前の画面に遷移するようになる（＝指定したフラグメント以降のバックスタックをすべて削除）


参考記事（ありがとうございました。）
https://star-zero.medium.com/navigation%E3%81%AE%E6%88%BB%E3%82%8B%E5%88%B6%E5%BE%A1-c469a5225e97

## 混乱した原因
AndroidDeveloperを日本語訳して読んでいたからか、popupToの挙動の理解を誤っていた。
どうしても挙動と説明が合わない場合には、ちゃんと英語を読もう・・・
仮想記憶管理

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/3c361d35-8373-98d6-f2f5-a4f0d72dbe5d.png)　
仮想記憶管理によって、主記憶の容量以上の領域が使えるようになります。例えば、パソコンに１Gバイトの主記憶が搭載されているとしましょう。仮想記憶管理によって、４Gバイトでも８Gバイトでも使えるようになります。仮想記憶管理があれば、メモリ不足でプログラムが動作しないという心配がなくなるのです。

１：ページング方式
　コンピュータに実際に搭載されている主記憶の領域を実記憶空間と言います。一方で、OSがプログラムに見せているメモリ領域を仮想記憶空間と言います。実記憶空間よりも大きなサイズの仮想記憶空間を見せることで、プログラムでは、主記憶の容量以上のメモリ領域を使うことができます。
　OSでは、サイズの小さな実機置く空間をやりくりして、サイズの大きな仮想記憶空間が実在するかのように振る舞います。ページング方式は、実記憶空間をやりくりする方法の一つです。ページング方式では、実記憶空間と仮想記憶空間をページと呼ばれる一定サイズに区切りページ単位で管理します。
　実行するページが実記憶空間に存在しないことをページフォルト、実記憶空間にページを入れることをページインと言います。
　ページインを行うときに、実空間に空きがない場合もあります。この場合には、最も不要と思われるページを一旦補助記憶装置（ハードディスクやSSD）に待避させて空きをつくってからページインを行います。ページを補助記憶装置に退避させることをページアウトと言います。

２：ページ置き換えアリゴリズム
　ページアウトを行う際には、実記憶空間の中で最も不要と思われるページを選んでページアウトします。どうれを選ぶのかを決める方法がページ置き換えアルゴリズムです。代表的なページ置き換えアルゴリズムとは
①LRU(Least Recently Used)：最後にアクセスしてから、最も長い時間経過しているページを選ぶ。

②FIFO(First In　First Out)：最初にページインさせたページを選ぶ。

　LRUは、例えば、何年もの間使わずに、押入れの奥でホコリをかぶっているものを選んで捨てるということと同じ考え方です；。

３：スラッシング
　実記憶空間（主記憶の容量）が仮想記憶空間に比べて、極端に小さいと、ページインとページアウトを頻繁に繰り返す現象が発生します。この結果、補助記憶装置に頻繁にアクセスするようになり、システム全体の性能が極端に低下します。これをスラッシングと言います。スラッシングが発生する場合、プログラムの同時起動数を減らしたり、主記憶を増設して容量を増やしたちする必要があります。