OmniAICreator/Qiita-1.07M huggingface dataset:
イベントログ7036問題とその解決方法

# 概要
イベントログに、サービスの開始と終了を表す7036が大量に記録されるというものです。
環境によっては7042も記録される場合があります。

# とりあえず解決したい

- 以下の内容のregファイルをインポートする

```
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ScEvents]
"7036"=dword:00000000
"7042"=dword:00000000
```

- 管理者権限のコマンドプロンプトまたはPowerShellでregコマンドを使用する

```
>reg add HKLM\SYSTEM\CurrentControlSet\Control\ScEvents /v 7036 /t REG_DWORD /d 0 /f
>reg add HKLM\SYSTEM\CurrentControlSet\Control\ScEvents /v 7042 /t REG_DWORD /d 0 /f
```

この作業を行った後に再起動すると反映されます。

# どうしてこうなるの？

Windows Vistaや同系統のWindows Server 2008から実装されたもので、サービスの起動や終了のたびに逐次その旨をイベントログに記録していく仕様が追加されたものです。

本来であればWindows Server 2008以降のServer系エディションでのみ記録されるようになっています。

しかし、インターネットで検索したところWindows 7などClient系エディションでもServer系エディションと同じくサービスの起動と終了ログが大量に記録される事例[^1]が散見されました。

[^1]:["Service Control Manager" 7036 - Google 検索](https://www.google.com/search?q=%22Service+Control+Manager%22+7036)など

# サービスの起動と終了のログって？

- イベントソースがService Control Manager
- IDが7036または7042

これらのログの事を指します。

## 7036はサービスの動作状態の変更

サービス側の`SetServiceStatus`APIによって動作状態が変更されたことを表します。

## 7042はサービスの動作状態を変更する要求

管理コンソールのサービススナップインからの操作や`net start service`、`net stop service`など、サービス外の`ControlService`APIによって停止や再起動の要求がなされたことを表します。

# 解決方法は？
冒頭のレジストリ編集で解決できます。
また、応用として、IDが7000番台のイベントログを有効化することも出来ます。
有効化は単にDWORD値を0から1にするだけです。

# 動作のメカニズムについて
システムの起動時、正確にはサービスを管理するプロセス`services.exe`が起動されたときに、`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ScEvents`を参照し、`ScEvents`の中にある全ての値をスキャンします。

スキャン中に以下の条件を満たす値があればその値をチェックします。
- 値の名前がイベントIDの10進表記
- 7000番台
- 値のサイズが4バイト(※4バイトの値であればどの型でもかまいませんが、通常はDWORD値です)

その値が1になっていれば、該当するイベントIDが記録されます。
0であれば抑制するようになります。

このスキャン処理は初期化段階で一度だけ呼ばれるのみで、以降は再起動されるまでその状態を維持します。
したがって、`ScEvents`の内容を変更した場合は再起動しなければなりません。

# 何故この記事を書いたのか

以前にツイッター[^2]で解決方法を掲載したのだが、一年経っても検索結果に現れず。
希少な事象ほど検索しても見つかりにくいという事なのだろうか。

インターネットの検索結果[^1]で解決策を調べようとしても、ID:7036はエラーや警告では無いから無視してもいいだとか、それならまだマシな方。

検索結果のリンクを一つ一つチェックしていたところ、何か適当なことでも書いておけばいいだろう精神で量産されたであろう記事[^3]が検索結果のトップに近い位置に出てきた。
確認したのだが、さんざん無関係なトラブルシューティング手順をダラダラと書き並べ、剰え『まだ直りませんか？修復ツールをダウンロードして実行します』で締めくくられていて、問題を解決させる気が無い記事に失望した。

真面目に困っている人に失礼だ、というのがこの記事を書いた目的です。

[^2]:https://twitter.com/a1lic/status/1539434413729017856
[^3]:Event ID 7036: What Does It Mean & How to Fix It - windowsreport.com/event-id-7036/ ※読むだけ時間の無駄なのでリンクは張りません
CodeShare.io使い方


自分用メモ

<h1>登録</h1>
<a href="https://codeshare.io/">CodeShare.io</a>にアクセスして、名前とメールアドレスとパスワードを設定するだけ


<h1>使い方</h1>
Create a new CodeShareを選択すると、一意なURLが作られ、エディタが立ち上がる。

↓
URLを共有することで、他人とコードを共有しながら開発を行え、レビューなどを受けることができる！
ビデオ通話機能もあり、みんなでワイワイとコード開発ができる！
Go言語とメモリ: 確保と保存の理解

## はじめに

Go言語の学習中にメモリについてつまづきました。そのことについて整理するためにこの記事を投稿します。この記事では、Go言語でのメモリの「確保」と「保存」に焦点を当てます。

## メモリについて意識する場面とは

例えば`json.Unmarshal`と`json.Marshal`関数か`json.NewDecoder`と`json.NewEncoder`関数のどちらを使用するかについてです。`json.Unmarshal`と`json.Marshal`は、メモリにすでに全体が読み込まれているJSONデータを処理する際に適しています。これは、JSONのサイズが小さく、一度に全てのデータをメモリに読み込むことができる場合に限られます。例えば、APIからのレスポンスや小さな設定ファイルなどが該当します。一方、`json.NewDecoder`と`json.NewEncoder`は、大きなサイズのJSONデータやストリーム型のデータを扱う場合に適しています。これらの関数は、データを逐次的に処理できます。これは大きなデータファイル（数GBものJSONデータ）や、リアルタイムで更新されるデータ（ソケットからのストリーミングデータなど）を扱う際に重要です。

## 1. メモリ領域の確保と保存の違い

メモリの「確保」は、ある種のデータを格納するためのメモリ領域を準備することを意味します。一方、「保存」は、特定の値をメモリ上に記録することを指します。

Go言語では、変数を宣言することでメモリ領域が確保されます。例えば以下です。

```diff_go
var myInt int
```

このコードは、整数を保存するためのメモリ領域を確保し、`myInt`という名前をつけます。この時点では、`myInt`にはゼロ値である`0`が自動的に保存されます。ですので,変数の宣言だけで初期化をしていない場合でも最終的には各型のゼロ値が自動的に保存されます。

## 2. メモリに確保と保存がされるときと確保と保存がされない時のパターン

変数の宣言と初期化はメモリの確保と保存の一般的なパターンです。

```diff_go
var i int = 10
```

ここでは、`i`という名前のメモリ領域が確保され、値`10`がその領域に保存されます。

また、Goの構造体や配列などの複合データ型も同様です。以下の例では、`Person`という型の変数`p`が作成され、それぞれのフィールドに値が保存されます。

```diff_go
type Person struct {
    Name string
    Age  int
}
p := Person{Name: "Alice", Age: 30}
```

ただし、型を定義するだけではメモリは確保されません。

```diff_go
type WeatherResponse struct {
	Main struct {
		Temp float64 `json:"temp"`
	} `json:"main"`
	Weather []struct {
		Description string `json:"description"`
	} `json:"weather"`
}
```

この`WeatherResponse`型を実際に使うまで、メモリ領域は確保されません。

## 3. 関数とメモリ

関数が呼び出されるとき、その引数とローカル変数はメモリ（具体的にはスタック）に保存されます。関数が終了すると、そのスタックフレームは解放され、引数とローカル変数はメモリから消去されます。

```diff_go
func add(a int, b int) int {
    var sum = a + b
    return sum
}
```

関数`add`が呼び出されると、引数`a`と`b`、そしてローカル変数`sum`のためのメモリ領域が確保されます。関数が終了した後、これらの領域は解放されます。

## まとめ

Go言語のメモリ管理は、効率的なプログラムの設計において重要な役割を果たします。メモリの確保と保存の違いを理解し、それらがいつ発生するのかを知ることで、Go言語の動作についてより深く理解することができます。
cscの作法 その352

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

# 練習問題
MDIコンテナに、色を指定せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3431f5e8-bce5-eb69-565f-d74c60377a26.png)


# サンプルコード

```

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace App
{
	public class Form2: Form {
		private PictureBox picDisplay;
		public Form2(string title, string fileName) {
			InitializeComponent();
			Text = title;
			picDisplay.Image = Image.FromFile(fileName);
		}
		private void InitializeComponent() {
			this.picDisplay = new PictureBox();
			((System.ComponentModel.ISupportInitialize)(this.picDisplay)).BeginInit();
			this.SuspendLayout();
			this.picDisplay.Location = new Point(1, 7);
			this.picDisplay.Name = "picDisplay";
			this.picDisplay.Size = new Size(225, 247);
			this.picDisplay.TabIndex = 0;
			this.picDisplay.TabStop = false;
			this.AutoScaleDimensions = new SizeF(6F, 13F);
			this.AutoScaleMode = AutoScaleMode.Font;
			this.ClientSize = new Size(227, 256);
			this.Controls.Add(this.picDisplay);
			this.Name = "ChildForm";
			this.Text = "Child";
			((System.ComponentModel.ISupportInitialize)(this.picDisplay)).EndInit();
			this.ResumeLayout(false);
		}
	}
	public class Form1: Form {
		private System.ComponentModel.Container components = null;
		Form2 frmchild;
		public Form1() {
			InitializeComponent();
			foreach (System.Windows.Forms.Control c in Controls)
			{
				if (c is System.Windows.Forms.MdiClient)
				{
					//Console.WriteLine("ok");
					((MdiClient) c).BackColor = Color.Aqua;
				}
			}
		}
		protected override void Dispose(bool disposing) {
			if (disposing)
			{
				if (components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose(disposing);
		}
		private void InitializeComponent() {
			this.AutoScaleBaseSize = new Size(5, 15);
			this.ClientSize = new Size(400, 400);
			this.IsMdiContainer = true;
			this.Name = "MDI";
			this.Text = "MDI";
			this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
			this.Load += new System.EventHandler(this.Form1_Load);
		}
		private void Form1_Load(object sender, System.EventArgs e) {
			frmchild = new Form2("Child", "1.png");
			frmchild.MdiParent = this;
			frmchild.Show();
		}
		private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
			frmchild.Hide();
			frmchild.Dispose();
			frmchild = null;
		}
		[STAThread]
		static void Main() {
			Application.Run(new Form1());
		}
	}
}



```

以上。
RapidMiner AI 2023 コンテスト参加体験記

# はじめに
データ分析初心者の私が、車両の振動データの分類にチャレンジしたAIコンテストに参加しました。コンテストに参加する前は、機械学習やデータ分析についてほとんど知識がありませんでした。しかし、このコンテストを通じて、データ分析の基礎から機械学習の応用まで学ぶことができました。この記事では、私のような初心者の方々に向けて、コンテスト参加の体験談をまとめたいと思います。

# コンテストの概要
RapidMiner AI 2023 コンテストは、車両の振動データからどの車両が通過したのかを予測するモデルを作成し、その分類精度（正答率）を競うコンテストです。コンテストの詳細については、以下のリンクを参照してください。
　https://www.rapidminer.jp/news/event/1546/

またコンテストの上位入賞者がどのように課題に取り組んでどのような発見があったのかなどを発表した動画が以下のサイトで公開されていますので、興味のある方は参照ください。
　https://ksk-anl.smktg.jp/cc/0y1QTemdB

# 分析手法
主催者から提供された振動の時系列データ分析するために、次の指標を用いました。
**基本的な統計指標**
時系列データの平均値や分散などの基本的な統計指標を抽出しました。
**車両の平均速度** 
提供されたデータには、車両がレールを一周する間の振動データが一定の時間間隔で保存されています。これを利用して、車両の平均速度を求めました。
**自己相関関数**
時系列データの自己相関関数を求めることで、データ間の相関関係を調べました。自己相関関数は、以下の文献などを参照して求めました。
　https://www.jstage.jst.go.jp/article/jscej1969/1970/174/1970_174_11/_pdf

# モデルの詳細
コンテストで使用したモデルについて詳しく説明します。
## 基本的な統計指標
RapidMinerの標準プロセスである「Extract Aggregates」を用いて、時刻歴データの以下の指標を求めます。
合計値、平均値、分散、最大・最小値、中央値、第一四分位数、尖度、歪度。
ここで、
**第一四分位数（first quartile）** とは、データを小さい順に並べたとき、初めから数えて25%の位置にある値のことを指します。
**尖度（kurtosis）** とは、確率分布の形状を表す指標であり、その値が大きければ鋭いピークと長く太い裾をもった分布であることを示します。
**歪度（skewness）** とは、分布の非対称性を表す指標であり、その値が大きければ左右非対称な分布であることを示します。
## 自己相関関数(ACF)
RapidMinerの「Autocorrelation / Autocovariance」プロセスを用いて、自己相関関数(ACF)を求めました。ACFは、「過去と現在のデータがどれだけ似ているか」を表す指標であり、時系列データの予測や分析に役立ちます。ラグというパラメータがあり、k=0の時、自分自身との比較となり、ACF=1となります。kが1以上の場合、ACFはk個の時間間隔だけ離れたデータとどれだけ似ているかを表します。

今回は、このモデルのパラメータであるラグの最大値(maximum lag)の値を調整して正答率の改善を試みました。

# 結果の解釈
コンテストでは、ACFのmaximum lag(k_max)を調整しながら16回試行し、k_max = 6のとき、90.4%の正答率を得ました。初期値としてデフォルトのk_max = 12を試行したのですが、k_maxを小さくする方がk_maxを大きくするよりも結果が改善しました。

# 今後の展望
データ分析の経験がほとんどなかった私でも、RapidMinerのわかりやすいインターフェースを用いることによって、効率よく予測モデルを改善することができました。車両の振動データのモデル化において、自己相関関数は有効なツールであることが確認できました。今後は車両のシミュレーション結果などを利用してモデルを改善し、より実践的な問題に応用できるようにしたいと考えています。
２日ほど悩んだ、フローの数式

本当に参りました。まさかのIdの桁数とデバックにおける「別のユーザとしてフローを実行」でのユーザIdには、本当に参った。


今回は今まで別のシステムで運用していた社内の承認申請をSalesforceで作り変えるというお話です。
残念ながら承認ワークフローは仕様が違い過ぎて使えないので、フローで作ることになりました。


今回はある条件の時だけに、申請者が登録すると即承認としていいパターンを作っていました。

Route__cという部門によって経路選択を行えるようにしています。経路によっては承認者が異なります。
本当はロール階層とかを使ってもよさそうでしたが、承認者が部門を兼務していることがあるのでロールをやめて経路をしていすることにしました。（経路はフローの中で申請者の部門から自動でセットしています）

経路によって!$Record.ApprovalRoute__r.Authorizer1__r.User001__cのようにユーザIdを引用します。
しかし、何とここは18桁のIdなんですよね。数式リソースなので15桁と思い込んでましたが、デバッグしてみると18桁のIdが取得されています。

```
CASE( {!$Record.Route__c} ,
"001" , {!$Record.ApprovalRoute__r.Authorizer1__r.User001__c} ,
"002" , {!$Record.ApprovalRoute__r.Authorizer1__r.User002__c} ,
"003" , {!$Record.ApprovalRoute__r.Authorizer1__r.User003__c} ,
"004" , {!$Record.ApprovalRoute__r.Authorizer1__r.User004__c} ,
"005" , {!$Record.ApprovalRoute__r.Authorizer1__r.User005__c} ,
"006" , {!$Record.ApprovalRoute__r.Authorizer1__r.User006__c} ,
"009" , {!$Record.ApprovalRoute__r.Authorizer1__r.User009__c} ,
"010" , {!$Record.ApprovalRoute__r.Authorizer1__r.User010__c} ,
"011" , {!$Record.ApprovalRoute__r.Authorizer1__r.User011__c} ,
"012" , {!$Record.ApprovalRoute__r.Authorizer1__r.User012__c} ,
"013" , {!$Record.ApprovalRoute__r.Authorizer1__r.User013__c} ,
{!$Record.ApprovalRoute__r.Authorizer1__r.User__c} )
```

また、上記の結果が申請者と同じ（承認者と申請者が同一）の場合をチェックしたかったので,
これと等しいかを比べてみました。

```
{!$User.Id}
```

当然、デバックでは「別のユーザとしてフローを実行」を指定しているのですが、この値はデバックしている私のIdが15桁として入ってました。ええええ、別のユーザのIdにならないし、何でここは15桁なんだよ。

仕方ないので別にある申請者というユーザの参照項目を使うと、ちゃんと別のユーザの15桁のIdになっていましたね。
ああでも15桁なんです。

最終的には18桁、15桁のIdが混在するので以下のように無理やり15桁に桁数をそろえることになりました。

```
LEFT(CASE( {!$Record.Route__c} ,
"001" , {!$Record.ApprovalRoute__r.Authorizer1__r.User001__c} ,
"002" , {!$Record.ApprovalRoute__r.Authorizer1__r.User002__c} ,
"003" , {!$Record.ApprovalRoute__r.Authorizer1__r.User003__c} ,
"004" , {!$Record.ApprovalRoute__r.Authorizer1__r.User004__c} ,
"005" , {!$Record.ApprovalRoute__r.Authorizer1__r.User005__c} ,
"006" , {!$Record.ApprovalRoute__r.Authorizer1__r.User006__c} ,
"009" , {!$Record.ApprovalRoute__r.Authorizer1__r.User009__c} ,
"010" , {!$Record.ApprovalRoute__r.Authorizer1__r.User010__c} ,
"011" , {!$Record.ApprovalRoute__r.Authorizer1__r.User011__c} ,
"012" , {!$Record.ApprovalRoute__r.Authorizer1__r.User012__c} ,
"013" , {!$Record.ApprovalRoute__r.Authorizer1__r.User013__c} ,
{!$Record.ApprovalRoute__r.Authorizer1__r.User__c} ) ,15) =LEFT({!$Record.Applicant__c},15)
```

しかし、同じ数式を数式項目としてつくるとなぜかちゃんと機能しているんですよね。
何でフローとは挙動が一致しないのだろう。
【多クラス分類】マクロ平均再現率と正解率が一致するときもある

<p>
多クラス分類の混同行列でマクロ平均再現率と全クラスの正解率が一致するときがあり、しばらく詰まってしまったので記事にします。
<h1>多クラス分類の評価指標

[このページ](https://analysis-navi.com/?p=553)がわかりやすく、大変助かりました。
ほかの評価指標についてはこちらを見てください。

今回はこのような多クラス分類の混同行列で考えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/ec32d5f7-9a2c-6b5e-6f88-748421b40d0b.png)
オレンジのマスが予測が正解したときです。

<h1>正解率
<p>

```math
\frac{正解したデータ数の合計}{すべてのデータ数} 
```
今回の場合であれば、
```math
\frac{210+240+400}{300+400+500} = \frac{850}{1200} = 70.8％
```
になります。

<h1>マクロ平均再現率
<p>
マクロ平均再現率とは、各クラスの再現率を平均したものです。

```math
\frac{それぞれのクラスの再現率の合計}{クラス数} 
```
それぞれのクラスの再現率は
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/1b221bf9-906f-efc5-f2ef-d5819bbe37a2.png)
になるので、マクロ平均再現率は

```math
\frac{70.0+60.0+80.0}{3}  = \frac{210.0}{3} =70.0％
```
になります。
<h1>マクロ平均再現率と正解率が一致する例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/ef8080f9-aac9-03a4-6eda-419e9a2bb4b4.png)
上の表の例では、マクロ平均再現率は70.0%、正解率は70.8%と一致しませんでした。
一方、下の表の例で考えてみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/cea51c0f-d6c2-f137-f0e8-9da4d293af65.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/a0c32139-f0cf-05c1-e63b-0a240c7dea06.png)
正解率は
```math
\frac{300+350+400}{500+500+500} = \frac{1050}{1500} = 70.0％
```
マクロ平均再現率は
```math
\frac{60.0+70.0+80.0}{3}  = \frac{210.0}{3} = 70.0％
```
になり、一致します。え？なんで？

<h1>マクロ平均再現率と正解率が一致する条件

結論から言うと、`それぞれの真のクラスの枚数が等しいときにマクロ平均再現率と正解率が一致`します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/10765f53-ec4d-d732-a27d-199f6abd3dd0.png)
a~iはそれぞれの枚数が入ります。
今回は真のクラスの枚数が等しいので、
```math
a+b+c = d+e+f = g+h+i = N
```
とします。
正解率は
```math
\frac{a+e+i}{(a+b+c)+(d+e+f)+(g+h+i)}  = \frac{a+e+i}{3N} 
```
となります。

マクロ平均再現率は
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/9092f8a2-5f94-ddbc-db4c-e939d97752d3.png)
より、
```math
(\frac{a}{N}+\frac{e}{N}+\frac{i}{N})÷3=\frac{a+e+i}{3N} 
```
となるので、正解率もマクロ平均再現率も
```math
\frac{a+e+i}{3N} 
```
となります。

<h1>まとめ

それぞれのクラスのデータ数(枚数)が同じとき、マクロ平均再現率と正解率が一致します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081435/3ae470a5-08fd-7c44-d256-dd3988fcea5a.png)

<h1>参考

[https://analysis-navi.com/?p=553](https://analysis-navi.com/?p=553)
[https://kunsen.net/2021/03/18/post-3653/#Accuracy-2](https://kunsen.net/2021/03/18/post-3653/#Accuracy-2)
[https://www.haya-programming.com/entry/2018/03/14/112454](https://www.haya-programming.com/entry/2018/03/14/112454)
ウェブスクレイピングって何がどこまで違法なの？について

ウェブスクレイピングってなんかこう、闇を感じるというか、やっちゃいけないことやってるような感じがするというか、そういう感じないですか？

盗んだバイクで走りだす、じゃないけれども。

ここではウェブスクレイピングが何がどこまで違法なのかについて書きたいなと思います。一応法律の資格も持ってるんで大きく間違ってはないはずです。

# 3つの分岐があるよ

まず最初に、ウェブスクレイピングが合法、というか問題ないかどうか、については3つの分岐があります。
あの女子が好きな、あなたは朝方？それとも夜型？みたいな「性格診断YES/NO」みたいなやつを想像してもらえれば。

1.自分だけで使うの？（はい！/いいえ…）
2.そのまま転載しちゃうの？（はい…/いいえ！）
3.その転載する内容は著作権絡んじゃう？（はい…/いいえ！）

てな感じ。

んで選択肢の末尾に「！」がついてる方を選んだ場合は、そのウェブスクレイピングは何も違法じゃないのでその時点で終了！もう安心！という感じ。

逆に末尾「…」のやつを選んで最後の3番も「はい…」を選ぶとこれがいわゆる違法なウェブスクレイピングってやつになります。

結局ウェブスクレイピングで画像など引っこ抜いてきても自分だけで使うなら問題ない（友達にあげるとかは著作権的にダメ）。その情報を友達でもなんでも、誰かに公開するときに違法感がムクムク出てくる感じ。

# 例えばのケース

[ジムたくさんまとめたやつ](https://kerori.oqrio.com/)

わたしは上記のウェブサービスを暇つぶしに作ってる、というか自身もジム通いをしているので興味本位で調べてたことをただまとめてるだけなんですが、これも各ジムの店舗名はそのジムの公式サイトに行ってスクレイピングしてゲットしています。

店舗名をスクレイピングしてそのままネット上に公開しているんで、上記チェック項目でいうと1番は「いいえ…」、2番は「はい…」と順当？に違法への道をまっしぐら。

でも3番目の著作権に抵触しちゃう？の部分で「いいえ！」なのでギリギリセーフといった感じ。

# どこから著作権的にアウトなの？

結局一番気になるのは「んじゃどこからどこまでが著作権的にセーフでどこからがアウトなの？」っていう部分だと思います。

ここらへんは裁判の結果（「判例」っていいます）を見るのが一番なんですが、例えば会社や商品のロゴマークとかは、使用に際し特に許可を得なくても著作権違反にはならないみたい。

なので例えば「企業一覧」みたいなウェブサイトを作るとして、各会社のロゴマークを画像として載せてても基本的に大丈夫。

でもそのお店が販売してる商品画像をウェブスクレイピングで公式サイトからすっぱ抜いてきてそのまま掲載したら著作権違反になる（ただみんなやってるよね、スクレイピングで取ってきてないだけで、普通に右クリックポチっ「画像を保存」して）ので、ここらへんがなんとなくの線引きかなー、と。というか裁判官がそこらへんで線引きしてるなーという感じ。

なのでウェブスクレイピングした内容を公開するときに、「これって企業ロゴよりもヤバめかな？」という観点で一度見てみると判断しやすいと思います。

ちなみに商品の画像を自分で撮影したものであれば載せてもOKです。

これは商品自体に著作権があるのではなくて「写真自体」に著作権があるため。

# グノシーとかトリバゴとかは？
グノシーとかトリバゴとか、前者はニュースまとめ、後者は旅館情報まとめ、みたいなサービスってあります。

あれって「んじゃ違法なんじゃ？」あきらかに他者の商品（ニュース記事や宿泊情報）を勝手にスクレイピングなりして載せてるよね？っていう。

個人的にはグレーゾーンかなと思います。

現にグノシーやスマートニュースのようなニュースまとめサイトは、著作権がらみで問題になっていたはず。

そのスクレイピングしてきた他者のニュースや宿泊情報を並べた「一覧画面」はギリOKで、その一覧から気になるニュースや宿泊情報を推した際に表示される「詳細画面」自体も自サイトでやっちゃうのはNG。

という事だったと思います。

つまり、そのまとめサイトを見て、そのニュースなり宿泊情報なりに興味を持ったユーザーを元サイトに流入させるようにしないとダメ、っていう感じ。

昔「NAVERまとめ」っていうサイトがあった（今は閉鎖されてる）んですが、あれはよその記事の内容をぺたぺた貼り付けて、自分の記事を作るってやつだったんですが、このやり方だと、引用の限度を超えてるし、元の記事が読まれなくなるからダメ、みたいな事だったと思います。

# 最後に：マナーも忘れずに！
ここではウェブスクレイピングの何がどこまで違法なのかについて書きました。

まとめると、「ウェブスクレイピングした文章や画像をそのまま公開する時で、かつ、それが著作権に違反してる場合に違法になるよ！」って感じ。

違法かどうかはロゴマーク程度の物か、どうかっていうのが一つの判断基準になってるっぽい。

んでそういう違法かどうか、という話とは別にスクレイピングはお相手のサーバーに負担をかける行為でもあるので、きちんとプログラム内で数秒ごとにアクセスするようにするなど、マナーを守ってスクレイピングしましょう。
Ubuntu Linux 20.04 LTSにGoをインストールする

# はじめに

Goをインストールするにあたって、寄り道しながら、どのようにインストールするべきか、いろいろな方法を見てみました。

## 公式サイトを見てみる

直接圧縮ファイルをダウンロードするように解説されています。これだと面倒なので、パッケージ管理ツールを使ってインストールする方法がないか調べてみます。

https://go.dev/doc/install

## GitHubを見てみる

GitHubだとパッケージ管理ツールを使ったインストール方法がREADMEに書いてあることが多いですがなかったです。
https://github.com/golang/go

## GitHubのWikiを見てみる

もう少し粘ってみましょう。
WikiにUbuntuのページがありました。

https://github.com/golang/go/wiki/Ubuntu

**Using PPA**として、公式ではないですが、aptを使ったインストール方法が書かれていました。
PPA(Personal Package Archive)とは、非公式のレポジトリのことです。

https://help.ubuntu.com/community/PPA

本来であれば、公式のインストール方法に従うべきですが、Wikiに従って、試しにこちらから入れてみます。

https://launchpad.net/~longsleep/+archive/ubuntu/golang-backports

提供元のサイトを見てみると、

```
Latest updates
golang-1.20 5 weeks ago
Failed to build: i386
```

Goの1.20.5のbuildが失敗している記述がありました。
とりあえず入れてみましょう。

```sh
$ sudo add-apt-repository ppa:longsleep/golang-backports
$ sudo apt update
$ sudo apt install golang-go
$ go version
go version go1.20.4 linux/amd64
```

1.20.4がインストールされています。
公式で提供されている最新バージョンは1.20.5なので
今、Go公式から入手できるバージョンよりは低いようです。buildに失敗した履歴があるのに放置しているのはなぜなのでしょう？

今回は、最新版を入れたかったので、適当にコマンドを実行して入れると、意図してないバージョンが入ってしまう危険性があることがわかりました。

消しておきます。

```sh
$ sudo apt remove golang-go
$ sudo apt autoremove
```

## Ubuntuの公式パッケージを調べてみる

apt searchコマンドを使用して、公式パッケージでgoをサポートしているものがないか、調べてみます。

```sh
$ apt search golang-go
...
golang-1.20-go/jammy 1.20.4-1longsleep1+focal amd64
  Go programming language compiler, linker, compiled stdlib
...
```

ありましたが、1.20.4でした。
公式レポジトリでサポートされているコマンドがあったのでPPAの使用を促しているGoの公式Wikiは情報が古いということですね。

## wgetコマンドを使って入れる

Go公式のダウンロードページから右クリックでリンクを取得します。

```sh
$ wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz 
$ rm -rf go1.20.5.linux-amd64.tar.gz 
$ export PATH=$PATH:/usr/local/go/bin
$ go version
go version go1.20.5 linux/amd64
```

無事に最新版のGoがインストールできました。

## まとめ

Ubuntuの公式レポジトリでパッケージが用意されていても、必ずしも最新版ではない、ということが知れてよかったです。
パスの設定の手間があるので、マイナーバージョンの差異くらいならaptでインストールするほうが管理が楽かもしれないですね。
KatalonStudioで未使用のTestObjectを削除したい

# KatalonStudioでTestObjectを整理したい

未使用のTestObjectとは、TestCase、Test Listener、またはキーワードで参照されていない TestObjectを指します。
これらがあることで、紛らわしかったり見づらかったりするので、使ってないものを削除したいと思いました。

## バージョン 7.0.0以降未使用のTestObjectを探せるようになった

>Katalon Studio バージョン 7.0.0以降、テスト オブジェクトのリファクタリングが利用可能です。

参照：https://docs.katalon.com/docs/maintain/refactor-test-objects-in-katalon-studio



# 手順

プロジェクトの``Tools > Test Object > Show unused Test Objects``を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/c63de117-8ef2-8dc0-beb4-71748d96e2ea.png)

なんかいっぱい出てきます（私のプロジェクトに未使用が沢山あったため）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/5a16ba60-cb49-ca40-9757-86b943404729.png)
こちらが未使用のリストです。

``Delete All``ですべて削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/0ae0d47d-790d-1506-885b-f35bc1ee94ba.png)

:::note warn
Katalon Studio では削除されたオブジェクトを復元することができないため、注意してください。
Gitなどで復元できるようにすることをお勧めします。
:::

フォルダ分けしていた場合、TestObjectを削除しても空になったフォルダは残ってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/54dbc0b0-3b87-d771-1ac5-9ee8f0288f48.png)
これは手動削除みたいです。

## 残ったTestObjectについて どこで参照されているか確認したい
TestObjectを右クリックして``ShowReferences``を選択するとSearchタブで表示されるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/3fda6af8-d453-dd1d-93c5-76c650a0806b.png)

Searchタブの表示例
![スクリーンショット-2023-06-09-151553.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/1e989e28-fc30-a158-61ce-cf8ef204216d.jpeg)

# 以上
おつかれさまでした
IPv6 + WireGuard でリモートアクセス VPN

IPv6 環境で WireGuard を使ってリモートアクセス VPN を実現できたのでまとめる。

## やりたいこと
外出先から自宅内のサーバ (NAS) にリモートアクセスしたい。

我が家のネット回線は フレッツ + OCN を契約しており、IPv6 は普通に IPoE でインターネットに出ていきつつ IPv4 は OCN バーチャルコネクト (MAP-E) での IPIP6 トンネル経由という、最近よくありがちな構成となっている。

従来の PPPoE 接続であればグローバル IPv4 アドレスが1個は付くため LAN 内で VPN サーバを動かしてそこにポートフォワーディングをしてやれば簡単にリモートアクセスは実現できたものだったが、今回のように MAP-E を使っている場合はグローバル IP は他の利用者と共有なので利用できるポートが限られている [^map-e] し、類似の IPIP6 技術である DS-Lite に至っては ISP 側で NAT するのでポートフォワーディングはできない。

[^map-e]: MAP-E で降ってくるグローバル IPv4 アドレスと利用可能ポートは実際はほぼ固定らしいので、IPv4 ポートフォワーディングはできないことはないっぽい

なんとかしてこの IPoE 環境でリモートアクセスを実現できないものかと頭を悩ませていたが、無理に IPv4 で頑張らずに **普通に IPv6 でやればよいのでは...？** と気づいた。[^ipoe]

[^ipoe]: フレッツの IPoE でも IPv6 アドレスは半固定なので変わる可能性はあるらしいということを作ったあとで知った。MAP-E で良かったのでは？

## 作った構成
WireGuard が IPv6 に対応してそうな気配があったので、自宅に転がっていた Raspberry Pi に入れて動かしてみることにした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/dd76ca61-1845-3291-bf03-3c7d4723260f.png)

### ホームゲートウェイの設定
Raspberry Pi の IPv6 アドレスの 51820 ポート宛のパケットが通過できるように穴を開けておく。

### サーバ (Raspberry Pi) 設定
WireGuard のインストールやキーペア生成などの説明は割愛。

まず sysctl で IPv6 パケットのフォワードを許可しておく。(`sudo sysctl -p` で設定を反映させる)

``` :/etc/sysctl.conf
net.ipv6.conf.all.forwarding = 1
```

設定ファイルはこんな感じ。

``` :wg0.conf
[Interface]
PrivateKey = ********
Address = fd00::1/64
ListenPort = 51820
PostUp = ip6tables -A FORWARD -i %i -s fd00::/64 -j ACCEPT; ip6tables -t nat -A POSTROUTING -s fd00::/64 -o e+ -j MASQUERADE
PostDown = ip6tables -D FORWARD -i %i -s fd00::/64 -j ACCEPT; ip6tables -t nat -D POSTROUTING -s fd00::/64 -o e+ -j MASQUERADE

[Peer]
PublicKey = ********
AllowedIPs = fd00::2/64
```

### クライアント設定
iPhone に WireGuard アプリを入れて設定した。

``` :wg0.conf
[Interface]
PrivateKey = ********
Address = fd00::2/64

[Peer]
Endpoint = [X:X:X:X:Y:Y:Y:Y]:51820
PublicKey = ********
AllowedIPs = fd00::/64, X:X:X:X::/64
PersistentKeepalive = 25
```

## 動作確認
クライアント (iPhone) で WireGuard VPN を有効にした状態で Web ブラウザから http://[X:X:X:X:Z:Z:Z:Z]/ (NAS の IPv6 アドレス) にアクセスしたところ、NAS の管理画面が表示できた。めでたしめでたし。


## まとめ
- クライアントから接続する際のエンドポイントを IPv6 アドレスにして、WireGuard のパケットがホームゲートウェイを通過できるように設定した
- トンネル内アドレスは IPv6 のユニークローカルアドレス `fd00::/64` [^ula] にして、ピア毎に `::1` `::2` ... と適当に連番で割り当てているだけ
- クライアントから LAN 内の別のホストにアクセスするためには NAT する必要があったが、コマンドが `ip6tables` に変わっているだけで、やっていることは IPv4 のときと同様 [^nat]

[^ula]: IPv6 のユニークローカルアドレス (ULA) は IPv6 のプライベートアドレス的なやつ (という認識)

[^nat]: IPv6 だし NAT しなくても動くかな？ と思って試してみたが動かなかった。NAT 無しでフォワードしてもパケットは到達できるが、帰りがデフォルトゲートウェイに行ってしまって Raspberry Pi まで届かないっぽい？

**あれ...? 意外と簡単にできてしまったな？？？**

IPv4 over IPv6 で試行錯誤してたときは全然うまくいかなくて泣きそうだったのに、IPv6 でやったらこんなにすぐできてしまうとは...。

## 参考
- [WireGuard で VPS と IPv6 over IPv4 | 暇言](https://wp.hima-jin.info/wireguard-ipv6-over-ipv4/)
- [バイク野郎のひとりごと: Ｖ６プラスの IPv６ 側を使って Wireguard VPN を接続する](https://bike8615.blogspot.com/2020/12/ipv-wireguard-vpn.html)
- [WireGuardのAllowed IPsの設定についての補足 | ネットワークとともに](https://www.infrastudy.com/?p=1065)
- [iptablesの仕組みを図解 - Carpe Diem](https://christina04.hatenablog.com/entry/iptables-outline)
Microsoft認定試験の小技紹介

## はじめに
AZ-900, AI-100, AZ-204, AZ-400 とMicrosoft認定試験を何度か受けているうちに
回答の規則性のようなものを発見したのでご紹介させていただきます。

:::note warn
絶対これに当てはまるという訳ではございません。
また私個人の考察なので、使う際は自己責任でお願いします。
:::

## 規則性について
それはズバリ「問題文に出てくる単語が選択肢の中に含まれているものが答えになりやすい」ということです。

例えば、以下の問題Project4に関する内容を聞いていますが
表の中にも、答えであるCの文にも、「Build Pipeline」と「Docker」というキーワードが含まれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2258693/e830fe3c-e1dc-2a43-370e-d3b3b9016e5e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2258693/25e9c562-c9d0-b082-f9dc-8ae2b363b8b3.png)

このように問題文の単語をそのまま引用して使っている、もしくは表現を少し変えて使っているものが答えになりやすい…ような気がします。

回答に迷った際は試してみると良いかもしれません。
Addressableを使っているときにGameObjectを削除する方法



ポイントは
シーンに配置したGameObjectを削除するときは```Destroy()```で良い
```InstantiateAsync()```で生成したGameObjectを削除するときは```ReleaseInstance()```で削除する

例えば、敵キャラクターが死んだときは以下のように書く
このように書くと両方の場合に対応できる
```csharp
    public void Die()
    {
        var released = Addressables.ReleaseInstance(gameObject);
        if (!released)
        {
            Destroy(gameObject);
        }
    }
```
OCI資格試験とセミナがなんと無料(期間限定)

# Oracle Free Certification for OCIイベント

2023年6月1日から8月31日の期間において、「[Oracle Free Certification for OCI](https://education.oracle.com/ja/oracle-oci-certification)」 というイベントが開催されています。イベント期間中は下記を無料で利用できます。もちろん参加費用もかかりません。

* OCI資格試験チケット(2回分)
* OCIオンライントレーニング
* OCIのLive Session受講

:::note info
通常、1回あたりの試験費用は、35,000円程度かかるため、かなりお得です。
:::

下記カテゴリのトレーニングが無料開放されています。

* Oracle Cloud Infrastructure
* Oracle Database Management
* Oracle Cloud Applications

初学者向けのFoundationsだけではなく、おなじみの `Oracle Cloud Infrastructure Architect Associate` やプロフェッショナル系の`Oracle Cloud Infrastructure Certified Architect Professional` まで幅広く利用できます。
また Race to Certification Challenge の課題をクリアすると更なる達成報酬を得られます。

# Race to Certification Challenge
Race to Certification Challengeは、3つのセクタで構成されており、セクタごとにクリア条件と達成報酬が設定されています。

## セクタ1
### 達成条件
* オンライントレーニングを1つ受講
* Live Sessionに1回参加
* 試験に1つ合格

### 達成報酬
* 1年間有効な1回分の試験チケット
* セクタ1のデジタルバッジ

## セクタ2
### 達成条件(セクタ1取得分もカウントされる)
* オンライントレーニングを2つ受講
* Live Sessionに1回参加
* 試験に2つ合格

### 達成報酬
* 1年間有効な1回分の試験チケット
* セクタ2のデジタルバッジ
* オラクルブランドの帽子(試験スコア上位300名)

## セクタ3
### 達成条件(セクタ1、セクタ2取得分もカウントされる)
* オンライントレーニングを3つ受講
* Live Sessionに1回参加
* 試験に4つ合格<BR>そのうち、2個はプロフェッショナル試験に合格が必要(対象は参考情報参照)

### 達成報酬
* 3ヶ月有効なOCIラボへのアクセス権
* 1年間有効な1回分の試験チケット
* セクタ3のデジタルバッジ
* オラクルブランドのジャケット(試験スコア上位300名)

# 参加してみた
ちなみに私は、Oracle Cloud Infrastructure 2022 Architect Professionalの勉強中の身ですが、せっかくの機会ですので、レースに参加登録しました。手始めに下記のオンライントレーニングを受講しました。
* Become an OCI Foundations Associate (2023) (元々無料枠ですが着実に進めるため)

オンライントレーニングの動画資料は英語ですが、別途、英語の原稿と閲覧可能なテキストを利用できるため、自分のペースで学習を進めることができそうです。
ご興味のある方は、ともにゴールを目指しましょう。

# 参考情報
セクタ3に必要なプロフェッショナル試験の一覧は下記となります。
1Z0-1109-23 Oracle Cloud Infrastructure 2023 DevOps Professional
1Z0-1104-23 Oracle Cloud Infrastructure 2023 Security Professional 
1Z0-1110-23 Oracle Cloud Infrastructure 2023 Data Science Professional
1Z0-1067-23 Oracle Cloud Infrastructure 2023 Cloud Operations Professional 
1Z0-997-23 Oracle Cloud Infrastructure 2023 Architect Professional 
1Z0-1084-23 Oracle Cloud Infrastructure 2023 Developer Professional
1Z0-1111-23 Oracle Cloud Infrastructure 2023 Observability Professional
1Z0-1071-23 Oracle Cloud Infrastructure 2023 Digital Assistant Professional 
1Z0-1042-23 Oracle Cloud Infrastructure 2023 Application Integration Professional 
1Z0-1041-23 Oracle Cloud Infrastructure 2023 Enterprise Analytics Professional 
1Z0-1118-23 Oracle Cloud Fusion Analytics Warehouse 2023 Implementation Professional 
1Z0-770 Oracle APEX Cloud Developer Professional 
1Z0-1120-23 Oracle Content Management 2023 Implementation Professional 
1Z0-1094-23 Oracle Cloud Database 2023 Migration and Integration Professional 
1Z0-1093-23 Oracle Base Database Services 2023 Professional 
1Z0-931-23 Oracle Autonomous Database Cloud 2023 Professional
Dockerで、Next.jsの開発環境を素早く構築する

# 概要
Docker、Next.js初心者の自分用にメモ

# 前提
- Githubアカウントを持っていること
- PCにDockerがインストールされていること
# 手順
- 以下のリポジトリをtemplateとして新規リポジトリを作成する
https://github.com/mizu0715/docker-next.js
- ローカルの任意の場所でgit cloneする
- docker-compose.ymlがあるディレクトリに移動
- コマンド実行
```
/hgoehoge$ docker-compose up -d
```
- もう一つシェルを起動し、以下の順に実行
```sh
# コンテナの中に入る
/app# docker-compose exec app bash 
# src/package.jsonの内容で、パッケージを追加
/app# yarn 
```
- 開発モードでNext.js実行
```
yarn dev
```

# まとめ
これで、ローカル開発環境は素早く構築することが可能です。
あとは、必要に応じてyarn addして、欲しいライブラリをインストールすることで機能拡張も容易になります
GitHub Desktopで部分的にコミットする方法

## この記事は何？

GitHub Desktopでファイル単位ではなく、ファイルの一部など部分的にコミットしたい方向けの記事です。

## 手順
ファイル編集が終わった状態からの手順です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/3c5c58a4-0230-8e7c-5661-a3318d21bd18.png)


一旦、changed files の横のチェックを外し、全ての選択を解除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/74aed294-7d11-01d9-e16e-1dea4f6c48fd.png)


コミットしたいファイルの該当行を選択します。（青いところが選択されています）別ファイルも跨った選択が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/43a62729-7336-5511-3d7d-6358543e079c.png)



ちなみに、クリックする場所によって選択される範囲が異なります。
行番号の右端辺りをクリックするとまとめて選択することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/14c9b16f-174d-204d-063d-dd11f62842bb.png)


該当箇所を全て選択できたらコミットメッセージを入力して、コミットします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/6f2f851d-361a-77a9-3bb1-2871e4c89227.png)


部分的にコミットができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/a3ab4095-4bf6-f8bd-ec23-fc52c207178d.png)


### ファイル単位でのコミット
ファイル単位でコミットしたい場合は、該当ファイルをチェックすればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/dcd0bf75-78be-fa63-5ed7-7e9b1ed136bd.png)



## おまけ

ちなみにコミットの取消は、「History」でコミットを右クリック→「Undo commit」、コミットの修正は「Amend last commit」で行えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630627/74331f49-7e77-1727-9b1c-9f950288a941.png)
PowerAppsを用いた生産性向上：結論ITリテラシの壁を超えることが可能

## はじめに
初学者がPythonを勉強しています。
といいながら、最近はMS365導入に伴うセットアップ、社内のガバナンス、クラウド移行、社内管理、現状データ整理などなど対応に追われINPUT量が多い中、
powerappsを触ったのでここらでOUTPUTを・・

なお間違っている内容や改善などご教示いただければ幸いです。

## 目的
（共通）業務の省人化を目的とする。
    ※正直GPT,Bard,MSBingなどなど生産性向上させるツールをバンバン用いて、まずは開発を展開する。
（今回）powerappsを用いた営業推進アプリ

:::note info
今回はpowerappsということもあり、文章での記述となりますのであしからず。
:::

## 方針
・powerappsはローコードで作成できるため、実際の開発難易度が格段に低いのが良い点。
　まずは一度サンプルアプリを用いた実際の社内提案が速そう。
　※実際、社内のクリティカルな仕事に付随する仕事が想定以上に多い。　
　※ITリテラシの壁を超えることができる！という成功体験及びアプリの快適さに包まれてほしい。Youtubeなど誰でも使用できるツール/依存性が高いツールを目指す。
　　
（独り言）
　昔は自分でPDCAを回すことが当たり前だったが、今ではGPTなどにまず質問→そこから戦略を練る・・といった、AIへ投げる（ブレストみたいな？）そこからまとめ上げるという開発/戦略へ
　最終的にはAIが全て提案してくれる未来（それはまた怖い時代か。。

## 開発
・最初に開発するアプリは、営業の提案DBアプリとした。
　弊社では営業が提案する際、従来クラウド/WEBで資料検索していた。これをアプリを用いて楽に検索/ツールへのリンク/有意義な情報は更にアプリへ追加させることで利益直結の営業部隊に使用できるように作成/展開。

・アプリの決定理由
　1. 当方も経験したことがあり、DBが多くいざというときに出てこないパターンがあった。
　2. 営業に展開しやすい環境だったということもあるが、営業だと使用頻度も高くユーザーとのコミュニケーションの中で必然的に改善項目を吐き出してもらえる。

・アプリを展開するにあたり注意したこと
　1. 従来の方法を出さないこと。変化を好まない人に戻る選択肢を与えない！
　2. アプリ説明は、ほぼせず使用してもらった（誰でも理解できるので教育の時間は不要。というかわかりやすく開発できないアプリは継続して使用されない）
　3. まずはサンプルで重要な機能のみ実装して60%程度で展開、どんどんバージョンをアップ。使用されるアプリであれば必然的にメンテ能力も向上する
　4. 実際に使用してもらうことで優位性を理解（コストとの兼ね合い）し次のフェーズへ。

## 熟考した部分
・"使用される"アプリの開発。これが一番重要
　わかりやすく誰が見ても理解できるように配慮。また適宜画像などを用いて実際のアプリのように視覚的に難易度を下げていく。
・最低限の仕様検討
（これは単独開発のため、自由度は高い。また使用されることでpowerappsの認知度が高まり、さらなる開発に繋がっていく）
・アプリが増えたら・・・・と考えたが、開発者が増えた場合でもアプリを作成したら、カタログアプリへ登録して管理（半年1回でアクセス数が少ない→削除など）
　開発者が少ない弊社ではまずはできることを増やすことが重要。

・やってわかったこと
powerappsはまずやってみた方がよい。そして形になると嬉しい。
もちろんAIの力を十二分に活用しよう。

## 今後の方向性
・現状MS365、python、powerappsだが、次はpowerplatform などへ展開する。
　DX人材になるべく動き出せており非常にありがたい。
・もっと開発スピードを上げたいが、最低限レベルは考慮して動いていく。
・AIをより有意義に活用する。(プロンプトの理解）
・目的をもって成長する。
dsqueryコマンド等、RSATツールの有効可方法

①
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate
を削除

②
オプション機能より、RSATツールを一通りインストールする
![スクリーンショット 2023-06-09 143149.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3161727/0db7889f-0d3c-6208-40d4-b1f0a64580fa.png)

たぶんこの3つのどれかが正解
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3161727/ee390fbf-bf40-7a77-4219-29db7872e6cf.png)
[Windows] 文字起こしにデスクトップ音を利用する試み

## はじめに

デスクトップ音を直接文字起こしに利用できれば、リアルタイム文字起こし検証プロセスが効率的になると考え取り組みました。
[Virtual Audio Cable](https://vb-audio.com/Cable/)を利用することで簡単に実現できました。

関連記事：[[ローカル環境] faster-whisper を利用してリアルタイム文字起こしに挑戦](https://qiita.com/reriiasu/items/920227cf604dfb8b7949)

2023 年 06 月 09 日

## 環境

Windows 11
VBCABLE_Driver_Pack43

## [Virtual Audio Cable](https://vb-audio.com/Cable/)

Virtual Audio Cable とは

> VB-CABLE is a virtual audio device working as virtual audio cable. All audio coming in the CABLE input is simply forwarded to the CABLE output.

VB-CABLE は仮想オーディオケーブルとして動作する仮想オーディオデバイスです。CABLE の入力に来る全てのオーディオは、単純に CABLE の出力に転送されます。

### 利用方法

1. ドライバのインストール
   VBCABLE_Driver_Pack43.zip
   (1.09 MB - OCT 2015 / XP to WIN11 32/64 bits)
   を管理者権限でインストール

2. デスクトップ音声の出力先を VB-Audio Cable に変更
   設定 > システム > サウンド > サウンドを再生する場所を選択
   ![sound_settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553528/cbb4c35e-a1ed-c1e1-a857-ba7fd7dc14a7.png)

3. 2.の変更をするとデスクトップ音が聞こえなくなるので対策
   1. 設定 > システム > サウンド > サウンドの詳細設定
   1. 録音 > VB-Audio Cable Output> プロパティ
   1. 聴く
   - このデバイスを聴くにチェック
   - このデバイスを使用して再生する => 利用していたスピーカー

VB-Audio Cable Output をマイクの代わりに音声入力デバイスに指定する。
Youtube の音声をリアルタイム文字起こしすることも可能となります。

Youtube をスピーカーから再生し、マイクを利用して集音するより雑音が入らなくてよいです。
C#でのbmp画像の構造体のポインタの取得(再)

「C#でのbmp画像の構造体のポインタの取得」で登録していたが、前のコードはポインタの操作のためにわざわざ数値型に変換して計算していた。
juner様からIntPtr.Add(IntPtr, Int32) を教えていただいたので修正した。

削除するつもりはなかったが、非表示のしかたが分からなくて、あわてて削除してしまいました。
編集でよかったように思います。

bitmapのフォーマット

https://www.setsuki.com/hsp/ext/bmp.htm

現在のコード
```c#
            byte[] imageBytes = System.IO.File.ReadAllBytes(path);
            // 先頭から画像本体へのオフセット値取得
            int AtOffsetData = 10;
            int imgOffset = BitConverter.ToInt32(imageBytes, AtOffsetData);

            IntPtr bitMapPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * imageBytes.Length);
            Marshal.Copy(imageBytes, 0, bitMapPtr, imageBytes.Length);

            // BITMAP構造体へのオフセット
            int BitMapInfoOffset = 14;
            IntPtr bitMapInfoPtr = IntPtr.Add(bitMapPtr, BitMapInfoOffset); 
            IntPtr imagePtr = IntPtr.Add(bitMapPtr, imgOffset);  
            
            // 画像解析ライブラリへの関数へポインタ渡す。
```
Outlookの予定が非公開かどうかを判定する【PowerAutomate】

## はじめに
Outlookの予定表からイベントを取得するフローをPowerAutomateで作成したのですが、
自分のプライベートな予定までも取得してしまうため、表題の処理を加えました。

## 機密度
Outlookの予定が非公開かどうか判定するには「機密度」を使用します。
機密度の種類は以下の4つです。
* normal 標準
* personal 個人用
* private プライベート
* confidencial 社外秘

デフォルトは「normal」で公開スケジュールとして登録されます。
下の画像のように「非公開」として登録すると、機密度は「private」になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2258693/4ec96889-6ebb-d20d-0c9c-d68927d16df5.png)

## フロー
以上のことを踏まえてフローを作成します。

### 予定表からイベントを取得する
まずは「予定表からイベントを取得する」アクションを使って1日のイベントを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2258693/2c46da3a-f1b2-4fde-5f2c-7ebb5d3e4f09.png)

:::note warn
Outlookアクションを使って取得したイベントはUTCになっているので、
開始時刻、終了時刻で検索を絞る際は注意してください。
※この画像の場合、日本時間に直すと9:00~18:00で検索しています
:::

### イベントを対象にループ処理を行う
次にループ処理のアクションを追加します。
Outlookから取得した各イベント（value）に対し、「機密度がprivateに等しい」かどうかを判定します。

「はい」の場合は非公開な予定なので後続の処理をスルーし、
「いいえ」の場合のみ処理を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2258693/9d18a95c-4aaf-3345-f426-81aba5924f30.png)

## 最後に
私の場合、Outlookに私的な用事も入れてしまう派なので、
この処理を加えて良かったなと思っています。
皆様も利用目的に応じて工夫してみてください。ご参考になれば幸いです。
Azure Database for MySQLを4分で日本語対応

## 概要

Azure Database for MySQL
を使用しており、テーブルのレコードに対して日本語を入れてもpymysql から怒られないように
したかったのですが、案の定時間を溶かしたので備忘録的にメモしておきます。

4ステップで完了します。
1ステップ１分で完了させて、４分後にはタスク完了しましょう。

## ステップ１

### pymysql のコネクションストリングの変更

```
ASYNC_DB_URL=mysql+aiomysql://user:password@host_ip:3306/test?charset=utf8mb4
```
というように、`charset=utf8mb4`
を追加していなければ追加します。


## ステップ２
### Azure コンソールから、Server Parameters を変更

Azure Database for MySQL　のコンソールから、
![Screen Shot 2023-06-09 at 14.18.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/db81e5f5-ca33-f45b-0e70-cea2b3bd4bd5.png)

ここにあるように、

- `character_set_server`
- `collation_server`

をそれぞれ

- `utf8mb4`
- `utf8mb4_general_ci`

と設定します。
１分で完了と書きましたが、このパラメータの変更により、データベースは再度構築されますので、
１０分ほど待つ必要があります。
データベースがリスタート完了したら、ステップ３に行きましょう。

## ステップ３
### MySQL サーバにsshし、以下の設定を反映

```
show variables like "chara%";
```
でヒットしたもののうち、

```
character_set_client
character_set_connection
character_set_database
character_set_results
character_set_server
character_set_system
```

たちを、

```
SET character_set_client=utf8mb4;
SET character_set_connection=utf8mb4;
SET character_set_database=utf8mb4;
SET character_set_results=utf8mb4;
SET character_set_server=utf8mb4;
SET character_set_system=utf8mb4;
```

などを使って全てutf8mb4に設定。


## ステップ4
### MySQL サーバにsshし、データベースをAlterします。

```
ALTER DATABASE test character set utf8mb4 collate utf8mb4_general_ci;
```

上は、`test`というデータベースに対してコマンドを実行しています。



お疲れ様でした、これでおそらく日本語でレコードをインサートできるようになっているはずです。


何回やってもこういうタスクは時間がかかりますね。。

今回はこの辺で。

@kenmaro
Liunx同士でソケット通信するTCP

# はじめに
これはWindows10で仮想環境を使用してLinuxを動かしています。

## 開発環境

Windows10

Virtual Box Ubuntu 22.04 LTS
VSCode(C++)

# コード
### サーバー側

```C++:Server.cpp
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h> 
#include<string>
#include<iostream>

int main() {
    int sockfd;
    int client_sockfd;
    sockaddr_in addr;
 
    socklen_t len = sizeof( sockaddr_in );
    sockaddr_in from_addr;
 
    char buf[1024];
 
    // 受信バッファ初期化
    memset( buf, 0, sizeof( buf ) );
 
    // ソケット生成
    sockfd = socket( AF_INET, SOCK_STREAM, 0 );
     
    int port=12345;
    std::cout << "ポート番号を入力" << std::endl;
    std::cin >> port;

    // 待ち受け用IP・ポート番号設定
    addr.sin_family = AF_INET;
    addr.sin_port = htons( port );
    addr.sin_addr.s_addr = INADDR_ANY;
 
    // バインド
    bind( sockfd, (struct sockaddr *)&addr, sizeof( addr ));


    // 受信
    listen( sockfd, SOMAXCONN );
   
    // コネクト
    client_sockfd = accept( sockfd, (struct sockaddr *)&from_addr, &len );

 
    // 受信
    int rsize;
    while( 1 ) 
    {
        rsize = recv( client_sockfd, buf, sizeof( buf ), 0 );

        if ( rsize == 0 ) 
        {
            break;
        } 
        else 
        {
            std::cout<<"recvData  "<< buf << std::endl;

            sleep( 1 );

            std::string a=" Linux Server";
            
            std::cout<<"sendData  "<< a <<std::endl;

            write( client_sockfd, a.c_str(), rsize );



        }
    }
 
    // ソケットクローズ
    close( client_sockfd );
    close( sockfd );
 
    return 0;
}
```
### クライアント側

```C++:Client.cpp
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<iostream>
#include<string>

int main() {
    int sockfd;
    struct sockaddr_in addr;
 
    // ソケット生成
    sockfd = socket( AF_INET, SOCK_STREAM, 0);
 
    int port = 12345;
    std::cout << "ポート番号を入力" << std::endl;
    std::cin >> port;

    std::string addrNum;
    std::cout << "接続するIPアドレス" << std::endl;
    std::cin >> addrNum;
    // アドレス&ポート番号設定
    addr.sin_family = AF_INET;
    addr.sin_port = htons( port );
    addr.sin_addr.s_addr = inet_addr( addrNum.c_str() );
 
    // サーバ接続
    connect( sockfd, (struct sockaddr *)&addr, sizeof( struct sockaddr_in ) );
 
    // データ送信
    std::string str;
    std::cout<<"送信したいデータ"<<std::endl;
    std::cin>>str;

    const char* data[100]{str.c_str()};
    char recvData[1000];
    for ( int i = 0; i < 10; i++ )
    {
        send( sockfd, *data, 100, 0 );
        
        recv( sockfd, recvData, sizeof(recvData), 0 );
        
        std::cout<<"recvData  "<<data<<std::endl;
        sleep(1);
    }
 
    // ソケットクローズ
    close( sockfd );
 
    return 0;
}
```

## さいごに
前に書いた記事ではwindowsからliunxへの片方向の送信でしたが今回は双方向で送信を行っています。

### 参考にさせていただいたサイト様
https://www.koikikukan.com/archives/2017/10/31-000300.php
PowerShellのTimeSpanで1ミリ秒以下を入力したい

PowerShellの`TimeSpan`を取り扱うコマンドレットとしては、`New-TimeSpan`コマンドレットがあります。

今回、`TimeSpan`に1ミリ秒以下を入力したいと思い`New-TimeSpan -Milliseconds 0.1`としたら下記のようになってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/11e0ff2b-5b2b-9371-9080-9e5f835446a7.png)

みごとの0になってしまい、`Milliseconds`オプションに小数点を入れるのはだめそうです。

本記事はこの対策として、ちょっと色々と試してみたメモ。

## 今回実施している環境

- Windows 10 21H2
- PowerShell 7.4.0-preview.3

## New-TimeSpanでTimeSpanオブジェクトを作成して、10でわってみる。

```powershell
(New-TimeSpan -Milliseconds 1) /10
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/1340fcf3-eb28-b8ac-deae-29910d3292f5.png)

Ticks　が 1000 になってますし、 他項目も0.1ミリ秒になっていてよさそうです。

## timespan の FromMillisecondsメソッドは小数点もいれられる

コマンドレットで`TimeSpan`オブジェクトを生成する事にこだわらなければ。
下記のように記述する事もできました。

```powershell
[timespan]::FromMilliseconds(0.1)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/1ff4b26e-8a54-b92b-3419-c1eafca2c53d.png)

## 総評

PowerShellで`TimeSpan`オブジェクトの細かい時間を積み上げる計算をしようとして、`TimeSpan`オブジェクトに1ミリ秒以下ってどうやって入力すれば？　となりましたが。

本記事の方法でとりあえず入力はできました。
Oracle Database 23aiで追加されたSQLの新機能 INTERVAL データ型の集計 をFree版で試してみた

Oracle Database 23ai から INTERVALデータ型を集計で使えるようになりました。

INTERVALデータ型が列にある表を作成します。

```sql
CREATE TABLE time_table
  (start_time    TIMESTAMP,
   duration_1    INTERVAL DAY (6) TO SECOND (5),
   duration_2    INTERVAL YEAR TO MONTH);
```

集計できるように２レコードを挿入します。
```sql
SQL> INSERT INTO time_table VALUES (SYSDATE, '10 12:00:00', '9-11');

1 row created.

SQL> INSERT INTO time_table VALUES (SYSDATE, '20 05:00:00', '3-05');

1 row created.
```
列幅を調整して、INTERVALデータ型を集計します。

```sql
column SD1 format a30;
column AD1 format a30;
column SD2 format a15;
column AD2 format a15;
SQL> SELECT SUM(duration_1) SD1, AVG(duration_1) AD1, SUM(duration_2) SD2, AVG(duration_2) AD2
     FROM time_table;

SD1                            AD1                            SD2             AD2
------------------------------ ------------------------------ --------------- ---------------
+000000030 17:00:00.000000000  +000000015 08:30:00.000000000  +000000013-04   +000000006-08
```
以上から、INTERVALデータ型を集計できました。
QRコードをデザインする新しい方法

## はじめに
企業などのロゴやテキストや図形等を加えて、コードが生成できるという記事がありました。

「こちらをページを参照」ということから出始めてきたように思うQRコードですが、QRコード決済をはじめいろいろな画面で見かける当たり前のものとなっています。

QRコードは、ぱっと見、QRコードだ、ということしかわかりません。LineやPayPayでは、小さくロゴが入っているのをみたことがありますが、その程度でした。

![Screenshot_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/a0befd67-cd4e-24e9-ad62-77b3aa5a2fcb.png)

## ロゴやテキストいりのQRコード生成

以下のオンラインツールで、自由にデザインしてQRコードを生成できます。

https://github.com/kochrt/qr-designer

すごいところは、自由にできるところがかなり大きいところです。(上記で振れたPayPayなどのような、小さいロゴを入れ込むといった程度ではない)

サンプルGalleryを見ても背景カラーや企業ロゴなどがあります。今後は、このようなデザインのQRコードが増えてくるのでは、と思わせる感じでした。

![Screenshot3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/91a36ac0-0607-b80a-2cd0-3f7260e637d4.png)

試しにツールを触ってみても誰でもできるという感じでした。

![Screenshot4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/2dd95925-7342-0418-ce2b-558b939f75fa.png)

## 画像生成AIとQRコードの融合

これと並行してたまたま見つけましたが、時代はさらに先をいっていました。
画像生成AIと融合させることで、かろうじてQRコードであることがわかるくらいのものになっています。生成AIの幅は本当に広いと感じます。

https://pc.watch.impress.co.jp/docs/news/yajiuma/1506717.html

画像生成AI「Stable Diffusion」で美麗イラストとQRコードを融合させる試み

https://gigazine.net/news/20230607-qr-code-controlnet/

URLをいれるだけでかっこいいQRコードを生成してくれるものも登場していました。

https://barcode.so/

![barcode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/1c2e04a9-8561-0f95-3209-13a2cf89b1fc.png)

上記を利用して作成したQRコード

![myqrcode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/cbf0ccb1-1138-43ca-b2d0-b8bc6fac3305.png)

## まとめ
バラエティー豊かでデザイン性のあるQRコードがたくさん登場し、"なんであんな無機質な真っ黒なコードを読み取っていたんだ"、と言われる時代が来るのかどうか楽しみです。

## 参考URL

https://coliss.com/articles/build-websites/operation/work/qr-code-designer.html
JAVA PATH 参考サイト

https://learn.jamf.com/ja-JP/bundle/technical-articles/page/Configuring_JAVA_HOME_and_JRE_HOME_Environment_Variables_on_a_Windows_Server.html

https://www.javadrive.jp/start/install/index4.html

https://www.kkaneko.jp/tools/win/openjdk.html

C:\Windows\system32>call powershell -command "[System.Environment]::SetEnvironmentVariable(\"JAVA_HOME\", \"C:\soft\jdk-20.0.1\", \"Machine\")"

C:\Windows\system32>call powershell -command "$oldpath = [System.Environment]::GetEnvironmentVariable(\"Path\", \"Machine\"); $oldpath += \";C:\soft\jdk-20.0.1\bin\"; [System.Environment]::SetEnvironmentVariable(\"Path\", $oldpath, \"Machine\")"

https://qiita.com/ryo-sato/items/87d05021fcc0519e8828
【備忘録】U-blox ZED F9Pのファームウェアを更新する

U-blox ZED F9Pモジュールのファームウェア書き込み、更新方法について記載します。

## 手順
１．U-centerをインストールする
２．ファームウェアをダウンロードする
３．ファームウェアを書き込む

## １．U-centerをインストールする
・　U-centerの専用サイトからダウンロードする
・　ダウンロードしたexeファイルをクリックしインストールする

https://www.u-blox.com/en/product/u-center

## ２．ファームウェアをダウンロードする

・　[U-Bloxのweb](https://www.u-blox.com/en)へアクセス
・　検索ページへ移動し「ZED-F9P」で検索をかける
・　「ファームウェアのアップデート」と記載されている項目を探す
・　ZED-F9Pのファームウェアをダウンロードする（図１参照）

図１
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/b8ecbb80-b7d6-3e1e-2a1d-52260d8a731d.png)


## ３．ファームウェアを書き込む

・　U-centerとF9Pモジュールを接続する
・　接続ボタンを押し接続する（図２参照）
・　ファームウェアアップデートボタンを押す（図３参照）
・　ダウンロードしたファームウェアを指定し「GO」を押下（図４参照）
・　書き込みが開始される（図５参照）
・　完了すると「Firmware Upfate SUCCESS」が表示される（図６参照）
・　接続ボタンを押し切断する
・　F9Pモジュールを取り外す

図２
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/a85fb41b-198a-eb08-2fa2-bd93bc6ca329.png)

図３
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/ef71266a-2c31-f227-7bad-e3dc2c806bb1.png)

図４
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/3b7ae843-145b-1142-4819-8ab66735a0d7.png)


図５
![ファーム１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/6728a9ae-1d9a-38f3-752c-014299de3c7a.png)

図６
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/3d03868e-dd43-9559-853a-574967922900.png)
メソッドの練習

これだと実行するとエラーになるので、
なんでエラーになるのかの理由と、これから引数を使った正しいソースコードを書く。

```
stock_price =1000

def stock_price_with_corporate_tax
  corporate_tax = 0.3
  return stock_price + stock_price * corporate_tax
end

stock_price_with_corporate_tax
```




エラーが起きた原因は、stock_price=1000がメソッド内で使われていたから。
引数を使い訂正した正しいコードはこちら。

```
stock_price =1000

def stock_price_with_corporate_tax(stock_price)
  corporate_tax = 0.3
  return stock_price + stock_price * corporate_tax
end

stock_price_with_corporate_tax（stock_price）
```

メソッド外の変数はメソッド内では使えない。
def定義の外で中の値を使うとエラーになるので引数が必要になる。
プログラムの仕組み　

## プログラムとは
:::note
何かをする順番を示す
EX)運動会のプログラムと同じ
:::

プログラム：命令とデータの集合体

## よく聞くマシン語とは

コンピュータが解釈できる電気信号となったプログラムのこと

## 実行までの流れ

::: note warn
【前提】
プログラムがハードディスクなどのディスク媒体に保存されるとき
**電気信号→磁気信号へと変換される**
:::

メインメモリのディスク媒体に保存された**磁気信号**は
↓
**電気信号**へと変化し
↓
メモリにコピーされ
↓
実行される






------

参考文献
プログラムはなぜ動くのか / 矢沢久雄著
GitHub Actionsを使用したHerokuに自動デプロイする方法

## 概要
GitHub Actionsを使用し、GitHubからHerokuへの自動デプロイを設定する方法を記述致します。

## 前提条件
まず、以下の条件を満たしていることを確認して下さい。

- Heroku CLIがインストールされている。
- Herokuアカウントを所持している。
- HerokuにデプロイしたいアプリケーションがGitHubリポジトリに存在する。

## 方法
### 1. HerokuのAPIキーを取得
Herokuのダッシュボードにログインし、右上のアイコンをクリックし、「Account settings」を選択します。
そこで「API Key」セクションを見つけ、"Reveal"をクリックし、APIキーを表示します。
このキーをメモしておきます。

### 2. GitHubのリポジトリにSecretsを追加
リポジトリのメインページで「Settings」タブを選択し、「Secrets」をクリックします。
"New repository secret"をクリックして、新しいシークレットを追加します。
シークレットの名前は 
- `HEROKU_API_KEY` とし、先程メモしたAPIキーを値として入力。
- `HEROKU_APP_NAME`というシークレットを作成し、その値としてHerokuアプリケーションの名前を入力。

### 3. GitHub Actionsのワークフローファイルを作成
GitHubリポジトリのルートに `.github/workflows` というディレクトリを作成し、その中に`ワークフローファイル`（例えば、`deploy.yml`）を作成します。
以下はそのワークフローファイルの一例になります。

```yaml:deploy.yml
name: Deploy to Heroku
on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Login to Heroku
        uses: akhileshns/heroku-deploy@v3.12.12 # This is the action
        with:
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
          heroku_email: "your-email@example.com"
```
heroku_emailのところには`herokuで使用しているメールアドレスの置き換えて下さい。
これにより、GitHubのmainブランチにプッシュされると、新しいバージョンのアプリがHerokuに自動的にデプロイされるようになります。

### 4. ワークフローファイルをGitHubにプッシュ

以上の設定をリポジトリにコミットしてプッシュします。するとGitHub Actionsが自動的にワークフローを読み込み、設定に従ってアクションを実行します。

### 5. 実行の確認
実行されたことを確認するには、Githubのレポジトリのタブの「Actions」を参照して確認致します。
ここで、過去の実行されたワークフローを確認する事がし、完了です。

これがGitHub Actionsを使用してHerokuに自動デプロイする基本的な手順ですが、各プロジェクトの要件により設定内容が異なるため、必要に応じて適宜調整するとよいと思います。

## 参考
- [GitHub Actions を使用してデプロイする](https://docs.github.com/ja/actions/deployment/about-deployments/deploying-with-github-actions)
- [Git Hub Actions入門](https://zenn.dev/hashito/articles/7c292f966c0b59)
- [GitHub Actionで自動デプロイ](https://qiita.com/keninph1/items/33c2c871ca884cfa58b1)
- [10分で学ぶ GitHub Actionsの超基本！ ファイルを置くだけでかんたん実行！](https://youtu.be/Vaslap4nHh0)