OmniAICreator/Qiita-1.07M huggingface dataset:
SQLのCASE式を用いてORDER BY でソート列を作るテクニック

## 問題

CASEを使った既存の体系を新たな体系に変換した集計をやっていきます。

`Tests`という仮のテーブルがあるとします。

| key| greatest |
|----|----------|
| A | 2 |
| B | 5 |
| C | 7 |
| D | 3 |

任意の順番（B→A→D→C）に並び替えるクエリを書いてください。

### 補足

そもそも、こんなクエリを発行させないといけないようなテーブルがおかしいですが、クエリの勉強だと思ってください。

仮定として、テーブル自体を見直した方がいいような設計であるとします。今回は仮に、ソート用の列が存在せず、ソートさせた結果が欲しいとします。

本来、SQL（SELECT）の仕事はデータ検索です。結果の見た目の整形は本来の役割ではありませんが、時としてクエリに頼らざるを得ない場面はありますよね？（僕はありました）

そういうシーンであると仮定して欲しいです。

## SQL

```sql
SELECT key
FROM Tests
ORDER BY CASE key
 WHEN 'B' THEN 1
 WHEN 'A' THEN 2
 WHEN 'D' THEN 3
 WHEN 'C' THEN 4
 ELSE NULL
 END;
```

ソート列も出力させたいのなら

```sql
SELECT
 key,
 CASE key
 WHEN 'B' THEN 1
 WHEN 'A' THEN 2
 WHEN 'D' THEN 3
 WHEN 'C' THEN 4
 ELSE NULL
 END AS sort_col
FROM Tests
ORDER BY sort_col;
```

ちなみにこの書き方は 以前書いた記事👇 に似てますね。これらは、最初に書いたSQLよりも標準的なSQLにのっとってます。

https://qiita.com/ryosuketter/items/d09c0fc8abf134165d22#%E5%AE%9F%E4%BE%8B

なぜなら、`ORDER BY`は`SELECT`よりも後に実行されるので、SELECT句で作られた計算列（今回なら: `sort_col`）を参照できるからです。

### SELECT文の処理の実行順序

```
FROM // 検索対象のテーブルが決定
↓
WHERE // 条件による絞り込み
↓
GROUP BY // グループ化
↓
SELECT // SELECTに記述された計算が実行
↓
HAVING // グループ化された結果を条件によって絞り込み
↓
ORDER BY // ソート
↓
LIMIT // 指定された行数で絞り込む
```

https://qiita.com/k_0120/items/a27ea1fc3b9bddc77fa1

## 参照

https://www.amazon.co.jp/dp/4798157821/

25p

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
setErrors 上書き出来ない cakePHP

# はじめに
気力と体力がほとんどないのでちょっと乱雑な文章になりそうですが、
共有したいことは共有出来ているはずなので優しい心でお願いします！:bow:

バリデーションエラーの一部をなかったことにしたいけど少し戸惑ったのでここに残しておきます！

ちなみになぜそうしたかったかですが、Formでエラー表示しないとしてもエレメントで確認すると表示に違いがあるな〜〜〜と思い、これじゃだめだ！！！！だめなんだ！！！となりました、、

ちなみに表示させたくなかった文言は『このメールアドレスはすでに使用されています。』です。どのメールアドレスが登録されているかバレちゃうので、、:rolling_eyes:



# では早速

```PHP

$fix_errors = $user->getErrors();
$fix_errors['email'] = null; //キーごと無くすunsetでは上手くいかなく戸惑いました、
$user->setErrors($fix_errors, true); //メソッド確認したら上書きするかの指定しないといけなかったのね、、と

```

ちなみに

```PHP
    /**
     * Sets error messages to the entity
     *
     * @param array $errors The array of errors to set.
     * @param bool $overwrite Whether or not to overwrite pre-existing errors for $fields
     * @return $this
     */
    public function setErrors(array $errors, bool $overwrite = false);
```

# おまけ(エレメントの確認)

```html
<input type="email" name="email" placeholder="メールアドレス" required="required" data-validity-message="入力してください" oninvalid="this.setCustomValidity(''); if (!this.value) this.setCustomValidity(this.dataset.validityMessage)" oninput="this.setCustomValidity('')" id="email" value="aaab@s.com" maxlength="191"> //使用されているメールアドレスもの


<input type="email" name="email" placeholder="メールアドレス" required="required" data-validity-message="入力してください" oninvalid="this.setCustomValidity(''); if (!this.value) this.setCustomValidity(this.dataset.validityMessage)" oninput="this.setCustomValidity('')" id="email" value="aaabaaa@s.com" maxlength="191"> //使用されていないメールアドレスもの
```

あと最初は以下のようにやろうとしてました、、セキュリティ的な問題等なければ以下でも問題ないかと思います！

```PHP
if ($isShowEmailError === true) {
    echo $this->Form->control('email', ['placeholder'=>'メールアドレス', 'label' => '']);
} else {
    echo $this->Form->control('email', ['placeholder'=>'メールアドレス', 'label' => '', 'error' => false]);
}
```

# 最後に
そもそものメールアドレスが間違っている時等ははエラーが表示されるように、エラーを削除する前にエラー内容の確認は必須かと思います！以下のような場合のエラー表示は必要ですからね( ･ὢ･ ) 
<img width="200px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133940/ad9a1044-8c47-c023-fc78-b72f92d21dd7.png"></img>
WoWHoneypotの構築をAnsibleでIaCしてみた

## はじめに
WoWHoneypotの構築を先ほど行っていたのですが
再現性を担保するためにIaCを行なったので記録していきます.

## 環境
server: ubuntu20.04 (AWS)
client: Macbook air 2020

## 出来上がったもの
https://github.com/S-mishina/WoWHoneypot_Ansible

## 実際のコード(要点)

### files/wowhoneypot.service

```
[Unit]
Description=WoWHoneypot daemon
Documentation=https://github.com/morihisa/WOWHoneypot

[Service]
ExecStart = /home/ubuntu/wowhoneypot.sh
ExecRestart = /bin/kill -WINCH ${MAINPID} ; /home/ubuntu/wowhoneypot.sh
ExecStop = /bin/kill -WINCH ${MAINPID}
User = root

[Install]
WantedBy = multi-user.target
```
### files/wowhoneypot.sh

```
#!/bin/bash
cd /home/ubuntu/wowhoneypot
/usr/bin/python3 /home/ubuntu/wowhoneypot/wowhoneypot.py
```

### site.yml

```
---
- hosts: webserver
  tasks:
    - include: WoWHoneypot/tasks/main.yml
```

### tasks/main.yml

```
---

#==========システム導入編==========#
- name: ubuntu git_install
  apt:
    name: git
    state: latest
  become: yes

  #ユーザー直下に落とす
- name: git_clone_wowhoneypot
  command: git clone https://github.com/morihisa/WOWHoneypot.git wowhoneypot
  become: yes

- name: service Wowhonepot
  become: yes
  copy:
    src: ../files/wowhoneypot.service
    dest: /etc/systemd/system/wowhoneypot.service

- name: Wowhonepot.sh
  copy:
    src: ../files/wowhoneypot.sh
    dest: /home/ubuntu/wowhoneypot.sh
  become: yes

- name: chmod +x wowhoneypot.sh
  command: chmod +x wowhoneypot.sh
  become: yes

#==========実行編==========#

- name: start wowhoneypot.service
  command: systemctl start wowhoneypot.service
  become: yesl
```

### 設定ファイルの追加(host/hosts)

```
[webserver]
Target01 ansible_ssh_host='global_IP'
[webserver:vars]
ansible_ssh_user='User_name'
ansible_ssh_private_key_file='key'
```
## 実行方法

```
$ ansible-playbook site.yml -i hosts/hosts
```

## 参考サイト
https://qiita.com/hogehuga/items/cad931485f58ae487d53
OSX上でPyCharmをつかってxlwingsを実行するとCommand failed: The user has declined permission. (-1743)エラーになる場合の対応策

# 現象

PyCharmでxlwingsのプログラムを書こうとすると、以下のエラーが出る。

```bash
Command failed: The user has declined permission. (-1743)

```

実行しようとするコードは以下の通り

```python
#!/usr/local/bin/python3.9
# -*- coding: utf-8

import xlwings as xw

wb = xw.Book('myexcel.xlsx')

```

同じプログラムをターミナルから実行すると問題なく動作した。
どうやらPyCharmにOSXのパーミッションが足りないようだ。

この記事を参考にした。
https://intellij-support.jetbrains.com/hc/en-us/community/posts/360005152379-Pycharm-cannot-get-permission-to-control-Excel-Mac-

# 対応方法
PyCharmをターミナルから起動する。

ターミナルを開いて、以下を実行してPyCharmを起動する。このとき他にPyCharmが起動していればて終了させる。

```bash
/Applications/PyCharm.app/Contents/MacOS/pycharm
```

エラーが発生しなくなった。

毎回長いコマンドを入力するのは面倒なので .bashrc に alias を定義。

```bash
alias pc='/Applications/PyCharm.app/Contents/MacOS/pycharm'
```

コマンドラインから pc を入力すると PyCharm が起動するようになる。
GETとPOSTとは PHP

#■はじめにリクエスト行う方法を認識する。
●ブラウザのアドレス欄にURLを直接入力する。
●お気に入りからアクセスする。
●ページ内のリンクやボタン、画像などをクリックする。
●入力フォームに情報を入力して送信ボタンをクリックする。
などがあります。

#■リクエストを行う際サーバーに渡したいデータ
●見たい商品や動画のID
●ページ移動する際のページ番号
●ログイン画面に入力するメールアドレスやパスワード
●注文画面に入力する名前や住所などの個人情報

#■GETとPOSTというのはリクエストの方式の1つです。

####▼GET
リクエストを行う時にURLの末尾にデータ名を記載しくっつけて送る方法です。
?以降にデータが記載している。

■できない事
URLに長さの制限がある。長い文章や画像のようなデータ量が多いデータをURLにくっつけて送る事はできない。
個人情報やパスワードなどの情報をURLに記載されていたらまずい。

▼使い分け
画面表示のために必要
表示したい画像や動画のID、ページ番号など

GETは取得するためのリクエスト

```
/search?id=なになに
```

####▼POST
リクエストを送る際にURLにデータ等を記載しないで送る方法。

個人情報やパスワードを入力する場合や膨大なデータを送信する場合はこのPOST方式を使う。

ユーザーが画面に入力して送信するもの
ログインIDや個人情報

POSTは送信するためのリクエスト

■formタグのmethodにpostを使う

``` php
<form method="post">
 </form>
```
AWS Glue python shell で ETL

AWS Glue python shell で ETLジョブ作成する際のハマりどころメモ
2021/1 時点

# Glue Python shellとは？

- GlueのジョブTypeの１つ
- Sparkを使うまでもない軽いジョブや各種連携に使える
    - 例
        - DBにSQLを投げる
        - FTPサーバからファイルGET
        - 外部サービスをAPIでキック
        - などなど
- Python（version2 or 3）で処理を書ける
- ジョブ実行環境はジョブ毎にサーバレスリソースが割り当てられる（Lambdaのような感じ）
    - 1DPU または 1/16DPU から選べる
    - 1DPUは、4vCPUのコンピューティングと16GBのメモリに相当
    - Lambdaのように時間制約（15分）はない

# 気になったポイント

### [1] VPC内での実行とリソース接続

- Glueの「接続」機能で接続先リソースやNWを設定しておき、ジョブの設定で紐付けると、該当のセグメント（SG）を起点としてジョブが実行される

### [2] 利用できるライブラリ

- 標準サポートされているライブラリは以下
    - https://docs.aws.amazon.com/ja_jp/glue/latest/dg/add-job-python.html
    - DB接続には`PyGreSQL`を利用できる
- これ以外のライブラリまたは独自のライブラリを追加することもできる
    - ライブラリを追加するには、`python setuptools` を使って、WhleelファイルまたはEggファイルを自分で作成して、S3にアップロードし、ジョブでそのパスを指定する
        - 参考：https://dev.classmethod.jp/articles/yoshim-glue-wheel/
    - 注意点としては、ジョブ実行の際にPyPIに接続してinstallされる動きとなるようで、ジョブ実行場所はNATなどで外部接続が許可されてる必要あり
        - 参考：https://forums.aws.amazon.com/thread.jspa?threadID=308033

### [3] 外部FTPサーバからのGET処理はできる？

- 以下でSFTPサーバからGETしてS3にPutするサンプルが紹介されてる
    - 参考：https://github.com/ShafiqaIqbal/SFTP-S3-Glue-Ingestion-Python/blob/master/Glue_Python_FTP_S3_Ingestion.py
    - SFTP接続のライブラリ`paramiko`を利用する。(標準サポートされてないのでWhlなどで要追加)
- ただし外部リソースからのGET処理はGlue Studio Connectorという選択肢もある
【不具合修正】Laravel-admin の Grid 表示で列固定 (fixed)すると表示がズレる


## どんな不具合か
#### 【概要】
![スクリーンショット 2021-08-09 14.43.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811865/3d51fac5-e019-087a-9b35-3814779c5572.png)
Laravel-admin の Grid 表示で、「表示固定された列」と「通常の列」とで表示が上下にズレてしまう（上画像のようになる）。これはレコード数（行数）が少なければ気にならないレベルだが、多くなると顕著になる。

↓Laravel-admin のデモページを見てもらえれば一目瞭然。

https://demo.laravel-admin.org/users?&per_page=100

#### 【Laravel-admin バージョンごとの発生状況】
| バージョン | 不具合 |
|:--------|:-----:|
| 1.7.3   | あり   |
| 1.8.11  | あり   |
| その他   | 不明   |

#### 【ブラウザごとの発生状況】
| ブラウザ  | バージョン       | 不具合 |
|:--------|:--------------|:-----:|
| Chrome  | 92.0.4515.131 | あり   |
| FireFox | 90.0.2        | あり   |
| Safari  | 14.1.2        | なし   |

私が普段使っているブラウザでは、Chrome と Firefox でこの不具合が発生する。


## 修正概要

- Laravel-admin バージョン：1.8.11
- 修正箇所
 - ソース：/vendor/encore/laravel-admin/resource/views/grid/fixed-table.blade.php
 - 行番号：182（scriptタグ内）
- 原因：レコードオブジェクトの高さを取得している jQuery の outerHeight()メソッドは、ブラウザによっては整数に丸めてしまうらしい。
- 対策方法：getBoundingClientRect().heightを使うと、オブジェクトの高さを小数のまま取得できる。

## 修正コード

```php:fixed-table.blade.php（修正前）
$('.table-main tbody tr').each(function(i, obj) {
    var height = $(obj).outerHeight();  // 【このコードを修正】

    $('.table-fixed-left tbody tr').eq(i).outerHeight(height);
    $('.table-fixed-right tbody tr').eq(i).outerHeight(height);
});
```

```php:fixed-table.blade.php（修正後）
$('.table-main tbody tr').each(function(i, obj) {
    var height = $(obj).get(0).getBoundingClientRect().height;  // 【このコードを修正】

    $('.table-fixed-left tbody tr').eq(i).outerHeight(height);
    $('.table-fixed-right tbody tr').eq(i).outerHeight(height);
});
```
getBoundingClientRect() は DOMオブジェクトのメソッド。
$(obj)はjQueryオブジェクトなので、そこから直接は使えない。
なので、間に「get(0)」を付けてDOMオブジェクトとして扱う必要がある。
ダブルイリミネーショントーナメントの勝率

オリンピックの野球がダブルイリミネーション方式という変則的なトーナメントだった。これは様々な競技に取り入れられている方法らしい。
強いチームが1位になる確率が違うのか気になったので、簡易的にシミュレーションしてみた。

今回の野球だと6チームしかないので、単純なノックアウト方式のトーナメント(シングルイリミネーショントーナメント)だと試合数が少なくなってしまう。ダブルイリミネーション方式だと15試合となり、これは(組み合わせは違うが)総当たりと同じ総試合数となる。

なので総当たりと結果を比べてみることにした。総当たりだと同じ勝ち数で並ぶことがあるので、その場合は直接対決で勝った方を勝者とした。

6チームの強さをランダムに生成し、各マッチでは強さの比をもとにランダムで勝者を決めた。
強さが1位のチームが何回勝つかを100万回試行したところ、
総当たり: 374272回
ダブルイリミネーション: 377142回
となり、ダブルイリミネーション方式は、総当たりと同程度に、実力のあるチームが勝ちやすい方式だということがわかった。ダブルイリミネーションのほうがわずかに高い結果となったが、総当たりで同じ勝ち数のチームが3チーム以上の場合をちゃんと処理していない(強さ順の最初の2チームしか見ていない)ので、そこで差が出たかもしれない。
また、強さを[0, 1)のランダムにしたときと、[0.5, 1)のランダムにしたときでは特に差がないようだ。

この総当たり方式だと明確な決勝戦がなく、ダブルイリミネーション方式のほうが盛り上がりそうだ。また(将棋などとは違って)体を動かすスポーツだと勝つほうがより休めるので、そこの有利不利は影響しそうである。

ソースコード: https://github.com/firewood/test/blob/master/double_elimination.py
ネタに困っている人事担当者向け！オンライン研修でも楽しみながら学べる画像判定クイズアプリ

もうすぐ内定式や内定者研修が始まる時期ですね。
今年も内定者研修はオンラインで行う企業も多いのではないでしょうか。

オンラインだと座学ばかりになってしまい、参加者が退屈しないか悩んでいる人事担当者もいるかと思います。

当社でも小売企業の内定者向けにウェビナーを企画している時に
単なる講義だけではなく、エンタメ要素やちょっとしたブレイクタイムになるような
全員参加型のコンテンツを入れることはできないかな？と悩んでいます。

そんなオンライン研修のネタに困っている人事担当者や企画担当者向けに
オンラインでも参加者が手を動かしながら楽しめるようなクイズWebアプリを作ってみました。
（今回は小売企業を対象にしています。）

#アメリカ小売企業売上ランキングクイズ
このWebアプリは、アメリカの小売企業のロゴをWebカメラに映すと
その企業が売上何位なのか、クイズの答えを教えてくれるというものです。

<a href="https://gyazo.com/30a010459311ded1e4453c9d782fbafe"><img src="https://i.gyazo.com/30a010459311ded1e4453c9d782fbafe.gif" alt="Image from Gyazo" width="800"/></a>

#使用したツール
###Teachable Machine
アメリカ食品小売企業売上ランキング上位3社のロゴの画像を学習させました。
![Image Model - Teachable Machines - Google Chrome 2021_08_09 14_57_19 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811853/8c7198dc-9185-4d4c-2b78-99331da1b5ec.png)


###CodePen
Teachable Machineと連携させ、Webアプリを作成しました。
1位の企業を当てた場合は分かりやすいように背景が黄色になるようにしました。
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="NWjLqJx" data-user="komoriac" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/komoriac/pen/NWjLqJx">
  アメリカ小売企業売上ランキング</a> by KomoriAC (<a href="https://codepen.io/komoriac">@komoriac</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

###Node-RED
推論の結果をNode-REDに送り、アプリで動作があるとLINE Botにメッセージが届くようにしました。

![Node-RED _ nodered-komori.herokuapp.com - Google Chrome 2021_08_09 14_39_44 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811853/39bc9db5-a636-c126-82e5-e3387fc80a59.png)

###LINE Bot
上位3社だけではなく他企業のランキングも見られるように詳細ページを案内するメッセージを配信しました。
<img width="500" alt="linebot.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811853/3c3f2518-369a-e82a-3e19-73013ed7daf4.jpeg">

#改善したいところ
●クイズなのでアプリの見た目をもう少し派手にしたかったです。
●Webカメラに自分の顔が写っている時はウォルマートの判定がでてしまうので
　画像を学習させるときにもう少し気を付ければよかったです。
●Webアプリがループで作動してしまうので、LINEに大量のメッセージが届いてしまいます。
　制御できるようにしたかったです。

#AI(機械学習)をもっと応用したい
今回初めてTeachable MachineとCodePenを使用しましたが
こんな簡単に機械学習やWebアプリを作ることができるんだと驚きましたし、
もっと色々なことに応用してみたいと思いました。

画像認識の場合は、送られてきた申請書の不備を見つけてくれるもの、
音声認識の場合は、セミナーで出てきた専門用語の意味を教えてくれるもの
があるといいなと思うので、いつか作れるようになってみたいです！
Mac版McAfeeの邪魔者（通知）を消す

## Mac版McAfeeの邪魔者

こいつ。Launchpad使用中でもついてくる邪魔者。

![McAfee.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163288/bb33d165-df95-0f28-93e9-9b0519df8281.jpeg)

### 結構悩まされている方はいた

* [McAfeeの通知が突然現れては消えないというのを繰り返してい... - Yahoo!知恵袋](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11242703071)
* [MacBookにマカフィーを入れていますが、最近、「マカフィー通知」、... - Yahoo!知恵袋](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10239271615)

## 原因はダークモードだった

[解決！マカフィー通知が消えない問題（mac） | 明日も！ギターブログ](https://guitar-effect.com/mcafee-mac/)

なんと、別の解決方法を見つけ出して、この記事を書く直前に見つけてしまった…。
でもわざわざ見つけたんだから、自分が見つけ出した方法も書いておく。

## 対処方法：ターミナルで1コマンド叩くだけ

McAfeeのタスクを再起動すれば消える。

```
sudo launchctl stop com.mcafee.virusscan.fmpd
```

## 最後に

解決方法を書いているサイトの通り、「閉じる」が消えているだけなので、右下あたりを空でクリックしていれば、隠れてる「閉じる」ボタンに命中して消える。
[tips]VScodeのショートカットキーまとめてみた。（随時追加予定）

## はじめに
皆様お久しぶりです。プレイライフの熊﨑です！
最近投稿できていませんでしたが、また少しづつ自分のアウトプットも兼ねて投稿を行っていきたいと思います！
今回は自分が業務でよく使うショートカットキーをまとめました！
新しいショートカットキーを使用したら随時更新します！

## vscodeのショートカットキー

|キー  |効果  |
|-----|-----|
|shift + tab|複数行のインデントを同時に削除できる|
|command + p|ファイル検索（ファイル名で検索）|
|shift + command + f|ファイル検索（含まれる文字で検索）|
|shift + command + h|複数ファイルで置換|
|command + f|ファイル内検索|
|option + command + f|ファイル内置換|
|command + a|全選択|
|command + w|ウインドウを閉じる|
|command + s|保存|
|command + c|コピー|
|command + v|ペースト|
|command + z|やり直し|
|command + j|ターミナルを開く|
|command + o|ファイル or フォルダを開く|
|command + b|サイドバーを表示 or 非表示|
|command + /|行をコメント化する|
|option + ↓ or ↑|１行丸ごと上 or 下に移動|
|shift + option + ↓ or ↑|１行丸ごと上 or 下にコピー|
|option + → or ←|単語ごとに移動|
|command + → or ←|行頭 or 行末に移動|
|controll + option + command + ¥|エディタの分割|

### rspec用
※vscodeのプラグインである、Rails Run SpecsとRails Go to Specをインストールする必要がある

|キー  |効果  |
|-----|-----|
|shift + command + y|ファイルに合わせたspecファイルを作成 specファイルに移動|
|shift + command + t|現在選択しているファイルのテストを実行|
|command + l|現在の行のテストを実行|
|command + y|最後に行ったテストを実行|

## 参考資料
[vscodeのショートカットキー（macOS）](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf)
AtCoderログ：0064 - ABC 213 に参加しました

この記事は 2021年08月08日(日)21:00-22:40 に開催された [AtCoder Beginner Contest 213 (ABC 213)](https://atcoder.jp/contests/abc213) に参加した記録です。

https://atcoder.jp/contests/abc213

# 結果
- 得点：600 (=100+200+300)
- 時間：78:05 (= 68:05 + 05:00 × 2)
- 順位：4187 / 8091
- パフォーマンス：583
- レーティング：268 → 307 (+39) Highest更新！
- 段級位：9級

![2021-08-08_abc213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/3e8dbc3b-4755-7024-ce06-c51ad58ae328.png)

# 詳細
|問題|得点|時間|提出コード|復習|
|:--:|:--:|:--:|:--:|:--:|
|[ABC 213 A](https://atcoder.jp/contests/abc213/tasks/abc213_a)|100|03:38|[○](https://atcoder.jp/contests/abc213/submissions/24856327)|[AtCoderログ：00**]()|
|[ABC 212 B](https://atcoder.jp/contests/abc213/tasks/abc213_b)|200|10:05|[○](https://atcoder.jp/contests/abc213/submissions/24862419)|[AtCoderログ：00**]()|
|[ABC 213 C](https://atcoder.jp/contests/abc213/tasks/abc213_c)|300|68:05(2)|[○](https://atcoder.jp/contests/abc213/submissions/24883461)|[AtCoderログ：00**]()|
|[ABC 213 D](https://atcoder.jp/contests/abc213/tasks/abc213_d)|400|---|---|---|
|[ABC 213 E](https://atcoder.jp/contests/abc213/tasks/abc213_e)|500|---|---|---|
|[ABC 213 F](https://atcoder.jp/contests/abc213/tasks/abc213_f)|600|---|---|---|

# 感想
- [前回から問題数が 8 問に増えていたようです::https://twitter.com/atcoder/status/1417819718895865858]。私が解ける範囲の問題では難易度の変化は感じられませんでした。
- A, B, C まで完答できました。
- A, B は素直に回答して正解。
- C の解法はすぐに頭に浮かんだのですが、コーディングするのに手間取ってしまい、時間の大半を使ってしまいました。
- D 以降に全く歯が立たないので、夏休みにグラフを勉強したいと思っています。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0063 - ABC 085 B](https://qiita.com/RoadLynton/items/fcdbb429c74bf7c61056)
- 次の記事 → [AtCoderログ：0065 - ABC 071 B](https://qiita.com/RoadLynton/items/a4026a43eb3b76489a4a)
[Flutter] pubspec.yaml(コメントアウトなし)

コメントアウトの削除がめんどくさい方に向けてです。

僕のためでもあります。。。



```dart
name: "you app name"
description: A new Flutter project.

publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
    
  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^1.0.0

flutter:
  uses-material-design: true

```
queryとprepareの使いわけ php

#■queryとprepareとは
PHPからデータベースを操作する手順です。

①データベースに接続
②実行したいSQL文をセットする。
③SQLに対してパラメーターをセットする。
④実際にSQLを実行する。
⑤結果を取得する。
⑥データベースから切断する。


###▼PHPからデータベースを操作するには簡易版と詳細版がある。
#■簡易版にはqueryをつかう。
上記の②③④の手順を簡易的に一括で行えるのがquery。

▼使い分け
SQL文の中に変動値がない場合queryを使う。

``` php
//変動値がないSQL文　例
$sql = "SELECT * FROM テーブル名";
```
▼使い方
セットから実行まで一括で行なっている。

``` php
$dbh->query($sql);
```


#■詳細版にはprepareを使う。
上記の手順通り個別に行う。②③④に個別にメソッドが用意されている。
②prepareメソッド
③bindValueメソッド
④executeメソッド

▼使い分け
SQL文の中に変動値がある場合prepareを使う。
プレースホルダを使用する際と同じ時に使う前記事で紹介。

``` php
//変動値があるSQL文(プレースホルダ使用) 例
$sql = "SELECT * FROM テーブル名 WHERE name= :name"; 
```
▼使いかた
②③④を個別に行う。
③のbindValueに関してはプレースホルダを使用するのに必要なメソッド

``` php
//②実行したいSQL文をセット
$stmt = $dbh->prepare($sql);
//③SQLに対してパラメーターをセット(プレースホルダを使用するのに必要な手順)
$stmt->bindValue(':name',$name,PDO::PARAM_STR);
//④SQL文の実行
$stmt->execute()
```
ABC213 B問題復習～AtCoder Beginner Contest 参戦録 #4

# はじめに

社内外の優秀なエンジニア達から「技術トークが多少わかる採用担当」として信頼を得たいと思い2020年6月から参加を始めた競技プログラミング。当時の職場のプロダクト開発で使用していたJavaScriptを使っていたが、2021年5月に開催された以下の大会から初学者にやさしいと言われるPythonに変更した。

https://atcoder.jp/contests/zone2021

採用の仕事からは離れたが、せっかくなので競プロを今度は仕事のためでなく自分のために続けようと思ったからだ。

学びやすい言語に変えたはいいが、実力を示すポイントである"Rating"が一向に上がらない（むしろ下がっている）。忙しさを言い訳に復習せずに本番に臨み続けているので当たり前だがなんとかできないものかと悩んでいたら、コンテスト後に公開される模範解答にPythonの実装例が追加されていることにある時気づいた。

そんなコンテンツやメンターをしてくれている友人エンジニアからのコメントをふまえて、直近開催された回で不正解となった問題の復習をした。気づきをここにまとめる。

# ABC213 復習

## 問題

https://atcoder.jp/contests/abc213/tasks/abc213_b

## 自分の誤答

```python
# -*- coding: utf-8 -*-
N = int(input())
A = list(input().split(" "))
B = [[0] *2 for i in range(N)]

for i in range(N):
    B[i][0] = A[i]
    B[i][1] = i

B.sort()

print(A[len(A)-2][1]+1)
```

## 学び・気づき

### 敗因

-  split()メソッドは文字列のリストを返すことを知らなかった
    -  整数に変換する必要があった
-  最後にprintする配列を勘違いしていた・・

### 模範解答からの学び

https://atcoder.jp/contests/abc213/editorial/2365

-  シンプルな書き方

    ```python
    A = list(map(int,input().split()))
    ```

-   区切り文字が空白であればsplit()メソッドの引数は省略可能

https://docs.python.org/ja/3/library/stdtypes.html#str.split

-   組になっているものを扱うときはタプルを使う
    -   リスト用意→append()メソッドでタプル要素追加
-   「最後から2番目」は「逆順から並べれば最初から2番目」

# おわりに

最近ABCの出題形式が大きく変わった。

https://twitter.com/atcoder/status/1417819718895865858

ハイレベルな人たちは同じ時間でより多くの問題を解くための取捨選択が大事だと語っているが、100点相当のA問題や200相当のB問題の難易度も上がっているような感覚がある。私のような本当のビギナーにもこの変更はインパクトがあった（と思う）。

1年前の自分のQiita記事を久しぶりに読み返したところ「C問題まで解けるようになることが目標」と繰り返し書いていた。退化しているようで悲しさもあるが今はB問題までを安定して解けるようになることが先決。今回のような復習記事も書きつつ、楽しくレベルアップできればいいなと思う。
勉強メモ25_Webアプリのログファイルに出ているエラーの種類と出現回数を抽出する

##0 はじめに

・Webアプリでは、調査のためアプリが動いている本番サーバーに
　アクセスしたときのログやエラーになったときのログを作成し、
　ログがたまったらgzファイルにして格納していることがあります。
　そんなgzファイルを展開して、エラーの種類やそのエラーの
　出現回数を調べるやり方の例です
・今回は、アプリのサーバーのOSがLinux(CentOS)だった時の例です。

##1 ログのディレクトリ構成

```shell:ログのディレクトリ構成
/apuri
  |-log
     |-apuri_20210730.log.gz # 1日経ったらgzに変更するように設定されているとします
     |-apuri_20210730.log.gz
     |-apuri_20210731.log.gz
     |-apuri_20210801.log.gz 
     |-apuri_20210802.log.gz
     |-apuri_20210803.log.gz
     |-apuri_20210804.log.gz
     |-apuri_20210805.log.gz
     |-apuri_20210806.log.gz
     |-apuri_20210807.log.gz
     |-apuri_20210808.log.gz
     |-apuri_20210809.log
```

##2 ログの中身
 ・ログは項目ごとにタブ区切りで出力されているとします
 ・項目は以下の通り
　　1項目目:ログ出力日付
　　2項目目:ログ出力時刻
　　3項目目:アクセスURL
　　4項目目:IPアドレス
　　5項目目:HTTPステータスコード
　　6項目目:エラー種類
　　7項目目:エラーの内容
　　8項目目:アクセスしたユーザー

※下記、項目間は半角スペースですが、実際はタブで区切りになっていることにします


```shell:apuri_yyyymmdd.log
2021/08/09 01:11:12 apuri/login.php 192.168.100.131 500 loginError ログインに失敗しました rinchome
2021/08/09 01:15:12 apuri/selectUser.php 192.168.100.130 500 selectError ユーザー情報取得に失敗しました rinchome
2021/08/09 01:15:13 apuri/selectUser.php 192.168.100.133 500 selectError ユーザー情報取得に失敗しました rinchome2
2021/08/09 01:15:16 apuri/selectUser.php 192.168.100.133 500 selectError ユーザー情報取得に失敗しました rinchome3

```

##3 エラーの種類やそのエラーの出現回数を調べるコマンド
 ・今回は2021年07月と08月のエラーの種類とその出現回数を取得
 ・コマンド上で出力する項目は、6項目(エラー種類)と7項目(エラーの内容)とする

```shell
$ zcat /apuri/log/apuri_202107*.log.gz /apuri/log/apuri_202107*.log.gz | awk 'BEGIN {FS="\t"} {print $6 "\t" $7}' |sort |uniq -c
# 上記、sortコマンドはオプション指定しない場合は、行単位で並び替えてくれる
# 上記、uniq -c で重複している内容の出現回数をカウントし、表示する
```

##4 実行結果イメージ
loginErrorのエラーが1回出現
selectErrorのエラーが3回出現
した場合

```shell
$ zcat zcat /apuri/log/apuri_202107*.log.gz /apuri/log/apuri_202107*.log.gz | awk 'BEGIN {FS="\t"} {print $6 "\t" $7}' |sort |uniq -c
      1 
      1 loginError      ログインに失敗しました
      3 selectError     ユーザー情報取得に失敗しました
```
【Java Silver】 関数型インターフェイス、ラムダ式対策

###目的
現在、Java Silverの取得に向けて勉強中です。関数型インターフェイス、ラムダ式関係の問題の理解に苦しんだので重要ポイントをまとめました。本記事が同じような目標を持った方に少しでも役にたったら幸いです。

###ラムダ式とは

関数型インターフェース：実装が必要なメソッドを一つだけもつインターフェースのこと。

```java
public interface calcSum{
    public abstract int sum(int num1, int num2);
}
```

ラムダ式：関数型インターフェースを実装する際に使われる式のこと。

通常、上記のCalcSumインターフェイスを実装し、利用する場合、以下のようにインターフェイスを実装し、実装したクラスをインスタンス化して利用します。

```java

//実行用クラス
public static void main(String []args){
　　　　　　　　calcSumImpl sum = new calcSumImpl();
    int answer = sum.calcSum(5,4);
    System.out.println(answer);
  
}
//インターフェイスを実装したクラス
class calcSumImpl implements CalcSum{
    @Override 
    public int calcSum(int num1,int num2){
        return num1 * num2;
    }
}

```
上記をラムダ式を使用して実装すると以下のようになります。メソッドは一つしかないので、メソッド名を省略できます。また、インスタンス化する処理も省略され、記述しているのは引数と｛｝内の実装部分だけです。

```java
public static void main(String []args){
    CalcSum calcSum = (int num1, int num2) -> {
      return num1 + num2;
    };
    int answer = calcSum.calcSum(5,4);
    System.out.println(answer); 
}

```
ラムダ式の基本構文は以下の通りです。

```
//構文
（引数） -> {};
```
###注意点①（記述の省略）
また、以下のように引数の型や｛｝、returnの記述を省略することができます。

```java
//引数の型を省略
 CalcSum calcSum = (num1,num2) -> {
      return num1 + num2;
    };

//{}やreturnを省略（処理が一行のみの場合）
 CalcSum calcSum = (num1,num2) -> return num1 + num2;
```
ただし、｛｝とreturnの省略、記述には以下の条件があります。
・ラムダ式で｛｝を省略した場合には、returnを記述できない。また、処理は１文のみ。
・ラムダ式で｛｝を記述した場合には、reutrnを省略できない。また、処理は複数行でも可。

###注意点②（変数のスコープ）
ラムダ式は、それを囲むボブロックと同じスコープをもつ。よって、ラムダ式を宣言しているブロックで宣言したローカル変数と同じ名前の変数はラムダ式内では宣言できません。また、ラムダ式外で宣言されたローカル変数にラムダ式内からアクセスするには実質的にfinalな変数でなければなりません。
そのため、以下のようにラムダ式内外で変数の値を変更しようとするとコンパイルエラーとなります。

```java
interface Function {
	void test();
}

public class Test {
	public static void main(String[] args) {
		String val = "hello";
		Function f = () -> {
            //val = "hello!hello!" //コンパイルエラー
			System.out.println(val);
		};
        //val = "GoodMorning!" //コンパイルエラー
		f.test(); //hello
	} 
}
```

###関数型インターフェース
関数型インターフェイスはプログラマが自由に定義できるが、頻繁に使われるであろうものについては、java.util.finctionパッケージとして追加されました。Java Silverでは以下に示す４つが試験でよく出題されます。

| 関数型インターフェイス | メソッド | 説明 |
|:-:|:-:|:-:|
| Consumer<T> | void accept(T) |  引数を受け取って処理をする。結果を戻さない、引数の消費者。 |
| Supplier<T> |  T get() | 何も受け取らずに結果だけを戻す供給者 |
| Predicate<T> |  boolean test(T) |  引数を受け取ってそれを評価する「断定」 |
| Function<T,R>  | R apply(T) | 引数を受け取って、指定された型（R）の結果を戻す「処理」  |（）
メモ > Reactで使えそうなフォームライブラリ


調べてる途中のメモです


## Schema

### [data-driven-forms](https://github.com/data-driven-forms/react-forms)

すべての機能を備えたフォームを構築するための宣言型の方法

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/f3dca3b4-4f4c-d27d-cfbd-bb9ba9e3ddad.png width=500px />




### [react-jsonschema-form](https://github.com/mozilla-services/react-jsonschema-form)

JSONSchemaからWebフォームを構築する


<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/ae952603-a023-8f7d-1ccb-c160592be0a0.png width=500px />

[react-jsonschema-formのをもっとかんたんに使う便利ツール - Qiita](https://qiita.com/immmmmmmm/items/4aab469c9026caffea6b)

[react-jsonschema-form playground](https://rjsf-team.github.io/react-jsonschema-form/)

[HTMLフォーム入力からJSONを生成できるWebサービスで遊んでみよう ( react-jsonschema-form ) - Qiita](https://qiita.com/YumaInaura/items/12524ee3a95fef9f3487)


[JSON Schemaとreact-jsonschema-form - Qiita](https://qiita.com/pirosikick/items/f4c010e5914caec13808#react-jsonschema-form)


## 人気？


### [react-hook-form](https://github.com/react-hook-form/react-hook-form)

Reactのフックを使って、手間をかけずにフォーム検証を行うことができます。


<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/2a86f86d-6201-be32-7c95-1e4c3c951d60.png width=500px />



### [formik](https://github.com/jaredpalmer/formik)

フォームを構築するための宣言型の方法で、Reactのフォームを制御するシンプルで簡単な方法です。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/706c9bfd-d59f-7d45-7ada-2a7aac363ed6.png width=500px />



## Form


### [formcat](https://github.com/guilouro/formcat) 

React ContextAPIを使用してReactのフォームを制御するシンプルで簡単な方法です。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/3060603c-407d-75d1-5944-d04f217a9413.png width=500px />


### [formy-react](https://github.com/formsy/formsy-react/)

React JS 用のフォーム入力ビルダとバリデータです。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/6eb141ad-d4f3-860e-87a9-ee766bd7a379.png width=500px />

### [react-final-form](https://github.com/final-form/react-final-form)

サブスクリプションベースのフォーム状態管理。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/011667d4-c3a5-62d5-e892-26450743117a.png width=500px />


### [react-formawesome](https://github.com/MAKARD/react-formawesome)

素晴らしいフォームを作るための複雑なライブラリ。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/643e908f-5bc2-ffdc-2714-2836537c16ff.png width=500px />


### [surveyjs](https://github.com/surveyjs/survey-library)

進化したアンケート・フォームライブラリ。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/09977703-70cf-0f34-10e1-81bece4000d8.png width=500px />


## 更新されてない

### [prexus-form](https://github.com/AppliedMathematicsANU/plexus-form)

6 years ago
JSON-Schemaを利用したReact用の動的なフォームコンポーネントです。


### [react-validation-mixin](https://github.com/jurassix/react-validation-mixin)

React用のシンプルな検証mixin(HoC)です。

6 years ago
This repository has been archived by the owner. It is now read-only.
「出力として使用」で子Botから親Botへ情報を渡す

#はじめに
子Botの変数に「出力として使用」をチェックし、子Botから親Botへ変数を渡す場合のやり方は、いくつかあります。以下、簡単にまとめてみます。

# 親Botで辞書変数を定義し、子Botの変数名をキーとして使う
一番最初はこのやり方だけでした。
![arg01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/ff3a1529-178d-ecac-4640-25fd36d60005.png)

例えば子Botのko1という変数を親のreturnDicというディクショナリ変数で受けて、returnDic{ko1}のように参照します。

# 親Botで「複数の変数」で受ける。
Automation360（A2019）の途中から出てきたやり方です。
![arg02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/3ba15e9f-d5bc-21a2-b0bf-1463b5c11417.png)

子Botから渡ってきた情報を親Botのどの変数で受けるか子Botの変数毎に指定します。「キー」が子Botの変数を示して「変数にマップする」で親のどの変数で受けるかを指定します。
親Botでディクショナリ変数の指定は不要です。
なので「キー」という表記は「ディクショナリ」で受けていた時代を知っている人にとっては理解しやすいのでしょうが、初めてここから入る人は「キー」って何？？と疑問に思いそう。

# 親Botで「複数の変数」で受ける、でさらにクイックマップを使う
前の項とほぼ同じですが、「複数の変数」ではクイックマップが使えます。
クイックマップを使うと親Bot側の変数を自動で作ることができます。変数名はデフォルトで子Botの変数名と同じです。
![arg03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/3982d7e5-c10e-667e-383a-be7e6b6d086b.png)


ここまで来ると、V11のクイックマップと同じですね。
ただ「マップされた変数」のキー「ko1」というのが、これだけ見ると不思議な感じがします。
最新では「複数の変数」がデフォルトになっているので、ディクショナリとかキーとか全部捨てて、V11のように「親Botの変数」「子Botの変数」の対応付け表にすればわかりやすいのにな、
などと思ってしまいます。
node puppetterでwait系の処理を結構書いたので、メモ


```javascript
const Util = require('./util');

const wait = {
	/**
	 * 指定時間処理を止める
	 */
	sleep : async (time)=>{
		if(time === undefined){
			time = process.env.puppet_wait_ms;
		}
		return new Promise(resolve => {
			setTimeout(() => {
				resolve();	
			}, time);
		});
	},
	/**
	 * 指定のエレメントにselecter要素が表示されるまで待つ
	 * @param  ElementHandle  elem puppeteerのElementHandle
	 * @param  string  selecter
	 * @return Promise  listで返す
	 */
	forChildSelecter:async (elem,selecter) =>{
		let isShow = false;
		let targElms = {};
		for(let i = 1 ; i <= process.env.puppet_wait_count; i++){
			targElms = await elem.$$(selecter);
			if(targElms.length > 0){
				isShow = true;
				break;
			}
			await wait.sleep();
		}
		if(isShow === false){
			throw new Error(process.env.puppet_wait_count+'回待ったけどダメ!');
		}else{
			return targElms;
		}
	},
	/**
	 * 指定のエレメントの中のselecter要素が消えるまで待つ
	 * @param  ElementHandle  elem puppeteerのElementHandle
	 * @param  string  selecter
	 */
	forChildSelecterHide: async(elm,selecter)=>{
		let isShow = true;
		let targElms = {};
		for(let i = 1 ; i <= process.env.puppet_wait_count; i++){
			targElms = await elm.$$(selecter);
			if(targElms.length == 0){
				isShow = false;
				break;
			}
			await wait.sleep();
		}
		if(isShow === true){
			throw new Error(process.env.puppet_wait_count+'回待ったけどダメ!');
		}else{
			return true;
		}
	},
	/**
	 * 指定のエレメントの中のselecter要素が作られて、消えるまで待つ
	 * @param  ElementHandle  elem puppeteerのElementHandle
	 * @param  string  selecter
	 */
	forChildSelecterShowAndHide:async (elm,selecter)=>{
		await wait.forChildSelecter(elm,selecter);
		await wait.forChildSelecterHide(elm,selecter);
		return true;
	},
	/**
	* ElementHandleから指定のClassNameが無くなるのを待つ。
	* 再帰確認時間はenv.puppet_waitでms
	*/
	removeClass : async (elem,targClassName)=>{
		let isRemove = false;
		for(let i = 1 ; i <= process.env.puppet_wait_count; i++){
			let handle = await elem.getProperty('className');
			let classNames = await handle.jsonValue();
			if(classNames.indexOf(targClassName) == -1){
				isRemove = true;
				break;
			}
			await wait.sleep();
		}
		if(isRemove === false){
			throw new Error(process.env.puppet_wait_count+'回待ったけどダメ!');
		}else{
			return true;
		}
	}
};
module.exports = wait;

```
nodeで.envを作る

node.jsで設定ファイルを一か所に集めたくなったので、
envファイルで設定値を保存したくなったので調べたら
[dotenv](https://www.npmjs.com/package/dotenv)っていうパッケージを見つけたので、
使ってみた。

## dotenvのページ

https://www.npmjs.com/package/dotenv

##　インストール

```bash
npm install dotenv
```

##　.envファイルを作る

プロジェクトルートに.envファイルを作る

中身はこんな感じ

```env:/.env
hoge = hogehogehogehoesetting

# 環境変数を定義コメントはこんな感じ
fuga = 設定値

```

## 使う

index.jsに以下を配置

```javascript
require('dotenv').config();
```

他のファイルでは、読み込む必要は無い

### 設定値の読みだし

```javascript
console.log(process.env.hoge) // hogehogehogehoesetting
```
って感じで、設定している文字列を取得できる

ちょう簡単
WIndows 365は便利な代物？

# Windows 365とは
Microsoftが提供し始めたDaaSのシステムである。DaaSのため、環境依存が少なくなると期待される。
# Windows 10が使える
クラウド環境でWindows 10を使うにはどうしてもMicrosoftが提供するシステムが必要になっていた。なので、今回、一応Windows 365でWindows 10のシステムをクラウド上に整えることができるようになった。

# 料金的にはどうなの？
クラウドのリソースを使うという面においてどうしても気になるのは、コストである。実際、筆者的には高いようにも思えるが利点も多いのは事実である。
筆者の契約したスペックは2コアで4GBのメモリ、64GBのSSDで月約5000円の出費である。1年で約6万円。うーん。なかなかいい、デェアルコア（クアッドコア）のノートPCが買えてしまうけどな。。。。

# メリット
+ インターネットの接続できる場所から同じ環境にアクセスできる。
+ クライアントの環境に左右されにくい。（インターネット環境に関しては依存してしまうが。）
+ パスワードなどの入力を察知されにくい
+ インストールを必要とするソフトウェアを持ち運びできる
+ システムの入れ替えなどで発生するリスクを低減することができる
+ 今までWindowsが入らないような低スペックマシンでもLinux等からの接続が容易に可能となった。（ラズベリーパイなど）


# デメリット
+ コストがかかる（特に快適な環境を整備するにはそれなりの費用がかかる）
+ デフォルト言語が英語設定である
+ リモート環境に関する多少の知識が必要となる
+ ゲーム、動画の視聴には向いていない。（pingの遅延がひどい）。 
+ サーバ用のCPUなので、クロック数が低く、2コア構成であったとしても一般的なデェアルコアCPUのCore i3 よりかはずっと低スペックマシンのように感じられる
+ 一部サイトへの接続が制限されている場合があり、自宅VPNや日本にあるVPN等に接続した上でサイトの閲覧が必要となることがある。（サーバが設置されている場所等に左右される）


# 無料試用で満足できるなら
筆者は無料試用版の契約ができなかったので、有料契約に踏み切ったが、これを読んだ読者は試用版が復活するまでまってから契約したほうがよいと思われる。とくにレスポンス等に関してはそこまで期待できない。

# 英語版のWindowsを日本語版のWindowsへ

https://qiita.com/n_hideyuki/items/8eacaf490282f60350ea

上記のページで日本語化について書いているので参考にしてほしい。

# windows 365やめる
最近下記の理由のためwindows 365やめました。
* cpuやメモリの制約が多すぎる（お金を払えば別だが、これ以上コストを割けない）
* 自宅サーバに安全に接続できるようになった
* Windows10 使用のマシンが多い
Swiftでの非同期処理

## 非同期処理

同期処理では上から行われるだけですが、非同期処理では並行処理が可能です。

同期処理では`画像ダウンロード開始` `ダウンロード完了` `プログラム終了`となりますが、
非同期処理でかくと`画像ダウンロード開始` `プログラム終了` `ダウンロード完了` となり、重い処理を待たずに次の処理が可能です。

```swift
import Foundation
import PlaygroundSupport
import Dispatch
import UIKit

// Playground上で非同期処理を行えるようにする
PlaygroundPage.current.needsIndefiniteExecution = true

func downloadImage(url: URL, completion: @escaping(Data)->Void) {
    let request = URLRequest(url: url)
    
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        if let data = data {
            completion(data)
        }
    }
    
    task.resume()
}

var image : UIImage?

print("画像ダウンロード開始")

let url = URL(string: "https://www.apple.com/jp/iphone-12/images/meta/iphone-12_overview__e6j9bvy6778m_og.png")!

downloadImage(url: url) { (data: Data) in
    image = UIImage(data: data)
    print("ダウンロード完了")
}

print("プログラム終了")

```
PyGrADSのインストール・使い方

# はじめに
気象・大気などの地球科学系の研究室なら、よく使うGrADS。
GrADSの拡張ライブラリであるpyGrADSが、python 3系に対応してライブラリとして使えるようになったらしい。

> 2021-07-05 Arlindo da Silva <dasilva@opengrads.org>, Version 3.0.b1
	* First major revision support Python 3
	* Python 2 support has been dropped
	* pygrads and ipygrads.py have been updated to latest IPython

(ChangeLogより)


端くれ大学院生として、誰かの役に立てれば幸いです。
（レスポンスもらえれば、書き足していきます。LGTMください（笑））

# 動作確認環境
- python 3.8.5
- pygrads 3.0.b1

# インストール
この章の目標：pyGrADSのインストールを行い、``.py``ファイルで使えるようにする
## ダウンロード

[こちら](https://sourceforge.net/projects/opengrads/files/python-grads/3.0.b1/)にアクセスし、
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407666/cf892a0e-3132-4b9a-8aee-92789f55f36c.png)
赤枠をクリックし、インストールを開始してください。

## 解凍
ダウンロードしたファイルは圧縮ファイル（.tar.gz）ですので、解凍を行います。

- Linux環境

```terminal
tar -zxvf pygrads-3.0.b1.tar.gz
```
で解凍できます。

- Windows

[lhaplus](https://forest.watch.impress.co.jp/library/software/lhaplus/)とかで（多分）解凍できると思います。

- Mac

特にソフトウェアなどは要らず、Zipなどと同様にダブルクリックで解凍できます。


解凍が完了すると、フォルダーが作成されます。
インストールは、解凍されたこのファイルから行います。

## インストール
ターミナルなどを用いて、フォルダーに移動してください。

ex.解凍済みフォルダーがデスクトップにある時

```
cd Desktop/pygrads-3.0.b1
```

移動ができたら、

```
python setup.py install
```

でインストールを行ってください。

インストールが完了すれば、

```python:test.py
import grads
```

でインポートができるはずです。


# 使い方
要望が多ければ作ります。
LGTMください。（笑）

# 最終更新日
- 2021/08/09
nodeで対話型のCLIを作る。


## コマンドライン受付部分を作る

```javascript:index.js
const readline = require('readline');
require('dotenv').config();
const Handler = require('./cli/handler');

const start = async ()=>{

	await Handler.init();//起動と同時にやる処理
	
	//準備
	const reader = readline.createInterface({
		input: process.stdin,  // 標準入力
		output: process.stdout, // 標準出力
		prompt :'やること入力して> '
	});



	// Enterキー押下で読み込み
	reader.on('line', async (line) => {
		if(line !== ''){
			//入力を取得して、コマンドと引数に分ける
			const args = line.split(/\s+/);
			const cmd = args.shift();
			//Handlerの中の関数を実行する
			await Handler[cmd](args);		
		}else{
			console.log('');
		}
		reader.prompt();
	});

	// ctrl+Cで終了
	reader.on('close', () => {
		console.log("finish");
	});

	// コマンドプロンプトを表示
	reader.prompt();
}
//実行
start();
```

##実行するコマンドを定義する

```javascript:handler.js
const Hogehoge = require('../app/hogehoge');

const handler = {
	'init': async (args)=>{
		console.log('システムにログインする');
		await Hogehoge.fugafuga();
		console.log('ログイン完了');
	},
	comandFuga:async()=>{
		console.log('comandFugaを実行');
		await Hogehoge.fuga();
		console.log('完了')
	},
	's': async(args)=>{
		console.log('オレオレコマンドなら、1文字のコマンドの方がいいよね');
		await Hogehoge.search(args);
		console.log('表示完了');
	},
};
module.exports = handler;
```
SQLのCASE式を用いて合計と再掲を表頭（列の方）に出力する行列変換

## 問題

`PopTbl2`（再掲）という仮のテーブルがあるとします。

| pref_name（県名） | sex（性別） | population（人口）  |
|----------------|----------|------------------|
|     徳島        |    1     |     60           |
|     徳島        |    2     |     40           |
|     香川        |    1     |     100          |
|     香川        |    2     |     100          |
|     愛媛        |    1     |     100          |
|     愛媛        |    2     |      50          |
|     高知        |    1     |     100          |
|     高知        |    2     |     100          |
|     東京        |    1     |     250          |
|     東京        |    2     |     150          |

これを、以下のような表頭に合計や再掲の列を持つようなクロス表を作ってください。

### 結果

| 性別 | 全国 | 徳島 | 香川 | 愛媛 | 高知 | 四国（再掲） |
|-----|-----|------|-----|------|-----|----------|
| 男  | 610  |  60  | 100 | 100 | 100 |   360    |
| 女  | 440  |  40  | 100 | 50  | 100 |   290    |

## SQL

この問題は、下記の記事の復習くらいの難易度なので、解説は省略します。

https://qiita.com/ryosuketter/items/d09c0fc8abf134165d22

```sql
SELECT
  sex,
  SUM(population) AS '全国',
  SUM(CASE WHEN pref_name = '徳島' THEN population ELSE NULL END) AS '徳島',
  SUM(CASE WHEN pref_name = '香川' THEN population ELSE NULL END) AS '香川',
  SUM(CASE WHEN pref_name = '愛媛' THEN population ELSE NULL END) AS '愛媛',
  SUM(CASE WHEN pref_name = '高知' THEN population ELSE NULL END) AS '高知',
  SUM(CASE WHEN pref_name IN ('徳島','香川','愛媛','高知') THEN population ELSE NULL END) AS '四国（再掲）'
FROM PopTbl2
GROUP BY sex
```

## 参照

https://www.amazon.co.jp/dp/4798157821/

24p

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
AtCoderログ：0063 - ABC 085 B

# 問題

https://atcoder.jp/contests/abc085/tasks/abc085_b

## 問題文
> $X$ 段重ねの鏡餅 $(X \ge 1)$ とは、$X$ 枚の円形の餅を縦に積み重ねたものであって、どの餅もその真下の餅より直径が小さい（一番下の餅を除く）もののことです。例えば、直径 $10$、$8$、$6$ センチメートルの餅をこの順に下から積み重ねると $3$ 段重ねの鏡餅になり、餅を一枚だけ置くと 
$1$ 段重ねの鏡餅になります。
> ダックスフンドのルンルンは $N$ 枚の円形の餅を持っていて、そのうち 
$i$ 枚目の餅の直径は $d_i$ センチメートルです。これらの餅のうち一部または全部を使って鏡餅を作るとき、最大で何段重ねの鏡餅を作ることができるでしょうか。

## 制約
> ・$1 \le N \le 100$
> ・$1 \le d_i \le 100$
> ・入力値はすべて整数である。

## 収録されている問題セット
- [AtCoder に登録したら次にやること](https://qiita.com/drken/items/fd4e5e3630d0f5859067) ([第07問](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-7-%E5%95%8F--abc-085-b---kagami-mochi-200-%E7%82%B9))
- [AtCoder Beginners Selection](https://atcoder.jp/contests/abs)

# 回答
## 回答1 (AC)
配列に保持された値の種類をカウントする問題です。値は整数で、その範囲は狭いので、さまざまな回答が考えられます。

まずは、値の種類をカウントするための配列 m を使用します。直径 d の餅が存在するときは m.at(d)=true, 存在しないときは m.at(d)=false となるように配列の値を設定していきます。count(m.begin(),m.end(),true) によって、配列 m に含まれる true の個数をカウントできます。コードは以下のようになりました。

```C++:abc085b-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n;
  cin >> n;
 
  vector<bool> m(101,false);
  int t;
  for ( int i=0; i<n; i++ ) {
    cin >> t;
    m.at(t) = true;
  }

  int answer = count(m.begin(),m.end(),true);
 
  cout << answer << endl;
}
```
なお、ここでは配列 m の値をブール値にしましたが、これを整数に変更することで、各値が何個存在するかを調べることもできます (が、今回の問題ではそこまでは必要なかったので、ブール値にしました)。

## 回答2 (AC)
カウントしたい配列の値が整数以外の場合や、整数だとしても範囲が膨大である場合には回答1を適用できません。そこでよく使用されるのが map 型変数です。map 型変数は 2 つの値 (key と value) のペアとして表され、key と呼ばれる値から value と呼ばれる値を参照することが可能です。いわゆる辞書型変数です。key の重複はできないので、この問題のように値の種類が必要な場合によく使用されます。map を使ったコードは以下のようになりました。

```C++:abc085b-2.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n;
  cin >> n;
 
  map<int,bool> m;
  int t;
  for ( int i=0; i<n; i++ ) {
    cin >> t;
    m[t] = true;
  }
  int answer = (int)m.size();
 
  cout << answer << endl;
}
```

## 回答3 (AC)
今回の問題は値の種類をカウントしたいだけなので、set 型変数を使うことが出来ます。set 型変数の要素は重複はできないし、要素そのものしか保存されないので、今回の問題には最適です。set を使ったコードは以下のようになりました。

```C++:abc085b-3.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n;
  cin >> n;
 
  set<int> m;
  int t;
  for ( int i=0; i<n; i++ ) {
    cin >> t;
    m.insert(t);
  }
  int answer = (int)m.size();
 
  cout << answer << endl;
}
```

# 調べたこと
## [AtCoder に登録したら次にやること](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-7-%E5%95%8F--abc-085-b---kagami-mochi-200-%E7%82%B9)
回答1と回答3が紹介されていました。

## [AtCoder の解説](https://atcoder.jp/contests/abc085/tasks/abc085_b/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2018/01/07/224838)
回答3と同じ方針でした。

## [AtCoder の解説](https://atcoder.jp/contests/abc085/tasks/abc085_b/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/abc085/editorial.pdf)
方針1は回答1、方針2は回答3と同じでした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0062 - CODE FESTIVAL 2016 qual B B](https://qiita.com/RoadLynton/items/fd27eb724b58c947fd05)
Scalaのソースコード整形ツールについて

私が初めて Scala を触ったのが [Eclipse](https://www.eclipse.org/downloads/) + [ScalaIDE](http://scala-ide.org/) なのですが、その時からソースコード自動整形ツールが導入されており、複雑な for 文やメソッドチェーンも「なるほどこういう風に改行やインデントを工夫すると見やすくなるのかー」と感心したものです。最近では業務やOSSなどで複数人で開発していると、ソースコードに対するスタイルの考え方の不一致も増えてきて、レビュー指摘が荒れたりもしますが、そんなときでも自動整形ツールがあれば、そのツールの出力に従うというルールのもとで開発を円滑に進めることができます。そんな、最近では必ず設定されるソースコード自動整形ツールについてちょっと調査したのでその備忘録＆ポエムとして残しておきます（Scalaが対象です）。

# Scalariform

https://github.com/scala-ide/scalariform

ScalaIDE のフォーマッター機能である Scalariform は、昔から使われていたので、ある程度歴史がある Scala プロダクトのフォーマッターでは使われていたりします。ScalaIDE の他、[sbt プラグイン](https://github.com/sbt/sbt-scalariform)もあるため、Eclipse ベースではないプロジェクトでも利用可能です。

ただ、残念ながら[更新が途絶えていて（現時点で2019年が最新版）](https://github.com/scala-ide/scalariform/releases/tag/0.2.10)、Scala3 も出た昨今、ちょっとサポートに難があるかもしれません。

IntelliJ IDEA でサポートされないのも辛いです（[検索するとプラグインがヒットする](https://plugins.jetbrains.com/plugin/7480-scalariform)が、最新版のIntelliJ IDEAにはインストールできない）。

# Scalafmt

https://github.com/scalameta/scalafmt

もう一つの Scala フォーマッターである Scalafmt は [IntelliJ IDEA に標準対応](https://pleiades.io/help/idea/work-with-scala-formatter.html)しています。更新も活発で、[Scala3 にも対応しています](https://scalameta.org/scalafmt/docs/configuration.html#scala-3)。とりあえずフォーマッター入れたいのであれば、Scalafmt にしておくのが今のところベターなんですかね？

## 導入方法

せっかくなので既存 sbt プロジェクトへの導入方法です。といっても、やることは少なくて plugins.sbt への追加と `.scalafmt.config` を追加するだけです。

```plugins.sbt
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.0")
```

```config:.scalafmt.config
version = 3.0.0-RC6
preset = IntelliJ
```

これで `sbt scalafmtAll` とすれば、配下にある scala ファイル全てをフォーマットしてくれます。

```
$ sbt scalafmtAll
```

らくしょーですね！


## .scalafmt.config

[色々と設定があります](https://scalameta.org/scalafmt/docs/configuration.html)が、個人的にはバージョンの指定と[presetの指定](https://scalameta.org/scalafmt/docs/configuration.html#presets)だけにしたほうがいいかなーと思っています。

### version

このバージョンは scalafmt-core のバージョンです。省略すると latest が設定されます。省略した場合の難点として、 scalafmt-core のバージョンが上がったときに既存のフォーマットに変更がある可能性があります。また、パッチバージョンアップであっても、フォーマットに変更がないことが保証されません。そのため、この規則を省略していると、いつの間にかフォーマット規則が変更されて自分が変更していないコードのフォーマット結果がコミットに含まれるとかいう地獄が形成されかねません。

### preset

いくつかの設定をまとめたものです。下記があるようです。

- default
- IntelliJ
- defaultWithAlign
- Scala.js

よほど凝ったことをしたいということがない場合は default か IntelliJ にしておくと良いでしょう。

## 備考

フォーマットされていないコードを scalafmt でフォーマットした場合、稀にフォーマットされないことがあります。その場合は2~3回 `sbt scalafmtAll` してみて、出力結果が変わらないことを確認してからコミットしましょう。

# まとめ

- Scalariform は古くなってしまったので、今からフォーマッターを導入する場合は Scalafmt を使いましょう。
- ところで、既存のプロジェクトに Scalafmt をいれて `sbt scalafmtAll` をするとめっちゃ差分でるんですが、こういったフォーマッターの入れ替えや適用って皆さんどうしていますか？他の進行中のブランチとの兼ね合いもあるし、上手い導入の仕方を知っている人がいたら教えて欲しいです :pray:
プレースホルダ　php

#■プレースホルダとは
SQLインジェクション(DBに対して第三者が不必要なSQLを実行する事)等から守る方法
開発者の想定しない命令テーブルのデータ消去等を悪意のある第三者にさせないために使う。

万が一不正な値が入力されても第三者にSQL文の命令はできなくなる。

###▼SQL文の中にPHPの変数を直接書いてはダメ！！！
SQLインジェクションが容易に行えるようになってしまう!!

``` php
//■ダメな例
$sql = "SELECT * FROM user WHERE name= '$name'";
```

#■プレースホルダを使用する。
①変動箇所を:で指定。文字列カラムでもシングルクオテーションは不要。
プレースホルダの名前はカラム名と同じにしておくと分かりやすい。


``` php
$sql = "SELECT * FROM user WHERE name= :name";
```

②プレースホルダに実際の値をバインドする。
実際にプレースホルダを使えるようにここで指定してる。

``` php
$sql = "SELECT * FROM user WHERE name= :name";

//bindValue('プレースホルダ名',バインドするデータ,データの型);
bindValue(':name', $name, PDO::PARAM_STR);
```

文字型:PARAM_STR
数値型:　PARAM_INT
ラージオブジェクト(画像データなど)  PARAM_LOB
NULL   PARAM_NULL
PHP7.4でzipがインストールできない

PHPのインストールでzip（**php74-php-pecl-zip**）のインストールに依存関係の問題で少しはまったのでメモ。php -m　で「zip」が表示されてない状態。

環境：PHP/7.4 OS/Amazon Linux2

結論からいうと、Amazon Linux2のリポジトリが邪魔して、依存関係を解決できない状態になってました。

###1.**libzip-1.3.2-1.amzn2.0.1.x86_64**が邪魔してインストールできない

```
[root@ ~]# yum install php74-php-pecl-zip

--> トランザクションの確認を実行しています。
---> パッケージ php74-php-pecl-zip.x86_64 0:1.19.3-2.el7.remi を インストール
--> 依存性の処理をしています: libzip5(x86-64) >= 1.8.0 のパッケージ: php74-php-pecl-zip-1.19.3-2.el7.remi.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ **libzip5.x86_64 0:1.8.0-2.el7.remi** を インストール
--> 依存性の処理をしています: libzstd(x86-64) >= 1.3.6 のパッケージ: libzip5-1.8.0-2.el7.remi.x86_64
--> 依存性解決を終了しました。
エラー: パッケージ: libzip5-1.8.0-2.el7.remi.x86_64 (remi-safe)
             要求: libzstd(x86-64) >= 1.3.6
            インストール: **libzstd-1.3.3-1.amzn2.0.1.x86_64** (@amzn2-core)
                libzstd(x86-64) = 1.3.3-1.amzn2.0.1
            利用可能: libzstd-1.3.3-1.amzn2.x86_64 (amzn2-core)
                libzstd(x86-64) = 1.3.3-1.amzn2
```
よく読むと必要なパッケージに**remi**って書いてあります。

###2.**libzip-1.3.2-1.amzn2.0.1.x86_64**を削除

```
yum remove libzip-1.3.2-1.amzn2.0.1.x86_64
```

###3.**amzn2-core**をrepoを対象から外す。

```
yum update --disablerepo=amzn2-core
```

ここがちょっと盲点でした。
まさかAmazon Linux2のリポジトリが邪魔してるなんて思いもしませんでした。

https://twitter.com/wjspg/status/1407680680440385543?s=20

###4.改めて**php74-php-pecl-zip**をインストール

```
[root@ ~]# yum install php74-php-pecl-zip
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ php74-php-pecl-zip.x86_64 0:1.19.3-2.el7.remi を インストール
--> 依存性の処理をしています: libzip5(x86-64) >= 1.8.0 のパッケージ: php74-php-pecl-zip-1.19.3-2.el7.remi.x86_64
--> 依存性の処理をしています: libzip.so.5()(64bit) のパッケージ: php74-php-pecl-zip-1.19.3-2.el7.remi.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ libzip5.x86_64 0:1.8.0-2.el7.remi を インストール
--> 依存性解決を終了しました。

依存性を解決しました

インストール:
  php74-php-pecl-zip.x86_64 0:1.19.3-2.el7.remi                                                   

依存性関連をインストールしました:
  libzip5.x86_64 0:1.8.0-2.el7.remi
```

今回の問題の直接的な解決には繋がらなかったけど、パッケージのリポジトリまわりはこの記事が参考になりました。どのリポジトリがきいてるとか、このパッケージはこのリポジトリから入れてるよってのも知ることができます。
https://qiita.com/SwuBHj8aKGqBKHet/items/5dba7a80d63c52d89b82

rpmでハマったことは何度もあったけど、yumでハマることはあんまりなかったので、yumまわりの仕組みがいろいろわかりました。Remiってずっとなんだと思ったけど、人の名前でした。Remi Colletさん。
📦Docusaurusの複雑なプラグイン設定にハマるな

この記事では[Vercel](https://vercel.com)でデプロイした[Docusaurus 2.0.0-beta.4](https://docusaurus.io/)を使っています。

## 説明
Docusaurusを使い始めたが、あまりにもDocusaurusを使っている途中にハマってしまったので、紹介したいと思う。

Docusaurusには、**プラグイン**という機能がある。
例えば
 - docsとblog以外のディレクトリを追加する(@docusaurus/plugin-content-docs)
 - Google Analyticsと連携する
などの機能がある。
私はこの両方の機能の設定でハマった。

## plugin-content-docs で複数ディレクトリを追加する
公式サイトの説明は[こちら](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-docs)。

例えば、
- docs
- blog
- **article**
- **memo**
- **qanda**
というディレクトリ構成にする。
この場合、`docs`と`blog`はデフォルトで使用可能だが、`article`と`memo`と`qanda`は存在しない。

このプラグインを設定する時、値は一つしか設定できない。
だが複数設定する際には、以下のように`@docusaurus/plugin-content-docs`プラグイン自体を複数参照すればいい。

~~~javascript
  plugins: [
    [
      '@docusaurus/plugin-content-docs',
      {
        id: 'article',
        path: 'article',
        routeBasePath: 'article',
        editUrl: "https://github.com/OO/OOO/edit/main",
        editCurrentVersion: true,
        sidebarPath: require.resolve('./article/sidebars.js'),
        showLastUpdateAuthor: true,
        showLastUpdateTime: true,
      },
    ],
    [
      '@docusaurus/plugin-content-docs',
      {
        id: 'memo',
        path: 'memo',
        routeBasePath: 'memo',
        editUrl: "https://github.com/OO/OOO/edit/main",
        editCurrentVersion: true,
        sidebarPath: require.resolve('./memo/sidebars.js'),
        showLastUpdateAuthor: true,
        showLastUpdateTime: true,
      },
    ],
    [
      '@docusaurus/plugin-content-docs',
      {
        id: 'qanda',
        path: 'qanda',
        routeBasePath: 'qanda',
        editUrl: "https://github.com/OO/OOO/edit/main",
        editCurrentVersion: true,
        sidebarPath: require.resolve('./qanda/sidebars.js'),
        showLastUpdateAuthor: true,
        showLastUpdateTime: true,
      },
    ],
~~~

## plugin-google-analyticsの場所
公式サイトは[こちら](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-google-analytics)。

公式サイトによると

~~~javascript
module.exports = {
  plugins: ['@docusaurus/plugin-google-analytics'],
  themeConfig: {
    googleAnalytics: {
      trackingID: 'UA-141789564-1',
      // Optional fields.
      anonymizeIP: true, // Should IPs be anonymized?
    },
  },
};
~~~
とある。
実はこのプラグインは特殊でJavaScriptの`plugin`下には書かず、`module.export`下に書く。
なので、このようになる。

~~~javascript
module.exports = {
  plugins: ['@docusaurus/plugin-google-analytics'],
  themeConfig: {
    googleAnalytics: {
      trackingID: 'UA-141789564-1',
      // Optional fields.
      anonymizeIP: true, // Should IPs be anonymized?
    },
  },
 plugins: [
 ]
};
~~~

初めての記事投稿なので下手ですが、是非コメントで改善点を教えてくださると助かります！
Docusaurusユーザーがハマらずに設定出来たらうれしいです。

## 参考
1. [Sasigume氏によるTweetのリプライ](https://twitter.com/sasigume/status/1421766427120267264?s=20)
2. [NikitaIT氏によるissue](https://github.com/facebook/docusaurus/issues/3299)
3. [Discordによるサポート](https://discord.com/channels/398180168688074762/867060369087922187/871383296054013952)