OmniAICreator/Qiita-1.07M huggingface dataset:
【Kotlin】Any?.toString()とAny.toString()の違いに注意する

# TL+DR
- `Any?.toString()`と`Any.toString()`は挙動が異なる
  - `Any?.toString()`は値が`null`の時`"null"`という文字列を返す
- `nullable`型に同名の拡張関数が定義されていると、意図せず`null`安全呼び出しを怠ってもコンパイルエラーにはならないため注意が必要

# null安全呼び出しが不要な関数について
`Kotlin`の関数やプロパティは基本的に`null`安全呼び出しが求められます。

```kotlin
class Foo(val bar: Int)

val foo: Foo? = /* 省略 */
val baz = foo.bar // null安全呼び出しをしていないためコンパイルエラー
```

一方、`nullable`型の拡張関数は`null`安全呼び出し無しで呼び出すことができます。
以下は`CharSequence?`に対して呼び出せる`isNullOrBlank`関数です。

```kotlin:kotlin.text.Strings.ktより引用
/**
 * Returns `true` if this nullable char sequence is either `null` or empty or consists solely of whitespace characters.
 *
 * @sample samples.text.Strings.stringIsNullOrBlank
 */
@kotlin.internal.InlineOnly
public inline fun CharSequence?.isNullOrBlank(): Boolean {
    contract {
        returns(false) implies (this@isNullOrBlank != null)
    }

    return this == null || this.isBlank()
}
```

これは以下のように呼び出せます。

```kotlin
val str: String? = null
val isNullOrBlank = str.isNullOrBlank() // null安全呼び出し無しでもコンパイルエラーにならない
```

# 注意が必要な点
このような拡張関数の中には、`toString`のように、`null`安全呼び出しが必要な内容と同名のものが有ります。
これは同名でも挙動が異なる場合が有るため注意が必要です。

```kotlin
val str: Any? = /* 省略 */

val toString2: String? = str?.toString() // null安全呼び出しした場合

val toString2: String = str.toString() // null安全呼び出ししなかった場合
val toString3: String = str?.toString() ?: "null" // strがnullならtoString2と同じ値
```

## 補足
`Any?.toString()`は以下のように定義されています。

```kotlin:kotlin.Library.ktより引用
/**
 * Returns a string representation of the object. Can be called with a null receiver, in which case
 * it returns the string "null".
 */
public fun Any?.toString(): String
```
Raspberry PiのUbuntu MATEでSSH接続のセットアップ（GitHubから鍵登録）

最近、Raspberry Pi4を買いました。
せっかくなので[Raspberry Pi OS（旧Raspbian）](https://www.raspberrypi.org/downloads/)ではなく、正式サポートされているUbuntu Desktop環境の[Ubuntu MATE](https://ubuntu-mate.org/)をインストールしてみたところ、意外とハマったのでメモです。SSHでつなぐところまでやります。

# インストール方法
ここからイメージをダウンロードして、MicroSDに書き込みます。
[Choose an architecture \| Download](https://ubuntu-mate.org/download/)
イメージ書き込みはこのアプリがおすすめです。
[balenaEtcher \- Flash OS images to SD cards & USB drives](https://www.balena.io/etcher/)
あとは起動するだけですね。

# SSH接続のセットアップ
デスクトップ環境といっても、手元のPCからアクセスしたいこともありますよね。
ということで、SSHをつなぎます。

## OpenSSHをインストール
なんと、Ubuntu MATEにはOpenSSHがインストールされていませんでした。（[公式サイトにもちゃんと書いてある](https://ubuntu-mate.org/ports/raspberry-pi/)）

>The OpenSSH server is not installed by default. Simply install it to to enable SSH.

記載の通りに下記コマンドでOpenSSH-Serverをインストールします。

```bash
sudo apt install openssh-server
```

## 有効化
インストールだけでは動きません。OpenSSHを有効化します。

```bash
sudo systemctl enable ssh
sudo systemctl start ssh
```

## SSHキー生成
Raspberry PiのSSHキーを生成します。
Ubuntuでは下記でOpenSSHが再設定され、鍵の生成も自動で行われます。

```bash
sudo dpkg-reconfigure openssh-server
```

以上で、ユーザーのパスワード認証によるログインが可能になりました。
セキュリティと利便性追求のため、公開鍵での接続設定を行いましょう。

## クライアント公開鍵の登録方法
接続元となるクライアントの公開鍵を登録します。

公開鍵ファイルの転送は結構めんどくさいですが、実はGitHubに公開鍵を登録していれば、非常に簡単に転送可能です。なお、公開鍵の登録は[このページ](https://github.com/settings/keys)から可能です。

ですがその前に…なんとUbuntu MATEには[curl](https://curl.haxx.se/)が入っていないようです。（これは意外でした）
ということで、まずはcurlのインストールからです。

### curlのインストール
```bash
sudo apt install curl
```
これでファイルのダウンロードなど、いろいろな通信が手軽に実行可能になりました。

## 公開鍵のダウンロードと登録
では、気を取り直して。
実はGitHubでは、下記URLから登録済みのユーザーの公開鍵を取得することが可能です。
`https://github.com/<ユーザー名>.keys`

ここからクライアントの公開鍵を取得して、`~/.ssh/authorized_keys`に追加すれば、サクッと鍵の登録が完了します。

下記でフォルダ作成とダウンロード、追加が完了です。わざわざSCPする必要もなく、とても簡単ですね。

```bash
mkdir -p .ssh && curl https://github.com/kiri-i.keys >> ~/.ssh/authorized_keys
```

ちなみに、Linuxはファイル名の大文字・小文字を区別するので要注意です。ハマりました。
以上でパスワード入力なしに、クライアントからSSH接続が可能になったかと思います。

```bash
ssh <ユーザー名>@<ホスト名>
```

接続が確認できたら、セキュリティ向上のためパスワード接続をブロックしましょう。

## SSHのパスワード認証接続を拒否

SSHの設定ファイルを開き、

```bash
sudo vi /etc/ssh/sshd_config
```

`#PasswordAuthentication`を`#PasswordAuthentication yes`から`#PasswordAuthentication no`へ書き換えます。

再起動すれば、設定が反映されるはずです。
お疲れさまでした！
最新版インストールすると良いWordPressのプラグイン

今回Luxeritasというテーマを知ったことがきっかけとなり、今の時代に合ったWordPressのプラグインをご紹介したいと思い記事を書きました。

私がWordPressを設置する際の備忘録も、兼ねています。

#重要な点
WordPressのバージョンが5.5になってから、サイトマップの自動作成機能が標準対応になりました。
そのため、これまでサイトマップを作るときに重宝していたプラグインのGoogle XML Sitemapsは、ケースバイケースで選択されると良いと思います。

#テーマによってプラグインの構成を考える
今回知ったLuxeritasやCOCOONのようにSEO対策されているテーマの場合、All in One SEO PackなどのSEO関連のプラグインは、インストールしない方が良いようです。

#プラグインの一覧
私が使っているプラグインを、まとめました。
また、記事のサイトに、Luxeritasのテーマで推奨されてるプラグインの一覧ページのURLも、ご案内しています。


##Akismet Anti-Spam (アンチスパム)
有料のようなので、私は、使っていないです。
スパム対策に、おすすめです。

##Contact Form 7
問い合わせなどのフォームを簡単に作ることができます。

##Crayon Syntax Highlighter
ソースコードを綺麗に、掲載できます。

##Disable Comments
コメント欄を一括して非表示できます。

##Elementor
自由なレイアウトで、ページを作成できます。

##EWWW Image Optimizer
画像圧縮プラグイン

##Favicon by RealFaviconGenerator
ファビコンをWordPressに、設定できます。

##Google XML Sitemap Generator
サイトマップを自動で、作成できます。
ただし、WordPress5.5から、標準でサイトマップを作ることができるようになりましたので、ケースバイケースで選択すると良いです。

##Jetpack by WordPress.com
WordPressの稼働状況の確認できるほか、SNSのシェアや高速表示など多機能なプラグインです。

##Really Simple SSL
SSLを設定しているときは、必須のプラグインです。

##XCloner - Site Backup and Restore
WordPressのバックアップや引っ越しが出来るプラグインです。

##WebSub/PubSubHubbub
ブログの更新をGoogleなどに伝えることができます。


###Luxeritasのテーマで推奨されてるプラグインの一覧ページ
[https://thk.kanzae.net/wp/settings/t1270/](https://thk.kanzae.net/wp/settings/t1270/)
ssh-keygenを用いて秘密鍵と公開鍵を作る（Windows10とLinuxの違い）

# 1. はじめに
　秘密鍵と公開鍵を作成するにあたって、Linuxを用いるか何かしらのソフトウェアの導入が必要と思い込みをしていました。が、恥ずかしながらつい先日Windows10に標準でOpenSSHがインストールされている（ssh-keygenコマンドが使える）ことを知り衝撃を受けました。Linux版とほぼ同じようなのですが、Windows版固有の違いが見られたので紹介します。

※2021年9月よりgithubにて[古い暗号アルゴリズム（RSAなど）の利用ができなくなりました](https://github.blog/2021-09-01-improving-git-protocol-security-github/)。コマンドラインなどでgitコマンドを実行すると以下のようなエラーが発生しますが、その場合はEd25519等の暗号アルゴリズムを用いた新しいキーを生成し、githubに再設定する必要があります。

~~~
$ git clone git@github.com:xxxx/xxxx.git
Cloning into 'xxxx'...
ERROR: You're using an RSA key with SHA-1, which is no longer allowed. Please use a newer client or a different key type.
Please see https://github.blog/2021-09-01-improving-git-protocol-security-github/ for more information.

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
~~~


# 2. 作成方法
　秘密鍵と公開鍵を作成する際にパスフレーズとコメントを埋め込むことができますが、私は必要ないと考えているので、ssh-keygenのパラメータにて空文字を指定します。

## 2.1. Linuxの場合
linuxですと以下の通りとなります。
※二つのファイル（id_rsa：秘密鍵、id_rsa.pub:公開鍵）が生成されます。

~~~shell
$ cd 【秘密鍵と公開鍵を生成したい場所】

# RSA 4096bit
# $ ssh-keygen -q -t rsa -b 4096 -C '' -N '' -f id_rsa
#  githubで利用できなくなった。
#  https://github.blog/2021-09-01-improving-git-protocol-security-github/

# Ed25519
$ ssh-keygen -q -t ed25519 -C '' -N '' -f id_rsa
~~~


## 2.2. Windowsの場合(コマンドプロンプト)
 WindowsのコマンドプロンプトでLinux版のコマンドをそのまま実行すると、 ~~**エラー** になります~~ エラーとならずに鍵ファイルが生成されますが、passphraseが設定された状態となります（何が設定されているのか不明）。。。
以前はエラーとなってくれていたので、改悪されているように思いますが・・・。

~~~shell
>cd 【秘密鍵と公開鍵を生成したい場所】
>ssh-keygen -q -t ed25519 -C '' -N '' -f id_rsa
#以前は
#Saving key "id_rsa" failed: passphrase is too short (minimum five characters)
#というエラーが出ていたのですが、最近はエラーが出ず、且つよくわからないpassphraseが設定されている状態のkeyが生成されてしまいます。
~~~

 ~~エラーメッセージ的には、パスフレーズが短すぎますとのことなのですが、実は空文字指定が正しく認識されていないことが原因です。~~ 

空文字指定をしたい場合は、正しくは以下のようにコマンドを打つ必要があります。

~~~shell
>cd 【秘密鍵と公開鍵を生成したい場所】
>ssh-keygen.exe -q -t ed25519 -C "" -N "" -f id_rsa
~~~


## 2.3. Windowsの場合(PowerShell)

　PowerShellを使用すると上記コマンドでも **エラー** になります。

~~~shell
>cd 【秘密鍵と公開鍵を生成したい場所】
>ssh-keygen.exe -q -t ed25519 -C "" -N "" -f id_rsa
Enter passphrase (empty for no passphrase):　　←　え・・・。
~~~

正しくは、以下の通りです。

~~~shell
>cd 【秘密鍵と公開鍵を生成したい場所】
>ssh-keygen.exe -q -t ed25519 -C '""' -N '""' -f id_rsa
~~~


# 3. おわりに
 Windowsにおいても使えるLinuxコマンドが増えてきていることは歓迎なのですが、今回のケースのようにちょっとした違いで躓くこともあるように思います。本記事がどなたかの一助になれば幸いです。

# 参考
[Automate ssh-keygen -t rsa so it does not ask for a passphrase](https://stackoverflow.com/questions/10767488/automate-ssh-keygen-t-rsa-so-it-does-not-ask-for-a-passphrase/14946700#14946700)
[お前らのSSH Keysの作り方は間違っている](https://qiita.com/suthio/items/2760e4cff0e185fe2db9)
GithubActionでmasterプッシュ時にECRにimageをpushする

# aws ECRにリポジトリを作る
1. awsコンソールにログイン
2. 検索窓から「ecr」と検索すると「Amazon Container Services」というのが出てくるのでクリック
3. リポジトリを作成
 ![スクリーンショット 2020-08-23 21.35.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/7b33ff9a-98ad-9cfd-828f-e65966f9b507.png)
4. 今回は「test」という名前でリポジトリを作成します(名前は任意の名前で大丈夫です！) 
![スクリーンショット 2020-08-23 21.37.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/ed360dd9-467d-e041-0617-08cf2818d664.png)

# Github Actionsを動かすアクセスキー、シークレットキーを取得
1. awsコンソールにログイン
2. 検索窓から「iam」と検索
3. ユーザー追加をクリック
![スクリーンショット 2020-08-23 21.27.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/b5a5f2de-2c0a-6f54-c0f0-cbe0a636d305.png)
4.名前に「github-actions」(名前は任意の名前で大丈夫です！)アクセスの種類は「プログラムによるアクセス」にチェックして次へ
![スクリーンショット 2020-08-23 21.27.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/93318f91-c5c2-677a-ae5b-c5ba014344f7.png)
5.「既存のポリシーを直接アタッチ」を選択→「AmazonEC2ContainerRegistryPowerUser」と検索すると権限が出てくるのでこちらをチェック
![スクリーンショット 2020-08-23 21.29.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/ad26108e-6dfb-81e9-e8a2-2657b4d917c3.png)
6. あとは全て次へで大丈夫です。そしたら以下のような画面になるのでアクセスキーとシークレットキーをメモしておく
![スクリーンショット 2020-08-23 21.29.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/25fa151d-62dd-27a8-3882-8232195fdf2f.png)


# Githubにシークレットキーを登録
1. githubの該当のリポジトリにいき下記3つの変数を追加する

- AWS_ACCESS_KEY_ID（先ほど取得したアクセスキー）
- AWS_SECRET_ACCESS_KEY（先ほど取得したシークレットキー）
- AWS_ECR_REPO_NAME（ECRで作成したリポジトリ名＊今回の場合は`test`）
![スクリーンショット 2020-08-23 21.40.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/db3ab4c8-de71-d57c-31ca-96ca72ca9d92.png)
上記のように変数を指定することで`${{ secrets.キー名 }}`とすることでその環境変数を使用できる

# github actionsのymlを作成

```yaml:.github/workflows/config.yml
name: Build and Push

on:
  push:
    branches:
      - master

jobs:
  build-and-push:
    runs-on: ubuntu-18.04
    timeout-minutes: 300

    steps:
      - uses: actions/checkout@v1

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build, tag, and push image to Amazon ECR
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPO_NAME }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
```

# 確認！
- aws ECRにリポジトリを作る
- Github Actionsを動かすアクセスキー、シークレットキーを取得
- Githubにシークレットキーを登録
- github actionsのymlを作成

上記４点ができたら
githubにプッシュしてみてくださいするとgithub actionsが動きリポジトリにimageがプッシュされてれば完了です
![スクリーンショット 2020-08-23 23.10.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281558/ae4d2ccb-9276-7a9f-fc1e-ccb28f85efb1.png)

# 参考文献
[GitHub ActionでDockerコンテナをビルドしてAmazon ECRに保存する](https://dev.classmethod.jp/articles/github-action-ecr-push/)
とりあえずrecoil触ってみるまで

## 特にコメントなし

```jsx
import React from "react";
import "./styles.css";
import {
  RecoilRoot,
  atom,
  selector,
  useRecoilState,
  useRecoilValue
} from "recoil";

const countState = atom({
  key: "countState", // unique ID (with respect to other atoms/selectors)
  default: 0 // default value (aka initial value)
});

const charCountState = selector({
  key: "charCountState", // unique ID (with respect to other atoms/selectors)
  get: ({ get }) => {
    const text = get(countState);

    return text * 10;
  }
});

export default function App() {
  console.log("111111111");
  return (
    <RecoilRoot>
      <div className="App">
        <Test />
        <Test2 />
      </div>
    </RecoilRoot>
  );
}

const Test = () => {
  const [count, setCount] = useRecoilState(countState);
  console.log("fffffffff");
  return (
    <div>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        test
      </button>
      {count}
    </div>
  );
};

const Test2 = () => {
  console.log("88888888888");
  const count = useRecoilValue(charCountState);
  return (
    <div>
      <button>test2</button>
      {count}
    </div>
  );
};

```
JupyterLabでサクサクコード補間！jupyterlab-kiteの導入

# この記事でわかること
* JupyterLab上でコード補間ライブラリのkiteを適用する方法（Mac環境）

### 備考
* linux版の導入方法は[こちらの素敵な記事](https://qiita.com/fugaga/items/87fb69d88abea70f67c6)で解説されています。

# 概要
先日，Pythonなどのコード保管で知られる[kite](https://www.kite.com)がデータ分析等で使われるIDEでおなじみの[JupyterLab](https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html)に対応したことが[アナウンス](https://venturebeat.com/2020/08/04/kite-brings-its-ai-powered-code-completions-to-jupyter-notebooks/)されました。

今までJupyterLabでの補間といえばデフォルトで備わっているTab補間や，extensionの一つである[Jupyter-lsp](https://github.com/krassowski/jupyterlab-lsp)が知られていましたが，補間にラグが生じたり，環境によっては設定が必要であったりと少し使いにくいものでした。また，補間のタイミングや内容なども昨今の機械学習を利用した補間に比べては少々物足りない側面がありました。

今回適用可能なkiteは機械学習を用いた補間ライブラリの一つで人気の高いものでもあります。それが今までコード補間に対して弱点を持っていたJupyterLabで利用できるとなれば[JupyterLabファン](https://qiita.com/kirikei/items/a1639954ce5ccaf7ac3c)としては試す＆導入の解説を書かせて頂きます。

導入できると以下のようにTabを押さなくてもモリモリ補間してくれるようになります。

![kite-qiita.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185518/6abcf1c8-b5cb-790a-5581-d7980fa51e70.gif)

# 導入（Mac環境）

## kiteのインストール
基本は[jupyterlab-kite公式](https://github.com/kiteco/jupyterlab-kite)に則って実行すればOKです。
kiteの公式サイトからMac版をダウンロードしてdmgファイルを開き，Applicationにコピーを行い起動しておきます。extensionのインストールの前に本体をインストールしておく必要があるので気をつけて下さい。

## jupyterlab-extensionの導入
JupyterLabのExtensionをまだ導入したことがない方は[こちら](https://qiita.com/kirikei/items/a1639954ce5ccaf7ac3c#5-jupyterlab-extension%E3%81%AE%E7%B4%B9%E4%BB%8B)を参照して下さい。

※この記事の執筆時点ではjupyterlab-kiteはJupyterLabのバージョン2.2.0以降，nodejsのバージョン10以上にしか対応していないので気をつけて下さい（詳しくは[Github](https://github.com/kiteco/jupyterlab-kite)参照）

JupyterLabが利用可能な環境で以下を実行します。

```shell
$ pip install jupyter-kite
$ jupyter labextension install "@kiteco/jupyterlab-kite"
```

インストールが終わったら以下のコマンドでJupyterLabを立ち上げます。

```
$ jupyter lab
```

## 確認
JupyterLabの画面において，以下の画像のように左下にkiteのアイコンが表示され，かつnot connectingからしばらく待ってindexingに変われば導入OKです。あとは色々と試してみましょう。

![スクリーンショット 2020-08-23 22.54.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185518/18e94063-7d7d-0d5e-3d24-7bd13b8f67bf.png)

# 試してみた所感
こちらのjupyterlab-kiteですが，今までの補間よりもいくつもの利点があります。

* パッケージの推薦だけでなくいい感じに補間してくれる

kiteを利用すると，例えば以下のように`import num`の時点でコードを補間してくれる上によく使われる`numpy as np`まで推薦してくれます。

![スクリーンショット 2020-08-23 22.58.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185518/14359d3e-d7f3-8372-0cb3-2674488d9829.png)

* 関数やメソッドの引数や解説が表示される

例えば`numpy.arange`について以下のように引数の数や意味をTipsとして表示してくれます。これで関数の内容を忘れても問題ありません。

![スクリーンショット 2020-08-23 23.00.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185518/89ba7457-1214-a677-c6f0-4be7380c1e64.png)

* ユーザ定義の変数や関数も補間してくれる

下記のようにユーザが定義した関数も補間してくれます。docstringなどを書いておくと推薦時にちゃんと表示してくれるようです。

![スクリーンショット 2020-08-23 23.06.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185518/10dec981-b800-c8e8-e3a9-409f9e9e0de8.png)

# 終わりに
個人的にはJupyterLabの革命のように感じました。皆さんもぜひkiteを導入してみて下さい！
【AWS】AWS Ground Stationなるサービスについてちょっと調べてみた

#AWS Ground Stationを調べてみる経緯
AWSマネジメントコンソールを触っている際、サービス一覧に「衛星」のカテゴリが気になったのでちょっと調べてみることにしました。
#AWS Ground Stationってなにもの
###ざっくり説明
・人工衛星が取得したデータをAWSに送ることが出来るサービスのようです。
・地上に自前でアンテナを用意する必要は無くAWSが設置したGround Station(地上にあるアンテナ)で人工衛星からデータを受信することが出来るようです。
・人工衛星との通信時間をスケジューリングして使用するようです。
・人工衛星から送られてきたデータはEBS、EFS、S3に保存することが出来るようです。
・現在使用できるアンテナは、「米国東部 (オハイオ)」「米国西部 (オレゴン)」「中東 (バーレーン)」「欧州 (ストックホルム)」「アジアパシフィック (シドニー)」「欧州 (アイルランド)」の6つ
[AWS公式サイトの概要説明](https://aws.amazon.com/jp/ground-station/)
#どんなことに使用するの？
###・自然災害
>自然災害発生中、ダウンリンクされた映像データを迅速に分析して、生存者の割り出し、構造画像の査定、およびこのデータを迅速に第一に応答した人および救助隊にストリーミングできます。分析およびマシンラーニングをこのデータに適用して、最も安全な避難路および一時的避難のための最良の場所、および非常薬施設を割り出すことができます。

###・正確な天気予報 
>AWS クラウドを使用することにより、世界中からダウンリンクされた天気データを分析して、より正確に天気パターンを予測できます。これは船舶、飛行機、トラックおよび人が所在する地区の荒れ模様の天気に対する認識を高め、効率的に危険な状況を避けるのに役立ちます。

###・ビジネストレンド査定
>駐車場、物流センター、小売店などの様々な商業施設のレーダー衛星映像を使用して、たとえ暗闇や曇りの天気でも、自動的に車両、交通および利用客の流れのパターンを計測します。これを他の分析や機械学習などの AWS のサービスと、日時および天気の条件とともに組み合わせて、ビジネスおよび経営のトレンドをリアルタイムで査定することができます。これらの識見は、世界中至るところにいる関連ビジネス分析者および意思決定者にすばやく流れます。

[引用元](https://aws.amazon.com/jp/ground-station/)
#感想
AWSのサービスに人工衛星と通信するサービスがあったのは驚きですね。
AWS Ground Stationはアンテナは用意してくれますが人工衛星は自分で飛ばさないといけないので個人使用は難しそう．．．
(人工衛星との通信は男心くすぐられるロマンあふれるサービス)
いつか仕事で関わってみたいと思いました。
Scapyのコードを少しみてみる。構造体をどう処理しているか。

#目的
少し用事があり、例えば、Scapyのコードはどんな感じが見てみた。
Scapyとは、
**Scapy is a powerful Python-based interactive packet manipulation program and library.**
（引用：https://pypi.org/project/scapy/）

**Pythonには構造体がない**ので、
パケットなどの構造体的なデータをどう処理しているかを確認した。

対象コードは、
https://github.com/secdev/scapy

引用コードもすべて上記。


#わかったこと
##概要
コード上、以下の２つの構造体関連の処理があった

* structモジュール
* Structureクラス

基本、前者が使われている。



#structモジュール

↓以下のような感じで、packしていた。

```python
    psdhdr = struct.pack("!4s4sHH",
                         inet_pton(socket.AF_INET, u.src),
                         inet_pton(socket.AF_INET, u.dst),
                         proto,
                         ln)
```

##Structureクラス

↓以下のようなコードがあるが、Windowsのpcap対応用？？
使われ方がよくわからなかった。

```python
class sockaddr_in(Structure):
    _fields_ = [("sin_family", SHORT),
                ("sin_port", USHORT),
                ("sin_addr", in_addr),
                ("sin_zero", 8 * CHAR)]   
```

#まとめ
有名なScapyで、パケットの構造体的なデータがどう処理されているかを確認した。
**structモジュール**が使われていた。
（上記、少し、語弊があります。データをかためる部分で、structモジュールが使われていたという言い方が適当かも。）
c言語等に構造体がどう扱われているかという意味では、かためる以外の部分は、普通にクラスのメンバーになっているという言い方が正しいと思う。

コメントなどあれば、お願いします。:candy:
[Elixir]nilとの比較演算がtrueになる件について

Elixirの比較演算について

現象:
Elixirで数値と`nil`の比較を行うと`true`の結果になりました。
例えば、以下の結果になります。

```bash
iex(5)> 3 <= nil
true
```
`true`?
`false`か例外があがると思っていたところ予想外の展開。


いくつか他言語の例を見てみます。[^1] 
Rubyの場合:

```bash
irb(main):001:0> nil <= 3                                                                                               Traceback (most recent call last):
        4: from C:/Ruby27-x64/bin/irb.cmd:31:in `<main>'
        3: from C:/Ruby27-x64/bin/irb.cmd:31:in `load'
        2: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
        1: from (irb):1
NoMethodError (undefined method `<=' for nil:NilClass)
```

JavaScriptの場合:

```javascript
null > 0
false
```

Elixirに戻ります。
これは、Elixirでは`nil`に限らず、異なるデータ型間での比較が可能なためで、以下の順序が定義されていました。
`number < atom < reference < function < port < pid < tuple < map < list < bitstring`[^2]

`nil`は`atom`に分類される[^3]ため、`3 <= nil`が`true`になったようです。
以下、`nil`は`atom`になることの確認

```bash
iex(1)> is_number(nil)
false
iex(2)> is_atom(nil)
true
iex(3)> is_reference(nil)
false
iex(4)> is_function(nil)
false
iex(5)> is_port(nil)
false
iex(6)> is_pid(nil)
false
iex(7)> is_tuple(nil)
false
iex(8)> is_map(nil)
false
iex(9)> is_list(nil)
false
iex(10)> is_bitstring(nil)
false
```

上記を踏まえて、いくつか他の型との比較を検証します。

1.functionと`nil`の比較

```bash
iex(11)> f = fn x -> x end
#Function<6.99386804/1 in :erl_eval.expr/5>
iex(12)> f > nil
true
```
2.tupleと`nil`の比較

```bash
iex(13)> {:ok,0} > nil
true
```

3.listと`nil`の比較

```bash
iex(14)> [1,2,3] > nil
true
```

他の言語と一緒だと思っているとはまりそうなところなので、残して置こうと思います。

参考文献:
[^1]: https://stackoverflow.com/questions/41599273/why-is-nil-0-true-in-erlang/41601875)
[^2]: https://hexdocs.pm/elixir/operators.html#comparison-operators
[^3]: https://stackoverflow.com/questions/38852905/why-is-atomnil-equals-to-true-in-elixir
Javascript基本②



##ボタンをJavaScript上で扱えるようにする
ボタンを押したらコンソール上で「Hello world」と出す実装をしていきます！
**DOM**という仕組みを利用します。

##DOMとは
HTMLを解析して、データを作成する仕組みです。
DOMによって解析されたHTMLは階層構造のあるデータです。
これを、DOMツリーもしくはドキュメントツリーと呼びます。

JavaScriptを使うと、DOMツリーを操作することができます！
idやclassの情報を元に、DOMツリーの一部を取得して要素を増やしたり消したりします。
このDOMツリーの一部のことをノードオブジェクトと呼びます。

## ノードとは
DOMツリーを構成する要素をノードと呼びます。　
body →　ノード
header →　ノード
side_bar　→　ノード
footer →　ノード

##DOMツリーの情報
DOMツリーの情報は検証ツールで見れます。

##ノードの取得

**1.document.getElementById("id名");**
documentは開いているページのDOMツリーが入っているオブジェクト。
ドキュメントに対していくつかのメソッドを使用することで、DOMツリーに含まれる要素を抽出して取得することができます。DOMツリーから特定の要素を取得するための**メソッド**の一つです。


**2.document.getElementsByClassName("class名");**
classを指定して取得する場合は上記です。"Elements"と複数形にして利用します。
同じclassを持つ要素を全て取得することができます！

**3.document.querySelector("セレクタ名");**
セレクタ名とは、CSSでスタイルを適用するために指定している要素。
HTML上から、引数で指定したセレクタに合致するもののうち一番*最初に見つかった要素1つ*を取得


##コンソールでボタン要素を取得

document.querySelector("button");
戻り値は`<button id="Button">ボタン</button>`
HTMLタグのようなものがノードです。

##querySelectorメソッド　複雑なセレクタ指定

***idがbutton２のbuttonタグの要素***

```
docuent.querySelector("button#Button2"); 
```

***footerタグ要素の中の、クラスがnextのaタグ要素***

```
document.querySelector("footer a.next");
```

上記でquerySelectorメソッドを使って、ボタンをJavaScript上で取得することができます。

querySelectorメソッドでは、複雑なセレクタも指定できます。



#####今回は以上です！
【Git基本】別ブランチのコミットをcherry-pickで持ってくる&コンフリクト対処

前回深夜テンションで書いた記事が軽くバズってしまった @tsuboyataiki です。

一つの大きな機能作成で、複数の作業が同時並行になってしまい、別ブランチの特定の作業（コミット）が必要になるタイミングがありました。

そこで社員の方からcherry-pickの使い方を教えていただいたので残しておこうと思います。

# cherry-pickって？
**"cherry pick"**は直訳すると「（いいところだけ）つまみ食いする」みたいな意味があるそうです。

Gitの機能としては、[リファレンス](https://git-scm.com/docs/git-cherry-pick)より以下のような記述があります。
> Given one or more existing commits, apply the change each one introduces, recording a new commit for each.
訳：1つ以上の既存のコミットを前提として、それぞれが導入する変更を適用し、それぞれの新しいコミットを記録します。

要は「別のブランチ（ワークツリー）にある変更（コミット）を持ってこれるよ」という感じです。

# ユースケースは？

プロダクト・システムで大きな機能を作成するとき、表示部分、管理部分、データの関連付けなどごとにブランチを分けて作業することが多いでしょう。

その時、「管理部分作成で作ったメソッド持ってきたい」とか「別ブランチで定義した配列が必要になった」みたいなことがよく起きます。

そのような際にcherry-pickを使うことで、コミットログの整合性を取りながら特定の変更を持ってくることが出来ます。

# 使い方

コマンドの基本は以下の感じです。

```bash
$ git cherry-pick コミットのハッシュ値
```

実際に使用する際は、以下のように`$ git log`などで確認してから使うのが一般的かと思います。

```bash:使用例
$ git log
commit 645b44d687dea267b8b15657fb91fd7bc88f8bca (HEAD -> tsuboya-20200608, origin/tsuboya-20200608)
Author: TsuboyaTaiki <tsuboyataiki@taiki-mac.local>
Date:   Mon Jun 8 17:13:50 2020 +0900

    パスワードのバリデーション修正

　（　.. 省 略 ..　）

$ git switch tsuboya-20200607
$ git cherry-pick 645b44d687dea267b8b15657fb91fd7bc88f8bca
[tsuboya-20200607 d719a90] パスワードのバリデーション修正
 Author: TsuboyaTaiki <tsuboyataiki@taiki-mac.local>
 Date: Mon Jun 8 17:13:50 2020 +0900
 1 file changed, 1 insertion(+), 1 deletion(-)
```

↑で、別ブランチでのコミットを持ってこれました。

ここで`$ git log`で変更が反映されているか確認すると...

```bash
$ git log
commit d719a90b3667b1e866ea3938f1ca400782e2d133 (HEAD -> tsuboya-20200607)
Author: TsuboyaTaiki <tsuboyataiki@taiki-mac.local>
Date:   Mon Jun 8 17:13:50 2020 +0900

    パスワードのバリデーション修正
```

うまく行っていれば、このようにコミットログで確認できます。

# コンフリクトが起きた場合

上記で紹介した例はあくまでコンフリクト（各ブランチの変更内容の競合）が起きてない場合に過ぎません。

ただ実際のところ体感半分くらいの確率でコンフリクトは起きるのでその場合の対処も紹介します。



```bash:実際にコンフリクトを起こした例
$ git cherry-pick a37ed09019cc569c5d95e253d5f39729f7e2b2b5
Auto-merging app/models/account.rb
CONFLICT (content): Merge conflict in app/models/account.rb
error: could not apply a37ed09... change coment BBB
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
$
```

実際にコンフリクトが起きると、このようにコンフリクトが起きている箇所や、該当する編集内容が表示されます。また、先ほどうまく行った場合と違ってこの時点ではコミットはまだ反映されていません。

では、エディタで該当箇所を見てみると...

![スクリーンショット 2020-08-23 22.22.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305969/ba0a6e4c-b659-6327-79fc-602c22218ac0.png)

`Current Change`と`Incoming Change`という形で分かれている状態になっていますね。

`Current Change`を反映したい場合は、下の画像の赤丸の「Accept Current Change」を選択し、`Incoming Change`の場合は青丸の方を選択すると、選択した方が反映されます（僕の場合はVSCodeで操作しています）。

![スクリーンショット 2020-08-23 22.29.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305969/98e4e410-5126-6be0-060c-af8da8a1da8d.png)

あとは忘れずに`$ git add`と`$ git commit`をして終了です。

もしcherry-pickの操作をなかったことにしたい場合は、以下のようにHEADとステージングをリセットすれば大丈夫です（まだコミットしてない変更内容も消えてしまうので注意）。

```bash:
$ git reset HEAD
$ git restore .     # コンフリクトが起きたファイルだけでもOK
```

※このやり方は僕が試しただけなのでもっと適したやり方があれば教えていただけると幸いです。
[Flutter] ProviderパターンでTextFieldのイベントを扱う

## 2021/1/11 追記
[こちらの記事](https://qiita.com/Urotea/items/43b400de2b621e132b86#_reference-498971797776aad85fe8)が本記事の改善版になりますので参考にしてください。

## Statelessのように使いたい
TextFieldウィジェットのイベント監視にはControllerを使って，Statefulにする必要があります。
ProviderパターンではできるだけStatefulWidgetを使わないようにしたいので，下記のようにしてGestureDetectorのonTapのように扱えるようにしました。
どなたかのお力になれば。。

```dart
class EventListeningTextField extends StatefulWidget {
  EventListeningTextField({
    this.onChanged,
    this.onEditingCompleted,
    this.initialValue,
    this.inputDecoration,
  });
  Function(String) onChanged;
  Function(String) onEditingCompleted;
  String initialValue = '';
  InputDecoration inputDecoration;

  @override
  _EventListeningTextFieldState createState() =>
      _EventListeningTextFieldState(onChanged, onEditingCompleted, initialValue, inputDecoration);
}

class _EventListeningTextFieldState extends State<EventListeningTextField> {
  _EventListeningTextFieldState(
    this.onChanged,
    this.onEditingCompleted,
    this.initialValue,
    this.inputDecoration,
  );

  Function(String) onChanged;
  Function(String) onEditingCompleted;
  String initialValue = '';
  InputDecoration inputDecoration;
  final _textEditingController = TextEditingController();

  @override
  void initState() {
    _textEditingController.text = initialValue;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: TextField(
        controller: _textEditingController,
        onChanged: onChanged,
        onEditingComplete: () {
          onEditingCompleted(_textEditingController.text);
        },
        onSubmitted: (String value) {
          FocusScope.of(context).unfocus(); // キーボードを閉じる
        },
        decoration: inputDecoration,
      ),
    );
  }
}
```
AtCoderで青色になるまでに「やらなかったこと」を書いていく

# はじめに

先日の [AtCoder Beginner Contest 176](https://atcoder.jp/users/ryochansq/history/share/abc176) で 青色 になりました。

https://atcoder.jp/users/ryochansq

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">目標だった 青 になれました！<br>ありがとうございます！！<br><br>ryochansqさんのAtCoder Beginner Contest 176での成績：515位<br>パフォーマンス：1791相当<br>レーティング：1596→1618 (+22) :)<br>Highestを更新し、2 級になりました！<a href="https://twitter.com/hashtag/AtCoder?src=hash&amp;ref_src=twsrc%5Etfw">#AtCoder</a> <a href="https://twitter.com/hashtag/ABC176?src=hash&amp;ref_src=twsrc%5Etfw">#ABC176</a> <a href="https://t.co/gStopYkGid">https://t.co/gStopYkGid</a> <a href="https://t.co/4YNNnXuWUz">pic.twitter.com/4YNNnXuWUz</a></p>&mdash; 量産型リョウさん (@ryochansq) <a href="https://twitter.com/ryochansq/status/1297174953830150145?ref_src=twsrc%5Etfw">August 22, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


「〇色になるまでにやったこと」という記事はたくさんありますので、この記事では逆に「**やらなかったこと**」「**やらないように心掛けていたこと**」を簡単に書きます。

## スペック

- 社会人5年目、フロントエンドエンジニア2年目
- 大学院卒。専攻は理系だが情報系ではない
- 趣味で[iOSアプリ](https://appsto.re/jp/zvX7fb.i)を個人開発する程度にはプログラミングが好き
- 幼い頃に「数の悪魔」、学生時代に「数学ガール」を好んで読む程度には数学が好き

# やらなかったこと

## 写経AC、なんとなくの解説AC
他人のコードをただ丸写ししたり、解説をなんとなく読んで分かった気になってACしたり、ということはしないように心掛けました。
私にとって過去問をACすることは目的ではなく、「実力をつけてレートを上げること」が目的です。
もちろん問題が解けなかったら解説ACはしますが、次に似たような問題に遭遇した時には解けるようにする、ということを意識して解説ACをします。
具体的には、

- なぜこの解法で解けるのか
- なぜ自分はこの解法を思いつけなかったか
- どうすれば自分はこの解法を思いつけるようになるか
- 今回の考え方は他の問題にも応用できそうか

といったことを考えるようにしています。

## 〇〇埋め
ABCのC問題を全問解くとか、緑Diffを埋めるとか、そういったことは特にしませんでした。
私にとって何かを埋めることは目的ではなく、「実力をつけてレートを上げること」が目的です。
私が埋めること自体にそれほどモチベーションを感じないタイプの人間だというのもありますし、埋めることが目的になってしまうと、上述の写経ACやなんとなく解説ACをやってしまう恐れもあるためです。
もちろん、埋めることを目標にするとモチベーションが上がる！というタイプの方なら、やってもいい精進の方法だとは思います。

## ストリークを繋ぐこと
毎日必ず１問以上解いてストリークを繋ぐ、ということはしませんでした。
私にとってストリークを伸ばすことは目的ではなく、「実力をつけてレートを上げること」が目的です。
私がストリークを伸ばすこと自体にそれほどモチベーションを感じないタイプの人間だというのもありますし、ストリークを繋ぐことが目的になってしまうと、上述の写経ACやなんとなく解説ACをやってしまう恐れもあるためです。
また、ストリークを頑張って伸ばしていると、ストリークが途切れた時が恐いです。私は長く続いたログインボーナスが途切れるとやる気を失うタイプの人間なので、むしろ**ストリークは定期的に切る**ようにしています。
もちろん、ストリークを伸ばしているとモチベーションが上がる！というタイプの方なら、やってもいい精進の方法だとは思います。

## 他人の色変記事を鵜呑みにすること
競プロerには様々な性格・環境・レベル感の人がいます。性格や環境等が異なれば、適した精進方法というのも異なると思います。なので、他人の色変記事を読んで参考にすることはありますが、鵜呑みにはしないようにしています。

# おわりに
最後まで読んで頂きありがとうございました。この記事の内容も鵜呑みにせず、皆さんそれぞれに合った精進方法で、一緒に競プロライフを楽しめたらと思います！

次は黄色目指して<ruby>顔笑<rp>（</rp><rt>がんば</rt><rp>）</rp></ruby>ります！
githubのPull Requestをコマンド一発で作成する！

# 背景
https://github.com/newsdict/newsdict.io
や
https://github.com/newsdict/docker_rails
にPRするのが**めんどくさい**のでコマンド一つで済ませたい

# 前提
- PR先がいつも同一
- githubを使ってる
- レポジトリを集めたディレクトリがある(prsコマンドのみ)

# ディレクトリ構成
```
+ repositories
  + newsdict.io
  + docker_rails
  + ・・・・
```

# 作成するコマンド

|コマンド|パス|実行する場所|説明|
|---|---|--|---|
|create-pr|~/bin/create-pr|対象レポジトリ配下|直前のコミットログ名でPRを作成する|
|list-pr|~/bin/list-pr|対象レポジトリ配下|PR一覧を見る|
|prs|~/bin/prs|対象レポジトリの上層ディレクトリ|すべてのPRリストを出す|

# コマンドを置くディレクトリを作る
```
$ mkdir ~/bin
```

# create-pr
```
$ cat << EOF > ~/bin/create-pr
#!/bin/bash
pr_destination=newsdict

if [ "\$(git status 2> /dev/null)" != "" ];then
        project_name=\$(basename \$(pwd))
        git_message=(\$(git log -n 1 --oneline | cut -f2- -d' ' | sed 's/ /_/g'))

        hub pull-request -b \$pr_destination/\$project_name:master -m "\${git_message[@]}"
else
        echo "[ERROR] NOT UNDER GIT" >&2
fi
EOF
$ chmod +x ~/bin/create-pr
```

# list-pr
```
$ cat << EOF > ~/bin/list-pr
#!/bin/bash
pr_destination=newsdict
pr_src=yubele

if [ -f .git/config ];then 
        sed -i "s/git@github.com:\$pr_src/git@github.com:\$pr_destination/" .git/config
        hub pr list -f"%pC%i%Creset %t | %U%n"
        sed -i "s/git@github.com:\$pr_destination/git@github.com:\$pr_src/" .git/config
else
        echo "[ERROR] NOT GIT TOP DIR" >&2
fi
EOF
$ chmod +x ~/bin/list-pr
```

# prs
```
$ cat << EOF > ~/bin/prs
#!/bin/bash
pushd ~/environment
for i in \$(ls);do 
        if [ -d $i ];then
                echo "####" $i
                pushd \$i >/dev/null
                list-pr 2>/dev/null
                popd >/dev/null
        fi
done
EOF
$ chmod +x ~/bin/prs
```

# 最後に~/binのパスを通す

```
$ echo 'PATH=$PATH:~/bin' >> ~/.bashrc
```
Spyderのアップデート方法

Spyderを最新版にアップデートするために、Anacondaの全パッケージをアップデートしてみたのですが
Spyderは更新されていなかったため、
おかしいなと思いネットで調べてみました。
以下が今回アップデートに成功したやり方です！！

➀Anaconda promptを開く
➁"conda install spyder=4.1.4"　と入力してEnter　  ※4.1.4 = インストールしたいバージョンを入れる
➂このメッセージが表示されたら"y"を入力してEnter
　　![spyder-update06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696659/9e2d0494-4f65-d68b-f43d-bb24c1a4dd8c.jpeg)
➃アップデートが開始されます

以上です！
docker環境で遅いbundle installを劇的に早くする

## 目的
newsdict.io(docker環境上のrails)でbundle installの時間を早めたい

## 方法
- あまりバージョン変更がない最も重たいgemをベースのdocker imageに入れて置きgemを流用できるようにしておく
- nokogiriを使っていたので、[--use-system-libraries]を使う
- bundle install を並列で実行する

## 実際のコード

#### - あまりバージョン変更がない最も重たいgemをベースのdocker imageに入れて置きgemを流用できるようにしておく

https://github.com/newsdict/docker_rails/blob/master/Dockerfile#L70

#### - ベースとして使ったdocker image
https://hub.docker.com/repository/docker/newsdict/rails

#### - nokogiriを使っていたので、[--use-system-libraries]を使う

https://github.com/yubele/newsdict.io/blob/9747c9a4d0a69f8f251f1deb9d6b776856281a2b/Dockerfile#L25

#### - bundle install を並列で実行する

https://github.com/yubele/newsdict.io/blob/9747c9a4d0a69f8f251f1deb9d6b776856281a2b/Dockerfile#L24

## Q&A

### bundle installした結果をdocker imageのすればいいのでは？
Gemfileを頻繁に書き換える可能性があるため
[Github Actions] test後にsuccess or failureで実行するコマンドを変える

# 背景
https://newsdict.io でgithub actionsを使ったテスト後にslackにテスト結果を通知させたい

# 実装方法
- stepsの最後に[rtCamp/action-slack-notify](http://https://github.com/rtCamp/action-slack-notify "rtCamp/action-slack-notify")を入れて、ビルドが終わったら通知を実行されるようにする
- actionsの[if conditional](http://https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsif "if conditional")を使って条件分岐させる
- forkしたレポジトリからのPullRequest時には、Github secretが使えないのでmasterにpushしたときのみ、slack通知を発火するようにしている。

# 完成コード
https://github.com/newsdict/newsdict.io/blob/ee13b371e0d6af6df955b612531f51562fd42e27/.github/workflows/UnitTest.yml

# キーポイント
- slack notifyの個所が2つある
ビルドが通った場合と失敗した場合でビルドを分けている、{{ job.status }}を使えばビルド結果は判断可能だが、色分けやメッセージを変更する場合はこのやり方が妥当でしょう。
- if conditionalで[env.SLACK_WEBHOOK != null ]を行っている
forkしたレポジトリからPull Requestを送るときはPR先のsecretを読み取ることができないため、slack notifyでビルドエラーになっていしまう。本末転倒なのでsecretsが取れた場合のみslock notifyを発火するようにしている
- pullrequest, master両方トリガーにしているため、forkしたレポジトリからのpull request時にもPR元にsecretsさえ登録していれば、slack notifyが発火する（ややこしいが、PR先、PR元双方のactionsが動作することによってこれは実現される）
Pandas備忘録

# 概要

Pandasで個人的に覚えておきたいこと一覧
随時更新します

# 課題一覧

### 1. カラムが複数行存在する際に、2行目をカラム名とする方法
### 2. 複数行のカラムの読み込み
### 3. indexの重複削除
### 4. 行の入れ替え
### 5. 時系列データの補間

# 方法

### 1・2用のサンプルcsv

|Japan|||||America|||||
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|month|start|end|worktime|memo|month|start|end|worktime|memo|
|20200408|900|1730|8.5|hello|20200408|900|1730|8.5|hello|


### 1. カラムが複数行存在する際に、2行目をカラム名とする方法
#### ①
```python
df.columns=df.loc[0,:]
df.drop(0,axis=0)
```
#### ②(推奨)
```python
df = pd.read_csv("./excel-sample1.csv", skiprows=1)
```

### 2. 複数行のカラムの読み込み
```python
df = pd.read_csv("./excel-sample1.csv", header=[0,1])
```

#### コラム
- **複数行カラムの扱い方**

```python
print(df.loc[:,'Unnamed: 1_level_0'])
df.loc[:,('Unnamed: 1_level_0','start')]
# ずれるとダメ
df.loc[:,('Unnamed: 1_level_0','end')]
```

### 3・4用のサンプルcsv

|a|b|c|
|:-:|:-:|:-:|
|1|4|NaN|
|2|5|NaN|
|3|6|NaN|
|1|4|NaN|
|2|3|4.0|

### 3. indexの重複削除

```python
df_sample.loc[~df_sample.index.duplicated(keep='first')]
```

- 先頭を残すならfirst、後ろを残すならlast

### 4. 行の入れ替え

```python
df_sample.iloc[[0,1,4,2,3],:]
```

- この場合、indexは0, 1, 1, 2, NaNの順

### 5用のサンプルcsv

|datetime|id|sample1|sample2|
|:-:|:-:|:-:|:-:|
|2020/10/14 15:00|4|132|k|
|2020/10/14 15:15|4|144|l|
|2020/10/14 15:30|5|156|n|
|2020/10/14 15:45|5|168|m|
|2020/10/14 16:00|5|180|abc|
|2020/10/14 16:15|6|192|def|
|2020/10/14 16:30|6|204|ghi|
|2020/10/24 13:45|6|205|fgh|
|2020/10/25 13:45|6|206|fgd|
|2020/10/26 13:45|6|207|asd|


### 5. 時系列データの補間

```python
df["datetime"] = pd.to_datetime(df["datetime"]) # 一応
df2 = df.set_index('datetime') 
df3 = df2.resample('15T').mean()
df3["datetime"] = df3.index # インデックスから列に戻す(一応)
df3.reset_index(drop = True, inplace=True) # インデックスを振る(一応)
```

- 時刻を補間することで、元々のデータに存在しない時刻の線プロット補間を回避できる
【PHP】URLのリストをまとめてDLする

とりあえず備忘録として

URLのリストをまとめてDLできるようなものを作成していく。
例えば以下のようなテキストファイルにURLをつらつらと書いていってそれらをまとめてDLできる。

```：list.txt
https://.....
https://.....
https://.....
https://.....
```

#DL保存先ディレクトリを作成
ディレクトリの名前をURLリストファイルの名前と同じものとした。
コマンドライン引数でURLリストファイルのパスを受け取って、そこから名前を抽出する。

以下は保存用ディレクトリがなかったら作成するコード

```php5
$dirName = basename($argv[1], ".txt");
$dir = FILE . 'src/' . $dirName;
if (!file_exists($dir)) {
    mkdir($dir);
}
```
##basename
を使うことでパスからファイル名の抽出が簡単になる。
第1引数はパスで、第2引数へ拡張子を指定してやるとファイル名のみを抽出できる。


#コマンドライン引数でURLリストテキストを読み込む
URLが膨大になることを考えて読み込みは1行ずつ行い、URLリストファイルを配列にする

以下はその雛形

```php5
$file = fopen($argv[1], "r");
if ($file) {
    while ($line = fgets($file)) {
       //処理
    }
}
fclose($file);
```
参考：https://webkaru.net/php/function-fgets/

#ダウンロード
forで回していくがループの始まりを工夫した

```php5
for ($i = $argv[2] ?? 0; $i < count($array); $i++) {
//処理
}
```
`$i`の初期化を`$i = $argv[2] ?? 0;`のようにしている。
これは`$argv[2]`あればそれを代入して、そうでなければ0を代入するというもの。これによりDLしたい開始の場所を指定できる。


##curl
基本的な書き方しかしていないが一応載せます。

```php5
    $options = array(
        CURLOPT_URL =>  $url,
        CURLOPT_RETURNTRANSFER => true, 
    );

    $ch = curl_init();

    //オプション
    curl_setopt_array($ch, $options);

    $html =  curl_exec($ch);
    file_put_contents($filepath, $html);
    curl_close($ch); 
```
`CURLOPT_RETURNTRANSFER => true`を指定しないと保存がうまく行かなかったような、、、、

#実行
```
$php dl.php URLリストファイルのパス [オプション]
```
GitHub Pagesを初めて使ってみた。

#GitHub Pagesを使って『まいやんありがとう。』サイトを立ち上げてみる。

まずは新しいリポジトリ[outk/maiyanarigatou](https://github.com/outk/maiyanarigatou)を作成。
![スクリーンショット 2020-08-23 22.03.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458877/590f89b8-f95c-8aa3-f52f-9695d860c53b.png)

続いて、index.htmlファイルを新規作成し、内容を記述してcommit!
![スクリーンショット 2020-08-23 22.07.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458877/75c0f434-254c-05df-1154-740dfbc355cf.png)

最後に、Settings->GitHub PagesのSourceをmasterに設定すれば、
![スクリーンショット 2020-08-23 22.10.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458877/fe0aa24b-f28d-54dd-c33d-7c7a0ce86efe.png)

ブラウザで[https://outk.github.io/maiyanarigatou/](https://outk.github.io/maiyanarigatou/)にアクセスすると、先ほどのindex.htmlの内容が表示されました。
![スクリーンショット 2020-08-23 22.12.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458877/80e2fba5-9cf3-ff24-cb08-ca07e83ed6dc.png)

とても簡単で、プロジェクトごとに作成できるので今後も利用していきたいですね。
OCaml と Dune で ppx の前処理を展開した後のソースコードを得る

OCaml の ppx で構文拡張されたコードを、前処理・展開したソースコードを得る方法について。

OCaml は ppx という構文拡張で多くの有用な機能を実現しています。例えば [ppx_deriving](https://github.com/ocaml-ppx/ppx_deriving) など。 新しい ppx を使う前に、どのようなコードを生成するか見ておきたくなることがあります。また ppx を開発していると、型が合わない構文木を生成してしまうことがたまにあり、デバッグのため生成された構文木をチェックする必要があります。


この記事の内容は [OCaml 日本語 Slack](https://slackin-ocaml-jp.herokuapp.com/) で [@camloeba](https://twitter.com/camloeba) さんと [@_smorimoto](https://twitter.com/_smorimoto) さんから教わった内容をベースにしています。ありがとうございます！

## 方法1: ppxfind

最も簡単なのは、 [ppxfind](https://github.com/jeremiedimino/ppxfind) です。 findlib 経由でインストールされた ppx (ほとんどのppxはそうなっているはず) について、コマンド一発で展開後のソースが得られます。 `opam install ppxfind` でインストールしたのち、

```
> ppxfind -help
ppxfind [options] ppx1,ppx2,... [ppx-options] [file]
  -legacy  Use the legacy ppx system
  -debug   Enable debug messages
  -help    Display this list of options
  --help   Display this list of options
```

でヘルプが見れ、この通りに使えばよいです。 例えば `ppx_deriving` を適用したい場合は、 

```sh
> ppxfind ppx_deriving foobar.ml
```

のようにします。


## 方法2: X.pp.ml を -dsource で変換

dune を使っている場合は `_build/default/path/to/XX.pp.ml` に前処理後のソースコードがバイナリ表現で生成されています。 `ocamlc` の undocumented な機能である `-dsource` を使えば、このファイルをプレーンテキストに変換できます。

```sh
> ocamlc -dsource _build/default/foobar.pp.ml -stop-after parsing
```

## 方法3: ocamlmerlin を使う

dune を使っているなら [ocamlmerlin](https://github.com/ocaml/merlin) も使っていると思います。その場合、 `.merlin` にプリプロセッサの情報が残っているので、それを利用して展開することもできます：

```sh
FILE=path/to/file.ml
> cat $FILE | ocamlmerlin single dump -what ppxed-source -filename $FILE |jq -r '.value'
```
LaravelをRDSと繋ぐ

# TL;DR

- RDSを構築して、RDS情報をenvs/配下の値を適切に埋める
- envファイルに設定したい文字列に#がある時はダブルクオーテーションで括る

---

# RDS構築

一連の流れを説明とともに記述します。詳しいことは載っていないので注意です。
また、今回はRDSをパブリックサブネットに配置します。
（外部から繋ぎたいため）

本来はVPC内のプライベートサブネットに置き、
EC2などからしか接続させないようにするのがオーソドックスかと思います。

1. VPC作成
2. VPC > インターネットゲートウェイからインターネットゲートウェイを作成し、VPCにアタッチ
3. VPC > ルートテーブルから、VPCのルートテーブルにサブネットの関連づけをする
2. VPC > サブネットからパブリックサブネットを2つ作る (※1)
3. EC2 > セキュリティグループからRDS用のセキュリティグループ作成。<br />今回はパブリックサブネットに置くので、外部（XServer）のIPをインバウンドとして設定
4. RDS > サブネットグループを先に作成
    5. 先ほどつくった2つのサブネットを選択
6. RDS > パラメータグループを先に作成
    7. デフォルトであるものを適用させないくらいの文脈で作成
7. RDS > オプショングループを先に作成
    8. デフォルトであるものを適用させないくらいの文脈で作成
4. RDSからデータベースの作成 (かいつまんで状況↓)
    5. DBインスタンスサイズ
        6. テスト環境なのでバースト可能クラスのt2.micro選択
    7. ストレージ
        8. ストレージタイプ：汎用
        9. ストレージの自動スケーリングは無効に（テスト環境なので）
    9. 可用性と耐久性
        10. スタンバイインスタンスを作成しないでください
            11. テスト環境なので。2つ作ったサブネットの1つだけ使う感じ
    12. 接続
        13. 先ほどつくったVPC
        14. サブネットグループ
            15. 先ほど作ったもの
        16. パブリックアクセス可能
            17. あり。
            18. 今回、外部から接続させるため。プライベートサブネット上であれば「なし」
        19. セキュリティグループ
            20. 先ほど作ったもの
        21. アベイラビリティゾーン
            22. 2つのサブネットのどちらか好きな方
    23. データベース認証
        24. パスワード認証
    25. 追加設定
        26. DBパラメータグループ
            27. 先ほど作ったもの
        28. オプショングループ
            29. 先ほど作ったもの
        30. 自動バックアップの有効化。30日くらい
        32. モニタリングは無効化
        33. 削除保護の有効化
    34. データベースの作成！ (※2)


## ※1. RDSのサブネットを複数持たせる件について

RDSはマルチAZ、冗長化が簡単にできるように、デフォルトで複数のサブネットを用意したグループを作らせる

## ※2. Cannot create a publicly accessible DBInstance. The specified VPC does not support DNS resolution

↓ありがとうございます🙏🙏🙏

[Cannot create a RDS Readreplicaが作成できない。(publicly accessible DBInstance because customer VPC does not support DNS resolution and/or hostnames. )](https://qiita.com/okuda_h/items/73da63d144a65590bea6)

# Lalavelへの記述

envs/配下に適切に情報を記述する。

- DB_HOST
    - 接続とセキュリティ > エンドポイントを記述
    - XXXX.YYYYYYY.ZZZZZZ.rds.amazonaws.com なやつ
- DB_DATABASE
    - データベース名
    - Sequel ProからRDSに接続してデータベース作成してそれを書いた
- DB_USERNAME
    - とりえあずさっき作成したユーザを記述
- DB_PASSWORD
    - さっき作成したユーザのパスワードを記述

↑の設定後、以下を実行

```shell
php artisan config:clear
php artisan cache:clear
```

## 設定したenvがうまく反映されない

```
SQLSTATE[HY000] [1045] Access denied for user 'XXX'@'YYYYY' (using password: YES) (SQL: delete from `cache`)
```

がでまくった。usernameは合ってそうだが、host名(DB_HOSTに設定したRDSのエンドポイント)が正しくなさそうな感じになる。

結論としては **passwordにシャープが入っていた** ため。
コメント化されてしまい、うまくenvファイルがパースできなかったみたい。
（host名が間違っているのかと思ってかなりの時間を割いて調べてしまった😭）

envのパスワード部分を以下のようにダブルクオーテーションで括ることで解決。

```
DB_PASSWORD="XXXXXX"
```

---

できた🥳🥳🥳
GoogleスプレッドシートとGoogle Data PortalでCovid-19のダッシュボードを10分で作る

厚労省が公開している新型コロナ陽性者数のダッシュボードを10分で作成します。
GoogleスプレッドシートやGoogle DataPortalを活用すると、ブラウザだけで無料でオープンデータを活用したダッシュボードを簡単に作成できます。

#概要
- 元データ
    - 厚生労働省オープデータ
        - https://www.mhlw.go.jp/stf/covid-19/open-data.html
    - 陽性者数データ（CSV）
        - https://www.mhlw.go.jp/content/pcr_positive_daily.csv
- 利用するツール
    - Googleスプレッドシート
    - Google Data Portal
- 手順の概要
    - GoogleスプレッドシートのIMPORTDATA関数で厚労省のオープンデータを読み込む
    - Googleスプレッドシートで移動平均を算出
    - Googleスプレッドシートのデータを Data Portal でダッシュボード化する

#手順１：厚労省のオープンデータをGoogle Sheetsに読み込む

Googleスプレッドシートにアクセスし、新しいシートを作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/a77a9523-21d7-523a-777a-46062da686ac.png)

IMPORTDATA関数でデータをインポートする。URLはダブルクォートで囲む。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/4988d2ac-107c-7f2a-0c49-93aed730c8b0.png)

インポートされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/2c6cb603-8e5d-bd25-8614-f708c99c1974.png)

#手順２：Google Sheets で移動平均を算出

日付の書式を変更するついでに、7日間移動平均も算出してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/35f99bf4-bb66-7793-e89b-97c7a0d3b85f.png)

#手順３：Google Sheets のデータを Data Portal でダッシュボード化する

Google DataPortalにアクセスし、新しいレポートを作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/4efd249f-af8c-b54b-5708-bd38877ea633.png)

データソースとしてGoogleスプレッドシートを選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/0e05c68b-8d31-1d3e-36ef-f687721ea6e3.png)

先程、手順１で作成したシートを選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/c64c3988-23f6-deeb-46e9-e107b4e1f25a.png)

グラフを作成する。時系列グラフを選択し、ディメンションには日付、指標にPCR検査要請者数、7日移動平均を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/69278807-91cd-8aba-567f-4c5b9fe1bed3.png)

完成！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/c8ce0b97-b389-9be5-d63c-59798b984984.png)

リロードボタンを押すと、自動で最新化されます。便利ですね。

#補足：項目を追加する

後から項目を追加したくなった場合には、Googleスプレッドシート上に項目を追加して、DataPortalでデータソースを読み込み直すことで、項目を追加することができます。

ここでは、週単位での集計を可能にするために、WEEKNUM関数で週番号を追加、曜日ごとの感染者数を集計するためにWEEKDAY関数で曜日を取得。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/31e2a7c0-5331-7eb4-06c8-75b58f130365.png)

DataPortalのデータソースの左側の編集アイコン（鉛筆のようなアイコン）を押すと、データソースの情報が表示されるので、「接続を編集」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/866a4748-6370-f683-7c40-33d5346fe9b1.png)

「再接続」をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/69b75df0-a4aa-0f53-2553-65e08ff78d80.png)

そうすると、変更された項目が反映される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/c6a155e1-5fc7-945d-cb47-49009af6a719.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/7d5a40cb-5dd9-bb20-9b3f-faa039a9160f.png)

追加した項目を使ったグラフが作れるようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206394/ee5c9e9f-a24e-7bbc-486a-96bb90cbd800.png)

簡単ですね。オープンデータの活用とか、BIツールの利用はハードルが高いと思っている方が多いと思うのですが、いまどきはこんなに簡単です。
【chrome拡張機能】リクエストをカスタマイズ


#chrome.webRequest.onBeforeSendHeaders
これを使うことでリクエスト前に処理が走る。
##準備
これを使うにはイベントページを無効にする必要がある。
manifest.jsonに`“persistent”: false`の記載があるとイベントページとなるため、この記述を取っ払う。

しかしこれを取っ払うと常に裏でbackground.jsが動き続けることになってメモリを占領してしてしまうことに注意

イベントページの使用は推奨されている。
##構文
```javascript:構文
chrome.webRequest.onBeforeRequest.addListener(callback, filter, opt_extraInfoSpec);
```


リクエスト時のURLを取得
[Chrome 拡張機能でリクエストヘッダをカスタマイズする方法](https://r17n.page/2019/11/23/chrome-extension-customize-http-request-header/)
公式
https://developers.chrome.com/extensions/webRequest#event-onBeforeRequest

##calback
コールバック引数`detail`でリクエストが走るURLを覗くことができる。
URLを覗くにはこのようにする。

```javascript
details.url
```
##filter
度のURLのリクエストで走らせるかのフィルタ
またtypeも指定できる

これをオブジェクト形式にして引数として渡す。

以下はすべてのURLでtypeがxmlhttprequestのものを監視する設定。

```javascript
{
  urls: ["<all_urls>"],
  types: ["xmlhttprequest"]
}
```


#javascriptでテキストファイルをダウンロードさせる
メモリ上にDLさせてからファイルとして保存する
参考：https://www.atmarkit.co.jp/ait/articles/1603/30/news026.html

今回はfetchでいじっていきたいから、fetchでのBlobの使い方を調べる
参考：https://developer.mozilla.org/ja/docs/Web/API/Body/blob



ネット上のファイルを読み込んで操作したい
https://www.catch.jp/wiki/index.php?javascript_file

```javascript
let l
fetch('https://dl.dropboxusercontent.com/s/jwqmw6s0846qe6c/code.js')
  .then(response => {
    console.log(response)
    response.text().then(text=>l=text)
    
  })
```
これでlにテキストが入る

```javascript
fetch('https://dl.dropboxusercontent.com/s/jwqmw6s0846qe6c/code.js')
  .then(response => {
    console.log(response)
    response.blob()
    console.log(response.blob())
  })
  .then(blob => {
    console.log(blob)
    var objectURL =blob;
    console.log(objectURL)
    // リンク（<a>要素）を生成し、JavaScriptからクリックする
    var link = document.createElement("a");
    document.body.appendChild(link);
    link.href = objectURL;
    link.download = 'filename.js';
    link.click();
    document.body.removeChild(link);
  });
```
これがエラーになる

```javascript
fetch('https://dl.dropboxusercontent.com/s/jwqmw6s0846qe6c/code.js')
  .then(response => {
    console.log(response)
    let b=response.blob()
    console.log(b)
    return b
  })
  .then(blob => {
    console.log(blob)
    var objectURL =URL.createObjectURL(blob);
    console.log(objectURL)
    // リンク（<a>要素）を生成し、JavaScriptからクリックする
    var link = document.createElement("a");
    document.body.appendChild(link);
    link.href = objectURL;
    link.download = 'filename';
    link.click();
    document.body.removeChild(link);
  });
```
動いた


テキストをDLさせる
参考：https://helloworld-blog.tech/javascript/javascript%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E6%A9%9F%E8%83%BD%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B

テキストファイルをDLさせるにはBlobクラスをインスタンス化させる

#色々やったけど
結局以下の形に収束した

##Blobを生成
```javascript
 var blob = new Blob([text], {
    "type": "text/plain"
  });
```
今回はテキストなのでtypeをそのようにする。

##クリックさせる
```javascript
  let link = document.createElement('a')
  link.href = URL.createObjectURL(blob)
  link.download = filename + '.m3u8'
  link.click()
```
後は`URL.createObjectURL`でURLを生成してそれをクリックさせる。
ここまでの一連の流れで変数textに入ったっ文字列をfilenameに格納した名前でDLできる。