OmniAICreator/Qiita-1.07M huggingface dataset:
EDA Salon 第2回 - 世界の家畜生産量データ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/3a36a618-1d2d-db0a-7fc4-c22d5c07bf39.png)



<span style="color: gray; ">photo by pixabay</span>

# EDA Salon 第2回 - 世界の家畜生産量データ

今月は世界の家畜生産量に関するデータを探索的にデータ分析してみてください！

# データの場所

データは[こちら](https://exploratory.io/data/GMq1Qom5tS/svI8NNl3BJ)からダウンロードしてください。

ダウンロードできる形式は、EDFとCSVで用意しています。
EDFの場合は、データラングリングのステップもインポートできるため、どのようなラングリングをしているのかみたい場合はEDFの使用をお勧めします。


# データについて

このデータはFAO(Food and Agriculture Organization of the United Nation / 国際連合食糧農業機関)という世界の食糧生産と分配の改善に取り組む国連の専門機関が世界の食料・農林水産業に関する[データを公開している](http://www.fao.org/faostat/en/#data)のですが、そこからダウンロードしてきたデータを一部可視化や、分析を行いやすいように加工したものです。

元のデータは[こちら](http://www.fao.org/faostat/en/#data/QA)から。


# データの説明

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192148/09af1b87-b1c0-24a4-8c07-4eda1d38180e.png)

それぞれの列の説明です。

* Area - 国名
* Item - 動物の名前
* Unit - 生産量の単位
* Year - 年
* Value - 生産数


# サンプルの質問

データを探索的に分析するにあたって、最初に設定する質問は自分が興味のある質問を設定してみてください。

もし、どういった質問をすればいいのかわからない場合は、以下の質問を参考にしてみてください。

* どのような種類の家畜生産量が長年にわたって上昇または下降していますか？
* どの国で家畜生産量が増減していますか？
* 地域ごとに家畜の種類に傾向はありますか？


# EDA Salonへの参加方法

また、Exploratoryでデータを可視化したり、分析したら、それをノートに簡単にまとめて、「EDASalon」というタグ付きでパブリッシュしてみて下さい！

EDA Salonへの参加方法の詳細は下記をご覧ください。

* [EDA Salon: 探索的データ分析をみんなで学ぶ場](https://exploratory.io/note/kanaugust/EDA-Salon-crT4VNp7aa)

みなさんのご参加お待ちしております！
libvirt の image 保存ディレクトリの変更

Fedora29 を使っていますが、デフォルトのマウント方法なので、/dev/mapper/fedora-root は / に、/dev/mapper/fedora-home が /home マウントされていて、それぞれ 49G と 1.1T の容量となっています。/var/lib/libvirt は、/ に入っているので、/var/lib/libvirt/images にイメージが増えていくと、あっという間に / の容量が一杯になってしまいます。

特に、preallocation=full などとすると、sparse 化できないため、これはいけません。

そこで、images ディレクトリだけ、/home に作成することにしました。

```
# mkdir /home/<user>/libvirt/images
# ln -sf /home/<user>/libvirt/images /var/lib/libvirt/images
# semanage fcontext -t virt_image_t -a "/home/<user>/libvirt/images"
# restorecon /home/<user>/libvirt/images
```

qemu ユーザーを、<user> グループに追加することも必要だったかな。

```
# usermod -aG <user> qemu
```

```
# chmod 770 /home/<user>
```
MySQL の真偽値型のカラムで手抜きなクエリを書くとインデックスを使ってくれない

（この記事は私の blog の http://umezawa.dyndns.info/wordpress/?p=7323 の転載です）

## 概要

真偽値型（`BIT(1)` とか `BOOLEAN`（`TINYINT` のエイリアス）のこと）のカラムにインデックスを張っても、手抜きな SQL 文を書くとインデックスを使ってくれないようです。

```sql
mysql> CREATE TABLE booltest (
    bit1 BIT(1)           NOT NULL,
    tis  TINYINT          NOT NULL,
    tiu  TINYINT UNSIGNED NOT NULL,
    val  INT              NOT NULL,
    INDEX (bit1),
    INDEX (tis),
    INDEX (tiu)
);
（略）
（ランダムなデータをプログラム的につっこむ）
mysql> EXPLAIN SELECT * FROM BOOLTEST WHERE bit1;
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | booltest | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 998681 |    50.00 | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
mysql> EXPLAIN SELECT * FROM BOOLTEST WHERE bit1 = true;
+----+-------------+----------+------------+------+---------------+------+---------+-------+--------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref   | rows   | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+-------+--------+----------+-------+
|  1 | SIMPLE      | booltest | NULL       | ref  | bit1          | bit1 | 1       | const | 499340 |   100.00 | NULL  |
+----+-------------+----------+------------+------+---------------+------+---------+-------+--------+----------+-------+
```

`bit1 = true` と書かないとインデックスを使ってくれません。`TINYINT` 型にしてある `tis`, `tiu` でも同様です。普通のプログラミング言語なら `bit1` が真偽値型なら `bit1` と書いたのと `bit1 = true` と比較演算したのとは全く同じであるはずですが、SQL (MySQL) ではそういう挙動になってくれないようです。ちなみに `EXPLAIN` を外して実際にクエリしてみた場合、出てくる行は順番も含めて同じです。

まあ、プログラマが勝手に真偽値型だと思ってるだけであって、 `TINYINT` は数値型だし `BIT(1)` は値域が限定されている `BINARY` 型でしかないなので、MySQL はそこまで気を効かせてくれないのかもしれない…

## 環境

- Ubuntu 18.04 TLS
- MySQL 5.7.27
vagrant up時に以前作ったVMが読み込まれない時の対処法（Windows）

8月から新しい職場でweb開発を始めた駆け出しエンジニアです。
支給PC（Windows）で環境構築中、前日に作ったVMが読み込まれず新しく作成されてしまうという事が起こったので、その対処法について書きます。

## 0. 環境

- Windows 10 Home
- Vagrant 2.2.5
- VirtualBox 5.2.20
- 環境変数変更済み
	- 日本語ユーザー名が原因で`Vagrant`コマンドが失敗するので、環境変数`VAGRANT_HOME`を`C:\vagrant_home`として設定しています。
	  - [#05 仮想マシンを立ち上げよう | ローカル開発環境の構築 [Windows編] - プログラミングならドットインストール](https://dotinstall.com/lessons/basic_localdev_win_v2/38605)

## 1. 紐付けされているUUIDを調べる

`.vagrant/machines/default/virtualbox/id`に現在紐付けされている仮想マシンのUUIDが記入されています。
`Vagrantfile`のあるディレクトリで次のコマンドを実行します。

```powershell
PS> cat .vagrant/machines/default/virtualbox/id
xxxxxxx-1111-xxxxx...
```

`xxxxxx-1111....`が現在紐付けされているUUIDです。

## 2. VBoxManage.exeで仮想マシン一覧を確認

まず、環境変数（PATH）に`VBoxManage.exe`のあるディレクトリを追加します。
デフォルトでは（`C:\Program Files\Oracle\VirtualBox`）になると思います。

仮想マシン一覧を表示します。

```powershell
PS> VBoxManage list vms
"ubuntu-1804_default_12341234" {xxxxxx-1111-...}
"ubuntu-1804_default_22222222" {xxxxxx-2222-...}
```

`{xxxxx-1111...}`の部分がUUIDです。  
ここで先ほど調べたUUIDと異なる、以前作成したものがあればUUIDを控えます。
しかし私の場合、現在紐付けされているものしか表示されませんでした。

## (3. 仮想マシンを追加)

`*.vbox`ファイルの置いてあるフォルダを確認します。

`C:\vagrant_home`に昨日作成した、目的の仮想マシン（`ubuntu-1804_*.vbox`）が見つかりました。
VitualBoxのGUIを起動し、「仮想マシン」 >「追加」から該当する`*.vbox`ファイルを追加します。

再度、仮想マシンの一覧を表示します。

```powershell
PS> VBoxManage list vms
"ubuntu-1804_default_12341234" {xxxxxx-1111-...}
"ubuntu-1804_default_99999999" {xxxxxx-xxxx-...}
```

先ほど追加した仮想マシンが表示されているので、UUIDを控えます。

## 4. idファイルを書き換える 

先ほどのファイル（`.vagrant\machines\default\virtualbox\id`）の中身を、控えておいたUUIDで書き換えます。

`vagrant up`で以前の環境が復元できれば成功です。

## 参考

- [Vagrantの仮想マシンとの紐付けの直し方 - ウチのメモ](https://elm-arata.hatenablog.com/entry/2013/09/25/175547)
AWS EC2 コマンド(情報参照/起動/停止)

# 概要

AWS EC2を使用する時によく使うコマンドをまとめる。
個人でEC2を使う際、AWS Consoleを都度開くのがめんどくさいので、それを簡略化する目的のコマンドが主です。
・EC2インスタンスのIPアドレスなどの情報参照
・EC2インスタンスの起動/停止


# 前提条件

・実行端末OS: macOS 10.13.6
・AWSコマンド実行するための準備が整っていること
　→公開鍵の配置など色々あったかと思います。。

# よく使うコマンド

## 情報取得系

### パブリックIPアドレスの一覧を取得

```command
$ aws ec2 describe-instances --query "Reservations[].Instances[].PublicIpAddress"
```

### インスタンスIDを取得

```command
aws ec2 describe-instances --query "Reservations[].Instances[].InstanceId" 
```

出力をスペース区切りで取得(後ほどのインスタンス起動/停止のコマンド実行時に使用すると便利)
先の方法だと一見スペース(タブ?)区切りで出力されたように見えるが、コピー&ペーストするとスペースがなくなる。

```command
aws ec2 describe-instances --query "Reservations[].Instances[].InstanceId" | sed -e s/i/" i"/g    
```

### インスタンス名を取得

```command
$ aws ec2 describe-instances --query "Reservations[].Instances[].Tags[?Key=='Name'].Value"
```

### インスタンス名とパブリックIPアドレスを取得

テキストだと見づらいのでjson形式を指定しています。

```command
aws ec2 describe-instances --query "Reservations[].Instances[].[Tags[?Type=="Name"].Value,PublicIpAddress]" --outpu json
```

### インスタンス名とパブリックIPアドレス/プライベートIPアドレスを取得

```
$ aws ec2 describe-instances --query "Reservations[].Instances[].[Tags[?Type=="Name"].Value,PublicIpAddress,PrivateIpAddress]" --output json
```

## 起動や停止

### 起動

```
$ aws ec2 start-instances --instance-ids (インスタンスidをスペース区切りで)
ex. aws ec2 start-instances --instance-ids i-abcdef0123456789 i-abcdef0123456788
```

### 停止

```
$ aws ec2 stop-instances --instance-ids (インスタンスidをスペース区切りで)
ex. aws ec2 stop-instances --instance-ids i-abcdef0123456789 i-abcdef0123456788
```
Jupyter LabからQiitaへのPythonコード貼り付け

この記事ではJupyter Labで作成したPythonコードをMarkdown形式で出力し、Qiitaへ貼り付ける方法を説明します。やり方は比較的簡単で以下の通り。

1. Jupyter Labに適当なコードを打ち込む
2. File -> Export Notebook As...からMarkdown形式で保存する
3. Qiitaの記事を書くを開きMarkdownモードを選択
4. 先ほど保存したMarkdown(.md)ファイルをテキストエディタ等で開き、中身をコピペする

以下はおなじみHello Worldのテスト

```python
print("Hello World")
```

    Hello World
    
グラフなど画像がある場合にはNotebookがzipファイルとして保存されるので、zipファイルの中の画像を編集画面で挿入する必要があります。


```python
import matplotlib.pyplot as plt
import numpy as np
```


```python
x = np.linspace(0,2*np.pi)
y = np.sin(x)
plt.plot(x,y)
```





![output_4_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480831/43653b7e-11e9-6f2c-f107-1690f382c678.png)
Visual C++で#warningを作った

##コンパイル時に意図的にWarningを出したい

Visual Studioのお話。
C#だと#warningがあって意図的に警告を出せるのですが、C++には無いので作りました。

##実装
```
#define STRING2(x) #x
#define STRING(x) STRING2(x)
#define SetWarning( x ) __pragma( message (__FILE__ "(" STRING(__LINE__) "):warning:" x ) )
```

##使い方
```
SetWarning( "エッッッッッッッッツ" )
```

##コンパイル出力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55069/74fc3357-648a-571f-fe50-37cac6c40043.png)

VS2019以前ではエラー一覧に出て来ませんでしたが、
VS2019では表示されるようになってました。完璧です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55069/0fdc2a62-04a0-13e8-f4ab-60bd9a2b40af.png)
RailsにVueを数行で入れてみる


##### 対象者
RailsにVueを簡単に入れたいひと

##### この記事でやること
コマンドで簡単にRailsにVueを入れる。

##### この記事でやらないこと
Vueをコンポーネントにする	

コンポーネントに関して諸説あり、難しかったので今回はやっていません。
わかりやすくて、よい情報があったら教えてください。

```bash
rails new vue-rails --webpack=vue

rails g scaffold blog title:string body:string

rails db:migrate
```


ページ全体に読み込ませるためこれを追加する

```ruby:app/views/layouts/application.html.erb
  <body>
    <%= yield %>
    <%= javascript_pack_tag 'hello_vue' %>
    <%= stylesheet_pack_tag 'hello_vue' %>
  </body>
```

rails s して
http://localhost:3000/blogs
を確認。

scaffoldを使わずに、手でindexを作ってもいいと思います。
簡単にVueを入れて雰囲気を味わうためこうしました。

これを改造しながらなれていってステップアップすればいいと思います。
筆者もこの辺でさまよっていますので、わかりやすくてよい記事があったらコメント欄で教えてほしいです。

[30歳からのプログラミング
Webpacker の基本的な仕組み]
(https://numb86-tech.hatenablog.com/entry/2019/01/09/215714)


[rails/webpacker]
(https://github.com/rails/webpacker#vue)
Azure Table Storageにログを出力するハンドラー

Azure WebAppsでPythonアプリを動かした時のログ出力の仕方がどんなに調べても分からなかったので諦めてAzure Table Storageに出力するハンドラーを作りました。

Github https://github.com/uezo/azure-table-storage-logging

`logging.Handler`の拡張クラスなので従来のハンドラーと同じ手続きかつ併用できるのと、WebAppsに限らずあらゆるPythonアプリケーションで使えます。

# インストール

```bash
$ pip install azure-table-logging
```

# 使い方

```python:yourapp.py
import logging
from azuretablelogging import AzureTableStorageHandler

# ロガーの取得
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# ハンドラーの生成。Azure Storageのアカウント名とキー、ログを記録するテーブル名を指定
handler = AzureTableStorageHandler(
    account_name="your_account_name",
    account_key="your_account_key",
    table_name="table_name"
)

# 生成したハンドラーをロガーに追加
logger.addHandler(handler)

# あとはいつも通りログ出力
logger.debug("デバッグ")
logger.info("情報レベル")
logger.warn("警告レベル")
logger.error("エラーレベル")
logger.critical("致命的レベル")
```

実行すると、`table_name`に指定したテーブルに5レコード追加されます。

PartitionKey|RowKey|Timestamp|LocalTimestamp|LevelName|Level|Message
---|---|---|---|---|---|---
main|251837309460.3795|2019-08-05T07:49:01.574Z|"2019-08-05 16:48:59,220"|CRITICAL|50|致命的レベル
main|251837309460.44092|2019-08-05T07:49:01.504Z|"2019-08-05 16:48:45,687"|ERROR|40|エラーレベル
main|251837309460.51297|2019-08-05T07:49:01.444Z|"2019-08-05 16:48:43,586"|WARNING|30|警告レベル
main|251837309460.77405|2019-08-05T07:49:01.374Z|"2019-08-05 16:48:21,398"|INFO|20|情報レベル
main|251837309498.6117|2019-08-05T07:48:47.676Z|"2019-08-05 16:48:05,928"|DEBUG|10|デバッグ

# 出力項目

カラム名|loggingとの対応|説明
---|---|---
PartitionKey|%(name)s|ロガーの名前
RowKey|n/a|ソートキー。新しいものほど値が小さい。9999年12月31日のEpochからAzure Storageに書き込む直前のEpochを引いたもの
Timestamp|n/a|Azure Storageに書き込まれた時間
LocalTimestamp|%(asctime)s|アプリケーションでログを出力した時点の時間
LevelName|%(levelname)s|ログ出力レベル
Level|%(level)s|ログ出力レベルの数値表現
Message|formatterで指定した値|ログメッセージ。Formatterでフォーマット可能


# その他のポイント

- Azureへの書き込みは別スレッドで処理しており、アプリケーションのパフォーマンスにはほとんど影響を与えません。
- 書き込みはハンドラーインスタンス毎に単一スレッドで行われるため、書き込み順序は保証されます。
- 大量のログを出力した際のパフォーマンスや問題は検証できていません。
- 指定したテーブル名が存在しないときは新規作成します。
Who should assemble product? // BuilderPattern

{builder, product}@BuilderPatternは，every single Command@CommandPatternのembodiment．
product@BuilderPatternにassignされたclassがassembleのような処理を必要とする場合，定石通りにbuilderにassembleを実装すべきか?

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235834/d5b161c7-41ea-cfe4-bb37-15491b7568a4.png)
Dockerコンテナを非rootユーザで実行する

### rootユーザの問題

- Dockerコンテナを実行するとrootユーザで実行される
- ファイルを生成するコンテナを実行するとowner:groupがrootになる
    - -uオプションで回避できる場合もある
- 一般ユーザでは生成されたファイルにアクセス権がない
- ホスト側でマウントしたときなどに一般ユーザでなにかと困る

---

### 一般ユーザで実行してほしいもの例

- ファイルを作成するコマンド
- Jupyter
- サイト/ドキュメントビルダ
    - pandoc
    - sphinx
    - etc

---

### コンテナを実行してファイルを作成した例

```console
$ docker run --rm -v /tmp:/tmp debian:stable-slim touch /tmp/a.txt
$ ls -n /tmp/a.txt 
-rw-r--r-- 1 0 0 0  8月 10 16:35 /tmp/a.txt
```

一般ユーザからはファイルの書き込みができなくなる

---

### run-non-root

Run Linux commands as a non-root user, creating a non-root user if necessary.

https://github.com/creemama/run-non-root

---

#### run-non-rootの機能

- コンテナが一般ユーザで実行できる
    - 実行時にユーザが作成される
    - Dockerfileでハードコートする必要がない
- UID:GIDが指定できる
- USERNAME:GROUPNAMEが指定できる

---

#### run-non-rootの実行例

```console
$ docker run --rm -v /tmp:/tmp creemama/run-non-root:latest -- touch /tmp/a.txt

Running ( exec su-exec nonroot:1000 touch /tmp/a.txt ) as uid=1000(nonroot) gid=1000(nonroot) groups=1000(nonroot) ...

$ ls -n /tmp/a.txt 
-rw-r--r-- 1 1000 1000 0  8月 10 16:36 /tmp/a.txt
```

デフォルトではUID:GID=1000:1000で実行される

---

#### オプションでUID:GIDを指定

```console
$ docker run --rm -v /tmp:/tmp creemama/run-non-root:latest -u 1001 -g 999 -- touch /tmp/a.txt

Running ( exec su-exec nonroot:999 touch /tmp/a.txt ) as uid=1001(nonroot) gid=999(ping) groups=999(ping) ...

$ ls -n /tmp/a.txt 
-rw-r--r-- 1 1001 999 0  8月 10 16:36 /tmp/a.txt
```

---

#### 環境変数でUID:GIDを指定

```console
$ docker run --rm -v /tmp:/tmp -e RUN_NON_ROOT_GID=1001 -e RUN_NON_ROOT_UID=999 creemama/run-non-root:latest -- touch /tmp/a.txt

Running ( exec su-exec nonroot:1001 touch /tmp/a.txt ) as uid=999(nonroot) gid=1001(nonroot) groups=1001(nonroot) ...

$ ls -n /tmp/a.txt 
-rw-r--r-- 1 999 1001 0  8月 10 16:37 /tmp/a.txt
```

---

#### run-non-rootのなかみ

- su-exec
- tini
- run-non-root.sh

---

#### [su-exec](https://github.com/ncopa/su-exec)

- 指定したユーザ権限でプログラムを実行
- su, sudoが予測不可能なTTY、シグナル送信の問題を回避
- gosuより軽い

---

#### [tini](https://github.com/krallin/tini)

- PID=1のプロセスがゾンビになることを回避
- SIGTERMが正しく処理される
- dockerの--initオプションで代用可？

---

#### run-non-root.sh

- 一般ユーザでコンテナを実行するシェルスクリプト
- 実行時にユーザを作成する
    - Dockerfileへのハードコート不要
- 任意のユーザが扱える

---

### つくったもの

https://hub.docker.com/r/driller/jupyter

- run-non-rootを使ったJupyterを実行するDockerイメージ
- 一般ユーザでJupyter Notebook/JupyterLabを実行

---

#### Jupyter Notebookの起動例

```console
docker run --rm -v <path_to_work_dir>:/notebooks -p 8888:8888 -e RUN_NON_ROOT_UID=$(id -u) -e RUN_NON_ROOT_GID=$(id -g) driller/jupyter jupyter notebook --no-browser --ip="0.0.0.0"
```

`<path_to_work_dir>` にはマウントするPathを指定

---

#### Jupyter Labの起動例

```console
docker run --rm -v <path_to_work_dir>:/notebooks -p 8888:8888 -e RUN_NON_ROOT_UID=$(id -u) -e RUN_NON_ROOT_GID=$(id -g) driller/jupyter jupyter notebook --no-browser --ip="0.0.0.0"
```

`<path_to_work_dir>` にはマウントするPathを指定
# AtCoder Regular Contest 022 C - ロミオとジュリエット(double sweep)

# AtCoder Regular Contest 022 C - ロミオとジュリエット(double sweep)

https://arc022.contest.atcoder.jp/tasks/arc022_3

ポイント：木構造の中で最も距離が遠い二点を求める方法
ある点から最も距離が遠い点を求め、その点から最も遠い点を求める。
この2つがグラフの中で最も遠い二点となる。



```python
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
from copy import deepcopy
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from operator import mul
from functools import reduce


sys.setrecursionlimit(2147483647)
INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.buffer.readline().split()))
def I(): return int(sys.stdin.buffer.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
mod = 1000000007


n = I()
G = [[] for _ in range(n)]
for a, b in LIR(n - 1):
    G[a - 1] += [b - 1]
    G[b - 1] += [a - 1]


def bfs(G, s=0):
    que = deque([s])
    # n = len(G)
    dist = [INF] * n
    dist[s] = 0
    while que:
        u = que.popleft()
        for v in G[u]:
            if dist[u] + 1 < dist[v]:
                dist[v] = dist[u] + 1
                que += [v]
    return dist


def double_sweep(G):
    dist = bfs(G, s=0)
    # n = len(G)
    ret = -1
    for u in range(n):
        if dist[u] > ret:
            ret = dist[u]
            v = u
    dist = bfs(G, s=v)
 # 直径の長さだけを知りたい時は、return max(dist)
    ret = -1
    for i in range(n):
        if dist[i] > ret:
            ret = dist[i]
            w = i
    return v + 1, w + 1


print(*double_sweep(G))


```
【salesforce】トリガー概要と汎用化

#1.トリガー概要
![trigger概要.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480807/69fd64b1-d6c7-c145-cda0-98515e114315.jpeg)

#2.一般的な実装例
```java:EmployeeTrigger.apxc
trigger EmployeeTrigger on Employee__c (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    if (Trigger.isInsert) {
        if (Trigger.isBefore) {
            // Before Insert 処理
        } else if (Trigger.isAfter) {
            // After Insert 処理
    }
    ．．．（略）
}
```

#3.問題分析
- トリガはシステム権限で実行するため、レコード共有権限は無視される
- メソッド単位でテストできないため、テストクラスの作成には不便利
- ロジックは共有できない

#4.Trigger構成図
![汎用化.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480807/24c033ca-609b-bbbc-390c-447d0afa6055.jpeg)

#5.TriggerHandler
```java:TriggerHandler.apxc
public abstract class TriggerHandler {
    public void execute() {
        switch on Trigger.operationType {
            when BEFORE_INSERT  { this.beforeInsert(Trigger.new); }
            when BEFORE_UPDATE  { this.beforeUpdate(Trigger.oldMap, Trigger.newMap); }
            when BEFORE_DELETE  { this.beforeDelete(Trigger.oldMap); }
            when AFTER_INSERT   { this.afterInsert(Trigger.newMap); }
            when AFTER_UPDATE   { this.afterUpdate(Trigger.oldMap, Trigger.newMap); }
            when AFTER_DELETE   { this.afterDelete(Trigger.oldMap); }
            when AFTER_UNDELETE { this.afterUndelete(Trigger.newMap); }
        }
    }

    protected virtual void beforeInsert(List<Sobject> newList) {}
    protected virtual void beforeUpdate(Map<Id, Sobject> oldMap, Map<Id, Sobject> newMap) {}
    protected virtual void beforeDelete(Map<Id, Sobject> oldMap) {}
    protected virtual void afterInsert(Map<Id, Sobject> newMap) {}
    protected virtual void afterUpdate(Map<Id, Sobject> oldMap, Map<Id, Sobject> newMap) {}
    protected virtual void afterDelete(Map<Id, Sobject> oldMap) {}
    protected virtual void afterUndelete(Map<Id, Sobject> newMap) {}

    @TestVisible protected Boolean isFieldValueChanged(SObject oldObject, SObject newObject, SObjectField field) {
        Object oldValue = getFieldValue(oldObject, field);
        Object newValue = getFieldValue(newObject, field);
        return oldValue != newValue;
    }

    @TestVisible protected Object getFieldValue(SObject obj, SObjectField field) {
        Object fieldValue = (obj != null) && (field != null) ? obj.get(field) : null;
        return fieldValue;
    }
}
```

#6.実装例
```java:TriggerHandler.apxc
trigger EmployeeTrigger on Employee__c (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    new EmployeeTriggerHandler().execute();
}
```

```java:amployeeTriggerHandler.apxc
public with sharing class EmployeeTriggerHandler extends TriggerHandler {
    public override void afterInsert(Map<Id, SObject> newMap) {
        // 業務処理
    }
    public override void afterUpdate(Map<Id, SObject> oldMap, Map<Id, SObject> newMap){
        // 業務処理
    }
}
```

#汎用化の記事元
[Apex Trigger Lightweight Framework](https://qiita.com/xuwenzhen/items/38b6b642ea64b86e949a)
pythonでツイートidからTwitterの詳細情報を集計しよう

##これまでのあらすじ
以前TweetIDを爆速でスクレイピングしてくる方法をまとめました。TweetIDとは各投稿についているユニークの値です。

今回はそれをもとに投稿テキストやいいね数、リツイート数やメディア数などを集計します。
現在取得してあるツイートIDはテキストファイルに保存されています。

https://qiita.com/Tokyo/items/de206d3e3a6a1997f257



##取得するデータ一覧
- 投稿テキストと文字数
- 投稿時間(ツイートが投稿された年月日と時間）
- いいね数/リツイート数
- 投稿に添付されたメディア(写真や動画)の数
- 投稿したアカウント(リツイートを除外するために）

因みに投稿時間は、ツイートIDから計算で求めることができます。
以前それについての記事も書いたので、分からない方は見てください。

https://qiita.com/Tokyo/items/41b5d0925de5eacfee67

##実際のスクリプト

```scrape.py
from bs4 import BeautifulSoup
from time import sleep 
import requests
from datetime import datetime
import pandas as pd
from tqdm import tqdm

#投稿IDから投稿日時を計算する関数
def caluculation(_id):
     unix_time = ((int(_id) >> 22) + 1288834974657) / 1000.0
     date_time = datetime.fromtimestamp(unix_time)
     return date_time

_id_list = []
text_list = []
date_list = []
favo_list = []
retweet_list = []
text_num_list = []
media_num_list = []

#ツイートIDが書いているファイルを開く、またtqdmを使って所要時間を確認したかったので、一旦別のリストに入れた。
with open ('otnk23_id.txt','r',encoding='utf-8') as f:
    for _id in f:
        moment_list.append(_id)

for _id in tqdm(moment_list):

    #投稿URLを作成
    url = 'https://twitter.com/otnk23/status/'+_id
    #投稿URLの末尾の改行文字(\n)を削除
    url = url[:53]
    #スクレイピングをする
    source = requests.get(url)     
    soup = BeautifulSoup(source.text,'lxml')     

    try:         
        account = soup.select_one('.u-linkComplex-target ').text     
    except Exception:         
        account = None              
    try:         
        likes = soup.select_one('.request-favorited-popup > strong').text     
    except Exception:         
        likes = 0  
    try:         
        retweets = soup.select_one('.request-retweeted-popup > strong').text     
    except Exception :          
        retweets = 0     
    try:         
        text = soup.select_one('.TweetTextSize').text     
    except Exception:         
        text = None     
    date = caluculation(_id)     
    try:         
        media = len(soup.select('.AdaptiveMedia-photoContainer'))     
    except Exception:         
        media = 0

#投稿したアカウントが自分だったら、(リツイートじゃなかったら）投稿に関する情報を追加する
    if account == 'otnk23':         
         text_list += [text]          
         date_list += [date]
         favo_list += [likes]
         retweet_list += [retweets]
         text_num_list += [len(text)]         
         media_num_list += [media]
         _id_list += [_id]

#Pandasのデータフレームを作ってデータを保存する
df = pd.DataFrame(
         data={'_id':_id_list,'text': text_list, 'date':date_list , 'likes': favo_list, 'retweets': retweet_list, 　　　　　'text_num': text_num_list,'media':media_num_list},
         columns=['_id','text', 'date', 'likes', 'retweets', 'text_num','media']
     ) 
#csvに保存する。
df.to_csv('otnk23.csv',index=False)

```

これでほしかった情報が集まりました。

##描画
次回このデータを分析して、データの描画をおこなっていきます。

https://qiita.com/Tokyo/items/42e9d1fea7d7e0cc6d26
gem'devise'に頼りすぎていて、sessionとcookieの概念が疎かだったので、まとめる

#はじめに
細かい事を気にしなくても、user機能一式導入できるdeviseに頼りすぎていましたが、仕組みがわからないのはまずいと思い、sessionとcookieとの違いを中心にログインとログアウトなどの仕組みを調べてまとめた備忘録。
＊プログラミングを初めて３ヶ月の初学者なので、間違いがあるかも知れません。何かありましたらコメントで教えていただけると幸いです。

#sessionとcookie
###session
以下引用です。https://it-trend.jp/words/session
>
コンピュータネットワークでは、接続を確立してから切断するまでの一連の通信のこと。HTTPのサイトでは、セッションにIDを振ることで同一のセッションを管理することができる。また、一連のインタラクティブな操作(例えばログインしてからログアウトするまで)を指す場合もある。

HTTPリクエストはステートレスなプロトコルの為、何かしらでユーザーを区別しないと一連の動作が断片的な物になってしまい不便です。折角ログインしても、マイページに行こうとしたら、ログインした人とマイページに行こうとしている人が同じ人物かサーバー側で判断出来ない為マイページに行けなくなってしまうみたいな感じです。
それを解決するのがsessionです。この仕組みによりユーザーに対してユニークな値を付与する事でユーザーの判別を可能にしています。
ログインのロジックはこれを使って実装されています

```ruby
session[:user_id] = user.id
```
このようにRailsではsessionと言うメソッドにuseridを持たせる事でログイン状態に、useridをdeleteする事で、ログアウト状態を作っています
＊deviseでは複雑な形で導入されていて、私の実力では理解が及びませんでした。

#cookie
ログインしたサイトを一度離れてまた閲覧してもログインしなくても出来るのはcookieが使われています。
cookieはPC側に保存され、該当のページへリクエストを送った時、一緒に送られて処理を行なっています。
deviseの初期画面のRemember meのチェックボックスがcookieを有効にするかを決めているみたいですね。

#まとめ
自分的に理解は深まったが言語化が難しく、なんとも言えないまとめになってしまいました。
ログイン機能を一から作ったり、deviseを大々的に弄る様な機会がなかったのでおざなりになっていましたが、仕組みの大枠は理解できたかなと思います。

#参照
「わかった」気になれるサイト。とりあえずわからない単語はここで一回調べると小難しい説明も入りやすくなるのでオススメです
https://wa3.i-3-i.info/word1791.html

https://time-space.kddi.com/ict-keywords/20180726/2392
レビューの心得

# 概要

ソフトウェアの開発における「レビュー」の効果を最大化するために、依頼者・レビュアーの双方が頭に入れておきたい事柄を簡単にまとめました。

# レビューとは

* レビューの目的
  1. 誤りの検出　→レビュアーの注意力・知識を借りる
  2. トレードオフに対する妥協点の決定　→レビュアーの知識・判断力を借りる
  3. 情報共有　→レビュアーに内容を知ってもらう
  4. 工程上の手続き　→正式なものとして承認する

* レビューは依頼者とレビュアーの共同作業
(少なくともレビューの場においては) 両者の立場は対等であり、互いに敬意を払いつつも遠慮はないようにし、レビューの効果を最大にすることを考える。

* レビューの主体は依頼者
依頼者が自身の仕事の完成度を高めるためにレビューという道具を「利用」する。

# レビュアーの心得

* 不可解だと思う箇所があった時にはすぐ誤りだと判断ぜず、なぜそうしたのかを依頼者に聞いてみる。
レビュー対象については依頼者の方がよく知っている。

* 修正方法を押し付けしない。
修正案として提示だけして、実際どのように修正するかは依頼者の裁量とする。

* 指摘したことが意図どおりに理解されているか確かめる。
誤った理解によって依頼者の作業時間を無駄にしないようにする。

# 依頼者の心得

* レビューの場で本質ではないことに時間を消費することがないよう努める。
文章の不備、ルールの違反、タイプミスなどがないか見なおす。

* 理由があって素直ではない方法をとった場合は、あらかじめそのことをレビュアーに伝える。
レビュアーの思考時間を無駄づかいしないようにする。

* 指摘をうのみにしない。
レビュアーはレビュー対象についてすべて理解している訳ではないので、誤った指摘をするかもしれない。

# 最後に

レビューはともするとやらされ感から形骸化したり、受けた指摘や返される反論でムッとすることがあったりしがちですが、依頼者とレビュアーが同じ目的・考え方を持って行うことで、効果的かつ気持ちよく進められたら良いなあと思います。

おわり。
googleタグマネージャーでCVを管理する

# googleタグマネージャーとは

googleanalyやadwordsのタグを一括管理するもの。開発をしなくてもタグの追加がしやすいようになっている。特別なイベントは実装必要だがform全体などは設定のみでできるようになる。

# 用語

* データレイヤー・・・googleanalyなど違うサービスに値を渡す
* コンテナ・・・タグを発行するコード。全ページに設置する必要がある。
* ワークスペース・・・タグの設定をする場所。バージョンで管理できるので戻すのもしやすい。
* 変数・・・Google タグ マネージャーの変数とは、ウェブサイトやモバイルアプリでコードが実行する際に入力される値の、名前付きプレースホルダです。

# 新規登録をCVとしてGAで測定できるようにする

https://support.google.com/tagmanager/answer/6106716

# 設定変更

googleタグマネージャーは複数人が作業することを前提に作られているのでワークスペースで変更を行って公開をしなければ反映されない。
AWS 認定 SysOps Administrator – Associate 関連の日本語ホワイトペーパー

# はじめに
AWS 認定 SysOps Administrator – Associate 関連の日本語ホワイトペーパーを探すのに手間取ったのでメモとして残しておきます。

なお、空欄のものについては日本語版を見つけられなかったので、知ってる人いたらコメントで教えていただけると非常に嬉しいです！！

# 日本語ホワイトペーパー

|No.|White Paper|日本語|
|:-:|:-:|:-:|
|1|[Architecting for the Cloud AWS Best Practices<br/>(October 2018)](https://d1.awsstatic.com/whitepapers/AWS_Cloud_Best_Practices.pdf)||
|2|[AWS Security Best Practices<br/>(August 2016)](https://d0.awsstatic.com/whitepapers/Security/AWS_Security_Best_Practices.pdf?refid=em_)|[AWS セキュリティのベスト プラクティス<br/>(2016年8月, 110ページ)](https://d1.awsstatic.com/whitepapers/ja_JP/Security/AWS_Security_Best_Practices.pdf)|
|3|[Overview of Security Processes<br/>(May 2017)](http://d0.awsstatic.com/whitepapers/Security/AWS%20Security%20Whitepaper.pdf)|[セキュリティプロセスの概要<br/>(2014年11月)](https://d1.awsstatic.com/whitepapers/International/jp/AWS_Security_Whitepaper.pdf)|
|4|[AWS Well-Architected Framework<br/>(July 2019)](https://d0.awsstatic.com/whitepapers/architecture/AWS_Well-Architected_Framework.pdf)|[AWS Well-Architected フレームワーク<br/>(2018年6月)](https://d1.awsstatic.com/International/ja_JP/Whitepapers/AWS_Well-Architected_Framework_2018_JA_final.pdf)|
|5|[Development and Test on Amazon Web Services<br/>(November 2012)](https://media.amazonwebservices.com/AWS_Development_Test_Environments.pdf)||
|6|[Backup, Archive, and Restore Approaches Using AWS<br/>(November 2014)](https://d0.awsstatic.com/whitepapers/Backup_Archive_and_Restore_Approaches_Using_AWS.pdf)|[AWS を使用したバックアップと復元の手法<br/>(2016年6月)](https://d1.awsstatic.com/whitepapers/jp/Backup%20and%20recovery%20approaches%20using%20AWS.pdf)|
|7|[Amazon Virtual Private Cloud Connectivity Options<br/>(July 2014)](https://media.amazonwebservices.com/AWS_Amazon_VPC_Connectivity_Options.pdf)||
|8|[How AWS Pricing Works<br/>(June 2018)](http://d0.awsstatic.com/whitepapers/aws_pricing_overview.pdf)|[AWS 料金表の仕組み<br/>(2018年2月)](https://d1.awsstatic.com/International/ja_JP/Whitepapers/aws_pricing_overview_JP.pdf)|
触媒分野の論文について、機械学習の活用具合をざっくり調べてみた

##はじめに
世間で賑わっている機械学習(ブームは過ぎたかもしれませんが)は、化学特に触媒分野でどの程度活用されているのでしょうか。
また、ヒットのタイミングや参考になりそうな文献がわかれば良いなと思い調べました。
(正確な件数を調べるためではない)

##検索方法
アメリカ化学協会(ACS)の文献で、機械学習と触媒に関連する論文のヒット数を調べてみました。
"Materials informatics"、"Chemo informatics"、"Catalyst informatics"など色々な単語があり、正確な値を出すのが大変なので、ざっくり"Machine Learning"と"Catalyst"が含まれている文献を探しました(船津先生、金子先生など有名な方の文献が含まれていないので、要注意です)。

検索ワード："Machine Learning"、Catalyst"
検索日：2019/8/10
検索期間：2010〜2019年
(個人ではACSを契約していないので、中身の詳細は見られません。関連度は参考程度です)

##検索結果
検索結果のURLがこちらです。
https://pubs.acs.org/action/doSearch?field1=AllField&text1=%22machine+learning%22&field2=AllField&text2=%22catalyst%22&field3=AllField&text3=&publication=&accessType=allContent&Earliest=&AfterMonth=&AfterYear=2010&BeforeMonth=&BeforeYear=2019&startPage=

2010年〜2019年までの間に266件発表されているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/b7a69bae-93da-5f9e-6276-c584faba0cd8.png)

年別の発表数を可視化してみました。
![_Machine Leaning_&_Catalyst_(〜2019_8_10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/1c58f02e-f05d-a379-a7c9-f7277690b913.png)
2016年を境に急激に発表数が増えています。
2019年は8月までの件数なので、150本近く発表されて過去最高を大きく更新しそうな勢いです。

どんな文献でヒットするかというと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/b51d00fb-abb6-2f47-f198-c5871eca65f0.png)
1位：C&EN Global Enterprise(IF=3.092)
2位：Chemical Review(IF=52.613)
・
・
・
といった並びです。

C&ENは、HPに下記の説明があります。論文というより、ニュース、記事って感じですね。
"Chemical & Engineering News (C&EN) is an award-winning go-to news source for members of the worldwide chemistry community in academia, industry, and beyond. "

他のジャーナルには研究内容が報告されており、JACS(IF=14.695)も15件程度あります。
他の単語で検索すると、
・Industrial & Engineering Chemistry Research
・Journal of Chemical Information and Modeling
といった文献もありました。

##検索漏れは、ものすごくありそう
上述の通りです。今回は、活用具合や参考文献がわかればよかったので。。。
まずは、参考になりそうな文献(のアブストだけ)を読んで推測します。
個別の文献は、お金払って取り寄せてみますかね。。。

##終わりに
・"Machine Learning"と"Catalyst"のキーワードで論文数を調べてみると、2016年くらいから急激に増えているようです。"Material informatics"で調べた方が件数が遥かに多いので、手法自体はこちらの結果を参照しようかと思います。まだ、バブルが終わってないといいな。

・2015年以前も一定数の発表はあります。High throughput screeningやコンビケムなど、網羅的なスクリーニングは昔から行われていたり、2000年代にニューラルネットワークや遺伝的アルゴリズムを試してみたという文献もみた覚えがあります。

・機械学習の手法自体を検討している最先端の文献は、今回の検索ワードで引っかかりにくいです。個別の単語で調べようかと思います。
ポインタの使い方

成功例

```c
    #include <iostream>
    using namespace std;
     
    int swap(int* a, int* b){
        int tmp;
        tmp=*a;
        *a=*b;
        *b=tmp;
        return 0;
    }
    
    int main(){
        int A,B;
        cin >> A >> B ;
        swap(&A,&B);
        cout << A << " " << B;
        return 0;
    }
    //出力結果　(A,B)→(B,A)
```
　　

失敗例

```c
    #include <iostream>
    using namespace std;

    int swap(int a, int b){
        int tmp;
        tmp=a;
        a=b;
        b=tmp;
        return 0;
    }
    
    int main(){
        int A,B;
        cin >> A >> B ;
        swap(A,B);
        cout << A << " " << B;
        return 0;
    }
    //出力結果(A,B)→(A,B)
```

Q1　なぜポインタを使わない例では入れ替えることが出来なかったのか？

Answer
swap(A,B)の際にswap関数によって入れ替える動作は成功したものの、swap関数の引数a,bはswap関数内でのローカル変数名であるため、外部の関数に影響を及ぼすことができない。
つまり、(A,B)を(B,A)にした結果をmain関数内に呼び戻すことができないため失敗。

Q2　なぜポインタを使う例では入れ替えることが出来たのか？

Answer
swap関数で宣言したa,bもmain関数で宣言したA,Bも同じメモリ空間上に位置している。そのためアドレスを指示すれば、何も問題は起きず、異なる関数内での連携もとれるため成功。
Vue.js ラジオボタンの選択状態でボタンを押せる・押せないを実装したいとき

単純なradioボタンではなく、radioと連動して、buttonを活性・非活性にしたいときは、こうやると期待どおりに動きました。

公式のようにvalueをそのままやるとdata内でうまく値が連携されないようです。
:value（v-bind:value）でやるとうまくいきました。

```vuejs

<input type="radio" v-model="picked" :value="true">hoge
<input type="radio" v-model="picked" :value="false">fuga

<button :disabled="!picked">HOGE</button>
<button :disabled="picked">FUGA</button>

```

[Vue.js
フォーム入力バインディング]
(https://jp.vuejs.org/v2/guide/forms.html#%E3%83%A9%E3%82%B8%E3%82%AA)
.each文について（初投稿）

初めて投稿します
プログラミング初心者です
プログラミングスクールでrubyを勉強しています

これから知った知識を投稿していきたいと思ってます

ということで、この間rubyでタイトルにある通り　　　

　　.each

文について学習したので、

　・　どんなメソッドなのか
　・　気をつけること

を書きたいと思います

多分超基礎知識だと思いますので、これからrubyを勉強しようとしている人向けに説明していこうかと思います


・　どんなメソッドなのか　
　１　配列の要素分繰り返す
　２　範囲オブジェクトを指定してその分繰り返し処理を実行する
　３　ハッシュの要素分繰り返す

　※　今回は上記１のみ説明します（まだこれしか勉強してないので・・・）
　　 ２、３について知りたい方、もしくはもっと詳しく知りたい方は

　　https://www.sejuku.net/blog/55970

　をご覧ください
　　

　書き方の例
　
　　オブジェクト（配列など）.each do |変数|
　　　処理
　　end

　意味は、
　
　　①オブジェクト内の情報を一つずつ取り出す→②処理を実行→再度オブジェクト内の情報を取り出す→③処理を実行・・・（①、②を繰り返す）④オブジェクト内の情報がなくなり次第処理終了

となります。

・　気をつけること
　each ~ do　の中で定義した変数はメソッド外ではスコープの範囲外である
　ということです（わかりにくい表現すみません、まだうまく言葉にできないです）

　良い例
　books = ["Dragon Ball", "One Piece"]
 
　　books.each do |book|
   　　title = book
   　　puts title 
　
　end

  実行結果

　　Dragon Ball
　　One Piece

　悪い例（スコープの範囲外）

　books = ["Dragon Ball", "One Piece"]
 
　　books.each do |book|
 　　 title = book
　
　　end
　puts title 
　　

　実行結果
　　undefined local variable or method `title' for main:Object (NameError)　　

　エラー文が出力されます

 意味は簡単に言うと「`title'てなんですか！？」という意味になります

　良い例、悪い例を見比べると、"puts title"が.each ~ do文の中にあるか外にあるかの違いがわかりますよね

　つまり、.eachメソッドの中で定義された変数は、メソッドの外ではスコープの範囲外（認識されない）となるのです

　ちなみに、.eachメソッドの外に"puts title"で内容を表示したい場合は

　.eachメソッドの外に.eachメソッド内で定義する変数を作っておけば認識されますので

　books = ["Dragon Ball", "One Piece"]
　title = []
 
  　　books.each do |book|
    　　title << book
    
  　 end
　 puts title

とやるとちゃんと表示されます
（あくまで例なので、そのままputs booksでいいじゃん！というつっこみは置いときましょう）


説明は以上になります

長々とここまで読んでくれた方ありがとうございました

つたない説明だったかもしれませんが、何かの役に立てば幸いです

今後も何か紹介したい内容や、自分自身のアウトプット&備忘録として利用させていただきます
pythonのソート

```python:python
>>> import random
>>> list = [i for i in range(1,10+1)]
>>> list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# リストの組み込みメソッド（リストをインプレースに変更する）
>>> random.shuffle(list)
>>> list
[8, 7, 10, 4, 2, 5, 9, 3, 6, 1]
>>> list.sort()
>>> list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 組み込み関数
>>> random.shuffle(list)
>>> list
[1, 3, 10, 5, 4, 6, 2, 7, 9, 8]
>>> sorted(list)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```
パスに半角スペースが入っていてエラーが発生するときの対処法（Windows）

## きっかけ
Windowsの`User`直下には`Program Files`など半角スペースが入った名前のファイルがある（たぶんデフォルトでそう）

これまではそれが問題にならなかったが、Dockerをインストールして`docker build`→`docker run`しようとしたら

```
invalid reference format: repository name must be lowercase.
```
というエラーが発生したので、そのときの対処法をまとめた

おそらく他の状況でも、**Windows OS**であれば以下の方法で対処できるはず


## 対処その１（コマンドプロンプトside）
1. コマンドプロンプトを起動し、問題の（半角スペースが名前に含まれている）ファイルの1コ上の階層に移動

1. `dir /x`を実行して、8.3形式のファイル名を表示
8.3形式とは、ベース部分が最大8文字、拡張子が最大3文字で構成されるファイル名のことで、元のファイル名と同様に扱える

```
C:\> dir /x
2016/11/29  11:50    <DIR>                       Fujitsu
2016/11/29  11:34    <DIR>                       Intel
2006/12/01  23:37           904,704              msdia80.dll
2018/08/18  21:49    <DIR>          MYCLOU~1     My Cloud Public
2018/04/12  08:38    <DIR>                       PerfLogs
2019/08/09  10:25    <DIR>          PROGRA~1     Program Files
2019/08/06  21:25    <DIR>          PROGRA~2     Program Files (x86)
2018/06/10  11:03    <DIR>                       Users
2019/07/30  13:19    <DIR>                       Windows
```

　　　　　　　　　　　　　　　　　　　↑これが8.3形式のファイル名

## 対処その２（エラーが出たシェルside）
1. 問題の（半角スペースが名前に含まれている）ディレクトリの1コ上の階層に移動
 
1. 8.3形式のディレクトリ名（今回の場合は`PROGRA~1`）を指定して元いたディレクトリまで戻る
1. エラーが出たコマンドを実行し、ちゃんと実行されることを確認
[Unity Addressable Asset System] AssetReferenceLabelRestriction が無い問題と AssetReferenceUILabelRestriction のビルドに失敗する問題

## 問題

https://www.youtube.com/watch?v=Rls8e7tZUNE&t=33s
というありがたい動画にある AssetReferenceLabelRestriction を使ったが、そんなものはないと怒られた。

## 調査

https://docs.unity3d.com/Packages/com.unity.addressables@0.6/changelog/CHANGELOG.html
にある、

> Attribute AssetReferenceLabelRestriction is renamed to AssetReferenceUILabelRestriction and must be surrounded by #if UNITY_EDITOR in your game code, to enforce it's editor-only capability

が見つかった。

Google 翻訳にかけると、

> 属性AssetReferenceLabelRestrictionはAssetReferenceUILabelRestrictionに名前が変更され、ゲームコードで#if UNITY_EDITORで囲む必要があります。これは、エディターのみの機能を強制するためです。

## 解決法

つまりはこう使えということ。

```cs
#if UNITY_EDITOR
using UnityEditor.AddressableAssets.GUI;
#endif
```

```cs
#if UNITY_EDITOR
    [AssetReferenceUILabelRestriction("Map")]
#endif
    public AssetReference reference = null;
```

なんか……スマートじゃない。
phpの配列同士の重複をチェックする

なかなかググり力不足で一発でぐぐれないのでこちらに書きます。

「php 配列 重複 チェック」で検索したときに出やすいです。

このケースでは、関数を使わないとこんな感じでforeachを使うことになると思います。

```php:example1
$array1 = [1 ,2 ,3];

$array2 = [2, 4];

$result = []:
foreach ($array1 as $a1) {
	foreach ($array2 as $a2) {
		if ($a1 === $a2) {
			$result[] = $a;
		}
	}
}

var_dump($result);
```

「array_intersect」を使うとスッキリ書けます。

```php:example2
$array1 = [1 ,2 ,3];

$array2 = [2, 4];

var_dump(array_intersect($array1, $array2));

array(1) {
  [1]=>
  int(2)
}
```

この関数と逆の結果になるものとしてarray_diffがあります。
こちらは、重複していない、異なるものをチェックして配列で返してくれます。
どちらも便利でよいです。

[php.net
array_intersect]
(https://www.php.net/manual/ja/function.array-intersect.php)

[php.net
array_diff]
(https://www.php.net/manual/ja/function.array-diff.php)
Swiftで指定したURLからHTMLのソースコードを取得する

# はじめに
Swiftで指定したURLのページからHTMLを取得する方法についてのメモです。
コンソールアプリとして作成しましたが、処理自体は流用できるのでiOSアプリやmacOSのアプリケーションにも組み込むことが出来るのではないかと思います。

## コード
### 入力した文字列をURLに変換する
キーボードからreturnキーが押下されるまでを文字列を入力します。
returnキーを押下すると、文字列の末尾に改行文字が入ってしまうので空文字に置き換えます。

``` Swift:main.swift
// プログラムの開始
print("URLを入力: ");
// キーボードから return キーが押下されるまで読み込む
let standardInput: FileHandle = FileHandle.standardInput;
// 入力された情報を文字列にする(UTF-8で文字列を生成する。)
var inputString: String = String(data: standardInput.availableData, encoding: String.Encoding.utf8)!;

// 入力した文字列から改行文字を空文字に置き換える
let replaceString = inputString.replacingOccurrences(of: "\n", with: "");

// 入力したURLからHTMLのソースを取得する。
let targetURL: URL = URL(string: replaceString)!;
```

### 指定したURLからHTMLを取得
あとは、URLをStringに渡してHTMLを取得します。
HTMLを取得できない場合や、URLが誤っている場合などで例外が発生する為
例外処理を入れてあります。

``` Swift:main.swift
do {
    // 入力したURLのページから、HTMLのソースを取得する。
    let sourceHTML: String = try String(contentsOf: targetURL, encoding: String.Encoding.utf8);
    print("取得したHTMLのソースは以下です。↓\n" + sourceHTML);
}
catch {
    // 何かしらのエラーが発生した。
    print("エラーが発生しました。");
}
```

### コード全体
コード全体は以下の通りです。

``` Swift:main.swift
import Foundation


// プログラムの開始
print("URLを入力: ");
// キーボードから return キーが押下されるまで読み込む
let standardInput: FileHandle = FileHandle.standardInput;
// 入力された情報を文字列にする(UTF-8で文字列を生成する。)
var inputString: String = String(data: standardInput.availableData, encoding: String.Encoding.utf8)!;

// 入力した文字列から改行文字を空文字に置き換える
let replaceString = inputString.replacingOccurrences(of: "\n", with: "");

// 入力したURLからHTMLのソースを取得する。
let targetURL: URL = URL(string: replaceString)!;
do {
    // 入力したURLのページから、HTMLのソースを取得する。
    let sourceHTML: String = try String(contentsOf: targetURL, encoding: String.Encoding.utf8);
    print("取得したHTMLのソースは以下です。↓\n" + sourceHTML);
}
catch {
    // 何かしらのエラーが発生した。
    print("エラーが発生しました。");
}
```
AtCoder Beginner Contest 136 B（桁数を文字列から識別！）

整数 Nが与えられます。
N以下の正の整数のうち、(先頭に0をつけずに十進法で表記したときの) 桁数が奇数であるようなものの個数を求めてください。
1≤N≤10**5

```c++
    #include <iostream>
    #include <string>
    using namespace std;
     
    int main() {
      int N, count = 0;
      cin >> N;
      if(N >= 1) {
        for(int i = 1; i <= N; i++) {
          if(to_string(i).length() % 2 == 1)
            count++;
        }
     }
      cout << to_string(count);
      return 0;
    }
```

to_string(i)→()内の数字を文字列に変換する！
to_string(i).length()→()内の数字を文字列に変換した後、その文字列の長さに変換する！
【SQL】用語集　随時更新

###DDL：Data Definition Language
データベースのデータ構造を定義する言語
・CREATE文(データベース/テーブルの作成)
・DROP文(データベース/テーブルの削除)
・ALETR文(テーブルのカラムを追加・変更・削除)

###DML：Data Manipulation Language
テーブル上のデータ検索・追加・更新・削除を行う言語
SELECT文(検索)
INSERT(追加)
UPDATE(更新)
DELETE(削除)
AWSを無料でお勉強：コンソールログインを検知したい

2019/08/24に追記
書いていたら結構長くなったのでリンクを貼っておきます。

その１
https://qiita.com/auf/items/9eb47a4fb5ba0f9f26fe
その２
https://qiita.com/auf/items/25b3f52ea74ff9f152c6
その３
https://qiita.com/auf/items/92c1e2b5f202a4894c71
その４
https://qiita.com/auf/items/c4309829e3385f69b1e4
その５
https://qiita.com/auf/items/e263c6d6ad4c4d7cd48d


***

前回決めたコンセプトに従って今日も考えます。

###コンセプト
・お金かけてまでやりたくないので基本的に無料でAWSを勉強する
　→ちょっとしたサービスを起動すると結構高額になりやすい。
・高いレベルのセキュリティ確保を目指す
　→アカウントを不正に使われるととんでもない額を請求されるので防ぐ

今回はコンソールログインの検知を考えたいと思います。アカウントを持っていると何かのミスで乗っ取られる可能性もありますからねぇ。MFA設定しておけばほぼ大丈夫ですが、不意なログインを検知できるようにしてみたいと思います。

###まずはCloudtrailを勉強
まず、ログインイベントをキャッチすることを考えます。パっと見てみるとCloudTrailのAPIアクティビティ履歴が良さそうです。が、ちょっとクラメソさんのページを見ると癖がありそうです。
https://dev.classmethod.jp/cloud/aws/cloudtrail-console-login-event/

AWSの操作にはグローバルイベントとローカルイベントがあって、コンソールのログインはローカルのようです。どういうことかというと、ローカルはリージョン固有、グローバルは全リージョン共通です。つまり、全リージョンのログインを検知できないと抜け道が沢山あることになってしまいます。

でも、もっと新しい記事ではデフォルト有効されているようです。
https://dev.classmethod.jp/cloud/aws/aws-cloudtrail-default-vs-custom/
確かに設定した覚えはないんですが、取得はされています。こんな感じ↓
![201908111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/3c35f38b-5fc6-958a-5cac-f344bb989495.png)



イベントを見てみるとAWS リージョンがus-east-1になっています。

###コンソールログインのリージョンを指定する
ということで
https://console.aws.amazon.com/console/home?ap-northeast-1#
のように東京リージョンを指定してみますが、なぜかcloudtrailにログイン履歴が出てきません。
いろいろ試すと結構反映には時間がかかるみたいですね。すぐにログにでてくるものではないみたいです。
まあ、それはそうとして、なぜかコンソールログインのリージョンがus-east-1のままです。

もう一度ログオフ、ログインを繰り返してURLを確認すると↓のようになっています。
![201908112.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/8aaddd12-ecbb-b25c-6892-53613c057c31.png)

なので、コンソールは東京リージョンを指定できているんですね。コンソールは東京リージョンでバージニアを選択しているようです。実際にバージニアになってますし。

ってことは、
![201908113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/5428d620-07f8-5a86-6c76-db3b89a6a205.png)

の「AWSリージョン」がコンソールログインで変わってくる訳ではないみたいです。じゃぁここの値って何なんだろう。。。一旦わからないので、今日はここまで。
Railsチュートリアル 第6章 6.1 要約

Railsチュートリアル 2周目の学習アウトプットとして、要約記事を書いていきます。
本投稿は、「第6章 ユーザーのモデルを作成する」の中の、「6.1 Userモデル」の要約です。

# 第6章 ユーザーのモデルを作成する
## 6.1 Userモデル
・AR（Active Record）とは
　データベースとやり取りをしてくれるRailsのライブラリ。
　データベースとRubyは全く別言語の世界だが、データベースを扱う言語を知らなくてもARを使えばデータベースに対する処理が行える。
　変数のようにデータベースに値を保存したり、データを作成・検索することができる。

・ユーザー登録ページを実装するためには、ユーザー名/メールアドレス/パスワードなどを保存しておくことが必要。
　そのために作成するのが、**Userモデル**。

・nameとemailを持つユーザーを保存するためには、nameとemailのカラムを持つusersテーブルを作成する。
　モデルの生成コマンドは下記。

```
$ rails generate model User name:string email:string
```

　モデルを生成すると、
　3つのマジックカラム
　・id
　・created_at(作成日時)
　・updated_at(更新日時)
　も自動で作成されるため、下記のデータモデルを持つusersテーブルが作成される。


| カラム名 | 型 |
|:-:|:-:|
| id | integer |
| name | string |
| email | string |
| created_at | datetime |
| updated_at | datetime |

・マイグレーションファイルを作成したら、下記コマンドを実行し、データベースに適用する。

```
$ rails db:migrate
```

・「DB Browser for SQLite」というツールを使うと、.sqlite3のようなバイナリ形式で書かれたデータベース用ファイルの中身を見ることができる。

### Active Recordで使えるメソッドいろいろ
**・newメソッド**
　新しいオブジェクトを作成する。

使用例）

```
>> user = User.new(name: "Takashi", email: "takashi@gmail.com")
```

→ name属性に"Takashi"、email属性に"takashi@gmail.com"が入ったuserオブジェクトが作成される。

**・saveメソッド**
　メモリ上に作成したデータを、データベースに保存する。

使用例）

```
>> user.save
```

→ 先ほど作成したuserの中身が、データベースに保存される。

**・createメソッド**
　オブジェクトの作成(new)〜データベースへの保存(save)をまとめて行ってくれる。

使用例）

```
>> User.create(name: "Youko", email: "youko@example.com")
```

→ name属性が"Youko"、email属性が"youko@example.com"のオブジェクトを作成し、データベースに保存する。


**・destroyメソッド**
　createメソッドと逆で、データベース上の指定したデータを削除する。

使用例）

```
>> user.destroy
```

→ データベース上に保存した、userのデータが削除される。ただし、メモリ上のuserデータは残る。

**・findメソッド**
　データベース上の情報をidで検索し、返す。

使用例）

```
>> User.find(1)
```

→ idが1のユーザ情報を返す。

**・find_byメソッド**
　データベース上の情報をid以外で指定して検索し、返す。

使用例）

```
>> User.find_by(name: "Kenta")
```

→ usersテーブルの中から、name属性が"Kenta"と合致するものを探し、返す。

**・firstメソッド**
　指定のテーブルの中で、1番目に保存されている情報を返す。

使用例）

```
>> User.first
```

→ usersテーブルの中で、1番目に保存されているユーザー情報を返す。

**・allメソッド**
　データベース上の、指定したテーブルに保存された全てのデータを返す。

使用例）

```
>> User.all
```

→ usersテーブルの全てのデータを返す。

**・update_attributesメソッド**
　データベースに保存されたデータの値を更新し、保存する。
　※ただし、検証に1つでも失敗するとうまくいかない。パスワードが要求されるようになるとそれ以外の属性だけを指定して更新しようとしてもうまくいかないので、後述のupdate_attributeメソッドなどを使う。

使用例）

```
>> user.update_attributes(name: “Keita”, email: “keita@gmail.com” )
```

→ userオブジェクトを元にデータベースに保存されたデータについて、name属性を"Keita"、email属性を“keita@gmail.com”に更新する。

**・update_attributeメソッド**
　検証を回避し、特定の属性のみを更新・保存する。

使用例）

```
>> user.update_attribute(:name, "Keita")
```

→ userオブジェクトを元にデータベースに保存されたデータについて、name属性が"Keita"に更新・保存される。

**・reloadメソッド**
　データベースの値に合わせて値を更新する。

使用例）

```
user.reload.email
```

→ データベース上のemail属性の値に合わせて、userデータのemail属性を更新する。
Azure AD BtoBで、ゲストユーザーがサインイン履歴が残らない場合の対応

AzureAD BtoBでゲストユーザーを招待すると便利。Office365だと、SharePointやTeamsに招待すると、いろいろ捗る。捗るから、どんどん招待するユーザーが増えていくので、定期的に棚卸必要、ってことで前回の[Office365のゲストユーザー（外部ユーザー）の一覧を取得する](https://qiita.com/hisssa0102/items/988eb74c758cd3c3608f)をまとめてみた。


定期的な棚卸で、30日ログインがない＝使っていないとみなして削除する、という運用がわかりやすい。グラフ見てログインなければ即削除、でいいし。


が、昨日もSharePointサイト使ってたゲストユーザーが、ログインできなくなったんですけど～？という問い合わせがあり、原因と対応をまとめてみた。




#AzureADとSharePointのファイルのログを見る

そのゲストユーザーは、すでに削除済みだった。いったん復元して、のログインログみたらやっぱり直近30日間にログインログはなかった。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/962129e4-9d42-18d6-20d1-5b0604429568.png" width=50%>

しかし、当該のサイトで、最終更新者がそのゲストユーザーのファイルの、最終更新日は昨日の日付。なんで？

#なぜログイン履歴がない！？

教えて！Azureのひと！ということで問い合わせてみた。


ブラウザで「サインイン状態を維持しますか」でチェックを入れているとこういう状態が起こるらしい。

この画面。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/478edffc-00a7-fe22-3a0b-4ef3a637b634.png" width=50%>


サインイン時にチェック入れておくと、180日以内に再度SharePointサイトを開くと、サインインなしでサイトを開くことができ、かつ180日間再延長されるらしい。

これの永続的にあたるらしい。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/d9a0007f-c207-c444-c9c5-f6ce6f656fb1.png" width=50%>
引用元：[Azure AD が発行するトークンの有効期間について](https://blogs.technet.microsoft.com/jpazureid/2018/02/28/aad-issure-token-lifetime/)

サインイン操作してないんだもん。そりゃ、AzureADのサインインログには出てこないわ。

テナント内ユーザーでも、ゲストユーザーでも、ユーザーから操作する分には操作は少ないほうがいいよね。ログイン状態保持したいって思うのもしょうがないよね。


#じゃ、対策は？

とはいえ、このままではサインインログに出てこないので、本当に使っていないユーザーなのか区別がつかない。
しかし、条件付きアクセスで永続的セッションを禁止できるそうな。
※20190810時点ではプレビュー

条件付きアクセスの名前を付けて

ゲスト全員
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/8f09c148-06b0-f713-242f-87e24244c601.png" width=50%>
全部のクラウドアプリ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/a944a169-68a2-0bd7-b870-87d97b00e3e5.png" width=50%>
永続的なブラウザーセッションにチェックして、「永続的にしない」
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/8b1f992e-51a0-faaf-b88b-093c58b06f29.png" width=50%>


これでOK!

ユーザーを割り当てたら、内部ユーザーであっても、サインイン状態の保持は出なくなった。
これで安心してAzureADのゲストユーザーのサインイン履歴で判別できる。




#おまけ：ライセンスいるの？

テナント内のユーザーの条件付きアクセスは、Azure AD P1が必要だけど、[M365 Businessでも大丈夫](https://docs.microsoft.com/ja-jp/azure/active-directory/conditional-access/overview)。
でもって、ゲストユーザーへ条件付きアクセスを適用できる数は、[テナントのAzure AD P1のライセンス数の5倍まで](https://blogs.technet.microsoft.com/jpazureid/2017/12/04/conditional-access-qa/)。

今回はゲストにはライセンス割り当てていないけど、きちんと適用されてました。


#まとめ

永続的なサインインを禁止すると、サインイン後最大でも24時間になる。これでゲストユーザーのSharePointへのアクセスの際、Azure ADのサインインログに現れるようになる。

SharePointやTeamsでゲストユーザーを招待している場合は、この設定はおススメです。


1つ気になったのが、内部ユーザー。AzureADP1割り当ててないユーザーにも適用できたっぽい。こっちはおいおい調べてみる。
[Unity] ビルド時に Json.NET が動かない問題 PlatformNotSupportedException

JsonUtility で Dictionary が使えなかったことにイライラしたので、 Json.NET を入れました。
Editor 上で Play する分には問題なく動いてくれましたが、 Build And Run すると、どうも上手くファイルが読み込まれていないようでした。

Development Build で確認すると、エラーメッセージが表示されました。
`PlatformNotSupportedException: Operation is not supported on this platform.`
そして二行目には、 `Newtonsoft.Json` の文字が。

## 解決法

https://github.com/JamesNK/Newtonsoft.Json/issues/2046
にある通り、 `Player Settigns` にある `Api Compatibility Level` を `.NET 4.x` に変更すると動くようになりました。

しかしこの方法には少し問題があるようで、
https://docs.microsoft.com/ja-jp/visualstudio/cross-platform/unity-scripting-upgrade?view=vs-2019
にある通り、動かないプラットフォームがある可能性がある、ということを知っておくべきでしょう。
Laravelのクエリビルダで条件の優先順位に変えるにはクロージャーを使う

```php:コード例

User::where(function ($query) use ($hoge) {
    $query->orWhere('hoge', $hoge)->orWhere('fuga', 1);
})->(省略)

```

```sql:sql例
select * from table_names where (columnA = A or columnB = B) and (columnC = C or columnD = D);
```

sqlは雰囲気です。エラーになりそうです:sweat_smile:

AND条件のほうがORよりも優先度が高く、意図したSQLにならない場合があります。
そんなときは、クロージャを使って書くとカッコが挿入され、優先順位を変えることができます。

[Laravel 5.8 データベース：クエリビルダ
パラメータのグループ分け]
(https://readouble.com/laravel/5.8/ja/queries.html#parameter-grouping)

[smith30のエンジニア日誌
mysqlでの論理演算子の優先順位]
(http://smith30-tech-memo.hatenablog.com/entry/2015/12/23/164745)
pythonの集合型set

```python:python
>>> set1 = {1,2,3,4,5}
>>> set2 = {1,3,5,7,9}

# 和集合
>>> set1 | set2
{1, 2, 3, 4, 5, 7, 9}

# 積集合
>>> set1 & set2
{1, 3, 5}

# 差集合
>>> set1 - set2
{2, 4}

# 排他的論理和
>>> set1 ^ set2
{2, 4, 7, 9}
```

```python:python
# リストから重複を除去
>>> list = [1,2,3,3,4,5,5,6]
>>> set = set(list)
>>> set
{1, 2, 3, 4, 5, 6}
```

```python:python
# 文字列のset
>>> strset1 = {"apple", "りんご", "banana"}
>>> strset2 = {"orange", "オレンジ", "banana"}
>>> strset1 | strset2
{'orange', 'banana', 'オレンジ', 'apple', 'りんご'}
>>> strset1 & strset2
{'banana'}
>>> strset1 - strset2
{'apple', 'りんご'}
>>> strset1 ^ strset2
{'orange', 'りんご', 'オレンジ', 'apple'}
```