OmniAICreator/Qiita-1.07M huggingface dataset:
kotlinでFirebaseAuthを使用してアカウント作成　サインイン

#はじめに
現在kotlinでチャットアプリを作成中でアカウント作成機能とログイン機能などをつけるためにFireBaseを使用しています。
以下の投稿ではAndroidプロジェクトにFirebaseを追加する方法について記載しました。
https://qiita.com/Oyama-Kohei/items/02e762dcd3203fee2193

今回の記事では前回の続きで実際にアカウントの作成機能　ログイン機能をどのように追加するのかについて、相変わらずのメモクオリティで記載していきます。
自分と同じ駆け出しAndroidエンジニアで勉強でアプリを作ってみたいなという人は是非参考にしていただければと思います。

#開発環境
・使用言語：kotlin
・AndroidStudio 4.1.2
・Android Emulator (自分はm1 Macでの開発をしているので以下のものをダウンロードして使用)
https://github.com/google/android-emulator-m1-preview

#アカウントの作成(メールアドレス/パスワード)
今回の作成する方式はメールアドレスとパスワードによるアカウント作成方法になります。
Firebaseには他にもGoogle認証を使用するものや電話番号を使用した認証などがありますが、自分はやったことがないので割愛します。（いつかこれもやってみたい）

上であげた別の認証については以下の資料を見てみてください。（安心と信頼の公式ドキュメント）
電話番号
https://firebase.google.com/docs/auth/android/phone-auth?hl=ja

Google認証
https://firebase.google.com/docs/auth/android/google-signin?hl=ja

アカウント作成の方法はズバリ以下です。

```kotlin
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password)

    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            //アカウント作成成功
            Log.d(TAG, "User email address updated.")
        }
    }
    .addOnFailureListener {
        //アカウント作成失敗
    }
```
こうして作成したアカウントはFirebase上のAuththenticationのusersに反映されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077515/9baf658a-982a-f883-46ed-1fc1735efdbf.png)

#作成したアカウントでログインする

サインインの方法についても以下です。簡単ですね。
同様にメールアドレスとパスワードを渡して認証が通ればサインイン完了です。

```kotlin
FirebaseAuth.getInstance().signInWithEmailAndPassword(email, password)
    .addOnCompleteListener {
        //アカウント作成成功
          Log.d(TAG, "User email address updated.")
        }
    }
    .addOnFailureListener {
        //アカウント作成失敗
    }
```

ちなみにサインアウトは以下のような感じでできます。もっと簡単ですね。

```kotlin
FirebaseAuth.getInstance().signOut()
```

#まとめ
Firebaseは何かと使い勝手が良くて、フロント勉強中かつバックの知識ほぼ無しな自分でもとっかかりやすかったです。
ほんとはバックのことも勉強したいんですけどね、今はフロントに集中・・・
量子ビットの測定による状態変化

#はじめに
量子コンピュータの本には次のようなことが書いてある。

> 量子ビットを測定すると、量子ビットの状態は測定基底のいずれかの固有状態に変化する。

IBM QuantumのCircuit Composerを触っていたら測定アイコンを2つ置くことができたので、測定によって状態が変わるのか試してみた。
※あまり意味がないネタです。


#方針
量子ビット$|\psi\rangle$をZ基底の固有状態$|0\rangle, |1\rangle$の線形結合で表す。
$|\psi\rangle = \alpha|0\rangle + \beta|1\rangle, |\alpha|^2 + |\beta|^2 = 1$

$\alpha = 1(\beta = 0)$の場合、$|\psi\rangle$はZ基底の固有状態$|0\rangle$になっている。
これをZ基底で測定すると古典ビットの0が得られ、$|\psi\rangle$は$|0\rangle$のままになっている。
この状態で再度測定しても同じ結果になる。

今回は状態が変化するかを確認したいので、最初に$|\psi\rangle$を重ね合わせ状態にしておいて、
同じ量子ビットを連続で2回測定することで、測定結果から量子状態が変わったかを確認する。

#流れ
均等重ね合わせ状態の量子ビットを用意する。
$|\psi\rangle = H|0\rangle = \frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)$

1回Z基底測定を行い、古典ビットc0を得る。
測定によって量子状態は以下のように変わっているはず。

>測定結果が0の場合、$|\psi\rangle → |0\rangle$に変化
>測定結果が1の場合、$|\psi\rangle → |1\rangle$に変化

ここで2回目の測定を行い、古典ビットc1を得る

>測定結果が0の場合、$|\psi\rangle$ は $|0\rangle$に変化していた
>測定結果が1の場合、$|\psi\rangle$ は $|1\rangle$に変化していた

古典ビットc0と古典ビットc1が同じであれば、測定によって量子ビットの状態が古典ビットに対応する状態に変化したと言える(可能性が高い)。


#結果：測定1回
システム
ibmq_santiago (よく見ずに実行したらibmq_santiagoになったが、待ちキューが長くて無駄に30分くらいかかってしまった...)
実行回数 1024回

回路
・測定結果を古典ビットc0に入れる(ヒストグラムの下1桁)
・q1は使っていない(測定もしていない)。古典ビットを2ビット用意するために配置
![1_circ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556297/4113b50b-f59d-e1f1-a1e6-63a4226505f9.png)

測定された古典ビットのヒストグラム
・上1桁はただの初期値で、測定値ではない。
・q0に対応するのは測定値の下1桁。0, 1の両方が出ている。
![2_pro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556297/cdae748d-aa4f-5c89-9f28-0c691ffb808f.png)


#結果：測定2回
システム
ibmq_santiago
実行回数 1024回

回路
・2回目の測定結果を古典ビットc1に入れる(ヒストグラムの上1桁)
![3_circスクリーンショット 2021-04-20 212558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556297/4085a901-55af-ba72-bb36-c3fdac8fb2ee.png)

測定された古典ビットのヒストグラム
・00, 11が多い。2回目の古典ビットが1回目と同じなので、測定すると量子ビットの状態が変化すると言える
・01, 10も少し出ているが、現時点ではエラーはしょうがない。量子ビットの状態を測定で厳密に制御するのは期待しないほうがよさそう。(リセットならできるのかな？）
![4_pro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556297/50f8d654-d8d0-a1bb-534d-ff78813737e0.png)


#おわりに
結果から測定すると量子ビットの状態が変化しているように見える。
とはいえ、そもそも2回連続で測定することが想定されているか不明なので、今回の結果が何か意味を持つものではない。
※まあ、ネタなので。
WSL2のUbuntuでphpcsを使う（VSCode）

# はじめに

- Docker について、WSL2 に移行するまでは、Windows10 に PHP、Composer をインストールし、VSCode とコード静的解析の phpcs を連携させて開発していましたが、移行後に phpcs の恩恵が受けられなくなりました  
  （not found と VSCode に怒られる…）
- 怒られるのはツラいので、WSL2 で利用する Ubuntu ディストリビューションに phpcs を設定し、そちらを VSCode で読み込むようにします

# バージョン

- Windows10 Pro
    - 21H1
- VSCode
    - 1.55.2
- Ubuntu
    - 20.04.2 LTS

# 前提

- Docker で WSL2 に移行が済んでいること

# 拡張機能インストール手順

中盤までは、ほぼこちらの記事と同様です。  
非常に助かりました。（ありがとうございます！）

<https://qiita.com/moules449/items/e38220db1bcda6f5fee9>

1．以下のコマンドを実行する（Composer インストール準備）

```bash
# PHP インストール
sudo apt install -y php
# php-cli インストール（Composer のインストールと実行に必要）
sudo apt install -y php-cli
# php-mbstring インストール（使用するライブラリに機能を提供）
sudo apt install -y php-mbstring
# unzip インストール（圧縮されたパッケージの解凍に必要）
sudo apt install -y unzip
# git インストール（Composer の依存関係パッケージダウンロードに必要）
sudo apt install -y git
# php-xmlwriter（phpcs の実行に必要）
sudo apt install -y php-xmlwriter
# php-curl（composer のインストール高速化に必要）
sudo apt install -y php-curl
```

2．↓リンク内の Composer インストールコマンドを実行する

<https://getcomposer.org/download/>

3．以下のコマンドを実行する（phpcs インストール＆設定）

```bash
# Composer コマンドをどこでも実行可能にする（php と同じ階層に移動する）
# /usr/bin/php があるとして
sudo mv ./composer.phar /usr/bin/composer && chmod +x "$_"
# Composer を最新にする
cd ~/.config/composer
composer update
# phpcs インストール
composer global require "squizlabs/php_codesniffer=*"
# CakePHP 用の phpcs をインストール
composer global require "cakephp/cakephp-codesniffer=*"
# WordPress 用の phpcs をインストール
composer global require "wp-coding-standards/wpcs=*"
# CakePHP を読み込む場合はこちらを実行（CakePHP に切替）
~/.config/composer/vendor/bin/phpcs --config-set installed_paths ~/.config/composer/vendor/cakephp/cakephp-codesniffer
# WordPress を読み込む場合はこちらを実行（WordPress に切替）
~/.config/composer/vendor/bin/phpcs --config-set installed_paths ~/.config/composer/vendor/wp-coding-standards/wpcs/
```

4．VSCode の settings.json を編集する（phpcs 読み込み設定）

```JSONC 
{
    // windows10 の設定値はコメント
    // "phpcbf.executablePath": "C:/Users/xxxx/AppData/Roaming/Composer/vendor/bin/phpcbf.bat",
    "phpcbf.executablePath": "/home/xxxx/.config/composer/vendor/bin/phpcbf",
    "phpcbf.standard": "CakePHP",
    // WordPress のコード静的解析をしたい場合はコメント解除（上の CakePHP はコメント化）
    // "phpcbf.standard": "WordPress",
    // windows10 の設定値はコメント
    // "phpcs.executablePath": "C:/Users/xxxx/AppData/Roaming/Composer/vendor/bin/phpcs.bat",
    "phpcs.executablePath": "/home/xxxx/.config/composer/vendor/bin/phpcs",
    "phpcs.showSources": true,
    "phpcs.standard": "CakePHP"
    // WordPress のコード静的解析をしたい場合はコメント解除（上の CakePHP はコメント化）
    // "phpcs.standard": "WordPress"
}
```

5．保存することで VSCode に反映される

# おわりに

- これで、美しくないコードを書いたときに、すぐ気付くことができるようになりました
- WSL2 に移行してから、`bin/cake`の実行権限がないとか、`log`ファイルの書き込み権限がないとか、`cache`ファイルの書き込み権限がないとか、やたらと怒られるので、とてもしんどいです  
  （Dockerfile をうまく記述すれば回避できるのか…？）
- この記事が他のエンジニアの助けになれば幸いです
- こちらもよかったらどうぞ

<https://qiita.com/rowpure/items/4d9df81a4ec4573efdcb>
Railsのtryメソッドは何をしている？

Railsでたまに見かける、`try`メソッド。こいつの正体が知りたくて調べてみた。

Javaではエラーハンドリングで`try catch`文をよく使うので、Railsのtryも似た感じかな~と思ったら検討外れだった。

railsの`ActiveSupport`が提供しているメソッドになる。

## tryメソッドは何をしているのか？

結論から言うと、オブジェクトの存在判定を行い、nilじゃない場合に引数に指定した処理を実行するメソッドである。
オブジェクトの存在をチェックした後に任意の処理を行うことができるため、処理実行のための担保にもなる。

### tryメソッドの使い方と、使用することのメリット

対象のオブジェクトがnilの場合、処理を実行しないため、エラーになるのを防ぐことができる。
条件判定を書く際にスッキリと書くことができる。

下記は`user`がnilでない場合`name`を取得する処理である。

```ruby
#tryを使用しない場合
user ? user.name :  "nilです"

#tryを使用した場合
user.try(:name) || "nilです"
```

上の`user`が２回出てくるより、`user.try(:name)`の方がわかりやすいしスッキリしている。

ちなみに`try`をメソッドチェーンで重ねることも可能となっている

```ruby
user.try(:name).try(:age)
```

また引数で渡したメソッドが定義されていない場合エラーは吐かれず、当然処理も実行されない

```ruby
# helloメソッドが定義されていない場合
user.try(:hello)
```


#### 参考
[Rails ドキュメント](https://railsdoc.com/page/try)
Linebot作ってたらセキュリティのお話が出てきた

#はじめに
techpitに「railsでlinebotを作ってみよー！」ってやつがあったので初めて見たらセキュリティについての項目があった。最近freeeとかlineとか情報漏洩してセキュリティに対する知見が重要になっている気がするのでアウトプットのために記事を書く。

#DNSリバインディング攻撃
DNSリバイディング攻撃はサイバー攻撃の一種であり、ドメイン名に対応するIPアドレスを短時間で変更し、罠サイトに仕掛けたJavascriptから攻撃対象サイトに対して悪さをするもの
Rails6ではDNSリバインディング攻撃の対策のため、localhostなどの指定されたホスト名以外でローカル環境にアクセスできないようになっている。アクセスを許可するためにはホスト名を指定して許可する設定が必要

今回linebotを作るにあたってngrokというものを使用しており、起動するたびにURLが変わってしまい、その都度ホスト名を許可するのは手間がかかるため、今回は全てのホスト名でアクセスできるように設定をした。（対策を無効化した）

```ruby:development.rb
config.host.clear
```

#CSRF（リクエスト強要)対策
リクエスト強要とは、別のサイトに用意したコンテンツ上の罠のリンクを踏ませること等をきっかけとして、引退ネットショッピングの最終決済などの重要な処理を呼び出すようにユーザーを誘導する攻撃
rails6ではリクエスト強要に対する対策が標準で設定されている。

今回はlinebotを作るにあたってCSRF攻撃のリスクはほぼないためこれを無効化

```ruby:〇〇controller.rb
protect_from_forgery except: [:アクション名]
```

#終わりに
セキュリティむずい
【Firebase Authentication】メールアドレス変更時の挙動まとめ【図解付き】 


今回は、**Firebase Authentication**サービスのうち、以下のことについてまとめました。

1. メール/パスワードによるサインインから、メールアドレスを変更したらどうなるか。
2. Googleなどのプロバイダー別サインインから、メールアドレスを変更したらどうなるか。

Firebase Authenticatonによる認証機能の基本的な実装は、参考記事も多く存在していますが、上記のようにメールアドレスを変更されるとどうなるのか分からなかったので調べてみました。

## 前提
今回はこのような認証機能を持つアプリを想定しています。

- メールアドレス認証を必要とする
- Googleなどの認証プロバイダー別サインインに対応
- アプリ内でメールアドレス・パスワード変更に対応

## メール/パスワードによるサインインからメールアドレスを変更

メールパスワードによるサインインから、メールアドレスを変更しようとすると、下図のような流れになります。

![Flutter-メール_パスワードサインイン (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699790/232eb3a7-8759-850a-11cf-0be814f16df7.png)

こちらは[公式サイト](https://firebase.google.com/docs/auth/web/manage-users?hl=ja)にも記載ある通りで、

1. ユーザー再認証:`reauthenticateWithCredential()`
2. メールアドレス更新: `updateEmail()`
3. 認証メールを開いて、メールアドレスを認証

上記の手順を踏んでメールアドレス認証を行えば変更完了です。

## プロバイダー別サインインからメールアドレスを変更

次に、プロバイダー別サインインからメールアドレスを変更してみました。

今回はGoogleサインインで試したときの挙動を下図に示します。
こちらは自分の思っていた動きと異なりました。

![Flutter-Googleサインインによるユーザー認証.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699790/1eb13784-265e-5228-9848-854b20ec9c1d.png)

1. メールアドレス更新: `updateEmail()`
2. パスワードリセットメール発行: `sendPasswordResetEmail()`
3. パスワードリセットメールを開いて、新パスワードを設定

1.メールアドレス更新: `updateEmail()`の際、Firebase Authenticationページで確認した限りでは、メールアドレスは新メールアドレスに更新されておりましたが、下図のようにプロバイダー情報がGoogleのままでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699790/d0572cc9-3cf3-c321-c4f0-0bb75e057260.png)

そのため、**パスワードリセットメールを発行して、メールのリンクより、パスワードを再設定してあげる必要がありました。**
※これはすなわち、Googleサインイン用パスワードがそのまま受け継がれることはなかったということ。

パスワード再設定後は、メール/パスワードによるサインインに対応したアカウントに切り替わりました。

### 「認証プロバイダーによるサインインからのメールアドレス変更を禁止」してしまうのも手

現在製作中のアプリは、パスワードリセットメールを発行して対応しておりますが、この手続きはユーザーにとって望ましいものではないかもしれません。

そのため、「認証プロバイダーによるサインインからのメールアドレス変更を禁止」してしまうのも手かもしれません。

## さいごに

セキュリティ面に関わる重要度の高い部分のため、理解の相違や改良点などありましたらご連絡下さいますと幸いです。

## 参考記事

>[[JS] Firebaseの覚書 ① メールアドレス認証](https://tenderfeel.xsrv.jp/javascript/3606/)

>[FirebaseのE-mail認証でアドレスが正しいことを確認する](https://nipo.sndbox.jp/develop-blog/emailverified)

>[【Flutter + Firebase】パスワードリセットメールを送信する](https://yaba-blog.com/flutter-firebase-password-reset/)
AWSにおけるVPCのルール

# VPCとは
VPC(VirtualPrivateCloud)は仮想ネットワークサービスのこと。AWS内部の自分専用のネットワーク領域。セキュリティ面も含めて設定が必要。<br>一つのアカウントで複数のVPCを設定することを**マルチVPC**という。<br>
AWSでは、VPCは1アカウントにつき５つまで設定可能。

# リージョン
データセンターの集合体。世界各国にあり、日本には東京と大阪にある。原則、東京在住であれば東京リージョンを使う方が良い。リージョンの中にアベイラビリティゾーン(AZ)が存在する。
東京リージョンでは、下記の４つのAZがある。

- ap-no-rtheast-1
- ap-no-rtheast-2(現在使用不可)
- ap-no-rtheast-3
- ap-no-rtheast-4

# サブネットとは
VPC内のネットワークを小分けしたもの。サブネットは、データセンターを跨いで作成はできない。


# CIDER表記について
IPアドレスの表記方法のこと。
0.0.0.0/0

|IPアドレス|使用できるIPアドレスの数|
|:--:|:--|
|10.21.59.223/32|`10.21.59.223`の1個のみ|
|10.21.59.223/24|`10.21.59.*`の256個|
|10.21.59.223/16|`10.21.*.*`の65536 個|

*VPCのアドレスレンジ帯は/16 ~ /28の範囲内で作ること

# VPCのポイント
- 故障に備えて、VPCを同じ構成で複数に分けて、それぞれ別のアベイラティゾーンに設定する方が良い
- IPアドレスは余分に作っておく方が良い
- アドレスレンジ帯は/24がおすすめ
    - 255個分のIPアドレスを確保できる
    - 第4オクテットで分割するのでわかりやすい
    - /28ではロードバランサー(ELB)が使用できない
簡単なアルゴリズム問題を解いた【探索、ソート】

#はじめに
キタミ式の基本情報技術者試験の勉強してたらアルゴリズムの説明が出てきたので、久しぶりにコーディングしてみた

一つのメソッドで完結させる、なるべく簡潔なコードにする、フラグ変数やインデックス変数を使わない、などの縛りを設けてます

※仕様は殆ど上記の本の内容だけに従ってます

※ハッシュ法、ヒープソートはわけわかめだったのでやってません
　似たような書き方されてるコードがあれば教えてください

#探索

###線形探索法
```Ruby
def linear_search(ary, find)
  ary.each { |x| return true if x == find }
  false
end
```

###二分探索法
```Ruby
def binary_search(ary_should_sort, find)
  ary = ary_should_sort.sort

  loop do
    return false if ary.size == 1

    middle = ary[ary.size / 2]
    return true if middle == find

    half = ary.each_slice(ary.size / 2).to_a
    half[1].concat(half[2]) if half[2] != nil

    ary = middle > find ? half[0] : half[1]
  end
end
```

#ソート
###基本交換法（バブルソート）
```Ruby
def bubble_sort(copied_ary)
  ary = copied_ary.dup

  (ary.size).times do
    (ary.size - 1).times do |i|
      ary[i], ary[i + 1] = ary[i + 1], ary[i] if ary[i] > ary[i + 1]
    end
  end

  ary
end
```
~~終了判定(`ary.each_cons(2).all? { |a, b| a <= b }`)があんまりよくない気がするけど本に何も書いてないのでセーフ~~
↑偶然バブルソートは配列の要素数回ループすると知ったので書き換えました

###基本選択法（選択ソート）
```Ruby
def selection_sort(copied_ary)
  ary = copied_ary.dup

  (ary.size - 1).times do |i|
    min_index              = ary[i..].index(ary[i..].min) + i
    ary[i], ary[min_index] = ary[min_index], ary[i]
  end

  ary
end
```

###基本挿入法（挿入ソート）
```Ruby
def insertion_sort(copied_ary)
  ary = copied_ary.dup

  divided_ary  = ary.chunk_while { |a, b| a <= b }.to_a
  sorted_ary   = divided_ary.max_by(&:size)
  unsorted_ary = (divided_ary - [sorted_ary]).flatten

  return sorted_ary if unsorted_ary == []

  unsorted_ary.each do |e_un|
    index = sorted_ary.size
    sorted_ary.reverse_each do |e|
      break unless e > e_un
      index -= 1
    end

    sorted_ary.insert(index, e_un)
  end

  sorted_ary
end
```

###シェルソート
```Ruby
def shell_sort(copied_ary)
  ary = copied_ary.dup

  h = 1
  h = h * 3 + 1 until h > ary.size / 9

  while h != 0
    sliced_ary = ary.each_slice(h).to_a

    taken_ary = sliced_ary[0].zip(*sliced_ary[1..])
    taken_ary.map!(&:compact).delete_if(&:empty?).map! { |x| insertion_sort(x) }

    ary = taken_ary[0].zip(*taken_ary[1..]).map(&:compact).flatten
    h = (h - 1) / 3
  end

  ary
end
```
これだけ仕様を調べてから書きました（[参考](https://programming-place.net/ppp/contents/algorithm/sort/005.html)）
我ながらいい感じのコードだと思います

###クイックソート
```Ruby
def quick_sort(ary)
  return ary if ary.size == 1 || ary.all? { |x| x == ary[0] }

  middle = (ary.min + ary.max).fdiv(2)
  smaller, bigger = ary.partition { |x| x < middle }

  return quick_sort(smaller) + quick_sort(bigger)
end
```
初めて書いた再帰的プログラムです
短く纏められる再帰凄い（小並感）

#おわり
WPF覚え書き～StackPanel～

#はじめに
WPF学習中のため自分用に記載していきます。
間違い、不足などありましたらコメントをよろしくお願いします。

#StackPanelコントロール
子要素を縦並び(Vertical)にするか、横並び(Horizontal)にするか設定する

***
●StackPanelの子要素を縦並びにする
子要素のHorizontalAlignmentプロパティの水平方向の要素を指定することも可能

```C#
~省略~
<StackPanel Orientation="Vertical" >
   <Button Content="Button1" />
   <Button Content="Button2" />
   <Button Content="Button3" HorizontalAlignment="Left"/>
   <Button Content="Button4" HorizontalAlignment="Right"/>
</StackPanel>
```

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454547/72f5fdd8-8183-32ca-2eb0-a1adc80b920b.png">



***

●StackPanelの子要素を横並びにする
子要素のVerticalAlignmentプロパティの垂直方向の要素を指定することも可能

```C#
~省略~
<StackPanel Orientation="Horizontal" >
    <Button Content="Button1" />
    <Button Content="Button2" />
    <Button Content="Button3" VerticalAlignment="Top"/>
    <Button Content="Button4" VerticalAlignment="Bottom"/>
</StackPanel>

```


<img width="300"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454547/c39ca744-cf2b-2d71-ccfb-035ded05a452.png">




#参照
[かずきのBlog@hatena](https://blog.okazuki.jp/entry/20130104/1357315810)
Google Chat Thread Switcher というChrome拡張を作りました

### 概要
Google Chat Thread Switcher は Google Chrome 拡張機能です。Google Chrome にインストールすると、Google Chat でスレッドを選んで移動することができるようになります。
### どこにある？
[Chrome ウェブストア](https://chrome.google.com/webstore/detail/google-chat-thread-switch/pcfiellepclcooaaifkkdnpcmeinafba) でリリースしています。
コードは[GitHub](https://github.com/itagagaki/Google-Chat-Thread-Switcher)で公開しています。
### イシュー
何か不具合があれば [Issues](https://github.com/itagagaki/Google-Chat-Thread-Switcher/issues) に書いてください。コメントや提案も歓迎します。
LeetCode日本語修行7日目- [28-  strStr()の実現]

### Implement strStr()
#####参考:https://leetcode.com/problems/implement-strstr/
###問題の内容:
haystackの中にneedleが最初に現れるIndexを返し、ないの場合は-1を返します。
明確にします。
ちなみに、needleが空の文字列の場合、何を返すべきでしょうか？
###例:

例1:
Input: haystack = "hello", needle = "ll"
Output: 2

例2:
Input: haystack = "aaaaa", needle = "bba"
Output: -1

例3:
Input: haystack = "", needle = ""
Output: 0
###ヒント:
0 <= haystack.length, needle.length <= 5 * 104
haystack and needle consist of only lower-case English characters.

---
この問題の解答は、普通のForLoopでできます、
又はKMP法を使って、回答します。
KMP法の中に、一番理解難しいのは、多分PartialMatchTableの事です、
PartialMatchTableとは、指定のStringの中に、prefixとsuffix イコールの部分です。
`abcdab`の場合
a -> 0
ab -> [prefix: a ,suffix: b] ->0
abc ->[prefix: a,ab ,suffix: c,bc] ->0
abcd ->[prefix: a,ab,abc ,suffix: d,dc,dcb] ->0
abcda ->[prefix: a,ab,abc,abcd ,suffix: a,ad,adc,adcb] ->　aは両方の中に共に出ました、 1です
abcdab ->[prefix: a,ab,abc,abcd,abcda ,suffix: b,ba,bad,badc,badcb] ->0
この場合：
`abcdab`のPartialMatchTableは
`000010` です


```Kotlin
class Solution {
    fun strStr(haystack: String, needle: String): Int {
        var m = needle.length
        var n = haystack.length
        if(m == 0){
            return 0
        }
        val pi = IntArray(m)
        var j = 0
        for(i in 1 until m){
            while(j > 0 && needle[j] != needle[i]){
                j = pi[j-1]!!
            }
            if(needle[i] == needle[j]){
                j++
            }
            pi[i] = j
        }

        var jj = 0
        for(i in 0 until n){
            while(jj > 0 && haystack[i] != needle[jj]){
                jj = pi[jj-1]!!
            }
            if(haystack[i] == needle[jj]){
                jj++
            }
            if(jj == m){
                return i - m + 1
            }
        }
        return -1
    }
}
```
NodeJSのrequestモジュールで同期処理する

[request](https://github.com/request/request)モジュールは、2020年2月の時点で非推奨になってしまったので、
最新の方法は以下のサイトを見てください。

[Node.jsでAysnc/Awaitを使ってHTTPリクエストを行う5つの方法](https://www.twilio.com/blog/5-ways-to-make-http-requests-in-node-js-using-async-await-jp)



非推奨とはいえ、requestは未だに使用されているので以下に書いておきます。

```js
request= require('request');
const rqt = (url) => {
    return new Promise((resolve, reject)=> {
        request(url, (error, response, body)=> {
            resolve(body);
        });
    });
}

(async () => { 
    const body = await rqt('https://httpbin.org/json')
    console.log(body);
})();
```



sync-requestモジュールだともっと簡単にできるが、こちらも非推奨になっている。

[同期処理でrequestモジュールの戻り値を返す(Node.js)(非コールバック)](https://steemit.com/side7nodejs/@pacopaco2643/request-node-js)
[Node.jsのHTTP通信はsync-request非推奨でthen-requestを推奨](https://designetwork.daichi703n.com/entry/2017/02/21/node-then-request)


```js
const request = require('sync-request');
const res = request('GET', 'https://httpbin.org/json', {});
console.log(res.body.toString());
```
[PHP] ASCIIを文字列に変換する

#概要
ASCIIから文字列に変換したい場合の方法をメモします。


#方法
* chr()を使う

[ASCII表](https://www.k-cube.co.jp/wakaba/server/ascii_code.html)

```.php
<?php
	$result = chr(111) ;

    print_r($result);
?>
//結果：　n
```
AMIからEC2を立てたときにパスワードログインできない問題

## 問題となったこと

EC2でAMIから複製してインスタンスを作る際、
元々パスワード認証だけでログインしていましたが、ログインできなかったのでその対処法を書いておきます。

## ログインする

キーを使って、ec2-userやcentosユーザを使用してログインを行う

## sshの設定変更を行う

- rootになる

```
sudo su -
```

- パスワード認証の設定を変更

AMI作成時に自動的にoffにするらしいです

```
vi /etc/ssh/sshd_config
==========
PasswordAuthentication no
↓
PasswordAuthentication yes
==========
```

- sshdの再起動

```
systemctl restart sshd
```

これでsshのパスワードログインができるようになったはずです。

## 勉強後イメージ

これで結構時間かかってしまった・・・
多分忘れない
【初心者でもわかる】カレンダー系jsを入れた時にスマホで入力欄が邪魔なので非表示にする方法

#どうも7noteです。入力するキーパッドを非表示にする方法です。

カレンダー系のjsを入れた場合、PCで検証しただけでは特に問題なさそうですが、
実機のスマホでみると標準のキーパッドが出てしまし、カレンダーの入力がしにくくなってしまいます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/ff13bcbf-36d1-9b83-7fda-a561383f11ba.png" width="300";>
**↑キーパッドが表示されて、カレンダーが見にくい。**


## inputのキーパッド入力を無効化する方法

この対策として、input属性に`readonly="readonly"`を指定することでキーパッドがでなくなります。

```index.html
<!-- キーパッドを表示させない -->
<input type="text" id="datepicker" readonly="readonly">
```

`readonly="readonly"`を指定することで、キーパッドからの入力がされなくなります。
しかし入力自体を完全に不可にしているわけではないので、jsなどでinputの値を操作することができます。


## まとめ

カレンダーは基本的にjavascriptで動いているので、もしjsを無効に設定しているブラウザでは全く操作・入力ができなくなるので注意ください。

似た属性に`disabled`がありますが、こちらは完全にinput自体を無効化してしまうのでsubmit等で値の送信ができません。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
makemigration と migrate


## はじめに
引き続き、勉強しているDjangoについてまとめました。
自分への備忘録代わりに書き留めています。
基本的な機能を理解できたら、家計簿アプリとか作ってみようと計画中です。

## データベースマイグレーションとは
アプリケーションで使うデータベースの定義を自動的に作成・管理する機能のことを示しています。

### 前提として、、、
Models.pyにDBの中にテーブルが作成されておらず、makemigrateとmigrateを実施することで、DBの中にテーブルが作成される仕組みになっています。


### makemigrate
DBの中にテーブルを作成するために、マイグレーションファイルを作成。
役割としては、models.pyに書いたモデルに対して、新しいマイグレーションを作成する。

```terminal:ターミナル
python manage.py makemigrations
```

大型開発の場合、一気に全てのDBを変更すると、不具合が出る可能性があるため、該当のアプリのみを変更する場合は、以下の通りに実行する。

```terminal:ターミナル
python manage.py makemigrations (アプリ名)
```

### migrate
マイグレーションを適用したり、適用をキャンセルするのに使います。
作成されたマイグレーションファイルを元に、DBにテーブルを作成します。

```terminal:ターミナル
python manage.py migrate
```

### おまけ：You have XX(数字) unapplied migration(s). 
サーバーを立ち上げようとしたら、`You have XX(数字) unapplied migration(s). `と書かれていた場合は、makemigration と migrateを実施するとデータベースのテーブルを更新すれば、解消されます。

### 参考資料
以下を参考にさせていただきました。

Django マイグレーション まとめ
https://qiita.com/okoppe8/items/c9f8372d5ac9a9679396
Python入門 Djangoの使い方（その12）マイグレーションする。
https://tech.pjin.jp/blog/2017/06/29/python-primer-26-django-12/
学習メモ】MakemigrationsとMigrateについて
https://qiita.com/frosty/items/8c715a53d7920c9cd1eb
マイグレーション
https://docs.djangoproject.com/ja/3.2/topics/migrations/
Pythonの外部ライブラリをインストールするコマンド

OS:Windows

Pythonの外部ライブラリをインストールするときの手順
コマンドプロンプトを開く
・ライブラリをインストールするとき、以下コマンドを入力

```
pip install ＜ライブラリ名＞
```


・ライブラリをアンインストールするとき、以下コマンドを入力

```
pip uninstall ＜ライブラリ名＞
```


・インストールされたライブラリを確認するとき、以下コマンドを入力

```
pip list
```

※pipというインストール用のコマンドはPythonをインストールするときに一緒にインストールされている

**＜補足＞**
ライブラリをインストールしたところ、以下のWARNINGが表示された

```
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
```
これはpipのバージョンが低いから
コマンド`python -m pip install --upgrade pip`を実行してバージョンをあげようねというメッセージ

実行すると古いバージョンがアンインストールされて、新しバージョンがインストールされる

以下のようにアンインストールもインストールもSuccessfullyなら大丈夫

```
Installing collected packages: pip
  Found existing installation: pip 19.2.3
    Uninstalling pip-19.2.3:
      Successfully uninstalled pip-19.2.3
Successfully installed pip-21.0.1
```
念のため上記の`pip list`（インストールされたライブラリを確認するコマンド）を実行するとSuccessfully installedのバージョンと同じになってることを確認できる


```
Package    Version
---------- -------
pip        21.0.1
```
https 通信可能なdocker registoryを作成する(オレオレ証明書)

# 目的
https通信で通信可能なDocker registoryをDockerコンテナで作成する
cri-oやdockerからpullできることを確認する

# 作業手順概要
以下の作業を行いDocker registoryを立てる
1. サーバーを構築するサーバのIPを固定
2. オレオレ証明書を作成
3. Dockerを使用してDocker registoryサーバ構築
4. アクセスするPCに証明書を登録

# 作業詳細
## 1. サーバーを構築するサーバのIPを固定

やり方は省略しますが、サーバのIPは`192.168.223.201`とする

## 2. オレオレ証明書を作成
以下手順を行い証明を作成する

```bash
$ mkdir certs
$ openssl req -newkey rsa:2048 -nodes -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
Generating a RSA private key
..................+++++
.......+++++
writing new private key to 'certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
```

## 3. Dockerを使用してDocker registoryサーバ構築
以下のコマンドを実行してDokcer registoryサーバーを構築する

```bash
docker run -d -p 443:443 \
   --rm --name registry \
   -v `pwd`/certs:/certs \
   -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
   -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
   -v $(pwd)/regist:/var/lib/registry \
   -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
   registry:2
```

再起動後も有効にする場合は`--rm`オプションを外して`--restart=always`のオプションを追加する

## 4. アクセスする機器に証明書を登録

* dockerの場合 \
レジストリサーバで使用した`certs/domain.crt`をコピー後以下のコマンドを実行する

```bash
sudo mkdir -p /etc/docker/certs.d/192.168.223.201/
sudo cp domain.crt /etc/docker/certs.d/192.168.223.201/ca.crt
```

* cri-oの場合 \
レジストリサーバで使用した`certs/domain.crt`をコピー後以下のコマンドを実行する

```bash
sudo mkdir -p /etc/containers/certs.d/192.168.223.201/
sudo cp domain.crt /etc/containers/certs.d/192.168.223.201/ca.crt
```

## 動作確認
### dockerによるコンテナ登録

nginxをdockerhubからpullし、名前を変更してローカルのdocker registoryに登録する

```bash
docker pull nginx
docker tag nginx:latest 192.168.223.201/test/nginx:latest
docker push 192.168.223.201/test/nginx:latest
```
### crulコマンドで動作確認数
以下のコマンドを実行する

```
curl https://192.168.223.201/v2/_catalog -k
```
先ほど登録した `test/nginx`が返ってくる
コーディング共有Webアプリを作ってみた

<h1>（１）作成のきっかけ</h1>

<p>普段はソーシャルワーカーとして障がいをお持ちの方の支援をしており、たまに簡単なHTMLやCSS,JavaScriptについて教える機会があります。</p>

<p>ブラウザでタグはこのように表示されるとか、ここにclassを設定してとか、基礎的なことぐらいしか教えられないのですが、今までそのような機会がなかった方にとっては、ホームページってこうやって出来ていくんだ！と、試行錯誤しながら自分でも勉強して一緒に学んでいます。</p>
<p>障がいによっては聴覚や発話、コミュニケーションにしんどさがある方もいるので、ひとつの画面を見ながらコードの説明をしたり、エディターの設定をしたりすることがハードルと成りうることもあり、何か良い方法はないかなと考えていました。

<p>ちょうど React か Vue を学びたいと思っていたので、勉強がてら CodePen や JSFiddle のような　コード共有サイトのシンプル版を作ってみようと思い作成することにしました。</p>

<h1>（２）作成したwebアプリ</h1>

<p><a href="https://sonocode.syeha.com/" rel="nofollow noopener" target="_blank">SONOCODE</a></p>

<p>コーディングをリアルタイムで共有することができ、音声チャットやその内容が字幕で表示されます。見た目はまあ CodePen ですね、いままでで完成させたwebアプリは一つだけでして、経験がない中いろいろ苦労しましたが、やはり React の学習が難しく、挫折しそうになりながらも Qiita や StackOverflow で調べ調べしてなんとか形になりました。</p>


<h1>（３）使った技術</h1>

<p>・React<br>
・CodeMirror<br>
・SkyWay<br>
・Firebase<br>
・Material-UI<br>

<p>その他にも MITライセンス のライブラリやデザインを組み合わせて、それらのおかげでwebアプリっぽくなったかなと思います。</p>

<h1>（４）参考にしたサイト</h1>

<h3><a href="https://codeshare.io/">codeshare.io</a></h3>
<p>このようなサイトが作りたかったのです、通信量からビデオは断念しました。</p>
<h3><a href="https://qiita.com/yusuke84/items/54dce88f9e896903e64f">WebRTC Platform SkyWay ハンズオン SFU編</a></h3>
<p>JavaScript で解説されており、とても分かりやすく助かりました。</p>
<h3>その他</h3>
<p>CodeMirrorについては様々なサイトやサンプルからヒントを得ました。</p>


<h1>（５）終わりに</h1>

<p>コロナ禍において障がいをお持ちの方の生活も大きく制限されており、何かできることはないかとICTを活用した生活の質向上や業務効率化などを素人ながら福祉の現場で行っています。自分の周りのひとが困っていて必要としている”機能”を作ることは、学びのモチベーションに繋がり自分のためにもなることだと感じており、今後もチャレンジしていきたいと思います。</p>
[UE4] Transformの変換の基礎の基礎

#概要
ゲームを作る上で、Transformの変換が必要になる場面がある。
特に回転の計算は、Rotationで計算してもおかしなことになることが多いので、Transformを使うことが多い。
Transformの計算は公式さえ覚えていれば基本的には問題無いが、使用頻度が高くなく忘れがちだったので、備忘録として書き残す。

今回は例として、アクターAから見たアクターBの相対Transformを求めていく。
ワールドの原点はWと記述する。

#公式
先に公式を乗せておく
ここでは、Aから見たBの相対Transformを以下のように記述する。

```math
^{A}\boldsymbol{T}_{B}
```
<br>
Transformの変換では、以下の2つの式が成り立つ。

```math
^{A}\boldsymbol{T}_{C}= \, ^{A}\boldsymbol{T}_{B} \, \times \, ^{B}\boldsymbol{T}_{C}
```
説明：Aから見たCのTransformは、任意の点Bを用いて、AB×BCで求めることも出来る。
(図はベクトルなので、あくまでイメージです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/bdc592f0-8b0b-d1f2-d26d-6833f683a57a.png)


```math
^{A}\boldsymbol{T}_{B} = (^{B}\boldsymbol{T}_{A})^{-1}
```
説明：Aから見たBのTransformは、Bから見たAのTransformを反転したものと等しい。


#解説
実際に上記公式を使い、Aから見たBの相対Transformを求めていく。
まず、A,BのTransformは、ワールドの原点から見たTransformなので、以下のように記述出来る。

```math
^{W}\boldsymbol{T}_{A}\\
^{W}\boldsymbol{T}_{B}\\
```

1つ目の公式を用いると、Aから見たBのTransformはワールドの原点Wを用い、以下のように表すことが出来る。

```math
^{A}\boldsymbol{T}_{B}= \, ^{A}\boldsymbol{T}_{W} \, \times \, ^{W}\boldsymbol{T}_{B}
```
<br>
更に2つ目の公式を用いると、Aから見たWのTransformを、Wから見たAのTransformで置き換えることが出来る。

```math
^{A}\boldsymbol{T}_{B}= \, (^{W}\boldsymbol{T}_{A})^{-1} \, \times \, ^{W}\boldsymbol{T}_{B}
```
<br>
結果として、Aから見たBのTransformは、原点から見たAのTransformを反転したもの×原点から見たBのTransformで求めることが出来ることが分かった。

#Blueprintでの実装
UE4でTransformの計算をする上で一番気を付けなければならないのが、**掛け算の順序が逆になっている**ことである。
先程求めた式の掛け算の順序だけ逆にすれば、Aから見たBのTransformが求められる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/e323389f-bb36-f605-1988-67c919b7b3d8.png)

#おまけ
Qiitaでは、Transformは以下のように記述することで書くことが出来た。
>
\`\`\`math
^{A}\boldsymbol{T}_{B}
```

```math
^{A}\boldsymbol{T}_{B}
```

参考
https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada
oauth2-proxyでメールアドレス認証する

# 目的
特定のメールアドレスのみ、認証を通したい。

# 環境
Docker

# 方法
`--authenticated-emails-file` オプションを使用する。

以下`docker-compose.yml`サンプル(一部抜粋)

```docker:docker-compose.yml
  oauth2-proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:latest
    container_name: oauth2-proxy
    command: >
      '--http-address=0.0.0.0:4180'
      '--cookie-secure=true'
      '--cookie-expire=24h'
      '--cookie-httponly=true'
      '--cookie-domain=************'
      '--cookie-name=************'
      '--cookie-secret=**********'
      '--upstream=http://******:5601'
      '--authenticated-emails-file=/usr/local/allowemails'
      '--client-id=*************.apps.googleusercontent.com'
      '--client-secret=************'
    volumes:
      - ./oauth2-proxy/allowemails:/usr/local/allowemails
```

```:outh2-proxy/allowemails
youremail@gmail.com
heremail@gmail.com
hisemail@gmail.com
```

# 参考
https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/oauth_provider#email-authentication
データベースからViewに投稿者名表示させる方法いくつか2（データベース検索方法）アソシエーション編

自分の理解を深めるために書いています。
自分は出社するといつもエクセルVBAでデータ作成が多いのですが、

例えば今日はある学年数千名分の名簿のアドレス１とアドレス２（１は都道府県市区町村２は番地建物名部屋番号）を
アドレス１〜５（１が都道府県２が市区３町村４番地５建物名等）で分けて提出するなんて作業を行っていました。

なのでfindやwhereなどはエクセルにあるので使いなれた存在でした。

今日はわたしのアソシエーションを使った変数の初体験になります。
直感的に操作できるといいますが、私自身はわかりにくいものでした。

テキストの引用から
-

>####投稿者名を表示するようにビューを変更しよう
tweetsテーブルのレコードである、「name」カラムの値が表示されている部分を、
アソシエーションを利用してツイート投稿者の「nickname」が表示されるように変更します。
Tweetモデルに対して「Tweet belongs to User」という形でアソシエーションを定義しているので、Tweetモデルのインスタンスが入った変数.userと記述すると、インスタンスが属しているUserモデルのインスタンスを取得できます。

>コンソールを利用して例を見てみましょう。

>アソシエーションを利用しない場合


>```ruby
% rails c
[1] pry(main)> tweet = Tweet.find(1)
[2] pry(main)> User.find(tweet.user_id)
=> #<User id: 1, email: "test@gmail.com", encrypted_password: "@@@@@@@@@@@@@@@@@", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2014-12-06 09:00:00", last_sign_in_at: "2014-12-06 09:00:00", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2014-12-06 09:00:00", updated_at: "2014-12-06 09:00:00", nickname: "test_ruby">
```

>アソシエーションを利用した場合


>```ruby
% rails c
[1] pry(main)> tweet = Tweet.find(1)
[2] pry(main)> tweet.user
=> #<User id: 1, email: "test@gmail.com", encrypted_password: "@@@@@@@@@@@@@@@@@", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2014-12-06 09:00:00", last_sign_in_at: "2014-12-06 09:00:00", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2014-12-06 09:00:00", updated_at: "2014-12-06 09:00:00", nickname: "test_ruby">
```

では実際にViewとコントローラでみてみましょう！
-

```contoroller/items.rb
def show
    @item = Item.find(params[:id])
end
```
※もし　@itemの@とったらインスタンス変数からローカル変数に変わるのでitemの使える範囲（スコープ）は
def show 〜 endまでになるのでviewのitemsのshowには変数の値を引き渡せなくなる。


```contoroller/items.rb
def show
    @item = Item.find(params[:id])
end
```

```ruby:items/show.html.erb
<th class="detail-item">出品者</th>
<td class="detail-value"><%= @item.user.nickname %></td>
```

ここでアソシエーションについて

```models/user.rb
has_many :items #複数形名詞（itemsは出品物）
```

```models/item.rb
has_many :user #単数形名詞（itemsは出品物）
```

#この@item.user.nicknameについて
#１.@item.がitems_controllerからのインスタンス変数
#2.user.が上に書いたアソシエーションを組んだ先のテーブル名（アソシエションの命名規則に合わせて）
今回は@itemなのでitemテーブルの組んだアソシエション相手はuserなので命名規則単数系でuserとします。
#3.（最後）userテーブル内の欲しいカラム名を記述します。
今回はnickname

理解が進みました。
色々な方に感謝！
networkxのデータセット

#はじめに

networkxとはpythonでグラフ・ネットワークを扱える便利なパッケージです。

```ruby:開発環境
Python 3.8.3
networkx 2.4 
```

#データセット

##1. Zachary’s Karate Club graph
ノード数:34
エッジ数:78

論文:Zachary W. (1977). An information flow model for conflict and fission in small groups. Journal of Anthropological Research, 33, 452-473.

```ruby:karate_club
import networkx as nx
G = nx.karate_club_graph()
```

##2.Davis Southern women social network.
ノード数:32
エッジ数:89

論文:Breiger R. (1974). The duality of persons and groups. Social Forces, 53, 181-190.

```ruby:Davis_Southern_women_social_network
import networkx as nx
G = nx.davis_southern_women_graph()
```

##3.football
ノード数:115
エッジ数:613

論文:Girvan, Michelle, and Mark EJ Newman. "Community structure in social and biological networks." Proceedings of the national academy of sciences 99.12 (2002): 7821-7826.

```ruby:football
import urllib.request as urllib
import io
import zipfile

import matplotlib.pyplot as plt
import networkx as nx

url = "http://www-personal.umich.edu/~mejn/netdata/football.zip"

sock = urllib.urlopen(url)  # open URL
s = io.BytesIO(sock.read())  # read into BytesIO "file"
sock.close()

zf = zipfile.ZipFile(s)  # zipfile object
txt = zf.read("football.txt").decode()  # read info file
gml = zf.read("football.gml").decode()  # read gml data
# throw away bogus first line with # from mejn files
gml = gml.split("\n")[1:]
G = nx.parse_gml(gml)  # parse gml data
```
PyTorch | Leaf Variableとは

**grad_fnがNoneではないのtensorはleaf variable**
https://blog.csdn.net/a1367666195/article/details/105654101
### Tensorの確認
```
print(tensor.is_leaf)
```
```
for name, param in model.named_parameters():
     if param.requires_grad and name == 'module.model.conv1.weight':
           print("module.model.conv1.weight.grad:", param.grad) # Noneが出ると、微分不可
```

### 要注意：leaf variableを無効化する操作
**view()**
代わりに：

```
x_fused = x_fused.reshape(-1, 5, 3, x_fused.shape[-2], x_fused.shape[-1])
x_fused.retain_grad()
```
localstorageを使用したものをブラウザで確認する時の備忘録

localstorageを利用したjsを組む事が増えたので、
その確認をブラウザで行う際の注意点を自分用にメモ。

# chrome
* localstorageの中身の確認はデベロッパーツールで[Application]－[Storage]－[Local Storage]でできる
* ↑で直接書き換えることも可能（コンソールでjavascriptを打つことでも可能）
* シークレットブラウザでの確認時、一度シークレットブラウザをすべて閉じない限り、タブやウィンドウが異なっていてもシークレットブラウザ上で一度開いた同サイトのlocalstorageを共有する

# IE
* chromeのように開発者ツールでlocalstorageを確認できない
* 確認したいときはコンソールで「localStorage.getItem('KeyName');」を打って確認する
* 書き換えたい場合もコンソールで「localStorage.setItem('KeyName', 'keyValue');」を打つ（注意：配列を入れたい場合はkeyValueの中身を配列にした上で「localStorage.setItem('KeyName', JSON.stringify(keyValue));」）
* InPrivateブラウズ使用時、同じサイトを開いていてもタブやウィンドウが異なるとlocalstorageは共有されない
GCPのLocationをPower BIで可視化する

# GCPのクラウドロケーションを可視化したい
## Steps
1. データをWebからインポート
1. 地図ビジュアルにプロット

## 1.　データをWebからインポート

今回使うWebサイトはこちら
https://cloud.google.com/network-connectivity/docs/interconnect/concepts/choosing-colocation-facilities
Network ConnectivityについてのDocumentにあるページ

### 1-1 Webからテーブルのパース
・データの取得の中に、その他へカテゴライズされている「Web」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627617/f6a5a664-7b8b-88fa-d115-e0dcf12202d5.png)

・さっきのURLをいれてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627617/22dd31c1-57e2-6067-93d5-6303f0e7cec0.png)

・Power BIからパースできるテーブルをいくつか提案してくれる
今回はHTMLにうめこまれているテーブル１にチェックを入れてデータの変換を選択
読み込みをする前にデータをきれいにしたほうがいい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627617/230ef470-451a-4b31-5b02-ff2627698c85.png)

・データクレンジング
今回はあんまり複雑なことはしないが、
特によく使う「一行目をヘッダーへ使用」を実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627617/2a41ddf6-14fb-7eef-8247-8f61788799bc.png)

## 2.　地図ビジュアルにプロット
Metroporitan areaをもとにプロットして、そこにあるプロバイダーの数を一意でカウントする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627617/52d8f1e0-8887-28b5-e55c-2a266fe279e8.png)

## 最後に
今後はAWSやAzureなどなどを同様にデータソースへ追加して、比較検討できるようにしていきたい
ローカルからSAP CloudPlatform CF環境へデプロイする際に詰まった話

# はじめに
前回、「[ローカルからSAP CloudPlatform CF環境へデプロイする](https://qiita.com/again_qt/items/854f8473d03f1a745eff)」という記事を書きました。
こちらの記事の通りにしばらくは順調にデプロイができていたのですが、ある日デプロイができなくなり、詰まってしまったのでその原因と解消法について、備忘録として書いていきます。

# 詰まった内容

```
cf deploy mta_archives/xxxxxxxxxx.mtar 
```

このように、cf deployコマンドを実行しようとしたところ以下のようなエラーが出ました。

```
'deploy' は登録済みコマンドではありません。
```

このエラーにより、ローカルからCF環境へデプロイができなくなってしまいました。

# 原因
cfのバージョンがこれまでは6.51.0だったのですが、いつの間にか6.52.0に上がっていたことが原因でした。

```
//前回の記事投稿時点でのバージョン
$ cf -v
cf バージョン 6.51.0+2acd15650.2020-04-07

//デプロイができなくなった時点のバージョン
$ cf -v
cf バージョン 6.52.0+b086fe522.2020-08-26
```

# 解消法
以下のコマンドを実行してプラグインをインストールすると、deployコマンドが実行できるようになりました。

```
cf install-plugin  multiapps
```

同じエラーに詰まった際は、上記のコマンドで解決できるかと思います。
ご参考になれば幸いです。
RSpecの導入方法

# 概要
###どのよう手順でRSpecを導入するのか。忘れてしまう場面が度々ありましたのでここに記述します。

# RSpecの導入手順
## １.Gemfileに「development, :test」内に「gem 'rspec-rails', '~> 4.0.0'」を記述する。
```ruby
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0'
end
```
##2.ターミナルで「bundle install」を記述

##3.ターミナルで「rails g rspec:install」を記述

##4.　.rspec内に「--format documentation」を記述する。(ターミナル上でテストコードの結果を可視化するため)
```ruby.rspec
--require spec_helper
--format documentation
```

##5. ターミナルでテストコード用のモデルを作成する。
### rails g rspec:model モデル名

### 以上の手順でRSpecの導入を行うことが出来る。
[git]間違えてmergeしちゃった！mergeを取り消したい！

##この記事の目的
間違えてローカル上で間違えてmergeしてしまったとき、mergeを取り消す方法を記録します。

##手順の概要
mergeしてしまった場合に、そのmergeする前のコミットまで地点まで戻るという方法

##コマンド

```ターミナル.
$git log
commitのログを確認し、mergeされる前のコミット番号を探す。見つかったらコピーしておく。

$git reset --hard ##################################
###には上記でコピーした番号を入力する

```

上記でmerge前の状態に戻ることができる。
pandas でセルに色をつけて xlsx で保存するメモ

## 背景

pandas にセルに色をつけて(e.g. マイナスの数値は赤), オシャンティな xlsx を作りたい.

## 色をつける

スタイルを指定することで実現します.

https://stackoverflow.com/questions/28075699/coloring-cells-in-pandas

ありがとうございます. `subset` で処理したい column を指定できます.

## xlsx に保存

https://stackoverflow.com/questions/56304652/python-pandas-style-background-color-not-visible-in-excel-file


`pd.style.apply(highlight)`

だけだと反映されません!

`pd = pd.style.appy(highlight)`

のように新しくオブジェクトを作る必要があります!

あとは `to_excel` なりで保存して.

環境によっては `Jinja2` のインストールを要求されるかもです!
VSCodeのUser Snippetsを設定したら幸せになった

## はじめに

VSCode はプログラミング以外にも、打ち合わせの議事録だったりちょっとしたメモでも愛用していて、
特に Markdown 形式で書くといい感じにきれいになるのでかなり使っています。


少し設定をいじるだけでかなり便利で幸せになったのでその紹介です！
（ググればたくさん出てくる内容ではありますが、便利だったので改めて書いてみました😏

## やりたいこと

Markdownを書いている最中にさくっと **今日の日付** を挿入したい。

## やりたいことのイメージ
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/60c2cda4-a955-da90-a11a-4e628b9c028d.gif)

## 設定方法

左下の歯車より `User Snippets` を選択
![スクリーンショット 2021-04-20 19.17.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/f33e4c87-a4d4-2b12-263e-9f57f1d49553.png)
上からリストが出るので`markdown.json` を選択
![スクリーンショット 2021-04-20 19.18.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/96aa7001-7bf5-b1f0-d9ce-62e779e9fc99.png)
こんな感じに記述
![スクリーンショット 2021-04-20 19.20.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/5b2db50f-3bca-5c16-25fb-7b1545eab733.png)

```json
"today": {
  "prefix": "today",
  "body": [
    "$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE",
  ],
  "description": "Insert today's date",
 }
```

## 結果

入力中にエンターキー押せば予測変換で勝手に出てくる！！（↓では`tod`だけで！）
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/60c2cda4-a955-da90-a11a-4e628b9c028d.gif)
例えば `YYYY/MM/DD` にしたければ、
body 部分を `"$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE"` と書けばOKです！
prefix をいじれば好きなキーワードで挿入できます！

### 余談

議事録のテンプレとかも設定できて便利〜
![memo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/56f4b610-04bd-7c8c-52e7-7e74fd8591b3.gif)

```json
"vsnote_template_memo": {
  "prefix": "vsnote_template_memo",
  "body": [
    "---",
    "date: $CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE",
    "tags:",
    "  - memo",
    "---\n",
    "# $CURRENT_YEAR$CURRENT_MONTH$CURRENT_DATE-$TM_FILENAME_BASE\n",
    "## 議題・やること\n",
    "## 決定事項\n"
  ],
  "description": "Meeting Template",
}
```

## おわりに

特定のMTG用とかメモ用とかブログ用とかたくさん作ればそれだけ幸せになりますね
調子乗って作りすぎるとメンテしにくくなるのでそこは要注意です！

それでは！≧(+･` ཀ･´)≦
Koalasのご紹介

[Koalas \| Databricks on AWS](https://docs.databricks.com/languages/koalas.html) [2021/4/15時点]の翻訳です。

[Koalas](https://github.com/databricks/koalas)は、[pandas](https://pandas.pydata.org/)の補完材を提供するオープンソースプロジェクトです。主にデータサイエンティストによって用いられるpandasは、簡単に使えるデータ構造とPython言語向けのデータ分析ツールを提供するPythonのパッケージです。しかし、pandasは大量データに対してスケールしません。KoalasはApache Sparkで動作するpandasと同等のAPIを提供することでこのギャップを埋めます。Koalasはpandasユーザーにとって有益であるだけではなく、Koalasは例えばPySparkデータフレームから直接データをプロットするなど、PySparkで実行するのが困難なタスクをサポートするので、PySparkユーザーにも役立ちます。

# 要件

- KoalasはDatabricksランタイム7.3以上が稼働するクラスターに含まれています。
- Databricksランタイム7.0以下でKoalasを使用するには、Databricksの[PyPI library](https://docs.databricks.com/libraries/workspace-libraries.html#pypi-libraries)としてKoalasをインストールします。
- IDE、ノートブックサーバー、Databricksクラスターに接続する他のカスタムアプリケーションででKoalasを使用するには、[Databricks Connect](https://docs.databricks.com/dev-tools/databricks-connect.html)をインストールし、[Koalas installation instructions](https://koalas.readthedocs.io/en/latest/getting_started/install.html)に従ってください。

# ノートブック

以下のノートブックでは、どのようにpandasからKoalasに移行するのかを説明しています。

- [10分でpandasからKoalasに移行](https://github.com/taka-yayoi/public_repo/tree/main/pandas_to_Koalas)

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
【Google Spread Sheet】RDBのように複数シートを紐づける方法


# はじめに

「幾つかのデータを紐づけて処理したいけれど、わざわざRDBを使うほどではない...」という時に、どのように対処するでしょうか？

RDBを使う人もいれば、Excel上で関数を駆使する人もいると思いますが、今回はGoogle Spread Sheetを使って「テーブルのJOINのような操作」を実現する方法を調べた結果を記事としてまとめてみました。

# 使用するデータ

## 球団マスタ

* 以下のデータを「球団」という名前のシートに記述します。

|ID|球団名|
|---|---|
|1|巨人|
|2|中日|
|3|ヤクルト|
|4|広島|
|5|DeNA|
|6|阪神|
|7|ソフトバンク|
|8|西武|
|9|楽天|
|10|ロッテ|
|11|日本ハム|
|12|オリックス|

## マスコットマスタ

* 以下のデータを「マスコット」という名前のシートに記述します。

|ID|球団ID|名前|
|---|---|---|
|1|1|ジャビット|
|2|1|シスタージャビット|
|3|1|キッズジャビット|
|4|1|おじいちゃんジャビット|
|5|2|ドアラ|
|6|3|つば九郎|
|7|3|つばみ|
|8|4|スラィリー|
|9|5|DB.スターマン|
|10|6|トラッキー|
|11|7|ハリーホーク|
|12|7|ハニーホーク|
|13|7|ハーキュリーホーク|
|14|7|ホンキーホーク|
|15|7|ヘレンホーク|
|16|7|ハック|
|17|7|リック|
|18|7|ホック|
|19|8|レオ|
|20|8|ライナ|
|21|9|クラッチ|
|22|9|クラッチーナ|
|23|10|マーくん|
|24|10|リーンちゃん|
|25|10|ズーちゃん|
|26|11|フレップ|
|27|11|ポリー|
|28|12|バファローブル|
|29|12|バファローベル|

## バッファ用シート

* データを一時的に書き出すバッファ用シート（シート名：buffer）を用意します。

# 作成したコード

* 球団名の「ヤクルト」に紐づくマスコットの名称をメッセージボックスに表示します。
* 1つの球団に紐づくマスコットは、1ないし複数となっている点に注意が必要です。

```javascript
function FindRelationRecords() {
  
  const SHEET_team = "球団"
  const SHEET_official_mascot = "マスコット"
  
  // シート関数のQUERYを使って、球団シートから指定した球団名（※B列）に該当する球団ID（※A列）を取り出す。
  let query_team = '=QUERY(\'' + SHEET_team + '\'!A1:B13,"SELECT A WHERE B=\'ヤクルト\'")'
  // 球団IDをbufferシートに書き込む
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("buffer").getRange(1, 1).setFormula(query_team)
  // (1,1)セルは列名が書き込まれているため、1つ下の(2,1)セルから球団IDを取得する。
  let team_id = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("buffer").getRange(2, 1).getValue()
  
  // bufferシートをクリアする
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("buffer").clear()
  
  // 球団IDをキーにして、マスコットを取り出す。
  let query_mascot = '=QUERY(\'' + SHEET_official_mascot + '\'!A1:C30,"SELECT C WHERE B=' + team_id + '")'
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("buffer").getRange(1, 1).setFormula(query_mascot)
  let mascot_names = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("buffer").getDataRange().getValues()
  
  // 配列の先頭の要素（※列名）を削除してメッセージボックスに出力する。
  mascot_names.shift()
  Browser.msgBox(mascot_names.join(','))
}
```

# 実行結果

* 球団名の「ヤクルト」に紐づくマスコットの名称が、メッセージボックスに表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/974c70d1-8198-7621-6c57-f94ac1d83dd0.png)

# 課題点

* Query関数の結果をバッファ用シートに書き出しているため、ちょっとした処理にもかかわらずコード数が増えてしまっています。
 * バッファ用シートを使わない方法があるかを調べてみましたが、Query関数を使う場合はシートへの書き出しが必須のようです。
* 処理が遅いので、大量のデータを処理するのには全く向いていないです。
 * もしかすると劇的に処理速度を速める方法があるのかもしれませんが、GAS初心者の私にはそれが分かりませんでした...
Docker + PHP + MySQL5.6環境でのエラー：mysqli_connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known

```
mysqli_connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known
```

「サービス名をdbにしなかったか、それともユーザー・db名を書き間違えただけだろう♪
こんなの余裕.....。**記述はあっている！！**」

なぜ、エラーに？？？

「dbに接続できないってことだけど、コンテナの状況は？？」

```
$docker-compose ps 

mysqld      Exit 1
```

「　**エラーになっている！！！**
　　なぜ？？？　　　　　　　　」

コンテナがそもそも起動できていないから、入れない。
だけど、どうしてだろう？？
ログをみてみよう

````
$docker-compose up
````
dbのログはどうなっているだろうか？？？

```
Plugin 'FEDERATED' is disabled.
```

これが原因ぽい
調べたら[この記事にたどり着いた](https://sh2.hatenablog.jp/entry/20091002)けど、

```:my.cnf
federated = 1
```
にすると解決するらしい

**「ん？？？治らんぞ」**

````:エラー
Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
````
これが表示されるから、他に方法があるはず



````:エラー
mysqld: unknown variable 'log_timestamps=SYSTEM'
````
今度はこのエラーが表示されたか
どうもmy.cnfの書き方がMySQL5.6と5.7では違うらしい
5.6の書き方に合わせて

````:my.cnf
explicit_defaults_for_timestamp = 1
````
上記を追記して、
改善

# 気付き
my.cnfまわりはバージョンによって書き方が異なるようだから、注意が必要
また、dockerのログをみないと気づけないエラーなので、docker-compose upなどでログをみていくべき
Azure PlayFab ロードマップ2021年4月(和訳)

[こちら](https://blog.playfab.com/blog/playfab-roadmap-update-april-2021)のページを日本語訳したものになります

今後は4半期ごとにロードマップは公開される予定(次回は2021年7月頃)
機能アップデートフォーラムの「[機能リクエスト](https://community.playfab.com/spaces/24/index.html)」に投稿された内容を元に反映するので、たくさんのコメント・投票お待ちしております
(もちろんバグ報告もお願い致します)


### 直近のアップデート
〇価格
・使用料ベースの価格が新しい価格プラン更新されました
・最低価格のない従量課金プラン(Pay-as-you-go)
・Developerモードでの最低プレイヤー数を増やし(現在は100,000プレイヤーまで)

〇マルチプレイヤーサーバー
・マルチプレイヤーサービスの対応地域が大幅に拡大しました
・AMD SKU のサポートを追加し、マルチプレイヤーの最適化された仮想マシンの価格性能性比を向上させました
・新しいAPIエンドポイントが追加され、セルフサービスによるクォータ要求やサービスビルド名の更新が可能になりました

〇PlayFab Party
・Unityプラグインが複数のプラットフォームに対応(Game Developer Kit（GDK）、Windows、Nintendo Switch、PlayStation 4 & 5、iOS、Android)
・Unreal Engine4プラグインがGame Developer Kit（GDK）およびWindowsに対応
・Partyの大幅なディスカウントを実施しました(Xboxユーザ同士での利用は無料です)

〇PlayFab Experiments
既存のA/Bテストに変わる機能になります
・実験での相互作用効果を防ぐために除外グループを作成することが可能
・複数の実験を同時に行うことが可能に
・タイトルデータにタイトルデータオーバーライドが追加され、ゲーム事件を迅速に管理できるようになりました
・プレイヤーグループを作成や管理が行えるセグメンテーションCRUD API をリリースしました

〇PlayFab Insights
・無料アカウントとDeveloper モードでも Insight が有効になりました
・イベント・サンプリングとカスタムデータリテンションが実装されました
・データエクスプローラーのパブリックプレビューを開始

### アップデート予定
※あくまで計画で日程なども未確定です

〇Cloud Script の Azure Functions 利用
Azure Functions の対応により C#だけではなくほかの言語のサポートやVisual Studio や VSCode のローカルデバックが可能になります
(Azure Functions への対応はPublic Previewです)

〇UGC(User Generated Content) とEconomy V2
Economy V2 のパブリックプレビューに向けた準備を実施中。
UGCは2021年7月に、Economy V2 API は2022年初頭にパブリックプレビューを開始予定

〇マッチメイキング
現在パブリックプレビューで利用可能です。
ポーリングを避けるためのリアルタイム通知ソリューションやマルチプレイヤーの状態を管理するためのロビーやセッションサービスなどを開発中です。
また今年後半にプライベートプレビュー予定のマルチプレイヤーサービスに関しても今後をご期待ください

〇ランキング V2
現在一部のお客様にプライベートプレビュー中です。
他の機能開発中のため、2021年秋ころに開発を再開予定です。


新機能に関してご興味やお試しされたい場合はMicrosoftの担当営業にご連絡ください。

また様々なフィードバックお待ちしております
カウントダウンメニュー


https://www.amazon.co.jp/%E7%A2%BA%E3%81%8B%E3%81%AA%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8FJavaScript%E3%80%8C%E8%B6%85%E3%80%8D%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E7%8B%A9%E9%87%8E-%E7%A5%90%E6%9D%B1/dp/4815601577

上記の書籍を参考にして行きます。

#カウントダウンタイマー
１、Dateオブジェクトの時間を設定する。
Dateオブジェクトは、日時を扱うためのオブジェクトです。
できることは、以下のようになります。
　①　現在日時を取得する。
　②　過去や未来の日時を設定する
　③　日時の計算をする

このオブジェクトは、１つの基準日を記憶しています。そのため、最初に初期化して使う事になります。また、初期化して()内にパロメータを含まない場合は、現在日時を記憶した状態で初期化されます。これを、プログラミングではインスタンスといいます。


```index.html
<script>
let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);

console.log(countdown(goal));
const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
document.getElementById('timer').textContent = time;
</script>
```
このときに、最初の変数ｇoalに初期化した現在日時を代入することで、初期化を図る事ができます。
次に、個々に時間と分、秒を取得します。
開いてるページの最後の時刻が設定されます。

ここで、値を作った後に、カウントダウンファンクションを作ります。

```index.html
<script>
function countdown(due) {
    const now = new Date();

    const rest = due.getTime() - now.getTime();
    const sec = Math.floor(rest / 1000) % 60;
    const min = Math.floor(rest / 1000 / 60) % 60;
    const hours = Math.floor(rest / 1000 / 60 / 60) % 24;
    const days = Math.floor(rest / 1000 / 60 / 60 / 24);
    const count = [days, hours, min, sec];

    return count;
}
</script>
```

関数の処理の中(due)に先程、作ったDateオブジェクトを受け取ります。
定数const(これは変わることのない)を初期化した日時を代入します。
getTimeメソッドは、1970年1月1日０時０分からを基準にします。
これを、Dateオブジェクトで取得した日時から引いています。その値を定数restに代入しています。
このミリ秒をもとに秒、分などを計算しています。
すべて出揃ったところで、これらを配列として、定数カウントに代入します。
配列とは、複数のデータを１つにまとめるときに使います。
また、これらを呼び出すためにリターンで返します。

最初に関数による処理を作って、console.log(counddown(goal));で配列を呼び出すことができます。

Math.floorとは、小数点を切り捨てる場合に使用します。

では、これをコンソールに呼び出していきます。

```index.html
const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
console.log(time);
document.getElementById('timer').textContent = time;
```
定数カウンターにcountdown(goal)を代入し、定数timeにcountdown(goal)に保存した値をindex番号順に呼び出し、代入します。
そして、それらの値をconsole.logで呼び出します。

![スクリーンショット 2021-04-20 18.57.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/63d8e29d-6ec9-5e3f-112d-1288b504e55f.png)


またこれらをHTMLに出力する場合は、まずidに紐づけます。そして、textContentでテキスト情報を取得します。
これが左のコードです。そしてtimeに代入して出力します。

>参考　
>https://www.amazon.co.jp/%E7%A2%BA%E3%81%8B%E3%81%AA%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8FJavaScript%E3%80%8C%E8%B6%85%E3%80%8D%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E7%8B%A9%E9%87%8E-%E7%A5%90%E6%9D%B1/dp/4815601577