OmniAICreator/Qiita-1.07M huggingface dataset:
tkinterを使ってテキストエディタのアプリを作ってみた　~PART3~

前回はサブウインドウについて解説していきました。今回はメインウインドウについて解説していきます。テキストエディタアプリに関する投稿は今回が最後になります。

メインウインドウ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2631873/e965e9a0-fedb-fdba-7c73-7090f96f487a.png)
仕様としては、まずメニューバーのFileタブを押下すると、Open...とSave as...とExitが表示されます。そのうちのOpen...を押下すると任意のテキストファイルを読み込み、下部のテキストエディタに表示させることができます。

また、Save as...を押下すると任意のディレクトリ内にエディタで作成した定型文を保存することができます。Exitはアプリを終了させます。では、プログラムを掲載します。

Open...押下時に動く関数open_func
```py
# Open...
def open_func():
    # 開くテキストファイルのパス
    typ = [("Text","*.txt"),("All Files","*.*")]
    txt_path = tk.filedialog.askopenfilename(filetypes = typ)
    # ファイルが選択された場合データ書き込み
    if len(txt_path) != 0:
            # テキストボックスのデータ消去
            txtbox.delete("1.0","end")
            # テキストボックスへ書込み
            with open(txt_path,"r") as file:
                txtbox.insert("1.end",file.read())
```
Save_as...押下時に動く関数save_func
```py
# Save...
def save_func():
            # 保存するテキストファイルのパス
            typ = [("Text","*.txt")]
            txt_path = tk.filedialog.asksaveasfilename(filetypes = typ,
                                                      defaultextension = "txt")
            # ファイルが選択された場合データを保存
            if len(txt_path,) != 0:
                # ファイルへ書込み
                with open(txt_path, "w") as file:
                    # テキストボックスの値を取得
                    data = txtbox.get("1.0","end")
                    file.write(data)
```
メインウインドウGUI
```py
### GUI ###
# ウインドウの作成
root = tk.Tk()
# フレーム
frame = ttk.Frame(root,padding = 5)
frame.pack(padx = 5,pady = 5)
# テキストボックス
txtbox = tk.Text(frame,width = 60,height = 20)
# スクロールバー作成
yscroll = tk.Scrollbar(frame,orient = tk.VERTICAL,
                      command = txtbox.yview)
yscroll.pack(side = tk.RIGHT,fill = tk.Y)
txtbox["yscrollcommand"] = yscroll.set
//縦型のスクロールバーを右側に配置し、縦方向に移動するコマンドを記述

# テキストボックスの配置
txtbox.pack()
# メニューバーの作成
menubar = tk.Menu(root)
root.configure(menu = menubar)
# Fileメニュー
filemenu = tk.Menu(menubar,tearoff = 0)
menubar.add_cascade(label = "File",menu = filemenu)
# Fileメニューの内容
filemenu.add_command(label = "Open...",command = open_func)
filemenu.add_command(label = "Save as...",command = save_func)
filemenu.add_separator()
filemenu.add_command(label = "Exit",
                    command = lambda:root.destroy())
//それぞれのメニューに関数を組み込み仕様通りに動くよう記述

# Helpメニュー
helpmenu = tk.Menu(menubar,tearoff = 0)
menubar.add_cascade(label = "Help",menu = helpmenu)
# >Manual
helpmenu.add_command(label = "Manual")
//メニューのみでマニュアル的なものは作成しておりません。

# 定型文ボタン
fp_button = tk.Button(root, text = "Fixed Phrase",
                      command = sub_window)
fp_button.pack(padx = 10,pady = 10,ipady = 5,fill = tk.X)
//サブウインドウを開く関数を組み込み、テキストエディタの下部に配置

# ウインドウ状態の維持
root.mainloop()
```
これで今回のプログラムは終了となります。このテキストエディタはメールの文面などを作成する際にすごく重宝いたしますので、もし、便利と思っていただいた方は自分なりにアレンジを加えて、作成してみるとよいかと思います。例えば誰か別の人に作成してあげる場合はマニュアルの部分も記述して作ってあげるとより親切かと思います。以上です。そのうちまた別の技術を投稿したいと思います。

エンジニアファーストの会社　<a href="https://www.cre-co.jp/">株式会社CRE-CO</a>　H_M
SpringBoot2.5.1以降でDBの初期化が走らない

こちらの記事のSpringBoot2.5.1以降の解消手順です。

https://qiita.com/gami_/items/0208a7e6d1a41b447c84

## 結論

以下を設定してください。

```application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:file:./target/db/testdb
spring.datasource.username=sa
spring.datasource.password=
spring.sql.init.mode=always
spring.sql.init.schema-locations=classpath:schema.sql
spring.sql.init.data-locations=classpath:data.sql
```

SpringBoot2.5.0以前は
```application.properties
spring.datasource.initialization-mode=always
spring.datasource.schema=classpath:schema.sql
```

SpringBoot2.5.0では
```application.properties
spring.sql.init.enabled=true
spring.sql.init.schema-locations=classpath:schema.sql
spring.sql.init.data-locations=classpath:data.sql
```

## 細かい補足

 - `spring.sql.init.mode` 2.5.1から変わったっぽいです。
   - あんまり情報が出てこなくてめっちゃ困りましたが、[こちら](https://github.com/spring-projects/spring-boot/commit/c52143727a9c35b656f2f0d5298344e876785404)のコミットで変更されていそう。
 - `2.5.0`から`spring.datasource`でまとめられていたプロパティ群が`spring.sql.init`に切り出されたみたいです。
TypeScriptをVSCodeで使いたい

※この記事は __とりあえずTypeScriptが使える環境が欲しいけど何をしたらいいかわからない__ 人向けの記事です。
# インストールするもの
## １.node.js
まずはnode.jsのパッケージを [install](https://nodejs.org/ja/) しましょう。
自分は最新版にしました。
その後パッケージを開きnode.jsをinstallします。
## ２.Typescript
コマンドプロンプトで[npm install -g typescript]と入力します。
（コマンドプロンプトは画面左下にある検索ボタンで[cm]と入力すると確認できます）
___
これで最低限必要なものは入れることができました。
# VSCodeでTypeScriptをJavaScriptにコンパイル
VSCodeでプログラムを書いたらVSCode内にあるターミナルで[tsc ファイル名]と入力すると同じファイル名で拡張子が[.js]のファイルが作成されます。

:::note warn
警告
この時プログラムを[ctrl + s]で上書きしていない場合、意図したものにならない可能性があります。
必ず上書き保存してから[tsc]コマンドを使いましょう。
:::

# 最後に
理解が浅い学習中の私が書いた記事です。
参考程度に読んでいただけると幸いです。
【Python】クラス変数、クラスのインスタンス変数の一覧を取得

クラス変数の変数名を一覧で取得したい、ということがあったのでその備忘録です。

```python: クラスとインスタンスを用意
class Hoge:
    a = 12
    b = "hoge"

    def __init__(self):
        self.c = 100
        self.d = "fuga"

hoge = Hoge()

```

```python: クラス変数"a", "b"を含んだ辞書を取得
>>> Hoge.__dict__.items()
 dict_items([('__module__', '__main__'), ('a', 12), ('b', 'hoge'), ('__init__', <function Hoge.__init__ at 0x0000029B6FBB40D0>), ('__dict__', <attribute '__dict__' of 'Hoge' objects>), ('__weakref__', <attribute '__weakref__' of 'Hoge' objects>), ('__doc__', None)])

>>> type(hoge).__dict__.items()
dict_items([('__module__', '__main__'), ('a', 12), ('b', 'hoge'), ('__init__', <function Hoge.__init__ at 0x0000029B6FBB40D0>), ('__dict__', <attribute '__dict__' of 'Hoge' objects>), ('__weakref__', <attribute '__weakref__' of 'Hoge' objects>), ('__doc__', None)])

```

```python: クラスのインスタンス変数の辞書を取得
>>> hoge.__dict__.items()
dict_items([('c', 100), ('d', 'fuga')])

>>> Hoge().__dict__.items()
dict_items([('c', 100), ('d', 'fuga')])
```
sealed classってめちゃくちゃ便利じゃない？

# 初めに
今回は、sealed classについて書いていきます。

### sealed class
簡単にいうと***全然違う***`data`の型でもひとまとまりで持っておけるクラスです。
例えばですが、一つの`RecyclerView`で二種類のデータの型を表示したい時などに非常に役立つ機能です。
書き方は、以下の通りです。
```kotlin
sealed class Example {

    data class hoge(
        val sample: Sample
    ) : Example()

    data class huga(
        val something: Something
    ) : Example()
}
```
`Sample`と`Something`が全く別の`DataClass`でもひとまとまりに管理をすることができるので`RecyclerView`に対して`Example`クラスを渡すようにすればあとは中身を見て判断するように実装すればいいだけです。
もし、片方は何もデータを保持したくないのであれば`object`で宣言をすれば問題ありません。

また、Data構造自体は全く同じだけど`View`に反映する時に区別をしたい時などがあると思います。
そんな時は下記の書き方をすることで簡単に区別することができるので非常に便利です。
```kotlin
sealed class Example {

    abstract val sample: Sample
    abstract val something: Something

    data class hoge (
        override val sample: Sample,
        override val something: Somthing
    ) : Example()

    data class huga (
        override val sample: Sample,
        override val something: Somthing
    ) : Example()
}
```
### 最後に
今回は最近改めて使いやすさと便利さを痛感した`sealed class`を紹介させていただきました。
自分はAPI通信でよく使ってましたが、それ以外でもいろんな場面で活躍してくれると思うので、是非皆さんも触ってみてください。
未経験からのエンジニア転職で後悔しないために知っておくべき3つの真実

採用活動に関わるようになり、思うところがあるので書きます。
情報収集をしていく中で「**未経験**　**エンジニア転職**」と検索して出てくる情報に対しての個人的見解です。

# 自己紹介
* 採用担当
* フロントエンドからサーバーサイド、インフラ、機械学習系の案件を経験
* エンジニア歴６年


# 前提　エンジニア転職における「後悔」とは何か？
「思っていた働き方ができない」という、いわゆる**ミスマッチ**を想定しています。
* アプリ開発がやりたいのに、事務作業ばかりやっている
* webシステムの開発がやりたいのに、PCの設定ばかりやっている
* 機械学習がやりたいのにやれない

全てミスマッチです。

こんな後悔をしたくない方に読んで頂ければ幸いです。

# 真実１　「未経験採用 → SESで客先常駐」は本当によくある
自社開発をしている企業ではあまりないかと思いますが、
受託開発をしている企業の場合、本当によくあります。

よくあるケースは、「**３ヶ月の研修後、客先常駐**」というやつです。

「会社としてはすぐに売上になるし、未経験の求職者は断りにくい」という判断をされると、
もれなく上記のケースに落ち着きます。

目安として、100人規模の受託開発系の企業だと、未経験採用→客先常駐が多くなります。


一方で、**客先常駐をしないで受託開発**をしている企業もあります。

説明会や面談時に
「未経験から入社した方は、どのように仕事をしていますか？」、と質問してみて下さい。

# 真実２　必ずしも転職エージェントを使う必要はない
情報収集のために依頼するのはありだと思いますが、
「エージェント任せ」にすると、**転職活動は失敗**します。


エージェントの方は、**IT業界の人ではあるが、現役のエンジニアではない**です。
開発現場にいた経験がある人は少ないですし、あっても古い情報を話しているケースが多いです。

## 未経験の方に紹介できる求人情報は似てる
エージェントのビジネスモデルという観点から考えると分かりやすいです。

エージェントの報酬は、転職成功者の年収のx%で算出されます。

そのため、時間をかけず求職者と企業をマッチングさせたい
　→　**未経験でも決まる確率の高い企業**を紹介
となります。

良い求人に巡り会えたらラッキーくらいに思っておく方が良いでしょう。

## 採用サイトから自分で問い合わせるメリットはあるのか？
大きく２つメリットがあります。
　１．実際に「**どんな人と一緒に働くのか？**」が分かる
　２．応募先の企業に、自分の**モデルケース**になる人がいるか分かる

入社後にどのように仕事をし、**どんなキャリアを築けるかを具体的にイメージできる**ようになります。

例えば、
* 入社後は先輩社員のもとで実装系のタスクを行う
* 1年後には、後輩の指導もしつつ詳細設計も行う
* 2年後には、顧客折衝も行う
* 3年後には、チームを持ってもらう

といった具合です。

その結果、ミスマッチを減らせます。

# 真実３　ポートフォリオは無くても良い
結局ポートフォリオだけでは判断しないからです。
ポートフォリオがなくても、勉強した内容をちゃんと伝えられたらOKです。
弊社での話になりますが、入社時に転職用にポートフォリオを用意していた方は１人もいません。


# 最後に
エンジニア転職の一助になれば幸いです！

弊社は未経験からエンジニアになった方が活躍している会社です。
未経験者の新卒・中途採用も実施していますので、ご興味ある方は[こちら](https://www.recruit.nuco.co.jp/)より。
３倍速で成長する人の特徴3つ

## 読んでほしい方
* エンジニアを目指して勉強している人
* エンジニアになりたての人
* 未経験からエンジニア転職を考えている社会人
* エンジニア職に興味のある学生

成長して、1日でも早く一人前のエンジニアになるぞ！
という人に向けての記事です。

未経験からエンジニアに転職をして、もうすぐ2年が経とうとしています。
そんな自分の経験や、会社の先輩後輩を見ながら感じたことをまとめてみました。

## 自分で考える癖がある
自分が成長していくにあたり、自分に何が足りずに何を身につけていくべきか。を自分で考えられるかどうか。
これが成長が早い人が持っている共通点の一つだと感じます。

もちろん、全てを我流で決めていくのがベストだということではありません。
数多ある情報の中から取捨選択し、自分の状況に合わせて活かしていく。
初心者エンジニアに向けた記事なども検索すれば、いくらでも出てきてしまうからこそ、たまたまみた記事の内容を100パーセント鵜呑みにするのではなく、自らで考えた上で取り入れていく必要があります。

また、自分の先輩にアドバイスをもらいにいくことも大切です。

しかし、**自分なりの意見を持ってから聞く**のと、自分の意見をもたずにただただ聞くのとでは雲泥の差があります

先輩と自分の能力、状況は同じではないので、先輩のアドバイスが自分に必ずしも当てはまるという保証もありません。(もちろん自分だけの判断より良い可能性は高いですが)

自分なりの意見を持ってからいくのが大切な理由としては、**「何を学ぶか」** も大切ですが、**「なぜ学ぶべきか」** ということを理解していることも非常に大切だからです。

受動的に学びをすると、**「読んでいる技術書に書かれた知識」** しか身につきません。

しかし、「なぜ学ぶべきか」を持っていると、1つの技術書に書かれている内容を超えて、その周辺知識も追加で調べたりするようになります。
**「学ぶこと」は目的ではなく、あくまでも成長していくための手段**です。

日々学習を継続していけるかどうか、そのモチベーションの源としても「なぜ学ぶべきか」をしっかり自分の中で確立できていることが大切です。

「意欲的に学んでいる時と、いやいや義務的に学んでいる時とで、知識の吸収に大きく差がある」
というのは、過去の人生振り返って実感してきた人も多いのではないでしょうか？

そういう意味も含めて、自分で考えて学んでいる人は、成長が早いと感じます。

## 考えるよりも行動する
**2,3行コードを書いて実行してみれば分かることを、30分かけてググっている人**を見かけることがあります。

また、「試しにコードを実行してみたときに、想定外の挙動をして新しい発見があった」ということも日常茶飯事です。

**エラーが出てしまうことは、何一つ悪いことではありません。**

むしろ、**「自分の知識が広げられるチャンス！」** というように捉えられている人は成長が早いです。

また、その時の実装で直接必要ではないにしても、「こういい場合はどうなるんだろう？」ということも一緒に確認する。などの癖があると、一つのことを学ぶ時に、その周辺知識も一緒に学ぶことができます。必要なことしか確認しない人と比べると、何倍も成長が早くなります。

よく言われていることではありますが、**「知っている」と「できる」の間には大きなギャップがあります**。
どれだけ優秀な人だったとしても、エラーを出さないということはありません。
というよりも、むしろ**優秀な人ほど多くのエラーを経験**してきています。

「エラーをびびらず、好奇心旺盛にどんどん試してみる」
それが、グングン成長していくための秘訣だと個人的に思っています。

## 気になったことはすぐに調べる
自分が知らない概念、専門用語を聞いたときに。「ふーん」と流す人と、すぐにググる人。
この差の積み重ねは非常に大きくなります。

**知っているものが増えると、新しいものが出てきたときの理解度も大きく変わってきます**。
（「要は〇〇と同じことか！」、「これは××の技術をもとにしているのか！」というように知識が広がっていくので）

人間は基本的に、自分の知らない範囲の言葉は耳に入ってきません。（電車で外国語で話している人の話が全く気になりませんよね）

QiitaやZennなどの技術記事を、情報収集として読んでいる人も多くいるかと思いますが、
自分の知っている技術の記事だと俄然読む気になる人も多いのではないでしょうか?

そのため、自分から知識を広げていく人と、本当に必要なものしか調べない人だと、知識の増え方が**加速度的に**差が広がっていきます。

最初の頃は、本当に日本語かと思うほど他のエンジニアの話している内容や、技術記事の内容は意味が分かりません。

千里の道も一歩から。

最初から専門家の人はいません。コツコツと目の前の単語から自分のものにしていきましょう。

## まとめ
自分で文章にまとめていきながら、「もっと学んでいかないとな」と再決意することができました。

向き不向きがあるかな？と思い上記には入れなかったのですが、
**「学ばないとどうしようもない状況に自分の身を置く」**
というもの非常に大事なポイントかなと思います。

よほど意志の強い人間でない限り、基本的にサボりたくなるのが人間です。
「来週の仕事をこなすためには、〇〇の知識がどうしても必要」となれば、人間はなんとかしたりします。

自分自身、知識がかなり乏しい状態でIT業界に飛び込みました。
楽な道のりだったわけではないですが、1年勉強してから入社したと考えるよりも圧倒的に成長は早かっただろうなと思います。

弊社は未経験からエンジニアになったメンバーが活躍している会社です。
未経験者の新卒・中途採用も実施していますので、ご興味ある方は[こちら](https://www.recruit.nuco.co.jp/)より。
AWSソリューションアーキテクトプロフェッショナル合格記

# はじめに
2021年末にAWSソリューションアーキテクトプロフェッショナルを受験し、合格したので
備忘録も兼ねて勉強した内容、教材などをまとめたいと思います。

# AWS認定試験とは？
AWS認定とはAWS上におけるサービスの知識やアーキテクチャなどを問う試験になります。
下記のような種類があります。

|区分 | 難易度 | 試験名 | 詳細 |
|:--|:-:|:--|:--|
|基礎レベル|低|Cloud Practitioner|6 か月間の基礎的な AWS クラウドと業界知識|
|アソシエイトレベル|中|・Solutions Architect（Associate）<br>・SysOps Administrator<br>・Developer |1 年間の AWS クラウドを使用した問題解決と<br>解決策の実施における経験|
|プロフェッショナルレベル|高|・Solutions Architect（Professional）<br>・DevOps Engineer|2 年間の AWS クラウドを使用した<br>ソリューションの設計、運用、<br>およびトラブルシューティングに関する経験|
|専門知識|高|・Advanced Networking<br>・Data Analytics<br>・Database<br>・Machine Learning<br>・Security<br>・SAP on AWS|試験ガイドで指定された Specialty 分野に<br>関する技術的な AWS クラウドでの経験|

# これまでの経験値
・試験については数年前に「Solutions Architect（Associate）」を取得しました。(期限切れ)
・数年ほど業務でAWS上に基礎的な構成のサーバー構築経験あります。

# 勉強
## 勉強教材
■Blackbelt
AWS公式のドキュメントです。
AWSのサービスごとの説明がまとめられている資料になります。
こちらはよく参照しました。
https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/

■よくある質問
AWS公式のドキュメントです。
サービスごとのよくある質問がまとめられています。
https://aws.amazon.com/jp/faqs/

■ホワイトペーパー
AWS公式のサービスの技術解説書です。
サービスの機能や設計・管理方法を技術的に解説しています。
AWSのサービスをしっかり理解する上では目を通したほうが良いですが、
時間的に余裕がなくあまりこちらは参照しませんでした。
https://aws.amazon.com/jp/whitepapers/

■AWS模試
こちらは無料版、有料版両方とも受けました。
一応両方とも合格ラインには達しました。

■Udemy
・これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座
　　以前の試験からだいぶ時間が空いてしまったので復習のため購入しました。
　　50%ほど視聴しました。
・AWS 認定ソリューションアーキテクト プロフェッショナル模擬試験問題集
　　問題集5回のうち、①②のみをそれぞれ2回づつ解きました。

■AWS AWB問題集で学習しよう
7問1セットになっている問題集です。
受験する試験の科目を1〜44セット解きました。
1-20くらいまでは反復して見直していましたが、時間がなくなってきて
それ以降の問題は1度通す程度でした。
参考にしていた当時は60まであったと思うのですが、44セットまでしか通せていません。
https://aws.koiwaclub.com/

■書籍
①AWS認定ソリューションアーキテクト－プロフェッショナル～試験特性から導き出した演習問題と詳細解説～
　　AWSサービスについての解説と1回分の問題集がついています。
　　こちらは2周勉強しました。
②AWS認定資格試験テキスト&問題集 AWS認定ソリューションアーキテクト - プロフェッショナル
　　半分ほど目を通しました。
　　(発売してすぐ購入したからか、少し誤字が気になりました)

## アウトプット
・ノートに書き出す
参考書や問題を解いているときにわからないものについて調べた内容を書き出し、
たまに見返すようにしていました。

・オリジナル問題の作成
社内でAWSの受験を目指すメンバー間で問題を出し合って対策しました。

・AWSの各サービスについて記事の作成
特定のサービスについてAWSのドキュメントなどを参照し、
まとめたものを社内で共有するということを実施していました。

## 勉強の進め方
受験の約半年ほど前から勉強に取りかかり始めました。
最初はUdemyのアソシエイトの教材と並行して書籍①を見始めました。
その後少し業務が忙しくなりあまり進められていない時期もあり、
受験2ヶ月前から集中的に勉強進めました。

教材としてよく使っていたのは、Blackbelt、よくある質問、
①の書籍、WEB問題集です。
移動時間もスマホで問題集を解いたり、
オリジナル問題を出すためにAWSのBlackbeltの資料を漁ったり
なるべくAWSの情報を取り入れるようにしていました。

# 試験前日
試験対象のサービス資料に一通り目を通して、試験に備えました。

# 試験当日
試験はテストセンターで受験しました。
試験会場には余裕を持って着くように行きました。
受付で本人確認の書類を提示して、渡される書類にサインして、準備ができたら
席に案内され、試験開始。という流れでした。

試験が始まると初見の問題ばかりで1問ごとに結構時間をかけてしまい、見返す時間が全くなかったです。
試験終了後、結果が表示されたときは嬉しさより、驚きの方が強かったです。

# 所感
試験結果のスコアギリギリだったため、対策が十分でないと感じました。
見返す時間がないと焦ってしまい、ミスする可能性が高くなってしまうので、
次回受験時は今回使った教材をベースにもう少し余裕を持って
受験できるよう勉強をしたいと思いました。

# 参考
https://aws.amazon.com/jp/certification/
https://udemy.benesse.co.jp/development/qualification/aws-qualification.html

# メモ
試験の更新情報
https://aws.amazon.com/jp/certification/coming-soon/
俺のキャッシュまとめ

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/%E4%BF%BA%E3%81%AE%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%BE%E3%81%A8%E3%82%81/)をご覧ください😀



生きていると度々キャッシュについて調査することがあり
その都度HTTPヘッダーの意味など忘れているのでメモしておく。

# 登場人物

- オリジン
    - webサーバー とか
- 共有キャッシュ
    - Proxy, CDN など
- ブラウザキャッシュ（正式名はプライベートキャッシュらしい）
    - クライアント

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56789/701041c2-83ff-31fa-f565-afdf428ac971.png)

# よく見るHTTPヘッダー

## レスポンス
- [Cache-Control](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control)
    - max-age
        - レスポンスが生成されてから最大 N 秒までキャッシュしていいか
            - キャッシュしてからの時間ではないので注意！
        - キャッシュの残り有効時間 = max-age - Age
    - no-cache
        - キャッシュしていいけど、利用する前にオリジンサーバーに更新がないか必ず確認してね
    - no-store
        - キャッシュしたらダメ！
    - その他
        - s-maxageなどmax-ageを無視するようなものもあるので、見知らぬものが設定されていた場合は都度調べること！
- [Age](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Age)
    - レスポンスが生成されてからの経過時間

## リクエスト
- Cache-Control （カンマ区切りで複数指定可）
    - no-cache
        - キャッシュを利用する前にオリジンサーバーに更新がないか必ず確認してね
        - ブラウザのスーパーリロード時はこれ！
    - no-store
        - キャッシュ保存しないでね！
        - 主要なブラウザーは no-store を使ったリクエストに対応していない。ので忘れてOK
    - max-age
        - N 秒以内に生成されたキャッシュなら許可するよ（キャッシュを返してくれていいよ）
        - 主要なブラウザーは再読み込み時 max-age=0
            - max-age=0 は no-cache の回避策。古いキャッシュ実装では no-cache に対応していないため。

# キャッシュが使われているか確認する方法

## 共有キャッシュ
- Cloud Front
    - キャッシュ使用
        - x-cache: Hit from cloudfront
    - 未使用
        - x-cache: Miss from cloudfront

## ブラウザキャッシュ
- 確認方法あるのかな？？

# FAQ
## ヘッダーでキャッシュクリアの指定は可能？

- 共有キャッシュ
    - [残念ながら不可能](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control#%E6%97%A2%E3%81%AB%E6%A0%BC%E7%B4%8D%E3%81%95%E3%82%8C%E3%81%9F%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%AE%E3%82%AF%E3%83%AA%E3%82%A2)
- プライベートキャッシュ
    - Clear-Site-Data で可能
        - ただし、あるサイトの保存されたすべてのレスポンスをクリアするので注意

## レスポンスにCache-Controlがない場合どうなるのか？
- よしなにキャッシュする
    - 有効期限の算出方法はRFCでは定めていない
    - 一般的にはLast-Modifiedヘッダの日時とDateヘッダの日時の差の10%の値を有効期間として定めることが多い
        - 参考：https://zenn.dev/kawakawaryuryu/articles/75af6ae44d2939
- そのため基本的には常に Cache-Control ヘッダー付与したほうがよい！
Node.jsの管理にVoltaを使ってみる

# Voltaとは
Windowsではnodistを長らく愛用していた。
それに代わるバージョン管理ツールとしてVoltaなるものを発見しインストールしていたが、数か月たっておりそのことをすっかり忘れていた。
node.jsのバージョンを上げる必要があったのだが、node.jsのインストーラーをDLしてセットアップしてしまい混乱した・・・。
今後忘れないように、まとめておく。

# 環境
OS：Windows 10 Pro 21H1

# 手順

インストーラをDLしてインストーラーを実行
voltaの確認
```
PS C:\> volta -v
1.0.8
```

特定のバージョンをインストールする

```
PS C:\> volta install node@16.15.1
success: installed and set node@16.15.1 (with npm@8.11.0) as default
```

nodeの確認

```
PS C:\> node -v
v16.15.1
```

試しに最新版を入れてみる

```
PS C:\> volta install node@latest
success: installed and set node@18.3.0 (with npm@8.11.0) as default
```

nodeのversionを確認するとインストールしたものに変わっている

```
PS C:\> node -v
v18.3.0
```

プロジェクトごとに切り替えたい場合は、pinコマンドを使う模様

```
PS C:\Users\dev\source\repos\DemoApp> volta pin node@16.15.1    
success: pinned node@16.15.1 (with npm@8.11.0) in package.json
```

これを実行すると以下の設定がpackage.jsonに追記される

```package.json
  "volta": {
    "node": "16.15.1"
  }
```

以上

##### 参考サイト
- https://zenn.dev/taichifukumoto/articles/how-to-use-volta
- https://docs.volta.sh/guide/getting-started
Ansible学んでみる

## 前提知識

- Linux
- Vagrant
- VBox

## Ansibleとは？

一言で言うと「構成管理ツール」です、
ソフトウェアのインストールや設定を自動的に実行する事が出来ます。

redhat.com/ja/topics/automation/learning-ansible-tutorial

## できること

`Vagrant up` すると `ansible` が実行され環境構築されるようにする

## Vagrantの準備

ファルダを用意して、フォルダに Vagrantfile を作成する。
Vagrantfile には下記を入力する。

```./Vagrantfile
Vagrant.require_version ">= 1.8.0"

Vagrant.configure(2) do |config|

  config.vm.box = "generic/ubuntu2004"

  config.vm.network "forwarded_port", guest: 80, host: 8080

  config.vm.synced_folder "./", "/home/vagrant/ansible/", create:"true"

  config.vm.provision :shell, :inline => <<-EOS
    /etc/apt/sources.list >> deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main
    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
    sudo apt update
    sudo apt -y install ansible
    sudo ansible-playbook /home/vagrant/ansible/playbook.yml
  EOS

end
```

## Ansibleの準備

Vagrantfile と同じディレクトリに playbook.yml を用意する。
Vagrantfile には下記を入力する。

```./playbook.yml
- hosts: localhost
  user: root
  tasks:
  - name: nginx install
    apt:
      name: nginx
      state: latest
      update_cache: yes

  - name: nginx service start
    service:
      name: nginx
      enabled: yes
```

## 起動する

Vagrantfile があるディレクトで下記コマンド入力すると
実行されVMが立ち上がりansibleが実行される

```bash
vagrant up
```

## 補足

別の方法でホスト側にansibleを入れ実行する方法もある

https://docs.ansible.com/ansible/2.9_ja/scenario_guides/guide_vagrant.html
SpringBootCLIインストール方法

# 事前準備
- [【初心者でもできる‼】Windows10にJava環境を作る方法（JDK14.0.1）](https://qiita.com/ryome/items/30135570954e36196821)
事前準備として、上記リンクの内容が必要です。
# SpringBootCLIインストール方法
1. 以下のサイトにアクセスする
    - https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.installing.cli
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/cccc8d1d-5819-4497-dedc-1c50f21838c9.png)
2. `spring-boot-cli-X.X.X-bin.zip` を展開する
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/64f5f8a2-7691-4bb2-484b-b4fea36951a1.png)
3. 展開したフォルダを `c¥` 配下に配置する。
![03-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/4b7ec62b-cbf0-f5bf-6d04-5141809660b0.png)
4. 環境変数を開く
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/3cb80554-7cd5-0e18-1049-3dd706247bc6.png)
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/ed548c16-444f-490d-1d14-4a59c27feefb.png)
5. `システム環境変数` の `新規(W)...` から `SPRING_HOME` を作成する
    - 変数名：`SPRING_HOME`
    - 変数値：`C:\spring-boot-cli-X.X.X-bin\spring-X.X.X`
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/9c8731cb-f689-89d2-0421-61220cd1201e.png)
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/765f6dc7-0f4f-a20f-b126-e84db84451f3.png)
6. `システム環境変数` の `Path` に `%SPRING_HOME%bin` を追加し、 `OK` を押下する
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/c56fe4c4-194b-403e-99e8-80f8a8df92f2.png)
![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/f9f80a26-4e37-1b0c-c476-142de7b1a81b.png)
7. `OK` を押下する
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/73168ea8-f261-ec53-9af4-7d323f808af5.png)
8. `OK` を押下する
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/ad8f5eec-3ddb-f383-16ef-b78a02306a71.png)
9. `コマンドプロンプト` を開く
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/d305e593-3b50-ff65-eb97-9f46059dbef9.png)
10. `コマンドプロンプト` に `spring --version` と入力する
```console:コマンドプロンプト
Spring CLI vX.X.X
```
上記が表示されれば成功
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/39346164-7902-7cdb-2a05-700c845b9b9e.png)
pip search で ERROR: XMLRPC request failed [code: -32500] の解決法

# 結論

```sh
$ pip3 install pip-search
$ pip_search mecab
```

:::note warn
インストールするパッケージ名は `pip-search` であるのに対し、コマンド名が `pip_search` であることに注意してください。
:::


# 起きたエラー

pipで検索しようとしたら、エラーが発生しました。

```sh
$ pip3 search mecab
ERROR: XMLRPC request failed [code: -32500]
RuntimeError: PyPI's XMLRPC API is currently disabled due to unmanageable load and will be deprecated in the near future. See https://status.python.org/ for more information.
```

インストールは問題なくできていました。

```sh
$ pip3 install numpy
Successfully installed numpy-1.22.4
```

# なぜエラーが起きたのか

`pip search` コマンドが裏で叩いてる XMLRPC API が使えなくなってることが原因のようです。
[こちらの記事](https://qiita.com/montblanc18/items/71a58d985de31ef47dfa)でちょっと詳しく解説されているので、気になる方は読んでみてください。

# 参考
- [How to Solve Error Message ERROR: XMLRPC request failed [code: -32500] upon executing pip search](http://www.dark-hamster.com/application/how-to-solve-error-message-error-xmlrpc-request-failed-code-32500-upon-executing-pip-search/)
- [PyPIのsearch APIが落ちているのでpipのコードを読んでみる](https://qiita.com/montblanc18/items/71a58d985de31ef47dfa)
access2000の作法 その17

# 概要
access2000の作法、調べてみた。
inner joinな、クエリーを作ってみた。

# サンプルデータ

議員.csv

```
議員名,会派コード
遠藤寛明,1
相田光照,1
遠藤和典,1
梶原宗明,1
五十嵐智洋,1
柴田正人,1
渋間佳寿美,1
矢吹栄修,1
小松伸也,1
島津良平,1
加賀正和,1
森谷仙一郎,1
鈴木孝,1
楳津博士,1
奥山誠治,1
小野幸作,1
金澤忠一,1
伊藤重成,1
舩山現人,1
田澤伸一,1
森田廣,1
坂本貴美雄,1
星川純一,1
志田英紀,1
梅津庸成,2
今野美奈子,2
菊池大二郎,2
髙橋淳,2
松田敏男,2
青木彰榮,2
青柳安展,2
石黒覚,2
吉村和武,2
髙橋啓介,2
木村忠三,2
関徹,3
渡辺ゆり子,3
菊池文昭,4
山科朝則,5
```

会派.csv

```
会派コード,会派名
1,自由民主党
2,県政クラブ
3,日本共産党山形県議団
4,公明党
5,無所属
```

# joinクエリーボタンを作る手順。
- 外部データ>インポート>テキストファイルで、csvをテーブルにする。
- menuフォームを右クリック。
- デザインビューを開く
- ボタンを設置
- ウィザードが開く  キャンセル
- プロパティシートを開く
- イベントを開く
- クリック時、コードビルダーを開く
```
Private Sub コマンド15_Click()
'join
    Dim db As DAO.Database
    Set db = CurrentDb
    Dim Q As QueryDef
    Set Q = db.CreateQueryDef("q議員会派", "SELECT 議員.ID, 議員.議員名, 会派.会派名 FROM 議員 INNER JOIN 会派 ON 議員.会派コード = 会派.会派コード;")
    MsgBox "ok"
End Sub

```
- フォームを閉じる
- 保存する


以上。
vuetifyのv-calendarで土日の色を変える

今回vuetifyのv-calendarを使用した中で、土日のカレンダーの背景色を変えることに苦労したので書いてみようと思います。

# 前提
  vue: 2.6.11
  vuetify: 2.6.0

# 手順に行き着くまでの過程
当初は、vuetifyのカレンダーのAPIで何かしら用意されているのでは :confused:
いや！あるはず！！！と思い、ひたすらv-calendarのコンポーネントページやAPIのページを見てました。
↓
一度思ってしまった考えを転換するのってなかなか難しくて
ひたすらvuetifyのドキュメントの中で探してました。
↓
もう流石にわからん！！と、上司に相談したところ、「HTML見に行けば？」と1分で解決策をいただきました :sob:

なかなか自力でなんとかするところと、人に相談するところとの境界線が
リモートも相まって、まだまだ手探りな駆け出しエンジニアです。

前置きが長くなってしまいました :sweat_drops: 

# 手順

 ### v-calendarでカレンダーを出力させる
:warning: Vue CLIから作る場合には、必ずvue CLI2で作ってください。:warning:
Vuetifyの現在のバージョンはVue 3をサポートしていません。
導入方法については、下記をご覧ください。

https://vuetifyjs.com/ja/getting-started/installation/#vue-cli-306b3088308b30a430f330b930c830fc30eb

vuetifyから提供されているので、カレンダー自体を出すのは簡単でした。
下記はカレンダーを表示するための最小のコードです。

``` App.vue
<template>
  <v-app>
    <div>
      <v-sheet height="94vh">
        <v-calendar></v-calendar>
      </v-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
```
![スクリーンショット 2022-06-01 12.41.19（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629280/b37dda26-f054-54d5-10b2-d45f8fa39ac3.png)

### 土日の設定をする
イメージとしては、週ごとに持っている`v-calendar-weekly__week`を`getElementsByClassName`でとってきます。
![スクリーンショット 2022-06-02 12.21.29（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629280/96104ae3-fb7e-8e34-eb71-9c9c6e92f53b.png)

sundayであれば配列上0番目に設定されています。
![スクリーンショット 2022-06-02 12.25.28（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629280/e1adc071-dee7-d7a4-ff4d-c300acfcbcfc.png)

saturdayであればの配列上6番目に設定されています。
![スクリーンショット 2022-06-02 12.32.13（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629280/bd19ee81-759e-93ea-ae7a-2acded75fec6.png)

`classList`にそれぞれ、sundayもしくはsaturdayを追加してあげて、styleの色を反映します。

![スクリーンショット 2022-06-01 18.15.45（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629280/af6af73c-ff84-805f-b69a-9a2fb7de50dd.png)
完成 :clap: 

コードは以下になります。

``` App.vue
<template>
  <v-app>
    <div>
      <v-sheet height="94vh">
        <v-calendar ref="calendar" @change="changeColor"></v-calendar>
      </v-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  methods:{
    changeColor: function () {
      setTimeout(() => {
        const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__week'))
        dayList.map(el => {
          el.children[0].classList.add('sunday')
          el.children[6].classList.add('saturday')
        })
      }, 200)
    }
  },
};
</script>
<style>
.saturday {
  background: rgba(0, 0, 255, .1);
}
.sunday {
  background: rgba(255, 0, 0, .1);
}
</style>

```

# 感想
`v-calendar-weekly__week`をどうとってくるのか非常に苦戦しました。
(結果的に、アドバイスという名のほぼやってもらった感じではありますが・・)

説明が拙くて、コードを見た方がわかるとは思いますが
自分の備忘録とし、またどなたかの参考になれば幸いです :bow_tone1: 


祝日の設定の仕方もかければいいなと思っております。
既存のフォルダをリモートリポジトリにプッシュしたかった

# 概要
リモートでリポジトリを作成しクローンする形であれば非常に簡単ですが、
既存のフォルダをGit管理下に置き、そのローカルリポジトリをリモートにPushする方法が自分にはややこしいかったのでまとめておきます。

# 環境
- Mac
- iTerm2 or SourceTree
- Bitbucket

# ローカルリポジトリを作成する

まずは既存のフォルダをGitの管理下に置きます。
```
$ git init
$ git add .  (git add.ではない！　addと.の間に半角スペース入れてね！)
$ git commit -m 'コミット内容'
```
これでローカルリポジトリができました。

# リモートリポジトリを作成する

次は各環境でリモートリポジトリを作成します。
私はBitbucketを利用しているので以下の画像のように作成しました。
![スクリーンショット 2022-06-03 11.22.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93737/f18da9d7-bf1e-3b56-7568-7bc96697e396.png)

# ローカルにリモート先を登録する

#### コンソール
```
$ git remote add origin <url>
```

#### SourceTree
![スクリーンショット 2022-06-03 11.22.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93737/793ab11d-f49e-039b-4aa9-a8bd48549bdd.png)



# リモートの環境をローカルに合流させる

そのままpushしてもエラーとなってしまうのでフェッチとリベースを行います。

#### コンソール
```
$ git pull origin master --rebase
```

#### SourceTree
![スクリーンショット 2022-06-03 11.09.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93737/bf9302f3-8a3f-2427-b002-f98b77f572c9.png)

# headの設定を行う
この手順で作業を行うとorigin/headが付与されない模様
以下のコードで設定を行う。
```
$ git remote set-head origin master
```


# できた！！！
これで合っているのでしょうか？ｗ
とりあえず動くのでこれでいいでしょう！

認識がおかしい、こっちの方がいいぞ等ご指摘待ってます。
よろしくお願いします。
CloudCraftとは

## Cloudcraftとは

CloudCraftは、[CloudCraft　Inc](https://www.cloudcraft.co/ "CloudCraft") が提供しているダイアグラム作成（作図）製品です。

### CloudCraftの機能一覧
:::note info
ドラッグ&度ラップによる操作

　様々なオブジェクトをダイアグラム上へ配置し、組織図などを簡単に編集できる
:::

:::note info
テンプレート

　各種フローチャートなどのテンプレートを利用して、効率的に図を作成できる
:::

:::note info
ダッシュボード

　全ての図を一元管理するダッシュボードを提供し、チームで利用するパーツなどを共有フォルダで管理できる
:::

:::note info
ファイルのインポート・エクスポート

  他の作図ツールから図形ファイルをインポートしたり、作成した図をPDF、画像、ベクター形式などのファイルとしてエクスポートしたりできる
:::

:::note info
変更履歴

　変更履歴を保存し、改訂前のバージョンに戻したり、参照したりできる
:::
【linux】.sh実行結果をログファイル出力する(特にpython系)

# 結論

リリースを始める前に下記のコマンドを流す

```bash
script -f >(awk '{print strftime("%F %T ") $0}; system("")' >> operation_log_$(date +%Y%m%d%H).ansi)
```

すると、移行のコマンド結果が時間付きですべてファイルに出力される。

shellの実行結果をログファイル出力する。
リリース時に重宝する。
ターミナルの結果が消えても安心。
Windows Defender ファイアウォールが勝手にONになる件について

とあるシステムでとある理由によりWindows Defender ファイアウォールをOFFにする必要があり、コマンドを使用しOFFに設定した。

```bash
netsh advfirewall set allprofiles state off
```
[コントロールパネル]⇒[Windows Defender ファイアウォール]で確認すると
![コンパネ_FirewallOFF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770621/13b13802-e68b-481f-3527-36d5587ae2cb.png)

良し！OFFになってる！
これで大丈夫だ！！

と思っていました、、、

～数日後～
ログ確認のためにRDPで接続しなきゃ、、、

えっ！？RDP出来ないぞ、端末の電源入ってないのかな

私：あの、＊＊＊の端末を起動して頂きたいんですけど、、、
現場の担当者：え？起動してますよ？
私：ありゃ

といった感じで現地に訪問することになりました。
すると、、、
![コンパネ_FirewallON.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770621/61a4ff68-218e-e720-c1ac-75da4e05704e.png)

FirewallがONになってる！！
コマンドでOFFにするだけじゃダメだったのか、、、

ということでいろいろ調べた結果、グループポリシーエディターで
[コンピューターの構成]⇒[Windows の設定]⇒[セキュリティの設定]⇒[セキュリティが強化されたWindows ファイアウォール]⇒[セキュリティが強化されたWindows ファイアウォール - ローカルグループポリシーオブジェクト]のプロパティからパブリック・ドメイン・プライベートそれぞれの[ファイアウォールの状態]という項目を未構成⇒無効に変更した。
![Local Group Policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770621/9094f7af-8668-c3b6-0dd8-61cf039f331e.png)

![Local Group Policy Tab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770621/b14d1099-9445-f6de-2a7b-e65a685b7419.png)


今のところ大丈夫そうである(￣ー￣)
JSTQB Advanced Levelの価値とメリットは？

## JSTQBとは
Japan Software Testing Qualifications Boardの略で
ソフトウェアテストに関する国際資格です。

現在、日本で受験できる試験は以下の3種類となります。
初級：Foundation Level
上級：Advanced Level テストマネージャ
上級：Advanced Level テストアナリスト

## 難易度について
初級
　基本情報技術者試験と同レベル
　合格率 60％前後
上級
　応用情報技術者試験よりは少し易しい
　合格率 20％前後

## 保有者の人数
おそらく、このような分布になると思われます。
![JSTQBベン図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2443317/0d6c300f-4739-97d2-5ab8-49a8a206c750.png)
現在CBT移行中で、**テストアナリストの試験が開催されていない**ため、
当面、保有者の数が増えることはありません。（2023年2月現在）

公式サイト
https://jstqb.jp/attribute.html


## 企業の認知度は
一般のIT企業にはまだまだ浸透していない感じ。
ソフトウェアテストの資格があること自体を知らないか、
または、そういう資格があることを知っていても、
FoundationとAdvancedの違いまでは知らない様子。

## 面接における反応（実話）
ISTQBグローバルパートナーかつ東証プライム上場のテストベンダー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2443317/75db0d4e-3780-b46a-51e4-38406fe7ec18.png)
正社員1600人に対して、Advanced Level保有者が8名とのこと。
さぞかし高く評価してもらえると思った結果がこちらです。

『私はすでに**Advancedを両方とも保有**しています。（どや！）』
『現在の会社には評価制度がないため、必要とされる会社を探しています。』
　↓
「その資格は、当社における最重点資格となっています。」
「さらに言えば、Advanced保有が部長昇格の条件の1つになっています。」
　↓
（さて、いくらの値段がつくんだろう・・・）

:::note warn
結果
**前職給与＋500円（年収500円アップ）**
:::

## コスパは最悪
テストマネージャ、テストアナリストとも、受験料は22000円なので、
Advancedを2つ取得するには、一発で合格しても44000円かかります。
年収500円アップということは、**元を取るのに勤続88年**という計算になります。

## まとめ
言葉では褒めてもらえましたが、金銭的には**500円の評価**です。
要は、対外的にアピールするために、資格保有者として歓迎はするが
特に資格を持っているからと言って、何ら還元はしないということらしいです。

こんな資格ですが、試しに取ってみたいという人はぜひどうぞ。
jetson AGX Xavier でrealsense D435をRViz2に表示する

# 環境
- Jetson AGX Xavier
- Ubuntu 18.04
- ROS2 Dashing
- Rviz2
# はじめに
<!-- 概要 -->
realsense depth camera D435をrviz2で表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1689380/3cad5b80-02e1-90f1-dbe3-738821d60176.png)


# 目次

1. [インストール](#Chapter1)
1. [エラー内容](#Chapter2)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# インストール
~~~:get code
mkdir -p ~/ros_ws/src
cd ~/ros_ws/src
git clone https://github.com/intel/ros2_intel_realsense.git
~~~

~~~:build
cd ~/ros_ws
source /opt/ros/dashing/setup.bash
colcon build --base-paths src/ros2_intel_realsense
~~~


<a id="#Chapter2"></a>
# 動作確認
~~~
source /opt/ros/dashing/setup.bash
source ~/ros_ws/install/local_setup.bash
~~~
コンソールを2つ立ち上げてそれぞれに下記のコマンドを入力
~~~:console1
ros2 run rviz2 rviz2 -d ~/ros2_ws/src/ros2_intel_realsense/realsense_ros2_camera/rviz/ros2.rviz
~~~
~~~:console2
ros2 run realsense_ros2_camera realsense_ros2_camera
~~~
![Screenshot from 2022-06-03 10-50-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1689380/e569c9c2-a48e-b40f-beda-7294f62d64f5.png)

## 既知の問題点
~~~
[WARN] [RealSenseCameraNode]: Given stream configuration is not supported by the device!
~~~
このような表示が出る場合はUSBケーブルが3.1のケーブルになっていない
ubuntuのディストリビューションは18.04が最後になりそう


<a id="#reference"></a>
# 参考文献
- [https://github.com/intel/ros2_intel_realsense ](https://github.com/intel/ros2_intel_realsense)
SQLサーバインストール手順について

# はじめに

“エンジニアファーストの会社　株式会社CRE-CO”のクワバラと申します。

常駐先でSQLサーバのインストールが必要になり、今回無料版を使ってインストールをしてみたいと思っています:point_up:

このSQLサーバを使って、今後いろんな設定等試していければ技術力・経験値が上がったと言えるのではないでしょうか:tongue:

それでは、レッツゴー！！

### 手順
##### 1 以下ダウンロードURL先からSQLサーバのダウンロード行う
・開発者：今すぐダウンロードするを選択する。
 [SQL Server ダウンロード先](https://www.microsoft.com/ja-jp/sql-server/sql-server-downloads)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/7edde0d7-d61b-5564-5332-20bdb26fc2fe.png)

※今回は練習用のため「SQL Server 2019 Developer エディション」をダウンロードします。

##### 2 インストール
・今回は開発用のため、「基本（B）」を選択する
・ライセンス条項に同意する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/f1108ccd-7a45-3835-5be8-ff73af7c8028.png)
・インストール先の選択を行いインストールを行う（今回はCドライブを圧迫したくないためDドライブに入れてみる。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/d93892e2-5332-58a3-c384-25b4e42ef5e6.png)
・ダウンロードを待つ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/c1e44f74-ec01-14f2-4698-f75c956c88b1.png)
・インストール完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/c94671ec-bddf-fd85-11e0-96a2a7fb3b98.png)

### 番外編
今回はSQLサーバのすべてのコンポーネントのアクセス、設定、管理、運用、開発を統合環境であるSSMSもインストールしてみます。
[SSMSのダウンロード先](https://docs.microsoft.com/ja-jp/sql/ssms/download-sql-server-management-studio-ssms?redirectedfrom=MSDN&view=sql-server-ver16)
・上記URL先から使用できる言語「日本語」を選択しダウンロードを行う
※ここで「SQL Server Management Studio (SSMS) 18.11.1 の無料ダウンロード」をインストールしてしまうと日本語化できないため注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/d9c27088-673b-3fd1-672c-db4010b9dd36.png)
・ダウンロードファイルを開きダウンロード先を指定し、「インストール」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/d344f11b-4aa3-6fd4-a5d2-4b03ea040a45.png)
・ダウンロードを待つ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/291f3baf-9a68-06f6-8ba9-bd59c06e8f24.png)
・インストール完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576052/657ffc51-1006-0694-2a5a-045506847575.png)

# おわりに
今回は常駐先で悩んでいたSQLサーバのインストールについて触れてみました。
導入自体は思ったよりも簡単でその後の設定が難しいのだろうと想像がつきました。。。
次回は推奨設定に従って設定等行えたら良いかなと考えています！

以上、クワバラによる「SQLサーバインストール手順について」でした！
AWS-CDK pipelinesでCloudFormation templateが一定のサイズを超えるとエラーになる

aws-cdkの以下issueで言及されている内容で、かなり前から話題になっているようです。

https://github.com/aws/aws-cdk/issues/12372

### 事象
CDKに機能追加をして、生成されるテンプレートが一定のサイズを超えると、以下のようなエラーが発生しました。
```
Template format error: YAML not well-formed. (line 2528, column 49) (Service: AmazonCloudFormation; Status Code: 400; Error Code: ValidationError
```
手元の環境では51KBまでは問題なく、それを超えるとエラーになるようでした。
エラーメッセージの`line`が指しているのはファイルの末端箇所で、そこが特段変わっているような感じはありません。
以下のコメントで言われている通りです。

https://github.com/aws/aws-cdk/issues/12372#issuecomment-797494427

### 環境
* 言語
python3.8
* aws-cdkのライブラリ
1.158.0
* CDK-CLI
2.26.0
* Node.js
16.15.1

### 試したこと
#### 追加したものが悪さをしているわけではない
元あったものを少し減らして、追加したいものを入れても51KB以内になるようにすれば、エラーは発生しない
#### 生成されたtemplateに対して`aws cloudformation validate-template`をしても、エラーは発生しない
具体的には以下の手順です。
* 該当のCodeBuildの
`ビルドの詳細 -> アーティファクト -> アーティファクトのアップロード先`
でS3に出力されているartifactが確認できるので、ダウンロードします。
デフォルトだと、KMS keyの権限エラーになる可能性があるので、該当S3ファイルの
`プロパティ -> サーバ側の暗号化設定 -> AWS KMS キー ARN`
からKMS キーポリシーを編集し、`Principal`に自分のアカウントを追加します。
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::xxx:root"
                ]
            },
            "Action": [
```
* ダウンロードしたファイルを解凍し、中にあるjsonファイルを任意のS3上にアップロードした上で以下コマンドを実行
```
aws cloudformation validate-template --template-url https://xxxxxx.s3.ap-northeast-1.amazonaws.com/hoge/fuga.template.json 
```

#### 生成されたtemplate自体はCFnで問題なく実行できる
上記で取得したtemplateファイルを使って、新たに別スタックで実行することはできるので、
手間ですが意図していたリソースをデプロイすることは可能です。

### エラーの回避方法
issueの中にも記載がありますが、特殊文字とファイルサイズの組み合わせがエラーを引き起こしているようです。
自分の場合は、APIGatewayのDesctiptionの中に日本語の文字を使っていたので、
それを全て1バイト文字にするとエラーが発生しなくなりました。

### まとめ
マルチバイトの文字を使わなければ問題は無さそうですが、修正されると良いなと思い、
自分もissueにコメントしておきました。

https://github.com/aws/aws-cdk/issues/12372#issuecomment-1144754156
Laravel 上で CSV を作成して保存する

# はじめに

仕事で Laravel 内でcsv を生成するコードを作成したのでその上で知ったことに関して備忘録代わりにこちらで記載しておきます。

# 保存場所の検討

Laravel のコードは当然ながら PHP で動いているので、ファイルを生成するのであれば、```fopen((パス), (オプション))``` を用いることになります。
（fopen から fclose までの一般的なファイル生成手法に関してはこの記事では割愛しますので、気になる方は各自お調べください）

この時、
```response()->streamDownload($callback, $filename, $header)```
のようなファイルを生成したそばからレスポンスとして返すような場合は、$callback に渡すクロージャ内で```fopen('php://output', 'w')```と
ファイルのパスを設定すれば問題ありません。

しかし、生成を行って一度保存する場合、その保存先を用意するにあたって気を付けるべき項目が存在します。

例えば、 **/storage/app/csv/{users.id}** といったディレクトリに保存しようとした場合、すぐに

```php
$path = storage_path() . '/app/csv/' . $user->id . '/' . $filename;
$stream = fopen($path, 'w');
```

といった形でストリームを開きたくなりますが、実際のディレクトリの状況を考慮しないと、該当するディレクトリが存在しない、権限が違って開けないなどの問題が生じます。

そのため、気を付けるべきことの一点目は **先にディレクトリを作成しておく** です。

## ディレクトリの作成（その１）

実際のディレクトリ生成の手段としては、２通り存在し、１つ目は **mkdir()** を用いるパターンです。

mkdir() は php 側のメソッドで、指定されたディレクトリを作成するメソッドです。

このメソッドは以下の２点に気を付ける必要があります。
１：存在しないディレクトリに対してディレクトリを作ろうとすると warning が発生する
２：既に指定のディレクトリが存在する場合も warning が発生する

上記を考慮する関係で、ファイルやディレクトリの存在を確認できる **file_exists()** を用いて以下の様な実装を行う必要が存在します。

```php
$storagePath = storage_path();
if(!file_exists($storagePath . '/app/csv')) {
    mkdir($storagePath . '/app/csv');
}
if(!file_exists($storagePath . '/app/csv/' . $user->id)) {
    mkdir($storagePath . '/app/csv/' . $user->id);
}
```

上記のコードを見てわかる通り、存在が不確かなディレクトリを上から１つ１つ存在を確認し、生成していく形になります。

## ディレクトリの作成（その２）

２つ目ファイル生成の手法は **Storage::makeDirectory()** を用いるパターンです。

Storage::makeDirectory() は Laravel 側のファサードに紐づくメソッドで、指定されたディレクトリを作成するメソッドです。

このメソッドは mkdir() と違って途中のディレクトリが存在しない場合や既に存在するディレクトリを指定した場合も問題なく実行できます。

しかし、Storage::makeDirectory() が Laravel 側のメソッドである関係上、php や laravel の設定次第では、生成されたディレクトリの作成者が mkdir() とは異なることがあります。この場合、fopen() でファイル作成が行われる関係上、ファイルの作成ができないといったパーミッションエラーが発生することがあります。

もしも Storage::makeDirectory() でディレクトリを生成したのちにファイルの生成ができないパーミッションエラーが発生した場合、以下の様な対応で解決できるかと思います。
・ディレクトリの権限を書き換える
・Storage::makeDirectory() での作成者が同じになるように設定を調整する
・Storage::makeDirectory() をやめて fopen() と同じ php 側の mkdir() を使う

# 文字コードの検討

ここまではディレクトリの検討に関して記載してきましたが、続いて CSV として検討すべき事項としては文字コードの問題があります。

基本的に、特に指定をせずに```fwrite()```や```fputcsv()```を行うと、 **UTF-8** で記載されます。

しかし、今回の対象が CSV であることを前提にすると、windows 環境では excel で扱われることが容易に想像でき、単なる UTF-8 の CSV を excel で開くと、2バイト文字は見事に文字化けしてしまいます。

そのため、excel でも対応できるような対策を講じる必要があるわけですが、対策としては主に２つの方法が存在します。

## 文字コードの対応（その１）

１つ目の対応方法は、excel が想定している文字コードである **Shift-JIS** に変換する方法です。

PHP において文字コードは ```mb_convert_variables()``` で変数単位で変換ができ、以下の様に扱います。

```php
$csv = ['ID', '名前', '作成日時'];
mb_convert_variables('SJIS-win', 'UTF-8', $csv);
```

mb_convert_variables() を扱う注意点として、第３引数には変数のみが入れられるので、配列等の値を変数に入れずにそのまま入れた場合はエラーとなります。

この方法に関しては excel の想定している文字コードに変換していますが、一方で mac などの他の環境で Shift-JIS 対応が出来ていない環境に CSV が渡されることが想定される場合、かえって面倒なファイル生成となります。

その場合は次に紹介する方法の方がより良い対応かと思います。

## 文字コードの対応（その２）

２つ目の対応方法は、単なる **UTF-8** ではなく、 **BOM付きUTF-8** にするパターンです。

BOM付きUTF-8 にすることで UTF-8 のままでありながら、excel にも UTF-8 としても文字コード解釈を認識させることができます。

BOM付きUTF-8 にする方法としては、fopen 直後のファイルのまだ何も記載されていない先頭に対して、

```php
fwrite($stream, pack('C*', 0xEF, 0xBB, 0xBF));
```

を実行する方法があります。

この方法を実行した上であとは従来の内容を文字コードを変換せずに記載することで、BOM付きUTF-8 である csv となります。
よく使う正規表現

よく使う正規表現

◆改行
\r\n	CRLF
\r	CR（キャリッジリターン）
\n	LF（ラインフィールド）

◆タブ
\t


◆行頭
^

◆行末
$

◆文字列の最初
\A

◆文字列の最後
\Z
【PostgreSQL】RDS (AWS) で 既存の DB を C ロケールで作り直す方法

# はじめに
AWS で RDS の DB を作成すると、デフォルトで作成できる DB の環境は、"lc_collate" と "lc_ctype" が C になってない。(GUI でポチポチ作成した場合)
その為、名前 (カナ) 列とかを昇順ソートすると思い通りのソートにならない!!
C ロケール DB の作成方法と、すでにデータがある場合のデータ移行コマンド (ダンプとリストア) を記載します。
※既存の DB のロケールを C にしたいと思いますが、できないようです……

#### 下記の環境を想定しています
```
- RDS(AWS)
- PostgreSQL 13
- ssh 接続で RDS を操作
```

# もくじ
- ロケール状態確認
- PostgreSQL インストール
- RDS 接続確認
- ダンプ
- DB 作成
- リストア
- リネーム


## ロケール状態確認
現在の状態を確認するコマンド
うちの DB に限って…と思ったときに a5mk2 とかで実行
lc_ctype や lc_collate は何になっていますか…
```
SELECT name, setting, context FROM pg_settings WHERE name LIKE 'lc%';
```

## PostgreSQL インストール
ここからが本題
インストール前にこちらを実行
```
sudo apt-get update
```
SQL コマンドを使うために、PostgreSQL をインストール
```
sudo apt-get install -y postgresql-13
```

## RDS 接続確認
```
psql \
   --host=RDSで作成したPostgreSQLのDNS名 \
   --port=RDSで作成したPostgreSQLポート番号 \
   --username=RDSで作成したPostgreSQLのユーザー名 \
   --dbname=RDSで作成したPostgreSQLのDB名
```

## ダンプ
デフォルトの DB にデータが入ってて、移行させたい場合、ダンプを取得する
※今現在いる場所に出力されます
　場所の確認するコマンド pwd
　実行する際は、psql から切断しておいてください。コマンドは ¥q
```
pg_dump \
   --host=RDSで作成したPostgreSQLのDNS名 \
   --port=RDSで作成したPostgreSQLポート番号 \
   --username=RDSで作成したPostgreSQLのユーザー名 \
   --dbname=RDSで作成したPostgreSQLのDB名 \
   > my_dump.pgdump
```

## DB 作成
C ロケールのデータベース作成
※実行する際は、RDS 接続確認 の psql 接続をしてください
```
create database 新しく作るDB名 lc_collate='C' lc_ctype='C' template template0;
```

## リストア
新しく作成した DB に、旧 DB のデータを反映させる
※ダンプを取得した場所で実行してください
　実行する際は、psql から切断しておいてください
```
psql \
   --host=RDSで作成したPostgreSQLのDNS名 \
   --port=RDSで作成したPostgreSQLポート番号 \
   --username=RDSで作成したPostgreSQLのユーザー名 \
   --dbname=新しく作ったDB名 \
   < my_dump.pgdump
```

## リネーム
旧 DB 名がベストだった場合
新 DB 名を "旧DB名2" とかでとりあえず作成した方へ

まずは旧 DB を削除するコマンド
```
DROP DATABASE 旧DB名;
```
そしてリネーム
```
ALTER DATABASE 新DB名 RENAME TO 旧DB名;
```

# おわりに
実装してテストして最終段階の時にあれ？ソートおかしくない？
ってなることありますよね…
……普通もっと早く気づきますかね…

# 参考文献
[ロケール(国際化と地域化)](https://lets.postgresql.jp/documents/technical/text-processing/2)
テックキャンプを受講した感想

# 私の簡単な経歴
元々私は2020年に会社員として入社し、半年で退社。
その後、スポーツジムにて2社アルバイトとして勤務しており、約1年間フリーターとして生きておりました。
コロナ禍のこともあり、思ったようにシフトに入ることができず、収入に不安があり、スポーツジムを退社。
これからどうするかを家族と相談した結果、現在需要が高まりつつあるITエンジニアに就職したいと伝え、2022年2月にテックキャンプに入学。4月に卒業後、転職活動を行って無事内定をもらい、7月に入社することになりました。

# なぜテックキャンプを受講しようと思ったのか？
プログラミングスクールはテックキャンプ以外にもあるのに、なぜテックキャンプを選んだのか。理由としては2点あります。
1つ目は、ずっと前からYouTubeで **マコなり社長の動画を見ており、もしプログラミングスクールを通うなら、テックキャンプがいい** と考えていたためです。
2点目は、1日10時間プログラミングをする密度の濃さに魅力を感じたためです。
以上の2点の理由からテックキャンプに受講しようと決意しました。

# テックキャンプで大変だったこと
細かい内容を記述することはできませんが、まず大変だったのは**プログラミングができるようにパソコンの環境を作っていく**ことです。
個人的にはすぐにプログラミングできると思っていたのですが、まずはプログラミングができるように環境を作らないといけないことに衝撃を受けました。必要なツールのインストールにかかる時間と環境構築の難しさもあり、**「最後までできるのか...?」** とかなり不安でした。
しかし、プログラミングができるように環境ができたら、あとはひたすらプログラミングをしていくだけですので最初の環境構築だけが大変でした。

# 仲間の大切さを知った
テックキャンプではチームで学習を進めていきます。基本的に個人で学習を進めていきますが、ただ学習するだけでなく、**自分が学習したことをチームにアウトプットしてより学習内容の理解を深めていくようになっています。それだけでなく、メンターに質問しにくいことを聞けたり、良い情報を得たときに共有できます**。
この点は他のプログラミングスクールが持ってない、**テックキャンプならではの強み**だと思います。
実際、私もチームの皆さんに良い刺激をもらったり、転職活動でも情報の共有をしていただいたこともあり、転職活動でも、良いモチベーションを維持したまま取り組むことができました。

# テックキャンプを受講して思ったこと
結論から言うと「テックキャンプに受講して本当によかった」と思います。理由は3つあります。
1つ目は、**仲間と一緒にプログラミングと転職活動に取り組めたため**です。
転職活動は1人で行いですが、テックキャンプを卒業してからもチームと一緒に情報の共有や、面接でやらかしたエピソードを聞けたりしましたので、それが励みになりました。

2つ目は、**ライフコーチとキャリアアドバイザーの存在**です。
テックキャンプ受講中はライフコーチと定期的に面談を設けてくださるので、親身になって話を聞いてくれたり、背中を押してくれるように励ましてくれました。
おかげさまで、学習期間中は高いモチベーションで取り組めました。
キャリアアドバイザーは転職活動の身近な相談役で、履歴書や職務経歴書・面接練習など、転職が成功できるように一緒に取り組んでいただいてとてもありがたかったです。

3つ目は**カリキュラムの内容がとても分かりやすかったから**です。
テックキャンプを卒業後、新しい言語を学ぶために参考本を購入して学習していますが、今でも思うのはテックキャンプのカリキュラムの内容が分かりやすいことです。
ここまで、分かりやすく説明できるのはテックキャンプの他にあるのかと思うほどです。
これは実際に受講していただくとわかると思いますので詳しい内容は割愛します。

# これからテックキャンプを受講しようと考えている方へ
私個人としては是非お勧めしたいのですが、**未経験からの転職なので就職のハードルは高い**です。そのため、覚悟を決めて受講する方がよいと思います。
しかし、**2週間はお試しで学習でき、無理と判断した場合は全額返金できる**そうなのでまずは受けてみてそこから判断しても良いかと思います。
【自分用備忘録】res.status().json と res.status().send の違い

初めまして。hojojoです。

Expressを触っていて、

res.status().json
res.status().send

の違いが分からなくなってきたので整理してみました。

以下の記事を見つけたのですが、結果は変わらないのでやっぱり同じっぽいですね。

https://neos21.net/blog/2019/03/12-01.html

じゃあ、好きは法を使えばいいよね！
だと納得いかなかったので、知り合いに聞いてみたら

・　res.send()はjson形式のデータではない簡単な文字列を返すときに使っている
・　res.json()はjson形式データを返す際に、明示的に分かりやすくするために使っている
・　apiを作る際はほとんどres.json()を使っている

だそうです。なるほど。
もし違う使い分けをされている方がいれば、コメント欄で教えてください。
符号拡張（C言語）

符号付き16ビット整数と、符号なし16ビット整数についての符号拡張を考える（『独習C』第2章）。

```C
#include <stdio.h>
#include <stdint.h>

int main()
{
	int32_t i32 = -10;
	int16_t i16 = i32;
	uint16_t u16 = i32;

	i32 = i16;
	printf("%i\n", i32);  // => -10

	i32 = u16;
	printf("%i\n", i32);  // => 65526
}
```

まず、符号付き32ビット整数`i32`を-10=1111 1111 1111 1111 1111 1111 1111 0110で初期化する。

その後、この32ビット整数を16ビットの`i16`と`u16`に代入している。

すると、`i16`と`u16`の両方には、**上位32ビットが切り捨てられた1111 1111 1111 0110**が代入される。

```c
i32 = i16;
printf("%i\n", i32);  // => -10
```

符号付き16ビットの`i16`（= 1111 1111 1111 0110）が、32ビットへ符号拡張される。

`i16`は”符号付き”なので、拡張する際は**値1で拡張**される。つまり`i32`に**1111 1111 1111 1111 1111 1111 1111 0110**が代入れる。

それで、`printf`してやると-10という結果になる。

```c
i32 = u16;
printf("%i\n", i32)  // => 65526
```

符号なし`u16`（= 1111 1111 1111 0110）が32ビットへ符号拡張される。

”符号なし”なので、拡張する際は**値0で拡張**される。つまり`i32`に**0000 0000 0000 0000 111 1111 1111 0110**が代入される。

それで`printf`してやると65526という結果になる。
Python 3.10 のwithステートメントで複数のオブジェクトを扱う

# Python 3.10 での `with` ステートメントに関する仕様変更

Pythonで `open()` 関数等と併用される `with` ステートメントは、カンマ区切りで指定することにより複数のオブジェクトを扱うことができる。（Python 3.1 以降）

```python
with open("file1.txt", mode="w") as f1, open("file2.txt", mode="w") as f2:
    f1.write("This is file1")
    f2.write("This is file2")
```

Python 3.10 では、括弧で囲うことで複数行にまたがって書けるようになった。

```python
with (
    open("file1.txt", mode="w") as f1,
    open("file2.txt", mode="w") as f2,
):
    f1.write("This is file1")
    f2.write("This is file2")
```

公式ドキュメントにも Python 3.10 で対応したことが明記されている。

> バージョン 3.10 で変更: Support for using grouping parentheses to break the statement in multiple lines.
>
> [8. 複合文 (compound statement) — Python 3.10.4 ドキュメント](https://docs.python.org/ja/3.10/reference/compound_stmts.html#the-with-statement)

:::note
公式ドキュメントには Python 3.10 でサポートとあるが、実際には言語パーサーが更新された Python 3.9 以降で動作する。括弧による記述に対応していない Python 3.8 以前では、バックスラッシュ `\` による行の継続で複数行の記述ができる。
:::

括弧が使用できるメリットは、バックスラッシュによる行継続に頼らない記述が可能であること、[Black](https://black.readthedocs.io/en/stable/#) 等のフォーマッタを利用した際にうまく自動整形されること、などがある。

# 参考文献

https://www.python.jp/news/wnpython310/with-statement.html

https://atmarkit.itmedia.co.jp/ait/articles/2110/12/news024.html
webpackについて

webpackのドキュメントをまとめます。
参照：https://webpack.js.org/concepts/

# 概念
webpackはエントリポイントから、プロジェクトに必要なすべてのモジュールをバンドルに結合する。
##### コアコンセプト
- エントリ
- アウトプット
- ローダー
- プラグイン
- モード
- ブラウザの相互性

### エントリ
エントリポイントはwebpackが構築を開始するモジュールのことを指す。エントリポイントは依存する他のモジュールやライブラリを把握する。
エントリー・プロパティーを設定することで（複数の）エントリーポイントを指定できる。
entryを設定していない場合、webpackは
./src/index.jsを./dist/main.jsに出力する。
```typescript:webpack.config.js
module.exports = {
  entry: './path/to/my/entry/file.js',
};
```
### アウトプット
アウトプット・プロパティーはwebpackが作成するバンドルをどこで発行するか、および、これらのファイルの命名方法を設定します。
メインファイルの場合は、./dist/main.js
その他のファイルは、./dist
に設定される。
```typescript:webpack.config.js
const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
  },
};
```
const path = require('path');はファイルパスを操作するモジュールです。

### ローダー
webpackはjavascriptファイルとJSONファイルしか認識しない。
ローダーを使用すると、他の種類のファイルをアプリケーションで使用できるモジュールに変換して追加できる。
ローダーのプロパティ
- test: 変換するファイルと識別する
- use: 変換を行うために使用するローダーを示す。
```typescript:webpack.config.js
const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
};
```

### プラグイン
プラグインを使用するには、プラグインに追加する。
ほとんどのプラグインはオプションを使用してカスタマイズできる。
```typescript:webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); //to access built-in plugins

module.exports = {
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};
```

### モード
パラメーターに設定することで、webpackの組み込み最適化を有効にできる。
```typescript:webpack.config.js
module.exports = {
  mode: 'production',
};
```

### ブラウザの相互性
Webpackは、ES5に準拠したすべてのブラウザをサポートする。（IE8以下はサポートされていない）
import()とrequire.ensure()を使う場合、古いブラウザではPromiseを読み込む必要がある。

### 複数のエントリポイントを別ファイルに振り分ける。
複数のエントリポイントを設定したい場合はパラメータや[name]を使う。
```typescript:NG
module.exports = {
  entry: [
    './src/js/entry_1.js',
    './src/js/entry_2.js',
  ],
  output: {
    filename: '[name].bundle.js',
    path: __dirname + '/dist'
  }
};
```
↑entryにエントリーポイント名がないので、エントリーポイント名[name]が「main」になる。
```typescript:OK
module.exports = {
  entry: [
    entry_1: './src/js/entry_1.js',
    entry_2: './src/js/entry_2.js',
  ],
  output: {
    filename: '[name].bundle.js',
    path: __dirname + '/dist'
  }
};
```

### その他
webpack.config.jsは下から実行される。
ruleなど書く順番に注意。

# 参考にした記事
https://qiita.com/sansaisoba/items/921438a19cbf5a31ec53