OmniAICreator/Qiita-1.07M huggingface dataset:
[C++] C++でマルチスレッドする

# もくじ

https://tera1707.com/entry/2022/02/06/144447

# やりたいこと

最近のC++では、マルチスレッドで処理を行うときに、処理の中身をラムダ式で書けたりするらしい。試したい。

# サンプルプログラム

```cpp
#include <thread>
#include "framework.h"
#include "WindowsProject1.h"
#include "resource.h"

// グローバル変数:
HINSTANCE hInst;                                // 現在のインターフェイス

// このコード モジュールに含まれる関数の宣言を転送します:
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    hInst = hInstance;

    DialogBox(hInst, L"MyTestDlgBase_Main", NULL, (DLGPROC)MyDlgProc);

    return (int)0;
}

// スレッド終了フラグ
int threadStop = !0;

// スレッドAの処理
void ThreadA()
{
    OutputDebugString(L"+ スレッドA開始\r\n");

    while (!threadStop)
    {
        OutputDebugString(L"  スレッドA実行中...\r\n");
        Sleep(500);
    }

    OutputDebugString(L"- スレッドA終了\r\n");
}


// 参考
// スレッド終了時にはjoin()で待たないといけないのはここを見て気づいた
// https://qiita.com/kaoru/items/7de0399b11f83241687c
// ラムダでの書き方
// https://qiita.com/termoshtt/items/d3cb7fe226cdd498d2ef
BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
    static std::thread th_a;
    static std::thread th_b;

    switch (msg) {
    case WM_COMMAND:
        switch (LOWORD(wp)) {
        case IDOK:
            EndDialog(hDlg, IDOK);
            return TRUE;
        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL);
            return TRUE;

        case IDC_BUTTON1:
            if (threadStop != 0)
            {
                // スレッドA,Bの終了フラグをクリア
                threadStop = 0;

                // スレッドA開始
                th_a = std::thread(ThreadA);

                // スレッドB開始
                int param = 0;
                th_b = std::thread([&param]{
                            OutputDebugString(L"+ スレッドB開始\r\n");

                            while (!threadStop)
                            {
                                OutputDebugString(L"  スレッドB実行中...\r\n");
                                Sleep(1000);
                            }

                            OutputDebugString(L"- スレッドB終了\r\n");
                        });
            }
            else
            {
                // スレッドA,Bの終了フラグをON(スレッドを終わらせる)
                threadStop = !0;

                // スレッド終了時にはjoinで終わるのを待たないと、異常終了してしまう(Abort)
                th_a.join();
                th_b.join();
            }
            break;
        }
        return FALSE;

    case WM_CLOSE:
        threadStop = !0;
        th_a.join();
        th_b.join();
        break;
    }
    return FALSE;
}

```

# 引っかかった点

### スレッドが終わりきってないときにexeが終了すると、エラーが起きてしまう。

なので、スレッドが終わるまで待ってからプログラム終了するようにする。
スレッドが終わるのをまつため、`th_a.join();`を使ってスレッドが終わるまで待つ。

### std::thread th_a = std::thread(ThreadA);と書くと、その時点からスレッドが走り出す

`std::thread`のobjectだけ先に作っておいて、後で好きな時にstartさせたかったが、`std::thread th_a = std::thread(ThreadA);`とかくと、その時点からすぐにスレッドが走り出してしまう。

まずは`std::thread th_a;`で宣言だけしておいて、スタートさせたいところで`th_a = std::thread(ThreadA);`をすればOK。
読書メモ_完全SIer脱出マニュアル

# 感想
SIerの自分には刺さる話だった
とりあえずQiitaのアカウントを作って何でもいいからアウトプットしてみようと思えた。
→やってみた


# メモ
## １章 なぜ「 エンジニア」 は SIerを去るのか
仕事が楽しいと友人に自信をもって言える

一般的なSIerの開発現場では、モダンで標準的な技術の採用を顧客と合意するのが 難しい
工数 見積もりの世界では、生産性を上げると売上が下がるので、優秀な人が評価されにくい


・転職理由をポジティブに言い換える
個人としてより高い生産性を求められる環境で、自分を試してみたくなった
生産性が高くモダンな技術や開発手法を使った汎用性のあるスキルを身につけたかった
活気のある職場で、新しい価値を社会に届けるような仕事がしたかった

# 2章
「IT企業」「エンジニア」という言葉の実態は多様
【FactoryBot】create_listで複数のインスタンスの配列を作成する【RSpec】

### はじめに
先日、RSpecでテストを書いていた際に、テストデータをまとめて作成したいなーと思って調べたので、ご参考になれば。
### create_listメソッドとは
create_listメソッドとは、ファクトリに定義しているテストデータを、配列としてまとめて取得することができます。
### 使い方

```rb:spec/factories/tasks.rb
FactoryBot.define do
  factory :article do
    sequence(:title, "title_1")
    sentence { "sentence" }
    status { :todo }
    association :user
  end
end
```

ファクトリに上記のような定義がある場合、
例えば、3つのarticleインスタンスの入ったテストデータがほしいとき、下記のように定義することで取得できます。

```rb:
articles = create_list(:article, 3)　#変数articlesに3つのtaskインスタンスの配列が入っている
```

また、明示的に値を渡したりトレイトを使うことで、特定のカラムを上書きすることもできます。

```rb:
articles = create_list(:article, 3, :doing, title: 'new_title')
# :doingはtrait、titleは上書き
```

つまり、抽象化するとこんな感じです↓

```rb:
create_list(<ファクトリ名>, <インスタンスの数>, <traitや上書きしたい項目>)
#戻り値は配列
```


### 参考

[factory_bot - create_listメソッドの使い方](https://forest-valley17.hatenablog.com/entry/2018/09/29/151009)

※間違いなどあればコメントください！
GitHub ReleasesをSlackチャネルで受け取る

## 方法

任意のチャネルで下記メッセージを投稿する。

```sh
/feed https://github.com/<owner_name>/<repository_name>/releases.atom
```

## 参考

- [GitHub と Slack を連携させる | Slack](https://slack.com/intl/ja-jp/help/articles/232289568-GitHub-%E3%81%A8-Slack-%E3%82%92%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%8B)
- [Subscribe to releases · Issue #397 · integrations/slack](https://github.com/integrations/slack/issues/397)
[ネタ]ノイズキャンセリングの原理を最速で体験する


#はじめに
イヤホンの中には、ノイズキャンセリング（アクティブノイズキャンセリング）という「ノイズとなる音を打ち消すことで外部の音に邪魔されずによりクリアに音楽を楽しむことのできる
機能」がついているものがあります。私はAirPods Proを使っているので日頃よくお世話になっている機能です。

この先端技術的な感覚を覚えるノイズキャンセリング機能ですが、原理としては意外と単純なものであったりします。「**逆位相**」とか「**波の重ね合わせ**」とか聞いたことがあるのではないでしょうか。今回はこのノイズキャンセリングの仕組みを簡単に説明し、さらにそれを手軽に体験する方法についてまとめます。

#ノイズキャンセリングの原理
最速で体験したい方はここは読み飛ばして次の項目に進んでください。
音というのは空気の振動であることはご存知だと思います。音は空気などの媒質を疎の部分と密な部分が連なって進行する縦波です。この波が鼓膜に伝わることで私たちは音を聞くという行為が成り立っています。

ここで以下のような波形の音楽があったとします。![スクリーンショット 2021-04-22 17.56.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/8d69d28a-ec94-442c-6f9c-44126b567f82.png)



このままの音を聞くことができれば良いのですが、実際には外部の騒音などが要因となりノイズが加わってしまいます。
![スクリーンショット 2021-04-22 18.00.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/bed61975-eea3-72ad-1713-da5ea17a39ea.png)

ノイズが加わると音楽は以下のような波形として聞こえてくるようになってしまいます。
![スクリーンショット 2021-04-22 19.13.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/da7cd2f2-3066-1c1c-6bf6-ad771be70bbd.png)


じゃあどうすれば、元のクリアな音楽の波形に戻すことができるのか。
**足されたならその分引けばよくね？**
というのがノイズキャンセリングの簡単な考え方です。

![スクリーンショット 2021-04-22 21.04.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/639a2dc3-1c32-c0fe-1e8d-489571b66aaf.png)

実際にはA-B = A+(-B)の考え方で、ノイズの位相を反転させたもの(**逆位相**)を足すことで元の音楽の波形に近づけるということになります。

![スクリーンショット 2021-04-22 21.25.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/dd3ab148-0bd5-6333-6879-e570b9c93df6.png)


ノイズをどのように取得するかについてですが、イヤホンの外側についてあるマイクで取得したり、内側のマイクでノイズ＋音楽として取得するなど様々な方式があるようです。

#ノイズキャンセリングの原理を体感する
ここまで少し長くなりましたがようやく本題に入ります。
使用するのは`Audacity`というアプリです。Mac版もWin版もあります。

##1. なんでもいいので音声ファイルを用意
用意してください。

##2. 音声ファイルをインポート
音声ファイルを`Audacity`にインポートします。ドラッグ&ドロップで大丈夫です
![スクリーンショット 2021-04-22 21.47.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/d3191a54-15d7-ae3a-dc89-fa84bb59ab9a.png)

##3. トラックを複製
2により生成されたトラックをコピー&ペーストで複製します。普通にもう一度ドラッグ&ドロップでインポートするのでも大丈夫です。
![スクリーンショット 2021-04-22 21.51.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/51038137-be15-987e-9b18-d52d93659c66.png)

##4.位相を反転
片方のトラックを選択して位相を反転させます。`エフェクト`から`上下を反転`を選択すれば大丈夫です
![スクリーンショット 2021-04-22 21.53.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377767/abfcefde-5ee0-a5f9-fa55-c0030d9b0f2c.png)

##5.再生してみる
再生してみましょう。何もおこらない。それで正解です。
再生中も片方のトラックだけミュートにすることができるのでそれも試してみてください。音が鳴ります。

#おわりに
以上です。
もし可能ならボーカル付き音源とオフボーカルの音源を用意して、以上を行うとボーカル音声だけ抽出できるのでより面白いかもしれません。

今回も読んでいただいてありがとうございます。ご指摘ご質問等ございましたらコメント・DMにまでよろしくお願いします。




・
・
・
次回：「Swiftで音声ファイルの位相反転を行う」（予定）
また読んでいただければ嬉しいです。
初心者がラズパイ3 にUbuntu 18.04 server インストール後に気をつける3点

# 記事の目的

Rasberry pi3 で Ubuntu 18.04 serverをインストール後にハマったので共有します
※記事作成は2021年4月

# 忙しい人向け

気をつけることは次の3点です
1. apt upgrade しない
2. 自動アップデートの設定を確認する
3. HDMI は電源を入れる前に挿す

# 1. apt upgrade しない

理由はわかりませんが、これをすると raspberry が起動しなくなります。
電源を入れてもいつまでも緑ランプが点灯しないままです。
理由についてコメントをいただければ幸いです。

## 2. 自動アップデートの設定を確認する

デフォルトのままだと自動アップデートがはいって
apt install がエラーになります。

```
Harissa@ubuntu:~$ sudo apt install gig
E: ロック /var/lib/dpkg/lock-frontend が取得できませんでした - open (11: リソースが一時的に利用できません)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
```

ネット記事でよく見る、ファイル削除をしても apt install できないです。

```
$ sudo rm /var/lib/apt/lists/lock
$ sudo rm /var/lib/dpkg/lock
```


自動アップデート中か確認します。
**apt.systemd.daily update** があればアップデート中です


```
Harissa@ubuntu:~$ ps aux | grep -i apt
root      1464  0.0  0.0   4624   772 ?        Ss   19:08   0:00 /bin/sh /usr/lib/apt/apt.systemd.daily update
root      1484  0.0  0.0   4624  1676 ?        S    19:08   0:00 /bin/sh /usr/lib/apt/apt.systemd.daily lock_is_held update
_apt      2836  0.8  0.1  96912  9432 ?        S    19:09   0:03 /usr/lib/apt/methods/http
abhishek  6172  0.0  0.0  21532  1152 pts/1    S+   19:16   0:00 grep --color=auto -i apt

```

自動アップデートをオフにします。
/etc/apt/apt.conf.d/20auto-upgrades を編集して 1 を　0 にするとオフにします、

```/etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Unattended-Upgrade "0";
```


自分の場合は30分放置してもアップデートが終わらなかったので、急いでる時は自動アップデートをオフにしてもいいかもしれないです


# 3.HDMI は電源を入れる前に挿す

ラズパイ 常連には常識かもしれませんが。
電源入れた後にHDMIを挿してもディスプレイが反応しませんでした。
"100TB"のファイルサーバにあるファイルを断捨離するために(4) ～ツール作成実践編①～

#はじめに
前回は、ZiDOMA dataで取得したCSVファイルの活用方法して
どのような分析レポートを作成するか検討した方法をお伝えしました。

また、実際に試作レポートを作成したときにかかった時間を考えると
CSVファイルから分析レポートを作成するまでに
非常に工数がかかってしまうため、Pythonで自動化するが必要だと考えたとも
お伝えしました。

今回、自動化する流れとして以下の図のように実現しました。

![処理の流れ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/770141/a2e1d34a-a31b-713f-aa27-72e4730d564a.png)

※1 あくまでもイメージです。
※2 ★印の部分が今回の記事の内容になります。

参考：
"100TB"のファイルサーバにあるファイルを断捨離するために(3) ～データ活用検討編～
https://qiita.com/karin_to/items/a2ee0d8332f1151b3b87

※また、前回の記事では今回の記事でデータを処理するためのpandasライブラリを
　ご紹介しますと書きましたが、次回以降の記事でご紹介させていただきます。
　まずは、以下のベースとなる部分をご紹介させていただこうと思います。

#ツール作成の概要
ツール作成の概要は以下の図のようになります。

![処理の流れ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/770141/34203752-eecd-eca7-906a-cdede1e71876.png)

1つ目の項目は、前回のデータ活用検討で採用したレポートをひな型として
Excelを作っておくだけなので、この回では割愛します。

2つ目以降の項目、特に今回はオレンジの枠の部分、
データを処理する前に必要なCSVファイルを読み込み、
Excelのテンプレートファイルを読み込み/保存する部分をご紹介します。
この部分を先に作っておけば、あとは基本的にデータを整理してExcelファイルに
結果を転記していく処理を作りこむだけでよいからです。

#CSVファイルを読み込む
 まずはZiDOMA dataで作成したCSVファイルのデータを読み込む処理が必要となります。
 CSVファイルを読み込む方法はいくつかあるようですが、
 今回ご紹介する方法が個人的に一番簡単でした。
 この2行だけでCSVファイルをすべて読み込むことができました。

```ReadCSV.py
# CSVライブラリを使いますよという宣言
import glob

# 読み込んだCSVのデータを"list_file_summary"に格納します
list_file_summary = glob.glob('data/csv/グラフデータ_*.csv')
```

*(ワイルドカード)を使っておけば、
csvファイルが複数あってもすべてのファイルを読み込むことができます。

# Excelファイルを開く、保存する
　CSVのデータを読み込んだあと、処理した後のデータを記入する
　Excelファイルの読み込み、および保存する処理をご紹介します。

```RunExcel.py
# Excelライブラリを使いますよという宣言
import openpyxl

# -------------------------------------------------------
# 上のCSVファイルを読み込む処理をここに入れればOK！
# -------------------------------------------------------

# Excelで作成したテンプレートの保存先とファイル名を指定する
read_path = 'data/excel/AnalysisSheet.xlsx'

# Excelを開く
ExcelBook = openpyxl.load_workbook(read_path)

# -------------------------------------------------------
# ここにCSVファイルから読み込んだデータを使って
# pandasライブラリでデータを整理し、Excelに書き込んでいきます
# 次回はこの部分を詳しくご紹介します
# -------------------------------------------------------

# 別名保存するために保存先とファイル名を指定する
save_file = 'data/excel/AnalysisSheet_営業部.xlsx'

# エクセルを保存する
ExcelBook.save(save_file)
```
ツール作成の大枠はこれだけで完成です。
次回は、CSVファイル、Excelファイルを読み込んだ後の
データの整理するための処理をご紹介します。

#関連記事:
"100TB"のファイルサーバにあるファイルを断捨離するために(1)
https://qiita.com/karin_to/items/8a375f41de0e4f754cfb

"100TB"のファイルサーバにあるファイルを断捨離するために(2)
https://qiita.com/karin_to/items/7e1dab963e0dc0ba2e9b

"100TB"のファイルサーバにあるファイルを断捨離するために(3)
https://qiita.com/karin_to/items/a2ee0d8332f1151b3b87
RealtekのNICでWake-on-LANが使えない

## 環境

使用しているNICはマザーボードに搭載されているRealtek 8111Hです．マザーボードはMSIのMPG B550 GAMING PLUS，OSはDebian10です．

## 問題

Wake-on-LAN (WOL)を使おうとBIOSの設定を変更したが，WOLが使えませんでした．設定はASKの[ページ](https://support.ask-corp.jp/hc/ja/articles/360046270034-MSI%E8%A3%BD%E3%83%9E%E3%82%B6%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%81%A7%E3%81%AEWake-On-LAN-WOL-%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)を参考にしました．所有する他のMSIのマザーボードではASKのページに書いてある設定にするとWOLは使えるようになりましたので，BIOSの設定の問題ではないようでした．

NICが怪しいと思い，ethtoolコマンドでNICのWOLが有効か調べると
``` Wake-on: g```
となっていたので，WOLは有効のようです．

しかし，電源を落としハブを見たところ，ランプが光っていないのでNICが動いていないようです．これでは，WOLは使えないのは当然です．

## 解決方法

調べたところ，Arch linuxのwikiにある[Wake-on-LANのページ](https://wiki.archlinux.jp/index.php/Wake-on-LAN)にRealtekの8111などのNICで接続ランプがつかない問題が報告されています．Arch linuxのwikiには，解決方法の一つとしてdriverの更新が提示してありました．

早速，新しいdriverを入れたところ，問題が解決しました．

- 公式サイトの[ダウンロードページ](https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software)の
```GBE Ethernet LINUX driver r8168 for kernel up to 5.6```
と書かれたdriverをダウンロードします．
- ダウンロードしたファイル(おそらくr8168-**.tar.bz2)を展開します．
- 展開されたフォルダ内にあるREADMEに書かれた手順どおり作業します．

新しいdriverを入れると，電源を落としてもハブのランプがつくようになりました．マジックパケットを送ると，起動します．
AndroidのconnectedCheckで実行デバイスを指定する

# 困っていたこと
gradleのコマンドでInstrumentationテストを実行する際、複数の実機/エミュレーターが接続されているとテストが全ての端末で同時に実行されてしまう。

```console
$ ./gradlew testApp:connectedCheck
$ (省略)
Starting 32 tests on Pixel_2_API_28(AVD) - 9
Starting 32 tests on SO-03J - 8.0.0
```

これはこれで、Matrixテストになっていいかも知れないですが、どれか特定の端末でだけ実行したい場合の方が多いのではないかと思います。
その度に接続を外したりエミュレーターを落としてその後また必要になったら再起動したりするのも面倒ですよね。


# 解決策

`ANDROID_SERIAL`環境変数を使う。

### (1)adb devicesでデバイスリストを表示

例えば、実機1台とエミュレーター1台をそれぞれ接続、起動しているとします。

```console
$ adb devices
List of devices attached
XXXXXXX 	device
emulator-5554	device
```


### (2)環境変数を指定してからgradleコマンドを実行する

リストされた端末のうち、エミュレーターを使いたい場合の例。

```console
$ export ANDROID_SERIAL=emulator-5554
$ ./gradlew testApp:connectedCheck
```

環境変数は同じターミナルから実行し続ける限りは有効なので、その後のコマンドでも同じ端末が選択されます。

実機の方を使いたい場合は、"XXXXXX"という方を指定すれば良いです。

# 参考ページ

https://stackoverflow.com/questions/23960667/running-gradles-connectedandroidtest-on-a-specific-device

# おまけ

複数端末でテストが実行されたときに、テストレポートはどうなっているのだろうと確認したら、ちゃんとMatrixの結果表示になっていました。
ちょっと感動しました。

|![test_matrix_report.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/3455ab39-9b67-cbb0-fd12-ef1cfc743f69.png)|
|--|
【初心者でもわかる】オフレフトの書き方を解説

#どうも7noteです。オフレフトを使った画像の表示方法について解説

画像ではなくテキストを使っている方がSEO、つまりGoogleの検索エンジンの上位にランキングされる評価が高くなると一般的に言われています。

画像＋altよりも、テキストの方が評価が高くなるため、できるだけソースにはテキストデータを設置している方が良いとされてます。

しかし装飾したテキストデザインなら画像で表示したい場合もあると思います。
そんな時に使えるのがオフレフトという手法。

## オフレフトとは？

簡潔に言えば、、、

**「img直書きよりSEOの評価がされやすい画像の表示方法」**

とでもいうのがわかりやすいでしょうか？
正確な言葉ではないですが、イメージは上のようなイメージをもっていただければとおもいます。

何をしているかというと、
テキストはソースに書くけど見えない位置に放り出して、代わりに背景画像を設定しておいてそっちを見せる。なんてことをしています。

## オフレフトの書き方

```index.html
<h2>ロゴ</h2>
```

```style.css
h2 {
  width: 150px; /* 画像の幅を指定 */
  height: 60px; /* 画像の高さを指定 */
  text-indent: -9999px; /* 文字を画面外へ表示させる */
  background: url(sample_bg.png) no-repeat; /* 背景画像を指定 */
}

```

**結果**
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/dbdc89fb-7214-1a19-48d1-4da1c7e5cdb7.png)

**ソース上で確認**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/05a75c50-8e17-ead6-1570-0977957d5511.png)
※簡略化したソースです

## 解説

このように見た目的には画像がでてますが、ソースを確認すると文字だけという状態が出来上がります。
これでGoogleのクローラーがwebサイトを見に来ても、テキストデータとして認識されるため画像だけの時よりも評価が高くなるでしょう。

## まとめ

SEOの対策になるとはいえ、これだけで検索結果の上位に上がることはまずないでしょう。
あくまでも何個もある評価点のうちのほんの一部なので、本格的にSEO対策を行うのであれば他にも様々な施策を行わなければなりません。

逆にテキストインデントの値が明らかにおかしいと認識されることで、スパム扱いされるという話もあります。
最新情報をしっかり確認しながら、使うか使わないかを決めてご利用ください。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
迷ったときに立ち返る HTML, JavaScript, CSS 概論 (3)

# 前段
 * 前回は URL とリクエストのお話ししました。その中で REST の話をしたとき、さらっと "ステートレスなクライアント/サーバプロトコル" と書いたのですが、ステートの話を端折っていたのでその話からしていきます。
 * その後、Web システムで各種問題を引き起こすキャッシュの話へと流れていきます。

# ステート
 * 概論 1回目で書いたように HTTP のリクエストとレスポンスはクライアントとサーバの1回のやりとりで処理が完結します。
   - クライアントからリクエスト送る、サーバがレスポンスを返すで1回の処理完了

 * なので、サーバー側で何も考慮しないと処理の状態(例えばログイン状態や、一連の流れの中で処理がどこまで進んでいるか等)を管理することができない。 
 * このままでは複数回のやり取りで処理を行うような場合、すべての状態を各リクエストのパラメタで渡す必要があり、処理が冗長になってしまう。
 * ここでいう一連の処理の流れが**セッション**、そのセッション間で保持する状態を**ステート**と言います。
   - 例: ログイン ～ ログアウトまでが セッション、ログインしているかどうかや、複数画面に跨る入力画面のどこまで進んでいるかがステート

## ステートフル と ステートレス

 * **ステートフル** とはサーバ側でセッションの状態(ステート)を保持していることを言います
   - ステートによってリクエストに対するレスポンスが変わります。例えばセッションタイムアウトの状態で画面遷移を行うとログイン画面に遷移したりするのはステートフルだからできることです。
   - サーバ側で状態を保持しているので、リクエストはシンプルにできたりします (パラメタを減らせます)

 * **ステートレス** とはステートフルの逆でセッションの状態を保持していないことを言います。
   - ステートレスな際はリクエストに対するレスポンスは一意です(もちろんデータによってレスポンスは変わるでしょうが、ステートによる影響は受けないという意味です)。
   -  ステートを持たないのでリクエストが増えてきたときにスケールはしやすいですね
   - 前回記載したように REST はステートレスです

 * ステートフルとステートレスの違いをネットでいろいろ見てみて、わかりやすい例えだったのが下記
   - 引用元: https://www.web-knowledge-info.com/posts/web_basic_knowledge17.html

> 1回目でやりとりした相手を2回目に会ったとき、覚えていることをステートフル。
> 一方、1回目でやりとりした相手を2回目に会ったとき、覚えていないことをステートレス。

# キャッシュ
 * 上記でステートフル、ステートレスの話を書いたのですが、意識してコードを書いても思い通りの結果が出なかったときってないですか ? リリースしたのにお客様から画面変わってないと言われたり、画面真っ白になるんだけどとか ...
   - Web系のシステムだと(リリース手順にある程度自信がある場合)結構キャッシュが悪さしてたりします
   - で、キャッシュが原因だとすると、そのたびお客様にキャッシュをいったん削除していただいて ... とお願いするのですが、この流れが不毛だし、リリースは気分よく終わらせたいのでキャッシュを制御することを意識しましょう
 * ただ、キャッシュが悪者という訳ではなく 、静的コンテンツはキャッシュのおかげで読み込み時間減らせるので、コードやコンテンツの修正がないのであれば非常に有用なものです。悪いのは適切なキャッシュコントロールをしていない開発者 ...

## Cache-Control, IF-Modified-Since ヘッダ

 * Cache-Control ヘッダ
   - キャッシュさせない no-cache が有名ですがディレクティブはいろいろあります
   - https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control
 * IF-Modified-Since ヘッダ
   - サーバーは最後にリソースが変更された時刻が、リクエストにより与えられた時刻より後の場合にのみ、リクエストされたリソースを返却します。
   - https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/If-Modified-Since
 * これらのヘッダを HTML に meta タグで記載すれば HTML のキャッシュは制御できるのですが、スタイルシートや javascript のキャッシュまでは制御されません。そこで後述

## スタイルシート、javascript キャッシュ除け
 * HTML からスタイルシート、javascript を呼び出す際にファイル名の末尾になんらかのクエリストリングを追加して、キャッシュさせないようにできます
   - 例: bar.js をキャッシュさせないようにする

```
<script src="js/bar.js" />
という記載だったとすると、後述のようにクエリストリングを追加し、キャッシュさせないようにする。
再度修正するときはクエリストリングの数値を大きくしていく。

<script src="js/bar.js?1" />
```
 * コメントにて廣瀬さんからキャッシュ除けより "Cache Busting" って用語を覚えてもらったほうがいいのではというのがありましたので、追記しておきます。

# 後段
 * 今回はステートとキャッシュの話でした。第1回 から今回までのキーワードをちりばめて技術系の人と会話すると それっぽい SE に見られると思いますので恥ずかしがらずに使ってみてください。技術に疎いお客様にこれみよがしに使うと、わかりづらい説明をする人だと思われますので注意してください。

 * HTML, CSS, JavaScript でこういうの知りたいとかありましたらコメントで残しておいてもらえると、次書く際の材料にしますので、よろしくお願いします。(まだ一つもリクエストないんだよね)

 * 次は開発者ツールの使い方なのか、ログの話なのか、別な概念の話なのか ...
heroku CLIがユーザーアカウント制御によってインストールできない時の対処法【備忘録】

#生じた問題
開発したアプリをPCからデプロイしたりサーバーの設定を変更したりするために「heroku CLI」をインストールしようとしたら、「このアプリは保護のためにブロックしました。」との警告。どうもWindowsのユーザーアカウント制御がブロックしているらしい...
![iOS の画像 (7).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820164/f4153b40-15bc-1ce5-6eaa-381371e1d203.jpeg)

#解決までのプロセス
###ユーザーアカウント制御を無効にしてみた

Windows10でユーザーアカウント制御を無効にする手順

1.Windows の「スタート」メニューで uac と入力する。
※uac=ユーザーアカウント制御（User Account Control）

2．「ユーザー アカウント制御設定の変更」を選択する。

3.通知設定のメモリを「通知しない」にする。
![スクリーンショット 2021-04-22 042600.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820164/73cb3a24-0963-a0ba-54da-f817821f45d9.jpeg)

4．「OK」をクリックし、コンピュータを再起動する。

上記の操作を行い、ユーザーアカウント制御を無効にして「heroku CLI」のインストールを再度行ったが状況は変わらず、「このアプリは保護のためにブロックしました。」との警告。上手くいかない…
※これを試した方は、すぐにユーザーアカウント制御を有効（メモリを元の位置に戻す）にしてください。無効の状態はセキュリティ的によろしくないので。

###管理者のコマンドプロンプトでダウンロードした「heroku CLI」をインストールしてみた。

Windows の「スタート」メニューで 「cmd」と入力し、「管理者として実行を選択」。
![スクリーンショット 2021-04-22 044538.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820164/8a049851-1406-b177-fa77-c5263f569807.jpeg)

コマンドプロンプトにダウンロードした「heroku CLI」の絶対パスを入力し、実行する。
C:\Users\tai06\Downloads\heroku-x64(1).exe　←　heroku CLIの絶対パス（「このアプリは保護のためにブロックしました。」との警告画面の「プログラムの場所」から確認できる）
![スクリーンショット 2021-04-22 045003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820164/ad901b84-d269-2ee1-ddf1-c026fb89d259.jpeg)

すると、ソフトウェアが起動しインストールすることができました！！
【VS Code / Markdown All in One】##タグから見出し番号を振る方法

# TL; DR

Markdown All in Oneで見出し番号を振るとき、`settings.json`に

```json
"markdown.extension.toc.levels": "2..6"
```

を加えると、`#`タグを無視して`##`タグから見出し番号を振ることができます。

# 解決したい問題点

VS Codeで[Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one)と[markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)を同時に使用して編集している環境です。両者の目次の見出し番号を振るときにh1タグ相当の`#`の扱いの差でちょっと困ったことになりました。
Markdown All in Oneの「Add/Update section numbers」「Create Table of Contents」を使って目次を作ろうと思ったんですが、markdownlintに「h1タグは2個以上使わないほうがいいよー」と注意されます。
markdownlint的には、`#`はタイトルで、`##`以降が見出しなんですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091433/7064aad6-383c-125a-fa09-b888d11c26f1.png)
じゃあ、タイトルをつけてそれぞれの見出しレベルを一つずつ下げようかと、こうします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091433/2dfa90de-f783-17bc-1c2b-46e1fdb1f2ae.png)
markdownlintの注意は消えましたが、目次にタイトルまで入ってしまう上に、中身の見出し番号が1.x.xのように、全て1から始まってしまいます。これではちょっと見づらい……。
ということで、

```markdown
# タイトル
## 1. 見出し
### 1.1 見出し
## 2. 見出し
```

このようにタイトルの`#`タグを無視して、見出し番号を振ってくれるような設定を探しました。

# 設定方法

設定方法は簡単で、次の1行を`settings.json`に追加するだけです。

```json
"markdown.extension.toc.levels": "2..6"
```

これを設定した上で、もう一度見出し番号を振り直すとこうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091433/325b0dc1-b215-9ee0-efb9-f028f3abae30.png)

きれいに設定できました！　これでいい感じにMarkdownドキュメントの作成ができますね。

ということで、Markdown All in Oneで`##`タグから見出し番号を振る方法でした。

# 参考

* [Feature request_ Set level for section numbering · Issue #718 · yzhang-gh_vscode-markdown · GitHub](https://github.com/yzhang-gh/vscode-markdown/issues/718)
Railsアプリでエラーメッセージを日本語化するの巻

##前提
・Modelのエラーのデフォルトは各々違うと思いますが、英語で書かれているとします。英語で書かれているよりかは日本 語で書かれている方が日本人には親切です。

##エラーメッセージを日本語化

・rails-i18nというgemを使用します。

・Gemfileに以下の一文を追加してbundle installをします。

```
gem 'rails-i18n'
```

・config/application.rbに以下の一文を追記します。サーバ再起動後にエラーメッセージが日本語化していると思います。(辞書的な役割をするコードをgithubから引っ張ってくることもできるそうですが、それに関してはおいおいやってみたいと思います。)

```
config.i18n.default_locale = :ja
```
・このままだとmodelの属性名については英語のままになってしまっているでしょう。
 (すみません画像や写真がなくて。）

##カラム名を日本語化するために
・modelの属性名については、日本語変換用のymlファイルを作ってあげる必要があります。　

・config/locales/models/にja.ymlというファイルを作成して以下のようにカラム名と日本語の対応表を記述してします。

```
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: 名前
        email: メール
        password:　パスワード
```

・config/application.rbにこのymlファイルの読み込む一文を追記します。

・これは正規表現を使い、config/locales以下のディレクトリ内にある全てのymlファイルを読み込むように指示する一文となります。

```
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml').to_s]
```

お後がよろしいようで、ありがとうございました。
はじめてC++で画面を作ろう! (1) インストール編

これから、C++言語を始める人のために「壁」、「開発環境のセットアップ」を説明していく。

```※説明は、Windows10 64bit版が前提条件とします。```

プログラム言語を覚えるのに画面が動く、GUI：Graphical User Interface (グラフィカル・ユーザー・インターフェース)があった方が、分かりやすい。

そこで、今回は、"QtCreator"を起動するまでの手順を紹介する。

#手順
1. MSYS2をダウンロード
1. MSYS2をセットアップ
1. pacmanコマンドで、必要なものをダウンロード
1. 環境変数の`PATH`を設定
1. QtCreatorを起動

#1. MSYS2をダウンロード
下記のURLからダウンロードしましょう
https://www.msys2.org/
現在(2021/04/28)では、"msys2-x86-64-20210419.exe"が最新版である。

#2. MSYS2をセットアップ
ダウンロードした、"msys2-x86-64-`yyyymmdd`.exe"ファイルをダブルクリックして、起動する。
そのまま、どこもイジらずにクリックして、終わらせましょう。
詳細は、上記のURLに書いています。
`c:/msys64`に構築します。


#3. pacmanコマンド
セットアップが終わると、`"MSYS2 MinGW 64bit"`コマンドプロンプトが表示される。

上で説明した、URLにセットアップの手順も書いているのだか、
次の pacmanコマンドで、__ucrt64__なるモノが増えて、手順が増えている。
[追加情報:2021-04-19版] さらに__clang64__が増えている!!

1.`pacman -Syu`
2.`pacman -Sy` __これが増えた!!__
3.`pacman -Su`
4.`pacman -S base-devel` __gcc__コンパイラー
5.`pacman -S mingw-w64-x86_64-toolchain`
6.`pacman -S mingw-w64-x86_64-clang` __Clang/LLVM__コンパイラー
7.`pacman -S mingw-w64-x86_64-cmake`
8.`pacman -S mingw-w64-x86_64-qt5`
9.`pacman -S mingw-w64-x86_64-qt-creator`

#4. 環境変数の`PATH`を設定
Windows10のPATHに次の3行を先頭に追加する。
※PATHの順序は、検索順序のため、順番を間違えないようにしよう!
1. C:\msys64\ucrt64\bin
2. C:\msys64\mingw64\bin
3. C:\msys64\usr\bin

#5. QtCreatorを起動
`c:/msys64/mingw64/bin/qtcreator.exe`ファイルをダブルクリックして、起動!!
ショートカットを作っとけば、起動が楽になります。

今回は、ここまで次回は、画面を作ろう!!です。
Flutter × Firebase Remote Configでメンテナンス中画面構築してみた

今リリース中の課題管理アプリでメンテナンス作業が多くその間にユーザーの方々にアプリの使用を止める実装が必要だなと感じたので実装しました。
いわゆる「メンテナンス表示画面」
（ゲームアプリとかでもよくありますよね）

# 環境など

|ツールなど|バージョンなど|
|:--|:--|
| MacBook Air Retina2020|macOS Catalina 10.15.7|
|Android Studio |4.0.0|
|Flutter| 2.0.4 |
|Dart |2.12.2|
|Xcode |12.4|

#はじめに
###Firebase Remote Configとは？？
`Firebase Remote Configは、アプリ内パラメータを定義し、その値をクラウドで更新することができるサービスです。
クラウド上で管理する値を変更するだけで、即座にアプリに変更を反映させることができます。`
本来であれば、コードを変更し、Appleに審査を通すなどのプロセスが必要ですが、Firebase Remote Configを使えば、すぐにアプリのデータの更新が可能になります。
今回はこれを使ってアプリメンテナンス中でユーザーにアプリの使用を止めたいときの処理を実装していきます!

![ダウンロード (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619648/85e89fcb-02ab-1c9f-e502-798b03a2a11d.gif)



###実装手順
####1.Firebase Remote Configにkeyを登録する
![スクリーンショット 2021-04-22 19.53.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619648/0e578337-c154-9a7a-8449-c35acaa7cb14.png)

####2.Remote Configのパラメーターを取得する
```
Future<bool> maintenanceCheck() async {
  bool check = true;
  final remoteConfig = await RemoteConfig.instance;
  await remoteConfig.fetch(expiration: const Duration());
  await remoteConfig.activateFetched();
  final isUnderMaintenance = remoteConfig.getBool('isUnderMaintenance');
  if (isUnderMaintenance) {
    return check;
  } else {
    check = false;
    return check;
  }
}
```
####3.Remote Configの値でBool値を用意

```
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  bool isMaintenance = await maintenanceCheck();
  runApp(MyApp(isMaintenance));
}

class MyApp extends StatelessWidget {
  bool isUnderMaintenance
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(title: 'Flutter Auth Demo'),
    );
  }
}
```
####4.メンテンス中かどうかで表示画面を変更

```
home: StreamBuilder(
          builder: (context) {
            if (isUnderMaintenance) {
              return AlertDialog(
                      content: Text(
                        'アプリメンテナンス中です。ご不便をおかけしますが、一時的にご利用を停止させていただいております。',
                        style: TextStyle(
                          color: Colors.black,
                          fontSize: 19.0,
                        ),
                      ),
                    ),
                } else {
```



#感想
これができると、次は強制アップデートも実装できるので続きをやっていこうと思います！
Flutterでのドキュメントが非常に少なかったので、こんな感じですがとりあえず残しておこうと思います。


###参考文献
>Firebase Remote Config

>>https://firebase.google.com/docs/remote-config?hl=ja

>Flutterでアプリに強制アップデートの仕組みを入れる
>>https://qiita.com/kasa_le/items/a7bae1b9aef6dfde2504
Fluxモデルについて

#はじめに
この記事では、Fluxモデルについて簡単にまとめました。
⚠️当方初学のため認識違いがある可能性大です
誤りを見つけた際はコメントにて指摘していただけると幸いです🙇‍♀️🙇‍♂️


#参考
この記事は、以下の情報を参考にして執筆しました。

- [Flux](https://facebook.github.io/flux/docs/in-depth-overview/)
- [Fluxとは何か MVC, MVVMとの違いも含めて](https://namu-r21.hatenablog.com/entry/2018/03/21/232726)
- [Fluxとはなんなのか](https://qiita.com/knhr__/items/5fec7571dab80e2dcd92)


#Fluxモデルとは
![Dispatcher.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790168/a15ce79f-aba3-57d6-cadf-d22e46e0ea6c.png)
(https://facebook.github.io/flux/docs/in-depth-overview/ から引用)
Action : Viewから発火されて作られるイベント
Dispatcher : すべてのActionを受け都度Storeにイベントを発火
Store : データの管理とビジネスロジックを担当
View : 画面の描画、ユーザ操作を受ける役。

MVCの延長線上にある概念。
Action, Dispatcher, Store, Viewの4要素で構成される。


#Fluxの特徴
- 全てのデータのオペレーションがDispatcherに集約されている
- Viewで独立したデータを持つ
- データ状態を一方向のフローで制御
- Event駆動


#Action
Viewから発火されて作られるイベント。
必ずDispatcherに向かう。


#Dispatcher
すべてのActionを受けてStoreへ渡す。


#Store
データの状態管理やビジネスロジックを担当。
Dispatcherから受けたActionに応じてViewへデータを渡す。


#View
画面の描画、ユーザ操作を受ける役。
ユーザの入力によってActionを発火しStoreからのデータを受ける。
WSL2の手動installでエラー(This update only applies to machines with the Windows Subsystem for Linux)

# 「Linux カーネル更新プログラム パッケージをダウンロードする」でエラー
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

の[手順 4](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#step-4---download-the-linux-kernel-update-package)で以下のエラーが出た時の対処方法で、公式に書かれている事を試しても解決しなかったときの対処

> This update only applies to machines with the Windows Subsystem for Linux


## 解決方法

1. [wsl_update_x64.msi](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi)をダウンロードして解凍
1. 解凍したフォルダ内の「lxss_kernel」をさらに解凍
1. 解凍したフォルダ「lxss_kernel」内の「FID_LXSS_KERNEL」を以下のディレクトリに配置
1. FID_LXSS_KERNEL　→　kernel　にリネーム

```
C:\Windows\System32\lxss\tools
```

以上で完了です。
量子力学入門１

#量子力学入門１

##原子の安定性の不成立：　古典力学・電磁気学

原子は原子核、電子で構成される。
原子核の周りを電子が周回軌道に沿って回転している。（古典力学）
電荷を持っている電子は、
加速度運動をしている時に電磁波＝エネルギーを放出する。（電磁気学）
したがって、“理論上”原子内で回転している電子は、エネルギーを失い、
やがて原子核に衝突し、原子は崩壊する。
しかし、現実の原子はこれに反している。
よって、古典力学では原子の安定性を説明できない。
より小さなサイズの世界を理解する必要がある＝量子力学。
「物質は波。」と考える。

##粒子と波動の二重性

###二重スリットの実験

電子ビーム1つずつをスリットに打ち込むと、
スリットの後ろに仕込んだスクリーン（紙と考えて良い）に縞模様が現れる。
「縞模様＝波動」であり、波の性質である干渉が起こっている。
したがって、スリットを通過している状態の電子を波と考える。
ビームの状態及びスクリーンに着いた状態の時は粒子と考える。
電子は、波と粒子の2つの状態をとりうる。＝粒子と波動の二重性
二重星を持つ粒子は、電子だけでなくすべての粒子＝量子である。

###（※波束）

粒子の場所は一点でなく、位置に依存する存在確率で表される＝波束。

##波動方程式

波が満たす方程式＝シュレーディンガー方程式という。

##不確定性原理

位置と運動量がともに確定している状態は存在しない。
位置の不確定性$\Delta x$ 運動量の不確定さ$\Delta p$の積は、正の定数$\frac{\hbar}{2}$かそれより大きい。＝「不確定性関係」
不確定性が０＝確定＝分かっている
位置が正確に分かっている（＝不確定性が0）と、
運動量が完全にわからなくなる（＝不確定性が∞）

https://youtu.be/zlVnhTD7qMQ
[Git] 空のコミットを作成

#概要
通常変更点がない場合コミットできませんが、オプションを記述することで空のコミットができるらしいのでその方法をメモします。

#方法
* --allow--emptyを記述

```
$ git commit --allow--empty
```

コメントありもできます。

```
$ git commit -m '空のコミットです' --allow--empty
```
【Laravel】Railsのようにターミナル（bash）でモデルを使ってDBのデータを取得する方法

LaravelでRailsのようにターミナル（bash）でモデルを使ってDBのデータを取得する方法について。

##対処法
`php artisan tinker`でphpの対話モードに入ることでモデルを介してDBのデータを取得できる。


```
$php artisan tinker

>>> モデルの名前空間::メソッド;
```



<br>
##実例
名前空間`App\Models\User`の中のデータのid=1のデータを抽出する。

```
$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.2.8 — cli) by Justin Hileman
>>> App\Models\User::find(1)
=> App\Models\User {#4239
     id: 1,
     name: "admin",
     email: "example@gmail.com",
     created_at: "2018-10-06 00:10:15",
     updated_at: "2019-01-24 21:16:54",
   }
>>>
```

####`find(id番号)`
指定したid番号のデータを取得する。


```:例
>>> App\Models\User::find(5)
```

`find(1)`は`first()`と同じ。

<br>
####`all()`
全データを抽出

```:例
>>> App\Models\User::all()
```


<br>
####`where('カラム名', 値)`
条件に一致するデータを抽出。whereのみではcollection型で出力されるため、データを表示するためには`first()`をつける

```:例
>>> App\Models\User::where('id', 3)->first()
```


<br>
####`toSql()`
SQLクエリを抽出する。

```:例
>>> App\Models\Article::where('id', 3)->toSql();
=> "select * from `articles` where `id` = ?"
```
削除機能実装で発見「コントローラーに指定しないと同じアクションのファイルに留まろうとする」



仮に（チェット）ルームの削除機能を実装するために、

1.resources :roomsにdestroyアクションのルーティングを追記
-

```rb:config/routes.rb
Rails.application.routes.draw do
  # 中略
  resources :rooms, only: [:new, :create, :destroy] do
    resources :messages, only: [:index, :create]   
　　　#メッセージはコメントです。親子関係（ネスト）です
  end
end
```

2.roomsコントローラーにdestroyアクションを定義
-

`1.チャットルーム削除対象の選定`
　　Room.find(params[:id])を使用して、削除したいチャットルームの情報を取得します。

`root（roomsのindex）にリダイレクトする記述をします。`
destroyアクションは、削除するだけなのでビューの表示は必要はありません。

重要
-
他のindex,createなどのアクションもそうですが、何も記述しないと
###controllerでしてしてある同じ「def」より後ろに記述のあるアクションのアクションページに止まります。


```rb:app/controllers/rooms_controller.rb
class RoomsController < ApplicationController
 # 中略
  def destroy
    room = Room.find(params[:id])
    room.destroy
    redirect_to root_path
  end
 # 中略
```
3.destroyアクション動かすlink_toを設定しましょう
-
"チャットを終了する"をクリックすると、チャットルームが削除されるようにリンクを設定します。

```rb:app/views/messages/_main_chat.html.erb
<div class="chat-header">
  <div class="left-header">
    <div class="header-title">
      <%= @room.name%>
    </div>
  </div>
  <div class="right-header">
    <div class="header-button">
      <%= link_to "チャットを終了する", room_path(@room), method: :delete %>
    </div>
  </div>
</div>
```

「rails routes」コマンドを実行すると、roomsコントローラーのdestroyアクションに対応するPrefixは、roomということが分かります。したがって、削除のパスはroom_pathとなります。
削除するチャットルームを区別するために、定義している@roomを引数にし、room_path(@room)と指定しましょう。
HTTPメソッドのdeleteを指定すると、roomsコントローラーのdestroyアクションが実行されます。

destroyアクションが実行されると、roomを削除することができます。

4.最後に、roomを削除したときに、そのroomに関連する情報も削除されるように設定
-
```app/models/room.rb
class Room < ApplicationRecord
  has_many :room_users, dependent: :destroy
  has_many :users, through: :room_users  
  has_many :messages, dependent: :destroy

  validates :name, presence: true
end
```

|アソシエーションオプション|働き|
|--|--|
|dependent|2つのモデルの間につながりがあることを明示的にRailsに対して宣言でき、それによってモデルの操作を一貫させることができます。dependentオプションに:destroyを指定した場合、Room（親モデル）が削除されたときに、関連付けしているMessageを削除できます。

MessageモデルとRoomUserモデルにdependent: :destroyを記述します。

dependentオプションに:destroyを指定した場合、Room（親モデル）が削除されたときに、関連付けしているMessage（子モデル）とRoomUser（子モデル）も削除されます。

>参考：1 関連付けを使う理由「Railsガイド」
>https://railsguides.jp/association_basics.html
自宅のグローバルIPアドレスを、外出先から確認する

Y子です。
自宅のグローバルIPアドレスが変わったときなどに、それを外出先から確認する方法を考えました。

# 概要・用途
__[バッチファイルでグローバルIPアドレスを取得](https://qiita.com/koiwaiwaiko/items/0d1848c8900adcc154f7 "バッチファイルでグローバルIPアドレスを変数に格納")__ し、Dropbox管理下のテキストファイルに書き込むことで、外出先等どこからでもIPアドレスを確認可能とします。
この処理をWindowsのタスクスケジューラーに登録し、定期的に情報を自動更新します。
以下のような用途を想定します。

| 用途（例） |
|:-|
| 自宅のプロバイダ契約が固定IPアドレスでない場合、ルータが再起動するとグローバルIPアドレスが変わることがある。<br>自宅にWebサーバを置き、ドメイン名を割り当てて外部からアクセスしている場合、グローバルIPアドレスが変わるとアクセスできなくなるため、DNS設定を変更するために変更後のIPアドレスが知りたい。 |

なお、外出中も自宅のWindows PCが稼働していることが前提です。
これが一番のハードルかもしれませんね…。
_【[確認環境：Windows 10 Home (Bld. 19042.928)](https://qiita.com/koiwaiwaiko/items/ef2d457ae1e1a7c8b698 "Windows10のバージョンを確認・表記する")】_

# 手順
## (1) バッチファイル作成

```bat:watch_globalip.bat
@echo off

rem 日付「2021/04/02」形式
set str_date=%date%

rem 時刻「09:46:17」形式
set str_time=%time: =0%
set str_time=%str_time:~0,8%

rem コマンドの実行結果を変数に格納
for /f "usebackq" %%a in (`curl https://api.ipify.org`) do set ipaddr=%%a

rem ファイル格納場所はDropbox配下
set outfile="C:\Users\yourname\Dropbox\globalip_%ipaddr%.txt"

rem ファイルに出力
echo [%str_date% %str_time%] %ipaddr%> %outfile%
```

__[前の記事](https://qiita.com/koiwaiwaiko/items/0d1848c8900adcc154f7 "バッチファイルでグローバルIPアドレスを変数に格納")__ の方法で、`curl`コマンドを使ってグローバルIPアドレスを取得します。
出力先は、Dropbox配下のテキストファイルですので、パスはお使いの環境に合わせて書き換えてください。
ファイルの内容とファイル名は、以下の方針で決めました。これは用途や使いやすさで調整するのがいいと思います。

* ファイル内容にIPアドレスを記録 … この情報が欲しいので外せない
* ファイル内容に日時を記録 … いつ時点の情報かわかるように
* ファイル名にIPアドレスを記録 … ファイルを開かなくてもわかって楽。あとファイルが増えるとIPアドレスが変わったことになるので気付きやすい
* ファイル名に日時は無し … 日時を付けるとファイルが増えて管理が面倒なので無し

また、ファイルへの書き込みは上書き`>`で行っていますが、追記`>>`にしてログのように扱うのもアリと思います。

```:実行結果
> watch_globalip.bat
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    13  100    13    0     0      6      0  0:00:02  0:00:02 --:--:--     5
```

```:globalip_xx.xx.xx.xx.txt
[2021/04/22 19:34:52] xx.xx.xx.xx
```

できました。結果のIPアドレスは、`xx.xx.xx.xx`と伏せています。
Dropboxで共有できているか、確認します。

## (2) スケジューラー登録
作成したバッチファイルを、Windowsのタスクスケジューラーに登録します。

1. スタート
1. Windows管理ツール
1. コンピューターの管理
1. タスクスケジューラー
1. タスクの作成

トリガーを適切に設定して保存し、動作確認として1回実行してみてください。
わたしは、「毎日」のトリガーを1日4回設定して、6時間間隔で実行するようにしています。

これで、グローバルIPアドレスが変わってしまっても察知できる準備が整いました。

## (3) DNS設定変更
IPアドレスが変わって設定が必要になったら、お使いのドメイン登録サービス（お名前.comとか）で設定してください。
サービスによっては、自動的に設定変更できる仕組みが用意されているかもしれません。

# おわりに
タスクスケジューラーとDropboxを組み合わせる方法を思いついたときは感動しました。
固定IP無しで自宅サーバを運用している方は、どうしてるんでしょうね。
同じように困ってるのか、わたしが知らないだけでとっくに解決済みなのか…。

他のやり方をご存じの方は、ぜひ教えていただきたいです。


では！
GCP(Google Cloud Platform)のバケットにアップしたzipファイルを解凍

ローカルPCに保存された数万個のセンサデータファイルをGCP(Google Cloud Platform)にアップする必要があり、フォルダごとアップしようとしたらものすごく時間がかかりそうなので、zipにまとめてバケットにアップロードしてから、GCP上で解凍する方法を調べた結果をメモ。

まず、GCPの画面の右上の赤丸の部分をクリックして、Google Cloud Shellを起動する。
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306431/f0639753-8c4c-da24-933d-844bf549e2fa.png)

Google Cloud Shellが起動したら、コマンドラインでunzipをインストールする。
`sudo apt install unzip`

次にcloudストレージのバケットにアップしたzipファイルをcloud shellのローカルにコピー。
`gsutil cp gs://my-bucket/sensorfile.zip .`

zipファイルを解凍(dataフォルダを作ってその中に解凍)
`unzip sensorfile.zip -d data`

解凍したファイルをフォルダごとcloudストレージのバケットにコピー。
`gsutil cp -r data gs://my-bucket`
しようと思ったけど、これをすると、6時間たっても約2KB×1万ファイルぐらいしかコピーが終わっていなかったので、-mオプションを付けてやり直す。

`gsutil -m cp -r data gs://my-bucket`
これだと1時間弱で約2KB×約3万ファイルのコピーが終わった。

念のため、コピーしたファイル数を確認。このコマンドは数分かかった。
`gsutil du gs://my-bucket/data | wc -l`


参考にしたサイト：
https://www.sneppets.com/cloud/how-to-unzip-a-zip-file-from-terminal-google-cloud-shell/
Google Chrome の試験機能 ( chrome://flags/ )で遊んでたら Chrome がﾀﾋんだ時の対処法

#経緯

1. リーディング リストとかいう新機能邪魔だなぁ。`chrome://flags/` で消すかぁ。
1. ワイ「おっ、この試験機能面白そうやん！有効にしたろ！」ﾎﾟﾁｰ
1. 2D描画の補助に Vulkan を使用する試験機能「Vulkan」を有効化。
1. なんか有効にしたら画面が正常に表示されなくなっちゃった…。<br>
(起動時のクリア色で真っ白又はリサイズにより一部又は全部が真っ黒)

#方法1(ボス級)
僕が使用した方法です。「Chrome flags 無効化」などと検索したときに日本語サイトで情報が**一切**出てきませんでした[^1]<sub>(アフィカスブログですら)</sub>。

####ショートカット( `.lnk` )を使用する場合

1. Chrome のショートカット( `.lnk` ) をどっかにコピペする。<br>
ショートカットが無い場合は実行可能ファイルを探し出す。Windows 10 の場合は `C:/Program Files (x86)/Google/Chrome/Application/chrome.exe` にあるかも。
1. ショートカットのプロパティを開き、`ショートカット>リンク先(T)` を探す。
1. その文字列の末尾に `--no-experiments` をぶち込む。

####DOS窓から実行する場合
1. Chrome の実行ファイルのパスをDOS窓にコピペする。
1. 末尾に `--no-experiments` をぶち込む。
1. 実行。

#方法2(通常)
検索するとよく出てくる通常の片し方です。画面が全く描画されないので出来ません。

1. `chrome://flags/` へ移動し、右上の `Reset all to default` ボタンを押す。<br>
(<time datetime="2021-04-22">2021/04/22</time>時点では `Reset all` でした。)

#方法3(ラスボス級)
<a href="https://support.google.com/chrome/answer/3296214?hl=ja">公式のヘルプ</a>にも書かれている、メニューが無い又は開かない場合に設定を元に戻す方法。再設定が嫌なので見送りました。正解でした。

1. Chrome を再インストール。

#終わりに
<a href="https://superuser.com/questions/575374/is-there-a-way-to-reset-chrome-flags-to-their-defaults">謎の海外兄貴</a>ありがとう！！！！！！



<!--  脚注  -->
[^1]: <a href="http">ぬいぐるみライフ？さんの記事</a>が出て来ました！  因みにアフィカスブログでは無く、何故かめちゃめちゃ役立つタイプの"一般"ブログです。
モデルのアソシエーションに別名をつける

# はじめに
自分のポートフォリオにフォロ-機能や通知機能を実装している際に、モデルのアソシエーションに別名をつけることがありました。再度、これがどういう意味なのか確認していきます。
あくまで、アウトプット用の分かり辛さがあるかと思いますが、ご了承ください。

# モデルのアソシエーションに別名をつける
今回は、フォロー機能を実装すると仮定してUserモデルとRelationshipモデルを用意した場合のことを考えてみます。フォロー機能で難しいのは、Relationshipモデルを中間テーブルとして、Userモデル自身で多対多の関係であるという点です。

さっそく先にコードを見てみます。



```user.rb
  #フォロー（こっち）側役
  has_many :relationships, dependent: :destroy
  has_many :followings, through: :relationships, source: :follow #架空モデル
  #フォロワー（あっち）側役
  has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id', dependent: :destroy #架空モデル
  has_many :followers, through: :reverse_of_relationships, source: :user #架空モデル

```

一行目は、単純にhas_manyでUserモデルとRelationshipモデルを関連づけています。
本題は二行目ですよね。
followingsなんて作ってないぞ！！って感じですよね。でもこれは実はUserモデルのことで、架空のモデルを作ったと考えるとイメージしやすいです。ただし、もちろん架空モデルなんてありませんから、その後ろで情報を付け加えてあげます。まず、through:relationshipsでRelationshipモデルは中間テーブルであるということを設定します。そして、source:followで、following配列の元はfollow_idの集合であるということを示します。
なお、follow_idはRelationshipモデルのカラムです。

つまり、二行目の部分は、Relationshipモデルを経由して、Relationshipのfollow_idに紐づけているわけです。

続いて、三行目です。
reverse_of_relationshipsという架空のモデルを同様に作っています。しかし、当然そんなものはないので後ろに情報を付け加えます。class_name："Relationship"でこいつは実はRelationshipモデルですよと明示します。さらに、foreign_key: 'follow_id', dependent: :destroy の部分で外部キーの設定等をします。

まとめると、三行目は、Relationshipモデルの名前をReverse_of_relationshipsにしただけです。

そして四行目は、三行目のreverse_of_relationshipsを経由して、user_idに紐づけています。

```relationship.rb
class Relationship < ApplicationRecord
  belongs_to :user
  belongs_to :follow,class_name: 'User'
```
relationship.rbでは、上記の通りです。

# 終わりに

こんな感じで、モデルのアソシエーションを別名で紐づけることができます。
DBの繋がりが複雑になると混乱してきますが、基礎をしっかりすればとても便利な技ですので、是非挑戦してみてください。
JavaScript基礎メモその2

# while文
while文は繰り返し処理を行う場合に用いる。

>```javascript
let number = 1;
//変数numberの値が100以下の時に処理を繰り返す
while (number <= 100) {
//繰り返す処理
  console.log(number);
  number += 1;
}

結果
1
2
3
.
.
.
100

#for文
for文はwhile文と同様に繰り返し処理を行うが、while文よりシンプルに書くことができる。
>```javascript
for (変数の定義; 条件式; 変数の更新) {
  処理
}
```

>```javascript
for (let number = 1; number <= 100; number += 1) {
  console.log(number);
}

結果
1
2
3
.
.
.
100

#for文とif文を使ったコード
1から100を順番に出力し3の倍数の時には「3の倍数です」と表示させる。
>```javascript
for (let number = 1; number <= 100; number++) {
  if (number % 3 === 0) {
  console.log("3の倍数です");
  } else {
    console.log(number);
  }
}

結果
1
2
3の倍数です
.
.
.
98
3の倍数です
100

#配列
配列は、複数の値をまとめて管理する場合に用いり、[値1, 値2, 値3]のように作る。
配列に入っているそれぞれの値を要素と呼ぶ。
配列も一つの値なので、定数に代入することができる。
>```javascript
const number = [1, 2, 3];

>console.log(number);
```

結果
[1, 2, 3]

配列が出力される。

#インデックス番号
配列の要素にはそれぞれインデックス番号が割り振られている。
インデックス番号は左側の要素から、0から始まる。
インデックス番号を用いて配列の要素を取得するには定数名の後に(変数名[1])のように取得したい要素のインデックス番号を指定する。
>```javascript
const names = ["toda", "sakurai", "owada"];
>
console.log(names[0]);
console.log(names[2]);
```

結果
toda
owada

#配列の要素を更新する
要素に値を代入することでその要素を上書きすることができる。
>
```javascript
const names = ["ishida", "kondou", "wakai"];

>console.log(names[0]);
names[0] = "harada";
console.log(names[0]);
```

結果
ishida
harada

インデックス番号[0]の"ishida"が"harada"に更新される。

#配列と繰り返し
for文を使って配列の要素を順番に取り出してみる。
>
```javascript
const names = ["tokoro", "nanase", "mogami"];

>for (let i = 0; i < 3; i++) {
  console.log(names[i]);
}
```

for文では、i = 0 で変数iに0を代入し、 i++ でiの値を1ずつ増やし、 i < 3 で3未満になったら処理を停止するようにしている。
変数iを用いて要素を取得している。　(names[ i ])

結果
tokoro
nanase
mogami

#length
lengthは配列の要素数を取得できる。
for文の条件式に使うことができる。
>```javascript
const names = ["tokoro", "nanase", "mogami"];
console.log(names.length);
```

結果
3

>```javascript
const names = ["tokoro", "nanase", "mogami"];

>for (let i = 0; i < names.length; i++) {
  console.log(names[i]);
}
```

結果
tokoro
nanase
mogami

#オブジェクト
オブジェクトは配列と同じく複数のデータをまとめて管理する場合に用いる。
配列との違いは、オブジェクトはそれぞれの値に対してプロパティと呼ばれる名前をつけて管理する。
>```javascript
//配列
[値1, 値2, 値3]

>//オブジェクト
{プロパティ1: 値1, プロパティ2: 値2}
```

>```javascript
const user = {name: "aoi", sex: "woman"};

>console.log(user);
```

結果
{name: "aoi", sex: "woman"}

#オブジェクトの値の取得・更新
・値の取得
>```javascript
const user = {name: "aoi", sex: "woman"};

>console.log(user.name);
```

結果
aoi

・値の更新
>```javascript
const user = {name: "aoi", sex: "woman"};
user.name = "akane";

>console.log(user.name);
```

結果
akane

# オブジェクトを要素に持つ配列
配列の要素には、オブジェクトも使うことができる。

>```javascript
const users = [
  {name: "noriko", sex: "woman"},
  {name: "yoshiki", sex: "man"}
];

>// 配列の値がオブジェクトなので、配列[インデックス番号]で対応するオブジェクトを取得できる。
console.log(users[1]);

>// 配列の中のオブジェクトのプロパティの値を取り出すには、配列[インデックス番号].プロパティ名 で取得できる。
console.log(users[1].name);
```

結果
{name: "yoshiki", sex: "man"}

yosiki

#存在しない容姿、プロパティの取得
配列に対して存在しないインデックス番号を指定したり、オブジェクトに対して存在しないプロパティを指定するとどうなるか試してみる。
>```javascript
const users = ["noda", "enndou", "saitou"];
console.log(users[1]);
console.log(users[4]);

結果
endou
undefined

>```javascript
const user = {name: "gotou", age: 22};
console.log(user.phonenumber);

結果
undefined

存在しない要素は取得しようとすると、undefinedとなる。
undefinedは未定義という意味。
LeetCode日本語修行9日目- [363-総和はKまで最大のマトリクス]

###Max Sum of Rectangle No Larger Than K
#####参考：https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/
###問題の内容:
m x n の行列と整数 k があります，総和はKまで最大のマトリクスの最大和を返す．
総和はKまで最大のマトリクスが存在することが保証されています。
###例:
例1:
Input: matrix = [[1,0,1],[0,-2,3]], k = 2
Output: 2
Explanation: Because the sum of the blue rectangle [[0, 1], [-2, 3]] is 2, and 2 is the max number no larger than k (k = 2).

例2:
Input: matrix = [[2,2,-1]], k = 3
Output: 3
###ヒント:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-100 <= matrix[i][j] <= 100
-105 <= k <= 105

---
今日の問題は、最大サブアレイを理解の上に、回答すると、わりと簡単になると思います。
対応の問題はこちら：https://leetcode.com/problems/maximum-subarray/
最大サブアレイの計算はArrayに対しての計算ですが、今回対象はMatrixです。
まずは、問題を変換します。
Matrixの形は以下：
[**8,2,4**,4,9]
[**1,7,3**,4,3]
[**2,1,6**,4,5]
[**7,2,3**,9,2]
太字になった部分の総和を計算する
sum
8+2+4   [**8,2,4**,4,9]
1+7+3   [**1,7,3**,4,3]
2+1+6   [**2,1,6**,4,5]
7+2+3   [**7,2,3**,9,2]
そして、sumMatrix = sumRow1 + sumRow2 + sumRow3 + sumRow4
即ち　sumMatrix : [sumRow1,sumRow2,sumRow3,sumRow4]
**sumMatrixの最大サブアレイの計算**になりました！



```Kotlin
class Solution {
    fun maxSumSubmatrix(matrix: Array<IntArray>, k: Int): Int {
        var rows = matrix.size
        var cols = matrix[0].size
        var answer = Integer.MIN_VALUE
        for(left in 0 until cols){
            var rowSum = IntArray(rows)
            for(right in left until cols){
                for(i in 0 until rows){
                  rowSum[i] += matrix[i][right]
                }
                answer = Math.max(answer,dpmax(rowSum,k))
            }         
        }
        return answer
    }

    fun dpmax(array:IntArray,k:Int): Int{
        var max = Integer.MIN_VALUE
        for(left in 0 until array.size){
            var sum = 0
            for(right in left until array.size){
                sum += array[right]
                if(sum > max && sum <= k){
                    max = sum
                }
            }
        }
        return max
    }
}
```
iRIC ソフトウェアの更新方法



# １．更新のみの場合（新規ソルバーや格子生成ツールを追加/削除する場合は２．へ）

- １） iRICを起動する

- ２）「メニューバー＞オプション＞メンテナンス」をクリック
「iRICを閉じて iRIC Maintainanceを起動」をクリック。

※このとき、起動しているiRICソフトウェアはすべて保存、終了してください。

- ３） 以下の画面が表示されるので、「コンポーネントの更新」を選択し「次へ」をクリック



<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/b2a0ff63-5554-37c5-0e59-8422554aa34e.png" width=75%>
</div>


- ４）更新されたコンポーネントがある場合、名前とバージョンが表示される。そのまま「次へ」をクリック


<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/1cd9b98f-569b-9016-76c8-df7fc33e762e.png" width=75%>
</div>




- ５）更新する場合は「更新」をクリック


<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/1535674c-c12a-870b-14f1-1808ca980ee4.png" width=75%>
</div>


- ６）更新が完了すると完了画面が表示される。
「再起動」をクリックすると、３．の画面が再度表示される。通常必要ないので、「完了」をクリックして終了するとソフトウェアの更新は完了する。

<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/8839ceff-65e4-b33b-40a8-0a0f72bb36ee.png" width=75%>
</div>


# ２．新規ソルバーや格子生成ツールを追加/削除する場合

- １） iRICを起動する

- ２）「メニューバー＞オプション＞メンテナンス」をクリック
「iRICを閉じて iRIC Maintainanceを起動」をクリック。



※このとき、起動しているiRICソフトウェアはすべて保存、終了してください。

- ３） 以下の画面が表示されるので、「コンポーネントの追加または削除」を選択し「次へ」をクリック

<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/8f834d83-0414-23fc-8669-30319cd29ca1.png" width=75%>
</div>



- ４） 以下の画面でチェックが付いている項目はインストールされる、逆にチェックが外れている項目はアンインストールされる（またはインストールされない）。必要な項目にチェックを入れて「次へ」をクリック。


<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/27c67593-c873-2b71-b000-5114e740a303.png" width=75%>
</div>


- ５） 更新の準備が完了すると以下の画面が表示される。「更新」をクリック。

<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/53dfffd2-e9c5-a7bb-1aee-403e3c0b57e7.png" width=75%>
</div>

- ６）更新が完了すると完了画面が表示される。
「再起動」をクリックすると、３．の画面が再度表示される。通常必要ないので、「完了」をクリックして終了するとソフトウェアの更新は完了する。

<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90108/2df20e39-a6f0-4991-fd4a-bcc0925f760f.png" width=75%>
</div>
【GitHub】ブランチ作成を忘れていた時の対処方法

### この記事はこのような方の参考になると思います

- ブランチ作成を忘れててmasterブランチでコードを書き進めてしまった方
- ブランチ作ろうとしたけど２択を迫られてどうしていいか解らない方

### 結論
- コードを書き進めてても問題なし。２択は下を選べばOK。上を選んでしまってもなんとかなります。

### 前提として、まだブランチを作成していない状態を想定し、順に方法を書いています。
※既に選択肢の「上」を選んでしまっている方は【上を選んでしまった場合】から読んでください。
それではいきます！！


①GitHubデスクトップのカレントブランチのタブをクリック
②[New Branch]をクリック
③ブランチ名を入力し、[Create Branch]をクリック
④以下の画面が表示されます
![a4f518aaee2236d34ad771f6f7fe4393.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1345348/e1d735b6-68d3-0ce1-c201-13461f864aaf.png)
⑤[Bring my~]を選択し、[Switch Branch]をクリック
⑥新しいブランチが作成され完了です
➡︎masterブランチにあったcommit前の変更点が新しいブランチに反映されていると思います


### 【上を選んでしまった場合】
※自身が行った操作と照らし合わせて手順確認してください！

①GitHubデスクトップのカレントブランチのタブをクリック
②[New Branch]をクリック
③ブランチ名を入力し[Create Branch]をクリック
④２択を迫られる
⑤[Leave my~]を選択し、[Switch Branch]をクリック
⑦新しいブランチが作成される
⑥masterブランチにあったcommit前の変更点は、masterブランチ上で保留状態[stash]になっている
![39e00c8c82dccc2edcc89a6c7f3cbb15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1345348/ad017792-2682-8803-0eaf-9f16e58c6803.png)
⑦左下の[Stashed Changes]をクリック
⑧Restoreクリック
⑨masterブランチにcommit前の変更点が復元される
⑩カレントブランチのタブをクリックし、新しく作成されたブランチをクリックすると再度２択を迫られるので下を選べば完了です
➡︎masterブランチにあったcommit前の変更点が新しいブランチに反映されていると思います
An error occurred (AccessDenied) when calling the PutBucketPolicy operation: Access Denied

# はじめに

AWSのチュートリアル「[Build a Modern Web Application \<Module 1: Build a Static Website\>](https://aws.amazon.com/getting-started/hands-on/build-modern-app-fargate-lambda-dynamodb-python/module-one/)」を進める際に躓いた点があったのでメモ。

# 発生したエラー

「Step3: Host The Website On S3」の「B: Update The S3 Bucket Policy」でウェブサイトにパブリックバケットポリシーを追加する際に以下のエラーが発生しました。

``` :Bash
$ aws s3api put-bucket-policy --bucket REPLACE_ME_BUCKET_NAME --policy file://~/environment/aws-modern-application-workshop/module-1/aws-cli/website-bucket-policy.json
An error occurred (AccessDenied) when calling the PutBucketPolicy operation: Access Denied
```

「『PutBucketPolicy』を実行しようとしたけどアクセスできませんでした」とのことらしいです。

# 解決方法

[こちらのサイト](https://stackoverflow.com/questions/53385012/cannot-set-bucket-policy-of-amazon-s3)を参考にしました。

1. 
[Amazon S3コンソール](https://s3.console.aws.amazon.com/s3)にて、「Step3: Host The Website On S3」の「A: Create An S3 Bucket And Configure It For Website Hosting」で作成したバケットを選択します。

1. 
「アクセス許可」タブの「ブロックパブリックアクセス（バケット設定）」を編集します。

1. 
「パブリックアクセスをすべてブロック」のチェックを外し、変更を保存します。

おそらくこれで先ほどのCLIコマンドが実行できると思います。~~コマンドを実行してパブリックバケットポリシーを追加した後は、「パブリックアクセスをすべてブロック」を再びチェックしておいたほうがいいかもしれません。（理解不足）~~パブリックアクセスのブロックがどのような影響を及ぼすのか要調査。