OmniAICreator/Qiita-1.07M huggingface dataset:
pythonでのスクレイピング



HTTP通信でHTMLを取得して解析する方法。
APIでJSON取得が出来ると良いが、そういうものが見つからない場合にスクレイピング的にHTMLから取得したい。
環境はWindowsServer2012+Python3.9.7

# パース
HTMLのパースには
`import bs4 # beautifulsoup4 XMLパーサ`
を利用する。
pipで取得して以下のようにしてセレクタを使って取得したりする。

```
selector = "#items" 
soup = bs4.BeautifulSoup(html, "html.parser") # パーサーに渡す
result = soup.find(selector)
```

# request
実際にHTMLを取得する方法だが、２つ存在する。
1つはPythonからhttpリクエストを投げてデータを取得する方法。
もう一つはブラウザ経由で取得、つまりReact等で構成されたページの内容を取得する方法。

requestsは一つ目の方法で、簡単に利用できる。
パースと組み合わせた簡単な処理は以下のような感じ。
[公式](https://docs.python-requests.org/en/latest/user/quickstart/)とか参照。

```python
def htmlSearch(key):
	proxies = {
	"http":"http://proxy:8080",
	"https":"http://proxy:8080"
	}

    params = {'q': key} # ここの書き方が正しいかは見てない

	url = "https://www.target.com" + key # URLがキーになっている場合
	selector = "#items" 
	req = requests.get(url,proxies=proxies,params=params)
	print(req.url)
	print(req.text)
	soup = bs4.BeautifulSoup(req.text, "html.parser") # パーサーに渡す
	result = soup.find(selector)
	print(result) # findは先頭の1件のみなのでget_textが可能

	return result
```

# Selenium
ブラウザコントロールのパターン。今回はこれがメイン。Chromeをコントロールする。
[ここ](https://ai-inter1.com/python-selenium/)がある程度参考になりそうだが、バージョン違いなのか、一部上手く行かない事もあった。

まずは`pip install selenium`でインストール。
pipでプロキシ使う場合は`pip install --proxy="http://proxy:8080" selenium`とする。
Chromeを操作するには[ChromeDriver](https://chromedriver.chromium.org/downloads)が必要なのでダウンロードしておく。
Python内では`driver = webdriver.Chrome(executable_path='G:/apps/chromedriver_win32/chromedriver.exe')`のように設定。
設定が間違っているとchromedriver_win32 executable needs to be in PATH.が出る。
これで`driver.get(url)`でChromeにURLを与える事が出来る。
今回入力操作は不要なので省略。
検索結果から値を取得するが、SeleniumにXPathを利用した取得機能が付いているのでそれを利用する。
実際にはReactでの読み込みに少し時間がかかるので待機が必要。
time.sleepやdriver.implicitly_waitを使う。

基本形はこのような形

```python
from selenium import webdriver
from time import sleep
from selenium.webdriver.chrome.options import Options

# key sample: /p/6891/0196/
def chromeSearch(key):
    try: 
        driver = webdriver.Chrome(executable_path='G:/apps/chromedriver_win32/chromedriver.exe')
        options = Options()
        # options.add_argument('--headless') # ヘッドレスモード

        url = "https://www.target.com" + key
        selector = '//*[@id="items"]/div[1]/div[3]/div[1]/div[1]/span' # 実際にはXPath検索

        sleep(1) # 念のため待つ

        driver.get(url)
        driver.implicitly_wait(10) # findで要素が見つかるまで最大10秒待機

        result = driver.find_element_by_xpath(selector)
        
        print(result.text) 

    # 使い終わったら閉じる
    finally:
        driver.close() 
        driver.quit()

	return result.text
```

実際にはExcelから読み込んで連続検索したりしたいので、外部からdriverを渡すようなメソッドを作る方が良さそう。

上記ソースでブラウザからの取得は上手くいったが、headlessオプションを付けると上手くいかない、といった挙動が発生した。
いくつか情報があって、ブラウザサイズの問題や、サーバ側でヘッドレスモードを弾こうとしている、といったもの。
ヘッドレスが弾かれる場合は[ヘッダーを偽装](https://github.com/diwu1989/Fake-Headers)する手法は取れそう。

```python
from fake_headers import Headers

header = Headers(
    browser="chrome",  # Generate only Chrome UA
    os="win",  # Generate only Windows platform
    headers=False # generate misc headers
)
customUserAgent = header.generate()['User-Agent']

options.add_argument("user-agent={customUserAgent}")
```

とりあえず画面サイズとヘッダ偽装を両方実装する事で対応出来た。
WSL2のCUDAのnvidia-smiからGPU使用率を得る裏技を発見

# 概要 - Abstract

WSL2でのCUDAにはある重大な課題があります。
NVIDIAの佐々木さん ( @ksasaki ) の記事にあるように、WSL2から`nvidia-smi`コマンドからGPU使用率を確認することはできません。

（2021/11/25現在）

https://qiita.com/ksasaki/items/ee864abd74f95fea1efa

上の記事では、Windows側からnvidia-smiコマンドを叩いてGPU使用率をロギングする策が紹介されています。しかし、WSL2とNative Windowsの行き来が必要なので、実用上の不便さは否めません。


この度は、**実はWSL2の`/mnt/c`にはCドライブがマウントされている**こと、および**WSL2がWindowsのバイナリを実行できる**こと、の2点に着目して、**linux内から`nvidia-smi`経由でGPU使用率を扱う裏技**を思いついたので、共有しつつ、その便利さを述べていきます。 


# 結論 - Conclusion

### 1. nvidia-smi.exeのWindows上でのパスを確認する

```:Powershell
> get-command nvidia-smi
```

### 2. WSL2からWindowsのnvidia-smiの実行ファイルのパスを指定する

`/mnt/c/`に続けて1.にて得られたパスをlinuxのパスの形式で打ち込みましょう。
(以下の`bar`とか`foo`はあくまで例なので、パスは各自書き込んでください。)

```:WSL2
"/mnt/c/bar/foo/nvidia-smi.exe"
```

驚くべきことに、なんとこれにより、**WSL2のlinuxターミナルからWindowsにインストールされている方のnvidia-smiコマンドを呼び出せる**のです。**それはまさに、WSL2のlinuxターミナルからGPU使用率が見えることを意味します。**

#### 驚きは止まらない
しかも、その**出力結果は、grepやパイプラインなど、linuxのターミナルを普段使いするように扱いと加工ができるのです。**

```:WSL2
"/mnt/c/bar/foo/nvidia-smi.exe" > ./log.txt
```

しかも、それには**何の違和感もなく、linuxで`nvidia-smi`を扱うように、パラメータを与えることもできる**のです。



例えば、以下の記事で登場する佐々木さんお好みのWindows側でのロギング方法を見てみましょう。

https://qiita.com/ksasaki/items/ee864abd74f95fea1efa

```:PowerShell
C:\WINDOWS\system32>nvidia-smi --loop=2 -i 0  --format=csv --query-gpu=timestamp,utilization.gpu,clocks.sm,power.draw,temperature.gpu
```

適切にパスを指定することにより、上のコマンドが、WSL2のlinuxターミナルから全く同じように扱えるのです！

```:WSL2
"/mnt/c/bar/foo/nvidia-smi" --loop=2 -i 0  --format=csv --query-gpu=timestamp,utilization.gpu,clocks.sm,power.draw,temperature.gpu
```


# さらなる実用上の工夫の余地も

とはいえ`nvidia-smi.exe`のパスを毎回指定するのは面倒なので、bashエイリアスを用いて`my-nvidia-smi`とか適当な名前をつけて扱うのもいいかもしれませんね。

https://qiita.com/_ydah/items/18d242b632e5486fe912

まあ、それも面倒なので、私は場合はctrl+rで履歴から繰り返してますが。。。


# WSL2におけるnvidia-smiコマンドの問題は修正予定

NVIDIAの中の人の佐々木さん曰く、
> 開発チームは認識済みで修正の予定

とのことですので、私の書いているこの記事は、そのうち不要になることでしょう！（と願いたい🤲）

# 感想

中の人から直接耳寄りの情報がQiitaで手に入るとは、いい時代になったものですね。

お読みいただきありがとうございました。それでは、より良きGPUライフを！
【読書感想】「Clean Architecture 達人に学ぶソフトウェアの構造と設計」を読んで

以下の本を読んでの感想です。
僕はまだこの本の内容をちゃんと理解しきれていないと思います。なので、今回は「感想」という形にとどめておき、将来再読した際に改めてちゃんとした考察を書きたいと思います。

https://www.amazon.co.jp/Clean-Architecture-達人に学ぶソフトウェアの構造と設計-Robert-C-Martin/dp/4048930656

## 感想（現時点での理解）

この本を読んでいて思ったのは、クリーン・アーキテクチャというのは決まったある一つの設計の型ではないのかな、ということです。決まった型というよりも、クリーンな設計をする上で考慮すべき原理・原則について説明されているのだと思いました。つまり、「今回のプロジェクトはクリーン・アーキテクチャを採用しよう」ということになっても、人によってその設計は変わってくるのではないかと思います。

ネットでクリーン・アーキテクチャについて調べると、以下の同心円の図が示され、その型に乗っ取った設計がクリーン・アーキテクチャであるように書かれている物が多いように思いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102360/c45da397-a7c0-9065-4896-0c18912805a7.png)
参考：　[The Clean Code Blog](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)

なんだか、クリーン・アーキテクチャが一つの型にはめ込まれているように思い、僕はなんだか違和感を感じていたのですが、この本の最後についてくる、訳者あとがきの以下の部分を読んでスッキリしました。

> 見よう見まねでアーキテクチャの「同心円」を実装している例が数多く見られる。だが、著者のように原理・原則に忠実であるためにも、まずは本書に目を通してもらいたい。そして、著者と対話しながら、自らのアーキテクチャをクリーンにしてもらえれば幸いだ。

この同心円の構成になっていればクリーン・アーキテクチャと呼べる、という単純なものではなく、この本にはクリーンなアーキテクチャを実現するための原理・原則がまとめられているのだと思います。

第２１章　叫ぶアーキテクチャでは、以下のようにも書かれています。

> では、あなたのアプリケーションのアーキテクチャは何と叫んでいるだろうか？最上位レベルのディレクトリ構造と最上位レベルのパッケージのソースファイルは、「ヘルスケアシステム」「会計システム」「在庫管理システム」と叫んでいるだろうか？それとも「Rails」「Spring/Hibernate」「ASP」と叫んでいるだろうか？

つまり、この本に書かれている原理・原則を理解し、そのプロジェクトにあった形で設計設計されたアーキテクチャが、クリーン・アーキテクチャと呼べるのだと思います。それは、結果的に内向きの依存関係を持った同心円の構成になるのだと思います。


僕はまだシステム開発の経験は浅く、ちゃんと理解できない部分が多々ありました。将来、システム開発への理解が深まってきたら改めて読み、もっとちゃんと理解したいな、と思わされる本でした。
Table View Sellが表示されない!!!

## ストーリーボードでセルが表示されてない???

HomeViewControllerにTable Viewを追加したが、画面が真っ白だった!
何度もやり直したが、解決できずx-codeが最新バージョンだから不具合が起きているのではとメンターに質問してみたが、「AutoLayoutの制約に問題があるようでした」とご指摘を受け右側にある設定画面を操作してみると、エミレーターにやっとセルが表示された!!!

## 右の画面
![スクリーンショット 2021-11-25 19.00.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/6bd3ac48-5c56-9185-ac31-75a0a1de8aee.png)


## 設定後のUI
![スクリーンショット 2021-11-25 19.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/60d6baf6-cd1a-fa82-cc7b-ae879e0278e4.png)
ファイルディスクリプタとNGINXの設定の関係

## 内容
LinuxのファイルディスクリプタとNGINXのworker_rlimit_nofileとの関係についていろいろ調べた結果をここに記す



###ファイルディスクリプタとは
プログラムがアクセスするファイルや標準入出力などのをOSが識別するために用いる識別子のこと
Linuxではすべてを「ファイルとして扱う」インターフェースになっている(未確認)


###OSで扱える最大のファイルディスクリプタは以下のコマンドで確認できる

```
$cat /proc/sys/fs/file-max
```

###プロセスごとの制限の確認
プロセスごとのファイルディスクリプタの最大値を表示する方法

```
$cat /proc/[pid]/limits 
#or
$ulimit -a
```

ここで表示されるものにSoft limitとHard limitがある
 - Soft limit：一般ユーザが変更できる制限でハードリミットを超えることができない
 - Hard limit：rootユーザのみ変更できる制限である
 
##NGINXとの関係

###worker_rlimit_nofileについて
NGINXの公式ドキュメントには以下のように書かれている

>
構文：	worker_rlimit_nofile number;
ディフォルト：	—
環境：	main
RLIMIT_NOFILEワーカープロセスの オープンファイルの最大数（）の制限を変更します。メインプロセスを再起動せずに制限を増やすために使用されます。

公式ドキュメント：https://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_core

1ワーカプロセスごとのオープンファイルの最大値がここで制限される
なのでこの値と上記のものと関係があると考えている(未実証)

###worker_connectionとの関係

worker_connectionにはデフォルトで`512`という値が設定されている
これは**たぶん**ファイルディスクリプタのソフトリミットのデフォルトの値が`1024`であるからと考えられる
【Ruby のまずいコード】ファイル書き出し

# お題

`Math::PI` の値をファイル pi.txt に書き出してください。

# コード

```rb
File.open("pi.txt", "w") do |f|
  f.print Math::PI
end
```

# 改善

ファイルに書き出す専用のメソッド [IO.write](https://docs.ruby-lang.org/ja/3.0.0/method/IO/s/write.html) があります。
これを用いると

```rb
IO.write("pi.txt", Math::PI)
```

と簡素化できます。
`IO.write` は `File.write` とも書けます。これについては次節で述べます。

ファイル読み込みのほうも同様で，

```rb
text = nil
File.open("text.txt") do |f|
  text = f.read
end
```

とか[^c1]

[^c1]: このコードでわざわざ `text = nil` としているのは，ブロック外でローカル変数を定義しないとこのあとで `text` が使えないから。代入される `nil` に意味はありません。原理的には何でも OK ですが，`nil` 以外だと何か意味のある値なのかと誤解される恐れがあります。

```rb
text = File.open("text.txt"){ |f| f.read }
```

などとしなくても，[IO.read](https://docs.ruby-lang.org/ja/3.0.0/method/IO/s/read.html) を使って

```rb
text = IO.read("text.txt")
```

と書けます。
`IO.read` は `File.read` とも書けます（次節参照）。

# IO.write/IO.read か File.write/File.read か

`IO.read` や `IO.write` を使ったコードを [RuboCop](https://rubocop.org/) で検査すると，セキュリティーの観点から「`IO.write` でなく `File.write` を使う」ように言われます[^rc]。

[^rc]: 検出されるかどうかは RuboCop の設定によります。

というのは，`File.read` や `File.write` はファイルの読み書きしかできませんが，`IO.read` や `IO.write` はファイル以外のさまざまなものに対しても読み書きでき，第一引数に与えるものによってはコマンドの実行すらできてしまうからです。
例えば，

```rb
IO.read("| mkdir hoge")
```

とやると，ディレクトリーが作れてしまいます！[^kw]
よって，たとえばウェブアプリでユーザー入力に基づく値を第一引数に与えることはコマンドインジェクション攻撃に繋がり得ます。

[^kw]: もちろんもっと怖いこともできます。ここでは，macOS，Linux，Windows で共通に使えるコマンドを例に取りました。

そういう観点からすると，この記事の対象読者（初心者を想定）に `IO.write` や `IO.read` を勧めるのは良くない気もしますね。
`File.write` や `File.read` を使う，と覚えておいたほうがよいかもしれません。
【SwiftUI】toolbar Modifierの表示位置（iOS）

SwiftUIのtoolbarの表示位置です。
全12種で細かい事を言う並びに優先順があるので全部違います。

#サンプルコード
```swift
NavigationView{
    Text("Hello, World!")
        .toolbar{
            ToolbarItem(placement: .navigationBarLeading){
                Text("leading")
            }
        }
    }
}
```

NavigationView内のViewに.toolbar Modifierをつけます。
中にはToolbarItemを使って配置します。
引数placementにToolbarItemPlacementで位置の指定を行います。

#対応表

| ToolbarItemPlacement（左から順） | 表示位置| 備考 |
|:--|:-:|:-:|
| .navigationBarLeading  | 左上（leading）  |   |
| .cancellationAction  | 左上（leading）  |   |
| .navigation  | 左上（leading）  |   |
| .principal  | 中央（center）  |   |
| .automatic  | 右上（trailing）  |   |
| .navigationBarTrailing  | 右上（trailing）  |   |
| .primaryAction  | 右上（trailing）  |   |
| .destructiveAction  | 右上（trailing）  | confirmationActionと同じ優先順位  |
| .confirmationAction  | 右上（trailing）  | destructiveActionと同じ優先順位<br />太文字（bold）  |
| .bottomBar  | 下部（bottom）  |  デフォルトは中央<br/>statusがあると左端 |
| .status  | 下部（bottom）  |   |
| .keyboard  | キーボード  |   |

|![Simulator Screen Shot - iPhone 11 Pro Max - 2021-11-18 at 19.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602101/c4ea5d73-c3d9-6e10-2dff-24271500ce54.png)|
|:--|

#実際に使うものは？
以下の４つが主になると思います。

* .navigationBarLeading
* .navigationBarTrailing
* .bottomBar
* .keyboard

中身はHStackで配置できるので、無理に色々使わずにHStackで並べた方が無難です。
無理に複数使って並べて順序がおかしくなることのないようにしましょう。

#余談
##iOSバージョンについて
toolbarはiOS14から使用出来ます。
navigationBarItemが非推奨になったので、問題が無ければ随時置き換えを行いましょう。

.keyboardはiOS15からです。
iOS14では使用出来ないので注意して下さい。

##ブログ記事の紹介
ツールバーについて更に説明が見たい方はこちら

https://thwork.net/2021/11/18/swiftui_toolbar-modifier/

ToolbarItem無しで簡易的な使い方をする場合や、
複数並べた場合のサンプルコード、
キーボードについての補足などがあります。
テーマによって画像を切り替えるREADMEを書く

## 動作例

![](https://raw.githubusercontent.com/matoruru/switch-images-based-on-theme/main/how-this-works.gif)

## ソースコード

https://github.com/matoruru/switch-images-based-on-theme

## 書き方

以下のように、画像名の後に`#gh-dark-mode-only`か`#gh-light-mode-only`を付け足します。

```md
![](./for-dark-theme.png#gh-dark-mode-only)![](./for-light-theme.png#gh-light-mode-only)
```

## 参考

- https://github.blog/changelog/2021-11-24-specify-theme-context-for-images-in-markdown/
- https://twitter.com/github/status/1463556704436637707
【AWS】NLB配下のEC2をCloudFrontのIPで制限したい②

# 概要
下記の続きとなります。

https://qiita.com/kurono/items/71814097531ed32efd55
# 追記
現在は、AWSより本ロジックを作成しなくても、対応できるようにマネージドプレフィックスリストが追加されております。
https://aws.amazon.com/jp/about-aws/whats-new/2022/02/amazon-cloudfront-managed-prefix-list/

# 過信(2022/2/8)
そもそも、NLBがどのIPでヘルスチェックしているかを俺は理解していなかった。

ヘルスチェックをするIPはCloudFrontのIPアドレスではなく**NLBの所属するVPC内で払いだされたIPアドレス**。
NLBの先のインスタンスでは**CFのIPアドレス**と**VPCのCIDR**(<mark>AWS公式はVPCのCIDRを登録するのが推奨っぽい</mark>)をセキュリティグループで許可してあげなければいけない。
[ターゲットセキュリティグループ](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/network/target-group-register-targets.html#target-security-groups)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/7beea5c4-52b7-f313-6ace-e7a5ad85a8dc.png)


# 罠

上記の設定をしたのち、ヘルスチェックも通りアプリアクセスも正常にいけた。
しかし、主題であるアクセスをCloudFrontからのみに制限するということが実現できておらずNLB直でもアクセスできてしまうことが発覚しました。

アプリアクセス的にはCloudFrontのIPしか許可していないのにNLB直が何故かイケてしまう状況。。
構成図的には下記のような状態だった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/3e7bf425-de0b-620b-60f4-6b1e7799ab0e.png)

<br>
<br>

設定値を眺めているとNLBのターゲットグループで**クライアント IP の保存**というのがあり、
これが**無効**になっていたのが原因だった。
[クライアント IP の保存](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/network/load-balancer-target-groups.html#client-ip-preservation)

クライアントIPを保持していると信じていたのにそうではなく**NLBのIPアドレスでアクセスしていた**ので
ヘルスチェック用のSGで通ってしまっていた状態だった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/08829185-06bd-8c67-420c-a4e5bf230011.png)


# 終わりに
どういった違いで設定が変わるかを覚えておくことが重要な気がします。

**インスタンス ID でターゲットを指定する場合**
→すべての受信トラフィックのクライアント IP が保持される。

**IP アドレスでターゲットを指定する場合**
→ターゲットグループプロトコルが TCP または TLS の場合、クライアント IP 保存はデフォルトで**無効**です。
→ターゲットグループプロトコルが UDP および TCP_UDP の場合、クライアント IP 保存はデフォルトで**有効**です。

今回の場合、IPアドレスでターゲットを指定しており、ターゲットプロトコルがTCPであった為、
**IP アドレスでターゲットを指定する場合**の1つ目に該当していたようです。
C#でWeb UIが開発できるBlazorのご紹介

#Blazorとは？

C#でWeb UIが開発できるフレームワークで、Javascriptの代わりに.NETとC#を使って、リッチでインタラクティブなWeb UIを構築可能です。Razorコンポーネント単位で画面の部品を構築していくため、再利用性が高いです。C#で実装しますが、Javascriptとの相互運用も可能です。（C#からJavascriptの処理を呼び出すことができますし、その逆も可能です。）

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158398/5621bc31-a251-43a1-bbc3-952d5cbf0d0f.png width=20%>

#Blazorの種類
##Blazor WebAssembly

WebAssemblyを利用することにより、Web ブラウザー内で .NETのコードを実行することが可能になります。ランタイムと共にバイナリコードがブラウザにダウンロードされ、UIイベントが発生するとブラウザ上で直接実行されます。サーバーサイドの構築が必要ないため、純粋な静的サイトとして展開可能です。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158398/d544075c-c048-8435-5e62-ec3f5bc8f7df.png width=40%>


##Blazor Server

RazorコンポーネントをAsp.net Coreサーバー上でホストして動作するBlazorアプリケーションです。
WebサーバーとWebSocket（SignalR）で通信することにより、Web UIを動的に構築します。そのため、WebAssemblyをサポートしてないブラウザでも動作可能です。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158398/d0514d6d-5afd-dca9-b5d2-42ec8c238e8a.png width=40%>

#Blazor WebAssemblyとBlazor Serverの比較

|機能       |       Blazor WebAssembly |    Blazor Server    |
|:-----------------|:------------------:|:------------------:|
|サーバーリソースへの直接アクセス|❌|🔵|
|DBアクセス|❌|🔵|
|初回起動速度|❌|🔵|
|対応ブラウザ|🔺Wasm対応ブラウザ|🔵ほぼすべてのブラウザ|
|オフラインで実行可能|🔵|❌|
|レスポンス速度|🔵|🔺|
|Webサーバー|🔵静的ファイルをホスティングできれば良い|🔺ASP.net Coreサーバーが必要|
|スケーラビリティ|🔵|🔺サーバー側リスースの追加が必要|

#Blazorのメリット
####.NET、C#の既存の技術でクライアントサイドを実装可能
高機能なVisual StudioのIDE支援や既存のNuGetパッケージなどを、Blazorアプリ開発にそのまま活かせます。Razor構文でそのままクライアント側のビューを実装可能なので、ASP.net MVCの知見を活かすことができます。

####クライアントとサーバー間でコードの共有が可能
クライアントサイドもサーバーサイドも.NETで構築するため、コードの共有が可能です。それぞれに重複して処理を実装する必要がないため、効率的に実装することができます。

#Blazorが向いている人は誰？
####Windows FormsやWPFの開発者で、Webアプリの開発を始めようとしている人
Javascriptが分からない、学習したくなかった人でも、既存のC#の知識でクライアントの処理を実装できます。
※ただし、HTML、CSSの学習は必須。Javascriptがどうしても必要な場面もある
 
####ASP.net MVCの開発者で、SPAの開発に興味がある人
本格的なReactやVue.jsなどのフロントエンドフレームワークの学習は敷居が高いと感じている人にもご利用いただけると思います。先程も書きましたが、Razor構文で記述できるため、ASP.net MVCの経験者は既存の技術スタックで対応可能です。
【AWS】NLB配下のEC2をCloudFrontのIPで制限したい①

## 概要
・CloudFrontの後段にELBがいるような構成になっていてCloudFrontではAWS WAFでDDos等防いでいるが、
　ELB及びEC2へは直接アクセスできてしまうのでブロックしたいパターン。
 
・ALBであればカスタムヘッダ/WAFで制御することも可能だが、今回はNLBということで後段のSGインバウンドを動的に対応させることに。

**公式ブログを参考にしていくことに。**　
https://aws.amazon.com/jp/blogs/security/how-to-automatically-update-your-security-groups-for-amazon-cloudfront-and-aws-waf-by-using-aws-lambda/

※大まかな手順等は上記公式ブログに記載の為今回は省きます。

# 追記(2022/2/8)
現在は、AWSより本ロジックを作成しなくても、対応できるようにマネージドプレフィックスリストが追加されております。
https://aws.amazon.com/jp/about-aws/whats-new/2022/02/amazon-cloudfront-managed-prefix-list/

## 構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435702/0c59ab7d-9894-43ca-d8f7-2ca194c70714.png)


構成の流れとしては以下

①初回は公式ブログにあるテストをし、現在の[IP Range](https://ip-ranges.amazonaws.com/ip-ranges.json)からLambdaの中でCloudFrontのGLOBAL/REGIONALのIPを抽出しSGに反映する。
②それ以降は、[IP Range](https://ip-ranges.amazonaws.com/ip-ranges.json)が更新されるたびに公式から公開されているSNSをトリガーにLambdaが動作してSGを更新してくれる。


## 問題①
公式ブログで参照先になっているPythonコードを試したところ、[このissue](https://github.com/aws-samples/aws-cloudfront-samples/issues/39)に挙がってる問題に直面し上手くいかなかったので上記エラーを解決している[もの](https://github.com/wangerzi/aws-cloudfront-samples/blob/master/update_security_groups_lambda/update_security_groups.py)を使用することにしました。

https://github.com/aws-samples/aws-cloudfront-samples

## 問題②
セキュリティグループのルール数に上限(デフォルト50)があり、GLOBALのIPを追加するセキュリティグループのルールが上限を超えてしまう問題があります。
セキュリティグループのNameタグで対象を選択しているので**同じNameタグのセキュリティグループの数を増やすorセキュリティグループのルール数の上限緩和**をする必要があります。
セキュリティグループのルール数の上限緩和も制約があるので申請する場合は確認したほうが良いと思います。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/increase-security-group-rule-limit/

## 注意点
当たり前だろ、と思われるかと思いますが構築中にあるLambdaのトリガー設定をするCLIはSNSがあるリージョンで実行しなければならないので<span style="color: #d61b09">export AWS_DEFAULT_REGION=us-east-1</span>等してから実行しないと上手くいきません。

今回自分はTerraformで構築したのですが、その際にもalias等使用してトリガーの設定をしないと上手くいかないと公式にも書いてあるので要注意です。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription



## 続編
https://qiita.com/kurono/items/27ed5d07cf396bcaa63d
【SwiftUI】キーボードを閉じる方法（iOS15）

SwiftUIを使ってソフトウェアキーボードを閉じる方法です。

#概要
<span>@</span>FocusStateを使用し入力フォームのフォーカスを外す事でソフトウェアキーボードを閉じます。

#コード
```swift
import SwiftUI

struct FocusStateBoolView: View {
    
    @State var text = ""
    @FocusState var focus:Bool
    
    var body: some View {
        Form {
            TextField("TextField", text: self.$text)
                .focused(self.$focus)
            Button("Focus ON"){
                self.focus = true
            }
            Button("Focus OFF"){
                self.focus = false
            }
        }
    }
}
```

#解説
ソフトウェアキーボードを閉じるにはフォーカス（選択状態）を解除するする必要があります。
iOS15からは変数でフォーカスの状態を保持できる様になった為、
これを用いてフォーカスを外してキーボードを閉じます。

なお、標準ではreturnキーを押すか、Viewを非表示にする事でフォーカスが外れます。
思うように外す事が出来ない場合があるため、閉じる機能を提供する必要がある場合もあります。

##<span>@</span>FocusState
フォーカスの状態を変数で保持するために、
iOS15から追加された<span>@</span>FocusStateを使用します。
<span>@</span>Stateの様にメンバ変数の前につけます。

```swift
@FocusState var focus:Bool
```

この時使える変数はBool又はHashableを実装したものです。
AppleのドキュメントではenumにHashableを実装して使用しています。

##.focused
次にModifierの.focusedを使います。

```swift
TextField("TextField", text: self.$text)
    .focused(self.$focus)
```

これで変数とフォーカスの状態が紐付けられました。
この変数のtrue/falseを切り替える事でフォーカスが切り替わり、
ソフトウェアキーボードの開閉が行われます。

#余談
##シミュレータについて
シミュレータでソフトウェアキーボードを使う際は「shift＋cmd＋K」で切り替えられます。
I/Oの項目からの切り替えも出来ます。

##ブログ記事の紹介
本記事は試験的にQiita用に要点を絞って簡潔にまとめて書いてみました。
ブログには細かな検証や複数の例を載せていますが、Qiita簡潔に最低限にする予定です。
好みがあると思うので使い分けて下さい。

以下のブログには詳細な説明や他のコード例があります。

ソフトウェアキーボードを閉じる方法（iOS14以前やUIの実装も含む）

https://thwork.net/2021/11/19/swiftui_keyboard-close_focus-remove/


<span>@</span>FocusStateの解説

https://thwork.net/2021/11/19/swiftui_focusstate/
【AWS S3】AWS CLIを使ってバケットに保存された最新のオブジェクトを取得する

#これはなに？
aws cliを使って、バケットに保存されている最新のオブジェクトを取得したかったのでそのコマンドのメモです。



## コマンド
--prefixでどのディレクトリから探すかを指定できる。
``Contents[?LastModified >= `2021-11-24T03:21`]``でどの時間より後かを指定している。

```:コマンド:
aws s3api list-objects --bucket my-bucket-name --prefix Directry/ --query 'Contents[?LastModified >= `2021-11-24T03:21`]' | jq -r  'sort_by(.LastModified) | reverse | .[0] | .Key'

```

##おまけ
出力されたオブジェクト名をそのまま用いて、オブジェクトの詳細を取得できる。

```:コマンド:
aws s3api head-object --bucket my-bucket-name --key ↑のコマンドの出力で得られたオブジェクト名

```

```:出力結果:
{
    "AcceptRanges": "bytes",
    "Expiration": "expiry-date=\"Mon, 25 Nov 2024 00:00:00 GMT\", rule-id=\"xxxxxxxxxxxx\"",
    "LastModified": "2021-11-25T08:48:23+00:00",
    "ContentLength": 105171,
    "ETag": "\"xxxxxxxxxxxxxxxxx\"",
    "ContentEncoding": "gzip",
    "ContentType": "application/json",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

```
【javascript】非同期処理

# 前提知識
### ブラウザとスレッド
連続して実行される一本の処理の流れ。

* 処理A
* 処理B
* 処理C

ブラウザのjavascriptに関わるスレッド
1. Main Thread > JavaScriptが関わるスレッド
1. Service Worker
1. Web Worker

### メインスレッド（Main Thread）

JavaScriptの実行とレンダリング（画面描写処理）を行う。
javascript => レンダリング

### FPS(Flames Per Second)

#### 1秒間あたりの画面（フレーム）更新頻度
* 1秒間に60回画面更新 => 60fps = 16.7秒に1回画面更新されている。

#### 重い処理があると画面が更新されなくなる。
* JavaScript側で16.7ms以上かかる処理のケース

# 同期処理と非同期処理

## 同期処理
1. メインスレッドでコードが順番に実行される。
1. 1つの処理が完了するまで、次の処理には進まない。
    1. 重い処理があった場合は、処理が完了するまで次の処理に進まない。

### case

* 3秒後に実行されるsleep関数を用意
    * ブラウザーをロードした時に3秒後に`sleep done`が表示される。
    * その後`button clicked`がレンダリングされコンソール状に表示されるようになる。
    * **3秒間中にボタンを何回押しても'button clicked'が表示されないことに注目したい。**
    * かならず、`sleep done`が表示された後に`button clicked`が表示される。
    * すなわち、javascriptのスレッドが処理されている時には次の処理（レンダリング）がされていないことがわかる。

```js
function sleep(ms) {
  const startTime = new Date();
  while (new Date() - startTime < ms);
  console.log('sleep done');
}

const btn = document.querySelector('button');
btn.addEventListener('click', function(){
  console.log('button clicked');
});

sleep(3000);
```

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/88374e24-b602-a2b7-4290-dd9434d8aed7.gif)

## case2（非同期処理）

* webAPIのsetTimeoutを使用して2秒後にsleep関数を実行する。
    * sleep関数を実行するまでの2秒間にボタンを押す。
        * >>> `button clicked`が表示される。
    * 3秒後にsleep done
    * またその後にボタンを押すと`button clicked`が表示される。
* **setTimeoutはjavascriptが占有するメインスレッドを解放されレンダリングが先に実行される。**
* そして、3秒後にjavascriptがメインスレッドを占有し`sleep done`を表示する。
* すなわち、**非同期処理とはjavascriptが一時的にメインスレッドから処理の解放されている時に実行されること**

```js

function sleep(ms) {
  const startTime = new Date();
  while (new Date() - startTime < ms);
  console.log('sleep done');
}

const btn = document.querySelector('button');
btn.addEventListener('click', function(){
  console.log('button clicked');
});

setTimeout(function(){
  sleep(3000)
},2000)

```

![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/fb2649d5-7def-a0a8-e7fe-ddaf26617fdf.gif)

### 非同期APIの例
* setTimeout
* Promise
* queueMicrotask
* etc...


* UIイベントではクリックなども非同期として渡すことができる。
* そのほか、NWイベント、i/oイベントなどがある。
起動途中で /dev/sda5: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY. と出て止まる

(遅れた夏休み企画 16/20)

家のキッズたちのために Ubuntu Linux ベースの PC 環境を整備しています。

cf., 「Ubuntu で MINECRAFT」
https://qiita.com/nanbuwks/items/df10bba9f0ed473827d7

キッズが使っていると当然ながらいろいろ問題が出ます。今までの問題は以下のようなものがありました。

- 「キッズ用 Ubuntu マシンに入ってきた怪しからんモノ」
 - https://qiita.com/nanbuwks/items/f27d2b1e263b5caf4b18

- 「ハードディスクエラーで起動しなくなった Ubuntu を fsck で誤魔化す」
 - https://qiita.com/nanbuwks/items/96e92023205d8f4bb694

# 今回のトラブル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1e93f27e-3061-39c0-14a6-42dcd8f3e77f.png)

起動しないというもの。

以前の「ハードディスクエラーで起動しなくなった Ubuntu を fsck で誤魔化す」よりは軽症です。
まずは症状の確認をしましょう。


```

/dev/sda5 contains a file system with errors, check forced.

```

ということでエラーの自動修復が進みますが

```

/dev/sda5: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.

```

自動修復ではうまく直せなかったということですね。なので /dev/sda5 を手動で fsck しましょう。
以下のように(initramfs) の後ろに fsck /dev/sda5 と打ち込んでエンターを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f0e02ceb-9e77-9fd5-7379-78a53cf12717.png)

チェックが進んでいる所

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a4bb1031-16b8-4a23-d79a-062ec38baa54.png)

エラーの箇所で直しますか？ と出てくるので y のキーを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/fdafdaa3-436a-10e6-6de7-877734a5bb85.png)
沢山エラーが出た場合には y のキーを押しっぱなしにしても構いません。


最後までいくと ***** FILE SYSTEM WAS MODIFIED ***** と出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/08b253e1-a161-1aed-4038-f455bf3c9972.png)

```

exit 
```
と打ち込んでエンターします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2e56f9b6-0458-96aa-d6f3-fbc63c8fd9e2.png)

うまく動作すればおしまいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/12f0a5f1-85e9-8b93-f20f-180cb935e748.png)
Vue3.0 + Vite + Cropperjs

# はじめに

前回の記事で`Vue3.0`で`Cropperjs`を使用する方法をまとめました。今回はビルド高速化の為にこれに`Vite`を使った方法を記載します。

https://qiita.com/hoshianaaa/items/a2a726dcd8a2bcfebf45

# 方法
1.パッケージの作成 + Viteのインストール + cropperjsのインストール

```
vue create aaaaa
cd aaaaa
npm init vite-app vue-todo-list
cd vue-todo-list
npm install
npm install cropperjs
```

2.`vue-todo-list/src/App.vue`を書き換える

```vuejs:vue-todo-list/src/App.vue
<template>
  <img ref="cropImg" alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Hello Vue 3.0 + Vite + Cropperjs" />
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

import Cropper from 'cropperjs';
import "cropperjs/dist/cropper.css";

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  mounted() {
    this.cropper = new Cropper(this.$refs.cropImg, {
      background: false,
      modal: false,
      highlight: false,
      viewMode: 1
    });
  },
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

3.実行

```
npm run dev
```

4.結果は以下のようになります

![Screenshot from 2021-11-25 18-42-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/c2350621-bd97-bfb1-5e57-1b155d2746c3.png)

# 環境

ubuntu20.04

# 参考

Viteの使用方法: https://qiita.com/Toshiaki0315/items/1ab4e479007bb0f76f06
Herokuにdashアプリをデプロイする

# 全体の流れ
- herokuアカウント取得
- heroku cliインストール
- python仮想環境構築
- プロジェクトディレクトリに必要なファイルを作成
    - app.py, Prockfile, requirements.txt, .gitignore
- heroku及びgitコマンドでデプロイ

# 実行環境
- windows10
- wsl2
- Ubuntu20.04
- conda 4.10.3

# 事前準備
* gitインストール
    * [Git \- Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* herokuのアカウントを取得
    * https://www.heroku.com/
* heroku cliをinstall
    * [The Heroku CLI \| Heroku Dev Center](https://devcenter.heroku.com/articles/heroku-cli#download-and-install)
    * wsl2では以下を実行

```:wsl
$ curl https://cli-assets.heroku.com/install.sh | sh
```

* heroku cliのインストール確認  

```:wsl
$ heroku --version  
heroku/7.59.2 linux-x64 node-v12.21.0
```

* condaでpython仮想環境を準備

```:wsl
$ conda create -n heroku_test python=3.10
$ conda activate heroku_test
```

* heroku login

```bash:wsl
$ heroku login
heroku: Press any key to open up the browser to login or q to exit:
```

# Dashアプリの作成
* プロジェクトディレクトリ作成

```:wsl
$ mkdir dash_app_example
$ cd dash_app_example
```

* モジュールインストール

```:wsl
$ pip install dash
$ pip install plotly
$ pip install gunicorn
```

* プロジェクトディレクトリに以下のファイルを準備
    * app.py
    * Prockfile
    * requirements.txt
    * .gitignore

### app.py

```python:app.py
import os

import dash
import dash_core_components as dcc
import dash_html_components as html

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

server = app.server

app.layout = html.Div([
    html.H2('Hello World'),
    dcc.Dropdown(
        id='dropdown',
        options=[{'label': i, 'value': i} for i in ['LA', 'NYC', 'MTL']],
        value='LA'
    ),
    html.Div(id='display-value')
])

@app.callback(dash.dependencies.Output('display-value', 'children'),
                [dash.dependencies.Input('dropdown', 'value')])
def display_value(value):
    return 'You have selected "{}"'.format(value)

if __name__ == '__main__':
    app.run_server(debug=True)
```

### .gitignore
```:.gitignore
venv
*.pyc
.DS_Store
.env
```
### Procfile
```:Procfile
web: gunicorn app:server
```
### requirements.txtを作成
```:wsl
$ pip freeze > requirements.txt
```
# デプロイ
```:wsl
$ heroku create my-dash-app # change my-dash-app to a unique name
$ git add . # add all files to git
$ git commit -m 'Initial app boilerplate'
$ git push heroku master # deploy code to heroku
$ heroku ps:scale web=1  # run the app with a 1 heroku "dyno"
```
成功すると
https://my-dash-app.herokuapp.com
にアプリが公開される。
# コードの更新
```:wsl
$ git status # view the changes
$ git add .  # add all the changes
$ git commit -m 'a description of the changes'
$ git push heroku master
```

# 参考資料
* https://dash.plotly.com/deployment
LabelMEの使い方（セマンティックセグメンテーション用アノテーションツール）

# 本記事でわかること
- LabelMeのインストール方法、および使い方
- 出力ファイル(json)の画像化

# LabelMeってなに？
MITによって作られたアノテーションツールで、本記事ではセマンティックセグメンテーション用のアノテーションのために使っていきます。

# LabelMeのインストール
インストール方法は「Anaconda経由」と「venv+pip経由」の2通りを紹介します。
といっても中身は対して変わりません。お好きな方をどうぞ。
※それぞれ、Anacondaをインストール済み、Pythonをインストール済みを前提条件としています。
※詳細は[こちら](https://github.com/wkentaro/labelme)から。

## Anaconda経由のインストール

```console
conda create --name=[任意の仮想環境名] python=[任意のPythonのversion]
activate [任意の仮想環境名]
conda install pyqt
pip install labelme
```

## venv+pip経由のインストール

```console
python -m venv [任意の仮想環境名]
./[任意の仮想環境名]/Scripts/activate
pip install labelme PyQt5
```

# LabelMeの起動
以下のコードを実行すると、ウィンドウが開きます。

```console
labelme
```

![labelmeの使用手順.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1538778/189d6bf1-f4d9-733d-3f5b-d78eff852866.png)

# LabelMEの使用手順

上の画像に振った番号の通りです。
①　画像の入ったフォルダを開きます。
②　マウスでカチカチして任意の物体を囲みます。囲み終わると「クラス名」を聞かれるので、入力しましょう。
③　必要なら修正します。
④　アノテーションデータを保存します。(①で指定したフォルダを確認すると○○.jsonというファイルが生成されてると思います。)
⑤　次の画像にいきましょう。（①に戻る。）

# json から PNG へ

生成されたjsonファイルですが、このままではうまくアノテーションできたか確認しづらいかと思います。なので、画像化することで視覚的に確認していきましょう。以下のコードを実行してください。

```console
labelme_json_to_dataset ○○.json
```

すると「○○_json」というフォルダができ、その中に以下の4点が生成されます。

- img.png
- label.png
- label_names.txt
- label_viz.png

![labelmeの生成ファイル.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1538778/d9946d44-e0cc-0759-7b9f-6e7e77f4f725.png)



# さいごに
本記事では、LabelMEを用いてセマンティックセグメンテーション用のアノテーション作業を紹介しました。
他にもインスタンスセグメンテーション用に変換もできるようなので、試してみたいところ。
それでは～(^^)/
【Swift】画面の戻り方のまとめ

Swiftで画面を戻る処理が何種類かあるのでまとめてみました。

## モーダル型で戻る

```swift
self.dismiss(animated: true, completion: nil)
```
`dismiss`で画面を破棄しています。

## モーダル型で2つ前の画面に戻る

```swift
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
```
2つ前の画面に戻るコードです。

## １つ前の画面へ戻る(NavigationController)

```swift
self.navigationController?.popViewController(animated: true)
```
NavigationControllerで１つ前の画面へ戻る処理。

## トップの階層へ戻る(NavigationController)

```swift
self.navigationController?.popToRootViewController(animated: true)
```
NavigationControllerでトップの階層へ戻る処理。

## 任意の階層へ戻る(NavigationController)

```swift
self.navigationController?.popToViewController(navigationController!.viewControllers[階層の番号], animated: true)
```
NavigationControllerで任意の階層へ戻る処理。

＊戻るだけで先に進むことはできません。

## 参考
https://naoya-ono.com/swift/navigation-controller-back/
https://qiita.com/Walkdream24/items/787df7d5b6e85330416a

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
プログラミング初学者がAtCoder茶色に到達するまでの学習ステップ

#自己紹介
当記事を閲覧してくださり誠にありがとうございます。

都内の私立大学経営学部に在籍しているさんちょと申します。

プログラミングを始めて半年ちょいのプログラミング初学者(Python)です。

#はじめに
当記事はプログラミング初学者が[AtCoder](https://atcoder.jp/)に登録して<font color=#663300>茶色</font>(レーティング562)に到達するまでに行った学習ステップを簡単に記録したものとなっております。
![スクリーンショット 2021-11-25 14.58.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502618/3b06e059-5d10-6e81-ba07-c0cbe9466da0.png)



#AtCoderとは
アルゴリズムに関する問題をプログラミングによって解き、解いた問題数や時間を競い合う競技プログラミングのコンテストを開催する国内最大級のサイト

ユーザーはコンテストの結果に応じてサイト内でレーティングされ、レーティングに応じてランク(色)が付されます。

|レーティング|ランク(色)|ユーザー分布|
|:------------------|----------:|:------------------:|
|2800-|<font color=red>赤</font>|上位0.2%|
|2400-2799|<font color=#FF773E>燈</font>|上位0.6%|
|2000-2399|<font color=#FFD700>黄</font>|上位2%|
|1600-1999|<font color=blue>青</font>|上位5%|
|1200-1599|<font color=#77EEFF>水</font>|上位10%|
|800-1199|<font color=green>緑</font>|上位20%|
|400-799|<font color=#663300>茶</font>|上位35%|
|-399|<font color=#BBBBBB>灰</font>|上位100%|
※ユーザー分布は2021/11/25時点

#学習ステップ
##1. ABC(AtCoder Beginner Contest)に参加してみる
重要なことはAtCoderを体験してみることです。

- ユーザー登録
- AtCoder内で最も簡易的なコンテストABCに参加

現在の自分の実力を確かめてみましょう！

##2. AtCoder Problemsで過去問
他ジャンルの学習法と同様にAtCoderでも過去問練習が重要です。

- [AtCoder Problems](https://kenkoooo.com/atcoder/#/table)でUser IDを入力
- UserのRecommendation機能をチェック
→自分のレベル感に適した問題が自動的に提示

- EasyとModerateに取り組んでみましょう！
- 目安は1日3時間取り組んでEasy5問、Moderate2問程度

※Difficultは余力のある場合のみ取り組んでみて下さい。

##3. 解法の記録
競技プログラミングで重要なことの１つとしてアルゴリズムの理解度があります。

アルゴリズムの理解度を高めるために過去問やコンテストで解けなかった問題の解法(自分の解法と正解の解法)を逐一まとめておきましょう！

>例
>
>@Anti-Division　ABC137C問題
>
>◎A以上B以下の整数でCでもDでも割り切れない数の個数
>
>・自分の回答
>
>①BをCで割った切り捨て数-AをCで割った切り上げ数
>
>②BをDで割った切り捨て数-AをDで割った切り上げ数
>
>if B>C*Dの場合
>
>③BをC×Dで割った切り捨て数-AをC×Dで割った切り上げ数
>
>回答：(B-A)-①-②+③
>
>else
>
>回答：(B-A)-①-②
>
>・正解
>
>問題の条件を満たすB以下の整数の個数-問題の条件を満たす(A-1)以下の整数の個数
>
>問題の条件を満たすx以下の整数の個数は以下の式
>
>x-(x//C)-(x//D)+(x//lcm(C, D))
>

※自分がわかる程度で簡潔に書くことがポイント！

##4. 最後に
- 毎週開催されるABCに必ず参加

※頻繁に参加することでレーティング伸び率が向上

- A問題とB問題はできる限り早く解く
- C問題は時間をかけて必ず解く

まずはA,B,C問題を必ず解けるようになりましょう！
dockerネットワークについて調べる〜bridgeの仕組み編

今回のお題
-
今回はdockerネットワークの一つであるbridgeの仕組みについてまとめます。

[前回の記事](https://qiita.com/keishi04hrikzira/items/d6ae264b8740e6484685)でdockerのネットワークには３種類あるという話をしました。

本記事ではその中でも最も使用頻度の高いbridgeというネットワークの仕組みについて話します。

:::note info
以下で説明する内容については、コンテナ作成時に自動で設定されるものになります。
手動で実行する方法についても別途取り上げる予定ですが、実際に使用する機会は少ないかもしれません。
:::

目次
-

- ネットワーク内のコンテナ同士での通信の仕組み
- コンテナとホストOSの通信の仕組み
- コンテナと外部インターネットとの通信の仕組み

ネットワーク内のコンテナ同士での通信の仕組み
-
ネットワーク内のコンテナ同士での通信は、仮想スイッチと呼ばれる中継地点によって実現している。

すなわち、コンテナ同士で通信する場合には両者の間を直接情報が行き来するのではなく、一度仮想スイッチを経由して情報がやりとりされることになる。

このような通信方式は、内部的には仮想NICと呼ばれる存在によって実現している。

具体的にいうと、コンテナと仮想スイッチはそれぞれ仮想NICと呼ばれる窓口を持ち、これらを出入り口として情報のやり取りが行われている。

コンテナとホストOSの通信の仕組み
-
コンテナとホストOSの間での通信も基本的な仕組みは変わらない。
ホストOSは仮想NICの代わりに物理NICと呼ばれるNICを持っているのでそれを仮想スイッチと接続することで通信を成立させている。

コンテナと外部インターネットとの通信の仕組み
-
コンテナから外部インターネットに対してリクエストを送信する場合、発信元IPアドレスおよび宛先IPアドレスは以下のようになる。

````IPアドレスの情報
宛先 = リクエスト先のグローバルIPアドレス
発信元 = コンテナのプライベートIPアドレス
```

このような場合には、以下の2つの問題を抱えることになる。

<dl><dt>上記の情報だけでは、仮想スイッチが転送先を判断することができない</dt>
<dd>上記の宛先IPアドレスは仮想スイッチの属するサブネット内のものではないので、IPアドレスを解釈することができない</dd>
<dt>リクエストの受け手が宛先を解釈できない</dt>
<dd>リクエストの受取手はグローバルIPアドレスなら理解できるが、上記の情報では発信元IPがプライベートアドレスになっており解釈できない</dd></dl>

つまり、プライベートIPとグローバルIPが混在していることによって、仮想スイッチでもリクエスト先でも解釈できない状態になってしまっている。

bridgeではこの状況を`デフォルトゲートウェイ`と`NAT`によって解決している。

デフォルトゲートウェイとは仮想スイッチが受け取った送信先が同一サブネット内ではない（＝仮想スイッチが解釈できない）IPアドレスであった場合のデフォルトの送信先である。

これをホストOSの物理NICのIPアドレスにすることによって、グローバルIPへのリクエストをホストOSへ転送することが可能になる。

NATとはNetwork Address Transferの略であり、プライベートIPとグローバルIPを変換する技術を指す。

コンテナから外部へリクエストが送られる場合には、ホストOSの物理NICをまたぐ際に送信元のアドレスがプライベートIPからグローバルIPに変換されることで、リクエストの受け手が発信元を解釈できるようにしている。
【JavaScript】非同期処理⑨　例外処理とエラー


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/6e2bde23ab072e931009


#目的

* 非同期処理についての理解を深める

#本題
###1.例外処理とエラー

例外処理とはなにかエラーが発生した際に飛ぶ特別な処理のこと

####基本構文

````js
try{
  throw new Error();
} catch(e) {
  // エラーハンドリング
} finally {
  // 終了処理
}
`````

####例1

基本的な使い方

````main.js
// 動かしたいコードをtryの中に記述していく
try{
  console.log("start");
  // エラーを出力する　→　catchに移行する
  throw new Error("error message");
  // 上記で処理がcatchに移行するので下記endは出力されない
  console.log("end")
} catch(e) {
  console.error(e);
} finally {
  // 出力される終了処理
  console.log('bye');
}
`````

上記の出力結果は以下の通り

```console.
start
> Error: error message
    at main.js:5
bye
```


####例2

さらに実践的な使い方

**前提**

jsonファイルからデータを引っ張ってくるがあえてここではからにしておく（エラーを出すため）

````user.json
[

]
```

````main.js
async function fetchUsers() {
  const response = await fetch('users.json');
  const json = await response.json();
  return json;
}


async function init(){
  const users = await fetchUsers();
  for(const user of users) {
      console.log(`I'm ${user.name}, ${user.age} years old`)
  }
}

init();
````

user.jsonファイルが空欄なので何も出力されていないが、ここにエラーを表示する

```js
async function fetchUsers() {
  const response = await fetch('users.json');
  // 条件分岐でデータがうまく渡っている場合そうでない場合で分ける
  if (response.ok){
    const json = await response.json();
    // ここでjsonファイルが0だった場合にthrowでエラー処理をcatchに移行したい
    // jsonファイルのlength（配列の長さ）が0だった場合falseなので!演算子でtrueにする
    if(!json.length){
      throw new Error("no data found")
    }
    return json;
  } 
}

async function init(){
  // 上記の内容をtryで捌く
  try {
    const users = await fetchUsers();
    for(const user of users) {
        console.log(`I'm ${user.name}, ${user.age} years old`)
    }
  }catch(e){
    // ここでthrowを受けることでno data foundとエラー表示される
    console.error(e);
  }finally{
    // 終了処理はどちらにせよ出力される
    console.log('bye');
  }
}

init();
````

####例3

カスタムエラーに関して

````js
async function fetchUsers() {
  const response = await fetch('users.json');
  if (response.ok){
    const json = await response.json();
    if(!json.length){
      // ここでNoDataErrorを出力できるようにする
      throw new NoDataError("no data found")
    }
    return json;
  } 
}

// Errorを継承
// 条件分岐でエラーを出力したい場合に行う
class NoDataError extends Error {
  constructor(message){
    super(message);
    this.name = `NoDataError`;
  }
}

async function init(){
  try {
    const users = await fetchUsers();
    for(const user of users) {
        console.log(`I'm ${user.name}, ${user.age} years old`)
    }
  }catch(e){
    console.error(e);
  }finally{
    console.log('bye');
  }
}

init();
``````


今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
* [Let'sプログラミング JavaScript入門](https://www.javadrive.jp/javascript/)
コロナウイルスの日ごとの死者数をグラフ化

[厚生労働省オープンデータ](https://www.mhlw.go.jp/stf/covid-19/open-data.html)の死亡者数（累積）から日々の死亡者数のグラフをgoogle colaboratoryで作成

厚生労働省のオープンデータには累積の死亡者数しかなかったので
日ごとの死者数を算出してグラフ化してみました。
データはhttps://www.mhlw.go.jp/stf/covid-19/open-data.html
の「死亡者数（累積）」のcsvファイルを使って
google colaboratory でグラフ化しています。
コロナウイルスの現状把握に役立てられればと。

pandasとmatplotlibをimport

```python:import
import pandas as pd
import matplotlib.pyplot as plt
```


downloadした死亡者数（累積）のデータ　deaths_cumulative_daily.csv　を読み込み

```python:データ読み込み
df = pd.read_csv('https://covid19.mhlw.go.jp/public/opendata/deaths_cumulative_daily.csv')
```

グラフ化する都道府県をPrefectureに指定
全国は'ALL'
各都道府県は以下から
'Hokkaido', 'Aomori', 'Iwate', 'Miyagi', 'Akita', 'Yamagata', 'Fukushima', 'Ibaraki', 'Tochigi', 'Gunma', 'Saitama', 'Chiba', 'Tokyo', 'Kanagawa', 'Niigata', 'Toyama', 'Ishikawa', 'Fukui', 'Yamanashi', 'Nagano', 'Gifu', 'Shizuoka', 'Aichi', 'Mie', 'Shiga', 'Kyoto', 'Osaka', 'Hyogo', 'Nara', 'Wakayama', 'Tottori', 'Shimane', 'Okayama', 'Hiroshima', 'Yamaguchi', 'Tokushima', 'Kagawa', 'Ehime', 'Kochi', 'Fukuoka', 'Saga', 'Nagasaki', 'Kumamoto', 'Oita', 'Miyazaki', 'Kagoshima', 'Okinawa'

```python:都道府県選択
Prefecture = 'ALL'
```

選択した都道府県のデータをリストとして抜き出し Todayリストを作成

```python:Todayリスト
Today = list(df[Prefecture])
```

Today リストの先頭に元の先頭の要素を挿入し、最後尾の要素を削除してYesterdayリストを作成

```python:Yesterdayリスト
Today.insert(0,Today[0])
Today.pop()
Yesterday = Today
```

作成したYesterdayリストを'yesterday'列としてdfに読み込み

```python:Yesterdayリストをdfに読み込み
df['yesterday'] = Yesterday
```

選択した都道府県のデータからyesterdayを引くことで日ごとの死者数DailyDeathsを算出

```python:日ごとの死者数を算出
df['DailyDeaths'] = df[Prefecture] - df['yesterday']
```

Date列をdatetime型に変換

```python:datetime型に変換
df['Date'] = pd.to_datetime(df['Date'])
```

グラフ作成とファイル保存

```python:グラフ化とファイル保存
df.plot('Date','DailyDeaths')
plt.savefig('dailyDeaths.png')
plt.show()

```

![dailyDeaths.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181170/e5fb50bb-1e49-d447-7832-8b2da758bd3a.png)
美雲このはちゃんってなんだ？

いやっほー！たぽでーす！
今日は土曜日だね！！！寝たい！！！寝る！！！！
今回、初めてConoHa Advent Calendarに参加してみました！
技術的なことはあまりかけないので、精一杯美雲このはちゃんについて解説してみるよ！
##そもそも誰？
美雲このはちゃん(以下、このはちゃん)は、ConoHaの応援団長であり、神様を目指して修行中である！
座敷童子一族の末裔として生まれ、栃木の由緒正しい某神社で暮らしていたんだけど、昔からのしきたりで一人前の座敷童子になるため東京で修行をはじめたらしい。身長は150cm+αで、年齢はないが、13歳ぐらいらしい。
##このはちゃんを熱く語る
筆者はこのはちゃんのLINEスタンプを購入したことがあるが、そのスタンプを友達や家族に送ると99.9999999999%「かわいい」と言われる。
それはこのはちゃんが素晴らしく可愛いことが世界に知れ渡っていて、誰が見てもかわいいと感じることができるぐらいかわいいからである。
このはちゃんは清楚正しい、とのことであるが、本当に清楚正しく、清楚正しいのである！！！！！！！！！！！
また、このはちゃんのツイッターや壁紙を眺めていると、少しばかりではあるが元気が出る気がする。
##このはちゃんってどこがかわいい？
このはちゃんはいろんなイラストレーターさんが書いているが、どれもかわいい。
例えば[ホームページ](https://conoha.mikumo.com/)のトップにあるこのはちゃんは、ちょっと舌を出していてピースしているのがまたかわいいのだ....
先程ラインスタンプについて言及したが、[このスタンプ](https://store.line.me/stickershop/product/1859068/)について話してみる。
このスタンプはぴょこっと歩いているような、漫画に出てきそうな目や口、絵のタッチなどを見て、とてもかわいい、と感じた。特に「帰宅中」というスタンプはピョーンと歩いていて、やっぱりかわいいのだ。
#このはちゃんはなぜかわいい？
そもそもかわいいってなんなんだ？「かわいい」とは、いとおしさ、趣き深さなど、何らかの意味で「愛すべし」と感じられる場合に用いられるらしい。
例えば、かわいいと思う場面を探してみる。
まず人がかわいいと感じるのは、必ずしも「笑顔」ではない。泣いている時、恥ずかしがっている時、そういうときも「かわいい」と感じる。これにどうこのはちゃんが当てはまるのか...調べてみた。
例えばかわいいには複数の種類がある。例えばホームページのこのはちゃんは「美しい」というようなかわいいである。先程も言及したが、舌を出していたりしてやっぱりかわいい。
もうひとつのかわいいは、先程も言及したLINEスタンプは「ぴょこっとしてかわいい」と思うようだった。実際、家族などに聞いてみても、LINEスタンプについては「美しい」というより「ぴょこっとしている？」と思うようだ。
このはちゃんを「さらにかわいい」と思うためには、こういう種類豊富なこのはちゃんを摂取する必要があるのかもしれない。
##おわりに
たくさん書いていたら時間がなくなっちゃった...
このへんで終わりにしようと思う。この記事を書いてみて思った。さらにこのはちゃんが好きになり、さらに「かわいい」と感じるようになった。とてもいい機会だった。みんなもアドベントカレンダー、機会があったら書いてみてね！
おわり
Webの勉強はじめてみた その3 ～HTMLへの動画埋め込みとJS編のはじめに～

今日は2コマ受講しました。
ちょっとした自己紹介ページとJavaScriptのさわり。

<h2>今日やったこと</h2>
:::note
1. 動画埋め込み
2. document.write
:::

<h2>気付いたこと</h2>
:::note
1. ニコニコ動画はscript、YouTubeはiframe
2. JavaScriptにもバージョンがあった
3. テンプレートリテラル
:::

<h3>1. JavaScript と iframeの違い</h3>

https://note.com/zrmn/n/n2e4ac9129c45

あとvideoタグ、使ったことないけれど適宜使い分ける感じなのかな。

<h3>JavaScriptのバージョン</h3>
これ、初めて知りました。
とはいえよくわからないのが本音。

https://qiita.com/zenno04/items/df26932ef12b5dfe70fe

使うときにはそんな意識することでもないんだろうか？

<h3>テンプレートリテラル</h3>
こういうちょっとしたの好きかもしれない。
三項演算子みたいな。
`document.write(`101×180+3001÷11は${101*180+3001/11}です`);`



<h2>まとめ</h2>
いよいよJSに取り掛かるけれど、
忘れてるところも多数あるので一からやるつもりでがんばります。
Docker上でのStreamlit環境構築【Windows 10】

# はじめに

Windows環境で、数値計算の環境の事情(例えばcvxpyとか環境構築がめんどっちいとかの事情があります)からLinuxを使用したいことがあります。そのような場合、Dockerを用いるかと思います。しかしながら、streamlitをDockerのコンテナで実行した際、Webブラウザの見方があまり記事としてなかったので拙いながらもまとめてみます。

# 環境

- Windows 10
- Docker for Windows
- Python
    - streamlit

# コンテナの作成

下記のコマンドを実行しコンテナを作成する。

```
$ docker run -it -p 8501:8501 -v <パス>:/home/jovyan/work --name unko jupyter/datascience-notebook  /bin/bash
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/c9747caa-becd-84e4-b600-a1532afa05d1.png)

# Streamlitの実行

試しに下記のPythonファイルを実行することを考えます。

```python
import streamlit as st
st.title("Hello World !")
```

ターミナルでPythonファイルを実行してみます。

```
$ pip install streamlit
$ python -m streamlit run hello.py
```

それではブラウザで結果を表示してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/0ec27e71-7d27-b8d9-c435-eb5f4fb42381.png)
WSL2上のコンテナでの開発時にviteのホットリロードが効かない事象への対処法

## 概要
vite で立ち上げた vue3 + Typescript のプロジェクトにおいて、`.vue` ファイルを更新した際にホットリロードが効かなかった。


###環境情報
* vite: 2.6.4
* vue: 3.2.16



## 原因
WSL上での開発時にホットリロードが効かない現象があるとのこと。([issue](https://github.com/vitejs/vite/issues/1153))
VsCode の Remote Dev Container で、WSL2上のコンテナ上で開発していたため、これが原因。

## 対処方法

issueにもあるように、`vite.config.ts` にホットリロードの設定を追記する。

```diff:vite.config.ts
export default defineConfig({
  plugins: [vue()],
+ server: {
+   watch: {
+     usePolling: true
+   }
+ }
})
```
これでホットリロードが動くようになった。


## 参考
https://github.com/vitejs/vite/issues/1153
https://www.youtube.com/watch?v=BUClW9wTqGQ
mysqlのパスワードを変える方法

## 背景
AWSのEC２にデプロイするためにmysqlに入ろうとしたがパスワードが間違っていて入れず、パスワードを思い出すこともできなかったので再設定しました。

##/etc/my.cnf
vimで/etc/my.cnfを開き、[mysqld]の下にskip-grant-tablesと書きます。

```ruby:/etc/my.snf
[myaqld]
skip-grant-tables
```


##mysqlを再起動
mysqlを再起動します。

```
sudo service mysqld restart
```

##mysqlに接続

```
mysql -u root
```

mysqlに接続し、以下のように入力することでDB内のテーブルを再読み込みします。

```
mysql> flush privileges;
```

##新しいパスワードを設定！

```
alter user 'root@localhost' identified by '新しいパスワード'
```

新しいパスワードを設定したらDBから退出し、

```
mysql> quit
```

vim /etc/my.cnf内のskpip-grant-tablesを削除します。(あるいはコメントアウト)
そしてmysqlを再起動します。

##ついに接続！

```
mysql -u root -p
```
を入力し、先ほど作成したパスワードで接続できれば、パスワードの再設定は成功です！
自分メモ：バッチで文字の色を変える



# はじめに
バッチファイルのEchoで文字の色を変える方法が分かりましたので自分メモ

#環境
Microsoft Windows [Version 10.0.19043.1348]
\(2021年11月25日時点)

#わかる方への簡単な説明
エスケープシーケンスを使用して文字色を変更しています。
やり方としてEscコード(\x1b)を直接ソースに埋め込みます。

#サンプル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630870/6a40e5c2-1b38-bfd5-e0e5-2bd07001390a.png)

#ソース
```batch:test.bat
@echo off

echo STYLE
echo Reset    [0m
echo Bold     [1mTrue[0m
echo Inverse  [7mTrue[0m
echo Underline[4mTrue[0m

echo Black    [30mTrue[0m
echo Red      [31mTrue[0m
echo Green    [32mTrue[0m
echo Yellow   [33mTrue[0m
echo Blue     [34mTrue[0m
echo Magenta  [35mTrue[0m
echo Cyan     [36mTrue[0m
echo White    [37mTrue[0m

echo Black    [40mTrue[0m
echo Red      [41mTrue[0m
echo Green    [42mTrue[0m
echo Yellow   [43mTrue[0m
echo Blue     [44mTrue[0m
echo Magenta  [45mTrue[0m
echo Cyan     [46mTrue[0m
echo White    [47mTrue[0m

echo Black    [90mTrue[0m
echo Red      [91mTrue[0m
echo Green    [92mTrue[0m
echo Yellow   [93mTrue[0m
echo Blue     [94mTrue[0m
echo Magenta  [95mTrue[0m
echo Cyan     [96mTrue[0m
echo White    [97mTrue[0m

echo Black    [100mTrue[0m
echo Red      [101mTrue[0m
echo Green    [102mTrue[0m
echo Yellow   [103mTrue[0m
echo Blue     [104mTrue[0m
echo Magenta  [105mTrue[0m
echo Cyan     [106mTrue[0m
echo White    [107mTrue[0m
```

#ソース解説
上記のソースをコピペしても実現しません。
ちょっと工夫する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630870/89cb248c-e5c5-1bb9-2ced-e5bf63ea8881.png)

カーソル位置の文字コードを見ていただくと、\x1bとなっていることが確認できると思います。
つまり、エディタなどで直接\x1bを埋め込むことで実現できます。

サクラエディタの場合のやり方としては、仮の文字列を置換する方法が考えられます。
仮文字として"ESC"を置き、置換で"\x1b"に置換します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630870/49ee2059-7fdc-c6d7-afd1-2185a1497f1d.png)
Typoraエディタの使いづらさをカバーする方法


# はじめに
皆さん[Typoraエディタ](https://typora.io)使っていますでしょうか。
Markdownエディタでありながら、段落などの文章構造が見たまま反映されていく機能(WYSIWYG(ウィジウィグ))が備わったシンプルかつ高機能なエディタです。

しかしながら、リリースから相当時間のたった現在でもtyporaはbeta版として更新を続けており、いまだにfile treeに関してはお世辞にも扱いやすいとは言えません。
難点としては例えば

- tab機能がなく、複数ファイルを開くことができない
- file tree上で矢印キーが効かないので、いちいちマウスに手を伸ばす必要がある
- file treeはファイルの並び替えができず、大量のファイルがあると、目的のファイルを探すのに苦労する

などが挙げられます。
そこで、typora以外の機能と併用することによって、これらの難点をなるべく回避する方法を紹介します。

# 目次
1.[複数の文章を同時に開きたい(Mac版)](#1-複数の文章を同時に開きたい(Mac版))
2.[複数の文章を同時に開きたい(Windows版)](#2-複数の文章を同時に開きたい(Windows版))
3.[file treeをなんとかしたい](#3-file treeをなんとかしたい(Mac版))

#1.複数の文章を同時に開きたい(Mac版)
システム環境設定→Dock→書類を開くときはタブで開く
を「常に」に設定しておきましょう。
typora以外のアプリにも適用されてしまいますが、慣れれば便利です。
![スクリーンショット 2021-11-25 17.11.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622282/d803cc6e-246d-9869-ab5d-6168d3adb3d5.png)


#2.複数の文章を同時に開きたい(Windows版)
window tabsをインストールしましょう。
https://github.com/mauricef/WindowTabs


#3.file treeをなんとかしたい(Mac版)
本末転倒のようですが、そもそもtypora上でファイルを選択するのを辞めれば解決します。ファイル選択はFinderから行いましょう。

まず、何かのマークダウンファイル(.md)の「情報を見る」から、「このアプリケーションで開く」の設定でtyporaを選択します。
同時に「すべてを変更...」に関しても有効にしておきます。

Macはcommand + tabでアプリを即座に切り替える機能があるので、複数アプリを横断するような使い方もそれほど苦ではないのです。
また、サイドバーも必然的に使用しなくなるので、画面も広く有効に活用でき、ファイルの並び替えに関しても気にしなくて良くなります。

# おわりに
可能な限りストレスを感じずにtyporaを使用する方法を紹介しました。今後もtypora活用のコツを紹介していこうと思います。


# 参考文献
- [全Windowタブ化。Setsで頓挫した夢の操作性をオープンソースのWindowTabsで再現する。](https://qiita.com/standard-software/items/dd25270fa3895365fced)
(未完) SATySFiで起きるエラー（雑記）

warning，どんな言語でもなんか出るけどうまくいくという事象ってよくあると思うんですけど，出てたら嫌な気分になりますし，なんとか解消しようと試みがちです．

今回はSATySFiで出会ったerror，warningのうち，（正しく？）解決できたものを書いてみます．

## Warning

### [Warning] a line unable to be broken into a paragraph occurs on page 1


```
  breaking contents into pages ...
LineBreak> UNREACHABLE
  [Warning] a line unable to be broken into a paragraph occurs on page 1
```

のようなもの．
どこで吐いてるのかがわかりにくくて微妙な気分になります．
このときは，

```
satysfi hoge.saty --debug-show-block-bbox
```

が効きました．
これを使った結果，右端まで埋まっていないblock boxがみつかり，そこの部分に対応するコードがinline-filされていないために起きているwarningでした．