OmniAICreator/Qiita-1.07M huggingface dataset:
エクスプローラーが散らかってしまう？ PowerShellで整理できました！

私がWindows環境で作業をしていると、いつの間にか色々なアプリケーションのウインドウが表示されています。
目的のウインドウに切り替えようとすると、ウインドウをかきわけるのに、何度もマウス操作しなければなりません。タスクバーの操作でも、何回かクリックが必要です。
特に、10個ぐらい開いてしまっているエクスプローラーの操作が大変です。

そこで、PowerShellを使って、これらのエクスプローラーをきれいに並べることで、扱いやすくしてみました。

# ポイント

1. `$shell=New-Object -ComObject Shell.Application; $shell.Windows()` でエクスプローラーの情報を取得できました。
2. `$shell.Windows() | foreach { $_.Left=0; $_.Top=0; $_.Width=800; $_.Height=600; }` でエクスプローラーの位置とサイズを変更できました。
3. `[System.Windows.Forms.Screen]::PrimaryScreen` や `[System.Windows.Forms.Screen]::AllScreens` で画面サイズを取得できました。

# 結果イメージ

次のように、エクスプローラーを並べてみました。

![コメント 2020-07-26 203203_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24511/7ef3ddbd-9eef-d2ea-a616-4d8095010b44.png)

# スクリプト

画面の左上から右下へ、少しずらしながら重ねて並べる。
なお、重ねる順番は、表示しているパス順にしました。

```powershell:エクスプローラーを左上から並べる.ps1
$w = 800
$h = 600
$x = 0
$y = 0
$dx = 30
$dy = 30
$shell = New-Object -ComObject Shell.Application
$shell.Windows() | where { $_.Name -eq "エクスプローラー" } | sort LocationURL | foreach {
  $_.Left=$x; $_.Top=$y; $_.Width=$w; $_.Height=$h; $x+=$dx; $y+=$dy;
}
```

同様に、画面右下を基準に並べる。

```powershell:エクスプローラーを右下から並べる.ps1
Add-Type -AssemblyName System.Windows.Forms
$sw = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Width
$sh = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Height
$w = 800
$h = 600
$x = $sw - $w
$y = $sh - $h
$dx = -30
$dy = -30
$shell = New-Object -ComObject Shell.Application
$shell.Windows() | where { $_.Name -eq "エクスプローラー" } | sort LocationURL | foreach {
  $_.Left=$x; $_.Top=$y; $_.Width=$w; $_.Height=$h; $x+=$dx; $y+=$dy;
}
```

# 動作確認環境

- Windows 10
- PowerShell 5.1

# 参考にさせていただいたサイト

- [powershell - HWNDを使用してIEウィンドウを選択](https://stackoverrun.com/ja/q/10196792)
- [[ Windows ] PowerShellからマルチスクリーンの解像度を取得 | 映像とその周辺](https://www.kalium.net/image/2017/07/31/powershell%E3%81%8B%E3%82%89%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%81%AE%E8%A7%A3%E5%83%8F%E5%BA%A6%E3%82%92%E5%8F%96%E5%BE%97/)
VueのComposition APIをTypescriptで使う際に覚えておくと便利なこと

## はじめに

Composition API を Typescript で使う際にハマったことの備忘録です。
随時更新していく予定。

Vue3 の環境構築は[こちら](https://qiita.com/eyuta/items/ba9a5dc5cc35e733853e)から。vue-cli からかんたんに Vue3 環境を作成できます。

## Version

```sh
Vue: 3.0.0
@vue/cli: 4.5.0
Typescript: 3.9.3
```

## Tips

### 1. Recursive Type References

[Composition API RFC](https://composition-api.vuejs.org/#basic-example) のコードをそのまま Typescript で実行すると、以下のエラーが表示されます。
`state` の定義中に、 自分自身(`state`)を使用しているためです。
(Typescript のバージョンによっては発生しないらしいです)

```txt
'state' implicitly has type 'any' because it does not have a type
annotation and is referenced directly or indirectly in its own initializer.
```

```ts
setup() {
  const state = reactive({
    count: 0,
    double: computed(() => state.count * 2)
  });
  return { state };
}
```

```ts
// use interface
interface Counter {
  count: number;
  double: number;
}
setup() {
  const state: Counter = reactive({
    count: 0,
    double: computed(() => state.count * 2)
  });
  return { state };
}

```

```ts
// use ref
setup() {
  const count = ref(0);
  const double = computed(() => count.value * 2);

  function increment() {
    count.value++;
  }

  return {
    count,
    double,
    increment
  };
}
```

ref. [Typescript state auto-typing and implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer #131](https://github.com/vuejs/composition-api/issues/131)

### 2. `props` で型推論が効くようにする

そのままだと `props` にほとんど補完が効かないため、 `props` に `ComponentObjectPropsOptions` を付与します。
こうすることで、 `props` に指定した `prop` に対し、 `default`, `required` といった property が補完されます。

```ts
import { defineComponent, ComponentObjectPropsOptions } from "vue";

interface CustomProps {
  msg: string;
}
export default defineComponent({
  name: "Home",
  props: {
    msg: {
      required: true,
      type: String,
      default: "",
    },
  } as ComponentObjectPropsOptions<CustomProps>,
});
```

以下の図で、 `required` が推論されているのが分かります。

- before
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110860/27a12b24-77a2-1334-18f8-225fb1307585.png)
- after
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110860/384adff4-f0a0-680d-a71e-a5e917a0dd62.png)

また、`defineComponent` の generics に任意の Type を与えることで、 `prop` の型を縛ることができます。
上記のコードでは、 `CustomProps.msg` の型が `string` のため、 `props.msg.type` に `String` 以外を指定するとエラーになります。
※ `defineComponent<CustomProps>` でもできそうですが、うまくいきませんでした...
うまい方法を知っている方がいらっしゃったらご教示いただけると嬉しいです。
統計メモ：期待値

期待値や分散の計算は非常によく使うので整理。性質は一度納得したら覚えておくとスムーズ

## 期待値の定義
連続型確率変数$X$に関する$f(X)$ の期待値は

$$
E_{X}[f(X)] = \int_{\mathbb{R}} f(x) p(x) d x
$$
$E_{x}[\cdot]$ は$X$に関して期待値をとる操作



## よく使う期待値の性質

### 1.定数の期待値
定数の期待値は定数になる（$a$は定数）

$$
E_{X}[a] = a\\
$$

### 2. 線形性
確率変数が$X$のみの場合

```math
E_{X}[af(X) + bg(X)] = aE_{X}[f(X)] + bE_{X}[g(X)]
```
  
  
  
複数の確率変数$X, Y$ についても線形性は保たれる

```math
E_{XY}[af(X) + bg(Y)] = aE_{X}[f(X)] + bE_{Y}[g(Y)]
```
上の式は、$X, Y$が互いに独立でなくても成立する

## 証明
### 1. 定数の期待値

```math
\begin{aligned}
E_{X} [ a ] &=\int a p(x) d x \\
&=a \int p(x) d x=a
\end{aligned}
```
### 2.線形性
確率変数が$X$のみの場合。期待値は積分（離散変数の場合総和）で定義されているため線形性が保たれる

```math
\begin{align}
E_{x} [a f(x)+b g(x)] &=\int \left\{ af(x)+b g(x) \right\}p(x) dx\\
&=a \int f(x)p(x) d x+b \int g(x)p(x) d x \\
&=a E_{X} [f(x)] + b E_{X}[g(x)]
\end{align}
```

複数の確率変数$X, Y$ の場合、期待値は同時確率 $p(x, y)$ を使いますが、周辺化されるため結果は単純になる

```math
\begin{align}
E_{XY}\left[f(X)+g(Y)\right] &=\iint \{ f(x)+g(y) \} p(x, y) d x d y \\
&=\iint f(x) p(x, y) d x d y+\iint g(y) p(x, y) d x d y \\
&=\int f(x)[\int p(x, y) d y] d x+\int g(y)[\int p(x, y) d x] d y \\
&=\int f(x) p(x) d x+\int g(y) p(y) d y
\end{align}
```

2行目から3行目の変形は周辺化 $ p(x)= \int p(x, y)dy$ を用いた

## 例

期待値の線形性から**和の期待値は期待値の和**となるが、これはよく使う

```math
E_{XY}[X + Y] = E_{X}[X] + E_{Y}[Y]
```

正規分布に従う2つの変数$X$と$Y$ があり、平均がそれぞれ$\mu_{x}, \mu_{y}$ の正規分布に従っているとする

```math
\begin{array}{l}
X \sim \mathcal{N}\left(\mu_{x}, \sigma_{x}^{2}\right) \\
Y \sim \mathcal{N}\left(\mu_{y}, \sigma_{y}^{2}\right) \\
\end{array}
```

$X$と$Y$の 和の確率変数$X + Y$ の平均は$\mu_{x}+\mu_{y}$ となる

```math
{E[X+Y]=E[X]+E[Y]=\mu_{x}+\mu_{y}}
```

---

私がよく分からなくなるのが以下です。
- 何に関しての期待値を取っているのか
- 変数同士の独立を仮定しているのか
日々精進。
ゼロからのプログラミング学習記録（仮）　DAY 1

【課題】
・まずは着手すること
・自己分析、キャリアプラン等の整理
・progate走り切り

<h1>progateから着手するのがおすすめらしい</h1>
<p>said by ホリエモン</p>
「SciPyを使わずに数値積分」を参考にしました。

(オリジナルポスト)

https://qiita.com/Tomhiro_Wiuchi/items/c7c70a646e5e55afb09f

(参考)

https://qiita.com/ykchat/items/5fc04bf80d24928a241c

##Wolfram|Alpha 日本語版で実行しました。

https://ja.wolframalpha.com/input/?i=∫%5B0から1%5D%284%2F%281%2Bx%5E2%29%29dx+定積分

##online sympyで実行しました。

https://live.sympy.org

print(integrate((4/(1+x**2)),(x, 0, 1))) 
pi
Pythonでファイルの文字列をデコードする。(Quated-pritableを読めるようにする)

最近会社で文字列でコード処理を書く必要があったので軽くメモとして残しておきます。

よくあるシチュエーションですが、保守対応でエンコード後のファイイルだけが資料として存在しているためデコードして読めるようにする必要があるという物です。


以下のコードでquoted-pritableを可読なものに変更します。

```python
import sys
import quopri
args=sys.argv

inputfile = args[1]
outputfile = args[2]

# ファイル読み込み
with open(inputfile, 'r', encoding='utf-8') as f:

#with open(inputfile, 'b') as f:
    data = f.read()  

# 変換
pre_decoded = quopri.decodestring(data,header=False)
decoded = pre_decoded.decode("utf-8", "ignore")

# 出力
with open(outputfile, 'w', encoding='utf-8') as fo:
    fo.write(decoded)
```

[参考ブログURL](https://mahimahironron.hateblo.jp/entry/2020/07/26/Pythonでファイルの文字列をデコードする%E3%80%82%28Quated-pritableを読)
Google ColabでGoogle driveの公開ファイルを直接ダウンロードする方法

#1.はじめに
　**Google Colab** で　**Google drive の公開ファイル** (例えば、fastText日本語版の学習済みモデルとか) を使う場合は、PCに一旦ダウンロードしてから Google drive経由で使うのが一般的だと思います。

　普通はこの方法で問題ないわけですが、場合によっては **わざわざ別途手動でダウンロードせずに**、Google Colab を先頭からポチポチするだけで動くコードにしたいと思ったりするわけです。

　今回は、そのための良い方法をWebで見つけましたので、備忘録として残します。

#2.サンプルコード
　サンプル例は、**fastText日本語版学習済みモデル** です。[**URL**](https://drive.google.com/file/d/0ByFQ96A4DgSPUm9wVWRLdm5qbmc/view)をクリックすると、まずこの画面が現れます。

![スクリーンショット 2020-07-26 19.08.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/1e635870-09ff-b4ad-b559-cec77eb617a7.png)

　この画面で、赤枠のボタンを押すと、ダウンロード画面になります。

![スクリーンショット 2020-07-26 19.10.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/2ee2f367-9363-be24-7aa6-ba6c7554371c.png)

　そうしたら、この**ダウンロード画面のURL**を控えておきます。後は、以下のコードで、直接ダウンロード出来ます。


```python
# Google drive からfastText日本語モデル(vector_neologd.zip)をダウンロードする
import requests

def download_file_from_google_drive(id, destination):
    
       # ダウンロード画面のURL
       URL = "https://drive.google.com/uc?id=0ByFQ96A4DgSPUm9wVWRLdm5qbmc&export=download" 

       session = requests.Session()

       response = session.get(URL, params = { 'id' : id }, stream = True)
       token = get_confirm_token(response)

       if token:
           params = { 'id' : id, 'confirm' : token }
           response = session.get(URL, params = params, stream = True)

       save_response_content(response, destination)    

def get_confirm_token(response):
       for key, value in response.cookies.items():
           if key.startswith('download_warning'):
               return value

       return None

def save_response_content(response, destination):
       CHUNK_SIZE = 32768

       with open(destination, "wb") as f:
           for chunk in response.iter_content(CHUNK_SIZE):
               if chunk: # filter out keep-alive new chunks
                   f.write(chunk)

if __name__ == "__main__":
       file_id = 'TAKE ID FROM SHAREABLE LINK' 
       destination = './data/vector_neologd.zip'  # 保存先パスの指定
       download_file_from_google_drive(file_id, destination)
```
enjoy !

（参考)
[Python: download files from google drive using url](https://stackoverrun.com/ja/q/10613995)

#＜追記 2021.5.29＞
　少し前から、Colab にこのためのライブラリー **gdown** が組み込まれて簡単になったので、追記します。
例えば、
表示リンク: **https://drive.google.com/file/d/1vcxH6JOtwh_-FoZ8SNXYlHF9qCi3YoDH/view** 
ダウンロードリンク: **https://drive.google.com/u/1/uc?id=1vcxH6JOtwh_-FoZ8SNXYlHF9qCi3YoDH&export=download**　
のときは、
**1vcxH6JOtwh_-FoZ8SNXYlHF9qCi3YoDH** が**id**です。このとき、ダウンロードするファイルが、**food_101.zip** であれば、下記のコードでダウンロードできます。

```python
import gdown
gdown.download('https://drive.google.com/uc?id=1vcxH6JOtwh_-FoZ8SNXYlHF9qCi3YoDH', 'food_101.zip', quiet=False)
! unzip food_101.zip
```
　これだけです。超簡単になりました！　colab はだんだんと使いやすくなっていますね。
clang で __chkstk が見つからないときのメモ


`undefined symbol: __chkstk`

と出る.

https://github.com/ispc/ispc/issues/542

コードのどこかで `__chkstk` を参照しているものがあると思われる. vcruntime(?) にある関数
mingw gcc だと libgcc をリンクすれば似たような関数をアサインする(?)ことで解決できるようだが, clang の場合はない.

とりあえずは適当にカラの関数をでっち上げて解決する.
SQLアンチパターン　Entity Attribute Value

# Entity Attribute Value

可変属性をサポートするなどの柔軟な設計を目指したことに起因するアンチパターン。

# テーブル設計

Entity Attribute Value（以下EAV）では次のような項目を持ったテーブルが設計される。

|名称|役割|
|:---|:---|
|Entity|親テーブルに対応した外部キーを格納|
|Attribute|カラム名に相当する属性名を指定|
|Value|属性の値|

***Book***

|book_id|
|:---|
|1|

***BookAttribute***

|book_id|attr_name|attr_value|
|:---|:---|:---|
|1|name|エンジニアになろう|
|1|status|used|
|1|creater|USER1|
|1|price|3520|
|1|page|450|
|1|release_date|2020/9/24|
|1|review|3.5|
|1|size|5x20x25cm|

## メリット

* テーブルの列数を削減できる
* 新規の属性を追加する際に列数を増加しなくて良い
* 属性が存在しない列にNULLが入りNULLだらけのテーブルにならない
* データベースの構造は単純になる

## デメリット

* データの取得が冗長化する
* 特定の属性にNOT NULL制約を設定できない
* データ型を使用できない
* 外部制約キーを使用できない
* 動的に属性名が増えるため整合性が担保しづらい

### データの取得が冗長化する

***Book（EAVを使用していない）***

|book_id|name|status|creater|
|:---|:---|:---|:---|
|1|エンジニアになろう|used|USER1|

***BookAttribute（EAVを使用）***

|book_id|attr_name|attr_value|
|:---|:---|:---|
|1|name|エンジニアになろう|
|1|status|used|
|1|creater|USER1|

「作成者（creater）」を取得したい場合、EAV設計をしない設計では「creater」が存在して入れば１文で必要なデータを取得できるが、EAV設計の場合では「attr_name」で必要なデータを条件として取得する必要がある

### 特定の属性にNOT NULL制約を設定できない

EAV設計の場合、特定の属性（「attr_name」の「creater」など）に対して個別にNOT NULL制約をつけることができない。

### データ型を使用できない

Attribute複数のデータを格納するためデータ型を使用できない。
時間や数値が混在するため文字列として指定することが基本となる。
また同じ日付を格納するにしても「2020−1−1」と登録するパターンや「2020/1/1」と登録するパターンなどが混在しデータの整合性が取りづらい

### 外部制約キーを使用できない

「attr_name」のうちの１つの属性に対してに外部キーを設定してしまうと全ての属性に制約がかかってしまうため使用できない

### 動的に属性名が増えるため整合性が担保しづらい

|book_id|attr_name|attr_value|
|:---|:---|:---|
|1|name|エンジニアになろう|
|1|book_name|エンジニアになろう|
|1|status|used|
|1|creater|USER1|

属性名が動的に増える可能性があるため整合性が担保しづらい。
上記のように「name」と「book_name」のように同じ本の名称を表す属性が複数登録されてしまうことがあるためあらかじめ属性名を統一して定義しておかないと整合性の担保が難しい。

# 次回

ポリモーフィック関連

# 参考文献

[SQLアンチパターン](
https://www.amazon.co.jp/SQL%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-Bill-Karwin/dp/4873115892/ref=sr_1_1?adgrpid=104444684056&dchild=1&gclid=CjwKCAjw4_H6BRALEiwAvgfzqy-f83NTsyQkauo7gn6ysgAPmJvKyvuI5FaXFnxFmhVfCzCRRACsaBoCY-oQAvD_BwE&hvadid=447984765572&hvdev=c&hvlocphy=1009332&hvnetw=g&hvqmt=e&hvrand=13417269104929133208&hvtargid=kwd-335484809678&hydadcr=27264_11561110&jp-ad-ap=0&keywords=sql%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3&qid=1599934568&sr=8-1&tag=googhydr-22)

![参考文献.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257405/b46d45ab-75ec-a620-eeb2-a422f6b1e659.jpeg)
４連休だったからmarkdownに時間を追加してプレビューするvscode extension作った

## 感謝
https://github.com/showdownjs/showdown
上記repositoryをcloneして中身を編集して使いました
テストは高速、buildもタスクで一発だった。
素晴らしいリポジトリだった

https://github.com/kajirikajiri/showdown
オプションとか、正規表現とか追加したバージョン

## 概要
![コメント 2020-07-26 190357.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253014/b827ec7c-db36-d400-bad3-64b5d5525917.png)

## extension
https://marketplace.visualstudio.com/items?itemName=kajiri.kajiri

## 使い方
h1~5タグに{{number}}を追加します
numberは時間です

あとはextensionを実行するとプレビューが見れます(kajiri start)

## github
https://github.com/kajirikajiri/vscode-extension


## 感想
タスクを管理できるものが欲しかった
trelloとかasanaほど高機能さは求めていなかった
plantumlのgantで管理しようかと思ったけど、betaだからどうなるかわからない感じだった
考えた結果、markdownでガントチャートみたいなものを作った
正規表現でh1~5タグの後ろの{{number}}を取得しています
あとはフロントでうまいことやってます

gruntは知ってたけど。使い方知らなかった。お手軽だった。タスクランナー
他人のコードを読むのは勉強になった

extensionはTypeScriptで書いた
最近TypeScript使ってるけど、vscodeの補完が便利になるし、すぐエラー出力してくれていい。

---
最近はobsidianをメモ帳に使ってます
https://obsidian.md/

実行コマンドがkajiri startになってしまった
【Microsoft Azure】Windows10の仮想マシンに入れたアプリが文字化けする

AzureでWindows10の仮想マシンを作った。
日本語専用のとあるアプリをインストールしたら文字化けしてしまった。

Windowsに日本語の言語パックはインストール済み。地域設定も日本に変更したのにおかしい。調べたら**システムロケールの変更**ができていない事が原因だった。

わかってしまえば「そんな簡単なことかよ〜〜！！」という話だが、困っている人がいるかもしれないでメモを残す。

#システムロケールの変更方法
<img width="1013" alt="スクリーンショット 2020-07-26 17.06.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241418/d2f80fbe-023b-941e-ab3e-9f6c18fde5c2.png">
設定から時刻と言語を選び、地域のページ下部にある「日付、時刻、地域の追加設定」をクリック。

<img width="480" alt="スクリーンショット 2020-07-26 17.07.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241418/9fb9cd07-54d8-f8c1-41eb-8fc9237aaacf.png">
システムロケールの変更をクリック。

<img width="439" alt="スクリーンショット 2020-07-26 17.07.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241418/9259c6a8-3e11-4728-e97f-468fa1f147f9.png">
現在のシステムロケールを「日本語」にしてOKをクリック。
再起動をすると文字化けが直った。

以上。
【C#】seleninmでスクレイピング

#参考
[Seleniumブラウザー自動化プロジェクト](https://www.selenium.dev/documentation/ja/)

PHPやPythonでスクレイピングの勉強をしていたのですが、
「Selenium」が様々な言語に対応しているという事と、
以前クラウドソーシングでC#の「Selenium」があったので、サンプルを記載しました。

##事前準備
####Nugetパッケージで以下をインストールします。
・Selenium.Support
・Selenium.WebDriver

####Chromeドライバをダウンロードします。
[Chromeドライバ](https://sites.google.com/a/chromium.org/chromedriver/downloads)から、自分の端末のChromeとバージョンが一致するものをダウンロードしてください。
今回のサンプルでは、「C:\\webdriver」にフォルダに配置しています。

##コード
以下は、amazonのサイトで、検索結果を取得するサンプルです。
「テレビ 4K」を検索エリアに入力して、検索後、タイトルを取得＆コンソール出力しています。
セレクタとかは、[セレクタ](https://www.selenium.dev/documentation/ja/getting_started_with_webdriver/locating_elements/)にわかりやすく各言語の説明が書かれています。

```
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace SeleniumCSharp
{
    public partial class Main
    {
        public Main()
        {
            scriping();
        }

        [Obsolete]
        private void scriping()
        {
            IWebDriver driver = new ChromeDriver("C:\\webdriver");
            //Webページを開く
            driver.Navigate().GoToUrl("https://www.amazon.co.jp/");

            //検索ボックスに入力
            IWebElement searchtextbox = driver.FindElement(By.Id("twotabsearchtextbox"));
            searchtextbox.SendKeys("テレビ 4K");

            //検索実行
            IWebElement searchbtn = driver.FindElement(By.ClassName("nav-input"));
            searchbtn.Click();

            //画面の表示が終わるまで待機（最大１０秒）
            TimeSpan TIMEOUT = new TimeSpan(0, 0, 10); // 10秒
            WebDriverWait wait = new WebDriverWait(driver, TIMEOUT);
            wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(By.CssSelector("span.a-size-base-plus")));
            //要素を探す（タイトル）
            IReadOnlyList<IWebElement> spans = driver.FindElements(By.CssSelector("span.a-size-base-plus"));
            //各要素を出力
            foreach (IWebElement span in spans)
            {
                //商品名を出力
                Console.WriteLine( span.Text);
            }
        }
    }
}
```
初心者によるプログラミング学習ログ 382日目

#100日チャレンジの382日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
382日目は、<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>昨日の作業・やったこと⇩<br><br>●就寝前筋トレ5分、キンドル読書 10分<br>●ブログ1記事作成<br>●プログラミング学習382日目 2h<br>・メンターの課題<br>・背景スライドショー実装<br><br>日曜出勤せつない・・・<br>13連勤確定<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアとつながりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a><a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@社畜✕投資✕ブロガー (@ppmp65) <a href="https://twitter.com/ppmp65/status/1287120731348692992?ref_src=twsrc%5Etfw">July 25, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
djangoのデータベースをバックアップする方法


## バックアップの方法
formatを指定しない場合（--format jsonなどを書かない場合）はjson形式で出力されます。

### 全アプリの全テーブルデータを出力

```
python manage.py dumpdata > filename.json
```

### 特定のアプリの全テーブルデータを出力

```
python manage.py dumpdata app_name > filename.json
```

### 特定のアプリのあるテーブルデータを出力

```
python manage.py dumpdata app_name.table_name > filename.json
```

## リストアの方法

```
python manage.py loaddata filename.json
```


## 参考
- https://7me.oji.0j0.jp/2017/django-memo.html
- https://www.memory-lovers.blog/entry/2019/01/14/112429
Mastering the FreeRTOS Real Time Kernel-A Hands-On Tutorial Guildの日本語訳

# この記事について
FreeRTOSのチュートリアル
> https://www.freertos.org/Documentation/RTOS_book.html
161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf
© Real Time Engineers Ltd. 2016. All rights reserved.

の日本語訳です。
Note:
・自分が読んだ場所から訳しています。
・個人的に重要と思われる部分は勝手に<font color="Red">赤字</font>にしています
・日本語にするとむしろ不自然な部分は英語のままです。
・「port」という単語が良く出てきますが「コンパイラとプロセッサの組み合わせ」のことです。「環境」と読み替えてもいいかも。

# 目次
[Preface]()
[Chapter 1 FreeRTOSディストリビューション (The FreeRTOS Distribution)](https://qiita.com/azuki_bar/items/40e52851f52ae84d6a3e)
[Chpater 2 ヒープメモリ管理 (Heap Memory Management)](https://qiita.com/azuki_bar/items/912c892f23612c306cb6)
[Chapter 3 タスク管理 (Task Management)](https://qiita.com/azuki_bar/items/99e653a59b9ad0176179)
[Chapter 4 キュー管理 (Queue Management)](https://qiita.com/azuki_bar/items/bae5d8037145baa3b29c)
[Chapter 5 ソフトウェアタイマ管理(Software Timer Management)](https://qiita.com/azuki_bar/items/56c53fb3e21dc5994f7c)
[Chapter 6 割り込み管理 (Interrupt Management)](https://qiita.com/azuki_bar/items/7f31eb80e8b6b2eff17f)
[Chapter 7 リソース管理 (Resource Management)](https://qiita.com/azuki_bar/items/7b907e57a8e171f0d56c)
[Chapter 8 イベントグループ (Event Group)](https://qiita.com/azuki_bar/items/a1b627ae5cf5164822de)
[Chapter 9 タスク通知 (Task Notificaiton)](https://qiita.com/azuki_bar/items/7f3aecc8bb1928f6a823)
Chapter 10 Low Power Support(記載なし)
[Chapter 11 開発者サポート (Developer Support)](https://qiita.com/azuki_bar/items/aaad0984e7a652196f3c)
[Chapter 12 トラブルシューティング (Trouble Shooting)](https://qiita.com/azuki_bar/items/af3ababf0a986fe61097)
VultrにDocker環境を作成する

#はじめに
格安VPCの[Vultr](https://www.vultr.com/?ref=8632241)にDocker環境を作ります。構築中は最安プラン（$5/Month）でよいと思います。

#Vultrはじめにやること（詳細は省略）

構築中はファイアウォールで自分のみアクセスできるようにし2要素認証を有効にしておくことを推奨します。

- インスタンス作成
- ファイアウォールルール作成
- 2要素認証の有効化


##OSバージョンを確認
Ubuntuで環境作りたかったのでOSはUbuntu 20.04を選択しました。最新版のUbuntuが選択できるの嬉しいですね。
数分で環境ができあがりますのでSSHで接続してOSバージョンを確認してみます。

```shell
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```


##パッケージを最新版にする
とりあえずパッケージを最新にしておきます。

```shell
$ sudo apt install aptitude
$ sudo aptitude update
$ sudo aptitude upgrade
```

##SSHのセキュリティ対策
デフォルトだとSSHが22/TCPで接続を受け付けてしまうので待ち受けポート番号を変更します。ついでにrootでログインできないようにもします。（事前にユーザを作成しておいてくださいね）

```text:/etc/ssh/sshd_config
Port 9443
PermitRootLogin no
```


```shell
$ sudo service sshd restart
```


##タイムゾーンを日本に変更
```shell
$ timedatectl set-timezone Asia/Tokyo
$ timedatectl
               Local time: Sun 2020-07-26 11:29:38 JST
           Universal time: Sun 2020-07-26 02:29:38 UTC
                 RTC time: Sun 2020-07-26 02:29:39    
                Time zone: Asia/Tokyo (JST, +0900)    
System clock synchronized: yes                        
              NTP service: active                     
          RTC in local TZ: no 
```

#Dockerをインストール
Dockerをインストールします。公式サイトの手順通りです。

```shell
$ curl https://get.docker.com | sh
$ sudo usermod -aG docker <username>
$ sudo systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-07-26 11:13:14 JST; 16min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 568 (dockerd)
      Tasks: 27
     Memory: 121.6M
     CGroup: /system.slice/docker.service
             └─568 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

$ ps aux |grep docker
root         568  0.3  9.3 935036 93552 ?        Ssl  11:12   0:03 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

$ docker --version
Docker version 19.03.12, build 48a66213fe
```

#Docker Composeをインストール
Docker Composeをインストールします。公式サイトの手順通りですが最新バージョンのURL（1.26.2の部分）はタイミングによって変わるので確認しておいてください。

```shell
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.26.2, build eefe0d31
```

#スナップショットを取得
最低限の環境ができあがったところで[Vultr](https://www.vultr.com/?ref=8632241)でスナップショットを取得しておきましょう。これをやっておけばいつでもこの環境に戻すことが可能です。
![img05.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680666/55790faa-69da-d5ed-83ac-6726f213080c.jpeg)
Rust: CouchDB のデータを削除 (Delete)

```text:Cargo.toml
[package]
name = "couchdb_delete"
version = "0.1.0"
edition = "2018"

[dependencies]
reqwest = { version = "0.10", features = ["json"] }
tokio = { version = "0.2", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```

```rs:src/main.rs
// --------------------------------------------------------------------
/*
	couchdb_delete/src/main.rs

					Jul/26/2020
*/
// --------------------------------------------------------------------
use std::env;

#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
	eprintln!("*** 開始 ***");
	let args: Vec<_> = env::args().collect();
	let key_in = &args[1];
	eprintln!("{}",key_in);

	let url_base = "http://localhost:5984/nagano";
	let url = url_base.to_owned() + "/" + key_in;
	let client = reqwest::Client::new();
	let resp = client.get(&url)
		.send()
		.await?;

	let body = resp.text().await? ;

	let json: serde_json::Value = serde_json::from_str(&body)?;

	let obj = json.as_object().unwrap();

	if obj.contains_key("_rev") {
		println!("{}", obj["_rev"]);
		let url_aa = url.to_owned() + "?rev=" + &obj["_rev"].to_string();
		let url_delete = &url_aa.replace("\"","");

		println!("{}", url_delete);
		record_delete_proc(url_delete.to_string()).await?;
		}
	else {
		eprintln!("*** no key ***");
		}

	eprintln!("*** 終了 ***");

	Ok(())
}

// --------------------------------------------------------------------
async fn record_delete_proc(url_delete: String)
	-> Result<(), Box<dyn std::error::Error>> {
	let client_aa = reqwest::Client::new();
	let resp = client_aa
		.delete(&url_delete)
		.send()
		.await?;

	println!("{:#?}", resp);

	Ok(())
}

// --------------------------------------------------------------------
```

実行

```bash
cargo run t2023
```
Go Test を書いてみよう

Goには標準でテスト機能が組み込まれています。
Goのソースに対して、簡単なテストを書いてみましょう。

## 環境
```
% sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.5
BuildVersion:	19F101

% go version
go version go1.14.6 darwin/amd64
```

## サンプルのディレクトリ構造
今回のサンプルファイルは、下記のようになっています。

```
gotest
  |-- app.go      // アプリの処理 （アプリ名を返す関すのみ持っている）
  |-- app_test.go // app.go の関数をテストする
  |-- main.go     // app.go の関数を呼び出す
```

```ruby:main.go
package main

import (
	"fmt"
)

func main() {
	fmt.Println(AppName())
}
```

```ruby:app.go
package main

func AppName() string {
	return "My App Name"
}
```

```ruby:app_test.go
package main

import (
	"testing"
)

func TestAppName(t *testing.T) {
	expect := "My App Name"
	actual := AppName()

	if expect != actual {
		t.Errorf("%s != %s", expect, actual)
	}
}
```

## アプリの実行確認
まず、アプリが動作することを確認しましょう。アプリ名が出力されています。

```
% cd gotest
% go run main.go app.go
My App Name
```

## Go のテスト
出力の```[path]```は、各自環境でのフルパスになります。

```
% cd gotest
% go test
PASS
ok  	[path]/gotest	0.066s
```

オプション「-v」を付けると、テストの詳細が出力されます。
テストを複数実行する際に、活躍できそうです。

```
% go test -v
=== RUN   TestAppName
--- PASS: TestAppName (0.00s)
PASS
ok  	[path]/gotest	0.135s
```

## Go のテストを書く際の注意点
1. テストファイル名の終端は「_test.go」でなければならない。
2. テスト関数名は「Test」で始まらなければならない。
3. テストファイルは、"testing"パッケージを宣言し、利用する。
4. デフォルトでassertは用意されていないので、自作する必要がある。
Rust: CouchDB のデータを更新 (Update)

```text:Cargo.toml
[package]
name = "couchdb_update"
version = "0.1.0"
edition = "2018"

[dependencies]
reqwest = { version = "0.10", features = ["json"] }
tokio = { version = "0.2", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = "0.4"
```

```rs:src/main.rs
// --------------------------------------------------------------------
/*
	couchdb_update/src/main.rs

					Jul/26/2020
*/
// --------------------------------------------------------------------
use std::env;
use serde_json::json;
use chrono::{Local, Date};

// --------------------------------------------------------------------
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
	eprintln!("*** 開始 ***");
	let args: Vec<_> = env::args().collect();
	let key_in = &args[1];
	let population_in = &args[2];
	eprintln!("{}",key_in);
	eprintln!("{}",population_in);

	let pp_in: i32 = population_in.parse().unwrap();

	let url_base = "http://localhost:5984/nagano";
	let url = url_base.to_owned() + "/" + key_in;
	let client = reqwest::Client::new();
	let resp = client.get(&url)
		.send()
		.await?;

	let body = resp.text().await? ;

	let json: serde_json::Value = serde_json::from_str(&body)?;

	let obj = json.as_object().unwrap();

	if obj.contains_key("_rev") {
		let name_aa = obj["name"].to_string();
		let name_bb = name_aa.replace("\"","");
		println!("{}\t{}", obj["_rev"], name_bb);
		let url_aa = url.to_owned() + "?rev=" + &obj["_rev"].to_string();
		let url_update = &url_aa.replace("\"","");

		println!("{}", url_update);
		record_update_proc(url_update.to_string(),name_bb,pp_in).await?;
		}
	else {
		eprintln!("*** no key ***");
		}

	eprintln!("*** 終了 ***");

	Ok(())
}

// --------------------------------------------------------------------
async fn record_update_proc(url_update: String,name: String,pp_in:i32)
	-> Result<(), Box<dyn std::error::Error>> {
	eprintln!("record_update_proc *** {}",pp_in);
	let client_aa = reqwest::Client::new();

	let date_mod: Date<Local> = Local::today();
	println!("{}", date_mod);

	 let obj_new = json!({
		"name": name,
		"population": pp_in,
		"date_mod": date_mod.to_string()
		});

	let json_str = obj_new.to_string();
	eprintln!("{}",json_str);

	let resp = client_aa
		.put(&url_update)
		.body(json_str)
		.send()
		.await?;

	println!("{:#?}", resp);

	Ok(())
}

// --------------------------------------------------------------------
```

実行

```bash
cargo run t2022 3189700
```
組み合わせの列挙

phpで組み合わせのコードを書きたいです。

1から9までの重複のない4つの数字を使用し,それらの並びの組み合わせを出力したいです。
例えば

````
1 2 3 4
````

という並びの組み合わせは4！＝24通りあります。

```
1234
1243
1324
.
.
.
中略
.
.
.
4321
```


丸投げする気はなく、このコードを書くためのヒントを頂けたら嬉しいです。
【ポートフォリオ を作成される方へ】Dockerでbinding.pryを使う方法

ポートフォリオを作成中、dockerとCircleCIを使ってHerokuにデプロイするために[こちらの記事](https://qiita.com/gakinchoy7/items/ae31107ef56efb16fe7e)を参考に作っていました。
そこにbinding.pryを使いたいと思った時の導入の方法をお伝えしようと思います。


```docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "4306:3306"

  web:
    build: .
    command: rails s -p 3000 -b '0.0.0.0'
    environment:
      RAILS_ENV: development
    volumes:
      - .:/sample_app #自身のアプリディレクトリ名を設定
    ports:
      - "3000:3000"
    links:
      - db
```   
上記の状態から
①command: rails s -p 3000 -b '0.0.0.0'を削除
②tty: true

最終的な形はこちら

```docker-compose.yml

version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "4306:3306"
  web:
    build: .
    environment:
      RAILS_ENV: development
    volumes:
      - .:/sample_app
    ports:
      - "3000:3000"
    links:
      - db
    tty: true
```

③docker-compose up
④docker-compose exec web bash
⑤rails s -p 3000 -b '0.0.0.0'
⑥好きなとことに binding.pryを差し込む

###参考
https://qiita.com/gakinchoy7/items/ae31107ef56efb16fe7e
https://stackoverflow.com/questions/35211638/how-to-debug-a-rails-app-in-docker-with-pry
Rust: CouchDB のデータを読む (Read)

こちらで作成したデータを読みます。
[Rust: CouchDB のデータを作成 (Create)](https://qiita.com/ekzemplaro/items/9418a7760b16950eb56e)

```text:Cargo.toml
[package]
name = "couchdb_read"
version = "0.1.0"
edition = "2018"

[dependencies]
reqwest = { version = "0.10", features = ["json"] }
tokio = { version = "0.2", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```

```rs:src/main.rs
// --------------------------------------------------------------------
/*
	couchdb_read/src/main.rs

					Jul/26/2020
*/
// --------------------------------------------------------------------
#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
	eprintln!("*** 開始 ***");
	let url_base = "http://localhost:5984/nagano";
	let url = "http://localhost:5984/nagano/_all_docs";
	let client = reqwest::Client::new();
	let resp = client.get(url)
		.send()
		.await?;

//  println!("{:#?}", resp);

	let body = resp.text().await? ;

	let json: serde_json::Value = serde_json::from_str(&body)?;

	let obj = json.as_object().unwrap();

	let nmax = &obj["total_rows"].to_string();

	let ix: usize = nmax.parse().unwrap();

	for it in 0 .. ix {
		let id = obj["rows"][it]["id"].to_string();
		let url_aa = url_base.to_owned() + "/" + &id;
		let url_bb = &url_aa.replace("\"","");
		read_record_proc(url_bb.to_string()).await?;
		}

	eprintln!("*** 終了 ***");
	Ok(())
}

// --------------------------------------------------------------------
async fn read_record_proc(url_in: String) -> Result<(), Box<dyn std::error::Error>> {
//	println!("{}",url_in);

	let client_aa = reqwest::Client::new();
	let resp = client_aa.get(&url_in)
		.send()
		.await?;

//	println!("{:#?}", resp);

	let body = resp.text().await? ;

	let json: serde_json::Value = serde_json::from_str(&body)?;

	let obj = json.as_object().unwrap();

//	println!("{:?}",obj);
	println!("{}\t{}\t{}\t{}",obj["_id"],obj["name"],obj["population"],obj["date_mod"]);
	Ok(())
}

// --------------------------------------------------------------------
```

実行

```bash
cargo run
```
リンクチェック方法のまとめ

ウェブサイト/ウェブサービスではリンクが正しく張れているかの確認は大事です。せっかくユーザがリンクを踏んだのに 404 になってしまってはユーザ体験を大きく損なってしまいますので。

数ページ程度のサイトなら手動でテストすることも可能ですが、多数のページを抱えるサイトでは手動では限界があります。ローンチ時は人海戦術でなんとか手動確認できても、長らく運営している間にコンテンツの更新が積み重なるとリンク切れの場所も多々でてくるでしょう。

ということで、リンクチェックを自動的に行う方法についてまとめてみます。

## リンクの種類

まず最初にリンクにはどのような種類があるのか整理しておきます。

### a href

リンクと言って一番最初に思いつくのが a タグの href 要素です。リンクターゲットをクリックすることで href 要素で指定されたリンク先に遷移します。

リンク先にはサイト内リンクと外部サイトへのリンクがあります。また、ページ自体へのリンクと id リンクがあります。ページが存在してターゲットの id が存在しない場合、通常はページの先頭を表示しますが、これは 404 などのエラーにならないですがユーザ体験は損なっています。404 エラーを発生しない分、検出が困難でもあります。

a タグが最初から HTML に書かれている場合と、JavaScript によって動的に生成される場合があります。一般的に後者のリンクチェックは難易度が高くなります。

### リソース

img src による画像、js や css ファイル、css ファイル中で指定される画像などです。

a タグと同様、HTML に書かれている場合と、動的に生成される場合があります。

### 動的処理によるページ遷移

JavaScript で処理した結果、location.href で別ページに遷移するものです。

## 外形チェック型

サイトに対して網羅的にチェックするのではなく、本番環境を運用している間に結果的に発生した 404 を検出する方法です。すべてのリンク切れを発見することはできませんが、一方で JavaScript で動的に生成されるリンクでもチェックが可能です。

### アクセスログ

ウェブサーバのアクセスログから 404 を返したものを調べる方法です。現実のアクセスログにはアタックの痕跡などノイズも多数残されていますので、それらを除去する必要があります。

原理的に全てのリンク切れを検出することは困難ですが、検出できないリンク = ユーザがめったに踏まないリンクだから軽視して良いという考え方もありだと思います。

### Google Search Console

Google Search Console のカバレッジでは、404 を含む様々なエラーを検出することができます。Google のクローラがアクセスした結果ですので、ある程度網羅的なエラー検出が期待できます。Google クローラも最近は簡単な JavaScript なら実行してくれるそうなので、動的処理のリンクも少しはカバーされると期待できます。

欠点としては、Google のクローラが一巡するまでは結構な時間がかかるということです。特に新規のサイトや規模が小さくて Google から重要でないと判断されているサイトはクロール頻度が低くなり、より多くの時間が掛かります。

### ブラウザの開発ツール

例えば Chrome のデベロッパーツールでは、Network タブで読み込んでいるリソースと読み込み状況を確認できます。ページ単位でのチェックなのでサイト全体を調べることはできませんが、方法の一つとして覚えておきたいです。

## 静的解析型

静的に生成された HTML の場合、静的解析でリンクチェックを行うことができます。

### 孤島発見器

[孤島発見器](https://www.vector.co.jp/soft/win95/net/se078643.html) は Windows 上で動作する静的リンクチェッカです。個人的に長らく愛用していたツールです。最終更新日が 2001年4月26日と古いのですが、Windows 10 でも動作します。ページ内リンクにも対応している優れものなのですが、name 属性のみで id 属性に対応していません。時代的に仕方がありませんが。

### linkchecker

宣伝になって恐縮ですが、拙作の [linkchecker](https://github.com/saoyagi2/linkchecker) も同様のツールです。コマンドラインで動作しますので、CI に組み込むこともできます。

## ウェブサービス型

フォームに URL を入力するとリンクをチェックしてくれるウェブサービスがあります。[W3C Link Checker](https://validator.w3.org/checklink) などが代表的です。

ウェブサービス側からアクセスできなければならないため、必然的にチェック対象は本番環境になり、ステージング環境やローカル環境は対象外になってしまいます。

リンク先のページを再帰的にリンクチェックしてくれますが、再帰深さが制限される場合もあります。

実質的にクローリングを行うわけですので、アクセス間隔は適切に取られます。結果的にサイト全体をチェックするのにかなりの時間がかかります。

## ウェブサーバ動作型

実際にウェブサーバを動作させてチェックを行う方法です。ウェブアプリもチェック可能ですし、開発環境やステージング環境などの閉じた環境でもチェック可能です。もちろん本番環境に対してチェックを行うこともできます。

[CUIから実行できるリンクチェッカーの比較](https://qiita.com/kmats@github/items/f1339ac83b74342c7390) では2つのリンクチェッカが紹介されていますし、[wgetでWebサイトのリンク切れをチェック](https://qiita.com/ueokande/items/73ed88c915430c8ba47c) では wget コマンドを使う方法が紹介されています。Windows や macOS 上で動作する GUI アプリもあります。

## 動的生成に対する対応

静的解析型、ウェブサービス型、ウェブサーバ動作型のいずれにも言えることですが、JavaScript で動的に生成されるリンクや動的処理によるページ遷移への対応は困難です。究極的にはリンクチェッカ側で JavaScript を動作させるしかないわけで、Selenium でテストスクリプトを書くなどの対応が考えられます。
Rust: CouchDB のデータを作成 (Create)

```text:Cargo.toml
[package]
name = "couchdb_create"
version = "0.1.0"
edition = "2018"

[dependencies]
reqwest = { version = "0.10", features = ["json"] }
tokio = { version = "0.2", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```

```rs:src/main.rs
// --------------------------------------------------------------------
/*
	couchdb_create/src/main.rs

					Jul/26/2020
*/
// --------------------------------------------------------------------
use serde_json::json;

// --------------------------------------------------------------------
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
	eprintln!("*** 開始 ***");
	let url_base = "http://localhost:5984/nagano";

	record_insert_proc(url_base,"t2021","長野",38921,"1956-2-15").await?;
	record_insert_proc(url_base,"t2022","松本",95436,"1956-10-22").await?;
	record_insert_proc(url_base,"t2023","上田",81592,"1956-9-7").await?;

	record_insert_proc(url_base,"t2024","小諸",58931,"1956-7-5").await?;
	record_insert_proc(url_base,"t2025","岡谷",25416,"1956-9-12").await?;
	record_insert_proc(url_base,"t2026","塩尻",71582,"1956-5-30").await?;


	eprintln!("*** 終了 ***");

	Ok(())
}

// --------------------------------------------------------------------
async fn record_insert_proc(url_base: &str,key_in: &str,
	name: &str,pp_in:i32,date_mod:&str)
	-> Result<(), Box<dyn std::error::Error>> {
	let url = url_base.to_owned() + "/" + key_in;
	let client_aa = reqwest::Client::new();

	println!("{}\t{}\t{}\t{}", key_in,name,pp_in,date_mod);

	 let obj_new = json!({
		"name": name.to_string(),
		"population": pp_in,
		"date_mod": date_mod.to_string()
		});

	let json_str = obj_new.to_string();
	eprintln!("{}",json_str);

	let resp = client_aa
		.put(&url)
		.body(json_str)
		.send()
		.await?;

	println!("{:#?}", resp);

	Ok(())
}

// --------------------------------------------------------------------
```

実行

```bash
cargo run
```
AWS Well-Architected Labsのご紹介

# AWS Well-Architected Framework
「AWSのベストプラクティスに沿って設計/構築/運用したいけど、何をどうすればベストプラクティスになるのか分かってないな〜」と思っているそこのあなた。**AWS Well-Architected Framework**を使いましょう。**オペレーショナルエクセレンス、セキュリティ、信頼性、パフォーマンス効率、コスト最適化**の5つの柱についてAWSのベストプラクティスに沿っているかをチェックできます。AWS Well-Architected Frameworkには以下3種類があります。

### 1. AWS Well-Architected ホワイトペーパー
ベストプラクティスが記載されたドキュメントです。都度更新が入るので、最新のドキュメントは[公式ページ](https://aws.amazon.com/jp/architecture/well-architected/?ref=wellarchitected-ws&wa-lens-whitepapers.sort-by=item.additionalFields.sortDate&wa-lens-whitepapers.sort-order=desc)から確認しましょう。

### 2. AWSソリューションアーキテクトもしくはWell-Architected認定パートナーによるレビュ
ソリューションアーキテクトもしくはパートナーの方にレビュしてもらいます。使ったことはありませんが、お金はかかりそうです。

### 3. AWS Well-Architected Tool
AWSのマネジメントコンソールから質問に答えていって、ベストプラクティスに沿っているかをセルフチェックできます。

# AWS Well-Architected Labs
ベストプラクティスについてドキュメント読むとか質問に答えるでも良いんだけど、実際に手を動かして理解したいと思う方は多いんじゃ無いんでしょうか。そんな方におすすめなのが、AWS Well-Architected Frameworkの内容をハンズオン形式で学べる[AWS Well-Architected Labs](https://wellarchitectedlabs.com/)です！

自分が実践したハンズオンの内容を別記事としてまとめるので、内容が気になる場合は以下もご覧ください(追記中)。

- Operational Excellence
    - 100 - Inventory and Patch Management
        - [AWS Systems Managerのパッチマネージャーを使ってパッチ適用を自動化する](https://qiita.com/chanhama/items/3945831a8278e34ee358)
- Security
    - 100 - AWS ACCOUNT AND ROOT USER
        - [AWSアカウントのルートユーザを通常運用で使ってはいけません](https://qiita.com/chanhama/items/d31aabca60ccdb447c79)

# 参考
- [AWSベストプラクティスをハンズオンラボで学ぼう](https://dev.classmethod.jp/articles/well-achitected-update-2020july/)
- [AWS Well-Architected フレームワークのご紹介](https://www.slideshare.net/TakanoriOhba/jaws-days-2020-aws-wellarchitected?ref=https://jawsdays2020.jaws-ug.jp/session/aws-well-architected-%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E4%BD%BF%E3%81%84%E3%83%89%E3%82%B3%E3%83%AD%E3%81%A8%E3%82%AA%E3%83%BC%E3%83%88%E3%83%A1%E3%83%BC/)
Ubuntu18.04でapt-get updateに失敗した時の解決方法

Ubuntu18.04でapt-get updateに失敗した時の解決方法

```
$ sudo apt-get update
エラー:1 http://jp.archive.ubuntu.com/ubuntu bionic InRelease
  'jp.archive.ubuntu.com' を解決できませんでした
エラー:2 http://security.ubuntu.com/ubuntu bionic-security InRelease
  'security.ubuntu.com' を解決できませんでした
エラー:3 http://jp.archive.ubuntu.com/ubuntu bionic-updates InRelease
  'jp.archive.ubuntu.com' を解決できませんでした
エラー:4 http://jp.archive.ubuntu.com/ubuntu bionic-backports InRelease
  'jp.archive.ubuntu.com' を解決できませんでした
パッケージリストを読み込んでいます... 完了
W: http://jp.archive.ubuntu.com/ubuntu/dists/bionic/InRelease の取得に失敗しました  'jp.archive.ubuntu.com' を解決できませんでした
W: http://jp.archive.ubuntu.com/ubuntu/dists/bionic-updates/InRelease の取得に失敗しました  'jp.archive.ubuntu.com' を解決できませんでした
W: http://jp.archive.ubuntu.com/ubuntu/dists/bionic-backports/InRelease の取得に失敗しました  'jp.archive.ubuntu.com' を解決できませんでした
W: http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease の取得に失敗しました  'security.ubuntu.com' を解決できませんでした
W: いくつかのインデックスファイルのダウンロードに失敗しました。これらは無視されるか、古いものが代わりに使われます。
```

（今回の場合は）proxyサーバを経由する必要があった。
/etc/environmentに、http_proxy,https_proxyを追記して解決

```:/etc/environment
http_proxy=(proxyサーバのipアドレス):(port)
https_proxy=(proxyサーバのipアドレス):(port)
```

# 参考
[Proxy環境でubuntu18.04LTS Serverでapt updateを実施したらエラーが発生しました](https://usado.jp/spdsk/2018/07/30/post-4157/)
ubuntu18.04でIPアドレス固定する

IPアドレス固定したいネットワークデバイス名を確認する

```
ifconfig
```

（以下は、デバイス名=eth0 の場合）
/etc/network/interfacesに固定したいネットワークデバイス名とIPアドレスなどを記載

```:/etc/network/interfaces
auto eth0
iface eth0 inet static
   address 192.168.11.100
   netmask 255.255.255.0
```

その後rebootして設定を有効化する

# 備考
rebootせずとも設定を有効化する方法を探したが今の所見付けられなかった。
以下だと設定が反映されないときがある。

```
# /etc/init.d/networking restart
or
# service networking restart
or
# systemctl restart networking
```

以下だと、一時的にしか反映されない。
（対向側のネットワークが途切れると再設定する必要がある）

```
ifconfig eth0 192.168.11.100
ifconfig eth0 up
```

# 参考
https://qiita.com/routerman/items/4d19b3084fa58723830c
EIGRP_neighbor形成について

##EIGRPでネイバー形成させる条件
- AS番号
- K値
- 同じサブネット
- 認証設定（有効化している場合）

#ネイバー形成されない時

- そもそもI/FはUPしている？
- Passive-interfaceが誤って設定されている？
- ACLでブロックしている？
- タイマー設定は？
 ※対向とhello,holdの値は合わせなくてよいが、hello送信間隔はhold時間よりも短くする必要がある
Docker環境にてコマンドラインからgnome-terminal起動時にエラーが出て起動しない

Docker環境にてコマンドラインからgnome-terminal起動時にエラーが出て起動しない

```
Error constructing proxy for org.gnome.Terminal:/org/gnome/Terminal/Factory0: Error calling StartServiceByName for org.gnome.Terminal: GDBus.Error:org.freedesktop.DBus.Error.Spawn.ChildExited: Process org.gnome.Terminal exited with status 8
```

Docker環境でのlocaleの設定が足りなかった。
以下の通りDockerfileにlocaleを設定する記述を追加して解決


```dockerfile:Dockerfile
RUN locale-gen ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:jp
ENV LC_ALL ja_JP.UTF-8
```

＃参考
[Docker: コンテナのlocaleを設定したい](https://qiita.com/suin/items/856bf782d0d295352e51)[https://wiki.gnome.org/Apps/Terminal/FAQ](https://wiki.gnome.org/Apps/Terminal/FAQ)
[https://askubuntu.com/questions/608330/problem-with-gnome-terminal-on-gnome-3-12-2](https://askubuntu.com/questions/608330/problem-with-gnome-terminal-on-gnome-3-12-2)
＜スプレ＞他の関数を呼び出す(GAS)

結論（main関数の中で引数を渡す）
---------------


今回したい処理はこちら。

```
main.gs
function main() {
  var sum = add(100, 200);
  Logger.log(sum); //300
}
```

元の合計を求める関数：addはこちら。
あらかじめ、引数を設置しておけばOK。

```

util.gs
function add(a, b) {
  return a + b;
}
```

結論（そのまましたの関数を呼び出す）
---------------

function no1(){

　while("条件式をここに記入します") {
 　 ここに処理1をかく
  }
  if ("条件式をここに記入します"){
    getMyVideoList("return値"); // 下の関数を使う
  }

}

function no1(){
  ここに処理1をかく

}
コマンドラインからgnome-terminal起動時にエラーが出て起動しない

コマンドラインからgnome-terminal起動時にエラーが出て起動しない

```
$ gnome-terminal
# Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
```

以下をインストールして解決

```
sudo apt install at-spi2-core
```

# 参考
[http://yuki-lab.jp/diary/diar1803.html](http://yuki-lab.jp/diary/diar1803.html)
Jest で async 関数のエラーを検証する

# 環境

- Jest: 26.1.0
- Typescript: 3.9.7

# 検証したい関数

```ts
const fail = async () => {
  throw new Error();
}
```

# テスト

```ts
await expect(fail).rejects.toThrowError(Error);
```

# 参考
https://github.com/facebook/jest/issues/1700
＜スプレ＞セル内が空白かどうかで処理を分けたい(GAS)


結論
----------
cell.isBlank()を使う。


```
function blankornot() {
  var lastRow = sheet.getLastRow();
  for (var i=1; i <= lastRow; i++){
    var cell = sheet.getRange(i, 2); //cellの値を撮ってくる
    if(cell.isBlank()){ //もしセルがブランクなら
      Logger.log(i + "行目は空白です。");
    }
  }
}
```
メソッドについての理解を深める

#疑問点
写真投稿アプリ作成過程において、「ツイート投稿時」と「ログイン認証時」にそれぞれpermitメソッドを使用した。しかし双方のpermitメソッドのコード規則に一貫性を感じない。疑問に感じたので調べてみることにした。

#調べた内容
①コードの確認
まずは双方のコードを振り返ってみる。

```ruby:tweets_controller.rb
【ツイート投稿時】
記述内容：params.require(:tweet).permit(:name, :image, :text)
記述汎用：params.require(:モデル名).permit(:キー名, :キー名)
```

```ruby:application_controller.rb
【ログイン認証時】
記述内容：devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
記述汎用：devise_parameter_sanitizer.permit(:アクション名, keys: [:キー名])
```

やはりpermitメソッドのコード規則が上下で異なっている。
ちなみに「application_controller.rb」ファイルはdevise Gemを用いて生成している。この辺りに解決のヒントがあるのだろうか。

②ウェブ検索
次にdevise Gemについて調べてみた。
どうやらpermitメソッドが追加されたのは、devise4というバージョンからのようだ。

https://qiita.com/shizuma/items/b176f165a7c8b1049eae

#仮説
①rails newにより生成されるruby on railsのGem郡にpermitメソッドの定義がある。
　またdevise:installにより生成されるGemにもpermitメソッドの定義がある。
②上記のpermitメソッドは別物である。
③devise Gemを通じて生成されたファイルはdevise内のpermitメソッドが適応される。

#検証結果
①の仮説を検証するべくdevise Gemのコード表を確認すると、permitメソッドに関するコーディングが記載されていた。「application_controller.rb」でのpermitメソッドはdevise Gemのコーディング規則に基づいていることが確認できた。

https://github.com/heartcombo/devise

**→同じ名前のメソッドでも、定義元のGemファイルによってコーディング規則は異なる。**
Laravelで PhotoSwipeを手っ取り早く使う方法

## 地味に導入が面倒なのでまとめてみた。

### 参考
PhotoSwipeSimplify(PhotoSwipeを簡単に使うための超便利なライブラリ([参考サイトこちら](https://min30327.github.io/photoswipe-simplify/))

### 導入方法
#### 1. npmでインストール
```bash
npm install jquery.photoswipe
```
#### 2. app.jsで読み込む
```javascript:resource/js/app.js
require('photoswipe');
window.photoswipeSimplify = require('photoswipe-simplify');
```

#### 3. img群をdata-pswp要素で囲む
```html
<div data-pswp>
... 画像 ...
</div>
```
#### 4. 初期化をしてスタート
```js
photoswipeSimplify.init();
```

ってやれば幸せになるよ。
Lambda＋SAMテンプレートのBlue/Greenデプロイメントで「デプロイの再試行」した際の動作を検証する

# はじめに
デプロイ運用は、Blue/Greenでシームレスにサービス移行できるのも重要だが、デプロイに失敗した際のロールバックと再デプロイをスムースに行えることも重要だ。

Canaryなデプロイにおける自動ロールバックについては、[過去の記事](https://qiita.com/neruneruo/items/2e7bf289f375ccc91356)で調査を行ったので、今回は手動ロールバックと再デプロイについての動作検証を行う。

なお、最初に断っておくと、この方法は結果的に期待した動作になっているが、途中でエラーが出たりして怪しさ満点である。もう少しちゃんとした検証が必要かもしれない。

# 前提条件
- Lambda＋SAMテンプレートでの基本的な動作の仕様を理解している([過去の記事](https://qiita.com/neruneruo/items/73906cdc3c2aa699644f)で紹介済み)
- デプロイは以下の仕様とする
 - Prodのエイリアスを使用してCanaryの向き先を制御する(SAMテンプレートで```AutoPublishAlias: Prod```としている)

 - API GatewayのLambda統合プロキシで、上記Prodをターゲットにしている

# 初回デプロイ直後の状態
以下のようになっている。初版と言いながらバージョン8なのは、この記事を書くにあたりいろいろ試行錯誤した結果なのであしからず。
![キャプチャ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/d34aec08-6cc3-59c3-2117-07cace22f356.png)

# 初回の修正を行った状態
初回の修正を行い、パイプラインが走った後、以下の状態になる。
バージョン9が作られ、Prodのエイリアスが最新バージョンに向いている状態だ。
![キャプチャ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/c281d6a5-f8ee-1ecb-eb7b-0b158862d3a9.png)

ここで、バージョン9に不具合があったことが分かったと仮定して、ロールバックをしてみよう。

![キャプチャ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/4c8611e9-409a-2be3-8be9-7029ed4d4c8f.png)

うーん、この「デプロイの再試行」ボタンなのか？日本語的には意味が違うが……
AWSはたまに翻訳が怪しいので、とりあえず押してみると…

![キャプチャ6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/d398872e-3a8c-96f5-a0c4-7392e196f984.png)
![キャプチャ7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/1f575780-7879-4384-490e-461ba51eed4d.png)

なんかエラーが一度出た。が、結果として最後のデプロイは成功しているようなので、確認してみる。

![キャプチャ8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/60e2f57c-310c-1450-a79f-584f4c202ac0.png)

期待した通り、Prodのエイリアスが元通り8を指している。
curlによる正常性確認も、しっかりバージョン8の動作をした。

では、ここで再度バージョン9の不具合修正を行い、デプロイを行う。

![キャプチャ10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/645ef5cf-d399-75c5-372d-a1f4c43a8f46.png)

すると、バージョン9を飛ばしてしっかりバージョン10を向くようになった。
では、仮にここで、さらにバージョン10にも不具合があってロールバックしたらどうなるだろうか？
ここでバージョン9に戻ってしまうと、瑕疵のあるバージョンがデプロイされてしまう。
では、再び「デプロイの再試行」ボタンを押してみよう。

![キャプチャ12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/19c5b777-aff6-4e9a-6974-6a77aa756404.png)

しっかりと、バージョン9ではなくてバージョン8に戻ってくれた。

この後、バージョン11をデプロイして、これはデプロイ成功したと仮定して、さらにバージョン12をデプロイ→ロールバックとしてみた。

![キャプチャ14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/39f50b48-8ee5-691c-8028-690e9d0764aa.png)

うむ、デプロイ成功したバージョンについてはしっかり覚えてくれて、そこまでロールバックしてくれるという仕様のようだ。

これ、エラーの謎さえ解けて、これが仕様通りの動作なのだとしたら、完璧に期待通りの動作なのだけど。
エラー内容をGoogleで確認しても分からなかったので、迷宮入りしてしまいそうである……。