OmniAICreator/Qiita-1.07M huggingface dataset:
Errno::ENOSPCが表示された時

rails sでサーバーを立ち上げようとすると、Errno::ENOSPCの表示が。
![スクリーンショット 2021-05-12 22.34.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340120/c700c684-0af0-f9bf-a17d-0d9359747da2.png)

###エラー内容
まずこのエラーの内容を確認すると、「No space left on device」の文字が確認でき、これは容量不足を示しています。
こいつが起きると何も操作ができなくなってしまい、だいぶやっかいです。
この容量不足には、ディスクの容量不足とinodeの容量不足の2パターンがあります。

##解決に向けて　
※出力結果は例となります。

まずは以下コマンドにて、現在の使用容量を確認します。

```:ターミナル
$ df

>ファイルシス   1K-ブロック    使用  使用可 使用% マウント位置
devtmpfs     492676       0  492676    0%  /dev
tmpfs        503448       0  503448    0%  /dev/shm
tmpfs        503448     472  502976    1%  /run
tmpfs        503448       0  503448    0%  /sys/fs/cgroup
/dev/xvda1   8376300 5655364 2720936   68% /
tmpfs        100692       0  100692    0%  /run/user/1000
```
ここでは使用%という部分が、現在のディスク使用率を表示しています。
ここが100%になっていれば、ディスク容量が一杯になっています。
※ここでは容量不足解消後の出力結果なので、100%のものはありません。

続いてinodeの容量確認ですが、こちらは先ほどのコマンドに-iを追加します。

```:ターミナル
$ df -i

>ファイルシス   Iノード  I使用   I残り   I使用% マウント位置
devtmpfs    123169    284  122885  1% /dev
tmpfs       125862      2  125860  1% /dev/shm
tmpfs       125862    373  125489  1% /run
tmpfs       125862     16  125846  1% /sys/fs/cgroup
/dev/xvda1  4193216 127452 406576  4% /
tmpfs       125862      1  125861  1% /run/user/1000

```
こちらもI使用％という部分を確認して、ここが100%になっていれば、inodeの容量不足となります。

上記コマンドで容量不足の確認ができたところで、不要なファイルを削除していきます。
まず、どのファイルが容量を圧迫しているか確認する必要があるので、以下コマンドで確認します。

```:ターミナル
$ find / -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -nr

>  59177 usr
  33328 home
   4025 var
    526 etc
     16 opt
     13 boot
      1 swapfile1
      1 .autorelabel
```
こんな感じで、左側にファイル数、右側にディレクトリが表示されるかと思います。
ファイル数が多いものが容量を圧迫しているので、更にその中で圧迫の原因となっているものを探っていきます。
先ほどの出力結果だと、usrディレクトリのファイル数が多かったので、これを更に深めていきます。(findの後に確認したいディレクトリ名を記載します。)

```:ターミナル
$ find /usr -xdev -type f | cut -d "/" -f 3 | sort | uniq -c | sort -nr

> 28277 share
  17869 lib
   7387 lib64
   3676 include
    929 bin
    526 local
    377 sbin
    136 libexec
```
ここではディレクトリ別のファイルが表示されています。この操作によって、ファイル数が多く、不要なディレクトリを探します。

上記コマンドでディレクトリを特定できれば、次はそれを削除していきます。
削除する時は、以下コマンドを使用します。

```:ターミナル
$ sudo rm -rf ディレクトリ名
```
例えば先ほどの出力結果だと、usr/shareが多かったので、これを削除する場合、
「$ sudo rm -rf usr/share」となります。

このコマンドは-rfがついているため、コマンドを実行すると強制的に削除が実施されるので、必要なファイルを削除しないようにご注意ください。

不要なファイルを削除したらもう一度、「df (-i)」コマンドにて使用率を確認して、使用容量が減っているか確認してみてください。
(2021年5月時点) VSCodeのPythonのバージョン更新で有効になったセマンティックハイライトを無効にする

> 2021年5月時点の話です

VSCodeでPythonのコードを開いてみたところ、何か変数とかの色の付き方に違和感が...

![スクリーンショット 2021-05-13 18.25.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303105/17941858-f4d6-eb4c-1ded-e003235c9fce.png)

今までは`self`が青だったし、全体的に変数やメソッド名がこんな水色ではなかったような？
この色の付け方はなんか気持ち悪いから前のバージョンに戻せないかな...と思い色々調べてみたところ

- 2021年5月にPython拡張機能が更新され、Pylanceがデフォルトで使用されるようになった

[Visual Studio Code向けPython拡張機能の2021年5月版が登場、Pylanceがデフォルト言語サーバに：CodeZine（コードジン）](https://codezine.jp/article/detail/14122)

- Pylanceのセマンティックハイライトは、これまでのVSCodeのPythonのデフォルトだったTextMate文法とは異なるルールで色付けしている

[Semantic highlighting colors every variable with same color · Issue #323 · microsoft/pylance-release · GitHub](https://github.com/microsoft/pylance-release/issues/323)

ということが分かりました。

このセマンティックハイライトは、settingsのjsonに以下の記述を追加することで無効化できるようです。
(上記のGitHubのissuesのコメント参照)

```json
{
  "[python]": {
    "editor.semanticHighlighting.enabled": false
  }
}
```

上記の設定追加後、馴染みの色に戻っていることが確認できました。

![スクリーンショット 2021-05-13 18.36.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303105/ce5274de-a59c-8161-f0a2-682cc65baad8.png)
kubernetes上にnginxを構築する方法メモ

# 目的
kubernetes上にwebサーバであるnginxを構築する方法のメモ

# Ref
https://kubernetes.io/ja/docs/tasks/run-application/run-stateless-application-deployment/

# Step1
- kubernetes環境は、お試しなのでkatakodaを使う。
- 以下にwebブラウザでアクセスしてkatakoda環境を立ち上げる。

https://www.katacoda.com/courses/kubernetes/playground

# Step2
- katakoda上でlaunch.shを実行。
- すると2ノード構成のkubernetes環境が立ち上がる

```bash:bash
controlplane $ launch.sh
```

# Step3
nginxのdeploymentをwgetで取得する

```bash:bash
$ wget https://k8s.io/examples/application/deployment.yaml
```

# Step4
nginxをdeployする

```bash:bash
$ kubectl apply -f deployment.yaml 
```

# Step5
nginxへ外部からアクセスできるようにserviceを作成する

```bash:bash
$ kubectl expose deployment/nginx-deployment --type="NodePort" --port 80
```

# Step6
nginxへhttpアクセスする

```bash:bash
curl http://localhost:31235
```

# Step7
nginxをversion upする

```bash:bash
controlplane $ git diff
diff --git a/deployment.yaml b/deployment.yaml
index dbed8bc..21cdbb1 100644
--- a/deployment.yaml
+++ b/deployment.yaml
@@ -14,6 +14,6 @@ spec:
     spec:
       containers:
       - name: nginx
-        image: nginx:1.14.2
+        image: nginx:1.16.1
         ports:
         - containerPort: 80
controlplane $ kubectl apply -f deployment.yaml 
controlplane $ kubectl describe pod nginx-deployment- | grep Image
```

# Step8
nginxをスケールアウトする（2台から4台へ）

```bash:bash
controlplane $ git diff
diff --git a/deployment.yaml b/deployment.yaml
index dbed8bc..2314cf6 100644
--- a/deployment.yaml
+++ b/deployment.yaml
@@ -6,7 +6,7 @@ spec:
   selector:
     matchLabels:
       app: nginx
-  replicas: 2 # tells deployment to run 2 pods matching the template
+  replicas: 4 # tells deployment to run 2 pods matching the template
   template:
     metadata:
       labels:
@@ -14,6 +14,6 @@ spec:
     spec:
       containers:
       - name: nginx
-        image: nginx:1.14.2
+        image: nginx:1.16.1
         ports:
         - containerPort: 80
controlplane $ kubectl apply -f deployment.yaml 
controlplane $ kubectl get pod -w
```


# 残タスク
- nginxのconfigの変更方法の記載
- nginxへのhtml/css/jsなどのstaticファイルの配置方法の記載
MinecraftでMODを開発したい#4

*MinecraftでMODの開発をします*
*試行錯誤を書いていくだけのものになります*

##概要
MOD一覧などに表示される情報の登録

##動作環境 2021/05/12
||Version|
|:-:|:-:|
|Mac OS Big Sur|11.1|
|IntelliJ IDEA|2021.1.1|
|AdoptOpenJDK (HotSpot)|1.8.0_282|
|Minecraft|1.16.5|
|Forge|36.1.0|

##目次
-　リソースパックの情報
-　mods.toml
-　ロゴ画像
-　build.gradle 


##リソースパックの情報
```src/main/resources/pack.mcmeta
{
    "pack": {
        "description": "Example Mod Resources",
        "pack_format": 6
    }
}
```

##mods.toml
```src/main/resources/META-INF/mods.toml

modLoader = "javafml"
loaderVersion = "[36,)"
license = "The Unlicense"
issueTrackerURL = "https://www.xxxxxx.com

[[mods]]
modId = "examplemod"
version = "${file.jarVersion}"
displayName = "Example Mod"
displayURL = "https://www.xxxxxxxxxx.com
logoFile = "logo.png"
credits = "xxx"
authors = "xxxxx"
description = "練習用MOD"

[[dependencies.examplemod]]
modId = "forge"
mandatory = true
versionRange = "[36,)"
ordering = "NONE"
side = "BOTH"

[[dependencies.examplemod]]
modId = "minecraft"
mandatory = true
versionRange = "[1.16.5,1.17)"
ordering = "NONE"
side = "BOTH"
```
MODの読み込みや一覧表示に使われる情報を記述

licenseはMODの利用条件を指定
このMODは例なので「Unlicense」という極めて緩いライセンスを採用
デフォルトはAll rights reserved（すべての権利を留保する）で、著作権法上の例外や別途の許諾を除き、複製や再配布などを禁止
Modpackでの利用や改変、再配布などをどこまで許容するか考え、自分で利用条件を決めたり、既存のライセンスを選ぶ

issueTrackerURLは不具合の報告を受け付けるURL、logoFileはロゴ画像のファイル名、creditsは謝辞をそれぞれ指定
issueTrackerURL、displayURL、logoFile、credits、authorsは無くても問題なし

descriptionなどでTOMLの複数行文字列を使うと、改行コードをCRLFにして保存した時にCRが正常に表示されないため、LF（\n）だけで改行しています。改行コードをLFにして保存すれば、複数行文字列も問題なく使える

##ロゴ画像
`src/main/resources/logo.png`


##build.gradle 
元のbuild.gradleからの変更点

- groupをcom.ドメイン名.examplemodに、archivesBaseNameをexamplemodに変更
ビルド時に出力されるファイルの名前は(archivesBaseName)-(version).jar

- minecraft { runs {内の4つのexamplemodをexamplemodに置換(今回は同じのため置換なし)
JSONファイルの自動生成を行う時に必要になる設定

- jar {とmanifest {との間に行を追加し、compileJava { options.encoding = 'UTF-8' }を挿入
コード内コメントに日本語が入っていた時の文字化けを防ぐため、文字コードを指定

- jar { manifest { attributes([内のSpecification-TitleとImplementation-TitleをExample Modに、Specification-VendorとImplementation-Vendorを任意のものに変更
jarファイル内のMETA-INF/MANIFEST.MFに記載される情報
 

##確認
![スクリーンショット 2021-05-13 18.37.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1482491/6b476b11-fc94-0413-1198-cf43290b3276.png)


######参考文献
https://www.tntmodders.com/tutorial/info-1165/
Ubuntuでpythonのバージョンを切り換える

pythonのバージョンを管理したり切り替える方法です

# 現在使う設定になっているpythonのバージョンを確認
```
$ python --version
Python 2.7.17
```
確認すると、python3を使いたいのですがpython2系の設定になっているようです

# インストールされているpythonのバージョンと場所を確認
```
$ which python    #すべてのpythonがインストールされている場所を確認
/usr/bin/python    #/usr/bin以下にあるようです
$ ls /usr/bin/ | grep python    #/usr/bin/以下にインストールされている全pythonのバージョンを確認
python2
python2.7
python3
python3.6
python3.6-config
python3-config
```
# update-alternativesが存在することを確認
update-alternativeはpythonのバージョン管理を行います。

```
$ which update-alternatives
/usr/bin/update-alternatives
```

# pythonのバージョン登録・管理
登録されているpythonのバージョンや優先順位を見ることができます

```
$ sudo update-alternatives --config python
update-alternatives: error: no alternatives for python    #まだpythonが登録されていない状態です
```

pythonのバージョンを登録します
sudo update-alternatives --install [pythonの場所] python [pythonの場所][バージョン] [優先順位の数字]
今回はpython3.6と2.7を登録してみます

```
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 1    #python3.6を優先順位1で登録
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 2    #python2.7を優先順位2で登録
```
登録されたpythonのバージョンやリストの順、優先順位を確認

```
$ update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python2.7   2         auto mode
* 1            /usr/bin/python2.7   2         manual mode
  2            /usr/bin/python3.6   1         manual mode
Press <enter> to keep the current choice[*], or type selection number: 2    #python3.6を使用したいのでSelectionの2を入力
update-alternatives: using /usr/bin/python3.6 to provide /usr/bin/python (python) in manual mode
$ python --version    #使用する設定になっているpythonのバージョンを確認
Python 3.6.9

```

無事python3系に切り替えられました！
CML2におけるubuntuのSSH設定

# この記事について
CML2内に立てたubuntuサーバからCiscoノードに対してsshができなかった時の対処方法

```
$ ssh cisco@10.10.0.2
Unable to negotiate with 10.10.0.2 port 22: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
```

# 必要なSSH設定
- 原因は新しいサーバでは古い暗号化方式がデフォルトではサポートされなくなっている
- SSHクライアントにSSHサーバが使用している鍵交換方式と、共通鍵暗号化方式を設定

```:~/.ssh/config
Host 10.*
  KexAlgorithms +diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 # 鍵交換方式の指定
  Ciphers aes128-ctr,aes192-ctr,aes256-ctr #共通鍵暗号化方式の指定
```

共通鍵暗号化方式はOSによってConfig内に記載あり。
共通鍵暗号方式がサーバの指定するものと一致しない場合、正しいパスワードを入力してもログイン不可。

```
iosvl2-0#sh run | i ssh
ip ssh version 2
ip ssh server algorithm encryption aes128-ctr aes192-ctr aes256-ctr
ip ssh client algorithm encryption aes128-ctr aes192-ctr aes256-ctr
```


以上

# 参考記事
[OpenSSHの暗号化周りの設定について](https://qiita.com/aqmr-kino/items/8c3306ea8022b0d5cbe4)
AWS S3 からバケットごと一括でダウンロードするとき手順メモ

AWS S3 からバケットごと落としてくるとき自分用メモです。
初めてされる方は公式ドキュメントを読みましょう。

## aws コマンドのインストール

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html

```shell
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --version
```

## 接続情報の設定

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html

```
aws configure
```

## バケット取ってくる

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-copy

```
mkdir bucket-name
aws s3 cp -r s3://bucket-name ./bucket-name/ --exclude "*_logs*" --recursive
```
フルカラー7セグLED(WS2813-7segPanel)で電子サイコロを作ろう

# はじめに
フルカラーLEDのWS2813Bを7セグLED風に並べて数字を表示する基板(WS2813-7segPanel)を作成したので、その基板を1電子サイコロを作成します。
基板の表面に手をかざすとハンドパワーで1から6のランダムな数字が回転して停止します。

#基板の説明
基板単体の大きさは82×100mmの大きさで、表面にはWS2813Bを24個実装して7セグ風の数字と、ピリオド(.)とコロン(:)表現できます。また右上に温度、湿度、気圧センサのBME280と、中央下側に照度センサを搭載しています。
裏面は制御用マイコンWROOM-02とその周辺回路となっています。
![単体表裏.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146211/0c578f8a-4ce9-9f74-627c-b56fced0226a.png)
基板の入手方法は[スイッチサイエンス殿](https://www.switch-science.com/catalog/7166/)で販売させてもらってます。

#完成品
完成品の動画です。
手を基板に近づけるとLEDの文字回転し始めます。だんだん変化する速度が遅くなり停止したら点滅するようにします。

<iframe width="560" height="315" src="https://www.youtube.com/embed/Qopp2jRZ_7U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

#プログラム
####仕様
・明るさが暗いから明るいに変化した時にサイコロをスタートする。
・LED色は乱数で決定する。
・数字は乱数で生成して30回変化して停止する。
・同じ数字が連続して表示しないようにする。
・変化する速度は徐々に遅くなり停止する。
・停止後、数字を3回点滅する。

```C++:Dice.ino
/*******************************************************
　電子サイコロ
********************************************************/

#include "WS2813Panel.h"

WS2813Panel MyPanel(1);

uint32_t color[] = {0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff, 0xffffff};
uint8_t bright = 0x20; //明るさ
//uint16_t swstat = 0;   //ボタンの状態記録用　チャタリング防止

int PreBright = 0xff;
int CurBright = 0;

//-------------------------------
void setup()
{
    Serial.begin(115200);
    Serial.println("Program Start");

    Serial.println("LED Initialze");
    MyPanel.Begin();
    //   MyPanel.SetBrightness(bright);
    //明るさ自動調整ON
    MyPanel.AutoBright = true;
    delay(10);
    MyPanel.Clear();
    MyPanel.DispNum(0, 0, 0xffffff);
    MyPanel.Show();
}
//-------------------------------
void loop()
{
    CurBright = MyPanel.GetBright();
    //    Serial.printf("CurBright = %d  PreBright = %d\n", CurBright, PreBright);
 
    if ((CurBright - PreBright) > 5 && PreBright < 5)
    {
        Dice();
    }
    PreBright = CurBright;
    delay(200);
}

//-------------------------------
void Dice()
{
    randomSeed(millis());
    int num;
    int temp;
    uint32_t clr = color[random(0, 7)];

    //数字を30回変化させる　変化する間隔はだんだん遅くなる
    for (int i = 0; i < 30; i++)
    {
        temp = random(1, 7);
        if (temp == num)
            continue;
        num = temp;
        MyPanel.DispNum(0, num, clr);
        MyPanel.Show();
        delay(i * 20);
    }
    //停止した数字を点滅3回
    for (int j = 0; j < 3; j++)
    {
        MyPanel.DispNum(0, num, 0);
        MyPanel.Show();
        delay(200);
        MyPanel.DispNum(0, num, clr);
        MyPanel.Show();
        delay(200);
    }
}

```
#基板回路図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146211/df28ab59-6668-3e6e-d1d4-85ab27bf7f52.png)

#参考リンク
[GitHub WS2813-7segPanelライブラリー](https://github.com/VEC01773/WS2813-7segPanel)
[YouTube RainClock2](https://youtu.be/SeoeUBH3Rpc)
[お天気時計](https://qiita.com/VEC01773/items/10ce7e36fe853ed73f64)
[コントローラ付基板](https://www.switch-science.com/catalog/7165/)
[コントローラ無し基板](https://www.switch-science.com/catalog/7166/)
4浪1留大学中退自称バンドマン(フリーター)と学ぶHTML 

初めまして、4浪1留大学中退自称バンドマン(フリーター)です、特技は業を背負うことです。
現在独学でプログラミングを勉強しております。

いろいろ情報を仕入れた結果、Qiita書いた方が良いよということを聞いたので備忘録も兼ねて書いていこうと思います。
しかし、普通に書いても面白くない気もするしこのような肩書きなので説得力のかけらもないと思います。
ですので、こんなハッピーポンコツ野郎でもプログラミングってできるんだし私もやってみようかな？って思える記事を書きたいなと思います。

#HTMLとは?
　まず、HTMLとはなんぞや？ということでググってみて[Techacademy](https://techacademy.jp/magazine/4843)を見てみると

>『ハイパーテキスト・マークアップ・ランゲージ（Hyper Text Markup Language）の略。簡単にいうと、コンピュータが理解できる、マークアップをするための言葉です。マークアップとは、もともと雑誌や新聞の編集用語で、文章構成の指示のことを指します。「この文章はタイトルです」「この3つの文章が1セットで記事です」というような、注釈のようなものですね。Web制作では、ホームページ上に表示をしたい文章や写真などの情報に対し、HTMLという言葉で、コンピュータに文章構成を指示することから始まります。』

とあります。この時点で???な方もいると思います。ざっくりと例えるなら__フルーツバスケット__です。何言ってんだこいつと思われる方もいると思われますしフルーツバスケットに参加したことない陰の者のために説明させてください。
　まず、フルーツバスケットというものを説明すると椅子取りゲームの一種です。以下に基本ルールやアレンジを書きました。（[wikipedia](https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%AB%E3%83%BC%E3%83%84%E3%83%90%E3%82%B9%E3%82%B1%E3%83%83%E3%83%88_(%E9%81%8A%E3%81%B3))からの引用）

#フルーツバスケットのルール
基本ルール
1.鬼役を一人決め、他の者は鬼を取り囲むように内側を向き円状に座る（椅子にかけて行うこともある）。
2.座っている参加者には一人ずつ果物の名前が割り当てられる（リンゴ、みかん、ぶどうなど）。
3.チームわけをする要領で果物の名前を割り当てておく場合もある。
4.鬼役が特定の果物の名前を呼ぶと、その果物の名前がついている人は席を交換しなければならない。
一人ずつ別々の果物の名前をあてる方式の場合には、鬼役は2つの果物の名前を続けて呼ぶことになる。チームわけをする要領で果物の名前を割り当てる方式の場合には1つでよいことになる。また、鬼が「フルーツバスケット!」と言った場合には全員が席を交換しなくてはならないとするルールもある。
鬼役はこの席の交換の機会に開いている席を取ろうとする。鬼役が席に座ることができた場合には、座れなかった者が新たに鬼役となる。
5.隣の席に移動するのは禁止。
6.該当しているのに移動しなかった場合は鬼役になる。

ルールのアレンジ例
1.呼ぶべき名前をあらかじめ決めず、「黒い靴下をはいている人」「眼鏡をかけている人」「苗字が『さ』で始まる人」などと人の特徴で呼ばせる遊び（「なんでもバスケット」や「大嵐」などの呼称がある）もある。この場合は該当者が一人しかいなかった場合は無効となる。 また、チームごとに得点を設定し、鬼が出たチームから得点を引いていき勝敗を決める遊びもある。

　ここでいう__参加者というのが文字(テキスト）__で参加者一人一人に__果物の名前という目印（マーク）__をつけ__果物を指定すると参加者が動く__という感じです。アレンジすることで眼鏡をかけてる人や過去に不倫騒動で炎上したことあるバンドマンなど果物以外の要素を持つ人を指定することもできます。フルーツバスケットでは椅子取りですがCSSというものを使えば椅子取りだけじゃなくお手手を繋がせたりバトルロワイヤルさせたりなどの指示を出すことができます。CSSについてはまた別の記事で書きたいと思います。

#まとめ
　簡単に話を整理すると__HTMLとは文字(テキスト)に目印(マーク)をつけて後で後で編集しやすくする__というものです。HTMLだけだとただ文字が並ぶだけのセリアの食器みたいなWebサイトが出来上がりますがCSSというものを用いることで文字の大きさや色を変えたり、配置や間隔を編集することが可能です。ある程度できる方から見たら違うと思われるかもしれないのですがプログラミングというものに興味を持ったばかりの人向けですのでご容赦ください。
FirebaseUIをビルドするための環境をDockerで作る

# はじめに
firebaseuiを多言語で使うには各言語用にビルドされたものが必要で、`<script>`タグでCDNから取得する場合は手間ではないんだけど、node環境など`import`して使いたければ自前でビルドする必要があって面倒くさい。
https://github.com/firebase/firebaseui-web#developer-setup

パッケージの更新や、日本語以外の対応が必要になった際に動きやすいよう、Dockerでfirebaseuiのビルド環境を作った。

なお、firebaseuiを日本語化する方法を解説した記事で、`firebaseui-ja` なるnpmパッケージを使っているのをちょくちょく見かけるけど、あれはFirebaseの公式パッケージではない。 2年前の初回登録以降メンテナンスはされていないようで、公式のfirebaseuiとはけっこうバージョンが離れている。
https://www.npmjs.com/package/firebaseui-ja

# Dockerfile
```dockerfile
FROM node:15-buster-slim

WORKDIR /node
RUN mkdir -p /usr/share/man/man1
RUN apt-get update \
    && apt-get install -y git curl default-jdk
RUN npm install -g n
RUN n 8.17.0
RUN git clone --depth 1 https://github.com/firebase/firebaseui-web.git
```

# ポイント
Docker環境を作る際に引っかかったポイントは次の２点。

## 最新のnode環境では、node-sass がビルドエラーになる
`firebaseui-web`が依存している`gulp-sass:4.1.0`が、`node-sass:4.8.3`に依存しており、最新のnode環境ではビルドできない。

node-sass のバージョンを上げるか、nodeのバージョンを下げる必要がある。
今回はnodeのバージョンを下げることで対応した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134740/05300cd4-9db3-53f7-5bf3-8c2c07090d35.png)

`node-sass:4.8.3` に対応させるためには、node 8 まで下げなければいけないらしい。
node8系の最終バージョンである8.17.0にダウングレードした。

```dockerfile
RUN npm install -g n
RUN n 8.17.0
```

[参考]
https://qiita.com/ymasaoka/items/ab18c49a9074973ef75a

## jdkが必要
firebaseuiのビルド条件は次のように指定されている。

```
Node.js (>= 6.0.0)
npm (should be included with Node.js)
Java SE Runtime Environment 8
```

なので、`default-jdk` をインストールしようとしたのだけど、うまくいかない。
対応策を調べてみると、`/usr/share/man/man1` というディレクトリを作成すると問題が回避できるらしいので、この処理をapt-getの前に行う。

```dockerfile
RUN mkdir -p /usr/share/man/man1
RUN apt-get update \
    && apt-get install -y git curl default-jdk
```

[参考]
https://qiita.com/SHinGo-Koba/items/a73e5f345c22c5ebbf96

# ビルドする
環境が整えば、あとはマニュアル通りの手順でビルドできる。

```bash
npm install
npm run build build-npm-ja
```

`ja` の部分を好きな言語コードに変更すれば、各言語版ができる。

`dist`ディレクトリの中に、`npm__ja.js` が作成されているので、これをimportして使う。
typescript用の型定義`index.d.ts`も作られている。

```bash
# ls ./dist/
externs  index.d.ts  npm__ja.js
```

```javascript
import firebaseui from './npm__ja'
```

できあがり！
Kotlin学習記

<!-- タイトル：Kotlin学習記 -->
# はじめに
### 今回はKotlinのnull安全についてJavaとの比較を交えながらまとめたいと思います。
<br>

# null安全とは？
### null安全とは、コードからnull参照の危険性を排除することを目的としたKotlinの機能であり、null参照を使用とするとコンパイルエラーが発生する。
### この機能はJavaで頻出のNullPointerExceptionを避けるために有効であると考えられます。
<br>

# Non-Null型とNullable型
### KotlinにはNon-Null型とNullable型が存在しており、以下のように実装する。
<br>

```Kotlin
var str : String  = "あいうえお" //Non-Null型
str = null //コンパイルエラー
```
```Kotlin
var str2: String? = "かきくけこ" //Nullable型
str2 = null //問題なし
```
### 上記のように、nullを格納できないNon-Null型、nullを格納できるNullable型が存在することで、潜在的なnull参照の危険性を排除し、視覚的にnullの存在を把握することができることは可読性や保守性の向上に繋がると私は感じました。
<br>

# Nullable型の処理について(ここからが本題)
### 次に、Nullable型の処理について、もう少し詳細を記述します。
<br>

## 【疑問】
### Nullable型にnullが格納できるのであれば、Nullable型の値を参照すればNullPointerExceptionが発生するのでは？
<br>

### 上記の疑問に関しては、Nullable型を参照するためにはnullが格納されていないかを事前に確認する必要があり、確認していない場合はコンパイルエラーが発生する仕組みになっている。
<br>

```Kotlin
var str2: String? = "かきくけこ"
print("この文字列の長さは${str2.length}です。") //コンパイルエラー
```
### コンパイルエラーが発生するため、nullが格納されていないことを確認する必要がある。
<br>

```Kotlin
var str2: String? = "かきくけこ"
if (str2 != null) //nullではないことを確認している
  print("この文字列の長さは${str2.length}です。")
else
  print("この文字列はnullです。")
```
<br>

### また、場合によってはエルビス演算子を用いることでより簡潔に記述できる。
```Kotlin
(Nullable型の変数)?.(trueの時の処理)?:(falseの時の処理)
```
# まとめ
Javaを学習しつつ、Kotlinを学習していると、より理解が深まりやすく利便性についても享受できると感じています。引き続き、学習していきたいと思います。
### 参考記事
https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/null-safety.html
【FE】情報セキュリティ（まとめ３）


## 1. 共通鍵暗号方式 VS 公開鍵暗号方式


|      | 共通鍵暗号方式  |公開鍵暗号方式 |
| :--- | :----: |:----:|
| 暗号化と復号の鍵 | 同じ     |  異なる    |
| 鍵の配送     | 手間がかかる |必要なし    |
| 処理速度     |早い　　      |遅い      |
| N人の相互通信に必要のカギ数|n(n-1)/2    |2n      |
| 秘密として管理すべき鍵     | 両方の共通鍵|秘密鍵のみ|
| 代表的なアルゴリズム     |AES,3DES,BlowFish |RSA,楕円曲線暗号、エルガマル暗号|


---

## 2.公開鍵暗号方式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479551/63ad98ab-cc8c-8fcb-cfec-5eb61e00130a.png)

+ メリット：データの安全性を高める。
+ デメリット：処理時間がかかる。
+ 応用：デジタル署名。

---
## 3.デジタル署名
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479551/bc45b1ab-3dd1-a316-13bd-223334de21f4.png)


---

参考資料：https://www.fe-siken.com/index_pm.html　　
　　　　　午後試験の各過去問。
KPTってなあに？

## はじめに
KPTとは仕事やプロジェクトの節目で振り返りを行うことで業務の改善を行うためのフレームワークです。
現状分析を行い、次にやるべきことを明確にするために役立ちます。

## KPTってなあに？
KPTとは(Keep/Problem/Try)の略です。
Keep/Problem/Tryそれぞれの項目について書き出していくことになります。書き出すときのポイントを下の欄でまとめているので、参考にしてみてください。

 - Keep 良かったこと(今後も持続すること)
 - Problem 問題点(改善するべきこと)
 - Try 次に挑戦すること(改善するための手段)

## KPTのやり方
 1 ホワイトボード、3色の付箋、マジックペンを用意する。
 2 Keepについて付箋に書き出して、ホワイトボードに貼っていく。
 3 Problemについて別の色の付箋に書き出して、ホワイトボードに貼っていく。
 4 Keep、Problemについて、Tryを別の色の付箋に書き出してホワイトボードに貼っていく。

 - 付箋に書き出すときは、3分間など時間を区切ってやるのが良いです。
 - 2回目以降には、前回使用したKPT表を使用し、表をブラッシュアップする必要があります。(Tryで実践できたものをKeepに移動する。不要なもの、Keepですでに身についたものは削除するなど。)
 - タイミングや頻度について、特に決まりはありませんが、定期的に短いスパンで行った方が良いとされています。

## それぞれの項目の書き出し方について
それぞれの項目についての書き出し方についてまとめておきます。参考にしてみてください。

### K(Keep)の出し方
 - 他人の行動、自分の行動など、よかったとを書き出す
 - 顧客や周りの人に褒めてもらったことを書き出す。
 - 小さなことで良いので数を出す

### P(Problem)の出し方
 - チームの問題点を書き出す。
 - Problemの多い人を詰問するのではなく、共に解決策を考える。
 - 共有することでチームの改善につながるという意識を持つ。

### T(Try)の出し方
 - 具体的な行動を出す(「◯◯を気を付ける」よりは「◯◯を実施する」のような書き方にする。)
 - Keepからはさらによくする方法を書き出す。
 - Problemからは問題の解決策を書き出す。
 - なぜそのTryをやるのかというような目的を意識する。


## 最後に
KPTは、振り返り術として高く評価されている手法の一つです。
チームだけでなく、個人でも活用できるものなので、ぜひ活用してみてください。
WP REST APIで元レスポンスを継承したレンスポンスを返すカスタムエンドポイントを追加する

# はじめに
WP REST APIのレスポンスをプロジェクトに適したものにしたい。でもプロジェクトの拡張の可能性を考慮すると元レスポンスは保ったままで、そこに変更を加えた形のレスポンスを返す独自のカスタムエンドポイントを追加したい...

そんな時のカスタムエンドポイントの追加方法について記述していきます。

# 結論
WP_REST_Posts_Controllerクラスのget_itemsメソッドで元レスポンスの中身を取得する。

```php
function get_posts_custom( $request ) {
    $response = new WP_REST_Posts_Controller('post');
    $posts = $response->get_items($request);
    if ( empty( $posts ) ) {
        return null;
    }
    //処理
    return $posts->data;
}

add_action( 'rest_api_init', function () {
    register_rest_route( 'wp/custom', 'posts', array(
        'methods' => 'GET',
        'callback' => 'get_posts_custom'
    ) );
} );
```

# 方針
カスタムエンドポイントを追加することは[公式](https://ja.wp-api.org/extending/adding/)にも記述がある。追加されるエンドポイントとそのエンドポイントが叩かれたときに返る値を定めることで実現できる。

```php
<?php
add_action( 'rest_api_init', 'slug_register_starship' );
function slug_register_starship() {
    register_rest_field( 'post',
        'starship',
        array(
            'get_callback'    => 'slug_get_starship',
            'update_callback' => null,
            'schema'          => null,
        )
    );
}

/**
 * "starship"フィールドの値を取得
 *
 * @param array $object 現在の投稿の詳細データ
 * @param string $field_name フィールド名
 * @param WP_REST_Request $request 現在のリクエスト
 *
 * @return mixed
 */
function slug_get_starship( $object, $field_name, $request ) {
    return get_post_meta( $object[ 'id' ], $field_name, true );
}
```

上の例では`slug_get_starship`でレスポンスの内容を定めることがわかります。ここにwp-json/wp/v2/postsのレスポンスの内容を引っ張ってきたい。

そこでWP REST APIのGitHubを参照するとwp-json/wp/v2/postsのレスポンスの内容はWP_REST_Posts_Controllerクラスのget_itemsメソッドで作られることがわかります。

```php
class WP_REST_Posts_Controller extends WP_REST_Controller {
    ..
    /**
	 * Get a collection of posts.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_Error|WP_REST_Response
	 */
	public function get_items( $request ) {
           ..
        }
    ..
}
```

これだ！！ということでカスタムエンドポイントのレスポンスを定める関数の中でメソッドを呼び出します。

したのコードのようにするとwp-json/wp/v2/postsを同様のレスポンスが再現できます。あとはこれを使いやすいように変更を加えていくだけ。

```php
function get_posts_custom( $request ) {
    $response = new WP_REST_Posts_Controller('post');
    $posts = $response->get_items($request);
    if ( empty( $posts ) ) {
        return null;
    }
    //ここでレスポンスの中身をいじる
    return $posts->data;
}

add_action( 'rest_api_init', function () {
    register_rest_route( 'wp/custom', 'posts', array(
        'methods' => 'GET',
        'callback' => 'get_posts_custom'
    ) );
} );
```

# 最後に
ご拝読ありがとうございました。少しでも役に立てれば幸いです。よいWPライフを。
CakePHP で mPDF を使う

こちらの記事と同様のことを Ubuntu 21.04 で行いました。
[CakePHP 4 に mPDF 8 を導入してテンプレートから PDF を生成](https://tt-computing.com/cake4-mpdf8)

プロジェクトの作成

```bash
composer create-project --prefer-dist cakephp/app:4.2.* sample-project
```

サーバーの起動

```bash
cd sample-project/
bin/cake server
```

起動の様子

```text
$ bin/cake server

Welcome to CakePHP v4.2.6 Console
-------------------------------------------------------------------------------
App : src
Path: /home/uchida/lang/php/cake/sample-project/src/
DocumentRoot: /home/uchida/lang/php/cake/sample-project/webroot
Ini Path: 
-------------------------------------------------------------------------------
built-in server is running in http://localhost:8765/
You can exit with `CTRL-C`
[Thu May 13 17:14:26 2021] PHP 7.4.16 Development Server (http://localhost:8765) started
```

http://localhost:8765　にアクセス
![cakephp_may13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/1b8acb84-f8dd-d783-c700-6167bb0e3846.png)

mPDF のインストール

```bash
composer require mpdf/mpdf
```

TakaoMincho.ttf のシンボリックリンクを作成

```bash
mkdir data
mkdir data/font
cd data/font
ln -s /usr/share/fonts/truetype/takao-mincho/TakaoMincho.ttf .
```

PDF を出力するプログラム

```php:src/Controller/SampleController.php
<?php
declare(strict_types=1);

namespace App\Controller;

use Mpdf\Mpdf;

class SampleController extends AppController
{
  public function index()
  {

  $mpdf = new Mpdf([
    'fontDir' => [ROOT . DS . 'data' . DS . 'font'],
    'fontdata' => [
      'takao' => ['R' => 'TakaoMincho.ttf'],
    ],
    'default_font' => 'ipa',
  ]);

    $html = '<h1>こんにちは、世界！</h1>';
    $html .= '<blockquote>';
    $html .= 'May/13/2021 PM 17:03<br />';
    $html .= '</blockquote>';
    $mpdf->WriteHTML($html);
    $encodedName = rawurlencode('sample001.pdf');

    return $this->response->withType('pdf')
      ->withHeader('Content-Disposition', "attachment;filename*=UTF-8''{$encodedName}")
      ->withStringBody($mpdf->Output('', 'S'));
  }
}
```

```html:templates/Sample/my_pdf.php
<html>
  <head>
    <?= $this->Html->css(['sample/my_pdf.css']) ?>
  </head>
  <body>
    <h1><?= $title ?></h1>
    <p>Sample</p>
    <p>サンプル用のＰＤＦです</p>
  </body>
```

```css:webroot/css/sample/my_pdf.css
h1 {
  color: #f00;
}
```

サーバーを起動して、
http://localhost:8765/Sample
にアクセスする
![cakephp_mpdf_may13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/54911117-42e5-b7ef-b87b-b6f5afe5d7b1.png)

次の環境で確認しました。

```text
$ php -v
PHP 7.4.16 (cli) (built: Mar 23 2021 16:15:03) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.16, Copyright (c), by Zend Technologies

$ composer --version
Composer version 2.0.9 2021-01-27 16:09:27
```
AWS仕組み

AWSの仕組みについて勉強したのでメモしていきます。

##導入
よく聞くEC２は簡易的なサーバーのようなもの
アカウントさえあれば数分で作ることが可能

またELB（ロードバランサー）を使用すれば冗長構成も可能
メインとセカンダリのサーバを構成できる

後にDBを追加して解析、蓄積も可能（RDS）

ネットワークを構築して使用する場合は
VPCに接続して仮想的に、サーバーの運用が可能

外部に繋いでいく場合、DNSサービスとしてRoute５３というサービスがある

またバックアップにS3というストレージに保存可能

##仕組み

###アンマネージド
・スケーリングして冗長構成が可能
・細かい詳細設定はユーザー側で管理
ex)EC2　サーバのセッティングは自分でやる

###マネージド
・設定はAWS側で管理
・設定範囲が限定的
ex)Route５３　AWS側で管理　

##グローバルインフラ構成
リージョン＞AZ＞エッジロケーション
簡単にいうと、データセンターの区別

世界中に多数のデータセンター

###リージョン
・全部で２４地域　
・中国は他国と違う
→中国はデータを提示する義務がある
・日本には東京、大阪がある
・リージョン間は物理的に完全に独立したインフラ拠点
・隣接リージョン間は物理的なネットワーク回線で接続されている
ex）障害対応で東京のインフラのバックアップを大阪にとっておく
・リージョンに応じてAWSサービスの利用可否がある
→米国は最新のバージョンをいち早く利用可能だが、日本は少し遅いなど
・BCP対策のために他リージョンにサーバ構成すると良い

###AZ
・全部で７６ゾーンあって、リージョンの中にAZが存在する
・AZ内部にに物理サーバがあり、そのAZ内の物理サーバを仮想化して提供している
・複数AZでセカンダリサーバやDBを構築しておくのが基本

###エッジロケーション
・２０５以上
・キャッシュデータなどを利用する際のさらに小さなエンドポイントとなる拠点


##AWS全体像
・試験で問われる内容
必須レベル
アプリケーション統合、コンピューティング、AWSコスト管理
DB、マネジメントコンソール、移行と転送、ネットワーキングとコンテンツ配信
セキュリティ・アイデンティティ・コンプラ、ストレージ

・その他
分析、コンテナ、開発者用ツール、機械学習

###コンピューティング
・EC2
仮想サーバを立ち上げるサービス
ELB/AutoScaling（サーバを自動で増やして負荷に対応）/セキュリティグループ（サーバに対するFW）

・Lambda
サーバレスでプログラミングコード処理を実行するサービス
仮想サーバを立ち上げずとも、直接サービス上コードを実行して
簡易的にアプリケーションなどを実行できる

・Lightsail
EC2より簡単にサーバのセットができる
簡易的にWebサイトなどを作れる。

・ECS
Docker形式でインフラを総合的に構成できる

###ストレージ
・S3
可用性、耐久性が高く中長期に向いてる
大量にデータ保存可能　データは実質無制限

・EBS
EC2にネットワークを介してアタッチして利用する専用のブロックストレージ
EC2インスタンスを起動するときに同時にEBSを作ってEC2にアタッチ
サーバ保存用
EC2にネットワークで接続されている

・インスタンスストア
EC2に物理的に接続されている一時データ保存用ストレージ

・EFS
複数のEC2インスタンス間で内部用でアクセス（データ共有）

・S3Glacier
低コスト　データの取り出しは遅いので、あまり使用しないバックアップとかに使う

##ネットワーキングやコンテンツ配信
・VPC
仮想ネットワーキング環境を構築するサービス

・クラウドフロント
コンテンツ配信ネットワークサービス

・Route５３
DNSサーバの機能提供
ドメイン登録とルーティング

・Direct Connect
AWSとデータセンター、オフィス、コロケーション環境との間にプライベート接続を確立するサービス

・API GW
他のサービスからアクセスする

・ストレージGW
オンプレとクラウドストレージを連携構成を使える

##データベース
マネージド型で提供されている

・RDS　
主要なDBを扱える
リレーショナルDBサービス

・Aurora
RDSのデータベースエンジンとして使われる
RDSより高性能なRDBを使う場合はこっち

・dynamo　DB
規模に関係なく数ミリ秒台のパフォーマンスを発揮する
キーバリュー型のノンSQL型のDB
セッション管理、ドキュメント管理

・ElastiCache
インメモリ型データストア
メモリ内にキャッシュをためて最速に接続できる

・Redshift
高速かつシンプルで費用効果の高い完全マネージド型のデータウェアハウス
データ分析に使う



###今日はここまで
明日清書してみやすくします
MacCatalystを使い方を解説

#準備
###Macのバージョン確認
まずMacのバージョンを確認します。

1.デスクトップ画面左上のAppleマークをクリック
2.「このMacについて」をクリック
3.開いたウィンドウでMacのバージョンを確認

![スクリーンショット 2021-05-14 9.29.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1456321/5215b7f3-5d62-73d2-758d-f5f3671767ee.png)

※Macのバージョンが10.15以降でなければMacCatalystで作ったアプリが動きません。

###Xcodeのバージョン確認
次は、Xcodeのバージョン確認です。
もしXcodeがインストールされていなければApp Storeからダウンロードしてください。

1.Xcode.appを起動する
2.デスクトップ画面左上の「Xcode」をクリック
3.「About Xcode」をクリック
4.開いたウィンドウでXcodeのバージョンを確認

![スクリーンショット 2021-05-14 9.33.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1456321/0d979afd-8898-73c1-f7cf-83358279d42b.png)!

※Xcodeのバージョンは11.0以降でなければMacCatalystが使用できません。

#MacCatalystを使ってみる
では、実際にMacCatalystを使ってアプリをMac対応させていきます。

###使用した環境
|開発環境　|バージョン 　|
|:--------|:---------|
|MacOS  　|10.15.7 　|
|Xcode  　|11.3.1  　|

###MacCatalystの機能を有効にする
1.MacCatalystを使いたいアプリをXcodeで開く
2.プロジェクト設定の [TARGETS > General > Deployment Info > Mac] にチェック
![スクリーンショット 2021-06-10 14.33.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1456321/5605f468-cfe7-1bc4-783c-3ff1b3d1bbbd.png)
3.アラートが出てくるので「Enable」をクリック
![スクリーンショット 2021-06-10 14.33.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1456321/8542fa29-1506-cee2-a4d5-3e3ef40d9ba2.png)!
4.ビルド先がMy Macに設定されているのを確認して ▶ をクリックしてビルド
5.「Build Succeeded」が表示され、アプリが正常に動けば成功です
![スクリーンショット 2021-06-10 14.34.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1456321/e208bdb1-ca06-f5aa-cef6-6d1ba6897cbc.png)
MacCatalystで注意するべき３つのこと

#iPad対応アプリしか移植できない
MacCatalystでアプリをMacに移植するには、iPad対応が必須です。
iPhone対応アプリのMac移植をすることもできますが、その場合もiPad対応が必要になります。

|移植元アプリの対応OS|MacCatalystが使えるか|
|:-----------------|:-------------------:|
|iPhone & iPad     |                   〇|
|iPhoneのみ         |                  ✕|
|iPadのみ           |                  〇|


#デバイス間の仕様の違い

MacとiPadでは様々な点で違いがあります。
移植元のアプリによっては以下の違いに注意する必要があります。

####操作方法の違い
Macではキーボード&マウス、iPadではタッチパネルのようにMacとiPadでは操作方法が違います。
MacCatalystでは自動でキーボード&マウス操作に対応してくれるので、基本的に気にする必要はないですが、特殊な操作方法を実装している場合等は注意が必要かもしれません。

####内蔵カメラ・マイク・センサー等の有無
Macの場合、カメラやマイクを内蔵していないものもあります。
その場合でも外部接続でカメラやマイクは使えますが、ジャイロセンサーをはじめとした各種センサーはMacに非対応なので、iPadのセンサーを使った機能はMacでは実現できないものと考えた方がいいでしょう。

####アプリ画面のサイズ
iPadではアプリ画面がスクリーンのサイズで固定されますが、Macの場合はアプリ画面のサイズを自由に変更することができます。そのため、アプリ画面のレイアウトについて調整が必要になってくる場合もあります。


#旧バージョンだと使用不可
開発する場合、開発環境はXcodeのバージョン11.0以降が必要で、アプリを動かすだけでも、macOS 10.15以降が必要になります。
アプリを旧バージョンのMacにも対応させたい場合は注意が必要です。
　
　
MacCatalystの注意点を解説しました。
次回はいよいよMacCatalystの使い方を説明していきます。
Xojo で スタンドアローン Web アプリを RaspberryPi で動かす

# Xojo を cgi 動作させる場合の問題点

今まで Xojo を Web アプリ作成ツールとして使ってきました。
Apache を Ubuntu Linux PC サーバや RaspberryPi で動かしたうえで、Xojo アプリケーションを cgi として登録するやりかたです。

「Xojo で Web アプリ Tips ( Web1.0 )  :  cgi として動かすノウハウ」
https://qiita.com/nanbuwks/items/b73472ac210a9c873807#cgi-%E3%81%A8%E3%81%97%E3%81%A6%E5%8B%95%E3%81%8B%E3%81%99%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6

 しかしながら様々な問題があります。

- Xojo 2020 r1 以降は cgi としてのビルドができなくなっている。
- 日本語名での cgi 動作ができない
- 謎の不具合

日本語名での cgi 動作ができない問題は以下で解説しています。
「Xojo で Web アプリ Tips ( Web1.0 )  :  アプリ名の制限」
https://qiita.com/nanbuwks/items/b73472ac210a9c873807#%E3%82%A2%E3%83%97%E3%83%AA%E5%90%8D%E3%81%AE%E5%88%B6%E9%99%90

謎の不具合というのは、

「Xojo で Web アプリ Tips ( Web1.0 )  :  トラブルシューティング」

https://qiita.com/nanbuwks/items/b73472ac210a9c873807#%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0

のようなことが度々発生したり、Webアプリで timer を発動したら他のスレッドが停止したりということが起こっていた。

これらをの問題を、cgi 動作で解決するのは不可能と判断し、cgi 動作の代わりにスタンドアローンWebアプリとして動かすことにした。今回は例として RaspberryPi 上で動かし、説明する。


# スタンドアローン Web アプリとは

サーバとなるマシンで、あらかじめビルドした Xojo Web アプリを実行しておく。
そうすると指定の待ち受けポートが開き、Xojo Web アプリは Webサーバとして動作する。

複数の Xojo Web アプリを同一のサーバマシンで動かすには、ポートを変えて動かすとよいみたいだ。



# 環境

- Xojo 2019 r2
- Raspberry Pi 3

# 作成方法

XojoのBuild Settins で設定します。

- Linux をチェックし、アーキテクチャを ARM 32-bit を選択。
- Shared で、 Deployment Type を Stand Alone に変更。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e0a93990-5a26-8891-ef1b-4411ebace0ad.png)

「Build」すると、ファイルが生成されます。この 1 つ上の階層のアプリケーション名フォルダごとコピーするのが良いでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/fab1dd1e-b559-8064-8875-3f849bd03614.png)

RappberryPiに転送して、設定します。


```

$ cd EntryBlood
$ sudo chmod 555 EntryBlood
$ ls -alh
total 3.8M
drwxr-xr-x 4 www-data www-data  16K Dec 25 07:25  .
drwxr-xr-x 8 www-data www-data  16K Jan  1  1970  ..
-r-xr-xr-x 1 www-data www-data 3.7M May 13  2021  EntryBlood
drwxr-xr-x 2 www-data www-data  16K Dec 25 07:25 'EntryBlood Libs'
drwxr-xr-x 3 www-data www-data  16K Dec 25 07:25 'EntryBlood Resources'
```

以下で起動します。

```

$  sudo ./EntryBlood --port=8080
```

sudo は無くてもOKですが、後で自動起動で設定することを考えて root での動作確認をしてみます。


起動オプションなどは以下で参照できます。

https://docs.xojo.com/UserGuide:Web_App_Deployment_Details

ブラウザで、http://(RasbperryPiのIPアドレス):8080 として開きます。

# RaspberryPi 上で自動起動を設定

問題ないようであれば、RasbperryPiが起動したら自動で起動するように設定します。

/etc/rc.local に書くのですが、今回は USB メモリにWebアプリファイルを配置して、USBメモリごと差し替えるように工夫しました。


```
.
.
.
 sleep 45

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

python3 /home/pi/LCDmessage.py $_IP
mount -o exec,uid=33,gid=33 /dev/sda1 /mnt
/mnt/trans.sh & > /dev/null

exit 0
```

上記で、

- LANが安定するまで待つ
- IPアドレスを取得
- LCDにIPアドレスを出力
- USBメモリを www-data 権限でマウント
- USBメモリ中の初期化スクリプト「trans.sh」を実行


USBメモリ中には、trans.sh と Webアプリプログラムが収録されているフォルダが入っています。
trans.sh 内部で、Xojo の Web アプリを実行しています。

```
/mnt/EntryBlood/EntryBlood --port=8080 &
```

これで、起動時に RaspberryPi 上で Webアプリが動作するようになります。
ajax非同期通信でPHPへ一括POST、結果を受取る（備忘録）

本業ではなく、欲しいと思ったツールを時折作っているので、忘れていることが多い・・・

今回はajaxでの非同期通信
やりたいことは
　①ページ内の要素を一括してrecieve.phpへ送信
　②recieve.phpで（DB検索など）処理して結果（件数など）を返す
　③結果を表示


```html:ajax_post.html
<html>
<head>

<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script type="text/javaScript"><!--

function res_num(){
   var $form = $('#form1');
   var data = $form.serialize();

   //ajax通信
   $.ajax({
   type:  "post",
   url:   "recieve.php",
   data:  data ,
   success: function(res) {
      // 成功時の処理
      document.getElementById('res').value = res;
    }
  });
}

//--></script>

</head>

<body>
<form name='form1' id='form1' method='POST' action='hoge.php'>
   対象日：<input type='date' name='b_date' id='base_date' value='2021-05-13'><br>
   単　価：<input type='text' name='tanka' id='cb_tanka' value='1234'><br>
   <input type='button' onclick='res_num();' value='検索'><br>
   結　果：<input name='res' id='res' value=''>

</form></body></html>
```
```php:recieve.php
<?php
$b_date = $_POST['b_date'];
$tanka  = $_POST['tanka'];
//普段のように受け取れるので、処理を書く
//例えばDB問い合わせて、結果件数を$resに入れる
echo $res;
?>
```
こんだけ
でも忘れちゃうのよね（T.T）
Rails in Docker × Rspec with Capybara × selenium_driver

#####追記
2021/05/14
この記事だけでは、system_specで、jqueryなどのチェックができるようにはなりませんでした。自分の場合は、下の記事の設定を導入し、やっとテストできるようになりました。

https://qiita.com/Ub_Iwerks/items/7a74c67fb97636d21b32

## 概要

これらの記事を参考にCapybaraのテスト実行環境を `:rack_test → :selunium`へ変更致しました。（とても参考になりました。ありがとうございました！）

https://qiita.com/at-946/items/e96eaf3f91a39d180eb3

https://qiita.com/aotaro1994/items/8bfbd92c25e1fb90e588

この記事では変更点だけを羅列しますが、注意点としましては、`gem 'rspec-rails', '>= 4.0.2'`こいつだけバージョンの指定が必要である、という事です。

これは2個目の記事に参考にさせていただきました！

## 動作環境とバージョンについて

```ruby
ruby 2.6.6
Rails 6.1.3
rspec-rails 5.0.1
selenium-webdriver 3.142.7
capybara 3.35.3
```

## 結論

```ruby:Gemfile
+  gem 'rspec-rails', '>= 4.0.2'
+  gem 'capybara'
+  gem 'selenium-webdriver'
```

```ruby:docker-compose.yml
version: '3'
services:
	db:
	  image: mysql:8.0
	  environment:
	    MYSQL_ROOT_PASSWORD: password
	  ports:
	    - '3306:3306'
	  command: --default-authentication-plugin=mysql_native_password
	  volumes:
	    - mysql-data:/var/lib/mysql
	web:
	  build: .
	  command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
	  volumes:
	    - .:/myapp
	  ports:
	    - "3000:3000"
	  depends_on:
	    - db
+     - chrome
	  stdin_open: true
	  tty: true
+ chrome:
+	  image: selenium/standalone-chrome:latest
+	  ports:
+	    - 4444:4444
	  stdin_open: true
	  tty: true
	chrome:
	  image: selenium/standalone-chrome:latest
	  ports:
	   - 4444:4444
volumes:
  mysql-data:
    driver: local
```

```ruby:rails_helper.rb
-# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
+Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
 :
+Capybara.register_driver :remote_chrome do |app|
+  url = "http://chrome:4444/wd/hub"
+  caps = ::Selenium::WebDriver::Remote::Capabilities.chrome(
+    "goog:chromeOptions" => {
+      "args" => [
+        "no-sandbox",
+        "headless",
+        "disable-gpu",
+        "window-size=1680,1050",
+      ],
+    }
+  )
+  Capybara::Selenium::Driver.new(app, browser: :remote, url: url, desired_capabilities: caps)
+end
 RSpec.configure do |config|
+  config.before(:each, type: :system) do
+    driven_by :rack_test
+  end
+
+  config.before(:each, type: :system, js: true) do
+    driven_by :remote_chrome
+    Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
+    Capybara.server_port = 3000
+    Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
+  end
   config.include FactoryBot::Syntax::Methods
   # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
   config.fixture_path = "#{::Rails.root}/spec/fixtures"
```

```ruby:.rspec
---require spec_helper
+--require rails_helper
 --format documentation
```


最後まで目を通していただきありがとうございました！！
latexdiff で変更後のみを赤く強調．

## はじめに．
latexdiff は二つのTeXのソースコードを比較する際に便利なコマンドです．たとえば，before.tex に見つけたスペルミスを訂正して after.tex に保存したとします．latexdiff を使うと次のように，二つのファイルのどこが異なるのかがひと目で確認できます．
[latexdiff の標準的な出力]
![Screen Shot 2021-05-13 at 16.29.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453674/744ef45c-a0d3-b88b-8d5d-29fee312bc58.png)
ところが，訂正後のみを強調させるだけでよく，訂正前の記載が邪魔になることがしばしばあります．つまり，以下のように出力したくなるわけです．
[理想的な出力]
![Screen Shot 2021-05-13 at 16.37.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453674/9b4db9ca-7bfc-b448-5195-0dd1aac59d1d.png)
ここではこの方法を記載します．

## 方法．
ここでは以下の before.tex を訂正し，after.tex として保存した場合を考えます．

```tex:before.tex
\documentclass{jlreq}
\begin{document}
以下の文章を訂正します．\\
 hallo warld ? \\
こんにちわ世界．
\end{document}
```

```tex:after.tex
\documentclass{jlreq}
\begin{document}
以下の文章を訂正します．\\
 hello world ? \\
こんにちわ世界．
\end{document}
```
latexdiff を使い，diff.tex を生成します．

```:bash
$ latexdiff before.tex after.tex > diff.tex
```

diff.tex を vi 等のテキストエディタで開き，プリアンプルにある次の二行を書き換えます．

```tex:diff.tex(変更前)
(前略)
\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}}
\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}}
(後略)
```

```tex:diff.tex(変更後)
(前略)
\providecommand{\DIFadd}[1]{{\protect\color{red}#1}}
\providecommand{\DIFdel}[1]{{}}
(後略)
```

最後に，diff.tex をLuaLaTeXなどの適切なエンジンでコンパイルします．すると，上記 [理想的な出力] が出力されたdiff.pdf が得られます．
notes Class的な使い方 

Dim St As Stack	
Public idx As Integer
Class Stack
	
	Public fld List As Variant
	Public title List As Variant
	
	Sub Push(p1,p2)         ' Push a value on the stack.
		idx% = idx%+1		
		
		title(idx%)			= p1 
		fld(idx%)			= p2  ' Set the top value on the stack.				
	End Sub
	
End Class


Set St= New Stack


ExportListToinstance

Function ExportListToinstance()
	
	idx			=0			
	
	Call St.Push("受講者(No)","EmpNo")
	Call St.Push("受講者(名前)","EmpNm")
	Call St.Push("ステータス","Status")
	Call St.Push("講習日(from)","TDateFr")
	Call St.Push("講習日(to)","TDateTo")
	Call St.Push("名称","Tr")
	
End Function
フォームからパラメータとしてコントローラーに値を送る方法

### プルダウンで選択したユーザーの情報をparamsで扱えるようにパラメーターを送ります。
---
```
<select name="room[user_ids][]">
  <option value="">チャットするユーザーを選択してください</option>
  <% User.where.not(id: current_user.id).each do |user| %>
    <option value=<%= user.id %>><%= user.name %></option>
  <% end %>
</select>

```

select要素のname属性に"room[user_ids][]"を指定し、option要素のvalue属性にuser.idを指定しました。このように記述することでparamsは以下のようになります。

```ruby
{"room" => {"user_ids" => ["選択したユーザーのid"]}}
```

room[user_ids]という記述は値としてハッシュをさらに入れ子にすることを示しています。
room[user_ids]で送られるparamsの中身↓

```ruby
{"room" => {"user_ids" => "値"}}
```

次に、末尾の[]の記述はキーに対する値を配列として格納することを示しています。これにより1つのキーに対して、複数の値を受け取ることができます。
room[user_ids][]で送られるparamsの中身↓

```ruby
{"room" => {"user_ids" => ["値"]}}
```
以上の仕組みを利用して、選択したユーザーの情報をコントローラーへ送信できました。

しかし、現状のままですと現在ログインしているユーザーのidをparamsで送信することができていません。
（User.where.not(id: current_user.id)としているためです。）
現在ログイン中のユーザーのidも一緒にparamsでコントローラーへ送信できるように以下の記述を追加しました。

```
<select name="room[user_ids][]">
  <option value="">チャットするユーザーを選択してください</option>
  <% User.where.not(id: current_user.id).each do |user| %>
    <option value=<%=user.id%>><%= user.name %></option>
  <% end %>
</select>
<input name="room[user_ids][]" type="hidden" value=<%= current_user.id %>>
```
type属性に"hidden"を指定することで画面上には表示されないinput要素を作成できます。
name属性に"room[user_ids][]"を指定し、value属性にはcurrent_user.idを指定しています。
この記述でparamsは以下のようになります。

```ruby
{"room" => {"user_ids" => ["選択したユーザーのid", "現在ログインしているユーザーのid"]}}

```
room[user_ids]に2種類のユーザーidを格納することができました。
[WordPress] 投稿に作成者と別に監修者を設定して、作成者別アーカイブで合わせて表示

# やりたいこと
- 投稿に作成者とは別に「監修者」のカスタムフィールドを用意してWordPressのユーザーを紐付けておく
- 作成者別アーカイブで該当ユーザーの作成した投稿（デフォルト）以外に監修者に設定されてる投稿も混ぜて表示する

# 監修者カスタムフィールド
コードではなくカスタムフィールド系プラグインでさっと作成

# 作成者アーカイブ
WordPressの作成者アーカイブは癖が強いです。
`pre_get_posts`フックあるいはサブクエリで作成者アーカイブのクエリを改変（その作成者の投稿と、監修者カスタムフィールドにその作成者が付与されている投稿を混ぜる）すれば一見正しいコードに見えます。ただし、元々のクエリの作成者情報に引きづられてページ送りなどがすごく影響を受けます。

# やってみて影響を受けたもの

1. 投稿と監修者の投稿と合わせたとき、本来のユーザーの投稿数より *多い* と、ページ送りはできる（生成される）けど、最後の方のページが404と判定され投稿が表示されない。
2. `pre_get_posts` フックで作成者アーカイブの時にクエリ改変する。このとき `author_name` があると1の影響あったため、削除する。ページ送りできるようになるが、ユーザー情報を使う部分で不具合（titleタグなど）が出る。

ということは`pre_get_posts`の後に実行されるアクションフック（今回は `wp`）で、削除したauthor_name, author をセットし直したらいいんじゃね？となります。

# 実際のコード
作成者アーカイブでのプログラムの流れはこんな感じ

1. ユーザーが作成者の投稿IDを配列で取得しておく
2. ユーザーが監修者カスタムフィールドで紐付けられているの投稿IDを配列で取得しておく
3. `pre_get_posts` フックにおいて、作成者アーカイブの場合、`author_name`を空白にセット、1, 2の投稿のみをセットしたクエリにする
4. `wp` フックで作成者アーカイブの場合、3で削除（空白をセット）された`author_name`, `author`を戻す

```
<?php
// ユーザーが作成者の投稿IDを取得
function get_author_post_id( $user_id ) {
	if ( empty( $user_id ) ) {
		return;
	}
	$post_id = array();
	$posts_array = get_posts( array(
		'posts_per_page' => -1,
		'author' => $user_id,
		'fields' => 'ids',
	) );
	if ( ! empty( $posts_array ) ) {
		$post_id = $posts_array;
	}
	return $post_id;
}
// ユーザーが監修者の投稿IDを取得
function get_supervisor_post_id( $user_id ) {
	if ( empty( $user_id ) ) {
		return;
	}
	$post_id = array();
	$posts_array = get_posts( array(
		'posts_per_page' => -1,
		'meta_key' => 'post_supervisor', // 監修者カスタムフィールドのキー
		'meta_value' => $user_id,
		'fields' => 'ids',
	) );
	if ( ! empty( $posts_array ) ) {
		$post_id = $posts_array;
	}
	return $post_id;
}

function mod_pre_get_posts( $query ) {
	if ( is_admin() || ! $query->is_main_query() ){
		return;
	}
	if ( $query->is_author() ) { // 作成者アーカイブの場合
		//クエリ改変
		$userdata = get_user_by( 'slug', get_query_var( 'author_name' ) );
		$userid   = $userdata->ID;
		$user_main_post_id = (array) get_author_post_id( $userid );
		$user_sub_post_id  = (array) get_supervisor_post_id( $userid );
		$user_posts_ids = array_merge( $user_main_post_id, $user_sub_post_id );
		$user_posts_ids = array_unique( $user_posts_ids );
		$user_posts_ids = array_values( $user_posts_ids );

		$query->set( 'author_name', '' ); // これをセットしないとページ送りができなくなる
		$query->set( 'post__in', $user_posts_ids );
	}
}
add_action( 'pre_get_posts', 'mod_pre_get_posts' );

// wp のアクションフックで削除した author_name, author をセットし直す。これを実施しないとクエリを参照にして実行される関数に影響が出る
function mod_wp_author() {
	if ( is_author() ) { // 作成者アーカイブの場合
		global $wp_query;
		$username = $wp_query->query[ 'author_name' ];
		$userdata = get_user_by( 'slug', $username );
		$userid   = $userdata->ID;
		set_query_var( 'author_name', $username );
		set_query_var( 'author', $userid );
	}
}
add_action( 'wp', 'mod_wp_author' );
```

こういったクエリの改変のコードを書いたときに便利なプラグインが「Query Monitor」になります。
https://ja.wordpress.org/plugins/query-monitor/

実際に呼ばれてるクエリやどんなフックで何が実行されているかを確認できます。

現場からは以上です。
フィボナッチ数列の隣り合う2項の比率をグラフに表してみる

## フィボナッチ数列とは
フィボナッチ数列は数学Ⅲの漸化式でやりますよね。

$1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ...$

という具合に、初項が $F_1 = 1, F_2 = 1$ 

そして $\quad F_{n+2} = F_{n+1} + F_n \quad (n \geq 1)\quad $ という漸化式であらわされる数列です。
（0から始める場合もある）

この数列はとても不思議な性質を持っていて、その一つに隣り合う2項の比
$\large \frac{F_n}{F_{n-1}}$ の極限が黄金比に収束するというもの。

つまり

$$ \lim_{n \to \infty}\frac{F_n}{F_{n-1}} = 1.6180339887498948482...$$

となることを示しています。

今回は、それを完全な形ではありませんが、視覚的に表現してみようと思います。

## Pythonでのグラフの描画

Pythonのグラフ描画モジュールの扱いに慣れていないため、コードが汚いですが気にしないでください。

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

a = [1, 1]
x = []
ratio_list = []

for i in range(0, 10):
    x.append(i+3)
    a.append(a[i] + a[i+1])
    ratio = a[-1] / a[-2]
    ratio_list.append(ratio)

# 漸近線の表示
y1 = 1.6180339887
plt.axhline(y=y1, xmin=0, xmax=13, c='blue', ls='--')

# 比率のグラフ
plt.xlim([2, 13])
plt.ylim([1.45, 2.05])
plt.xlabel('x')
plt.ylabel('$\\frac{F_x}{F_{x-1}}$', rotation=0)
plt.xticks(x)
plt.grid(which="major", color="black", alpha=0.5)
plt.plot(x, ratio_list, c='red', marker="o")

# 表示
plt.show()
```

下図の青色の破線が黄金比の近似値 $y = 1.6180339887$ を表しています
隣り合う2項の比が早い段階で黄金比へ収束していることがわかります。
![aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545378/95d0d5ec-3eac-f3c5-0e74-85bc83c47113.png)


## 追記
フィボナッチ数列関連の処理はこっちの方がスマートでよさそうです

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


def gen_fibonacci(num):
    a = 1
    b = 1
    x = []
    ratio_list = []
    for i in range(1, num):
        x.append(i + 1)
        ratio_list.append(b / a)
        (a, b) = (b, a + b)
    return x, ratio_list


# 漸近線の表示
y1 = 1.6180339887
plt.axhline(y=y1, c='blue', ls='--')

# 比率のグラフ
plt.xlim([1, 11])
plt.grid(which="major", color="black", alpha=0.5)
plt.title('Ratio of x items to x-1 items')
plt.xlabel('x')
plt.ylabel('$\\frac{F_x}{F_{x-1}}$', rotation=0)
plt.xticks(gen_fibonacci(10)[0])
plt.plot(gen_fibonacci(10)[0], gen_fibonacci(10)[1], c='red', marker="o")

# 表示
plt.show()
```

![asd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545378/88d2b838-ecec-5a1d-8e51-c538ecabbc0c.png)
自分用メモ: CloudWatchの捉え方

CloudWatchは[時系列DB](https://qiita.com/kanegoon/items/054b53c4c15609d32d3a)を直接操作させてくれるサービスと捉えれる.
InfluxDBは時系列DBである.
InfluxDBには[Continuous Query](https://docs.influxdata.com/influxdb/v1.8/query_language/continuous_queries/#introduction)というのがある.

> メトリクスの保持
CloudWatch には、メトリクスデータが次のように保持されます。
* 期間が 60 秒未満のデータポイントは、3 時間使用できます。これらのデータポイントは高解像度カスタムメトリクスです。
* 期間が 60 秒 (1 分) のデータポイントは、15 日間使用できます。
* 期間が 300 秒 (5 分) のデータポイントは、63 日間使用できます。
* 期間が 3600 秒 (1 時間) のデータポイントは、455 日 (15 か月) 間使用できます。

InfluxDBではこれはこの様に表現できる.
それぞれの粒度毎にDB又はtableを分けて表現する.

> 期間が 60 秒 (1 分) のデータポイントは、15 日間使用できます

```sql
CREATE CONTINUOUS QUERY "60" ON "log_group"
BEGIN
  SELECT * INTO "log_group"."15days"."log_stream" FROM "original" GROUP BY time(60s)
END
```

> 期間が 300 秒 (5 分) のデータポイントは、63 日間使用できます。

```sql
CREATE CONTINUOUS QUERY "300" ON "log_group"
BEGIN
  SELECT * INTO "log_group"."63days"."log_stream" FROM "original" GROUP BY time(300s)
END
```

> 期間が 3600 秒 (1 時間) のデータポイントは、455 日 (15 か月) 間使用できます。

```sql
CREATE CONTINUOUS QUERY "3600" ON "log_group"
BEGIN
  SELECT * INTO "log_group"."63days"."log_stream" FROM "original" GROUP BY time(3600s)
END
```

CloudWatchのコンソール上ではこの様に作成されたtableを選択肢し、queryをしている様に見受けられる.

## 参考文献

* https://qiita.com/nmrmsys/items/cdeb4afa76c591acfd3f
* https://zkat.hatenablog.com/entry/2020/01/01/013519