OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonでクエリビルダを実装してみた

# 初めに
前回Flaskを拡張して少し使いやすいようにしてみました。
[Flaskをベースにフレームワーク作ってみた](https://qiita.com/kihara-takahiro/items/e2d4c44e1182a6b7e4a1)
今回は前回作ったフレームワークに簡単なクエリビルダ機能を追加しました。
まだ、結合とか複雑なSQLが対応できていないことやpostgresでしか使用できないことなど問題はありますが、紹介していこうと思います。

# 作ったもの
ソースコードは[GitHub](https://github.com/KiharaTakahiro/beaker)で公開しておりますので、ご自由に使用していただければと思います。

## 取得
下記のコードで該当抽出条件に従ってSQLが生成されます
### 書き方
```
# サンプル
  with start_transaction() as tx:
    query_builder = create_query_builder(tx)
    client = query_builder.table('{テーブル名}').where('{フィールド名}', '=', 2).or_where('{フィールド名2}', '=', 3).select()

# 全項目を取得する必要がない時はselectの引数に与えれば必要分だけの取得になります
client = query_builder.table('{テーブル名}').where('{フィールド名}', '=', 2).or_where('{フィールド名2}', '=', 3).select('{フィールド名3}',{フィールド名4})
```

### 生成されるSQL
`SELECT * FROM {テーブル名} WHERE {フィールド名} = %s OR {フィールド名2} = %s;`
AND条件としたいときはwhereを続けて使用すればAND条件となります

## 登録
登録内容に従ってINSERT文を発行します。
### 書き方
```
  with start_transaction(False) as tx:
    query_builder = create_query_builder(tx)
    query_builder.table('{テーブル名}').insert({'{フィールド名}': 6, '{フィールド名2}': 'test'})

```
### 生成されるSQL文
`INSERT INTO {テーブル名} ({フィールド名}, {フィールド名2}) VALUES (%s, %s);`

## 更新
更新内容に従って更新処理を行います。
### 書き方
```
  with start_transaction(False) as tx:
    query_builder = create_query_builder(tx)
    query_builder.table('{テーブル名}').where('{フィールド名}', '=', 6).update({'{フィールド名2}': 'test2'})

```
### 生成されるSQL文
`UPDATE {テーブル名} SET {フィールド名2} = %s WHERE {フィールド名}= %s;`

## 削除
下記の内容に従って削除処理を行います。
### 書き方
```
  with start_transaction(False) as tx:
    query_builder = create_query_builder(tx)
    query_builder.table('{テーブル名}').where('{フィールド名}', '=', 6).delete()
```
### 生成されるSQL文
`DELETE FROM {テーブル名} WHERE {フィールド名}= %s;`

# 終わりに
PHPであることから抵抗感を示す人は多いもののLaravelのフレームワークはよくできていると思っていてPythonにもLaravelの使用感で使えるものがあるといいなと思っているため、Laravelで実現されている機能はどんどん追加していきたいなと思っています。
今回作ったクエリビルダは急造なのでバグもあるでしょうし、結合に未対応であることから、機能の拡張は必要だと思うもののこのくらいのことが実現できれば実は事足りていて結合や複雑なSQLへの対応は直にSQLを書いたほうが見やすいのでは？という思いもあるのでこのまま進めていきバグは改修するもののそんなに機能拡張は積極的にはしていかないかもなとも思っております。
dockerでsvelte開発環境を構築する

# 前提
最近、人気のwebフレームワークsvelte（スベルト）を使ってみようと思い、開発環境を作りました。

https://svelte.jp/

ホストOSにdockerとdocker-composeをインストール。
動作実行環境はmacOS Big Sur 11.4。

# ファイル構成
`project`ディレクトリにソースコードを配置して、ホストOSとコンテナで共有します。

```
.
├── Dockerfile
├── docker-compose.yml
└── project
```

# dockerファイルの作成
svelteはnodeで動きます。gitはsvelteのプロジェクト作成で使用。

```
FROM node:lts-alpine3.16

WORKDIR /project

RUN apk add git
```

# docker-compose.ymlの作成

```yaml
version: "3"
services:
  web:
    build: .
    tty: true
    volumes:
      - ./project:/project
    ports:
      - "8080:8080"
```

# 作業ディレクトリの作成

```
% mkdir project
```

# docker起動
```
% docker-compose up -d
```

# svelteインストール
コンテナ側で作業します。
```
% docker-compose exec web sh
```

プロジェクトを作成します。（公式ページ「Svelte の一番簡単な始め方」参考）
https://svelte.jp/blog/the-easiest-way-to-get-started

```
# npx degit sveltejs/template my-svelte-project
# cd my-svelte-project
# npm install
```

上述の`npx`コマンドで警告が出たので、`npm`をバージョンアップ。
```
# npx degit sveltejs/template my-svelte-project
Need to install the following packages:
  degit
Ok to proceed? (y) y
> cloned sveltejs/template#HEAD to my-svelte-project
npm notice
npm notice New minor version of npm available! 8.11.0 -> 8.17.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v8.17.0
npm notice Run npm install -g npm@8.17.0 to update!
npm notice

# npm install -g npm@8.17.0
```

package.json編集
`scripts`の`start`を書き換えます。この設定でホスト側からwebアクセスできるようになる。

```diff_json
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
-    "start": "sirv public --no-clear"
+    "start": "sirv public --no-clear --host 0.0.0.0"
  },
```



# サーバ起動
起動後は`control+P`+`control+Q`でdockerから抜けられる。
```
npm run dev
```

# 動作確認
webブラウザから`http://localhost:8080`にアクセス。
以下の画面が表示されれば成功。
![スクリーンショット 2022-08-14 15.12.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45425/e5c5662b-7470-7fb1-9940-365fe90d07a8.png)
AWS Direct Connectとは

AWS Black Belt Online Seminarで学んだことを記録していきます。
参照URL
https://www.youtube.com/watch?v=mEtluVrgXlk

## Direct Connectとは？
Direct Connectは専用線と思われがちだがオンプレミスと直接接続する専用線サービスではない。
ロケーションが起点となり、このロケーションとオンプレミスの間をキャリア線で結んで契約する必要がある。
ロケーションにある顧客機器ルータとAWSルータを構内配線で接続してAWS cloudを結ぶことができる。
ではDirect Connectはどんな機能を提供するのか？どの範囲で提供するのか？というと
ロケーションに設置されたAWSルータとAWS cloudの間がDirect Connectで提供される

オンプレミス→DirectConnectロケーション→AWSのVPC

上のようなイメージの構成となる。


## そもそも物理接続ってなんや？
顧客側の専用ラックとAWSラックをMeet-Me Roomという回線で接続している。
この接続に必要なのがクロスコネクトというPDFファイルがあり、記載されいている情報をもとに接続している。
この専用ラック（オンプレミスルータ）とAWSラック（AWSルータ）をMeet-Me Roomを経由して接続しているのを物理接続という。


接続のパターンとしては、、
パターン1：WAN回線で接続しているパターン
パターン2：専用線で接続しているパターン
パターン3：顧客側で閉域網

この三つがあります。具体的な解説は動画で見てみるとわかりやすい！
推奨されるベストプラクティスの説明の前に、、、

## LINK Aggregation Groupと知っておくこと
LAGと呼ばれる。
1ギガ、または10ギガのコネクションを集約して一つの論理インターフェースとして提供している
このLAGが顧客側機器とAWS機器を接続する際に使用している。
同じ速度のconnectionを最大で４つ集約して各connectionにトラフィックを分散させている。

Direct ConnectionロケーションはこのLAGにも対応している。

## 推奨されるベストプラクティス
基本的には顧客機器とAWS機器を接続したロケーションを二つ作成し
AWS cloudにある一つのVGWを接続する。そしてそのVPCでは二つのマルチAZ構成にしておくことが推奨される。
ベストプラクティスとしてはSLA99.9%

## さらに最大の回復性を持たせたベストプラクティス
上記の構成の上位互換となる構成。

①オンプレミスで４つの機器を配置
②この四つのゲートウェイデバイスとロケーションの四つのルーターを接続
③ロケーションでは４つのデバイスは２：２で分けられてロケーション内でAWS DirectConnect デバイス４つを用意して接続する
ロケーションA、ロケーションBといったふうになる。
④ロケーションA、ロケーションBは４つのAWSデバイスをVIFでVPCのVGWと接続する

## うん？VIFってなんだ？
VIFとは？
仮想インターフェース、connectionを通してリソースにアクセスするための論理インターフェースのことを言う。
CCNAにも出てくる論理インターフェースといったところ。
一つの大きなconnectionの中にVLANを複数設定することができる。

## SLAとは？
サービスレベルアグリーメントのことを言う。
不可抗力によってどうしてもシステムって障害が起きるよねー
だから普段から障害が起きてもサービスを提供できるように対策をしておきましょう！
その水準は？この水準がSLAと言う。冗長化をもっと具体的に表した基準みたいなもの。
Amazon EC2のリソース状況を監視

# Amazon CloudWatch
普通のサーバーと同じようにAWSのサービスにも監視が必要。
物理的な部分に関してはAWSが監視してくれますが、**載せるシステムやソフトウェアの監視は自分たちで行う必要**がある。そこで使用するのが**Amazon CloudWatch**。
Amazon CloudWatchは、各AWSサービスでのリソースのモニタリングと管理を行うサービス。
AWSの各種サービスからメトリクス（いろいろな観点から動作を評価する数値）、ログなどを収集し、記録する。収集したログが閾値を超えたら、特定のアクションが起こるように設定できるため、監視状況に対応した管理も可能。
※Amazon CloudWatchは、対応しているサービスと対応していないサービスがある。
# 使用できるアクションとAmazon CloudWatch Logs
Amazon CloudWatchでは、CPU利用率、ボリュームの読み書き回数やバイト数、ネットワークの送受信バケット数などを監視できる。
また、閾値を超えた場合には、**メール送信、EC2アクション（インスタンスの起動・停止など）、Auto Scaling(インスタンスの数の変更)、Lambda関数による任意のプログラム実行**などができる。
また、**Amazon CloudWatch　Logs**として、各種ログを記録する機能もある。
このログは汎用的なログである。
* Lambda関数の実行する際にログを記録
* Amazon EC2インスタンスにエージェントを入れ、インスタンス内の任意のログを記録
* 簡単なフィルター機能があり、ログを確認
* CloudWatch Logsのログは一定期間で消す
* S3バケット（Amazon S3におけるデータの保存する容器）にエクスポート
などができる
また**AWS CloudTrail**という監査サービスを使うと、
**誰が、どのリソースにアクセスしたのか**について証跡が残る
CSSの基礎的知識 Part1

## CSSの基礎的な知識
### はじめに
エンジニア初心者やプログラミングを始めて間もない頃はインプットで学んだことが定着してスラスラと出てくるまで時間がかかってしまいます。しかし、だからと言ってアウトプットを辞めてしまうとすぐに忘れてしまいます。
そこで僕が感じる初心者が分かりにくいところやそれ知りたかったであろう情報を思いついた順にランダムに投稿していきます。もしよかったら参考にしてください。

### CSSとは？
まず、HTMLで記述した文字や画像等がWebページに表示されます。そしてそのWebページの文字の色や大きさ・字体、背景や配置等デコレーションをしてみやすくわかりやすくする為に利用するものです。

### CSSの使い方
まず、HTMLには　**<>,</>(タグ)** というもので囲った要素の名前をつけます。それに対してCSSにて指定するのが一般的です。

【例】
```index.html.erb
<title>
  CSSの基礎的な知識
</title>
```
```index.scss
.title {
  color: black;
  font-size: 19px;
  font-weight: bold;
}
```
といったような形で<>で囲ったタイトルに対してCSSで指定することによってみやすくおしゃれなWebサイトができます。詳しいCSSの指定の仕方は随時投稿していきます。ぜひ参考にしてください。
「経験豊富な情シスが足りない」について　原因は思ったとおりかな


前回は「[経験豊富な情シスが足りない](https://qiita.com/Keiji_otsubo/items/cdb46d25eb6959197b2e)」という記事を読んだ感想を書かせてもらいました。

その原因としてすぐに思い当たったのは
**ここ何十年の間に景気が低迷して何でもコストをカットしてきたせいで　色んなことに余裕が無くなったのが一番の原因と思っています。**
前職ではほぼ管理部門にいたのでITでないお仕事としては、どうやったら利益を出せるかということを会社として実践できるかを考えて実際に行っていくことでした。そのために色んな分析を行うのですが私の役割としてはデータの解析でした。今みたいに便利なツールは無かったので(あったとは思いますが有料で手が出せなかったというのが本当です。貧乏だったなぁ)Excelだけでは難しいことはプログラムを書いて行っていました。大量のデータを扱う場合はリレーショナルデータベースも使って行っていました。

その時も結局は売り上げを伸ばすことよりもコストを削減する方が不確定要素が少ないので結果が出やすいことは分かっていましたが、この記事を読んだらやっぱりなぁって思いました。


[「10年で売り上げ横ばい、利益5倍」が生んだ人権リスク](https://bookplus.nikkei.com/atcl/column/072400106/072400002/?n_cid=nbpbkp_fbad_2204_262&utm_source=facebook&utm_medium=display&utm_campaign=nbpbkp_fbad_2204_262&fbclid=IwAR2p1CWc0ZJrUXp__r6xsUYGyNw3ATIb0FP8IRkvfjN9THlj5oixPyMdnmc)

人権リスクについては今回の内容とは違うと思うので言及しませんが、この記事の中の

**この10年、企業はコスト削減しかしてこなかった**

![image.png](https://cdn-bookplus.nikkei.com/atcl/column/072400106/072400002/01.jpg?__scale=w:600,h:787&_sh=07a0230d50)

>　このグラフから読み取るべきメッセージは至って単純。この10年、日本企業は「売り上げは伸びていないのに、利益は5倍にも増大した」ことだ。正確には、2019年の全産業の売上高は1482兆円で、10年前（1386兆円）の1.1倍にしかなっていないが、純利益は同期間で9.2兆円から45.0兆円と4.9倍に拡大している。

>　売り上げが増えず利益が上がる理由はひとつしかない。コストが削減されたからだ。はっきり言おう。この10年間、企業もコンサルティング会社も、総体としてみれば「コスト削減」しか実現できなかった。

まぁ、ただしリーマンショックが2008年だったからこのグラフは少々恣意的に範囲を切り取っているような感じもしますが、コストカットしかしてこなかったのは正しいでしょうね。某レバノンに逃げた経営者さんもコストカッターだけだったように思います。

前職の経験では人件費、特に教育関連は減った（直接的な研修費用とかだけでなくて、OJTとか新しい技術を学ぶ時間なども含めて）と思います。私自身は万年赤字の貧乏な事業部にいたこともあって情報システム部門では独自にシステムを作ってもらえなかった（優先順は低かった、いや相手にされてなかった）ので、結局は自分でサーバーを立ててシステムを作ったものです。そのため業務として新しい技術を試してみたり、Linuxで遊んだりすることができました。おかげで豊富とまではいきませんが色々と経験ができたと思います。

またDX関係のレポートも同じようですね。 やっぱり人の問題だ。

[【Press Release】調査レポート「DXの内容を理解」は昨年比で約2倍と大きく伸長―DXの認知・理解は進んでいる一方で、自社内での人材不足や教育困難が課題―](https://industrial-x.jp/2022/08/10/pressrelease_dxreport2022/?fbclid=IwAR21YrfetVfCA8Yi535uG6gf_DfdpVdTYTkEiLFOF_jplIIZlZPhigxKVLE)

**今後必要な検討事項**
「DX推進人材の確保・育成」が最多、 次いで「リモートでDXを推進できる仕組み」。
![image.png](https://ci5.googleusercontent.com/proxy/sJIQWQQ5vqua8N7sCbQm6Ew8AT9COHg4Gq0yV-zybL7hC4wmuoeuhPwlD4xJRNAUxolR53iUl8jYrawG1_60zw5enZiGlWA4EfAz7QXuL5t87twrt9t0mhBcgjut0B0ijlBYr0bkVtWqQ6bwOJD2gmevLIjAVpKyoNVPi9GTBEHfvQ5Wn3QNqNfZWEMOi7TFpurD3ojqcw=s0-d-e1-ft#https://prtimes.jp/i/51016/61/resize/d51016-61-05556c5e34be242b15a9-3.png&s3=51016-61-b1f4f2db6fd417fb86e9bf66754a68f2-2176x912.png)


>DX推進経験のある人材は市場に多くありません。 その上、 DX人材にはプロジェクトマネジメントスキル、 デジタル関連の専門知識、 加えてビジネス経験やビジネス知識など多様なスキルを求められる。 これにより、 **外部の専門機関との協業が必要となっていると考えられます。**

この外部の専門機関の活用は前回のレポートにはなかった視点ですね。何もしないよりかは断然といいと思いました。求められるスキルが高いので社内で育てるにしても、育てられる人がいるのかが問題でしょう。勝手に育ってくれる人ばかりだったらそもそも経験豊富な人も充足できただろうから、残念ながら内部だけに期待するのは無理かもしれない。
仮想インターフェースの種類と接続方法

AWS Black Belt Online Seminarで学んだことを記録していきます。

参照URL
https://www.youtube.com/watch?v=mEtluVrgXlk


## 三つの仮想インターフェース

VIFを使用するときには大きなconnectionの中に
複数のVLANを設定することができる。主にこの三つがある。

・プライベートVIF
・パブリックVIF
・トランジットVIF

VIFを複数のアカウント（クロスアカウント）で利用することができる
またデータ転送量については各アカウントに課金されていく。


## プライベートVIFを使った接続方法

DirectConnect ゲートウェイを使用した接続が推奨されている。
（DXGW）
XGWを使用することで複数のVPCと接続することができる。

基本的には

オンプレミスのルータ→AWS DirectConnectデバイス→VGW

といった構成である。この間をBGPピア接続をする。
また、複数のプラベートVIFを設定することによって本番、検証、開発環境といったふうに分けることもできる。

## パブリックVIFを使った接続方法

オンプレミスのルータ→AWS DirectConnect デバイス→AWSルータ

顧客がわのパブリックVIFを使用してBGPピアを構成する、
中国を覗く全リージョンのパブリックサービスの接続ができる。
AWSリソースのパブリックIPをAWSから広告している
プライベートVIFと混合して設定することが可能。

グローバルにあるS3と接続するためにパブリックVIFを使用するユースケースもある。


## トランジットVIFによるTransit Gateway(TGW)への接続

トランジットVIFを使用してDXGW経由でTGWへ接続することができる。

顧客側ルータ→DXGW→TGW→VPC〇〇

というような構成となります。
顧客側ルータとDXGWの間をeBGPピアで接続しVPC側にはVGWは不要となる。
VPCとTGWをアタッチしておく。
D言語がどこで使われているか(2022年版)

アクティブなものから停滞気味なものまで雑に並べています。

## Organizations using the D Language (dlang.org)

公式サイトの[Organizations using the D Language](orgs-use-in-d)では、D言語をプロダクト開発に使っている企業・団体を紹介しています。
特に[Sponsors](sponsors)にも名を連ねているSymmetry InvestmentsとWeka.IOではコアプロダクトでのDの利用事例がDConfなどで紹介されています。

## OneDrive Client for Linux

- https://abraunegg.github.io/
- https://github.com/abraunegg/onedrive (GitHub)

無料のMicrosoft OneDriveクライアントです。GitHubのスター数で考えてももっとも利用されているOneDriveクライアントのひとつと思われます。

## Inochi2D

- https://inochi2d.com/
- https://github.com/Inochi2D (GitHub)
- https://3dnchu.com/archives/inochi-creator-beta/ (日本語紹介記事)

リアルタイム2Dパペットアニメソフトです。

## Dplug

- https://github.com/AuburnSounds/Dplug (GitHub)

Audio Plugin フレームワークです。AuburnSoundsは[公式サイト](orgs-use-in-d)で紹介されていた企業のひとつでもあります。

## Serpent OS

- https://serpentos.com/
- https://github.com/serpent-os (GitHub)

Linuxディストリビューションです。パッケージマネージャやビルドツールの開発でD言語が使われています。

## Funnel Labs

- https://www.funnel-labs.io/
- https://www.funnel-labs.io/2022/06/17/language-choice-and-performance-java-and-d/ (マイクロサービス文脈での比較記事)

タクシーサービスやセンサーモニタリングなどのリアルタイムデータを効率的に扱うサービスを提供するシステムを開発しているようです。DConf 2022の発表内容によるとバックエンドでD言語を利用しているとのことです。

## WekaIO Matrix

※ 追記

- http://oss-tsukuba.org/wp-content/uploads/2019/12/GfarmWS2020_WekaIO_overview.pdf
- https://dlang.org/blog/2018/12/04/interview-liran-zvibel-of-wekaio/

コメント欄でlemipjiさんに教えてもらいました、ありがとうございます！

NVMeベースの並列スケールアウトNASです。ストレージシステムのdata pathおよびcontrol pathで利用されているそうです。

## Tilix

- https://gnunn1.github.io/tilix-web/
- https://github.com/gnunn1/tilix (GitHub)

GTK3ベースのタイル型ターミナルエミュレータです。比較的高機能で利用者もそこそこ多いのですが、現在機能開発が滞っておりメンテナを募集中です。

## tsv-utils

- https://opensource.ebay.com/tsv-utils/
- https://github.com/eBay/tsv-utils (GitHub)

eBayのコマンドラインでTSV形式のデータを扱うユーティリティツールです。filter,select,sample,joinといったツールを提供しています。

## vectorflow

- https://github.com/Netflix/vectorflow (GitHub)

Netflixのニューラルネットワークライブラリです。疎なデータに特化しているとのことです。最近は開発が停滞気味のようです。

[orgs-use-in-d]: https://dlang.org/orgs-using-d.html
[sponsors]: https://dlang.org/foundation/sponsors.html
起動しなくなったwslのext4.vhdxから、パーミッションを維持しつつデータを救出する方法

## やることを一言でいうと

**公式サイトから最新の**Linux向け7zipをwslにダウンロードしてwindows側のext4.vhdxからデータを解凍する

## 必要なもの

1. データの移行先のディストリビューション(wsl2)
1. 起動しなくなったwslのext4.vhdx
    1. パスは、`$HOME\AppData\Local\Packages\hoge.{ディストリビューション名}.hoge\LocalState\ext4.vhdx`であることが多い
        1. 例 : Ubuntu 22.4.1.LTSの場合 : `$HOME\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx`
1. **最新の**7zip

:::note warn
apt等でインストールできる`7za`や`7pzip-full`の場合、vhdxファイルの解凍に対応していない可能性があります。
::: 

## やること

起動しなくなったwslのext4.vhdxを好きな場所にコピー

:::note warn
必要な人のみ：自分が作業してた際にディストリビューションの初期処理で消えかけたため、警告
:::

移行先のディストリビューションで、**[公式サイト](https://sevenzip.osdn.jp/download.html)から最新の**Linux向け、7zipを救出先のwslへダウンロード、＆ 解凍

```bash
$ curl https://www.7-zip.org/a/7z2201-linux-x64.tar.xz -O
$ # 展開先のディレクトリを作成
$ mkdir 7zip
$ tar xvfJp 7z2201-linux-x64.tar.xz -C 7zip
$ # ヘルプを出して動くか確認
$ 7zip/7zz
```

ダウンロードした7zipを使い`/mnt/c/`等にあるext4ファイルを展開する
```bash
$ # ex4.vhdxの中身がばらまかれないように保存先のディレクトリを作成 & 移動
$ mkdir hogehoge
$ cd hogehoge
$ # 先程展開した7zipでファイルを展開する
$ ../7zip/7zz x /mnt/c/hogehoge/fugafuga/ext4.vhdx
$
```

:::note info
展開時、シンボリックリンク等が展開に失敗したとエラーを吐きますが、そこは諦めましょう
:::

## おわり
PyAudio+SpeechRecognitionからマイク入力を受け取りSofTalkで出力

# 挨拶
初めまして、日本システム開発株式会社の鈴木です。
技術者として更なる向上を目指すためQiitaアウトプットをする取り組みを行っています。
技術者としては経験が浅く発信内容はとにかく試したものの覚書になります。
本稿は議事録の作成補助システムを作成した際に試作したシステムについての内容です。
# 環境
この記事では以下の環境を用いています。
・Python3.8.1
・SpeechRecognition 3.8.1
・PyAudio                0.2.11
・SofTalk Ver 1.93.45

# 概要
Pythonを用いてマイクから入力された音声データを他のソフトウェアに渡すことを考えます。
今回はPythonの音声認識ライブラリーの一つ、SpeechRecognitionを用いてマイク入力をテキストに変換します。変換後テキストは音声合成ソフトSofTalkに読み込ませ合成音声に変換します。

# 実装
　大まかに音声の認識、テキスト変換→変換テキストをSoftalkに渡し実行という流れで処理を行います。
```python:MicrophoneToSoftalk.py
import speech_recognition as sr
import subprocess
import tempfile
import os
import subprocess


os.chdir(os.path.dirname(os.path.abspath(__file__)))
# start以下にSofTalk.exeのPathを指定する
_start = "start SofTalk.exe"
_word = "/W:初期テキスト"

# 音声入力
while True:
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("音声受付中")
        audio = r.listen(source)
        print("音声を認識します")

    try:
        # Google Web Speech APIで音声認識
        text = r.recognize_google(audio, language="ja-JP")
    except sr.UnknownValueError:
        print("音声を認識できませんでした。")
    except sr.RequestError as e:
        print("音声認識リクエストを要求できませんでした;"
              " {0}".format(e))
    else:
        #認識成功（SofTalkへ渡す）
        _word = "/W:"+text
        _command = [_start, _word]
        subprocess.run(' '.join(_command), shell=True)
        print(' '.join(_command))
    if text == "切り替え":
        break
print("完了。")
```
### 音声認識
SpeechRecognitionはGoogle Cloud Speech APIを利用できるPythonのライブラリの一種です。メインループ内のelse節までで音声認識を行っています。
音声認識自体は``Recognizer.listen()``メソッドを用いて行い認識に失敗した場合はexcept句でそのエラーをキャッチ、エラーが起きなかった場合（認識に成功した場合）はtextに認識結果を保持しておきSofTalkに渡します。
なお、日本語を認識できるのはrecognize_googleメソッド（Google Cloud Speech）のみのようです。

### SofTalkの起動
SofTalkはコマンドライン起動をします。コマンドラインの起動はPython標準のsubprocessを用いて行います。Sokftalkはコマンドラインにて
``start (Softalk.exeのパス)　/W:(出力したいテキスト)``
を入力することで音声出力できるためあらかじめ用意しておいた起動コマンド（_start）に音声認識部分から渡されたテキストを読み込ませることで出力をします。

### プログラムの終了処理
メインループは``while True:``で回しているためどこかで中断しない限りは音声認識をし続けます。今回は認識したテキストが「切り替え」の時（「切り替え」と発声したとき）ループを抜けるようにします。
つぶやきを転送するslack-appをGASで作った(slack90日間対策)

# 前提・モチベ
- 有料WS、無料WSの２つを使い分けている（WS=ワークスペース）
- 今まで無料WSでつぶやきチャンネルを持っていて、ブツブツつぶやいていた
- 90日制限が近づいたので有料WSでつぶやきを初めた
- 有料WSのつぶやきを無料WS側に転送したい

# 無料WS側のアプリ作成
- [create new app]
  - App Name: yasubei_tsubuyaiter (適当なので名前は任意で付けてくだせぇ）
  - Development Slack Workspace: 無料側のワークスペース
- アプリの管理画面から[Incoming Webhooks]を選択
  - 右上のスイッチをONにする
  - [Add New Webhook to Workspace]を押す
    - 転送先のチャンネルを選択（#yasubeiつぶやき、など）
    - Webhook URLが生成されるので、copyしておく
    - 念の為curlコマンドで動作確認する(略してすみません。curlは入れてください）

# GASアプリ作成
- GooleDriveへ移動
- 任意の場所で右クリック → その他 →　Google App Script
- 以下のようにプログラムする（ほぼコピペで大丈夫なはずです。必要なところだけ書き換えてください）

```javascript
function doPost(e){

  // 疎通確認(verify時に通信が来ます)
  var params = JSON.parse(e.postData.getDataAsString());
  if('challenge' in params){
    return ContentService.createTextOutput(params.challenge);
  }

  // Botの投稿に反応しないように修正
  if('subtype' in params.event) {
    return
  }

  userName = params.event.user;
  if('text' in params.event) {
  // 実際に表示されるメッセージ内容
    var contents = `${params.event.text} (from 有料WS #yasubeiつぶやき)`
  }

  // リクエスト内容を整形
  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : JSON.stringify(
      {
        "text" : contents,
        link_names: 1
      }
    )
  };

  // 投稿先 (無料WS側 #yasubeiつぶやき)
  UrlFetchApp.fetch("無料WS側で作成したIncomming Webhook URLをこちらに貼り付けてください", options);
}
```
- 保存
  - 編集したら必ず保存してください。プログラムが書き換わらないので注意。
  - 初回のみ「承認が必要です」「アカウント選択」「〜がGoogleアカウントへのアクセスをリクエストしています」などと出てくるが∞にOKする
- デバッグ(任意)
  - したい人だけ。そもそも動かないのでしなくても良い。
  - 私はdoGet関数を作って投稿するプログラムを書いて動作確認した。
- デプロイ
  - 初回はデプロイの種類を聞かれるので「ウェブアプリ」を選択する
    - アクセスできるユーザーはとりあえず「全員」とする
    - デプロイが完了したら発行されるウェブアプリのURLをコピーする
  - デプロイはソースコードを少しでも書き換えたら必要
    - 試しに「デプロイの管理」→「編集ボタン」→「保存」をしてみたが、動作は変わらなかった
    - デプロイするたびにウェブアプリのURLが変わるのでその都度slackアプリ側の設定(Event Subscriptions)も書き換えてください。


# 有料WS側のアプリ作成
- [create new app]
  - App Name: yasubei_tsubuyaki_subscriber (適当なので名前は任意で付けてくだせぇ）
  - Development Slack Workspace: 有料側のワークスペース
- アプリの管理画面から[Event Subscriptions]を選択
  - 右上のスイッチをONにする
    - Request URLに先程コピーしたウェブアプリのURLをペーストする
    - 5秒ほど待つとウェブアプリへ疎通確認の通信(ソースコードのchallengeのところです)が行われ、成功するとVerifiedと表示されます
  - [Subscribe to bot events]を押す
    - "message.channels"を選択（この設定は別途チャンネルにAppの登録が必要になります。忘れずに！）
  - [Save Changes]を押してアプリ作成を完了する
- 有料WS側のつぶやきチャンネルへApp(yasubei_tsubuyaki_subscriber)を登録する
  - チャンネルメニューから[Integrations]→[Add apps]で登録できます。
  - この辺、昔はUI違かったと思うので、結構変わってるかもしれません。MacのDesktopアプリでは上記にありました。
- 動作確認
  - 有料WSのチャンネルでつぶやいた内容が無料WS側へ転送されれば成功です

# デバッグ
- スクリプトへの疎通確認
  - Event SubscriptionsでVerifiedと表示されること
  - doGet()を作ってしまい、直接ウェブアプリのURLを叩いてみて無料WS側につぶやきが反映されるかを確認する
  - 私がしたのは上記くらいですね。

# 参考サイト
- [【雑学】SlackとGASで自由度の高いSlackのチャットBotを作る](https://tektektech.com/slack-auto-reply-bot-with-gas/)
  - 私の記事よりこちらのサイトのほうがスクショも載っていてわかりやすいです。感謝です。
- [Slack Botのアプリをチャンネルに追加したい](https://www.pre-practice.net/2020/08/slack-bot.html)
  - チャンネル投稿がウェブアプリへ通信されていなかったため、こちらを参考にデバッグしました。感謝です。

# 感想
アプリ作るの簡単でいいですね
slackでアプリ作成設定してGASでサーバレスで動作させて...。昔は自分でサーバ立ててましたけどねぇ（物理）
メンテナンスも考えなくていいし、今の時代はスゴイなぁ

# おまけ
（利用者からFB）
両方入ってる人は両方表示されますねw
どっちで反応するかもちょっと迷う:thinking_face:

ああ、たし:crab:ｗｗ

その他出来ないこと
- 画像は転送されない
- 一度投稿したあとの編集は反映されない
[Go]個人学習のための環境構築

# 概要
Golang の勉強のためにやった環境構築についてまとめておきました (2022 年)。実務で役に立つこともあるだろうということで。

**個人的な開発環境**
- OS: MacOS (x86-64)
- go のバージョン: 1.19
- デフォルトシェル: zsh
- エディタ: VSCode

# 1. Go のインストール・設定
## 1.1. インストール
[Go 公式のインストーラダウンロードページ](https://go.dev/dl/)へアクセスし、OS にあったインストーラをダウンロードしてインストールします。

※2025/2/22 追記
バージョン 1.19 が不要になったため
https://go.dev/doc/manage-install
を参考に、
`/usr/local/go` と `/etc/paths.d/go`
を削除することでアンインストールできました。
(sudo su - で root ユーザーに成り代わって作業)

## 1.2. Go のパスを通す
自分の環境ではインストーラでインストールしただけでは、goコマンドが使えずパスが通っていなかったため、以下を`~/.zshrc` に記述して ``source ~/.zshrc`` で反映しました。

```
export PATH="/usr/local/go/bin:$PATH"
```

パスが通っていることの確認
```
# バージョンが表示されればOK
go version
=>
go version go1.19 darwin/amd64
```

# 2. VSCode 拡張機能のインストール
以下をインストールします。
- Go
- GitHub Copilot
    - GitHub Copilot Free が 2024/12 〜 使用可能になりました。これがあるのとないのとでは大違い (個人学習ではセキュリティを気にすることもないでしょう)
- vscode-proto3 (Protocol Buffersを扱うならば)

# settings.json
ファイルの保存時に、[goimports](https://qiita.com/WisteriaWave/private/4453d51583a55bb22f92) でフォーマットされるように。

設定例: 

```settings.json

  "editor.formatOnSave": true,
  "[go]": {
    "editor.defaultFormatter": "golang.go"
  },
  "go.formatTool": "goimports",
  "go.formatFlags": ["-w ./", ""],
```





# 学習用の GitHub リポジトリ作成・モジュール化

https://qiita.com/WisteriaWave/items/60a1052981131f95fbf6

の 「実際にモジュール化して公開してみる」を参考に、GitHub リポジトリを作成し、Go プロジェクトを作成して push すれば OK。ここから Go プロジェクトを改造して色々学習していきましょう。
げに遙かなる前田 日明への径

```
　今回覚えたこと:
    libnotify-devのinstall時にkeyboard-configuration dialog:
        actでcypressをautomaticallyに動かしたい
　　expectコマンドというものの存在
    macの¥キーは初期設定だとliterallyに¥が入力される
```

　Github Actionsでcypressを用いた単体テストが動くようにしろ，という命を受けた．私の専門領域ではないが，うっかり引き受けてしまい，結構酷い目に遭ったという譚．

　.github/workflows/にYAMLを書いてはgithubにpushする，を繰り返していたら，無料枠がなくなってしまうカモ!?，とのツッコミ．

　https://qiita.com/technote-space/items/7b2694786f577c823fc1

　Actというsimulator使ってください，とのお達しがあった．macで動かそうとすると…「xvfbが入っていないから単体テスト動かせませーん」というバブル期のOLのような匙投げ．「あ～来世はおれもバブル期のOLになりたいよ」とボヤきつつ，「apt install -y xvfb」をYAMLに挿し込む．
　再度act．
　「...が入ってませーん」だと．
　cypress公式に以下のような記述が…
```
apt-get install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
```
　……
　YAMLに記入し，再度act．今度こそ!

　なんか国の名前らしきlistが描画されて停まった．ここからが長かった．
　何とかexpectコマンドなるものの存在を突きとめる．net上の指南通りにscriptを記述するも何故か動かない．
```
expect -c "
  spawn sudo apt-get -y install libnotify-dev
  expect ¥"99. Wolof¥"
  send 55¥n
"
```
　休日返上でじぶんのgithubで試しても上手くいく．じぶんちではWindowsを使っている．
　万策尽きた…いよいよ年貢の納め時か…と呑みにいきかけたときだった．
　
　<b>なんで¥なんだっけ?</b>

　おそるおそるググる……macだと¥と\が…(以下略)


　つまり……actでcypressをautomaticallyに動かそうとしたらexpectコマンドのinstallが必要，というお話でした．
kintoneのメールアドレスリンクをテンプレート選択にするプラグイン

# できること1
kintoneのメールアドレスリンクをクリックすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1171945/683e3ff7-2138-d649-a1cf-56668721c868.png)

通常はメールクライアントに to しか渡りませんが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1171945/fa017d2e-1625-0e29-0e55-ea9cddd552b2.png)

一旦、テンプレート選択のダイアログを表示し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1171945/ee53658e-4dab-bd0c-595b-ba724f3bcb14.png)

選択されたテンプレートの内容（to, cc, bcc, 件名, 本文）を
メールクライアントに渡すよう変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1171945/5f3ca38c-0830-89d2-f080-82d53bdaae30.png)


# できること2
テンプレートに埋め込まれたプレースホルダを置換します。
プレースホルダはフィールドコードを二重中括弧で囲ったものとし、該当レコードの内容で置換します。
```テンプレート.txt
{{ company_name }}
{{ name }} 様
```
```置換後.txt
サイボー株式会社
最望 様
```

# 導入方法
## 1. テンプレートを登録するアプリを作成
まず、下記項目を含むアプリを作成します。
フィールドコード名は任意です（プラグインの設定で指定します）
|項目 |必須 |種類 |備考 |
|---|---|---|---|
|テンプレート名 |必須 |文字列（1行） |テンプレート選択時に表示 |
|CC |任意 |リンク（メールアドレス） |文字列（1行）も可 |
|BCC |任意 |リンク（メールアドレス） |文字列（1行）も可 |
|件名 |任意 |文字列（1行） | |
|本文 |任意 |文字列（複数行） |リッチエディタ不可 |

例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1171945/083af3ba-845e-16c4-27b6-4c276115a401.png)


## 2. プラグインをインストール
下記サイトの「Download」ボタンからプラグインを取得、
https://github.com/co-labo-hub/kintone-template-mailto/blob/main/dist/plugin.zip

kintoneへの導入方法はサイボウズ社の案内の通りです。
[プラグインを追加／削除する（システム管理）](https://jp.cybozu.help/k/ja/admin/add_plugin/plugin.html)
「ファイルからプラグインを読み込む」のところになります

## 3. プラグインを有効化
インストールしたプラグインを、利用したいアプリで有効にします。
手順はサイボウズ社の案内の通りです。
[プラグインを追加／削除する（アプリ設定）](https://jp.cybozu.help/k/ja/user/app_settings/plugin.html)
（4の必要項目の設定は次の手順をご覧ください）

## 4. プラグインの設定
上記手順の途中でプラグインの設定を行うところがあります。
ほぼ手順1で作成したアプリについての登録になりますが
一番下のみ、プラグインが動作するアプリ上でのメールアドレスフィールドコードの登録になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1171945/8d53fea4-5116-f3e3-eed9-73c4b7ac2607.png)

# モバイル
特にPCに比べ文字入力で不利なモバイルでは
テンプレートが使えるとはかどるかもしれません。

iOS 15.6
Safari
![ios_safari.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1171945/06f45a90-4d10-4368-be7c-494bdfb3ee20.jpeg)

# 参考
テンプレートメールの内容を参考にさせていただきました
[ビジネスメールの教科書 文例]()
【Python】pytest-freezegunでテスト実行時に日時を固定する方法

### この記事を書いた経緯

pytestで「明日の日時を取得して特定のフォーマットに整形する。」という関数(関数hogeとします)のテストを書く場面がありました。

しかし、関数の実行結果が現在日時に依存するため実行結果を検証できない問題が発生しました。(hogeの実行日時が08/01の場合⇒08/02, 08/10の場合⇒08/11が返る)

この問題を解決するためにpytest-freezegunというパッケージを利用します。
pytest-freezegunはテスト実行時に日時を指定することができるpytest用のパッケージです。

### 実行環境

- Ubuntu20.04
- Python3.8.10
- pytest6.2.5
- pytest-freezegun0.4.2

### 利用方法

#### インストール手順

※ Pythonとpytestはインストール済みとします。

```bash
pip install pytest-freezegun
```

正しくインストールできたことを確認します。

```bash
pip show pytest-freezegun

Name: pytest-freezegun
Version: 0.4.2
Summary: Wrap tests with fixtures in freeze_time
Home-page: https://github.com/ktosiek/pytest-freezegun
Author: Tomasz Kontusz
Author-email: tomasz.kontusz@gmail.com
License: MIT
Location: /usr/local/lib/python3.8/dist-packages
Requires: freezegun, pytest
Required-by: 
```

#### 使用例

本来はテスト対象の関数とテストコードは別のファイルに書きますが、可読性を優先して同じファイルに書きます。

```python:test.py
import pytest
import typing
from datetime import datetime, timedelta

# テスト対象の関数
def hoge() -> str:
　　# 翌日の日時を取得してm/d(a)という形式に整形する
    tomorrow: datetime = datetime.now() + timedelta(days=1)
    tommorow_str: str = tomorrow.strftime("%m/%d (%a)")

    # 変換後の日時を使って戻り値を作る。
    headline: str = f"{tommorow_str} の天気予報です。"
    return headline

# テストメソッド
# 日時のフォーマットは2022/08/14や20220814でも問題ありません。
@pytest.mark.freeze_time("2022-08-14")
def test_hoge():
  headline: str = hoge()
  assert headline == "08/15 (Mon) の天気予報です。"

```

test.pyメソッドをテストします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598747/f4bf22ba-ce55-a58a-0543-a33fee2d77e5.png)

テストが通ればOKです。(rootディレクトリやそのほかのpluginはご自身の環境に合わせて読みかえてください。)

### 捕捉

サンプルコードではデコレータを使って日時を固定していますが、```freezer```フィクスチャを用いてテストメソッド内で日時を固定することもできます。

```python:test.py

# テスト対象関数は省略します


def test_hoge2(freezer):
    freezer.move_to("2022-08-14")
    headline: str = hoge()
    assert headline == "08/15 (Mon) の天気予報です。"
```



また、pytest-freezegunで固定された日時はそのメソッド内のみで有効です。

```python:test.py

## 2022/08/14にテストを実行します。

def test_hoge2(freezer):
    freezer.move_to("2022-08-11")
    headline: str = hoge()
    assert headline == "08/12 (Fri) の天気予報です。"


def test_hoge3():
    headline: str = hoge()
    assert headline == "08/12 (Fri) の天気予報です。"
```

test_hoge3()内では現在時刻 = テスト実行日時であるため、テストが失敗します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598747/b31d99e3-5cd0-c3f4-9a01-796f2d5afdf7.png)


### まとめ

pytest-freezegunを使ってテスト実行時の日時に関わらず、テストを通す方法を紹介しました。

日時に限らずテスト実行時の環境(天気・外部API等)への依存をいかに減らすかということがテストコードにおいては重要です。
狂信者は「コンパイラ言語」と「インタープリタ言語」の違いを説明するよ

# 結論
コンパイラ言語とはコンパイラに欲しい機械語を吐かせるためのスクリプト言語だよ。インタープリタ言語はインタープリタに欲しい計算をさせるスクリプト言語だよ。よくインタープリタ言語は毎行REPL(Read-Eval-Print-Loop)してると言う。Readが行ごとに処理する言語が多いけど、shellやpythonのforみたいに実際には制御構文単位でReadしてEvalが動くよ。そのReadする単位がファイルで指示を出す先がコンパイラなのがスクリプト言語たるコンパイラ言語なわけ。
テスト関数名を日本語で書いた時にPycharmのコードインスペクションからの警告を抑制する妥協案

私はテストコードの関数名を日本語で書くプラクティスを支持しています。  
しかし、関数名を日本語で書くとPycharm(JetBrain製のIDE)から `non ascii characters in an identifier` という警告を受けます。 
![スクリーンショット 2022-08-14 7.25.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/3f0ea229-dcf8-e613-b1c0-ebe157d52390.png)
 
この場合の妥協案を記載します。

妥協案は `non ascii characters` ~ のルールをテストコードファイルのスコープにおいて重要度を下げることです。


# `non ascii characters` ~ のルールをテストコードファイルのスコープにおいて重要度を下げる

この環境設定メニューで Edit Scopes Order... を選択します。

![スクリーンショット 2022-08-14 8.15.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/a7cf794e-4d50-7525-c6ea-c496ef4a0037.png)

tests scope を作成し、testファイルの範囲を指定します
![スクリーンショット 2022-08-14 8.17.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/5082d39f-fd92-e84d-341b-21bfc3eaca55.png)

先程の環境設定メニューで作成したtest scope を選択します
![スクリーンショット 2022-08-14 8.17.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/5b17547a-8b59-135d-5e9a-f52998d34441.png)



重要度で `No highliting, fix only`を選択します

![スクリーンショット 2022-08-14 8.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/0c446ead-67a0-e5a3-0838-cccce23f13fa.png)

以上で `non ascii characters in an identifier` という警告が消えます。
Spresense SDKでコンフィグレーション情報を保存する方法

Spresense SDKのコンフィグレーションを使いこなすためのTIPSです。

#### 現在のコンフィグ設定を保存する

menuconfig等でコンフィグ設定を変更した結果は、`spresense/nuttx/.config`ファイルに反映されます。いま現在のコンフィグ設定を保存しておきたい場合、`mkdefconfig.py`ツールを使用します。このツールは Kconfig システムの`make savedefconfig`相当の処理を行ってくれます。

```
// カレントディレクトリは spresense/sdk にいる前提
$ ./tools/mkdefconfig.py hoge
```

`mkdefconfig.py`の引数に`hoge`と指定すると、`sdk/configs/hoge/defconfig`というファイルを作成します。このファイルは`sdk/configs/default/defconfig`に書かれている情報を含むフルのコンフィグファイルになります。

別のコンフィグレーションを実行した後や、`make distclean`を実行した後に、さきほど保存しておいたコンフィグ設定を復元するときは次のように実行します。

```
$ ./tools/config.py hoge
```

#### 現在のコンフィグ設定を差分のdefconfigファイルとして保存する

```
$ ./tools/mkdefconfig.py examples/fuga
```

`mkdefconfig.py`の引数に`examples/fuga`のように指定すると、`sdk/configs/examples/fuga/defconfig`というファイルを作成します。このファイルは、`sdk/configs/default/defconfig`からの差分のコンフィグ情報だけが含まれたファイルになります。

さきほどと同様に、保存したコンフィグ情報を復元するときは次のように実行します。
```
$ ./tools/config.py examples/fuga
```

#### 現在のコンフィグ設定に別のdefconfigを追加したい場合

さきほどの手順の応用編で、現在のコンフィグ設定を一時的に保存しておくことで、別のdefconfigを簡単に追加できるようになります。

例えば、いま現在のコンフィグ設定をキープしたまま、SDカードを有効にしたり、`gpio`コマンドを有効にしたり、他のサンプル`examples/alarm`を追加したい場合、

```
$ ./tools/mkdefconfig.py -y hoge
$ ./tools/config.py hoge device/sdcard feature/gpiotool examples/alarm
```
`mkdefconfig.py`の`-y`オプションは既存の設定ファイルを問答無用に上書きするオプションです。既存のファイルが存在していて、このオプションの指定が無いときは、上書きするかどうかを尋ねてきます。`-y`オプションを指定することで強制的に上書きします。
early return（早期リターン）についてまとめる　可読性の上がるコーディング

#### はじめに

**early returnとはコーディングにおけるテクニック。**

条件式を扱う際に早期にreturnを返すことでif文のネストを減らすというテクニック。

この記事でearly returnについてまとめていきます。


**2022/08/14 21時50分　追記**
**<font color="red">※あくまでコーディングにおけるテクニックの一例を示すものです。こういうものがあるよ、ぐらいの認識で読んで頂ければ幸いです。<font>**

#### early returnでリファクタリング（修正前)

ここで一例を挙げてみる。

```python:sample.py
class Student:

  def __init__(self, student_id, name):
    self.student_id = student_id
    self.name = name

  def student_check(self):
    
    if self.student_id != "" or self.name != "":
      if len(self.student_id) > 12:
        flg = False
      else:
        flg = True
    else:
      flg = False
    return flg

student_exe = Student("101122222212","山田花子")
student_exe.student_check()
```

このコーディングの中で可読性を落としているのは一例として、if文のネストが挙げられる。
今回は簡易的な処理しか書いていないが、、、

**<font color="red">実際には条件式の後に多くの処理が書かれる訳で。。。**

数十行も書いたソースコードをネストさせて、ネスト後にも数十行書かれていたとしたら、可読性はもっと落ちてくる。

~~そこでソースコードを改善する為にearly returnを使う。~~

**2022/08/14 21時50分　追記分**
そこで今回は記事の題名にもなっている、early returnを使ってコードを修正していく。
early returnは名前の通り、早期にreturnをすることである。



**そもそも論として、returnは必ず関数の最後で使わなければならないのか？**

**<font color="red">答えはNoである。**

勿論、常にearly returnを使うことが正解という訳ではない。
ただ、returnを必ず関数の最後に書くという思い込みを消すことが大事なのである。


#### early returnでリファクタリング（修正後)

```python:sample.py
class Student:

  def __init__(self, student_id, name):
    self.student_id = student_id
    self.name = name

  def student_check(self):
    if self.student_id == "" or self.name == "" or len(self.student_id) <12:
      flg = False
      return flg
    if self.student_id != "" and len(self.student_id) >12:
      flg = True
      return flg
 
student_exe = Student("10112222222212","山田花子")
student_exe.student_check()
```

この様に途中でreturnを行うことでif文のネストを減らすことができる。
~~心なしか可読性が上がった気がしませんか？~~

色々と粗はあると思いますが。。。

#### 最後に

~~early returnを意識して無駄なif文のネストを減らしましょう。~~

**2022/08/14 21:50追記分**
early returnを使えば、if文のネストを減らせることがあります。
**※勿論、early returnをすれば必ずしも可読性が上がる訳ではないです。**
なので、ここはearly returnを使った方が良いな、みたいな時に使ってみてください。
Power Automate の 「タグにメンバーを追加する」（Teamsコネクタ）の使い方

# Update（2023/02/12)

「手間２：チームとタグIDには「チームのタグをすべて一覧表示する」で取得した内部IDを指定する必要がある」は不要となりました。
当アクションの「チーム」で選択肢として表示されるチームを選択でOKです。


# はじめに

Power Automate の Teams コネクタに、「タグにメンバーを追加する」というアクションが存在しています。
これは、チームのメンバータグにユーザーを追加することが可能なアクションです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/311d6296-25ae-2086-cdbd-bedea1f0e530.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/fa915c8e-27f1-f780-1293-e3bc790e47c8.png)

**が、Power Automate の利点である、直観的に操作しながら設定するとエラーとなるため、使い方にコツが必要です。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/b8305228-545d-b3e9-2d5d-62e5247c6e53.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/a79fe5cb-dd23-22e6-9651-27a32207b354.png)



当アクションのDocsはこちら

https://docs.microsoft.com/ja-jp/connectors/teams/#%E3%82%BF%E3%82%B0%E3%81%AB%E3%83%A1%E3%83%B3%E3%83%90%E3%83%BC%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B


# 「タグにメンバーを追加する」アクションの使い方

このアクションを利用するには~~2手間~~ 一手間が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/5c7e7dd2-03fc-9c66-64bb-8cfb4324e8fa.png)




## 手間１：ユーザーＩＤは、Azure AD の内部ID を指定する必要がある

**メールアドレスやUPNを直接指定しても、アクションはエラーになります。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/d5060549-67c3-ec30-1ed1-4023851c1df7.png)

タグを割り振るユーザーを指定する [ユーザーID] には、「ユーザー プロフィールの取得 (V2)」 で取得した、[ID] （動的コンテンツ） 指定してください。






## ~~手間２：チームとタグIDには「チームのタグをすべて一覧表示する」で取得した内部IDを指定する必要がある~~

2023/02/12 当手間は不要となりました。チームをドロップダウンより直接選択でOKです。

**~~チーム と、タグID には、チームやタグが選択可能なドロップダウンリストが表示されますが、リストから選択してもエラーとなります。~~**

① 「チームのタグをすべて一覧表示する」アクションで、対象メンバーの存在するチームを選択し、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/7a7b9ac5-6ef8-9a04-6132-ba881dc9917a.png)


②　複数タグが存在する場合は、「アレイのフィルター処理」で目的のタグをタグ名で検索し、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/f8a2f152-6759-6b5a-d6a1-e9bc06459b59.png)

③ チーム と タグID にカスタム値として、内部IDを指定します

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/6602a689-e569-0400-dea1-e9290f00bc53.png)

**動的コンテンツでチームID やタグID を選択すると、Apply to each によるループ処理が差し込まれるため、下記のように式を使って取得するのが無難だと思います**

#### ■チームに設定する値
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/b5186bd4-f4c8-7aae-dedb-5186b0de70f9.png)

```
body('アレイのフィルター処理')?[0]?['teamId']
```

#### ■タグID に設定する値
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/5dfb27dd-f072-14f7-cb0d-09450b3952de.png)

```
body('アレイのフィルター処理')?[0]?['id']
```

# おわりに

記載したフローは最小限な内容ですが、チームメンバーを指定のタグに追加する目的は果たせるかと思います。
通常の操作だけではエラーとなってしまうこのアクション、改善されることを願います。
Splunk: 所有ユーザーの変更方法


###### 実施環境： Splunk Free 8.2.2

### 0. 概要

一度作成したスケジュールサーチやマクロなどについて、所有ユーザーを変更したい場合があります。
しかし、これらのオブジェクトについてはそれぞれのオブジェクトの一覧から所有ユーザーを変更できません。
ではどこで変更するのかというと、「ナレッジオブジェクトの再割り当て」という画面で変更します。

### 1. 手順

まずは、「設定」から「すべての環境設定」を選択します。

![WS000135.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/162d2cb5-1761-104c-dc5e-7bf9b1adc2e8.jpeg "設定")

次に「ナレッジオブジェクトの再割り当て」を選択します。

![WS000136.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/c64fb912-56df-4559-22e1-9a86f71638bf.jpeg "すべての環境設定")

これで、「ナレッジオブジェクトの再割り当て」画面に移動できます。

![WS000137.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/a4838686-6945-94d6-bc10-d8004ba001ab.jpeg "ナレッジオブジェクトの再割り当て")

「オブジェクトタイプ」を変更することで、どのオブジェクトについて所有ユーザーを変更するのかを選択します。
今回はルックアップ定義について変更するために、「 transforms-lookup 」を選択します。
するとルックアップ定義だけが表示されるので、所有ユーザーを変更したいルックアップ定義について「再割り当て」を選択します。

![WS000142.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/379a8c46-da34-28bd-97d5-225426315306.jpeg "ルックアップ定義")

すると以下のような「エンティティの再割り当て」画面が表示されます。
ここの「新しい所有者」に変更後の所有者を選択し、「保存」を押します。
今回は、「誰でもない」、すなわち所有者なしに変更します。

![WS000144.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/b77a6d5b-e837-2b75-4448-2d6fd41eb7d3.jpeg "エンティティの再割り当て")

以下のように変更されました。

![WS000145.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/7ca6bfb7-fd38-7f71-24b0-320020e1ae61.jpeg "誰でもない")

### 2. 所有者なしに変更する場合の注意

少々特殊なケースですが、共有権限が「プライベート」の場合、そのオブジェクトについて所有者なしにすることはできません。
以下のように、「 Cannot reassign privately shared entity to unowned 」というエラーメッセージが出て変更に失敗します。

![WS000146.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/aa163fb0-4c0a-96b7-add1-cc00c8fab601.jpeg "プライベート")
PiCamera module v2を有効にする

# はじめに
Raspberry Pi Camera V2を動かす記事はRaspi-configを使う方法が多く出ているが、
Raspi-configを持たないUbuntu1804やserver等では、依存関係などもあり、インストールが面倒です。
その為、Raspi-configを使わない方法をまとめる。

# 実行環境
 <table>
    <tr>
      <td align="center">ホスト</td>
      <td>RaspberryPi 3B+</td>
    </tr>
    <tr>
      <td align="center">OS</td>
      <td>Ubuntu 18.04.3 LTS</td>
    </tr>
    <tr>
      <td align="center">カメラ</td>
      <td>Raspberry Pi Camera V2</td>
    </tr>

 </table>

# 1.  /boot/firmware/config.txt を編集

```
start_x=1             # essential
gpu_mem=128           # at least, or maybe more if you wish
disable_camera_led=1  # optional, if you don't want the led to glow

```




# 2. v4l2ドライバーの読み込み

 Raspberry Pi の PiCameraを使用する場合、オフィシャルのV4L2ドライバーをロードする必要がある。 
下記のコマンドでraspiカメラを扱うためのポート（/dev/video0）を開けます。
```
$ sudo modprobe bcm2835-v4l2
```
 起動時に自動的にロードできるように、/etc/modules ファイルに以下の行を追加する。
```
bcm2835-v4l2
```
ディレクトリ配下の全てのファイルに接頭辞をつけるコマンド

# ディレクトリ配下のファイル冒頭に一律同じ接頭辞をつけたい
ファイル名の接頭辞でファイルの属性を簡易的に区別したい場合など、特定ディレクトリ内のファイル全てに接頭辞をつけたい場合がある。

## 例
```shell:元のディレクトリ構成
$ tree
.
├── featureA
│   ├── image1.png
│   ├── image2.png
│   ├── image3.png
│   ├── image4.png
│   └── image5.png
└── featureB
    ├── image10.png
    ├── image6.png
    ├── image7.png
    ├── image8.png
    └── image9.png
```
```shell:期待結果
$ tree
.
├── featureA
│   ├── a_image1.png
│   ├── a_image2.png
│   ├── a_image3.png
│   ├── a_image4.png
│   └── a_image5.png
└── featureB
    ├── b_image10.png
    ├── b_image6.png
    ├── b_image7.png
    ├── b_image8.png
    └── b_image9.png
```

# 前準備
`rename`コマンドをもちいるため、インストールされていない場合はインストールする。

```shell
brew install rename
```

# コマンド
下記コマンドで接頭辞をつけることができる。
```shell
rename 's/^/{つけたい接頭辞}/' *
```
今回の例で言えば、`featureA`ディレクトリに移動後、`rename 's/^/a_/' *`を実行することで`featureA`ディレクトリ内の全てのファイルに`a_`を付与することができる。


# コマンド実行例
```shell:元のファイル構成
$ ls
image10.png     image6.png      image7.png      image8.png      image9.png
```
```shell:接頭辞にb_をつける
rename 's/^/b_/' *
```

```shell:実施結果
$ ls
b_image10.png   b_image6.png    b_image7.png    b_image8.png    b_image9.png
```
人事のおじさんプログラミングを学ぶ Day1 「"Hello, World!"」

やってみないことには始まらないということで、「14歳からのプログラミング」を読みつつ、WindowsにVisual Studio CodeとNode.jsをインストールして、JavaScriptとHTMLで"Hello, World!"のコードの書き方をネットで調べてプログラムしてみました。

![2022-08-14_d1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783084/323ac55b-8c73-4692-b2e5-26c9372af690.png)
簡単なICPスキャンマッチング(1スキャン分)をpythonでやってみた

## 環境
- ROS1やROS2のpythonで動かしていました．
- Anacondaの使用時は少し上手く動かないかもしれません．

## 目的
超シンプルなICPアルゴリズムといえど，一旦は自分で書き起こして，点同士対応付けやマッチングの様子をビジュアル化をしたいもの．そこで，pythonで1スキャン分のICPスキャンマッチング(2D)を再現してみた．本アルゴリズムは「SLAM入門」を参考にして作りました．

## Repository
```
git clone https://github.com/KOKIAOKI/simple_icp.git
```
https://github.com/KOKIAOKI/simple_icp.git

## 概要
- 点群は，csv形式で任意のx,yの座標を用意します．(点群データは最終的にはnumpy配列にして計算していくので，ご自分に合わせて変えてみてください)
- 初期位置を手動で与えることができます．やり直すこともできます．最適化手法のパラメータとなる点群の代表点は，点群座標の平均値です．
![Initial_pose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1294864/2006e270-13c5-ff30-7a90-f48a8b166430.png)

- 最急降下法，ニュートン法，共役勾配法(CG法)のいずれかを用いて点群と点群同士をマッチングさせることができます．最近傍探索にはkd-treeを用いています．
- 出力には，マッチングするまでのアニメーション(対応付けも可視化)と軌跡を表示します．
- 軌跡グラフ上では，収束時点のスキャン点群位置を用いて，総当たり的に点群同士の平均距離の分布をヒートマップ状に出力します．
![newton_animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1294864/0741dd33-e9eb-8578-a0b8-ba7ef10d8645.gif)

## 使い方
READMEを参考にしてください．

## 中身について
- ICPの誤差関数
スキャン点群$\boldsymbol{p_i}(i=1,2...N)$と参照点群（地図側）$ \boldsymbol{q_j}(j=1,2...M)$で誤差関数$E$を定義します。スキャン点群と参照点群の対応付けは、kd-treeを用いて$\boldsymbol{p_i}$に対する最近傍の点$ \boldsymbol{q_j}$とします。$R$は回転行列、$ \boldsymbol{t}$は並進ベクトルです。意味合い的にはスキャン点群と対応付けられた参照点群の距離の二乗平均です。これを最小化します。最小化には下記で述べる３種のいずれかの最適化手法を用い、局所的な最適解を求めるたびに最近傍探索を実施します。収束判定はclassのinitの中でハードコーディングしているので適当にいじってください。

```math
E( \boldsymbol{x}) =\frac{1}{N} \sum_{i=1}^{N}\|(R \boldsymbol{p_i}+ \boldsymbol{t}) - \boldsymbol{q_j}\|^{2}
```

以下は時間が合ったら記述します。
### 最適化手法
「これなら分かる最適化数学」や「しっかり学ぶ数理最適化」という書籍が非常にわかりやすいです。
- 最急降下法

- ニュートン法

- 共役勾配法(CG法)

- 勾配F

- ヘシアンH

## おわりに
コードの中身は誰にも見てもらっていないので間違えてたり効率の悪い計算をしていたら申し訳ないです。良ければ改善点などを教えていただけると嬉しいです。スクリプト内は日本語でメモしていますので最適化部分の実装やICPの理解の補助となれば幸いです。
今後はNDT1スキャン分の簡単な可視化もしたいなと思っています。

## 参考文献
1. SLAM入門 ロボットの自己位置推定と地図構築の技術、友納正裕、オーム社、2018年
1. これなら分かる最適化数学　基礎原理から計算手法まで、金谷健一、共立出版株式会社、2005年
1. しっかり学ぶ数理最適化　モデルからアルゴリズムまで、梅谷俊治、講談社、2020年
Spring入門-URL叩いてファイル作成

Java界隈で良く使われているSpringBootでファイル作成処理を作っていきます。
![処理概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951197/5c49c42a-d484-c644-33d1-ccfa7ea8a5fc.png)

UserがリクエストURL「localhost:8080/api」を叩いたら、任意の場所にファイル作成を行う。
Springプロジェクトだと「src/main/resources」に置くことが多い。
※参照ファイルは大抵の場合、resourcesに入っている

```java:HelloController.java
package com.sample.app.controller;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.sample.app.controller.service.OutputStreamSample;

/** サンプルコントローラー */
@RestController
public class HelloController {

	/** ファイル作成処理サンプル */
	@Autowired
	OutputStreamSample outputStreamSample;

	private final String message = "ファイルが作成されました(ﾟ∀ﾟ)";

	/**
	 * getメソッドで処理を実行(http://localhost:8080/api)
	 *
	 * @throws IOException
	 * @return 表示メッセージ
	 */
	@GetMapping("api")
	public String hello() throws IOException {

		// ここにファイル作成処理を実行する。
		outputStreamSample.createFile();

		return message;
	}
}
```

```java:OutputStreamSample.java
package com.sample.app.controller.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;

/** ファイル作成処理サンプル */
@Service
public class OutputStreamSample {
	/**
	 * ファイル作成処理
	 * 
	 * @throws IOException
	 */
	public void createFile() throws IOException {
		// ファイルの中身を記載
		String exampleString = "HelloWorld\nようこそSpringBootの世界へ\nこれが作成されたファイルの内容だよ\n⊂⌒~⊃｡Д｡)⊃";
		// ライブラリ「org.apache.commons.io」を利用して String → InputStream を作成
		// toInputStream(InputStream, 文字コードの指定);
		InputStream inputStream = IOUtils.toInputStream(exampleString, StandardCharsets.UTF_8);
		// ファイル生成
		String resourcesPath = "src/main/resources/output/";
		FileOutputStream outputStream = new FileOutputStream(new File(resourcesPath + "samplefile.txt"));
		// ファイル書き込み処理
		int mojiIndex;
		while ((mojiIndex = inputStream.read()) != -1) {
			char getSingleChar = (char) mojiIndex;
			outputStream.write(getSingleChar);
		}
	}
}
```
・動作内容
「localhost:8080/api」を叩くと...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951197/4254cfec-b1f2-89af-4d35-b71f5e6b279b.png)
と表示される。

作成されたファイルの中身は..
```text:samplefile.txt
HelloWorld
ようこそSpringBootの世界へ
これが作成されたファイルの内容だよ
⊂⌒~⊃｡Д｡)⊃
```
こんな感じです。

・ライブラリ「org.apache.commons.io」について

```java
InputStream inputStream = IOUtils.toInputStream(exampleString, StandardCharsets.UTF_8);
```
ここの一文で使用されている「IOUtils.toInputStream」ライブラリーを用いて、文字データをファイルデータに置き換えている。

gradleでインストール際は以下の記述が必要。
```gradle
dependencies {
	implementation 'commons-io:commons-io:2.11.0'
}
```

・参考サイト
『Java で文字列を InputStream に変換する』
https://www.delftstack.com/ja/howto/java/java-string-to-inputstream/
『Apache Commons IO ™』
https://commons.apache.org/proper/commons-io/dependency-info.html
『Gradle Docs』
https://docs.gradle.org/4.10/userguide/java_plugin.html#sec:java_plugin_and_dependency_management

・動作確認用の公開ソースコード
https://github.com/sunn-sudo/spring-sample
Elasticsearchクラスタ検証(5): Elasticsearchシステム構成の基本

##### [前回] [Elasticsearchクラスタ検証(4): Elasticsearch 8.xのクラスタ化(HTTPS対応)](https://qiita.com/mingchun_zhao/items/05dd4ed7197bd2e27d6e)

## はじめに

Elasticsearchクラスタを設計する前に、
Elasticsearchシステム構成の基本をおさらいします。

## Elasticsearchとは、その特徴

- 全文検索サーバである、検索エンジンにApache Luceneを使用
    - 転置インデックスを使用し、全文検索を高速に
- 分散配置により、検索性能と可用性のスケールアウトを実現
    - クラスタ構成でデータを分散保存/処理
- REST APIを使ってJSONフォーマットの文書を扱う
    - 他のシステムと親和性がよい

## Elasticsearchクラスタのアーキテクチャ概要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/e21d0158-c2ef-1a23-94d7-fc42c1bde7fa.png)

※ 引用元: https://raw.githubusercontent.com/exo-addons/exo-es-search/master/doc/images/image_05.png

## Elasticsearchの論理構成

### 用語

- インデックス
    - ドキュメントの保存場所
- ドキュメント
    - インデックスに格納する一つの文章単位(RDBのレコード相当)
- フィールド
    - ドキュメント内のキー/バリューペア
        - データ型が存在
- ドキュメントタイプ
    - 全フィールドのデータ型(RDBのスキーマ相当)
    - 1つのインデックスに一種類のドキュメントタイプのみ
- マッピング
    - ドキュメントタイプの定義(RDBのテーブル定義相当)

### 構成

- インデックス
    - ドキュメントタイプ(マッピング)
        - ドキュメント1
            - フィールド1
            - フィールド2
            - 。。。
        - ドキュメント2
            - フィールド1
            - フィールド2
            - 。。。
        - 。。。

## Elasticsearchの物理構成

### 用語

- ノード
    - Elasticsearchが稼働する各サーバ
- クラスタ
    - 複数ノードが協調動作するグループ
- シャード
    - インデックスを分割する単位
        - 実体はLuceneインデックスファイル
    - 目的
        - 複数ノードで並列検索し性能向上
    - インデックス作成後には増やせない
- レプリカ
    - シャードの複製である、プライマリとレプリカは異なるノードに配置
    - 目的
        - 可用性(ノードダウン時データロスト防止)
        - 検索性能向上の狙いも
    - インデックス作成後も増やせる

### 構成

- クラスタ
    - ノード1
        - インデックス1
            - シャード1(プライマリ)
            - シャード2(プライマリ)
            - 。。。
        - インデックス2
            - シャード1(プライマリ)
            - シャード2(プライマリ)
            - 。。。
    - ノード2
        - インデックス1
            - シャード1(レプリカ)
            - シャード2(レプリカ)
            - 。。。
        - インデックス2
            - シャード1(レプリカ)
            - シャード2(レプリカ)
            - 。。。
    - ノード3
        - 。。。


## おわりに

Elasticsearchのシステム構成をおさらいしました。
次回も続きます。お楽しみに。

##### [次回] [Elasticsearchクラスタ検証(6): クラスタの基本構成](https://qiita.com/mingchun_zhao/items/f19f619c27f9177d7d0e)
Amazon Lightsail Wordpressでブログサイトを作る

# はじめに
- AWSを勉強したい私（ハードルが高いという先入観から重い腰がなかなか上がらず早数ヶ月経過）
- ブログを開設したい夫（今すぐにでもはじめたい様子。YouTubeで得た知識からよくわからんレンタルサーバーを年額16,000円で借りようとしている。まずい。）

目的の一致・半ば危機感から爆速でブログサイトを作成するに至りました。



# 前提
- Mac OS
- AWSアカウント作成済み

# やったこと

今回はスピード重視・完全なる個人サイト・まずはとりあえず開設という目的のためLightsailを使ってみました。基本的にチュートリアル通りの手順通り。

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

## 順番にやっていきます

- 公式チュートリアル
https://lightsail.aws.amazon.com/ls/docs/ja_jp/articles/amazon-lightsail-tutorial-launching-and-configuring-wordpress
（補足）https://www.takoboolog.com/wordpress1/

- 公式チュートリアル - 独自ドメインの取得
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register.html

- 公式チュートリアル - DNSの設定
https://lightsail.aws.amazon.com/ls/docs/ja_jp/articles/lightsail-how-to-create-dns-entry
（補足）https://www.takoboolog.com/domain2/

- 公式チュートリアル - スナップショットの手動作成
https://lightsail.aws.amazon.com/ls/docs/ja_jp/articles/lightsail-how-to-create-a-snapshot-of-your-instance

- 公式チュートリアル - スナップショットの自動作成
https://lightsail.aws.amazon.com/ls/docs/ja_jp/articles/amazon-lightsail-configuring-automatic-snapshots

- 公式チュートリアル - SSL設定
https://aws.amazon.com/jp/premiumsupport/knowledge-center/linux-lightsail-ssl-bitnami/
（補足）https://www.gworks.jp/2022/03/__trashed/