OmniAICreator/Qiita-1.07M huggingface dataset:
【HTML/CSS/Gitコマンド】個人的に忘れがちなところまとめ

##はじめに
DMMWEBCAMPの専門技術コースを卒業し、転職しましたが、
現在働きながら、PHPのコースを受講しております。
（業務ではRubyやPHPには全く触れていません）

####使わないと忘れる
まずは GitコマンドやHTML/CSSの学習からしていますが、専門技術コース受講時に学んでいたにも関わらず、「そういえばそうだった・・・」等、忘れていた箇所をまとめていきます。



##:point_up:Gitコマンド系

####ターミナル：「↑」
ターミナルやGitBashで利用。
↑を押すと前回実行したコマンドが表示される。
そういえばそうだった・・・。

#### git init の意味
:frowning2:git addは覚えてたけどgit initって何だったっけ？？
git initは、リポジトリを新規作成するコマンドで、
git initすることで、ローカルリポジトリとして登録される。
.gitというリポジトリに必要な内容が入っているディレクトリが作成される。
これに関しては、どういう目的でやっているのかを忘れておりました。

####コマンド：ファイルへの追記 "echo"
以下のコマンドでREADME.mdにhogeeeeee追記できる
echo "hogeeeeee" >> README.md 

##:point_up:HTML/CSS系

###インライン要素の中央揃えは　"text-align:center;"
ブロック要素とインライン要素で、中央揃えの仕方は違う。
###画像"img"もインライン要素
画像のimgタグはインライン要素なので、テキストと同じ扱い。
親要素に、text-align: center; を設定します。
:writing_hand:"""親要素"""指定

https://www.homepage-tukurikata.com/css/text-align.html


https://koshian-toast.com/margin-auto/

###HTML内部のmain要素
:frowning2:あまり使用できてなかったような気がします。
bodyの中はdivだらけでmainのように、ここがmainのコンテンツですよーと
明示的には記述できてなかった気がします。

```:HTML
<main>
 ”ページ内の中心的なコンテンツ”
　　この中には、Webページのmainにしたい要素を収める
　　この中に　header footerがあるのはおかしい
</main>
```

###HTML内部のsection要素

```:HTML
<section>
 ”ページや記事の一部分を表す”
　 section要素には、必ず見出し要素（<h1>系）必要！
 divとは適切に使い分けること！！
</section>
```

https://www.tagindex.com/html5/section/section.html

###CSS:ある要素の中のdiv

testクラス内のdivにCSSを適用させたい場合、

```:CSS
testクラス直下にあるdiv要素を指定
.test > div {
  width: 33%;
  height: 300px;
}
```

https://www.asobou.co.jp/blog/web/css-selectors

###CSS:ある要素の中の最初の要素

```
ヘッダーの中の最初の要素
header>:first-child{
  margin-right: auto;
}
```

https://www.vanfu-vts.jp/blog/2014/09/first-child_last-child/



###flex-basis　
flex-basis
フレックスアイテムの横幅を指定
flex-basis:120px;みたいな感じ

https://developer.mozilla.org/ja/docs/Web/CSS/flex-basis

###flex-grow
横幅の伸びる比率

https://developer.mozilla.org/ja/docs/Web/CSS/flex-grow

##終わり
HTML/CSSの箇所については、”誰にでも分かる＆見やすい”コードを書く上では必要な知識だったのに、
何だか忘れてたり、何となく覚えてはいるけど使えていなかったりしましたので、
今回しっかりと復習できてよかったです！！
<h6>使わなくても目的は達成できるけど、ちゃんと使って覚える。</h6>
1分で地図を作成する【Leaflet.js】

# Leafletとは
LeafletとはオープンソースのJavaScriptライブラリで、
地図を描画することができる

**公式リファレンス**
https://leafletjs.com/index.html

# 地図を描画する
- HTMLのheadタグ内でLeafletのcssとjsを読み込む

```HTML
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css">
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
```

- HTMLのbodyタグ内に地図を描画するタグを追加

```HTML
<body>
 <div id='mapcontainer'></div>
</body>
```

- JavaScriptで地図を描画する

```JavaScript
// 画面読み込み時実行
window.onload = () => {
  // Leafletの地図オブジェクト作成
  // 地図を表示するdiv要素のidを設定
  const map = L.map('mapcontainer');
 
  // 地図の中心緯度経度とズームレベルを指定
  map.setView([35.40, 136], 5);

  // タイルレイヤ(国土地理院地図)の設定
  const mapApi = "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png";
  const tilelayer =   L.tileLayer(mapApi, {
          attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"
      })

  // タイルレイヤを地図に追加
  tilelayer.addTo(map);   
}
```
nuxtプロジェクトでサブディレクトリにtsconfig.jsを配置した時のimportエラーを解消する

##動作環境
エディタ：VScode
nuxt.js2系 + typescript

##現象
プロジェクトのサブディレクトリにnuxtアプリケーションを作成。
コンポーネントをimportで読み込もうとするとエラーになる。

```javascript:sample.vue
<script lang="ts">
import ButtonMedium from '@/components/ui/ButtonMedium.vue';

export default {
 //
};

```

エラー内容

```
Cannot find module '@/components/ui/ButtonMedium.vue' or its corresponding type declarations.Vetur(2307)
```

##原因
VScodeのVeturが原因でした。
デフォルトの設定では、tsconfig.jsがルートディレクトリに存在していないと、Veturがtsconfig.jsを読み込むことができず、パス解決ができません。

##解決方法
vetur.config.jsでrootの設定を変更してあげればOKでした。


###nuxtプロジェクトのディレクトリ構成

```
nuxtProject
├── application //nuxtアプリケーション
├── docker
├── docker-compose.yml
└── vetur.config.js
```

###vetur.config.jsの設定
```javascript:vetur.config.js

/** @type {import('vls').VeturConfig} */
module.exports = {
  // **optional** default: `{}`
  // override vscode settings
  // Notice: It only affects the settings used by Vetur.
  settings: {
    "vetur.useWorkspaceDependencies": true,
    "vetur.experimental.templateInterpolationService": true
  },
  // **optional** default: `[{ root: './' }]`
  // support monorepos
  projects: [
    {
      // **required**
      // Where is your project?
      // It is relative to `vetur.config.js`.
      root: './application/', //ここをnuxtアプリケーションのルートを指定
      // **optional** default: `'package.json'`
      // Where is `package.json` in the project?
      // We use it to determine the version of vue.
      // It is relative to root property.
      package: './package.json',
      // **optional**
      // Where is TypeScript config file in the project?
      // It is relative to root property.
      tsconfig: './tsconfig.json',
      // **optional** default: `'./.vscode/vetur/snippets'`
      // Where is vetur custom snippets folders?
      snippetFolder: './.vscode/vetur/snippets',
      // **optional** default: `[]`
      // Register globally Vue component glob.
      // If you set it, you can get completion by that components.
      // It is relative to root property.
      // Notice: It won't actually do it. You need to use `require.context` or `Vue.component`
      globalComponents: [
      ]
    }
  ]
}
```

以上。

参考
https://zukucode.com/2021/02/vscode-vetur-subdirectory.html
［AWS］CodeBuild,CodeDeploy,CodePipeline攻略問題

#問題
問1. CodeBuildにおいてビルドプロジェクトは[A]を、buildspec.ymlファイルは[B]の設定を行う。以下からそれぞれに当てはまるものを選択せよ。
a. 実行環境の準備
b. 実行コマンド
c. デプロイ先の指定
d. ソースコードの作成

問2. CodeDeployの中で登場する「リビジョン」とはCodebuildが出力した[A]である。答えよ。

問3. CodeDeployの使用に必要な作業は、デプロイ先の対象インスタンスへ[A]をインストールすることと、[B]ファイルを作成することである。答えよ。

問4. 通常CodeBuildの主力アーティファクトはCodeBuildのコンソールにて[A]を、buildspec.ymlにて[B]を定義する。答えよ。
 
問5. CodePipelineにより、CodeDeployの[A]を設定する必要がない。答えよ。

#解答
問1. [A]実行環境の準備,[B]実行コマンド
問2. [A]出力アーティファクト(一旦S3などに保存される)
問3. [A]CodeDeployエージェント,[B]appspec.yml(対象インスタンスへのデプロイ方法が記述される)
問4. [A]出力パスやファイル形式,[B]アーティファクト名
問5, [A]リビジョン
ネットワーク用語　ケーブル

通信媒体
　　通信を行うための媒体
　　機器同士を優先で接続する場合はケーブルが通信媒体になる
　　無線の場合は電波が通信媒体になる

UTPケーブル
　　Unshielded Twisted Pairの略
　　一番身近なケーブルでLANケーブルと言われる
　　１００BASE-TX
　　１０００BASE-TX
　　１０GBASE-T
　　安価である
　　取り回しがしやすい
　　最大長は１００m
　１００mを超えるとレイトコリジョン発生のリスクがある

光ファイバーケーブル
　　高価
　　取り回しが難しい
　　最大長数１０Km
　　シングルモード
　　　　コアが細い
　　　　高速、超長距離
　　　　配線作業が難しい
　　マルチモード
　　　　コアが太い
　　　　中速、中長距離


データの衝突(コリジョン)
　　データは早い者勝ちで送ることができる
　　皆が一斉にデータを送信した際にデータの衝突が怒ることがある
　　ルールを作り待ち時間を作った
　　一定時間待ち、問題なければデータを送信する
　　待ち時間(プリアンブル)
　　　　　送りたいデータの前にプリアンブルのデータを送り、正しく送れたら自分のデータを送信する
　　　　　途中でコリジョンが起きたらデータを送信しない
　　　　１００m以上離れたところでコリジョンが発生したら、正しく送信できたと勘違いしてデータを送信してしまう
時間範囲指定のバリデーション

# 概要
フォーム入力で「09:00 - 18:00」のような時間を指定する際のバリデーション

#　結論
```
^([01][0-9]|2[0-3]):[0-5][0-9]\s-\s([01][0-9]|2[0-3]):[0-5][0-9]$
```

# 参考
* [日付および時刻の正規表現](https://www.javadrive.jp/regex-basic/sample/index6.html#section2)
vue : このシステムではスクリプトの実行が無効になっているため～　PowerShellからVueプロジェクトが作れない原因を解消

#解消方法

以下の命令をPowerShellで実行
Set-ExecutionPolicy RemoteSigned -Scope Process

おかげさまで以下の記事を見て一発で解消できました。このコマンドはセキュリティポリシーを一時的に変更しているようです。

https://qiita.com/kadotaoru/items/0fac22195b925a1b0a83


#備忘録

メモ：なぜかvue　～～のコマンドをPoweShellに入力すると以下のログが出てきました。

発生ログ
vue : このシステムではスクリプトの実行が無効になっているため、ファイル C:～～～～～～～ を読み込むことができません。詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
発生場所 行:1 文字:1
+ vue -v
+ ~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess


ログに出てきたサイトを見てみるとPoweShellで悪意のある事を実行しないようにセキュリティにひっかけてるようです。

https://go.microsoft.com/fwlink/?LinkID=135170

#ついでに
実行ポリシーの確認方法


```
PS C:\> Get-ExecutionPolicy -List
```

以下の記事が参考になりました。

https://qiita.com/earthdiver1/items/b3f529c81f5892972a72
ネットワーク用語　通信方式

ユニキャスト
　　１体１の通信
　　例：電話
ブロードキャスト
　　１対不特定多数の通信
　　ブロードキャストは届く範囲が決まっている。
　　例：学校の全校放送
マルチキャスト
　　１対特定のグループの通信
　　ブロードキャストを多用するとデータ量が多くなりデータ損失が起こりやすくなるためマルチキャストを使ってデータ量を減らす
　　例：学校のクラス内放送
エニーキャスト
　　１対特定のグループの中の最適な(ネットワークが近い)１人との通信
　　最初はエニーキャストで通信されるが、返信はユニキャストになり、その後ユニキャスト通信になる
　　例：DNSルートサーバーへの通信

DNSルートサーバー
　　世界に１３台あり１つのグループを作っている
　　DNSルートサーバー内で通信を行うときにエニーキャストで通信を行う
　　日本からの通信であれば一番近い日本のDNSルートサーバーからユニキャストで返信が来る
Power Automate + Forms + Onedrive + Excel online で作る勤怠システム（準備・仕組み 編）

# 目次
- [こんな方へオススメ](#こんな方へオススメ)
- [はじめに](#はじめに)
- [背景](#背景)
- [準備するもの](#準備するもの)
- [仕組み](#仕組み)
- [まとめ](#まとめ)
- [リンク](#リンク)
- [参考文献](#参考文献)

# こんな方へオススメ
- 本記事にご興味を持った方
- 勤怠入力でお困りの方
- Microsft製品をご利用されている方
- なるべくお金を掛けずに業務改善を行いたい方 ...

# はじめに
　本記事を見つけて頂き、ありがとうございますm(_ _)m
　本記事では、<font color="Magenta">**Power Automate(web) + Forms + Onedrive + Excel online で作る勤怠入力システム**</font>を紹介します。[準備するもの](#準備するもの)の操作に自信がなくても作成できるはずの内容となっております。
　文量が多くなるので幾分かの記事に分けて紹介します。今回は準備と仕組みについてです。

# 背景
　コロナの影響でリモート業務が増えるなか他部署より「お金を掛けずにPC、スマホのどちらからでも勤怠入力仕組み作れない？」と話が回ってきました。
　そこでMicrosoft製品を組み合わせるで作れないかと考えたところ、タイトルにあるような組み合わせで作成できることに気付き、実際に作成し、運用することとなりました。せっかくなので共有します。

# 準備するもの
#### 運営側
- Microsoftアカウント（下記のアプリを使用できるライセンス）
 - Power automate（Web版）
 - one drive(Sharepointでも可)
 - Excel online
 - Forms
<br>※ライセンスについては[こちらへ](https://docs.microsoft.com/ja-jp/power-platform/admin/power-automate-licensing/faqs#what-power-automate-capabilities-are-included-in-office-365-licenses)

#### 利用者側
- Microsoftアカウント（作成方法は[こちら](#https://www.onamae-office.com/guide/p/8)）
アカウント名は 「社員番号@ドメイン」で作成ください。
社員番号が数字のみの場合は桁数を統一してください。でないと、Automateが誤作動を生じる場合があります。
例：最大値が4桁であれば　社員番号12→0012 　
※アカウントは<font color="Magenta">**ライセンス付与なしで**</font>作成ください

# 仕組み
　以下の図を参考ください。
![qiita1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167400/8a959802-10de-0585-487d-a53229b0a498.png)

# まとめ
　今回は準備・仕組みについての内容となりました。次回より各セクションや機能について詳細な説明を行います。
　Automateが利用可能なライセンスについては把握しきれていないので、まずはOffice365のメニュー欄にてPower Automateがあるかを確認するのが手っ取り早いと思います。なければ「power automate web」とググってみてください。

# リンク
- [Excel 編（タイムシート）](https://qiita.com/crispy_1741/items/6db3cdfe09d43c9559d3)
- [Forms 編](https://qiita.com/crispy_1741/items/745f711bb3fa80a08df8)
- [Power Automate 編](https://qiita.com/crispy_1741/items/8b91c6fa2df111f1f4d9)

# 参考文献
【Google Analytics】どのリンクがクリックされたかを区別する方法

## 対象読者

- ブログへのアクセスをGoogleAnalyticsで集計している人
- どのリンクから訪問してきたのか、流入元を調べたい人

## 「クエリ文字列」で区別する

### クエリ文字列とは？
**クエリ文字列**とは、URLの末尾につけ足す文字列のことです。
「?」をURLの末尾につけ、その次に好きな文字列をつけます。

具体的な例を見てみましょう。

https\://my_blog.foo/0123456789/**?profile**

太字で示した部分がクエリ文字列です。

もしかすると、
「勝手に文字列を追加して大丈夫なの？」
「違うページに飛んだりしないの？」
と思う人もいるかもしれませんが、安心してください。

「?」以降の文字列はWebページの表示には影響しません（動的ページは例外）。

なので、クエリ文字列がついていようがいまいが、きちんと同じページが表示されます。

### クエリ文字列の活用方法

では、このクエリ文字列を利用して流入元を区別してみます。

例えば、**ページA**と**ページB**がそれぞれあったとします。
そして**ぺージA，B**それぞれには**ページC**という記事へのリンク（https\://my_blog.foo/page_c/）が１つずつ貼ってあります。

この場合、

**ページA** ⇒ **ページC** (https\://my_blog.foo/page_c/) 
**ページB** ⇒ **ページC** (https\://my_blog.foo/page_c/)

というページ遷移が考えられますが、この２つは通常区別することができません。

どちらの場合も、Google Analyticsでは
/page_c/
のように、まとめて集計されてしまいます。

そこで、クエリ文字列を付加したURLへ変更してみます。

例えば、
**ページA**には
https\://my_blog.foo/page_c/**?from_page_a**
**ページB**には
https\://my_blog.foo/page_c/**?from_page_b**
というリンクを貼っておきます。

すると、GoogleAnalyticsにはクエリ文字列付きのURL
/page_c/?from_page_a
/page_c/?from_page_b
のように、別々に集計されているはずです。

こうすれば、どのページからアクセスがあったのかを区別することができるようになります。

## Googleスプレッドシートで経過観察する方法

ついでに、クエリ文字列をつけたリンクのアクセス情報のみを抽出して管理する方法も紹介します。

ここでは、Googleスプレッドシートのアドオン機能を使います。

まず、[Googleスプレッドシート](https://docs.google.com/spreadsheets/create?hl=JA)へアクセスします。

アクセス出来たら、画面上部のメニューバーから
「拡張機能」＞「アドオン」＞「アドオンを取得」
をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/2d28f1c0-6a8d-53a7-fdf4-6520accad72f.png)

上の検索窓で「Google Analytics」と入力すると、一番最初に「Google Analytics」のアドオンが表示されるのでそれをクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/c93af36a-2f29-63d2-eb28-fd0677927ae6.png)

そのままインストールします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/146f0578-d33c-bf1f-c2fb-0326f3624a78.png)

すると、拡張機能のところに「Google Analytics」が追加されていると思うので、そこから「Create new report」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/e035e791-523f-432e-99b2-ce22af6d9a87.png)

レポートの名前を適当に入力し、集計したい指標などを選択していきます。

今回は例として

- PV
- 平均ページ滞在時間
- 離脱率

をMetricsで指定しました。

Dimensionsは「Page」を選択しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/64a7dac9-fb7e-eab7-2424-02f49ecd01ea.png)

次に、
「拡張機能」＞「Google Analytics」＞「Run reports」
を選択すると、新たなシートが作成されて集計結果が見られるようになります。

ここからはスプレッドシートの **[QUERY関数](https://strategy-conference.com/analysis/spreadsheet/1257/)** を駆使して、自分が見たいURLのみを抽出します。

先ほど紹介したURLの例なら、セルA2に

=QUERY('link clicks'!A16:D5000,"SELECT * WHERE A contains '/page_c/?'")

と入力します。すると「/page_c/?」という文字列が含まれるURLのみが抽出されます。
ネットワーク用語　OSI参照モデル

ネットワーク基礎

OSI参照モデル
アプリケーション層
  メールやファイルや動画など利用するアプリケーションを規定する。
プレゼンテーション層
　　同じ０．１の情報でも機器が違うと意味が違ってくるので、機器毎の表現形式を規定する
セッション層
　　データを一度に全部は送れないので、分割する必要がある。その分割の切れ目を規定したり、何度も通信する際の接続を繋いだり切ったりを規定する
トランスポート層
　　宛先まで確実にデータを届ける方法を規定する
ネットワーク層
　　いくつかのネットワーク機器を経由する際に、宛先までの最適なルートを規定する
データリンク層
　　直接繋がっている機器間でデータを送り出したり受け取ったりを規定する
物理層
　　０、１を電気信号や光の点滅に変えたり、逆に電気信号や光の点滅を０、１にする。
　　コネクタやケーブルの形状を規定するの。
Pythonで複数入力（無限入力）を実行する方法

```python:test.py
import sys

lines = []
for l in sys.stdin:
    lines.append(l.rstrip('\r\n'))
```

上記のようなコードでは、

```
python test.py
```
のように実行しても無限に入力を受け付けてしまい、最後まで実行できませんでした。
（追記）Linux・Macの場合はCtrl+D、Windows なら Ctrl+Zでできました。コメントありがとうございます。

下記でも実行できます。


```
echo "test1.txt" "text2.txt" | python test.py
```

参考：https://stackoverflow.com/questions/43554363/how-to-run-code-with-sys-stdin-as-input-on-multiple-text-files
PythonでDependency Injectionを実装する

備忘録としてDependency Injectionの基礎知識とPythonでの実装方法を整理します。


## 環境
- Python 3.8.10


### DIとは？

``` Dependency Injection``` の略です。具体的に言うと、クラスAで利用するインスタンスをクラスAの内部で生成するのではなく、抽象に依存させて外部から渡すことです。

サンプルコードを見てみましょう。

#### 悪い例

```main.py

class Cat():
    def __init__(self, name: str):
        self.name = name 
    
    def cry(self):
        print(f'{self.name} cry meow meow.')

class A():
    
    cat1 = Cat("ハチワレ")
    
    def action(self):
        self.cat1.cry()

if __name__ == "__main__":
    a = A()
    a.action()
```

Aクラスの内部でCatクラスインスタンスを生成し、cryメソッドを呼び出しています。
動作上は問題ありませんが、この実装だと猫の名前を変えるたびにAクラスを変更しなければなりません。名前が変わったというCatクラスの事情がAクラスに影響しています。

CatクラスとAクラスが密結合になっており、保守性が低い状態です。

そこで、以下ように変更します。

1. Aクラスインスタンスに外部からCatクラスインスタンスを渡す
1. AクラスではCatクラス(具象)ではなく、Animalクラス(抽象)に依存する。

変更後のコードがこちらです。

#### 良い例

```main.py
from abc import ABCMeta, abstractmethod

#抽象クラス
class Animal(metaclass=ABCMeta):
    
    @abstractmethod
    def cry(self):
        pass
    
# 抽象クラスを実装した具象クラス
class Cat(Animal):
    def __init__(self, name: str):
        self.name = name 
    
    def cry(self):
        print(f'{self.name} cry meow meow.')

class A():
    
    # 抽象クラスに依存する
    def __init__(self, animal: Animal) -> None:
        self.animal: Animal = animal 
    
    def action(self):
        self.animal.cry()

if __name__ == "__main__":
    
    # 抽象型としてCatインスタンスを生成する
    cat: Animal = Cat("ハチワレ")
    a = A(cat)
    a.action()
```

Catクラスの変更がAクラスに影響しにくい設計になりました。
(Catクラスのプロパティが変わってもAクラスはそれを知らなくても問題ない)

### DIのメリット

① クラス同士を疎結合に保ちやすい。

サンプルコードで確認した通り、DIを使うと依存先クラス(サンプルの場合はCatクラス)の変更が依存元クラスに影響しにくくなります。変更時の影響が小さくなるのでプログラムを修正しやすくなるのが嬉しいです。

② 単体テストをしやすい

「DIのメリットはテストがしやすくなる」とよく言われますがこれには2つの意味があると思われます。1つはクラス同士が疎結合になることでテスト観点が明確になるという意味です。もう1つは依存対象のオブジェクトを外部から渡すことができるため、テスト用のモックを利用できるという意味です。

テスタビリティ向上はDIを採用する目的として大きいでしょう。

### DIのデメリット

#### 依存対象が増えると辛い

サンプルコードではAクラスがAnimalクラスにのみ依存しているため気になりませんが、Aクラスが複数のクラスに依存する場合面倒なことになります。

依存先クラスのインスタンスを全て生成→ Aクラスのインスタンスを生成する時に引数に渡す という手順が必要になります。

実装コストが増える他、コードの可読性が下がります。

この問題を解決するためにDIコンテナやサービスロケーターという実装パターンが採用されることが多いです。DIコンテナについては別の記事で扱おうと思います。
pyenvとvenvを使って簡単にプロジェクト専用の環境構築をする

Pythonのパッケージを使いたいが、自分が使っているPythonのバージョンと互換性がなかったり、手持ちのパッケージの新しい/古いバージョンに依存していたりと色々と面倒な思いをすることは往々にしてある。そこで

- Pythonのバージョンを自由に切り替えられるようにpyenvを
- Pythonパッケージのバージョンを自由に切り替えられるようにvenvを

使う。

# pyenvのインストール

まずインストールする。Macならhomebrewで入れれば良い。

```bash
brew install pyenv
```

MacでなくLinuxとかなら

```bash
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
```

で入れる。

```bash
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
```

を実行しておいてから、

```bash
pyenv install --list
```

を実行してPythonの利用可能なバージョン一覧が出力されたら成功。

# pyenvで任意のバージョンのPythonをインストール

すでにマシンに入っているPythonのバージョンとは違うバージョンでPythonを使いたいと思ったら、上記コマンドの出力結果の中からバージョンを選んで

```bash
pyenv install [バージョン]
```

を実行すれば今後それを使うことができるようになる。

```bash
pyenv versions
```

の結果に指定したバージョンが入っていれば成功。

ちなみにインストールしたバージョンを消すには`~/.pyenv/versions/`の中から当該バージョンを`rm`すればOK。

# プロジェクト用のPythonバージョンに切り替える

ここからはプロジェクト毎に行う。
すでにマシンに入っているPythonのバージョンとは違うバージョンでPythonを使いたいときは、プロジェクトの作業ディレクトリに入ってから

```bash
pyenv local [バージョン]
```

でバージョンを切り替える。


```bash
python3 --version
```
の結果が指定通りのバージョンになっていたら成功。

# venvでパッケージを切り替える

作業ディレクトリにて、pyenvでバージョンを切り替えた状態で以下を実行すると`.venv`ディレクトリができる。これが仮想環境のディレクトリである。

```bash
python3 -m venv .venv
```

あとは仮想環境をアクティベートすればそのプロジェクト用に好き放題`pip3 install`して良くなる。

```bash
source .venv/bin/activate
```

ちなみに仮想環境から抜ける時は

```bash
deactivate
```

すればよく、仮想環境自体を消したければ`.venv`ディレクトリを`rm`すればOK。

ところで、pip installがうまくいかないことがある。その場合は、pipのバージョンが古かったり、Pythonのバージョンとして正しいものを使っていなかったりというのが原因であることが多い。それらのバージョン更新というのは自分でやるとして、何かバージョンを指定してインストールしようとしてうまく行かなかったときはURLを指定してインストールする方法がある。([参考](https://kajindowsxp.com/pip-unable/))

# 今後簡単にセットアップできるようにする

以下のようなスクリプトを作業ディレクトリに入れておく。（普通は`~/.bash_profile`などに書き込むが、必ずしもいつもpyenvを使いたいわけではないので自分はこうしている。）

```bash:setup.sh
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
pyenv local [使いたいPythonのバージョン]
source .venv/bin/activate
```

今後新しいシェルでプロジェクトを使うときは最初に`source setup.sh`すればよい。

# 参考にしたサイト

https://qiita.com/koooooo/items/b21d87ffe2b56d0c589b

https://zenn.dev/kenghaya/articles/9f07914156fab5

https://kajindowsxp.com/pip-unable/
wheelグループとsudo

sudoするためにwheelグループに追加してみた。
https://qiita.com/Esfahan/items/a159753d156d23baf180

```
usermod -aG wheel kubota
```

「usermod -G」は危険だそうです。
https://qiita.com/tk1024/items/16e98031b84a31df469b

パスワードありでsudoにしました。
温湿度マップでの部屋の状態の見え方

温湿度マップという部屋の状況を一目でわかるインターフェイスが作れたので、部屋の状態がどのように温湿度マップで表示されるか記載したいと思います。

* 温湿度マップは、温度(縦軸) vs 湿度(横軸)の2次元マップです
* 絶対湿度と熱中症指数の危険度によって色分けした画像のうえに温湿度データをマップすることで、一目で部屋の状態がわかります
* ●部分が現在、線は過去3時間の変遷を示しています

![温湿度マップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/e9f30eff-5a19-78b3-5514-2c581bacde03.png)

* 温湿度マップの作り方は以下ページを参照ください

https://qiita.com/tosshie/items/6adf6d533527674aef2a

#### 加湿器とエアコンで部屋の温度を上げたとき

* エアコンのみで温度を上げたときは、右下から左上に向かって（絶対湿度は変わらずに）温度が上がります
* エアコンと加湿をしたときは、左下から右上に向かって（絶対湿度も上がりながら）湿度も温度も上がります

![エアコン2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/803281f5-0490-60ed-a7e1-ec5ae0eb3030.png)

#### クローゼットの換気

* クローゼットの相対湿度があがってしまってカビが生えないように、ある一定の相対湿度になったらクローゼットを換気するシステムを作りました。
* クローゼットの温湿度データ(黄色とオレンジ)が、相対湿度がぐんぐん上がっていったところで曲げられて相対湿度が下がっています
    * クローゼットの中が寒いと、部屋の暖かい空気が入ったときにクローゼットの中の相対湿度が高くなるので、クローゼットの空気を温めることで相対湿度を下げています（クローゼットの中に部屋の空気をサーキュレータで送り込んでクローゼットの中の空気を上げています）


![クローゼット換気.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/cc418e94-dafc-05bb-09bf-6ca87847a097.png)

* クローゼットの換気システムについては以下記事を参照ください

https://qiita.com/tosshie/items/3a830e30f4381d9e1e4b


#### 冬の雪の日は屋外も絶対湿度で見ると低い

* 雪の日の屋外の湿度は90%などになりますが、絶対湿度で見ると(気温が低いので)とても低いです。

![屋外で雪.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/cf62a1e2-670a-c763-93d5-441ad38230eb.png)
C# Splitを使って文字列を文字数で分割できるか？

できません。orz
セパレーター（char）が無いと何ともできません。
不便なのでSplitByLengthなる関数を作ったりしましたが、拡張メソッドのほうが格好良くね？
ということでネットで調べて作りました。

【追記】
最初の投稿にいくつかコメントをいただきまして、勝手に完成度の高いものになってしまいました。
Qiita恐るべしです。
#サロゲートペアに対応
@ktz_aliasさんからサロゲートペアがあると文字化けするとコメントとコードをいただきました。
サロゲートペアって何？美味しいの？ってくらいに知らなかったんですが、4バイト文字だったのね。
@ktz_aliasさん、ありがとうございました。

~~~C#:丸写し
    public static class StringExtensions
    {
        /// <summary>
        /// 指定の文字数で分割
        /// </summary>
        /// <param name="value">分割する文字列</param>
        /// <param name="maxLength">分割する文字数</param>
        /// <returns>配列</returns>
        public static IEnumerable<string> Split(this string value, int maxLength)
        {
            var info = new StringInfo(value);
            var len = info.LengthInTextElements;

            var p0 = 0;
            var p1 = maxLength;

            while (p0 < len)
            {
                if (p1 > len)
                {
                    p1 = len;
                }

                yield return info.SubstringByTextElements(p0, p1 - p0);

                p0 = p1;
                p1 += maxLength;
            }
        }
    }
~~~
#.NET6版（サロゲートペア非対応）
@htsignさんから、.NET 6からChunkメソッドが使えると教えていただきました。
サロゲートペアがなんぼのもんじゃい！という方はぜひ。
とても簡潔に記述できます。
@htsignさん、ありがとうございました。

~~~C#:こちらも丸写し
    public static class StringExtensions
    {
        /// <summary>
        /// 指定の文字数で分割
        /// </summary>
        /// <param name="value">分割する文字列</param>
        /// <param name="maxLength">分割する文字数</param>
        /// <returns>配列</returns>
        public static string[] Split(this string value, int maxLength)
        {
            return value.Chunk(maxLength).Select(cs => new string(cs)).ToArray();
        }
    }
~~~
if文でもin演算子が使える JavaScript

if文でもin演算子が使用できます。
プロパティがオブジェクトにある場合にtrueを返します。

```javascript
if ('property' in obj) {
    // 処理
}
```

例（修正前）

```javascript
const card = { type: 'mtg', color: 'white' };
console.log('type' in card);  // 出力:true

delete card.color;
if ('color' in card === false) {
	card.color = 'black';
}
console.log(card.color);  // 出力:black
```

コメントでご指摘をいただき修正した例
ifの条件でfalseと比較せずに、否定演算子を使う

```javascript
const card = { type: 'mtg', color: 'white' };
console.log('type' in card);  // 出力:true

delete card.color;
if (!('color' in card)) {
	card.color = 'black';
}
console.log(card.color);  // 出力:black
```
【備忘録】KVMコンソールで使うISOイメージ作成

【概要】
Ubuntu 20.04.3 LTSのISOをコンソール起動対応にする。

・ISOイメージを作業用エリアにコピー　

```
# mount ubuntu-20.04.3-live-server-amd64.iso /mnt
# mkdir ubuntu-20.04.3-live-server-amd64-console
# cd ubuntu-20.04.3-live-server-amd64-console
# rsync -a /mnt/ .
# umount /mnt
```

```
# ll
total 80
dr-xr-xr-x 11 root root  4096 Aug 24  2021 ./
drwxrwxrwx  5 root root  4096 Feb 23 10:24 ../
dr-xr-xr-x  2 root root  4096 Aug 24  2021 .disk/
dr-xr-xr-x  3 root root  4096 Aug 24  2021 EFI/
dr-xr-xr-x  3 root root  4096 Aug 24  2021 boot/
dr-xr-xr-x  3 root root  4096 Aug 24  2021 casper/
dr-xr-xr-x  3 root root  4096 Aug 24  2021 dists/
dr-xr-xr-x  2 root root  4096 Aug 24  2021 install/
dr-xr-xr-x  2 root root 12288 Feb 23 10:35 isolinux/
-r--r--r--  1 root root 27368 Aug 24  2021 md5sum.txt
dr-xr-xr-x  3 root root  4096 Aug 24  2021 pool/
dr-xr-xr-x  2 root root  4096 Aug 24  2021 preseed/
lrwxrwxrwx  1 root root     1 Aug 24  2021 ubuntu -> ./
```

・コンソール対応にファイル変更１(isolinux.cfg)
　ui gfxboot bootlogo行をコメントアウト

```
# vi isolinux/isolinux.cfg
path
include menu.cfg
default vesamenu.c32
prompt 0
timeout 50
#ui gfxboot bootlogo ←コメント

```

・コンソール対応にファイル変更１(txt.cfg)
　下記を追加
　serial 0 115200
　console=tty0 console=ttyS0,115200n8

```
# vi ./isolinux/txt.cfg
serial 0 115200
default live
label live
  menu label ^Install Ubuntu Server
  kernel /casper/vmlinuz
  append   initrd=/casper/initrd quiet console=tty0 console=ttyS0,115200n8  ---
label hwe-live
  menu label ^Install Ubuntu Server with the HWE kernel
  kernel /casper/hwe-vmlinuz
  append   initrd=/casper/hwe-initrd quiet  ---
label memtest
  menu label Test ^memory
  kernel /install/mt86plus
label hd
  menu label ^Boot from first hard disk
  localboot 0x80

```

・ISＯイメージ作成
　ubuntu-20.04.3-live-server-amd64-console.isoでISOを作成

```
# mkisofs -r -l -J -o ../ubuntu-20.04.3-live-server-amd64-console.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table .
```
EC2の拡張ネットワーキングに関して

## はじめに
AWSのコンピューティングサービスであるEC2インスタンスの大半は拡張ネットワーキングがサポートされている。拡張ネットワーキングとは簡単に言えば有効化するだけでインスタンスのネットワークパフォーマンスが向上する機能である。利用にあたり追加料金がかからないのもメリットの一つ。本記事では拡張ネットワーキングに関してまとめておく。


## 拡張ネットワーキングとは何か？

SR-IOVによってネットワークのパフォーマンスを向上させる技術

- AWSドキュメントより
```
拡張ネットワーキングでは、シングルルート I/O 仮想化 (SR-IOV) を使用して、サポートされるインスタンスタイプにおける高性能ネットワーキング機能が提供されます。
SR-IOV は、従来の仮想化ネットワークインターフェイスと比較し、I/O パフォーマンスが高く、CPU 利用率が低いデバイス仮想化の手法です。
拡張ネットワーキングは、高い帯域幅、1 秒あたりのパケット (PPS) の高いパフォーマンス、常に低いインスタンス間レイテンシーを実現します。
```

## 利用するための条件は？

現行のインスタンスタイプであれば利用可能

- Linux
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instance-types.html#current-gen-instances

- Windows
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/instance-types.html#current-gen-instances


## 拡張ネットワーキングのタイプ

拡張ネットワーキングはインスタンスタイプによって以下のいずれかのインターフェイスをサポートしている
- Elastic Network Adapter (ENA)
  - 最大100Gbpsのネットワーク速度をサポート
- Intel 82599 Virtual Function (VF) インターフェイス
  - 最大10Gbps のネットワーク速度をサポート

インスタンスタイプ別にサポートされているインターフェイスに関しては以下URLにある表の**拡張ネットワーキング**列を参照

- Linux
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instance-types.html#instance-type-summary-table

- Windows
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/instance-types.html#instance-type-summary-table

## 有効化のやり方
基本的にはサポート対象のディストリビューションのAMIでインスタンスを起動すると自動的に有効化されている。なのでインスタンスを起動した後に有効化されているか確認することが重要。

- Linux: Elastic Network Adapter (ENA)
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/enhanced-networking-ena.html

- Linux: Intel 82599 Virtual Function (VF) インターフェイス
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/sriov-networking.html

- Windows: Elastic Network Adapter (ENA)
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/enhanced-networking-ena.html

- Windows: Intel 82599 Virtual Function (VF) インターフェイス
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/sriov-networking.html
【SwiftUI】Toggleを用いてチェックボックスを作る

SwiftUIでチェックボックスを実装する方法の1つとして、ToggleStyleのカスタムクラスを追加する方法があります。

**ToggleStyleとは、Toggleの外観と動作を定義するモディファイアです**

#カスタムクラスを実装する

```swift
struct CheckboxStyle: ToggleStyle {
    func makeBody(configuration: Configuration) -> some View {
        // チェックボックスの外観と動作を返す
        return HStack {
            Image(systemName: configuration.isOn ? "checkmark.circle.fill" :
                    "circle")
                .foregroundColor(configuration.isOn ? .blue : .black)
                .font(.system(size: 28, weight: .semibold, design: .rounded))
            configuration.label
        }
        .onTapGesture {
            configuration.isOn.toggle()
        }
    }
}
```

`configuration`からisOnやlabelが取得できるので、Toggleがオンとオフの時の外観を`makeBody(configuration:)`に書いています。
`onTapGesture`を追加してタップされた時にisOnを更新します。

#カスタムスタイルを指定する

```swift
@State private var isChecked: Bool = false

var body: some View {
        Toggle(isOn: $isChecked) {
            Text("チェックボックス")
                .font(.system(.title2, design: .rounded))
                .fontWeight(.heavy)
                .foregroundColor(isChecked ? .blue : .black)
                .padding(.vertical, 12)
        }
        .toggleStyle(CheckboxStyle())
    }
```

`.toggleStyle`に作成したカスタムクラスを指定します。

# 実行結果
####isOn = false
<img width="250" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/8db1d113-c007-864a-cf29-512cc71a5891.png">

####isOn = true
<img width="250" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/3c9b1f18-c9b8-2e10-2d18-fa0f68a7eac7.png">

`makeBody(configuration:)`の返すViewを変更することで色々な見た目のチェックボックスを実装することができます。
合唱部の先生が語るチームビルディング

##前書き

今日読んだ記事、致知出版社[『1日1話、読めば心が熱くなる365人の仕事の教科書』][1]の【10月31日】目。杉並学院中学高等学校合唱部の先生、渕上 貴美子さんの語る記事の感想文です。
世界一の合唱部の先生が語る指導法に、組織のチームビルディングの真髄のエッセンスが散りばめられていたと感じたので紹介させていただきます。

[1]:https://www.amazon.co.jp/1%E6%97%A51%E8%A9%B1%E3%80%81%E8%AA%AD%E3%82%81%E3%81%B0%E5%BF%83%E3%81%8C%E7%86%B1%E3%81%8F%E3%81%AA%E3%82%8B365%E4%BA%BA%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E8%97%A4%E5%B0%BE%E7%A7%80%E6%98%AD/dp/4800912474

##【10月31日】 合唱力を高めるポイント　渕上貴美子 杉並学院中学高等学校合唱部指揮者

渕上 貴美子。教育者。合唱指揮者。杉並学院中学高等学校で教鞭をとりながら、自ら歌好きの生徒を集めて合唱部を創部したという。
同校は数々のコンクールで輝かしい成績を残している。ウィーンの世界大会でも金賞を獲得した合唱部の名門校となっている。
同校の合唱部卒業生たちで結成された「菊華アンサンブル」は、渕上の指導のもと合唱を続けたいという卒業生が集まり2000年に結成された。
参考に付すが、渕上の経歴や卒業生たちの活躍が記されている。


渕上が語るのは、タイトルの通り「合唱力を高めるポイント」。
私は合唱のことはよくわからないが、世界一の実績を持つ渕上が語るそれは組織におけるチームビルディングに役立つ話であった。
チームのマネージャーさんやマネージャー候補さんにもお勧めの話である。

>合唱力を高めていくポイントは、まず「自分」を知ることが大切だと思います。
誰かの美しい声に憧れてそこに自分の声をダブらせたり、ないものねだりをするのではなく、自分の、今あるがままの声をきちんと見つめること。
それから、声を磨いていくということ。誰でも最初は輝いていない岩石のような石を、努力して磨き続けることによって輝かせていくのです。
私は生徒の出す声がよくなければ、ストレートに苦言を呈し、それをシビアに受け止めさせます。
その時に自分のことがしっかり見つめられない子は、やっぱり三年後に伸びません。
私がどんなに「こうしなさい」と言っても、それを受け止める心がなければ、悪いところも直せないし、よいものも吸収できません。

>それと、合唱はたくさんの人数でやっていくものなので、相手の喜んでいる姿を見て、自分にも喜びを感じられるような感性が必要だと思います。
誰かが褒められているのを見て妬ましく思ったり、相手が輝いている姿を見て羨ましく思ったり。
そうやって、人と比較をして自分の能力のなさを嘆くのではなく、相手のいい所を見つけて真似ていったり、輝いている人を見て「素敵だなぁ！」と、きちんと心から思えること。そんなふうに、素直な心になることが合唱にはすごく大切だと感じています。

>もう一つは、人の心が読める、あるいは感じられる、ということです。昨年、合唱部の中で、二人の生徒のお父さんが、病気で急に亡くなられました。
楽しい歌を歌っていても、その子の心の中は悲しみでいっぱいだったかもしれないし、悲しい歌を歌ったら。胸が張り裂けそうなほど苦しかったかもしれません。
そんなことを自分なりに心で感じながら、共に歌い思いを乗せていけるということが、すごく大切ではないかと思います。それがうまくできる年はいい歌が歌えます。
音大にたくさんの生徒が入る年もありますが、そういう年に、全国大会に行けなかったことがあります。どんなに一人ずつのレベルが高くても合唱ではいい結果が出るとは限りません。
相手のいろいろな思いを読み、感じられるようになれば、どんなに声がハスキーだろうが、多少音程が外れていようが、皆の思いが一つに揃って心が清められていきます。
そこが合唱のおもしろい、一人ではできない素晴らしいところではないかと感じています。

なるほど。会社も一人ではできない、素晴らしいところであるはずだ。
一人ひとりが渕上の教える合唱力の高めるポイントを押さえて活動すれば、１足す１が２以上の成果を出せる、そういうことではないだろうか。

（参考）
指揮者　渕上 貴美子　ー菊華アンサンブル

https://kikuka-ensemble.jimdofree.com/%E6%8C%87%E6%8F%AE%E8%80%85/


##後書き
うちの子どもも合唱部に入れたいなと思いました。杉並区に通えれば。渕上先生のところで。

以上、皆様のお役に立てば幸いです。
トピックブランチに常にmainブランチの更新を取り込むGitHub Actions

開発組織がある程度大きいと、次にリリースするバージョンの開発と、さらにその次にリリースするバージョンの開発が並行して行われることがある。
次にリリースするものはmainブランチにmergeしていくことになると思うが、その次にリリースするものはまだmainブランチにマージできないので、トピックブランチを作ってそちらにマージしていく運用にすることが多いのではないだろうか。
そんなときにmainブランチの変更を常にトピックブランチに取り込みたいと思うのは自然だと思うが、これを手動でやっていては手間がかかる。
こういう場合はGitHub Actionsを利用して、mainブランチの更新を検知してトピックブランチにPull Requestを出すようにしようと思ったのだけれど、ググっても楽にできそうなものがサクッと出てこなかったので忘れないようにメモっておく。

# 結論: vsoch/pull-request-action を使う

世の中便利なGitHub Actionsが公開されているので、それを使う
https://github.com/vsoch/pull-request-action

```
name: Create a pull request to topic branch

on:
  push:
    branches:
      - main

jobs:
  create-pr-to-topic:
    runs-on: ubuntu-latest
    steps:
      - name: Create pull request
        uses: vsoch/pull-request-action@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PULL_REQUEST_BRANCH: topic-branch-a
          PULL_REQUEST_TITLE: Merge main
```
最小の設定はこれだけ。他のオプションは公式のGitHubを参照
AWS: AppSync が使う DynamoDB のテーブルを調べる

参考ページ
[appsync](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/index.html)

API の一覧を取得

```bash
aws appsync list-graphql-apis > a01.json
```

apiID を調べる

```bash
jq '.graphqlApis[] | [.name , .apiId]' a01.json
```

API の情報を取得

```bash
aws appsync list-data-sources --api-id 123456*** > b01.json
```

テーブル名を取得

```bash
jq .dataSources[].dynamodbConfig.tableName b01.json
```

#DynamoDB のテーブル名の一覧#

```bash
aws dynamodb list-tables
```

#GraphQL のエンドポイントを調べる#

```bash
aws appsync get-graphql-api --api-id 123456*** > c01.json
jq .graphqlApi.uris.GRAPHQL c01.json
```
Pythonでインスタンスを比較するために__eq__を実装するときの注意点

# 概要

**Python**でインスタンスを比較するとき、**\_\_eq\_\_**メソッドを使いたいことがある。
独自の方法で複数のインスタンスが**同じ**か確認したいためだ。

ただ、この**\_\_eq\_\_**メソッドをオーバーライドした時は、同時に**\_\_hash\_\_**メソッドについても考える必要がある。
**\_\_eq\_\_**をオーバーライドすると、デフォルトでは**\_\_hash\_\_**が**None**を返すためだ。

もし、**\_\_eq\_\_**メソッドをオーバーライドしたオブジェクトを**ディクショナリのキー**や**セット**で使うときなど（※）は**\_\_hash\_\_**メソッドもオーバーライドする。
**※ハッシュ可能オブジェクトの場合**

# \_\_eq\_\_メソッドをオーバーライドしない場合

```python:example_not_override.py

class TestNotEq:
    def __init__(self):
        self.a = "a"

test_not_eq_1 = TestNotEq()
test_not_eq_2 = TestNotEq()

test_not_eq_1 == test_not_eq_2
Out: False

test_not_eq_1.__hash__()
Out: -9223371891910350837

test_not_eq_2.__hash__()
Out: -9223371891910350809

```

この場合、`self.a`に同じ値が入っているインスタンス`test_not_eq_1`と`test_not_eq_2`は`==`で比較すると`False`となる。


# \_\_eq\_\_メソッドをオーバーライドした場合

```python:example_override.py

class TestEq:
    def __init__(self):
        self.a = "a"
    def __eq__(self, other):
        return self.a == other.a

test_eq_1 = TestEq()
test_eq_2 = TestEq()

test_eq_1 == test_eq_2
Out: True

test_eq_1.__hash__()
Traceback (most recent call last):
  File "C:\Python\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-7-10d68bdb2b74>", line 1, in <module>
    test_eq_1.__hash__()
TypeError: 'NoneType' object is not callable

```

`==`での比較結果は`True`となるが、`__hash__`メソッドの呼び出しは失敗する。

これは`__hash__`が`None`になっているためである。

```python

test_eq_1.__hash__ == None
Out: True

```

# 対応 >>> \_\_hash\_\_メソッドをオーバーライドする

```python:example_override_hash.py
class TestEq:
    def __init__(self):
        self.a = "a"

    def __eq__(self, other):
        return self.a == other.a

    def __hash__(self):
        return super().__hash__()
```

# 参考

[Python Document \_\_hash\_\_](https://docs.python.org/ja/3/reference/datamodel.html?highlight=__eq__#object.__hash__)
pythonでDataFrameを処理するときに使う式

毎回データフレームを編集するとき、同じようなことをやっているのに毎回忘れてしまっている気がするので、使えそうなものを自分用にメモしておく

```python
# 必要ライブラリのimport
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

df_titanic = sns.load_dataset("titanic")
# 項目名の日本語化
columns_t = ['生存', '等室', '性別', '年齢', '兄弟配偶者数', 
             '両親子供数', '料金', '乗船港コード', '等室名', 
             '男女子供', '成人男子', 'デッキ', '乗船港', '生存可否', '独身']
df_titanic.columns = columns_t
df_titanic.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/cb47f30d-e0dd-d7bf-9a64-0afc41e85c3f.png)

# 列ごとの欠損値の数を確認する

```python
df.isnull().sum()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/870e77e9-6e06-4b21-7731-6a1c76ffff8b.png)

# 列の項目ごとに個数をカウントする

```python
df["乗船港"].value_counts()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/5c97dfae-a40d-6d74-07bb-8be73fccdf6d.png)

# 統計値を取得する

```python
df.describe()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/229ce533-f7dd-a49b-b2ce-c4c3eef35a30.png)

# 特定の項目でグループ化(集約)する

```python
df.groupby("性別").mean()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/a195c14f-636e-0f48-324a-6012a97e6d17.png)

# 特定の列を削除する

```python
df.drop("生存可否", axis = 1)
```

axis = 0にしたら行を削除する

# 欠損値のある行を削除する

```python
df = df.dropna(subset = ["乗船港コード"])
```

上記の[]は複数にしてもよい

# 欠損値を特定の値で埋める

```python
#平均値を入れる場合を考える
age_average = df["年齢"].mean()

df = df.fillna({"年齢": age_average})

```

# list, numpy, series, dataframeの変換

このサイトがまとまっているので参照する
https://irohaplat.com/python-convert-arrays-list-numpy-dataframe-series/

# matplotlib関連

このサイト見てみる(メモ)
https://lib-arts.hatenablog.com/archive/category/Matplotlib
vertex ai custom-jobsでBigQueryを叩くときにはプロジェクト名を指名する

## 症状

[`gcloud ai custom-jobs create`](https://cloud.google.com/vertex-ai/docs/training/create-custom-job)などでdocker imageを使ってジョブを走らせようとした場合、docker内でbigqueryへクエリを叩く処理が入っていると権限がないとエラーが出て怒られます。
例えば`User does not have bigquery.jobs.create permission`等です。

しかしサービスアカウントとして利用される`Vertex AI Custom Code` service agentはBigQueryへの[基本的なアクセス権限がある](https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents)はずので変です。またローカルで実行する上ではこのようなエラーは発生せず。

## 解決方法

色々調べても解決できず、試行錯誤の末BigQuery利用時に`project`をコード内で指定すれば上手くいく事が判明しました。どうやらcustom-jobs上で別の良く分からないプロジェクトとして認識されていたようだと思われます。

例えばPythonコードの場合

```python
from google.cloud import bigquery

# NG
bigquery.Client().query(QUERY)

# OK
bigquery.Client(project=MY_PROJECT_NAME).query(QUERY)
```
認証用クラスベースビュー、汎用クラスベースビューのフォームがformで受け取れる理由

#内容
Djangoでログイン処理を簡潔に実装するためのクラスベースビューであるLoginView（認証用クラスベースビュー）において、HTMLへフォームを表示させるときのformの正体を教えていただいたためメモします。AuthenticatedFormを継承している他の汎用クラスベースビューでも同様だと思います。

#form が現れる例
ログイン画面の作成を想定し、以下のようなurl.pyを記述しました。

```Python:url.py
from django.urls import path
from django.contrib.auth.views import LoginView,LogoutView

urlpatterns = [
    path('login/',LoginView.as_view(
        redirect_authenticated_user=True,
        template_name='accounts/login.html'
        ),name='login'),
]
```
このとき、Djangoが自動でログインに必要なフォームの生成を行ってくれるので利用し、login.htmlを作成します。

```HTML:login.html
{% extends 'base.html' %}

{% block main %}
{% csrf_token %}
{{ form }}
<button type="submit">ログイン</button>
{% endblock %}
```

ここで前述のフォームはlogin.htmlの {{ form }} で受け取り、表示されています。urls.py内ではformという変数は宣言しておらず、いったいどこから現れたのかが疑問でした。
調べても欲しい情報が見当たらなかったため、terartailで有識者のご意見を伺うとすぐに以下のような回答をいただきました。

>LoginViewでform_class = AuthenticationFormでformを定義しています。
コード見て継承を辿っていくと、FormViewが継承しているFormMixinのget_context_dataでget_form,get_form_classからself.form_classをコンテキストとして渡しているためだと思われます。
[[Django]クラスベースビューを利用した際のフォームの受け取り方](https://teratail.com/questions/5qo25y2je6ietw#reply-nztaqamhyfyq5w)

AuthenticatedFormが継承しているFormMixinのget_context_dataというメソッドから渡される値の名前がformだから、ということのようです。
書きたかったことは全てこの回答に詰まっているので後は実際にDjangoのソースコードを示すのみとします。

```Python
class LoginView(SuccessURLAllowedHostsMixin, FormView):
    """
    Display the login form and handle the login action.
    """

    form_class = AuthenticationForm
```

```Python
class FormMixin(ContextMixin):
    """Provide a way to show and handle a form in a request."""
（中略）
    def get_context_data(self, **kwargs):
        """Insert the form into the context dict."""
        if "form" not in kwargs:
            kwargs["form"] = self.get_form()
        return super().get_context_data(**kwargs)
```
このget_context_dataメソッドの二行目がポイントみたいです。

```Python
kwargs["form"] = self.get_form()
```
確かにformという名前の値が登場しています。

#反省点
疑問点が生じ、調べてもわからなかった場合はきちんと当該ソースコードの継承を追うことも頭に入れておく必要があることがわかりました。
Qiitaを利用するのは初めてなので、改善点や問題点とうご指摘いただければ大変助かります。
参考になったデバック方法

自分の知らないデバック方法をためておくためのページ！！

- ファイル出力機能でどこにファイルがでるかわからない
→ファイルを作成するメソッドを使って、ルートにファイルを作成するようにしてみる。デバックをしながらそのパスを拾い上げる

- try,catchを何階層も作成し、どこで落ちるか、当てはまるのかを特定する
Azure Functions - 共通コード管理

# フォルダー構成

[フォルダー構成](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-reference-node?tabs=v2#folder-structure)を参考に以下構成で実施

```
FunctionsProject
  │
  ├─ HttpTrigger1/
  │   ├─ function.json
  │   ├─ index.js
  │   └─ sample.dat
  │
  ├─ SharedCode/
  │   └─ util.js
  │
  ├─ node_modules/
  ├─ .funcignore
  ├─ .gitignore
  ├─ host.json
  ├─ local.settings.json
  ├─ package.json
  └─ package-lock.json
```

# 共通コードの実装

```javascript:SharedCode/util.js
module.exports = {
  testFunction: (context, param) => {
    context.log(param);
  },
};
```

# 共通コードの使用

```javascript:HttpTrigger1/index.js
const util = require('../SharedCode/util');

module.exports = async function (context, req) {
  util.testFunction(context, 'hello world');
};

```
Pythonでソート

#並べ替えたい

##sortを使う
###昇順
```python:
l  = [1, 2, 3, 5, 4, 8]
l.sort()
l
```
```
[1, 2, 3, 4, 5, 8]
```
###降順

```
l  = [1, 2, 3, 5, 4, 8]
l.sort(reverse=True)
l
```
```
[8, 5, 4, 3, 2, 1]
```
sort()はタプルに対しては使えない。sort()を使うと元のリストが書き換えられる。

##sortedを使う
```python
l  = [2, 1, 3, 5, 4, 8]
sorted(l), l
```
```
([1, 2, 3, 4, 5, 8], [2, 1, 3, 5, 4, 8])
```
元のリストはそのまま。sorted()は文字列やタプルを引数にできるが、返すのはリスト。

##itemgetterでリスト内のリストを並べ替え
```python
from operator import itemgetter

ll = [["acd", 123, 456], ["bfe", 234, 102], ["edo", 132, 9]]
print(
    sorted(ll, key=itemgetter(0)),
    sorted(ll, key=itemgetter(1)),
    sorted(ll, key=itemgetter(2)),
    sep = "\n"
    )
```
```
[['acd', 123, 456], ['bfe', 234, 102], ['edo', 132, 9]]
[['acd', 123, 456], ['edo', 132, 9], ['bfe', 234, 102]]
[['edo', 132, 9], ['bfe', 234, 102], ['acd', 123, 456]]
```

<br>
itemgetter()の括弧内でどれで並べ替えするか決められる。
<br>

```python
from operator import itemgetter

ll = [["acd", 123, 456], ["bfe", 234, 102], ["edo", 132, 9], ["bfe", 120, 2]]
print(
    sorted(ll, key=itemgetter(0, 1)),
    sorted(ll, key=itemgetter(0)),
    sep = "\n"
)
```
```
[['acd', 123, 456], ['bfe', 120, 2], ['bfe', 234, 102], ['edo', 132, 9]]
[['acd', 123, 456], ['bfe', 234, 102], ['bfe', 120, 2], ['edo', 132, 9]]
```
itemgetter(n, m)とすれば2段階でソートできる。(nが優先、mが第二段階)
password-authとsystem-auth

## 2023年11月28日更新

最近ようやくわかったことですが、passwdコマンドはsystem-authを参照にしている。

### 以下のブログを見て理解するほうがpasswdコマンドとpamの関係がわかると思います。


https://ozuma.hatenablog.jp/entry/20131005/1380942386



system-authを使っているまたはpassword-auth使っているかは
/etc/pam.d/以下を調べればいい

### もっと詳しく知りたい方よう

https://ihag.hatenadiary.org/entry/20080617/p1


結局、サービス名（sshd,passwdなど）を第一引数に渡す。そのファイルを参照する。


## 以下の記事も時間のある時書き直します。



対象OS
Red Hat Enterprise Linux Server release 7.7 (Maipo)

結論から

コンソールログインまたは、sshでのログイン失敗をカウントして拒否する設定は
password-auth

etc/pam.d/password-auth

設定変更箇所は2か所
3回間違いでアカウントロック

> auth        required      pam_tally2.so deny=3　
> account     required      pam_tally2.so

https://www.server-world.info/query?os=CentOS_7&p=pam_tally

ではsystem-authはなにをカウントしているかというと
sudo等の失敗みたいです。
system-authにも以下の設定を追加
> auth        required      pam_tally2.so deny=8
> account     required      pam_tally2.so

そうすると、sudoのパスワード失敗をカウントします。

ややこしい。。。
【streamlit】streamlit helloを実行してブラウザで動かす方法

#はじめに
streamlit hello を実行してブラウザで動かす方法について記事にしています。

#環境
Windows10
Python3.9

#streamlit hello の実行方法
1. コマンドプロンプトを起動します。
2. streamlit hello と入力して、Enterを押します。
![streamlit001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321513/827fce32-6822-89e8-01de-4ee8e1a12404.png)
3. ブラウザを起動します。
4. ブラウザのアドレスバーに http://localhost:8501/ を入力します。
5. 以下の画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321513/00f2b1f9-e434-11ea-4631-e3f1b76701ce.png)

#stream hello の操作方法
左画面のChoos a demo のところから、デモアプリを選択できます。
・Animation Demo
・Plotting Demo
・Mapping Demo
・DataFrame Demo

#おわりに
今回の記事は以上になります。では、また。
Databricks AutoMLでアルゴリズムを選択できるようになりました

[Databricks AutoMLのマニュアル](https://qiita.com/taka_yayoi/items/0ed860131a02aeade14f)でも説明されているように、Databricks機械学習ランタイム10.3以降では、AutoMLで使用するアルゴリズムを選択できるようになりました。ビジネス要件、機能要件によっては特定のアルゴリズムに限定したいというケースがあるかと思いますが、そのようなケースに対応することができます。

1. 事前にトレーニングに使用するデータを準備しておき、メタストアに登録しておきます。
1. Databricks機械学習ランタイム10.3以降が稼働するクラスターを作成して、起動しておきます。
![Screen Shot 2022-02-23 at 9.33.04.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/b8e1dee3-5fdf-d559-ee4c-34cb1dbd1556.jpeg)
1. サイドバーのペルソナスイッチャーで**Machine Learning**を選択し、**Experiments**をクリックします。
1. **Create AutoML Experiment**をクリックします。
1. **Compute**では上で作成したクラスターを選択します。
1. **ML problem type**では問題のタイプ(回帰、分類、時系列予測)を選択し、**Dataset**では、事前に準備しておいたトレーニングデータセットを選択します。
1. **Prediction target**には目的変数のカラムを指定します。
![Screen Shot 2022-02-23 at 9.45.11.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/eac7a326-6ad6-7a63-48f8-95219224a802.jpeg)
1. さらに**Advanced Configuration (optional)** を展開します。
1. すると**Training frameworks**に使用されるフレームワークが列挙されていますので、必要に応じて取捨選択を行います。
![Screen Shot 2022-02-23 at 9.46.51.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/116e086b-af8f-e192-f0f6-8cbc9ce77e5b.jpeg)

これでトレーニングを行うと選択されたフレームワークのみが使用されるようになります。以下の例ではscikit-learnのみが使用されています。
![Screen Shot 2022-02-23 at 9.54.09.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/89a46d16-a253-4ae5-0cbc-680e2e1f0425.jpeg)

また、**Alerts**をクリックすると、データに関する警告が表示されますので、トレーニングデータの見直しが必要かどうかの判断に活用することができます。
![Screen Shot 2022-02-23 at 9.54.27.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/dab392c6-ebc5-5cfd-94de-1bfaf68e6ecf.jpeg)

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
VSCodeでフォルダを開いて、ローカルUbuntuのコマンド操作が行えるようにする

#目的
* VS Code上からUbuntuを起動させた状態にする。
* VS Codeでフォルダを開いた状態で、ターミナルからUbuntuのコマンド操作が行えるようにする。

#前提
下記の状態になっていることを想定して書いています。

* Windows11上で、WSLを導入してUbuntuが起動できるようになっている。
* VS Codeに、Remote-WSL（VS CodeでWSLで作ったUbuntu環境を操作できるようになるプラグイン）を導入している。

#ポイント
ポイントはVS Codeの「ファイル→フォルダを開く」でフォルダを開こうとした時に指定するパスとして、開きたいフォルダの**Ubuntu上からみたパスを指定する**、ということです。
ここでWindowsからみたパスを指定してしまうと、フォルダは開けますが、Windowから開いたことになってしまうため、ターミナルを開いたときにUbuntuとしてコマンド操作することができなくなってしまいます。

#方法
1. はじめに開きたいフォルダを作成しておく。今回は「D:\dev\web_app\heroku-deploy-minimum」というフォルダが対象。
2. VS Codeの左下に下記のような緑のボタンがあるのでクリック。すると上のほうのダイアログに「New WSL Windows」とでるのでこれをクリック。

![vscode-icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/230347f7-e40e-3869-8b3a-03c8149d4619.png)
3. 新しいウインドウでVS Codeが開いて、左下のマークが下記のようになったら準備OK、これでVSS CodeからUbuntuを操作できるようになった。もともと開いていたVS Codeは使わないので閉じて問題なし。
![WSL Windows2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/c2fd00f4-6b78-cb81-8874-be88de99a3ae.png)
4. VS Codeで「表示→ターミナル」でターミナルを開きます。cdコマンドで、カレントディレクトリが目当てのフォルダになるまで移動する。赤枠の部分が目当てのフォルダのUbuntu上からみたパスなので、これをコピーしておく。
![path.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/8d560213-1b69-3222-5d53-c409271e2c35.png)
5. VS Codeで「ファイル→フォルダを開く」とすると、ウィンドウの上の真ん中あたりに下記のようなボックスがでるので、先ほどコピーしたパスを入力して「OK」をクリック。
![path2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/5e6b2cc2-ea50-fcd9-ad0e-b87b656624f1.png)
6. するとフォルダーが開いた状態になるので、あとは「表示→ターミナル」で再度ターミナルを開けば完了。
![open-folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/53448604-097f-40fc-a087-fc626720b981.png)

#まとめ
この構成ではじめてVSCodeからフォルダを開こうとしたとき、Windowsからみたフォルダパスを指定していたせいで、フォルダは開けたけどターミナルからUbuntuが操作できず、？？？となりました。
慣れてしまうとたいしたことはない話ですが、初めてやったことだとわからないことが多く、些細なことでも悩んでしまうなあと思ったので、書いてみました。
個人的メモ

# bit全探索(itertoolsを使う)

```python
from itertools import product

for pro in product((0, 1), repeat=n):  #長さnの各要素が0か1のタプルを返す＝bit全探索で便利
    print(pro)
```

# 二分探索(bisectを使う)

```python
import bisect
list = [10, 20, 30, 40]
bisect.bisect(list, 25)
```
```
2
```

# inputする

```Python
import sys
input = sys.stdin.readline
```

# 文字の種類を数える
```Python
n = int(input())
from collections import defaultdict
dic = defaultdict(int)
for _ in range(n):
    dic[input()]+=1
```

# 特定の行・列を省いたマス目を出力する
```Python
for i in range(h):
    if i not in d:  #dは省く行のインデックスが入っているリスト
        ll = [a[i][j] for j in range(w) if j not in e] #eは省く列のインデックスが入っているリスト
        print("".join(ll))
```

# 数列の隣接する k 項の和を求める
```Python
a = 0
for i in range(k):   #最初のk項の和を求める
    a += p[i]

l = [a]   #和を入れるリスト

for i in range(n-k):   #k項の内最初の項を引き, k項の最後の次の項を足す
    a = a - p[i] + p[k+i]
    l.append(a)

```
【streamlit】streamlit hello で コマンドとして認識されていないというエラーが出たときの対処法

#はじめに
streamlitをやり始めたときに、遭遇したエラーの解決方法です。

#環境
Windows10
python3.9

#streamlitをインストールします。
```
>pip install streamlit
```
#streamlit helloを実行します。
```
>streamlit hello
```
ここでstreamlitは内部コマンドまたは外部コマンドとして認識されていませんというエラーが出ました。

#streamlitにPATHを通します。
１．pip installでstreamlit.exeがインストールされているディレクトリを見つけます。
私の場合は、C:\Users\hogehoge\AppData\Roaming\Python\Python39\Scripts\streamlit.exe にいました。

２．PATHを通します。
・STARTボタンを右クリック⇒システム⇒システムの詳細設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321513/cc9bbcab-96e4-a269-d34a-591826c9ed1f.png)

・環境変数をクリック
・hogehogeのユーザ環境変数のPathを選択して編集ボタンをクリック
・環境変数名の編集になるので、以下を追加します。
C:\Users\hogehoge\AppData\Roaming\Python\Python39\Scripts

・streamlit hello を実行するとデモアプリが起動します。

#おわりに
今回の記事は以上になります。では、また。
[めんどくさがり用] 無償版 G Suite の完全終了 → 取り急ぎメール受信だけでも逃す

# 無償版「G Suite」、2022年7月1日に完全終了

めちゃくちゃお世話になりました。
ありがとうございました！

https://www.itmedia.co.jp/news/articles/2201/20/news065.html

がっつり組織で使いこなされている方は、もはや有償版に移行するしかなさそうですね。
今まで数年間、長ければ１０年越えで無料だったのですから、逆に今までが異常でしたね。

https://support.google.com/a/answer/60217

とはいえ・・・ **なんとかならないものか？** と思うのが心情です^^

# 現状を考えてみると・・・
個人での開発でしか使っていませんでした。
正直なところ、Workpspaceとしては使っていませんでした。

ただ **サービス毎に発行していた大量のメールアドレスをどうにかせねば・・・** です。
サービスからの送信はなんとでもなるのですが、お客さまからのお問い合わせなどがエラーで返ってしまうのだけは避けたい。 
つまり **とりあえず受信だけでも** 救いたい。


# レンタルサーバーに移行し始めてみるも・・・めんどくさい
:::note info
ここは単なる愚痴と経緯の読み物です
:::

ロリポップ！レンタルサーバーを借りているので、独自ドメイン設定をして、メールアドレスを作って・・・とやりかけたのですが、大量のメールアドレスを作って、１つ１つにテスト送信→受信確認が **めんどくさい** ・・・

めんどくさいので、
ロリポップさんに「あるドメイン宛のすべてのメール（アカウントがないものも含む）を、１つメールアドレスで受信できないか？」と問い合わせましたが、できないとのことでした。
カゴヤさんのメールサーバはそれっぽいことができるのですが、２ドメイン移行は追加で費用がかかってくるとのこと。

しゃーない、、、
でも、**こんな時間がかかるだけの単純作業に己の時間を取られるのか・・・でも、やらないと・・・でも、めんどくさい・・・あぁ、めんどくさい・・・** などと思いながら、とりあえず、あるドメインの大事なメールアドレスのレンタルサーバーでのアカウント作成を終えて、いざMXレコードの設定をしようとしました。

該当ドメインのホームページなどは CloudFlare であれこれしていたので、CloudFlareでのDNSのMX設定をしようとみてみると、ふと左メニューに「メールアドレス」の文字がありました。
結果↓

# CloudFlare Email Routing で、キャッチオール転送で解決！

https://blog.cloudflare.com/ja-jp/introducing-email-routing-ja-jp/

ドメイン宛のメールを、他のメールアドレスに転送することができるそうです。
しかも、「キャッチオール(catch-all)」 機能がある。
つまり、上記でロリポップさんに問い合わせた **「あるドメイン宛のすべてのメールを、１つメールアドレスで受信」が出来る** と言うことです。
転送先をGmailとかにすれば、レンタルサーバの独自ドメインのメールアドレス作成が一切不要とのこと。

![スクリーンショット 2022-02-23 8.43.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60052/c681bdc5-3edf-9417-d749-6ad9677c654b.png)

これで、
ドメイン数の分 × メールアドレスの数の分のめんどくさい作業がなくなり、ドメイン数の分の作業だけで済むようになりました！！
**めんどくさくない！**
*時間にして、どれだけの節約になるのだろう？精神的にも不毛なことをしなくてよい負担減も計り知れないです。*

:::note alert
適当なメールアドレスのスパムメールも受け入れることになります。
なので、最終的には Catch-Allではなく、１つ１つ必要なものだけを指定した方が良いです。
それでもレンサバにアカウントを１つ１つ作るよりは手間じゃないですよね^^
:::

---
# 参考： 転送されたメールアドレスで「送信」をしたければ
下記ページの「Gmailで独自ドメインでメール送信をする」が使えそうですね。

https://www.serversus.work/topics/qkf8sh2jusl8u6sjm5v5/

---
# 残件: ドキュメントは Google Workspace Essentials に移行？

メールの件は上記で片付きそうです。
ドキュメントとかは、こっちに移行できるかもしれませんね。

https://workspace.google.com/intl/ja/essentials/

---
そんなわけで、Googleさま、無償版 G Suite 最高でした。
今までありがとうございました！！！