OmniAICreator/Qiita-1.07M huggingface dataset:
40代が始めるWordPress副業 (2)

昨今の物価高、中国経済の停滞に伴う不況、増税により私の生活は厳しくなるばかり・・・
これはいよいよ副業でもせんとやってけん、ということで、最近副業が解禁された製造業の社内SEとして
サーバサイドや基幹システムばかりやっていた40代成りたてのおっさんが、
副業を始めて1年後までにどの程度稼げるようになるか、ツラツラと残していきます。

過去ログ
[#1](https://qiita.com/Takeshi_Shimoda/items/1421fc66b595b635e6de)

# なんでWordPress?
年末に高校時代の友人と忘年会を実施し、企業の基幹システム系のガチガチのスキル(JavaやOutSystems等)だと副業が転がっていない話をした際に、WEBサイト制作のディレクターをやっている友人にテーマ改造スキルがあるなら仕事をふれるよ、と紹介してもらったから。(持つべきは友達)

ちなみに所持スキルは以下のような感じ。
WEB/BATCH設計・開発
　Java, OutSystems ともに企業の開発標準を作成・指導できるレベル
　Java実績：会社の開発標準(Web/Batchともに)維持・展開・拡張・教育を担当
　　　　　　数千万から数億案件の開発リーダ
　　　　　※ただし最近はAWSで少し触る機会あるくらいで全然やってない
　OutSystems実績：会社のワクチン接種アプリを２週間で設計、開発、リリース
　　　　　　　　　自社の開発標準策定、プロジェクト支援多数
ツール開発　Python, Seleniumを用いたWEBクローリングによる情報収集アプリ開発
　　　　　　AWS EC2+Jenkinsでの構築・運用
　　　　　　GameWith社様のツール開発コンテストで佳作入賞
テスト自動化　SikuliとOutSystemsを組み合わせたノーコードテスト自動化ツールの開発
　　　　　　　テスト自動化手法の自社導入、対外発表(テスト自動化カンファレンス)
そのほか：C#(OutSystems Module開発), javascript, Oracle, Postgresql, PS等
　　　　　7億円規模案件のPL経験など

上記スキルがあればなんか出来そうな気もしたが、見つかるのはほぼSIerで常駐案件という感じ。
副業でちょこっと仕事したいんじゃーってなるとどこにもない。
その点WordPressやPHP案件は豊富なので、ワクワクしますね。

# やったこと
2023/1/3
Udemyで動画勉強中

ざっくり学ぶ、WordPress 6.xでノーコードサイト制作講座
　27/118まで
ちゃんと学ぶ、WordPress テーマ開発講座
　38/52まで

# 備忘録
相対パスは絶対パスに修正する
vendor/fontawesome-free/css/all.min.css
↓
http://mysite.local/wp-content/themes/myblog/vendor/fontawesome-free/css/all.min.css
↓
PHP　echo get_template_directory_uri();　/vendor/fontawesome-free/css/all.min.css

SSL通信かどうかが定まらない場合
https://...
↓
//...

ページは共通化した方がメンテナンス性よいのでパーツ化する
get_header(), get_footer, ほかにparts化したい場合はget_header('phpファイル名の拡張子抜き')のように指定

関数拡張やイベントを追加したい場合はfunctions.phpに記述する

-- 追記 -----------
言語宣言は動的にする
html PHP language_attributes();

ページ表示の状態によってClass制御する
body PHP body_class();

おまじない
body PHP wp_body_open();
HTTPヘッダとは

# HTTPメッセージ

HTTPは、WebブラウザとWebサーバー間の通信に使われるプロトコルです。

ブラウザはリクエストする前にリクエストメッセージを作成します。
Webサーバーはレスポンスをする前にレスポンスメッセージを作成します。
（リクエストメッセージ・レスポンスメッセージを総称してHTTPメッセージという）

HTTPメッセージは以下のような形式です。

```
スタートライン
ヘッダ
(空行)
ボディ
```
```:レスポンスメッセージの例
HTTP/1.1 200 OK
Content-Type: application/xhtml+xml

<html>
...
</html>
```

ボディには、リソースそのものが入っています。

# HTTPヘッダとは

HTTPヘッダは、メッセージのボディに対する付加的な情報（メタデータ）が入ります。

HTTPヘッダによってボディに関する説明を加えたり、サーバーからキャッシュに関する指示をブラウザに伝えたりすることができます。

どのようなヘッダがあるのかは以下を参照。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers


# まとめ

HTTPヘッダは、メッセージのボディに対する付加的な情報です。
[Python]スライスで文字列を反転させる

スライスはいいぞ。

# 方法
```py
s = "aiueo"
s = s[::-1]   # <- ここで反転
print(s)      # "oeuia"
```

# しくみ
スライスの引数は、それぞれ以下の意味を持ちます。

```
[始点:終点:ステップ]
```

値を代入しなければ、自動的に初期値が挿入されます（それぞれ0, 文字列長, 1）

このうち、**ステップ**というものに注目。
これは、スライスが処理する中の繰り返しで**インデックスに加算される値**です。

普段は1なので、頭から一文字ずつ。
ここを2にすると、最初の文字から**1つ飛び**で処理していきます。
インデックスが`0->2->4`と飛ぶからですね。

---

で、`-1`はというと。
**始点と終点をひっくり返す**効果を持っています。
つまり、文字列の終わりから一文字ずつ処理するんですね。

つまり、「後ろから一文字ずつ並べていく = 文字列が逆になる」という感じです。
【Web制作⓪】webページを公開するために

# はじめに
Web公開までのビジョンを立てるために、Webページを公開するまでの流れを調べました。
※自分の調べたことを書いて覚えるために書きます。自分に向けて書いてます。


# Webページを**公開**するまでの流れ
Webページを制作し、公開することをゴールとすると、
1. Webページの制作
1. ドメインの取得
1. サーバーを用意する
1. ドメインとサーバーを繋ぐ
1. ホームページのデータをサーバーにアップロードする（　公開:v:　）

この５工程が必要です。

### 1.Webページの制作
#### ホームページ制作の基礎
Webページを制作するのには、**HTML**を使用します。
一般的なホームページには、見出しや本文などが存在します。
HTMLはプログラム言語で、その見出しや本文などの要素を定義するために使います。
定義した要素をデザインして、おしゃれなホームページを制作するのには、**CSS**を使用します。


HTMLを使ってホームページを制作する流れは、
- テキストエディタを用意する
- HTMLの基本となるタグを使って記述
- HTMLで保存
- ファイルをブラウザで表示して確認

#### テキストエディタの用意
今回は、VScodeでHTML開発環境を用意する。
プラグインなど[このサイト](https://qiita.com/84zume/items/476a29264fdc98d98201)を参考にして設定した。

### 2.ドメインの取得
ドメインとは、住所のようなもの。
![image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079184/a165abaa-0d2b-be6f-5522-868138eff61f.gif)

### 3.サーバーを用意する
レンタルサーバーを借りるのが最も簡単(無料で用意することは可能ではある)

### 4.ドメインとサーバーを繋ぐ
書くのめんどくさくなってきたので、元サイト↓

https://pr.toriaez.jp/navi/column/2546.html




# 参考文献
- https://pr.toriaez.jp/navi/column/2511.html
- https://qiita.com/84zume/items/476a29264fdc98d98201
- https://pr.toriaez.jp/navi/column/2546.html
-
【Webアプリ開発】3ヶ月の長期インターンでの反省点と経験したこと

# はじめに
- 地方の大学に通う3年生
- 研究室でのPythonを使った開発でプログラミングに興味を持つ
- エンジニアとして働くことの難しさややりがいを知りたいと思い、インターンに応募
- Webに関してはFlaskを使って簡単なWebアプリを作ったレベル

2022年10月からの3ヶ月間ですが、すごく貴重な経験をさせていただきました。
まだインターンは続きますが、一旦これまで経験したことと反省点を整理するために振り返りたいと思います。
拙い文で、間違っているとこもあるかもしれませんが、生暖かい目で見てもらえると幸いです。

# 体験した業務内容

社内向けWebアプリの開発に要件定義から経験させていただきました。
インターン生同期3人で要件定義を行い、開発はそれぞれで行っています。

### 要件定義
これまで個人で開発するときは、なんとなくで進めて、開発途中でなんとなく機能追加というスーパーアジャイル開発を行ってましたが、もちろん実務ではそうはいきませんでした。

アプリのコンセプト・似た他社サービスにない強み・ペルソナ（アプリを使用する具体的なユーザー像）

これらを先に定義しておくことで、その後の企画・開発がスムーズに進みました。

また、一つ一つの機能の有無に対して、実装方法に対して、なぜ？と突き詰めて考え、理由づけしていくことが難しく感じました。

### 要件定義に対してのレビュー
インターン生3人で行った要件定義に対して、先輩社員から設計に不備がないかレビューをいただきました。
緊張に弱い僕は、先輩に意見をもらうたびに慌てふためいてました。
そうならないためのポイント

- 前提として、責められる場ではなく仕様の確認をする場
- 突っ込まれても、その設計になった理由を話す
- 突っ込まれた点に対し、詰めきれてなかったのであれば素直に認める

## 開発環境
### データベース：MySQL
今回はdrawSQLを使ってER図を作成しました。

- 学んだこと
- 汎用的なカラム名は避ける
    - 例：memo → description
- 制約について
    - 外部キー制約：_id系につける（元データが消されてもデータが消されないように）
    - ユニーク制約：同じデータが登録されたくないカラムに
    - 複合ユニーク制約：指定したカラムの値の組み合わせが同一のデータは登録できないように
- NULLについて
    - NOT NULL制約：NULL入れてもいいカラム以外には基本的につける
    - テキストの型にNULLを許可すると複雑度が増すから避ける
        - 通常の値と空文字とNULLの3つを扱うことになる

### バックエンド：RailsでWeb APIサーバーを構築

- 使ったライブラリ、ツール
    - Pry：デバック
    - RuboCop:　.rbファイルを検査しコードの書き方をチェックしてくれる
        - デフォルトだとチェックがかなり厳しいので`.rubocop.yml`でフォーマットルールを設定
    - bullet：N＋1問題を検知
        - N＋1：データ取得の際、データが増えるほど発行されるクエリ数が多くなる問題
- API設計
    - リソースベースのルーティング
        - `resources`を宣言するだけで`index`,`update`などのアクションを個別で宣言する必要がなくなる
        - アクション名ではなく、HTTPメソッドでリソースを表現するURIが生成される
    - RESTful APIを意識
    - ファットコントローラーを避ける
        - 複数のアクションで重複している処理は`before action`で定義
        - 長いコードはメソッド化してモデルへ

個人的には、N＋1問題が一番思い出深いですね。
ネストしたテーブルデータの扱いに苦戦し、Bulletからかなり怒られました。
ただ、この問題はアプリのパフォーマンスに直接関わるため解消に努めました💪
苦しんだところは以下記事でまとめています。

https://qiita.com/a2c6201/items/93196860bcf0ce78df96

また、N＋1について学ぶとき、以下の例えがとてもしっくりきました。

> 日常生活で例えるなら、スーパーで商品を1点ずつお会計するようなもの。
それだけ無駄なことを行なっている状態を指します。

https://qiita.com/massaaaaan/items/4eb770f20e636f7a1361
### フロントエンド：React
こちらは現在も続けています。
- 躓いたこと, 学んだこと
- ライフサイクル(処理順序)を理解して開発
- reactのstateが即時更新されない
    - 原因：　state更新処理が非同期だから
- コンポーネントのimport error
    - `named export`, `default export`の違い

## 終わりに

突っ走ってきた感じで、まだまだ詰めきれていないところばかりです。
Web開発における、フロント・バック・インフラという必要な知識量、奥深さに圧倒され続けた3ヶ月間でした。
ただ、いろいろな技術を学ばせていただけましたが、 Web開発の楽しさを知れたということが一番の収穫でした。
今後は、個人的にコードを書くだけでなくWebの仕組みの部分も勉強したいと思います。
解像度を上げる

「解像度を上げる」を読んだのでメモ

・そもそも「解像度が高い」とは何？
→考えや事実認識が「詳細」であること

・解像度を高めるには何が必要？
→「深さ」「広さ」「構造の把握」

　・深さとは？
　→原因の追求（なぜ？どうしてその現象が発生するのか）
　　・深さを高めるには？
　　→現場を知る

　・広さとは？
　→様々なアプローチと視点
　　・広さを高めるには？
　　→専門知識を増やす

　・構造の把握
　→概念や現象の整理
　　・構造の把握を高めるには？
　　→図式化する（フローチャートとか）
vimでインデントの設定がpythonのときに反映されないときの対処法

インデント、タブを半角2文字にするため、`.vimrc`に以下のように記述した。
```
set tabstop=2
set softtabstop=2
set shiftwidth=2
```
しかし、pythonのときだけ反映されず4文字になる。どうやらpythonはデフォルトで何かあるようで、それを無効にするため（？）に以下を`.vimrc`に追加すると、無事反映されて2文字になった。
```
let g:python_recommended_style = 0
```
Ender 5 S1事始め⑥（Cura最大解像度変更）

[前々回](https://qiita.com/fmax/items/647eae81f20a9e8a6503)でArc Welderが円形状に効果があるということが分かった。
今回は更なる高精度化を求めてUltimaker Curaの「メッシュ修正」の設定項目の一つ「最大解像度」について効果を確認したいと思う。

## 最大解像度
最大解像度とは「スライス後の線分の最小サイズ」である。
前々回でスライサーで円は直線に分割されるという話を書いたが、最大解像度を変えると円の分割数が変わる。
ただし、注意したいのは**線分の最小サイズ**というところ。
つまり、円が大きい場合は分割数がカウンターストップし、最大解像度の変更の効果が見られない。

最大解像度の変更で期待される効果は下記となる
|  | メリット | デメリット |
|:-:|:-:|:-:|
| 最大解像度UP | 精度の向上 | gcode肥大化による移動途中での停止→肌荒れ |
| 最大解像度DOWN | gcode削減による高速動作 | 精度の低下 |

## ファイルサイズ測定
gcodeが肥大化したかどうかはファイルサイズを測定すると判定できる。

まずは前々回作成した[Dimensional Accuracy](https://www.thingiverse.com/thing:5719188)を最大解像度を変更しながらファイルサイズを測定した。
なお、最大偏差は最大解像度の半分としている。
| 最大解像度(mm) | ファイルサイズ(kB) | ファイルサイズ(kB) Arc Welder使用 |
|:-:|:-:|:-:|
| 0.25 | 822 | 222 |
| 0.15 | 842 | 222 |
| 0.1 | 844 | 217 |
| 0.05 | 846 | 218 |
| 0.01 | 846 | 220 |

ご覧の通り、0.25mm→0.15mmで多少の変動は見られるがファイルサイズに大きな影響は無い。
これは分割数のカウンターストップが行われているためと思われる。

これでは最大解像度変更の効果が分からないため、次に#FDMTestのモデルを同様にスライスしてみた。
| 最大解像度(mm) | ファイルサイズ(MB) | ファイルサイズ(MB) Arc Welder使用 |
|:-:|:-:|:-:|
| 0.25 | 6.6 | 4.43 |
| 0.15 | 6.93 | 4.55 |
| 0.1 | 7.25 | 4.65 |
| 0.05 | 7.67 | 4.67 |
| 0.01 | 7.73 | 4.69 |

微妙にファイルが肥大化している。
Arc Welder使用時は円が分割されて肥大化されたものを円に戻してしまうため、大きなファイルサイズの違いにはならない。つまり
**最大解像度UPによる肥大化<<Arc Welderによるgcode削減**
ということで、Arc Welderを使うという前提ならばガンガンに解像度UPして良いのではないだろうか？

と言ってもFDM方式の精度限界が±0.1mmぐらいと思われるため10倍精度としても0.01が精々と思われるが。

## それで実際効果あるの？
実際に#FDMTestをデフォルトの0.25mm→0.01mmに変更して印刷してみたが
少なくとも#FDMTestのポイントに影響するような**有意な差異は見られなかった**。
うーん、正直良く分からない・・・。

## 結論
結論としてはパラメトリックなCADからの出力モデルで
かつArc Welderを使うという前提ならば最大解像度を上げることによるデメリットはほぼ発生しないと思われる。
ただし、**ぶっちゃけデフォルトでも結果がそんなに変わらない**ためメリットの発生もほぼ見られず
最大解像度を上げるのは気休め程度と考えた方が良さそうである。
【Sourcetree】GitHubリポジトリと連携するための方法

# 初めに

Sourcetree で開発したソースコードを GitHub のリポジトリで管理するための設定方法を記載します。

# Sourcetree のバージョン

Version 3.4.10.0

# 手順

**GitHubの手順**

１. GitHub でリポジトリを作成する。
２. SSH の URL をコピーする。例）`git@github.com:user-name/repository-name.git`

**Sourcetreeの手順**

３. 右上の「設定」を押下する。
４. 「リモート」タブを選択し、「追加」を押下する。
５. リモート名は「デフォルトリモート」にチェックを入れる。
６. 手順 2 でコピーした URL を「URL/パス」欄に貼り付ける。
７. 「ユーザー名」欄を確認し、ユーザー名に問題なければ「OK」ボタンを押下する。問題があれば修正し、「OK」を押下する。
８. 右上の「リモート」を押下し、手順 1 で作成したリポジトリが開くことを確認する。
SQL – テーブルのカラムを後から AUTO_INCREMENT に変更するクエリ

# 例

AUTO_INCREMENT と PRIMARY の両方を設定する必要があるようだ

`ALTER TABLE [table_name] MODIFY [column_name] INT NOT NULL PRIMARY KEY AUTO_INCREMENT;  `

# 検証例

```sql
CREATE TABLE articles (
  id INT
);

INSERT INTO articles (id) VALUES (100);

ALTER TABLE articles MODIFY id INT NOT NULL PRIMARY KEY AUTO_INCREMENT;  

INSERT INTO articles () VALUES ();
INSERT INTO articles () VALUES ();
INSERT INTO articles () VALUES ();

```

ID は今までの最大の値から振られるようだ

<img width="1218" alt="image" src="https://user-images.githubusercontent.com/13635059/210324774-1299a6cf-2608-4aa1-88e2-c33c25fc3549.png">

https://www.db-fiddle.com/f/v18VJbVdperct26qQDmnG8/1


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
symfonyで$request->isXmlHttpRequest()をpostmanで叩く


isXmlHttpRequestを通す場合は
下記を追加すると良い。

ヘッダーに追加
X-Requested-With
XMLHttpRequest


```hogeController.php
    /**
    * 
    * sessionに保存
    * @Method("GET", "POST")
    * @Route("/setting_session", name="setting_session") #URLを指定
    */
    public function SaveSession(Request $request) { 
      if($request->isXmlHttpRequest()){


...
```


https://www.devopsschool.com/blog/use-postman-in-laravel-project/
AMD CPU Ryzen で コマンドラインからAndroid Emulator を実行させる

AMDのRyzenでAndroid StudioのEmulatorを実行させるためにいろいろ試したメモです。

# 環境
CPU：AMD Ryzen 7 4800U with Radeon Graphics 1.80 GHz
OS：Microsoft Windows 11 Home
メモリ：16.0GB

# 結論
コマンドラインからオプションを指定して起動させる。

###### 前提
Emulatorの設定
System Image: x86_64


###### 実行コマンド
このパスで
`C:\Users\XXX\AppData\Local\Android\Sdk\emulator>`

このコマンドを実行する。
`.\emulator -avd (仮想デバイス名) -gpu swiftshader_indirect`

仮想デバイス名は同じパスで以下のコマンドで一覧表示される。[(公式ドキュメント)](https://developer.android.com/studio/run/emulator-commandline?hl=ja)
`.\emulator -list-avds`

`Sdk\tools`のパスにあるemulator.exeではなく、`Sdk\emulator`のパスにあるemulator.exeじゃないと動かないので注意してください。

# 試したこと
1\. 再インストール
Android Studioインストール時に何かのエラーが出ていたが放置していた。
エミュレーターの実行がうまくいかなかった段階になって修正しようとしたが、どんなエラーか忘れてしまっていたので再インストールした。
初回のインストール時のエラーは出なかったが、エミュレーターは起動しなかった。

2\. vulkanファイルの導入
https://www.kunimiyasoft.com/android-studio-4-2-2-emulator/
こちら方の記述と同じく、amdvlk64.dll, vulkan-1.dllをネットから探してきてSystem32フォルダに入れた。
エラーメッセージを見てもこの二つのファイルを探しているようだったので、エミュレーターの実行を期待したが効果なし。

3\. arm64イメージの使用
amd製CPUではx86_64イメージだと動かないと聞いたのでarm64イメージを使用したが効果なし。
armeabiイメージを使用すると動いたとの記事も見かけたので試すがこちらも効果はなかった。

4\. BIOSの確認、Windowsのハイパーバイザの有効化
https://zenn.dev/deranemy/articles/8156e76f87e5fb
これを試したが効果なし。

5\. 仮想デバイスの割り振りメモリの増量
仮想デバイスのメモリ容量が足りていない場合、エミュレーターが実行できないという記事を見つけたのでメモリの割り当てを増やしたが効果なし。

6\. オプションをつけてコマンドを実行
いろいろ試してうまくいかなかったので、改めて表示されるエラーメッセージをよく読みました。
すると下のほうにちょっと見切れた感じで「swiftshader_indirect　のオプションをつけてコマンドラインから起動してみてほしい」といった内容のメッセージがあり、これを試すとエミュレーターが実行できました。
GPU関係の設定らしいですがよくわかりませんわ。


# 終わり
調べるといろいろ方法が出てきて、それぞれ解決した人と解決しなかった人がいたので決まった解決方法はないのかなと思います。
間違いあれば指摘いただけると助かります。
2022振り返り - プログラミング初心者が独学で1年弱やってみて

tl,dr;
- 
- 2022年、今年こそはプログラミングを勉強しようと思い初心者用の教材を勉強した。途中怠ける時もあったが1年間継続することができた。
- 実施したことのほとんどがオンラインの無料教材のため、書籍購入費用を加えても総額2−3万円程度で済ますことができた。
- 最も時間がかかったのが、Couseraでのnand2Tetris (Part 1-2 で 100hrsくらい)だったが、コンピュータの基本的な原理を大まかに把握できるため、自分のようにコンピュータサイエンス未修の人にはぜひお勧めしたい

Summary
- 
これまでも、たまにプログラミングを勉強しようと思いProgateやその他の教材をやってみては、(無料範囲は終わらせるものの)続かず、やめるということを繰り返していた。2022年こそはと思い、これまでとは異なり、高級言語の学習ではなくコンピュータサイエンスから勉強してみたところ、これまでわかっていなかった基礎概念をざっくりと把握することができ、勉強を継続することができている。

what is this?
- 
プログラミング初心者が1年近く勉強をしてみた振り返り
学習時間は平日の仕事終わり及び土日が中心。1日XX時間やる！、とかいうと続かないので、とりあえず続けることを目標に実施

やったこと (時間は肌感)
- 
- CS50 - 50-70hrs (Harvard Universityの1年生向けコンピュータサイエンス講座。無料受講可能)
- nand2Tetris - 100-150hrs (こちらも大学の授業？をもとにしたオンライン講座。NANDゲートと呼ばれる論理ゲートから始まり、実際にエミュレータ上で動く基礎のコンピュータを作成するまでを行う。NANDゲートから始まり、テトリスゲームを作れるCPUを制作するため、Nand2Tetrisと呼ばれる)
- LeetCode - AtCoderと同じく、Algorithm問題などを解けるサイト
- 読書 - コンピュータサイエンスやアルゴリズムなど関連本を４冊ほど読了。

学んでよかったこと
- 
- コンピュータの基本原理がざっくりでもわかったことにより、未知のことにぶつかった時の嫌悪感が減った(これまでと比べてうっすらであるが全体感がわかった)
- これまで謎に包まれていたワードである、バイナリ、ビット、アッセンブラー、コンパイラだったり、メモリとCPUの関係性などを知ったことで、これまで漠然と言語化もできていなかった疑問が一部解消した
- 途中サボった期間もあったものの、1年近く学習を続けることができ、自信になった

今後
- 
コンピュータサイエンスがひと段落したところで、現在は"アルゴリズムとデータ"と"簡単な自作アプリ"の2つを勉強中。進める中でgitだったりCommandLineなど新たな疑問が出てきたため、合わせて学習中
- アルゴリズム問題
- 自作アプリの作成 (Python, Swift)
- github, CommandLineなどわからない点を都度勉強
Java：ラッパークラス

## ラッパークラスとは
各基本データ型に対応したクラスの事。
基本データ型であるint型やdouble型の値をオブジェクトとして扱えるようになり、基本データ型にはない色々なメソッドを利用することが出来るようになる。

Javaでは基本データ型が用意されており、数値や文字を格納したり演算子と組み合わせる場合であれば基本データ型を使えば十分だが基本データ型にはクラスのようにメソッドは用意されていないので、基本データ型に対して操作を行ったりすることは出来ない。
そこで基本データ型の値を持つことができ、色々なメソッドを用意したクラスが用意されていルのが**ラッパークラス**と呼ばれるもの。

![スクリーンショット 2023-01-03 16.29.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/b85c4bec-fd0d-529d-8962-5acb6a5447e8.png)
ラッパークラスの名前は基本データ型の１文字目を大文字にするがint型とchar型は名前が変わる。
```:使い方
// 基本データ型
int i = 10;
//  ラッパークラス
Integer j = new Integer(10);
```
基本データ型から対応するラッパークラスのオブジェクトを作成し、そのオブジェクトに対して用意されたメソッドを利用することで例えば数値から文字列への変換といった処理が可能になる。

基本データ型の値に対して様々な操作を行うには、基本データ型の値を持つラッパークラスのオブジェクトを作成する。そして作成したオブジェクトに対してラッパークラスで用意された様々なメソッドを用いていく。

## ラッパークラスの一例
**Integerクラスのメソッドや定数**
```:MIN_VAlUE,MAX_VALUE
static final int MIN_VAlUE
static final int MAX_VALUE
```
int型で扱える最小値と最大値を設定する

```:parseIntメソッド
static int parseInt(String s)
// 例
int i = Integer.parseInt("10");
```
引数として文字列を受け取り、int型に変換する

```:toStringメソッド
static String toString(int i)
// 例
String s = Inetger.toString(10)
```
引数としてint型を受け取り、文字列型に変換する。


![スクリーンショット 2023-01-03 16.54.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/af3704d2-1918-5c1f-158f-e386dede7185.png)


## 参考記事
https://www.youtube.com/watch?v=ecFQxn7-MCY&t=201s

https://www.javadrive.jp/start/var/index13.html#section1
[python] Djangoでurlを取得し、QRCodeを作成する

# はじめに
QRCodeによる現場管理を構想しているので、DjangoでQRCodeの生成方法をまとめておく。
こういうのは知ってて利用するよりも、その都度、調べるしかないですね。
# 環境
Django 3.1.13
python 3.9
qrcode 7.3.1
```
pip install qrcode
```
# Code
## QRCode作成
```python:view.py
import qrcode
import qrcode.image.svg
from io import BytesIO


def show_work(request, work_id):
    work = Work.objects.get(pk=work_id)

    url = request.build_absolute_uri()
    # 表示されるurlを取得

    factory = qrcode.image.svg.SvgImage
    img = qrcode.make(url, image_factory=factory, box_size=10)
    # box_sizeでイメージの大きさを調整

    stream = BytesIO()
    img.save(stream)
    svg = stream.getvalue().decode()
    return render(request, 'show_work.html', {"work": work, "svg" : svg})
```

## QRCodeを表示
```html:show_work.html
    {{svg|safe}}
```

# 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/c740776b-6baf-15c6-5abb-597c14dcc160.png)
localhostなのでなにも表示はされないですが、これで簡単にurlのQRCodeを作れます。

# 参考

https://itc.tokyo/django/get-url-user-on-template/

https://medium.com/geekculture/how-to-generate-a-qr-code-in-django-e32179d7fdf2
[Python]キャスト可能かを調べる

# これなに？
受け取った値がそもそもキャスト可能かどうか調べたいこと、ありますね？（~~開発では忌避されるべきですが~~）
競プロとかでたまに使うので、実装しました。

# 方法
キャスト時に不可能と判断された場合`ValueError`が吐かれるので、これをキャッチする要領で実装します。

```py
def isInt(val):
    try:
        int(val)
    except ValueError:
        return False
    else:
        return True
```
ROS2で使える2DのLaserScanで動くSLAM, Localization関係のパッケージまとめ

現在ROS2で使えてOSSとして公開されているSLAM、自己位置推定関係のパッケージを調べてまとめてみた
2D LiDARのsensor_msgs/LaserScanをSubscribeして動くものが調査対象

備考：GitHubでROS2 で使えるbranchがあるものが対象、実際に動くかは不明

# 2D LiDAR SLAM

### Google Cartographer

Github:  

https://github.com/ros2/cartographer



Subscribe Topics : sensor_msgs/LaserScan, sensor_msgs/Imu, nav_msgs/Odometry, sensor_msgs/NavSatFix

ソフトウェアライセンス：Apache-2.0 license
  
ROS1であったもののROS2実装　
IMU,Odomは必須ではなくLaserScanのみで動作する
詳しい説明は他に解説記事がいっぱいあるのでここでは省略

### slam_toolbox

Github: 

 https://github.com/SteveMacenski/slam_toolbox


Subscribe Topics : sensor_msgs/LaserScan, TF(odom -> base_link)

ソフトウェアライセンス： LGPL-2.1 license


ROS2標準のSLAM（ROS1のGmappingみたいなもの）
Odomは必須なので、OdomがないロボットはCartographerを使ったほうがよい

導入方法などは以前書いたこちらの記事を参照

https://qiita.com/porizou1/items/152ad3829e84a9ba0355


### littleslam_ros2

Github: https://github.com/rsasaki0109/littleslam_ros2
Subscribe Topics : sensor_msgs/LaserScan, TF(odom -> base_link)
ソフトウェアライセンス：  MPL-2.0 license


こちらはSLAM入門という本のアルゴリズムのROS2実装
Odomが必須

https://www.ohmsha.co.jp/book/9784274221668/


### slam_gmapping

Github: 

https://github.com/Project-MANAS/slam_gmapping


Subscribe Topics : sensor_msgs/LaserScan, TF(odom -> base_link)
ソフトウェアライセンス：  CreativeCommons-by-nc-sa-2.0

ROS1のGmappingのROS2ラッパーらしい　eloquent-develがあるがFoxyやHumbleで動くか不明
Odomが必須


### iris_lama_ros

Github: 

https://github.com/iris-ua/iris_lama_ros/tree/eloquent-devel


Subscribe Topics : sensor_msgs/LaserScan, geometry_msgs/PoseWithCovarianceStamped, TF(odom -> base_link)
ソフトウェアライセンス：   BSD-3-Clause license

以下のパッケージのROS2ラッパー
https://github.com/iris-ua/iris_lama_ros

launchでParticle Filter SLAM、オフラインSLAM、Graph SLAMを選択できる
eloquent-develがあるがFoxyやHumbleで動くか不明


# 自己位置推定関係


### amcl 

Github: 

https://github.com/ros-planning/navigation2/tree/main/nav2_amcl


Subscribe Topics : sensor_msgs/LaserScan, nav_msgs/OccupancyGrid, TF(odom -> base_link)
Publish Topics : TF(map -> odom)
ソフトウェアライセンス：   LGPL-2.1-or-later

同じみの自己位置推定パッケージ、Navigation2の機能として提供される。
基本的にNav2と一緒に使う。



### mrpt_navigation/mrpt_localization/

mrpt_navigationというROS1のNavigationStackのような自律移動パッケージのROS2実装の中にある自己位置推定の機能
mrpt_navigationをインストールしてこのノードだけ使えばamclと同じように使える


https://github.com/mrpt-ros-pkg/mrpt_navigation/tree/ros2/mrpt_localization


### emcl2_ros2


上田先生のemclをROS2 移行したもの


https://github.com/CIT-Autonomous-Robot-Lab/emcl2_ros2


### rf2o_laser_odometry 

Github:

 https://github.com/Adlink-ROS/rf2o_laser_odometry


Subscribe Topics : sensor_msgs/LaserScan, nav_msgs/OccupancyGrid, TF(odom -> base_link)
Publish Topics : TF(odom -> base_link)
ソフトウェアライセンス：    GPL-3.0 license

ROS1であったLaserオドメトリパッケージ　rf2o_laser_odometryのROS2版
ホイールオドメトリが取得できないロボットはこれを使うことで、LiDARのLaserScanのみでオドメトリできる。
ライセンスがGPLなので商業利用しづらいのが難点。


-----------------



# 総括


3D LiDAR SLAMやVisual SLAMのパッケージもこのページにまとめようと思ったが、いろいろありすぎるので2D SLAMのみにした。

SLAMにおいてはホイールオドメトリが使えるロボットはslam_toolbox、使えないロボットはCartographerと使い分けるのがいいだろう。















-----------------



# 参考


https://qiita.com/nnn112358/items/814c0fb0d2075eb71da0


https://qiita.com/rsasaki0109/items/493c1059ffe3178166bc
開発工程を料理に例えてみた


## 概要
開発工程って料理に似ているんじゃないかと思い投稿してみることにしました。
今回は、開発工程を以下の料理工程に当てはめていこうと思います。
1. 献立決め（要件）
2. レシピ決め（設計）
3. 調理（開発）
4. 味見（テスト）
5. 提供（納品）

### 1. 献立決め（要件）
何はともあれ顧客が欲しいものは何かが決まっていないと何も作れません。
料理に例えると、何を食べたいのかを決めるフェーズ（献立）に当たります。

自分向けに作ることもあれば食べさせたい相手がいることもあるでしょう。
相手を満足させたいなら、相手が何を食べたいか聞くのが確実です。
好きな食べ物は何か、嫌いな食べ物は何か、色々聞いて献立をどうするか決めましょう。

### 2. レシピ決め（設計）
要件が決まったらどう作るかを決めていきます。
料理に例えると、どう作るか（レシピ）に当たります。

すでに一回作ったことがあってレシピを調べる必要がない場合もあります。
もし家庭の味を引き継ぎたい、次も同じ味を再現したいと思っているのであれば、レシピを残しておくのをおすすめします。
誰が作っても同じように作れるレシピがあったらフランチャイズ化も夢ではないかも。

### 2.5. （番外編）買い物（調達）
設計に並行して開発環境や人員を整備します。
料理に例えると、買い物かシェフを雇う人がいれば雇用もここでやりましょう。

レシピに必要なだけ買い物をすれば基本的には良いかと思います。
ですが、もしかしたらどこかで失敗してしまったりうまくいかないことが起きがちです。
リスクに備えて多少のバッファは用意しておきましょう。

### 3. 調理（開発）
設計と調達が済んだら実際に製造していきます。
料理に例えると、実際に作る作業（調理）に当たります。

原則、レシピに従って作りましょう。
慣れてくるとこっそり隠し味を入れたくなるかもしれないですが、隠し味までしっかりレシピに書くのを忘れないでください。

### 4. 味見（テスト）
製造が進んできたらテストが始まります。
料理に例えると、味見に当たります。

思った味ではないことが多々あるでしょう。
レシピが間違っているのか、レシピに書いてないことをしてしまったのか確認しましょう。
間違ってても味を整えればまだ間に合います。

### 5. 提供（納品）
テストも終わって完成したらいよいよ納品です。
料理に例えると、食卓なり顧客への提供に当たります。

いよいよ誰かの口に入ります。
満足してリピートしてもらえるか、髪の毛が入っていて作り直しを要求されるか、
何が起きても対応できるように準備しておきましょう。
会計が終わったら一段落です。

## 終わりに
正月暇すぎて、ポエム書きました。
実際は、方式設計やテストも単体、結合、総合と色々ありますが、概要はこんな感じなのでは。
【分析】機械学習でFXを攻略！ができない原因を考える。

誰もが一度は考える「株やFXをAIで攻略できないか」問題。
そして実践している人は数多くいるのだが、成功者はあまり多くないようです。
そこでなぜ攻略が難しいのか、自分でDQNやランダムフォレストを実行しながら考えてみました。

![432433.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088680/cbd54c27-001d-b3e6-0b08-3012b7be0fb3.png)


# そもそも特徴量が間違っている。
大企業のサイエンティストもFXを攻略しようとしている記事はよく見かけますが、
しかしそもそもが間違っているのでうまくいかないだろうな、とは思っています。

だいたいの記事では特徴量として、high,low,open,closeの値を持ってきています。
しかしこれだと例えばドル円の価格が120円の時と140円の時では特徴量に乖離があるため
使えない数値となるでしょう。
1ドル120円の時に学習させた学習データでは、1ドル140円の相場で稼ぐことはできないはずです。もっと言うと、120円の時と121円という1円差程度の時を考えたとしても、データがおかしいのでうまくいかないだろうと思います。

しかしこれは特徴量をpips単位にすればＯＫです。
high-low= で「1つの足で何pips動いたかがわかる」ので、それを足し合わせていけば120円台だろうが
140円台だろうが同じデータになります。

この要領でhigh low open closeすべてをpips単位に変更し（minmax Scalerを使う）、新たなチャートを完成させればいい。
この新しいチャートと値を使って移動平均やボリンジャーバンドなどを計算しなおすのも有効だろう。
そうして計算された特徴量をランダムフォレストやＤＱＮあたりで処理すれば精度は最初より上がるはず。

精度が上がらない人はぜひ試してください。
私も実験を続けてみます。

## 価格を予測しようとしてもおそらくムダ。ゲームとして考えたほうが効率的
これもよくある記事ですが「FXの価格をLSTMで予測してみました。」というようなものがありますね。たぶん予測するだけムダだと思います。プライスを後追いするだけの意味のない線が出来上がって終わりでしょう。

そんなできないことをやるよりも、上がるか下がるかそのままかの3択ゲームとして考えたほうが効率がいいと思います。そして「1時間後に利益が取れているかどうか」をデータをもとに「先に答えを作って」おきます。それをDQNなどで学習させればいいですね。
要はゲームを作ってそれに勝てる方法を探ればよいのです。（実際そうそううまくはいかないと思うが、精度は上がってくるはず）

## 標準偏差から外れている個所がトレンド相場、のはず。
トレンド相場ってなに？と言われたら私は「標準偏差から外れている個所」じゃない？と答えます。普段は相場はランダムウォーク的な動きをしています。ですがニュースなどが出るとそこから外れて大きく動き出します。ボリンジャーバンドウォークする状態ですね。
仮にその付近をトレンド相場と考えると、大きく稼げるエントリーポイントは「レンジ相場の中にある」。つまり標準偏差内に収まる値のどこかに存在する、と考えられます。たぶんね。

これを踏まえると、変なところでエントリーするのを避けられるんじゃないかな？と考えます。特にブレイクアウトなどすでに標準偏差を超えてからエントリーするような戦略だとトータルで一生勝てない気がします。


## それでも完全攻略は不可能だと思う。
ここまでやってもうまくいく可能性は低いと思っている。しかしこの記事がみなさんのヒントになればうれしいです。

## 実際に実験した結果は後日公開します。
まだ実験データが足りないので後日公開したいと思います。






#### 私の分析力が気に入ったらぜひAI研究に誘ってください。自動運転とかずっとそればっかり研究できる分野がいいですね。楽しそうな仕事に就きたいです(^^)/
割り算の結果を任意の桁まで表示する

# やりたいこと
`1÷3`の答えは`0.33333...`だが、これを任意の桁まで表示したい。

# やってみる
前提として、普通に`print()`で出すと誤差が起きる。

```py
>>> print(1/3)
0.3333333333333333
```

出力は16桁で止まっている。
これは、**floatによる演算の正確性が保証されるのがだいたい16行目まで**[^1]であることに由来しており、これ以降は正確ではないということになる。

さて。

方針としては「一桁ずつ計算する」という方式をとる。
筆算を想像すればわかりやすいかも。
1. 割る
1. 答えを記録する
1. あまりを10倍する
1. 1へ

この繰り返しで計算していく。

```py
n = 1 # 割られる数
m = 3 # 割る数
k = 10 # 小数部の桁
ans = [str(int(n//m)), ""] # 結果。[0]が整数部、[1]が小数部を保存する

stuck = n - m*int(n//m) # あまり
x = 0 # 割り算の結果（一桁のみ）

while len(ans[1]) < k:
    stuck *= 10
    x = stuck // m
    ans[1] += str(int(x))
    stuck -= m * int(x)
    
# 小数部が存在しない場合は0を差し込んでおく
if len(ans[1])==0:
    ans[1] += "0" * k
```

ところどころ`x`を`int`にキャストしているが、これは**割り算の結果が必ずfloatで返される**ため。


[^1]: 正確には15.95行までだったような気がする（53 * log10 2 =15.95）
【Tips】Typescript+Mustache.jsでリカーシブなテンプレートを作成する方法

# はじめに
Mustache.jsは便利だが、リカーシブなテンプレートを作成したい場合にはクセがあり分かりにくい。
やり方をググってもなかなか出てこないので、やり方をメモっておく。

# Mustacheテンプレート
コードは以下のように作っておく。
```> attribute```の部分が、Partialsという部品呼び出しの記法だ。これ自体は、メインのテンプレートファイルが大きくなりすぎる場合に部品を切り出すための記法であるが、これを応用することでリカーシブに呼ぶことができる。

```mustache:main.mustache
{{#attributes}}
{{> attribute}}
{{/attributes}}
```

```mustache:attribute.mustache
{{attributeName}}
{{#attributeValue}}
  {{> attribute}}
{{/attributeValue}}
```

# Typescriptのサンプル① 短項目の場合
上記の機能を呼び出すタイプスクリプトは以下のように書ける。

```typescript:index.ts
import * as Mustache from 'mustache';
import { readFileSync } from 'fs';

const path = require('path');

type templateDataAttribute = {
  attributeName: string;
  attributeValue: null | (string | templateDataAttribute)[];
}

type templateData = {
  attributes: templateDataAttribute[];
}

const main = () => {
  const template: string = readFileSync(path.join(__dirname, 'mustache/main.mustache'), 'utf-8');
  const partial: string = readFileSync(path.join(__dirname, 'mustache/attribute.mustache'), 'utf-8');

  {
    const templateData: templateData = {
      attributes: [{
        attributeName: 'hoge',
        attributeValue: null,
      }],
    };

    console.log('--- case 1 ---');
    console.log(Mustache.render(template, templateData, { attribute: partial }));
  }
};

main();
```

上記を実行すると、以下のような出力が得られる。

```
--- case 1 ---
hoge
```

nullで終端することで、```attribute.mustache```側の```{{#attributeValue}}```が呼ばれなくなるという仕組みだ。

# Typescriptのサンプル① 1階層ネストでのリカーシブコール
上記の```index.ts```のmain()関数に以下のコードを書き加える。

```typescript:index.ts
// 前略
  {
    const templateData: templateData = {
      attributes: [{
        attributeName: 'hoge',
        attributeValue: [{
          attributeName: 'hige',
          attributeValue: null,
        }],
      }],
    };

    console.log('--- case 2 ---');
    console.log(Mustache.render(template, templateData, { attribute: partial }));
  }
// 以下略
```

上記を実行すると、以下のような出力が得られる。

```
--- case 2 ---
hoge
  hige
```

ここまでくれば、あとはお手の物だろう。

# Typescriptのサンプル③ 2階層ネストでのリカーシブコール
上記の```index.ts```のmain()関数に以下のコードを書き加える。

```typescript:index.ts
// 前略
  {
    const templateData: templateData = {
      attributes: [{
        attributeName: 'hoge',
        attributeValue: [{
          attributeName: 'hige',
          attributeValue: [{
            attributeName: 'hage',
            attributeValue: null,
          }],
        }],
      }],
    };

    console.log('--- case 3 ---');
    console.log(Mustache.render(template, templateData, { attribute: partial }));
  }
// 以下略
```

上記を実行すると、以下のような出力が得られる。

```
--- case 3 ---
hoge
  hige
    hage
```

バッチリ2段階のネストもいける！
ループや条件分岐も組み合わせることで、複雑な構造もMustacheのみで書けそうだ！
【オブジェクト指向設計実践ガイド】SRP編

# はじめに

あけましておめでとうございます
今回は昨年末に参加させて頂いたインターンで会社に購入頂いた[オブジェクト指向設計実践ガイド](https://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E8%A8%AD%E8%A8%88%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%EF%BD%9ERuby%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8B-%E9%80%B2%E5%8C%96%E3%81%97%E3%81%A4%E3%81%A5%E3%81%91%E3%82%8B%E6%9F%94%E8%BB%9F%E3%81%AA%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%82%B2%E3%81%A6%E6%96%B9-Sandi-Metz-ebook/dp/B01L8SEVYI/ref=sr_1_1?crid=3RUPK4BZVDYRS&keywords=%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E8%A8%AD%E8%A8%88%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89&qid=1672663982&sprefix=%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%2Caps%2C285&sr=8-1)を読んだ自分なりの解釈を書いていこうと思います。
SRP編とかタイトルに書いてる今の自分は、正月のやる気に押され連載にする気満々なのでエタらないうちにさっさと書き切りたい。
今回はSRP編です。

# SRPとは何ぞや

オブジェクト指向においてなくてはならない原則。単一責任の原則。Single Responsibility Principle.
クラスは自身がしなくてはならない最小のことのみを行い、それ以外のことはするなという原則のこと。

ではこのSRPは何のために必要なのか。

それは ***「変更が簡単なようにコードを書く」*** ため。

# 実践

自分の練習も兼ねて本で取り上げられていた例とは違うオリジナルのSRPの実装をやってみる。
試しに人間というオブジェクトを考えよう。ここではクラスとして実装する。

オブジェクトには最低限データと振る舞いの2つがないといけない。

```ruby
class Human
    # これはデータ
    attr_reader :weight, :height
    def initalizer(:weight, :height)
        @weight = weight
        @height = height
    end

    # 適正体重を求めるメソッド(= 適正体重を返すという振る舞い)
    def desirable_weight
        (height ^ 2) * 22
    end

    # BMIを求めるメソッド
    def bmi
        weight + (height ^ 2)
    end
end

```

このHumanクラスはデータと振る舞いを両方備えている。
簡単なHumanクラスでBMIを求めるメソッドを実装してみたので、これを発展させてHumanの肥満度を評価してみたい。

```ruby
class Human
    # ...既に定義したHumanクラス
    
    def obesity_degree
        case
            when bmi < 18.5 then "やせ"
            when 18.5 <= bmi && bmi < 25 then "普通"
            when 25 <= bmi then "肥満"
        end
    end
end
```

さて、この拡張は正しいのか？ SRPを破ってはいないか？
BMIは明らかにHumanの属性。そしてHumanに「Humanさん、あなたの肥満度を教えてください」と尋ねるのも妥当な気がする。
しかしBMIが18.5未満ならやせであるなんてことはHumanは知らなくていい。
つまり `obesity_degree` がHumanにいるのは問題ないけれど、その実装はどこかへ分離したい。

しかしメソッドの実装をHumanクラスではないどこかへ移した方が良いことが分かっても「今すぐ」実際にそうすべきかは別の問題なのだ。なぜなら開発チームが今持っている知識で適切な移動先が見つかるとは限らないから。
この程度の規模のコードであれば、開発チームはそのための知識をまだ十分に持っているとは言えないので実装を切り出す決断は(可能なら)十分な知識を得る将来へ先延ばしにすべき。

よって今回はHumanに関係ないロジックが入り込んでいるので、クラスがSRPを守っているとは言えない。ただそれはHumanの他の部分からはcase式の切り出しやすい形で明確に分離されているのでこのままにしておくという結論に(自分は)なった。

# データではなく振る舞いに依存せよ

- インスタンス変数はメソッドで包め
- 配列にインデックスアクセスしているのは、SRPを守れていない証拠。どのインデックスにどんなデータが入っているかという知識は別の1つメソッドに詰め込むこと。

# まとめ

- オブジェクトはデータと振る舞いの2つを持つ
- 実装がSRPを守れているかオブジェクトに問いただすこと
    - これには「オブジェクトさん、あなたのxxxを教えてください」と聞いてみると良い。
    - クラス単位であってもメソッド単位であっても。
- 「新しいオブジェクトを作る」、「メソッドを切り出す」などの設計に関する決断は、可能なら先送りせよ
    - 後で切り出しやすいよう異なる責任同士は(もし同じオブジェクトに書くなら)隔離して書くこと
- データではなく振る舞いに依存せよ。データに直接アクセスするのではなくラッパーを定義すること。
S3に保存されているCSVファイルをjsonレスポンスで受け取る

## 概要
この記事では、S3上に保存されたCSVファイルをLambdaで取り出し、jsonで返す方法を紹介します。
HTTP通信の窓口にはAPIGatewayを使用しています。
APIGatewayのイベントをトリガーにLambdaからS3へアクセスします。

この記事では、S3のポリシー設定、Lambdaのロール設定、LambdaとAPIGatewayの設定は割愛し、Lambdaの実装にフォーカスします。

## 前提条件
CSVファイルは以下のものを使用しました。
全体のソースコードは下に載せます。
またAWSサービスの認証はそれぞれの環境でお願いします。

```csvs:hoge.csv
"name","age"
"fuga","22"
"hoge","20"

```

## `Lambda`の実装
実装には`Go`を用います。
大まかに以下の流れです。
1. s3にアクセスするためのクライアントを作成
2. s3からオブジェクトを取得する
3. オブジェクトを構造体にマーシャルする
4. 全ての処理が成功したらレスポンスを返す

以下で詳しく説明していきます。

### `Lambda`から`S3`にアクセスするための設定
S3にアクセスするためのクライアントを作成し、バケット名とファイル名で検索しています。

```go:main.go
func hander(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	session := session.New()
	s3Client := s3.New(session)

	bucketName := "qiitahoge"
	objectKey := "hoge.csv"

	object, err := s3Client.GetObject(&s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		return events.APIGatewayProxyResponse{
			Body:       err.Error(),
			StatusCode: 500,
		}, nil
	}
    ...
}
```

### S3オブジェクトを読み込む
標準パッケージである`encoding/csv`を使ってCSVファイルを読み込みます。

```go:main.go
func hander(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    ...
    defer object.Body.Close()
	reader := csv.NewReader(object.Body)
	rows, err := reader.ReadAll()
	if err != nil {
		return events.APIGatewayProxyResponse{
			Body:       err.Error(),
			StatusCode: 500,
		}, nil
	}
    ...
}
```

### 読み込んだ結果を構造体に割り当てる
`Hoge`という構造体を定義し、CSVの読み込み結果を割り当てます。

```go:main.go
type Hoge struct {
	Name string `json: "name"`
	Age  string `json: "age"`
}

func hander(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    ...
	var response []Hoge
	for i, v := range rows {
		if i == 0 {
			continue
		}

		name := v[0]
		age := v[1]

		hoge := Hoge{
			Name: name,
			Age:  age,
		}

		response = append(response, hoge)
	}
    ...
}
```
 
### レスポンス実装
今までの処理で問題がなければ、ステータスコード200と共にjsonオブジェクトを返してあげます。

```go:main.go
func hander(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    ...
	bytes, err := json.Marshal(response)
	if err != nil {
		return events.APIGatewayProxyResponse{
			Body:       err.Error(),
			StatusCode: 500,
		}, nil
	}

	return events.APIGatewayProxyResponse{
		Body:       string(bytes),
		StatusCode: 200,
	}, nil
}

func main() {
	lambda.Start(hander)
}
```

### 最後に
上の手順でlambdaの実装は完了です。
この後にgoファイルを圧縮して、lambdaにアップロードします。
最後に、`Lambda`と`APIGateway`を繋いでAPIの完成です。
Postmanからリクエストを送ったところ、CSVの内容をjsonで確認することができました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551042/2086b494-da5d-8867-b4a8-a657dc866f86.png" width="400" />

全ソースコードは[こちら](https://github.com/h-taro/lambda-go-demo)です。

### 参考
https://qiita.com/saki-engineering/items/e5cf56301d94ceea3ce0
AWS RDS上のDBを ローカル環境のDbeaver上で表示させる方法

## 概要

AWS(EC2 ,RDS CLOUD9) + Ruby on Railsでプロジェクト作成した。
上記プロジェクトで使用しているDB(Mysql)を
Windows(ローカル環境)のDbeaver上でRails プロジェクトのDBを表示させる例を示す

## 前提条件

### 具体的に必要な内容 (省略)

・ローカル環境を用意(Windows) 
・Dbeaver をWindows内にインストール
・AWS準備
・AWS EC2(Amazon Linux2)を開発環境・本番環境それぞれに作成
・ElasticIPを作成し 各EC2インスタンスに割り当てておく
・開発環境 (統合開発環境として　AWS CLOUD9を使用)内でRailsプロジェクト作成
・DB(RDS含む)を準備
・「ローカル環境→開発環境」「ローカル環境→本番環境」「開発環境→本番環境」
　それぞれへssh接続で移動できるための鍵・設定準備

## 具体的内容

### 1.開発環境情報

EC2-インスタンス使用 (Amazon Linux)
  -インスタンスid: i-〇〇〇〇〇...
  -EC2ユーザー名: ec2-user(デフォルトのまま :変更可)
  -パブリック IPv4 アドレス:〇〇.〇〇〇.〇〇.〇〇
  -Elastic IP:　上記に同じ

統合開発環境 AWS cloud9を使用
DB: sqlite3 (Railsでの標準DB)

### 2.本番環境情報

EC2-インスタンス使用 (Amazon Linux)
  -インスタンスid: i-△△△△...
  -EC2ユーザー名: ec2-user(デフォルトのまま :変更可)
  -パブリック IPv4 アドレス:△△.△△△.△△.△△
  -Elastic IP:　上記に同じ

DB: mysql 使用 (AWS RDS使用)
  -mysqlユーザー: root
  -mysqlパスワード: □□□□...
  -使用データベース(スキーマ)名: ××××...

AWS RDS情報
  -DB識別子: rds-mysql-server
  -エンドポイント: rds-mysql-server.△△△△△.ap-northeast-1.rds.amazonaws.com
  -ポート: 3306(mysqlで使うポート) 　
  
![RDS情報.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294345/9bbd9d8a-88a6-01ae-28db-9d1af35b93a0.png)

### 3. ssh・鍵関連内容

①ssh接続させるための鍵ファイル(.pem)の作成 (作成時に〇〇.pem.pub　ファイルも作成)
②接続先の 「～/.ssh/authorized_keys」 ファイルに作成した鍵ファイル(〇〇.pem.pub)
 の内容を貼りつけておく

参考

https://qiita.com/soma_sekimoto/items/35845495bc565c38ae9d

CLoud9開発環境(amazon Linux)内の/.sshディレクトリに
鍵ファイル(practice-aws.pem)を作成済み
これがあることで開発環境→本番環境にssh接続で入ることができる

(開発環境のcloud9(Amazon Linux)内からEC2インスタンスにssh接続するコマンド)
ssh -i ~/.ssh/practice-aws.pem ec2-user@△△.△△△.△△.△△

開発環境内の鍵ファイル(practice-aws.pem)と同等のファイルをWindows ディレクトリ内にも置いておく

![Windows 鍵ファイル置き場.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294345/1ac388bd-1f27-b005-cd3c-fb22ddb99acf.png)

※これをすることでローカル環境→本番環境にssh接続で移動できる

## DB(本番環境: Mysql RDS)を見るために必要な操作

#### 1-1.Dbeaver上で本番環境のDBを見るDbeaverプロジェクト(mysql使用)を作成(省略)

#### 1-2.接続設定→「一般」タブ内設定

Server Host: rds-mysql-server.△△△△△.ap-northeast-1.rds.amazonaws.com
Database: ××××...
ユーザー名: root
パスワード: □□□□...

![dbeaver1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294345/afade235-7523-b97c-01c2-6a3976b1fad9.png)


#### 1-3.接続設定→「SSH」タブ内設定

Host/IP: △△.△△△.△△.△△
User Name: ec2-user
Authentication Method: Private Key
Private Key: Windowsディレクトリ内に置いた鍵ファイルを指定

![dbeaver2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294345/d2a050b4-ff9f-05a3-2b26-443a86cc2563.png)

## DB(開発環境: Sqlite3)を見るために必要な操作
[Python]標準入力

# 単要素
```py
s = input()
n = int(input())
```

# 一行に複数
> a b c

みたいなかんじ
`split()`は**空白区切りで要素を切り分ける**関数。
引数に文字を与えればその文字で切り分けてくれる。

`map()`は**高階関数**といい、「リストのすべての要素に同じ処理をします」というもの。
第一引数に関数を与え、第二引数に処理するリストを与える。

返り値はmapオブジェクト。このままではたまに面倒なので、`list()`を使って使いやすいリストオブジェクトに加工している。

```py
s_list = input().split()
n_list = list(map(int, input().split()))
```

# 複数行に一つ
>n
a
b
c

みたいなかんじ。たいてい要素数として`n`が渡される。
`[]`に囲まれたfor文は**リスト内包表記**というもの。今回はn回分与えた関数を繰り返している。

```py
n = int(input())
s_list = [input() for i in range(n)]
n_list = [int(input()) for i in range(n)]
```

# 複数行に複数（二次元配列）
↑でやったことの組み合わせ。

```py
n = int(input())
s_2d = [input().split() for i in range(n)]
n_2d = [list(map(int, input().split()] for i in range(n)]
```
[python]  Djangoでログイン状況を確認

# はじめに
nodejs などでは`passport`を使ってミドルウェアでログイン確認をしていたが、Djangoではそれさえも簡単にできるということなので、少しながらまとめてみた。
# 環境
Django 3.1.13
python 3.9

# Code
##  ログイン有無の確認
```python:view.py
def show_aaa(request, aaa_id):
    aaa = AAA.objects.get(pk=aaa_id)

    if request.user.is_authenticated:
    # Login: True , not Login: False
        return render(request, 'show_aaa.html', {})
    else:
        return render(request, 'login.html', {})
```
ログイン状態なら`True`
ログイン状態でないなら`False`
## 匿名ユーザーであることを確認
```python
request.user.is_anonymous
# Login: False, not Login : True
```
匿名状態なら（ログイン状態でないはい）`True`
匿名状態でないなら（ログイン状態なら）`False`
Djangoのドキュメントによると、匿名による判断はあまり推奨しないそうです。`is_authenticated`で判断ができてしまうので

# 参考


https://docs.djangoproject.com/en/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_authenticated
Postgresの公開サーバーを作った結果

## これはなに？
　初心者の私がVPSを契約してPostgreSQLのサーバーを立てて公開した結果、いろいろと学ぶことができたのでまとめます。
　本記事ではサーバー構築の手順は割愛し、私個人の想定外だった点や調べるのが不十分だった点を記載します。
### 今回使用した環境
VPS : KAGOYA VPS
OS  : Ubuntu 22.04.1 LTS
PG  : PostgreSQL 15.1

## きっかけ
　自身のデータベースに関するスキルを上げたいと思ったものの、なかなかそのような機会がなくてモヤモヤしていた矢先。
　そうだ、トラフィックを生み出せるコンテンツを作れないなら他人様に生み出してもらえばいい。と思い立ち、善は急げと取り組むことに。

## 結果、どうなったか
### PostgreSQLに対して大量のログイン試行
　ログイン試行のログが大量発生。改めて`pg_hba.conf`の設定が重要であることを再認識。

### ファイヤーウォールの設定が不適切であることが判明
　ufwで行ったデフォルト設定が不適切であったことが原因で、上記のログイン試行を許してしまったことが発覚。

## PostgreSQLへのログイン試行
　ネットの大海原へ公開した12月31日の夜から元日の夕方までの間に6,239回のログイン失敗のログがありました。
　これはすべて`postgres`ロール、すなわち標準設定のスーパーユーザーへのアクセスであります。
　元日の夕方からは`pg_hba.conf`の設定を見直し、リモートから`postgres`ロールへのアクセスを拒否するよう明示しました。
　なお、設定した`pg_hba.conf`は以下の通りです。
```
#IPv4
host    all    all        127.0.0.1/32    trust
host    all    postgres   0.0.0.0/0       reject
#IPv6
host    all    all        ::1/128         trust
host    all    postgres   ::0/0           reject
````
　今後、`postgres`ロールへのログインはローカル環境からに限られます。
　また実際には公開に向けて他の設定も必要です。例えば、ロール名と同じ名前データベースしかアクセスを許可しない場合は以下の通り設定します。
```
host    sameuser    all    0.0.0.0/0      scram-sha-256
```
## ufwで行った不適切なデフォルト設定
　サーバーを公開するならば、ファイヤーウォールは必須だろうと`ufw`を用いて設定を行いました
　しかし、 `ufw default deny`とすべきところを`ufw default allow`としたためにすべての通信が通過することに。
　設定時に？？？となっていたものの、深く検討しないまま設定。
　ufwのログを見て初めてこの誤りに気付くことに。
　本当に必要だったのは以下の手順での設定です。
``` 
ufw default deny
ufw limit postgres
```

## 今後の課題
### 低い？ログレベル
　今回、ufwのデフォルトログレベルでは誰が認証に失敗した、ブロックされたかといった記録を残すことはできましたが、その逆の「誰が成功したか」についての記録を最初から残すことはできませんでした。
　招かれざる客を門前払いするには、どういった条件で侵入されたかを検知する必要があるため明らかに収集不足です。
　そのため、ufwのログレベルは以下の通り設定すべきでした。

### ufwのログレベル設定
```
ufw logging medium
```

　なお、PostgreSQLは以下の設定とすることでクライアント認証の成否をログに残すことができます。
### PostgreSQL (`postgresql.conf`)のログレベル設定
```
logging_collector = true
log_connection = ture
```
　なお、PostgreSQLにおける`log_min_messages`はデフォルトです。

## 最後に公開サーバーについて
　非常に手前味噌で恐縮ですが、公開PostgreSQLサーバーについての詳細は以下をご覧ください。

https://miotsukushi0800.hatenablog.com/entry/2023/01/01/142938


## 参考文献
### PostgreSQL

https://www.postgresql.jp/document/14/html/runtime-config-logging.html

### ufw
https://manpages.ubuntu.com/manpages/jammy/man8/ufw.8.html
【AWS Lambda】Python外部ライブラリのimportにおけるUnable to import module 'lambda_function'エラーの対処方法

# 概要

外部ライブラリを`import`したときに以下のエラーが発生した場合に**Layerを追加**して対応する

```json:Response
{
  "errorMessage": "Unable to import module 'lambda_function': No module named 'ライブラリ名'",
  "errorType": "Runtime.ImportModuleError",
  "requestId": "リクエストID",
  "stackTrace": []
}
```

# 対応手順

### エラーが発生する例 
今回は例として、`requests`ライブラリを`import`する

以下のスクリプトをLambdaで実行するとエラーが発生する
```python:lambda_function.py
import requests

def lambda_handler(event, context):
    
    res = requests.get('https://example.com')
    body = 'statusCode: ' + str(res.status_code)

    return {
        'statusCode': 200,
        'body': body
    }
```
```json:Response
{
  "errorMessage": "Unable to import module 'lambda_function': No module named 'requests'",
  "errorType": "Runtime.ImportModuleError",
  "requestId": "レスポンスID",
  "stackTrace": []
}
```

### Layerを追加する

下記の公式ドキュメントを参考に`Layer`を自作して追加することもできるが、手間がかかるので**簡単な方法を紹介**する

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html

下記**Githubページ**から自分の条件に合ったページに遷移して、必要なライブラリのARNをコピーする（importしたライブラリがない場合は上記のドキュメントでやる）

https://github.com/keithrozario/Klayers/tree/master/deployments

今回の例では`Python 3.9`、`ap-northeast-1`リージョンなので以下のページからコピーする

https://api.klayers.cloud//api/v2/p3.9/layers/latest/ap-northeast-1/html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/31fd795e-baf1-a344-6362-fdb7ab54ea03.png)

コピーできたらコンソールの`レイヤーを追加`から`ARNを指定`を選び、先ほどコピーしたARNを貼り付けて`追加`をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/732a717d-b150-0c1f-6954-bf6e9fe4d1e7.png)

### 再度実行してみる
エラーが解消され実行できていることが分かる
```json:Response
{
  "statusCode": 200,
  "body": "statusCode: 200"
}
```


# 参考

https://aduce.jp/aws/volunteers-lambda-python-layers
ラズパイでOpenSSHを使った公開鍵認証

# やりたかったこと
Macからラズパイに公開鍵認証でSSH接続させるように設定したかった。

`vi /etc/ssh/sshd_config`でパスフレーズのみの認証をできなくする。
```diff
# To disable tunneled clear text passwords, change to no here!
- #PasswordAuthentication yes
+ PasswordAuthentication no
```
設定変更後は、`systemctl restart sshd`でプロセスを再起動させること。

:::note alert
ターミナルを落としたりSSH接続した状態から抜けてしまうと、再接続できなくなるリスクがある。
絶対に繋いだままにしておくこと。
ssh接続を試す場合は、別のターミナルを起動して接続を試すこと。
:::

# SSH接続に失敗する
Mac(クライアント側)で、秘密鍵(id_ecdsa)と公開鍵(id_ecdsa.pub)のキーペアを作成。
`-i`オプションで秘密鍵(id_ecdsa)を指定してSSH接続を試すも、下記のエラーとなる。
(`-v`オプションをつけるとデバッグメッセージを表示できる。)
```console:Mac
% ssh -v username@192.168.0.254 -i id_ecdsa
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.
username@192.168.0.254: Permission denied (publickey).
```

# 原因を調査する
ラズパイ側で認証ログを調べるも、全然情報がない。
```
# tail /var/log/auth.log 
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Jan  3 13:43:00 raspberrypi sshd[7919]: Connection closed by authenticating user username 192.168.0.10 port 54467 [preauth]
Jan  3 13:43:09 raspberrypi sshd[7928]: Connection closed by authenticating user username 192.168.0.10 port 54468 [preauth]
```

`vi /etc/ssh/sshd_config`でログレベルを変更。
おそらく標準がINFO(コメントアウトされてる)になっているので、debugに変更。
```diff
- #LogLevel INFO
+ LogLevel debug
```
設定変更後は、`systemctl restart sshd`でプロセスを再起動させること。

これで認証失敗の原因が調査できるようになった。

# 鍵の参照先が違う
ログを見てみると、`/home/username/.ssh/authorized_keys2`を参照しにいっているようである。そんな名称ではない。
```
# tail -20 /var/log/auth.log
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Jan  3 13:51:43 raspberrypi sshd[8816]: debug1: trying public key file /home/username/.ssh/authorized_keys2
Jan  3 13:51:43 raspberrypi sshd[8816]: debug1: Could not open authorized keys '/home/username/.ssh/authorized_keys2': No such file or directory
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
```
`vi /etc/ssh/sshd_config`で鍵名称を変更した。
```diff
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
- #AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2
+ AuthorizedKeysFile      .ssh/id_ecdsa.pub
```

# 権限で引っかかる
```
# tail -20 /var/log/auth.log
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Jan  3 13:53:56 raspberrypi sshd[9466]: debug1: Could not open authorized keys '/home/username/.ssh/id_ecdsa.pub': Permission denied
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
```
あ・・・rootでファイル作ったんだった・・・。
接続するユーザー名で作らないと当然権限がないので引っかかる。
```
# ls -l
合計 4
-rwx------ 1 root root 199  1月  3 13:35 id_ecdsa.pub
```
ということで、権限を変更する。
```
# chown username:username id_ecdsa.pub
```

# 接続できた
これで接続できるようになった。
もう`-v`オプションは要らない。
```
% ssh username@192.168.0.254 -i id_ecdsa
```
AUTOSAR Abstract Platform 物語(1) Model Based Design

AUTOSAR Abstract Platform

https://www.autosar.org/fileadmin/standards/foundation/22-11/AUTOSAR_TPS_AbstractPlatformSpecification.pdf
　
方向で、一歩でも前に進んだことを記録するために、12回の連載記事を書き始めます。　


<この項は書きかけです。順次追記します。>

# Model Based Design

AUTOSARが始まったころ、何人かの関係者からお聞きしたのは、　
Matlab/Simulinkで設計して模擬試験したら、ソフトウェアを自動生成する




# 参考資料

AUTOSAR R23-11 資料整理の計画（年越し懇親会遠隔開催時間投票含む）

https://qiita.com/kaizen_nagoya/items/6b939e2373e0e6047ae8



 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞


# 文書履歴(document history)
ver. 0.01 初稿 20230103

### 最後までおよみいただきありがとうございました。

いいね、フォローをお願いします。
Cloud Run での WebSocket 接続のタイムアウトに対処するためには

こんにちは！mayukorin です．今日は，Cloud Run での WebSocket 接続のタイムアウトに対処するための方法についてお話しさせていただこうと思います！

# 先に結論
* Cloud Run では， WebSocket 接続は __30秒__ でタイムアウトする[^1]．
* WebSocket では，このようなタイムアウトに対応するために __Ping and Pong フレーム__ が定義されている[^2]．
    * クライアントまたはサーバーがpingを送信
    * サーバーまたはクライアントがpongを送信
    * これを定期的に繰り返すことで，クライアント・サーバー間の接続を維持できる．
* Cloud Run の場合は，__30 秒未満__ の間隔で ping/pong を行えばよい

# 背景

WebSocket を使ったサービス[^3]をデプロイしたのですが，CloudRun上で何故か30秒でWebSocketの接続が切断されてしまうという現象が起きていました．ローカルで動かすときにはそんなことは起きなかったので謎でした．

ローカルでCloudRunにアクセスしても同じように30秒で切断されてしまったので，CloudRun側の問題であると確信しました．

# Cloud Run では， WebSocket 接続は __30秒__ でタイムアウトする
色々調べてみると，[Google Cloud のドキュメント](https://cloud.google.com/load-balancing/docs/https#websocket_support)に以下のようなことが書かれていました．

> WebSocket 接続のタイムアウトは、ロードバランサの構成可能なバックエンド サービス タイムアウトによって異なります。デフォルトは 30 秒です。このタイムアウトは、WebSocket 接続が使用中かどうかに関係なく WebSocket 接続に適用されます。

まさにこれが30秒で接続が切断される原因でした！

# WebSocket で定義されている Ping and Pong フレーム

このようなタイムアウトに対応するために，WebSocket では __Ping and Pong フレーム__ が定義されています[^2]．これは，クライアント・サーバー間の接続を維持する[^4] などの用途で使われるもので，以下のような手順からなります．

1. クライアントまたはサーバーがpingを送信
1. サーバーまたはクライアントがpongを送信
1. これを定期的に繰り返すことで，クライアント・サーバー間の接続を維持できる．

Cloud Run では接続が30秒でタイムアウトしてしまうので，このping/pongを __30秒未満__ の間隔で行えば接続が維持できるということになります！

ping/pong の仕組みは，自前で実装する必要があります．例えば，サーバー側からpingを送信したい場合 && サーバー側でGoのgorilla/webSocket を使っている場合は，[こちらの記事](https://qiita.com/dlstjq7685/items/564f28147daf20a6496d)が大変参考になります．他の言語でwebSocketを使っている場合にも，検索すれば出てくると思います（無責任でごめんなさい...）

# 結論（再掲）
* Cloud Run では， WebSocket 接続は __30秒__ でタイムアウトする[^1]．
* WebSocket では，このようなタイムアウトに対応するために __Ping and Pong フレーム__ が定義されている[^2]．
    * クライアントまたはサーバーがpingを送信
    * サーバーまたはクライアントがpongを送信
    * これを定期的に繰り返すことで，クライアント・サーバー間の接続を維持できる．
* Cloud Run の場合は，__30 秒未満__ の間隔で ping/pong を行えばよい

# 参考
* https://cloud.google.com/load-balancing/docs/https#websocket_support
* https://websockets.spec.whatwg.org/#ping-and-pong-frames
* https://qiita.com/dlstjq7685/items/564f28147daf20a6496d


[^1]:https://cloud.google.com/load-balancing/docs/https#websocket_support
[^2]:https://websockets.spec.whatwg.org/#ping-and-pong-frames
[^3]:[こちらの記事](https://qiita.com/mayukorin/items/f7034b33e1ca78c1dc11#treasure-%E3%81%A7%E9%96%8B%E7%99%BA%E3%81%97%E3%81%9F%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)の記事で紹介した Matchong というアプリです．

[^4]:これを一般に __KeepAlive__ と言うそうです
devcontainerでC++ Qt5, GTK4, SDL2 でGUIアプリ開発 


<br>

Windoiws10でもWSLgでLinux GUIアプリが動くようになったのでテンプレートを作ってみました。
環境構築がわからない初心者の方でもvscodeでコンテナを開けば開発

<br><br>

C++で
構文チェック、フォーマッタ、ビルド環境、拡張
と一通り整ったdevcontainerです。

<br><br>

ubuntu 22.04
windows 10(最新の状態にして下さい)
windows 11
は動くと思います。

**mac** はXQuartzをインストールする必要があるようです。

<br><br><br>

まず

### Ctrl + Shift + p
CMake: Configureを選んで下さい。

<br><br>

共通ショートカットは

### F5 ビルド + デバッグ


### F7 ビルド

<br><br><br><br>


##### windowsはwsl内でクローンして下さい


## Qt5

[CPP-QT5-devcontainer](https://github.com/kxkx5150/devcontainer-CPP-QT5-template)

![d.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57472/56227762-4e1b-ae60-4c0f-d849235653a7.png)

![ddd.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57472/af7ec9a7-f7cc-1fa4-602d-1340b605a65b.png)

## QtDesigner を起動するショートカットを設定

<br>

現在開いてるアクティブなui ファイルを開きます。

<br><br>

Ctrl + Shift + p　を押して
Preferences: Open Keyboard Shortcuts (JSON)  
を開いて下さい


keybindings.json　に以下をペースト
```
// Place your key bindings in this file to override the defaults
[
    {
        "key": "F1",
        "command": "workbench.action.tasks.runTask",
        "args": "Qt Designer"
    }
]
```



<br><br><br><br><br><br>


## GTK4

[CPP-GTK4-devcontainer](https://github.com/kxkx5150/devcontainer-CPP-GTK4-template)

<br><br><br>

## SDL2

[CPP-SDL2-devcontainer](https://github.com/kxkx5150/devcontainer-CPP-SDL2-template)

##### SDL2、GLFWを切り替えられます。

OpenGLに対応しています。

<br><br>

SDL2
OpenGL
GLEW
GLFW

SDL2とGLFWの切り替えはCMakeLists.txtの
set(USE_GLFW FALSE)　をTRUEにして下さい。




<br><br><br><br><br><br>
2023年1月　記事数一覧

2023年は2500記事を書けるかどうか、博打を打つことにした。　

自分自身との賭けです。法律には違反していないと思います。　

<この項は書きかけです。順次追記します。>

もし、書けたら、ある全書相当の冊子を購入します。　

予定との差は、平日6,休日10で計算します。

||数|予定との差|
|:--|--:|--:|
|1/1*|1|-9|
|1/2*|5|-5|
|1/3*|14|4|
|1/4*|3|-7|
|1/5*|10|0|
|1/6*|10|0|
|1/7*|21|11|
|第1週計|64|-6|
|1/8*|7|-3|
|1/9|17|11|
|1/10|7|1|
|1/11|0|-6|
|1/12|0|-6|
|1/13*|21|11|
|1/14*|13|2|
|合計|128|2|

1/1には、編集は十数箇している。

# 参考資料　
AUTOSAR Abstract Platform User Group Weekly Report(1) 2022.1.8
https://qiita.com/kaizen_nagoya/items/fece4f7719ef55d612bf

AUTOSAR Abstract Platform User Group Weekly Report(2) 2022.1.15
https://qiita.com/kaizen_nagoya/items/6f1168a36e795976a906

祝休日・謹賀新年：2023年の目標
https://qiita.com/kaizen_nagoya/items/24584ac215517a4621ee

2023 書き初め
https://qiita.com/kaizen_nagoya/items/d494737e2627127b530d

2022年12月は530記事書いたはず。＆2023年予定。
https://qiita.com/kaizen_nagoya/items/b6f675f8a7d8bddf0d21

AUTOSAR R22-11 一覧（２）
https://qiita.com/kaizen_nagoya/items/6b0615884e954c65fb43

AUTOSAR R22-11 マラソン
https://qiita.com/kaizen_nagoya/items/988aa405a6fdd794fe53

年末にできれば100記事を30点に仕上げる。年越し2日で第二段階終了。
https://qiita.com/kaizen_nagoya/items/3ffdc82caee3a325d1d7

年末にできれば100記事を30点に仕上げる。年越し2日で第二段階終了。
https://qiita.com/kaizen_nagoya/items/3ffdc82caee3a325d1d7

2023年1月　記事数一覧
https://qiita.com/kaizen_nagoya/items/78153968c5de76a7fd83

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

### 文書履歴(document history)
ver. 0.01 初稿 20230103

### 最後までおよみいただきありがとうございました。

いいね、フォローをお願いします。