OmniAICreator/Qiita-1.07M huggingface dataset:
AlmaLinux OS 9にOpenJDK 8をインストール（Amazon Corretto）

# はじめに

Amazon Correttoを利用してAlmaLinux OS 9にOpenJDK8をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Debian ベースおよび RPM ベースの Linux ディストリビューション用の Amazon Corretto 8 のインストール手順 - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-8-ug/generic-linux-install.html) 

## サポート

本手法で導入した場合、[よくある質問 - Amazon Corretto | AWS](https://aws.amazon.com/jp/corretto/faqs/)より、2026-05がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
AlmaLinux release 9.0 (Emerald Puma)

# rpm --import https://yum.corretto.aws/corretto.key 
# curl -L -o /etc/yum.repos.d/corretto.repo https://yum.corretto.aws/corretto.repo
# yum install -y java-1.8.0-amazon-corretto-devel
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "1.8.0_332"
OpenJDK Runtime Environment Corretto-8.332.08.1 (build 1.8.0_332-b08)
OpenJDK 64-Bit Server VM Corretto-8.332.08.1 (build 25.332-b08, mixed mode)
```
ブラウザのみでMarkdown表示 (marked.js + mermaid.js + highlight.js)

概要
----

シーケンス図をテキストで記述するのに、昔少しだけ使ってみたことがあるPlantUMLを調べていたら、ブラウザのみで使用できてMarkdownで記述できるmermaid.jsというJavaScriptライブラリがあることが分かった。他にmarked.js、hilight.jsというJavaScriptライブラリと連携して、シーケンス図を含むMarkdownファイルを記述してブラウザだけで表示できることが分かったので、メモしておく。

コード
------

コードは以下の通り。「[MarkedとMermaidを連携ができずうがー！ってなって微調整した - Qiita](https://qiita.com/gat3ta/items/1e9ada8d81d423d60493)」のコードをベースに、各ライブラリのドキュメントを参照しながら、動かない箇所を修正したもの。
`marked.html#sample.md`のように、URLの末尾に#に続けて記述したMarkdownファイルを読み込んで表示する。

```html:marked.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <meta name="robots" content="none">
    <title>MARKED</title>
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
    <!-- CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.5.1/build/styles/github.min.css">
    <!-- JS -->
    <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.5.1/build/highlight.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/mermaid@9.1.1/dist/mermaid.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/marked@4.0.16/marked.min.js"></script>
    <script>mermaid.initialize({startOnLoad:false});</script>
  </head>

  <body id="content">
    <script>
      //Markedのレンダリング設定
      //参考  https://mermaid-js.github.io/mermaid/#/usage?id=example-of-a-marked-renderer
      var renderer = new marked.Renderer();
      renderer.code = function (code, language) {
        if (language == 'mermaid') {
          //mermaid.js処理対象設定
          return '<div class="mermaid">' + code + '\n</div>';
        } else {
          //hilight.js処理
          return '<pre><code>\n' + hljs.highlightAuto(code).value + '\n</code></pre>';
        }
      }
      marked.use({ renderer });

      //Markdownファイル読み込み
      $(document).ready(function(){
        if (location.href.split("#").length > 1) {
          var urlParam = location.href.split("#")[1];
          $.get( urlParam, function( data ) {
            //marked.js処理
            $('#content').html(marked.parse(data));
            //mermaid.js処理
            mermaid.init();
          });
        } else {
          $('#content').html('please url#any.md');
        }
      });
    </script>
  </body>
</html>
```

補足
----

* コードブロックの内容がmermaid.js対象か判定する条件を、コード内のキーワードではなくlanguageに修正した。
* Rendererオブジェクトの設定方法を`marked.use({ renderer })`に修正した。
* marked.jsの処理を`marked(data)`から`marked.parse(data)`に修正した。

参考
----

* [Marked Documentation](https://marked.js.org/)
* [highlight.js](https://highlightjs.org/)
* [mermaid - Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.](https://mermaid-js.github.io/)
Alma Linux OS 9にOpenJDK 17をインストール（AppStream）

# はじめに

Application Stream(AppStream)を利用してAlma Linux OS 9にOpenJDK17をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[RHEL での OpenJDK 17 のインストールおよび使用 OpenJDK 17 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/openjdk/17/html-single/installing_and_using_openjdk_17_on_rhel/index)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux Application Streams Life Cycle \- Red Hat Customer Portal](https://access.redhat.com/support/policy/updates/rhel-app-streams-life-cycle) より、2027-12がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
AlmaLinux release 9.0 (Emerald Puma)

# yum install java-17-openjdk
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "17.0.3" 2022-04-19 LTS
OpenJDK Runtime Environment 21.9 (build 17.0.3+7-LTS)
OpenJDK 64-Bit Server VM 21.9 (build 17.0.3+7-LTS, mixed mode, sharing)
```
配列内のオブジェクト(連想配列)から　検索・取得

# 初めに
配列内にある、オブジェクト(連想配列)の中から、「指定の値が入っているオブジェクトのみ」を取得したい。

今回は、``name:``が``Bob``のオブジェクトを取得してみます。
```
const users = [
  { id: '101', name: 'Alice' },
  { id: '102', name: 'Bob' },
  { id: '103', name: 'Charlie' },
];
```

## findメソッドを使う

下記コード、nameの値が、Bobのオブジェクトを取得
```
                   //対象の配列.find((引数) => 引数.key名 === 検索したい値)
const targetUser = users.find((v) => v.name === 'Bob');

console.log(targetUser);
//出力結果　　{ id: '102', name: 'Bob' }
```
今回は、``name``で検索していますが、もちろん``id:``や他のkeyでも検索できます!

### [おまけ]　指定のデータの有無　を確認
指定のデータの有無を確認し、「存在した場合」と「存在しなかった場合」に処理を分ける方法です。
```
const users = [
    {id: 1, name: "田中"},
    {id: 1, name: "鈴木"},
    {id: 1, name: "山田"}
];

const result = users.some((u) => u.name === "田中");
if (result) {
    //データが存在した場合の処理
    console.log("あった");
} else {
　　　　　　　　// データが存在しなかった時の処理
    console.log("無かった");
}
```
# 終わりに
同じ値が複数あった場合等は、今回完全に無視しています。手っ取り早くということで。。。
その場合の代替として``filter()``を使う方法があるらしい。
Alma Linux OS 9にOpenJDK 11をインストール（AppStream）

# はじめに

Application Stream(AppStream)を利用してAlma Linux OS 9にOpenJDK8をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[RHEL での OpenJDK 11 のインストールおよび使用 OpenJDK 11 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/openjdk/11/html-single/installing_and_using_openjdk_11_on_rhel/index)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux Application Streams Life Cycle \- Red Hat Customer Portal](https://access.redhat.com/support/policy/updates/rhel-app-streams-life-cycle) より、2024-10がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
AlmaLinux release 9.0 (Emerald Puma)

# yum install java-11-openjdk
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "11.0.15" 2022-04-19 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.15+10-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.15+10-LTS, mixed mode, sharing)
```
Alma Linux OS 9にOpenJDK 8をインストール（AppStream）

# はじめに

Application Stream(AppStream)を利用してAlma Linux OS 9にOpenJDK8をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[RHEL 向け OpenJDK 8 のインストールおよび使用 OpenJDK 8 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/openjdk/8/html-single/installing_and_using_openjdk_8_for_rhel/index)

## サポート

本手法で導入した場合、[Red Hat Enterprise Linux Application Streams Life Cycle \- Red Hat Customer Portal](https://access.redhat.com/support/policy/updates/rhel-app-streams-life-cycle) より、2026-05がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
AlmaLinux release 9.0 (Emerald Puma)

# yum install java-1.8.0-openjdk
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "1.8.0_332"
OpenJDK Runtime Environment (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)
```
ScalaでEitherのリストを畳み込む

久しぶりにアプリケーションで再帰のコードを書いたのでメモ。

# Eitherになるリスト

リストに返り値がEitherになる関数を先頭から適用していき、その結果をひとつのEitherとして返す関数が欲しい。
Leftが発生した場合はその値を返す。

```scala
def sample1[A, B, C](list: List[A], f: A => Either[B, C]): Either[B, List[C]]
```

# foldLeft

畳み込みなので `foldLeft` を使うとこのようになる。

```scala
def sample1[A, B, C](list: List[A], f: A => Either[B, C]): Either[B, List[C]] = {
  list.foldLeft[Either[B, List[C]]](Right(Nil)) {
    case (Right(acc), x) => f(x).map(_ :: acc)
    case (l, _)          => l
  }.map(_.reverse)
}
```

リストでの関数適用順が逆になりLeftの結果が変わってしまうため `foldRight` を使って `map(_.reverse)` を除去することはできない。

# 再帰

sample1ではLeftが発生した後もリストの走査が続いているが、Leftが出た時点で終了させたい。
また、アキュムレーターを要素ごとに毎回matchするのも計算量はともかく、読む時のノイズになるため除去したい。

scalaにはコレクションの走査を中断する方法がいくつかあるが、再帰で表現した場合はこうなる。

```scala
def sample2[A, B, C](list: List[A], f: A => Either[B, C]): Either[B, List[C]] = {
  @tailrec
  def rec(acc: List[C], xs: List[A]): Either[B, List[C]] = xs match {
    case x :: tail =>
      f(x) match {
        case Right(r) => rec(r :: acc, tail)
        case Left(l)  => Left(l)
      }
    case Nil =>
      Right(acc)
  }
  rec(Nil, list).map(_.reverse)
}
```

# whileループ

Scalaではmutableにwhileループを使うこともできる。ライブラリではよく見られる実装方法である。

```scala
def sample3[A, B, C](list: List[A], f: A => Either[B, C]): Either[B, List[C]] = {
  val builder = List.newBuilder[C]
  var these: List[A] = list
  while (list.nonEmpty) {
    f(list.head) match {
      case Right(r) => builder.addOne(r)
      case Left(l)  => return Left(l)
    }
    these = these.tail
  }
  Right(builder.result())
}
```


# 終わり

scalaでは標準ライブラリで一通りのコレクション操作ができるため、自分で繰り返しを書く機会は少ない。ライブラリの実装ではmutableに`while`ループで実装している場合が多い。それでもmutableのコードは注意が必要であることには変わらないため、アプリケーションコードでは避けたい。機会は少ないがScalaでも再帰は書くことがあるので覚えておきたい。

このケースであれば関数型ライブラリでも解決できそうだが。
AlmaLinux OS 9 に Python 3.9 をインストール（OS標準）

# はじめに

Application Stream(AppStream)を利用してRHEL9にPython 3.9をインストール
参考：[動的プログラミング言語のインストールおよび使用 Red Hat Enterprise Linux 9 \| Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html-single/installing_and_using_dynamic_programming_languages/index)

## サポート

本手法で導入した場合、`Python 3.9 は、RHEL 9 のライフサイクル全体で対応します` という記載より2032-05がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

通常はインストールされている模様

```shell-session
# cat /etc/redhat-release
AlmaLinux release 9.0 (Emerald Puma)

# dnf install python3
... 略
```

### 各種確認

```shell-session
# which python3
/usr/bin/python3

# python3 --version
Python 3.9.10

# dnf info python3
Last metadata expiration check: 0:36:08 ago on Sun Jun  5 10:28:21 2022.
Installed Packages
Name         : python3
Version      : 3.9.10
Release      : 2.el9
Architecture : x86_64
Size         : 32 k
Source       : python3.9-3.9.10-2.el9.src.rpm
Repository   : @System
From repo    : anaconda
Summary      : Python 3.9 interpreter
URL          : https://www.python.org/
License      : Python
Description  : Python 3.9 is an accessible, high-level, dynamically typed,
             : interpreted programming language, designed with an emphasis on
             : code readability. It includes an extensive standard library, and
             : has a vast ecosystem of third-party libraries.
             :
             : The python3 package provides the "python3" executable: the
             : reference interpreter for the Python language, version 3.
             : The majority of its standard library is provided in the
             : python3-libs package, which should be installed automatically
             : along with python3. The remaining parts of the Python standard
             : library are broken out into the python3-tkinter and python3-test
             : packages, which may need to be installed separately.
             :
             : Documentation for Python is provided in the python3-docs package.
             :
             : Packages containing additional libraries for Python are generally
             : named with the "python3-" prefix.
```
【AWS】CloudWatchでEC2インスタンスを自動起動・自動停止する

# CloudWatchでEC2インスタンスを自動起動・自動停止する

本記事ではEC2 インスタンスを自動で起動・停止させる方法を紹介します。
必要な時だけインスタンスを起動するように設定することができます。

## IAMロールの準備
まずは、CloudWatch EventsからSSMを操作するためのIAMを作成します。
IAMのロール→ロールの作成と進みます。
![スクリーンショット 2022-06-04 16.13.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/4fdab0e4-ef77-0a1a-3c06-58421a01f0cb.png)
ユースケースの選択でCloudWatch Eventsを選択して次へをクリックします。
![スクリーンショット 2022-06-05 17.25.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/30e5ab89-7d66-f853-247c-e97169e073ca.png)
そのまま進んでタグ、ロール名、ロールの説明を入力し、ロールを作成する。
今回はec2-start-and-stop-automationroleという名前で作成しました。

ロール一覧から、作成したロールを選択し、[信頼関係]タブ → 「信頼ポリシーを編集」
**“ec2.amazonaws.com"** を追加し、「ポリシーを更新」をクリック
```{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "events.amazonaws.com",
                    "ec2.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```
次にAmazonSSMAutomationRole以外のポリシーは削除して
AmazonSSMAutomationRoleをアタッチします。
最終的にはこのようなロールができていると思います。
![スクリーンショット 2022-06-05 18.04.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/72f75b5e-8045-abed-c8c4-41de3bb548a1.png)
## CloudWatch Events の設定
では、自動起動・自動停止の設定をしていきます。
CloudWatchのルール→ルールの作成と進んでください。
![スクリーンショット 2022-06-05 18.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/c68c218e-7add-9eb6-a8b0-8084faa1c6ed.png)
## 自動停止の設定
今回は毎日24時にEC2インスタンスを停止するように設定してみます。
スケジュールのcron式 を選択。入力欄には```00 15 ? * * *```と入力。
UTCで入力する必要があるので、日本標準時との時差9時間を考慮する必要があります。
次にターゲットの追加から SSM Automation 選択し、以下のように設定します。
```
・ドキュメント: AWS-StopEC2Instance
・定数のInstanceId：停止したいEC2インスタンスのID
・既存のロールを使用：先ほど作成したec2-start-and-stop-automationrole
```
![スクリーンショット 2022-06-05 19.16.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/24c5efd4-7ce0-3626-c2b6-ccb8132d4bcd.png)
そして設定の詳細ボタンからステップ 2に進み、任意の名前と説明を入力してください。
「ルールの作成」をクリックすれば、毎日24時に自動停止する設定は完了です。
![スクリーンショット 2022-06-05 19.27.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/da295b81-a562-79ba-2e5b-9dad93180846.png)
## 自動起動の設定
停止用ルールと同じ流れで、毎日8時に起動するように設定していきましょう。
Cron式とドキュメントの設定値を変えるだけです。
```
・Cron 式：00 22 ? * * *
・ドキュメント：AWS-StartEC2Instance
```
![スクリーンショット 2022-06-05 19.45.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/28421aa7-228f-45ac-cc30-c5fd16b2fb44.png)
そして設定の詳細ボタンからステップ 2に進み、任意の名前と説明を入力。
![スクリーンショット 2022-06-05 19.50.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318577/4814f579-f34c-a134-1bad-42209218227c.png)
これで毎日8時に起動し、24時に停止する設定が完了しました。
## まとめ
* CloudWatchを使えばEC2インスタンスの自動起動・自動停止が簡単に実現できる

以上、ご訪問ありがとうございました。
EC2 rails 環境構築


```
$ sudo yum -y update
$ sudo yum  -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl libcurl-devel curl
$ sudo curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -
$ sudo yum -y install nodejs
$ sudo yum -y install wget
$ sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
$ sudo yum -y install yarn
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source .bash_profile
$ git clone (httpから始まるやつ)
$ rbenv rehash
$ rbenv install (gitのバージョンに合わせる)
$ rbenv global (バージョン)
$ rbenv rehash
$ ruby -v
$ sudo yum -y install mysql56-server mysql56-devel mysql56 mariadb-server mysql-devel
$ sudo yum -y install https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
$ sudo yum-config-manager –enable mysql80-community
$ sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
$ sudo yum install mysql-community-server
$ mysqld --version
$ mysql -u admin-p -P 3306 -h (RDSのエンドポイント)

※セキュリティーグループのインバウンドルール追加、


sudo mkdir -p /var/www
cd /var/www/
sudo chmod 755 www
cd www/
sudo git clone (ギットハブのhttpsを貼り付け)
cd (作成したフォルダー)
gem install bundler
touch .gemrc
vim .gemrc (なんか貼り付け)
gem install rails -v 6.1.4
cd /var/www/jojorion
bundle install
www $sudo chown ec2-user:ec2-user jojorion/
cd jojorion
$sudo chown -R ec2-user:ec2-user .
bundle install

vim config/database.yml (編集・追加)
bundle exec rails webpaker:install no! no!コマンド
RAILS_ENV=production bundle exec rails db:create
EDITOR=vim bin/rails credentials:edit
cat config/master.key (ローカルから鍵を取ってきてEC２に貼り付ける) 
RAILS_ENV=production bundle exec rails db:create
RAILS_ENV=production bundle exec rails db:migrate
RAILS_ENV=production bundle exec rails s -b 0.0.0.0
動作確認する

___ 

　sudo=ルート権限
/www配下にアプリケーション用のディレクトリーを入れる。
sudo chmod 755 /var/www/
※www/以降を７５５権限にする
sudo chown -R <ユーザー名>:<ユーザー名>
sudo chown -R ec2-user:ec2-user /var/www  
※オーナー所持者

↓bundle installがうまくいかない場合は、下記コマンドを実行する↓
$ bundle install --path vendor/bundle

```
Apple Developer Programを自動更新にする方法

Apple Developer Program　は年に一度、更新が必要で30日前になると下記のようなメッセージがAppStoreConnect上に表示されます。

![appStoreConect.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281022/500160e8-83c3-5a55-c0ec-859982bdde4a.png)
自動更新がうんぬんと書いていますが、青字のApple Developper Webサイトからだと日本は自動更新に対応しておらず毎度、手動で更新する必要があります。
日本語でApple Developer Programの更新について解説しているサイトではこのように解説していますが、StoreにあるApple Developer Appからだと通常のアプリと同様にサブスクリプション契約できます。
<img width="400" alt="IMG_3496.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281022/ae658102-5afe-958a-9f46-db28b8320c3d.png">
また、Apple Developer Programに登録したいApple IDとは別のIDを使ったデバイスでもアプリ内で別のIDでサインインできるので大丈夫です。
請求に関しては、使ったデバイスに登録された支払い方法に来るので注意が必要です。

Apple公式-プログラムの更新: https://developer.apple.com/jp/support/renewal/
アプリ: https://apps.apple.com/jp/app/apple-developer/id640199958
【Docker】Dockerコマンドまとめ

## 背景
- dockerコマンドを全然覚えない自分のために、使用したdockerコマンドをまとめておきたい。

## 目標
- 使用したdockerコマンドをまとめていく。

## dockerコマンドまとめテーブル
|コマンド  |説明  |
|---|---|
|$docker pull [イメージ名]|dockerhubからイメージを取ってくる|
|$docker images -a|イメージ一覧表示|
|$docker ps -a|コンテナ一覧表示|
|$docker run [イメージ名 or イメージID]|イメージからドッカーコンテナ起動まで|
|$docker image save -o [保存ファイル名.tar] [イメージ名]|イメージからtarファイルを保存する|
|$docker export [コンテナ名] > [保存ファイル名.tar]|コンテナからtarファイルを保存する|
|$tar xvf [ファイル名.tar]|tarファイルを展開する|
|$docker-compose build|docker-compose.ymlでビルドする|
|$docker-compose up -d --build|docker-compose.ymlでビルドし、バックグラウンドでコンテナを立ち上げる。<br>オプションで`--build`をつけているので、`image`は常に新しく`build`した`image`が使用される。|
|$docker rm -f \`docker ps -a -q`|全てのコンテナを強制削除する|
|\\$docker rmi $(docker images -q) -f|全てのイメージを強制削除する|
|\\$docker volume rm $(docker volume ls -qf dangling=true)|全てのvolumeを削除する|
|$docker build . |カレントディレクトリのdockerfileから起動する|
|$docker tag [イメージID] [付与したいtag] | imageのtagを変更する |


## 補足
- 自分がわかりやすいように書いているので、色々間違ってるかもしれません。

## 参考資料

- 阿佐 志保，プログラマのためのDocker教科書 第2版 インフラの基礎知識&コードによる環境構築の自動化，翔泳社，2018.

https://www.shoeisha.co.jp/book/detail/9784798153223

https://docs.docker.jp/engine/reference/commandline/pull.html

https://docs.docker.jp/engine/reference/commandline/save.html

https://docs.docker.jp/engine/reference/commandline/run.html

https://docs.docker.jp/engine/reference/commandline/ps.html?highlight=ps

https://docs.docker.jp/compose/reference/build.html

https://zenn.dev/gakin/scraps/4cc16e7761d1ef

https://qiita.com/Ikumi/items/b319a12d7e2c9f7b904d

## 個人ブログ

https://takuma-tech.com/2022/09/27/233/
UIWebViewからWKWebViewへの移行時、対応したはずなのにAppStoreConnectへ反映されない

# 何があった
2020年ころにWKWebViewに移行しないとアプリが公開できなくなるということがあった。
WKWebViewに対応してアップロードしたが、何故かAppStoreConnectで弾かれ続けていたという事象です。
化石アプリで更新が止まっているアプリだとまだUIWebViewあるかもしれないので一応残しておきます。

# どういう事象よ
参考：[【iOS UIWebView廃止の対応策】（2020年12月対応必須）cordova利用のハイブリッドアプリにおける「WKWebView」への移行対応について](https://b-risk.jp/blog/2020/08/uiwebview_to_wkwebview/)

AppStoreConnect上で起きていた事象は、上記の記事で書かれている内容とほぼ同じです。
AppStoreConnectへはアップロード出来ていたのですが、該当のビルドバージョンを処理中...のような表記がしばらく出た数分後、何事もなかったように消え去りました。
この時、本来であればAppleからメールが来るので原因に気づけるはずですが、当時はメールを受け取る部署が異なるために原因が分からず、頭を抱えていました。

# Appleからのメール
担当部署から連絡があり、メールの内容を連携いただきました。
内容は「UIWebView使っているからWKWebViewにしてアップロードしてくれ」的な感じでした。

アプリ内ではUIWebViewからWKWebViewに書き換えていたので「？？？」となっていました。

# 何が原因だったか
使用しているライブラリがUIWebViewを使用していたことが原因でした。
詳しくは[[iOS] UIWebView APIが含まれているライブラリを調べる方法](https://qiita.com/y-some/items/b1ea6eb37bd129d7aa8d)に書いていただいている内容がとても分かりやすいです。

# どのように対応したか
元々廃止予定のライブラリでしたので、これを機に取り外すこととなりました。
ライブラリを取り除いた後、再度AppStoreConnectへアップロードすると、無事アップロード処理が完了していました。
【Mac】高画質でSVGからPNGに変換

# はじめに
毎回忘れるので自分用のメモとして残しておきます。

Web上にSVGからPNGの変換サイトはいくつもありますが、画質が悪かったり、画像が小さすぎたりでほとんど使い物になりません。

SVGからPNGを簡単に変換できるコマンドを紹介します。

標準で入っているので何かをインストールする必要がありません。

# コマンド
```
qlmanage -t -s 1024 -o 保存ディレクトリのパス 変換したいファイル
```

もしデスクトップにある`sample.svg`をpngに変換してデスクトップに保存したいとします。
そうするとこのようなコマンドになります。

```
qlmanage -t -s 1024 -o /Users/miyamototaishin/Desktop /Users/miyamototaishin/Desktop/sample.svg
```

# 参考
https://m-miya.blog.jp/archives/1079010974.html
[Rails]concernをrake taskの中で使う

結論：これをrake taskに入れればよい
```
require 'active_support/concern'
```

実例

concernの所在
```app/controllers/concerns/test_concern.rb
module TestConcern
  extend ActiveSupport::Concern
    def test_method(test)
      略
    end
  end
end
```

rake task
```lib/tasks/test_task.rake
namespace :task do
  task test_rake_task: :environment do
    require 'active_support/concern'
    include TestConcern
      略
    end
  end
end
```
CSS 複数クラス、同一スタイルをまとめて記述する方法

# 方法

```css
.contactFormRadioRow1 label:first-of-type, .contactFormRadioRow2 label:first-of-type {
  margin-right: 16px;
}
```

上記の様に```,```で区切る事で複数のクラスにまとめてスタイルをあてられる。
今までに読んだ本を書き溜めていく

今までに読んだ本の書評＆備忘録として更新する。

# 読んだ本

##### ■達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ
おすすめ度★★★★★
DBに関わる設計を行ったときに読んだ。
SQLの大本にある概念まで丁寧に説明してくれる。
DBについてはミック先生についていこうと思った。

##### ■達人に学ぶSQL設計 徹底指南書 初級者で終わりたくないあなたへ
おすすめ度★★★★
読み途中。
SQLの実践的な例などが書いてある。

##### ■97-things-every-programmer-should-know
おすすめ度★★★
オライリーキノコ本
技術用語含む英語の文章が読みたくて、ちょこちょこ読んでる。
息抜きに良い。

##### ■オブジェクト指向でなぜつくるのか？
おすすめ度★★★★
オブジェクト指向?知ってるよ。車の例えのやつでしょ？
でも人に説明しろって言われたらさっぱり分からない。
そんな人に読んでほしいです。

##### ■プログラムはなぜ動くのか
おすすめ度★★★★
プログラムがキーボードから入力され、色々な結果を生み出すまでの
一連の過程を解説してくれる。
ところどころ理解できなかったので、数年後に読み直したい。

##### ■ネットワークはなぜつながるのか
おすすめ度★★★
ネットワークが全く分からなくて購入。
最初は読めたけど結局よくわからなかった。
もっと優しい本から入ろうと思った。

##### ■2週間でJava SE Bronzeの基礎が学べる本 徹底攻略シリーズ
おすすめ度★★★★★
Javaから勉強した初学者にはわかりにくい、メモリの概念について図解で詳しく触れている。
Java Bronze勉強の副読本として重宝した。

##### ■現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法
おすすめ度★★★★★
私の中では、リーダブルコードのコードじゃなくてシステム版って感じです。
実践的で、読みやすい。
経験積んで自分の裁量が増えたときに必要になりそう。

##### ■文系プログラマーのためのPythonで学び直す高校数学
おすすめ度★★★
数学の基本知識の確認とPythonで遊びが一度にできる。

# 読みたい本
##### ■SQLパズル 第2版
ミック先生の訳本
練習問題が載っている。

# 読みたいものその他
##### ■ミック先生のHP
http://mickindex.sakura.ne.jp/
CSS nth-childの指定方法

# 複数の子要素を個別に指定する方法
[公式ドキュメント](https://developer.mozilla.org/ja/docs/Web/CSS/:nth-child)


```html
<div class="contactFormRadioRow1">
     <input name="test" id="select1" value="1" checked="" type="radio"><label for="select1">電話</label>
     <input name="test" id="select2" value="2" type="radio"><label for="select2">FAX</label>
     <input name="test" id="select3" value="3" type="radio"><label for="select3">来社</label>
     <input name="test" id="select4" value="4" type="radio"><label for="select4">お問い合わせ</label>
</div>
```

```css
.contactFormRadioRow1 label:nth-child(n+0):nth-child(n+1):nth-child(n+2){
  margin: 0 16px 16px 0;
}
```

上記で一つ目と二つ目、三つ目の要素にcssをあてられる。

## うまくいかなかったら
上記でうまくいかない場合は

```css
.contactFormRadioTerm:nth-of-type(1), .contactFormRadioTerm:nth-of-type(3) {
  margin-right: 16px;
  margin-bottom: 16px;
}
```
直接指定したい要素のクラス名に```nth-of-type()```を複数指定する。
GASでLINEbot「食品栄養検索」

## はじめに
- なかやまきんに君さんに触発されて食生活等を見直した。
- 結果、栄養について気になり、気軽に調べられるアプリを作ることにした。

## 環境
- Mac　ver.11.6.6
- Google Apps Script
- Google スプレッドシート
- LINE Developers
 
## 問題点
- 栄養データのAPI接続ができなかった。
- 参考になる記事等があまり見つからなかった。

## 解説
- 【ライン】(Line Bot API)　⇄　Google Apps Script　↩️　Spread Sheet

- データについて
⇨https://www.mext.go.jp/a_menu/syokuhinseibun/mext_01110.html
【文部科学省】「日本食品標準成分表2020年版（八訂）全体版」
こちらからデータをスプレッドシートに落として整形いたしました。

## 注意点
- LINE_ACCESS_TOKENとsheetIdはスクリプトプロパティにて設定する。
※情報漏洩防止のため
【GAS】(プロジェクトの設定→「スクリプト プロパティを編集」→「プロパティ」「値」を入力)

### コード
```js
/**
* LINEから送信されたテキストを元に食品シートから検索して、結果の栄養情報を返すLINE BOT
* LINE API 送信マニュアル : https://developers.line.biz/ja/docs/messaging-api/sending-messages/#methods-of-sending-message
*/

/* Rest API(Post) */
function doPost(e) {
  // LINE APIのアクセストークンを取得。
  const lineToken = PropertiesService.getScriptProperties().getProperty("LINE_ACCESS_TOKEN")
  if (lineToken === null) throw new Error('スクリプトプロパティにLINE_ACCESS_TOKENを設定してください。')

  // LINE API POST MESSAGE URL
  const lineUrl = 'https://api.line.me/v2/bot/message/reply';

  // JSONをパースする WebHookで受信した応答用Token
  const replyToken = JSON.parse(e.postData.contents).events[0].replyToken

  if (typeof replyToken === 'undefined') {
    return;
  }

  // ユーザーのメッセージを取得
  const userMessage = JSON.parse(e.postData.contents).events[0].message.text;

  // LINEメッセージで食品シートから栄養成分を取得。取得結果を返信メッセージへ整形。
  const notifyMessages = searchSheetValue(userMessage)

  // LINEのAPIへ任意の情報でPOSTリクエスト
  UrlFetchApp.fetch(lineUrl, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + lineToken,
    },

    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [
        {
          "type": "text",
          "text": notifyMessages
        }
      ],
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({ 'content': 'post ok' })).setMimeType(ContentService.MimeType.JSON);
}

/**
* 指定の用語でシートの中身を検索
* @param search 検索用語
* @returns 検索結果
*/

function searchSheetValue(search) {
  // 取得対象シートID(URLのeditの前)
  const sheetId = PropertiesService.getScriptProperties().getProperty("SHEET_ID")
  if (sheetId === null) throw new Error('スクリプトプロパティにSHEET_IDを設定してください。')

  // IDをキーにスプレッドシート情報を取得
  const spread = SpreadsheetApp.openById(sheetId)

  // アクティブシートのシートの中身を二次元配列で取得
  const values = spread.getDataRange().getValues()

  // 検索正規表現作成
  const regex = new RegExp(search)

  // 食材で取得
  const result = values.filter(value => regex.test(value[1]))

  // 結果出力
  const notifyMsg = `食材名 : ${result[0][1]}
エネルギー : ${result[0][2]}
タンパク質 : ${result[0][3]}
炭水化物 : ${result[0][7]}
脂質 : ${result[0][5]}
`
  return notifyMsg
}
```
PHPでのスクレイピング

# 背景
とあるWebアプリを開発している際に、依頼者が別に管理しているサイトのデータを持ってきて使ってほしいとの要望。
そのデータはDBで管理していなくHTMLファイルに直書きしていたので、それらをPHPを使ったスクレイピングで取得した際の内容を記載。

使ったのは~~Googleが提供している~~[phpQuery](https://code.google.com/archive/p/phpquery/)（※）なるもの。
そやつを使うと想像以上に簡単にスクレイピングができました。
（※）GoogleでなくTobiasz Cudnikという方が作られたもののようです。

# 前提
今回データを取得したいサイトのHTML構造（一部）は以下の通り。

```データを取得したいサイト.html
・・・
 <div class="info">
   <h3>hoge</h3>
   <div class="txt">
     <p>hoge_text</p>
   </div>
 </div>
 <div class="info">
   <h3>huge</h3>
   <div class="txt">
     <p>huge_text</p>
   </div>
 </div>
 <div class="info">
   <h3>hoga</h3>
   <div class="txt">
     <p>hoga_text</p>
   </div>
 </div>
・・・
```

# やった内容
### phpQueryのインストールと設定
[Google Code](https://code.google.com/archive/p/phpquery/downloads)からphpファイルをインストール。
（※今回はphpQuery-0.9.5.386-onefile.zipを使用）

インストールしたZipファイルを解凍すると以下ファイルが入っているはず。
- phpQuery-onefile.php

### phpQueryの実行用ファイルを作成
次にインストールしたphpQueryを実行する用のファイル（scraping.php）を作成。
その中でrequire_onceを使ってphpQuery-onefile.phpを読み込みます。

```scraping.php
<?php 

require_once("./phpQuery-onefile.php");

$target_site = file_get_contents("データを取得したいサイトURL");
$file = fopen("./result.php", "a"); // 取得したデータを書き込む用ファイル

$html = phpQuery::newDocument($target_site); // $target_siteのDOM取得
$info = $htmlDOM->find("h3")->text(); //　今回h3タグの中身を取得したい

fputs($file, $info); // 取得したデータを$fileに書き込み

fclose($file);
```

これでscraping.phpを実行すると、以下のようにresult.phpに記載されるはず。

``` result.php
hoge
huge
hoga
```

### 他要素のデータも併せて取得したい場合
ただ今回はh3タグのデータだけでなく、h3タグの兄弟要素（pタグ）のデータも合わせて取得したいので上記コードに手を加える。
幸いなことに、データを取得したいサイトは[前提](#前提)にあるような構成になっていたのでループ処理にてデータを取得する。
ついでに取得したデータを使いやすいよう配列型になるように変更。

```scraping.php
<?php 

require_once("./phpQuery-onefile.php");

$target_site = file_get_contents("データを取得したいサイトURL");
$file = fopen("./result.php", "a");

// ↓ここから変更
$info_count = count(phpQuery::newDocument($target_site)->find("div.info > h3"));

for($i = 0; $i < $info_count; $i++) {
  $htmlDOM = phpQuery::newDocument($target_site);

  $info_title[] = $htmlDOM->find("div.info > h3:eq($i)")->text();
  $info_text[] = $htmlDOM->find("div.txt > p:eq($i)")->text();
  
  fputs($file, $i . ' => [' . "\n" . '"title" => "' . $info_title[$i] . '",' . "\n" . '"text" => "'  . $info_text[$i] . '",' . "\n" . '],' . "\n");
}

fclose($file);

```

これでscraping.phpを実行すると、以下のようにresult.phpに記載されるはず。
```result.php
0 => [
  "title" => "hoge",
  "text" => "hoge_text",
],
1 => [
  "title" => "huge",
  "text" => "huge_text",
],
2 => [
  "title" => "hoga",
  "text" => "hoga_text",
],
```
XCode13で使用しているライブラリのバージョンが勝手に書き換えられる件の対応

# 何が起きたか
いつも通りアプリリリースのためにビルドをアップロードした。ところがなぜかアプリの動作がおかしい・・・。
確認したところ、ライブラリのバージョン（CFBundleShortVersionString）がアプリのバージョンに書き換えられていたことにより障害となっていることが発覚した。

# なぜ起きたか
XCode13から追加された「Manage Version and Build Number」にチェックを入れると再現される。
ライブラリのバージョンがアプリのバージョンで上書きされる。
確認方法は、アップロード前の確認画面でライブラリのバージョンを確認するとよい。

# 参考
[Xcode "Manage Version and Build Number" option](https://stackoverflow.com/questions/68237292/xcode-manage-version-and-build-number-option)
[Xcode 13 app archiving is modifying framework plist](https://developer.apple.com/forums/thread/690647)

# どう対応すべきか
「Manage Version and Build Number」のチェックを外す。

# 所感
- 他にも被害者がいるはず・・・。
- ライブラリのバージョンで処理を分岐させるのやめよう。
- アップロード前にはライブラリのバージョンおかしくないか確認しよう・・・。
- auto incrementでアップロードするとバージョンがくそ分かりずらくなるのでやめてほしい。TestFlightのバージョンもごちゃごちゃになるので、テスターが混乱する。
- でもアップロードの所作は自動化したい。
phar ファイルを解凍する

## 環境

* Cent OS 7
* PHP 5.4.16 (cli)

## 発生した問題

過去に他人によってビルドされた phar ファイルの挙動を変更する必要があるが、 phar アーカイブ前のソースコードが残っていない。

## 解決方法

`phar` コマンドを用いて、 phar アーカイブファイル (&lt;file_name>.phar) を解凍する。

[[PHP] pharファイルの固め方と解凍の仕方-ぬこのおなかの忘備録 (itneko.blogspot.com)](https://itneko.blogspot.com/2017/08/phar.html)

phar コマンドファイルについては、 php-cli の RPM パッケージにバンドルされていた。

```
# rpm -qf /usr/bin/phar
php-cli-5.4.16-48.el7.x86_64
```
git-bash から ruby を実行すると、引数として与えたファイルパスが変になる

## 環境

* Windows 10
* ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x64-mingw32]
* GNU bash, version 4.4.23(1)-release (x86_64-pc-msys)


## 発生した問題


```
def upload(host, user, password, file, dest_path)
 p file
 p dest_path
...
```


thor を使って、こんな CLI アプリケーションを作成していたところ


```
$ bundle exec special_happy upload remote_host user password 'README.md' '/tmp/README.md'
"README.md"
"C:/Users/xxxx/AppData/Local/Temp/README.md"
```


二つ目のファイルパス ‘/tmp/README.md’ が置き換わってしまった。


## 解決方法

[ruby - Git for Windowsに付属しているbashコンソールからrubyを実行すると指定した引数が書き換わる - スタック・オーバーフロー (stackoverflow.com)](https://ja.stackoverflow.com/questions/20672/git-for-windows%E3%81%AB%E4%BB%98%E5%B1%9E%E3%81%97%E3%81%A6%E3%81%84%E3%82%8Bbash%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%8B%E3%82%89ruby%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%81%A8%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%9F%E5%BC%95%E6%95%B0%E3%81%8C%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%82%8F%E3%82%8B)

原因は上記だった。 Git-bash が悪さをしていた。ファイルパスっぽいものを与えられると、よしなに解釈してしまうらしい。

コマンドプロンプト (cmd) にスイッチして、そちらで実行することで現象は解消された。
【Python】Selenium 4の変更点とWarning

## はじめに

以前、[Selenium4の新機能](https://qiita.com/vZke/items/2ffdefc774e56145e093)をまとめましたが、使っている中でSelenium3 → Selenium4で書き方が変わったものが見つかったので残します。

## ドライバの指定

### ドライバのパスを指定する方法

Selenium3ではドライバ起動時に直接`executable_path`を指定していましたが、Selenium4では`Service`オブジェクトから`executable_path`を渡します。または、システム環境変数にパスを通します。

```python
# Selenium 3
from selenium import webdriver

options = webdriver.ChromeOptions()
driver = webdriver.Chrome(executable_path="./drivers/chromedriver.exe", options=options)
```

```python
# Selenium 4
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService

options = webdriver.ChromeOptions()
service = ChromeService(executable_path="./drivers/chromedriver.exe")
driver = webdriver.Chrome(service=service, options=options)
```

Selenium3の書き方でも実行できますが、以下のWarningが表示されます。

```text
DeprecationWarning: executable_path has been deprecated, please pass in a Service object
```

参考：[Upgrade to Selenium 4 | Selenium](https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/#python-1)


### webdriver-managerを使う方法

[webdriver-manager](https://pypi.org/project/webdriver-manager/)は各ブラウザのバージョンを自動で確認して実行してくれるライブラリです。ブラウザのバージョンアップの度にドライバを用意するという手間が省けます。

これも同様にSelenium3 → Selenium4 で書き方が異なります。

```
pip install webdriver-manager
```

```python
# Selenium 3
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(ChromeDriverManager().install())
```

```python
# Selenium 4
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
```

## モジュールの変更

`Select`と`WebDriverWait`を使うためのモジュールが変わっていました。もしかしたらSelenium3→Selenium4の変更点ではないかもしれません。

ソースコードを見ると、`.ui`を使っても`.select`と`.wait`がそれぞれ呼び出されるようになっているので支障はなさそうです。

### Select

```python
# Selenium 4
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select  # 以前はselenium.webdriver.support.ui

select_element = driver.find_element(By.ID,'selectElementID')
select_object = Select(select_element)
```

参考：[Working with select list elements | Selenium](https://www.selenium.dev/documentation/webdriver/elements/select_lists/)

### WebDriverWait

```python
# Selenium 4
from selenium.webdriver.support.wait import WebDriverWait  # 以前はselenium.webdriver.support.ui

WebDriverWait(driver, timeout=3).until(some_condition)
```
買い物カゴある？教えてTeachable Machineの美晴（見張る）さん！

みなさま、こんにちは。
上司からどんどん指示がでて、**本来の業務が進まない**ってことありませんか？
私は小売業勤務ですが、本業以外にレジ応援、ゴミ捨て、カート整理、カゴ整理など雑務が多く、
なかなか自分がやりたい業務ができませんでした。
中でもカゴ・カートの整理は店内外に散らばったカゴ・カートを回収してまわる仕事ですが、
**本業に没頭したまま忘れてしまう**ことも多々あります。でも忘れていると上司にカゴがなくなってるぞと怒られてしまうし、かといって行く回数はできる限り減らしたい！そんな仕事です。というわけで今回は**Teachable Machine**を使って買い物カゴの量を判別して、少なくなったら教えてくれるLINE Bot作ってみました。**命名：<font color="red">カゴを見張ってくれるので美晴さん**</font>✨です。


## 完成動画はこちら

カゴが補充されるまでメッセージ送信し続けます。

https://twitter.com/matsun_0831/status/1533060978115751936

codepenからの動画
**余裕あり→在庫少**に変わるとLINE Botがメッセージを送信します。

https://twitter.com/matsun_0831/status/1533061108411822080




### 今回使用したもの
[Teachable Machine](https://teachablemachine.withgoogle.com/)
[codepen]( https://codepen.io/)
[Node-RED](https://nodered.org/)
[LINE Developer](https://developers.line.biz/)







## 作成手順

### STEP1 Teachable Machineにカゴの状態を学習させる。

実際に店舗にお邪魔して**①カゴが少ない状態**、**②補充されている状態**の2つを撮影し、
**Teachable Machine**には**余裕あり**と**在庫少**の2つの項目で学習してもらいました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671003/427069f8-f644-4ac8-2985-101732da4553.png)




### STEP2 codepenによるコード作成。

:::note info
私はコード作成できません。今回は私がやってみたいことと同じような
内容を紹介している方のコードを参考に作りました。
:::

**参考記事はこちら（大変勉強になりました）**

https://qiita.com/aya2648/items/f1643f297b41f7a280fa#teachable-machine

このコード記述で私の思考が停止します。書いてある内容が全く分かりません。
試しに参考記事のコードをそのまま使ってみたところ、
うまくLINE Botからメッセージが送信されましたが、**1回の処理で停止してしまいました。
私は常時カゴの状況を監視してもらいたいので、1回で止まってほしくありません**
そこで書かれているコードの意味を1個、1個、調べてみました。
わからないながらも気になった部分はここ

```
await axios.post('https://nodered-（自分の名前）.herokuapp.com/receiver', results[0]);
```
調べていくと、上のコードは**Node-REDの``post``から結果が返ってくるまで待機する。**
という意味になるとわかりました。どうやらここが悪さをしているような気がします。
なので最初の`` await ``を削除すれば、待機しないでと言う意味なるのかなと思い
```
axios.post('https://nodered-（自分の名前）.herokuapp.com/receiver', results[0]);
```
このように`` await ``を削除したところ、うまくループするようになりました。
もう一つは時間です。コードには下記のような記述がありました。
```
setTimeout(loop, 1000);
```
この1000が時間を意味するようです。
そして``1000``とは**1000ミリ秒**、つまり**1秒間隔**で処理が走るように設定されているようなので
今回は``5000``（5秒）に変更しました。
これで、カゴ補充が完了するまで5秒毎にメッセージが送られ続けます。

:::note info
実装するときは5秒ごとでも煩わしいので、1分くらいがいいと思います。
:::





### STEP3 　Node-REDのフローを作成する。
**Node-RED**を使ってノード同士を結びつけて、**LINE Bot**で返すまでのフローを作成します。
下記図のように繋げることで、在庫少のデータが**Node-RED**に流れた時に
<font color="red">**食品入口カゴが減っています。補充して下さい**</font>とメッセージを送信します。
そして、在庫少と認識したらカゴを補充するまでは**ずっーとメッセージが送られ続ける**
という仕様になっています✨✨✨


<img width="表示幅" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671003/dacbcad3-017a-369e-fc18-c5395c12ce21.png">





### 終わりに
【感想】
画像認識なんて難易度高すぎて初心者は絶対に手を出せないと勝手に思っていましたが、
**Teachable Machine**を使えば簡単に画像認識ができてしまうことに驚愕しました。
出来栄えについてもうまく動いていると思っています。

今回協力いただいた店舗の店次長にも見てもらいましたが、こんなに便利そうなものが作れるならどんどん作ってほしいと言われ、他にも**レジ待ちの行列**を教えてくれるとか、**フードコートのゴミの散乱**を教えてくれるのもいいな～と追加注文が入りました。


【反省】
コードに関する知識がなく、今回はそのまま転用に近い状態なのでもっと勉強したいと思います。
まずはコードを見てどういった処理が行われようとしているのか？そこから理解できるようになりたいと思います。
またプロトタイプでは問題はないですが、実用化した場合、開店～閉店まで動くようにとか、
何かしらのエラーによって処理が停止した時に気付くことができるような仕組みも必要だと感じました。
各種規格の転送速度の年表

# これはなに？

転送速度がどう増えていったのかなと気になって調べたので、シェアしようと。
ソースは Wikipedia など（弱い）

## USB

|年|バージョン|転送速度|
|:--|:--|:--|
|1996|1.0|12 Mbps|
|1998|1.1|同上|
|2000|2.0|480 Mbps|
|2008|3.0|4 Gbps ※1|
|2013|3.1|8 Gbps ※1|
|2017|3.2|16 Gbps ※1|
|2019|4|32 Gbps ※2|

※1 8bit のデータが 10bit に変換された結果 5 Gbps なので実質 4 Gbps になる、など
※2 40 Gbps と記載されているが、たぶん 実質 8割の 32 Gbpsなんだとおもう。

## SCSI

情報源:
 * https://ja.wikipedia.org/wiki/Small_Computer_System_Interface
 * https://akiba-pc.watch.impress.co.jp/hotline/20000122/ultra160.html
 * https://ascii.jp/elem/000/000/330/330974/

制定年の時点では実現できていない規格があったりする感じで、よくわかなかった。

|年|バージョン|転送速度|
|:--|:--|:--|
|1986|SCSI|5 MB/s|
|1989?|Fast10|10 MB/s|
|1989??|FastWideSCSI|20 MB/s|
|1989???|32bit FastWideSCSI |40 MB/s|
|2000??|Ultra160|160 MB/s|
|2002??|Ultra320|320 MB/s|

## Serial Attached SCSI

情報源:
 * https://en.wikipedia.org/wiki/Serial_Attached_SCSI

|年|バージョン|転送速度|
|:--|:--|:--|
|2004|SAS-1|3.0 Gbit/s|
|2009|SAS-2|6.0 Gbit/s|
|2013|SAS-3|12.0 Gbit/s|
|2017|SAS-4|22.5 Gbit/s|
|2022?|SAS-5|45 Gbit/s|

## SATA

情報源:
 * https://pc.watch.impress.co.jp/docs/column/interface/298387.html

|年|バージョン|転送速度|
|:--|:--|:--|
|2001|SATA rev. 1.0|1.2 Gbps|
|2004|SATA rev. 2.0|3 Gbps|
|2008|SATA rev. 3.0|6 Gbps|

## LAN (ツイストペア）

LAN はケーブルの種類が色々あるけど、ここではツイストペアケーブルのみを対象としてみた。

|年|バージョン|転送速度|
|:--|:--|:--|
|1986|1BASE5|1 Mbps|
|1993|10BASE-T|10 Mbps|
|1995|100BASE-TX|100 Mbps|
|1999|1000BASE-T|1 Gbps|
|2006|10GBASE-T|10 Gbps|

## Wi-Fi

情報源:
 * https://en.wikipedia.org/wiki/Wi-Fi_6

これだけ無線なので他より遅いのは仕方ない。
あと、"Maximum Linkrate" なので、実効速度とはだいぶ乖離があるように思うがよく知らない。

|年|バージョン|Maximum Linkrate|
|:--|:--|:--|
|1997|802.11|2 Mbit/s|
|1999|802.11a|54 Mbit/s|
|2008|802.11n (Wi-Fi 4)|600 Mbit/s|
|2014|802.11ac (Wi-Fi 5)|6933 Mbit/s|
|2019|802.11ax (Wi-Fi 6)|9608 Mbit/s|

# まとめ

グラフにした。
Wi-Fi は転送速度じゃなくて　Maximun Linkrate だし、転送可能距離はバラバラだし、誤り検出誤り訂正の感じもそれぞれなので条件が揃っていないけど、まあ目安ということで1枚のグラフに入れてみた。

縦軸対数目盛注意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6854/8522bccc-2fea-5b08-7d68-c4d56722062e.png)

こうしてみると めちゃくちゃ速くなっている。
グラフ上はまだサチっている感じはしないけど、USB4 の無理矢理感なんかを見ると、そろそろ止まるかなという気はする。
どうなるんだろうね。
HTML5プロフェッショナル認定試験レベル1 Ver2.5 合格記


2022年6月上旬にHTML5プロフェッショナル認定資格レベル1 Ver2.5を受験し合格しました。

今年の4月に現在の会社にIT業界未経験として入社後、初めての資格試験として受験しました。

## 受験理由
もっとWeb全般の知識を深く体系的に身につけたいと思ったからです。独学で主にhtmlやcss, Javascriptを使って遊んでますが、用語は知っているが意味はあまり分からない等といった事が多々ありましたので今一度知識をしっかりと定着させたいと思いました。

## 試験概要

公式サイト: https://html5exam.jp/outline/lv1.html

90分（秘密保持契約とアンケートの時間を含む）
内訳：秘密保持契約5分、試験80分、アンケート5分
試験問題数
約60問
受験料
￥16,500（税込）

:::note warn
試験を受ける前はHPをよく見ておらず実際に問題を解く時間が90分だと勘違いしてました。
問題を解く事が出来る時間は80分です。
合格ラインは65点でした。
:::

## Ver2.5

2022年2月1日から従来のVer2.0からVer2.5が追加されました。
リリース後6か月まで(2022年8月)はVer2.0かVer2.5のどちらでも受験が可能ですが、その後はVer2.5でのみ受験が可能です。

2.0と2.5の出題範囲の大きな違いはありませんが<b>マルチデバイス対応</b>の問題が2.0より多く出題される傾向にあります。

引用: https://html5exam.jp/images/outline/html5_lv1_ver25.pdf


## 合格までの勉強方法・時間

##### 勉強方法
##### 1. ping-t 
実際の試験に近い問題を解きたかったので、有料サイトのping-tを活用しました。
500問近くあり、解説が各問題ごとに詳しく説明されています。
全ての問題をコンボに変え尚且つ模擬試験を5回以上で90%を超えた時点で試験を受けました。


##### 2. 実際にコードを書く
Visual Studio Codeでping-tで出題されたcssやHTMLのコードを書いて、ブラウザでどんな形で表示されるのかを確認しました。
問題を解くだけではなく、実際にコードを書くことで知識が定着しやすくなりました。 

##### 時間
トータル => 約2か月 <br>

## 試験本番

最初の問題から全く分からずかなり焦りました。
ping-tで勉強した範囲より思った以上に深く聞かれる問題が数問あります。
ただ、ping-tをしっかり解いていれば60問中殆どの問題に対処可能だと思いました。
記述問題は、4~5問でした。スペルミスに注意です。

## 感想
今まで使っていたhtmlタグ以外にも沢山のタグや書式があるのを知り、自分が使っていたのはごく一部だけなんだなと感じました。
pタグやspanタグを乱用するのではなく、意図する意味に沿って書式等を書くようになる良い機会となりました。
次はLPICレベル1を合格した後により難易度の高いレベル2の試験を受けようと考えています。
【 LeetCode : Java 】876. Middle of the Linked List 

## 前提

エンジニア歴：3年
Java：1年
C#：2年
アルゴリズム、CSの専門知識無し
コーディングテストの為、学習中

## 問題
[876. Middle of the Linked List ](https://leetcode.com/problems/middle-of-the-linked-list/)

Given the head of a singly linked list, return the middle node of the linked list.
If there are two middle nodes, return the second middle node.

 

Example 1:


Input: head = [1,2,3,4,5]
Output: [3,4,5]
Explanation: The middle node of the list is node 3.
Example 2:


Input: head = [1,2,3,4,5,6]
Output: [4,5,6]
Explanation: Since the list has two middle nodes with values 3 and 4, we return the second one.
 

Constraints:

The number of nodes in the list is in the range [1, 100].
1 <= Node.val <= 100

## 解法

Node数を2で徐算した解に+1した要素が中央のノードになる。
```Java:
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        
        ListNode[] A = new ListNode[100];
        int t = 0;
        while (head != null){
            A[t++] = head;
            head = head.next;
        }
        return A[t / 2];
    }
}
```

## 引っ掛かった所

### 1. ListNodeの理解不足

そもそもListNodeが何か理解していなかった。

>少し調べてみたところ、このListNodeとはLinked List（連結リスト）と呼ばれるもので、「コンピュータサイエンスで使用される最も一般的なデータ構造の一つ」だそうです。

[引用元] [ListNode (もしくはLinked Lists)](https://procon.fun/2020/01/07/listnode/)

引数でListNodeクラスの配列が渡されると思っていたが、実際は連なったListNodeの先頭のインスタンスが渡される。

```Java:
// 例題1の渡される引数
Input: head = [1,2,3,4,5]

// 渡されるListNodeのイメージです
ListNode{
    int val = 1;
    ListNode next = ListNode{
        int val = 2;
        ListNode next = ListNode{
            int val = 3;
            ListNode next = ListNode{
                int val = 4;
                ListNode next = ListNode{
                    int val = 5;
                    ListNode next = null;
                }
            }
        }
    }
}

```

### 2. インクリメントの理解不足

```Java:
A[t++] = head;
```
インクリメントされて配列の要素を指定すると思っていたが、
実際にはtで配列の要素を指定してheadを代入後にインクリメントされる。

```Java:
A[t] = head;
t = t + 1;
```

前置インクリメント演算子と後置インクリメント演算子の違いについて理解する必要があった。
[参考] [前置と後置の違い](https://eng-entrance.com/javaプログラミング%E3%80%80～陥りやすいミス①～)
マークダウン記法の基本・書き方

## マークダウン記法の書き方
会議の議事録や社内ドキュメント、自分のメモを効率化するためにオススメなのが、「**マークダウン記法**」。上記の見出しや強調、文字装飾が簡単にできるので、読みやすい文書ができ、業務効率が上がる。

初回は、簡単にできる「マークダウン記法」の基本と使い方について解説します。


#### 改行
行末で「**半角スペース**」を「２個」入力すると改行される。
【例】
表記：私は〇〇です。（半角スペース×２）よろしくお願いします。
表示：私は〇〇です。
　　　よろしくお願いします。

#### 見出し
冒頭に「#」を入力することで見出しを作ることができる。「#」の数によって見出しの大きさを変えることができる。
【例】
表記：＃ Blogの書き方
　　　＃＃ Blogの書き方
　　　＃＃＃ Blogの書き方
表示：
# Blogの書き方
## Blogの書き方
### Blogの書き方

#### 箇条書き
文字の前に「*」（アスタリスク）をつけることによって箇条書きになる。
【例】
表記：
*Twitter
*Instagram
*LINE
表示：
* Twitter
* Instagram
* LINE

#### ナンバーリング
文字の前に数字とピリオドを入力することによって番号をふることができる。
【例】
表記：
1.Twitter
2.Instagram
3.LINE
表示：
1. Twitter
1. Instagram
1. LINE

#### 水平線
「*」（アスタリスク）、「-」（ハイフン）、「_」（アンダーバー）を、3つ以上入力すると「水平線」を表示することができる。
【例】
表記：
Twitter
　***
Instagram
ー
LINE
＿＿＿
表示：
Twitter
***

Instagram
-

LINE
___

#### チェックボックス
「-」(ハイフン）[]（大カッコ）を入力することによってチェックボックスを表示できる。チェック済みは[]の中にxを入力することによって表示できる。
【例】
表記：-[x]Twitter
　　　-[]Instagram
表示：
- [x] Twitter
- [ ] Instagram

#### 強調
文を「*」(アスタリスク）二つで囲むことによって太字にすることができる。
【例】
表記：＊＊Blog ＊＊
表示：**Blog**

#### 斜体
文を「*」(アスタリスク）一つで囲むことによって斜体にすることができる。
【例】
表記：＊Blog＊
表示：*Blog*

### 「画像・リンク」で使用することができるマークダウン記法
#### リンク
[リンクしたテキスト]（URL）と入力することによって指定したURLへリンクできるようになる。
【例】
表記：[グーグル]（URL）
表示：[グーグル](https://www.google.com/?hl=ja)

#### 画像
![代替テキスト]（URL）を入力することによって画像を表示することができる。
【例】
表記：![代替テキスト]（URL）
表示：![代替テキスト](URL)

#### 引用
引用元の前に「>」を入力することによって引用表記することができる。
【例】
表記：
＞Blog
表示：
>Blog
【Vue】ちょこっとずつVue.jsを読む➀

## 環境構築

雑
```sh
$ npm install -g @vue/cli
$ vue create プロジェクト名
$ npm run serve
```

## 初期のコードを削って見やすくする

```vuejs:src>App.vue
<template>
  <HelloWorld msg="Welcome to Your Vue.js App" />
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>
```

```vuejs:src>components>HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
};
</script>

```

ブラウザ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524160/6184fbf4-12f4-895f-c56d-8eb423699c7c.png)
【Angular】チェックボックスのdisabled(非活性)を親コンポーネントから制御する

## やろうとしていたこと
画面初期化時に、ある条件を満たした時だけ、チェックボックスを非活性にしたくなった。
しかしながら、チェックボックスは子コンポーネントとして、部品化されていたため、親コンポーネントから値を受け取れるように修正する必要があった。
その方法について紹介します。
この方法であれば、親コンポーネントごとに設定できるので、親コンポーネント同士で影響がありません。


### 子（checkbox.component）
　
クラス
```typescript
@Input()
fromParent:boolean = false;

```

テンプレート
```html
<input type="checkbox" [disabled]="fromParent">
</input>
```


### 親（page.component）
クラス
```typescript

disabledFlg: boolean　 = false;

ngOnInit(){
  this.changeDisabled();
}

changeDisabled(){
 if(someCondition){
  //特定の条件を満たしたら、trueをセット。
   disabledFlg = true;
 }
}

```

テンプレート
```html
<app-checkbox [fromParent]="disabledFlg"></app-checkbox>
```
Android11以上でステータスバーの高さを取得する方法

# はじめに
Android12の対応をする際、ステータスバーの高さを取得する方法を変更する必要が出てきたので、その際対応した内容を備忘録的に残しておこうと思います。

# 取得方法
取得方法は比較的シンプルです。
以下のようにsetOnApplyWindowInsetsListenerを使用して取得する形になります。

```
view.setOnApplyWindowInsetsListener { v, insets ->
   val statusBarHeight = insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()).top
}
```

以上になります。
注意点としては、上記は30以上が対象になるので、30以下のバージョンでは取得方法を変える必要があります。

# さいごに
ステータスバーを透過していたりするとこの辺りの修正が必須になりますよね。
透過対応はなかなか大変な作業の一つなので、この辺りの実装は慎重に行っていきたいところです。
【Angular】親子間での値の受け渡し方法

## やろうとしていたこと
多数のページ（コンポーネント）で、チェックボックやドロップダウンを使用するため、コンポーネントとして部品化しました。
そこで課題となるのが親子間のデータの受け渡しです。
この記事では、わかりやすく説明するために文字列を渡す方法について書いています。チェックボックスやドロップダウンの値を渡すにはこの方法を応用してください。

## ①親⇨子 by @Inputデコレータ

### 子コンポーネントのクラス

```typescript
// Inputのインポート
import { Input } from '@angular/core';

// 受け渡し用のプロパティ定義。ここに親から渡された値がセットされる。
@Input()
fromParentToChild: string = '';
```

### 子コンポーネントのテンプレート

```html
<span>{{ fromParentToChild }}</span>
```

### 親コンポーネントのクラス
親コンポーネントのクラスには特にインポートは必要ありません。
テンプレートに渡したい値をセットするだけです。
```typescript
parent = 'I am your father.'
```
### 親コンポーネントのテンプレート

```html
<app-child [fromParentToChild]="parent"></app-child>
```

## ②子⇨親 by @Outputデコレータ

### 子コンポーネントのクラス
@Outputデコレータではイベントの発火により子から親に対して、通知を行います。

```typescript
// Outputのインポート
import { Output, EventEmitter } from '@angular/core';

@Output()
event = new EventEmitter<String>();

//チェックボックスをONOFFするとこのメソッドが走る。
onChanged() {
 this.event.emit('チェックボックスが選択されました');
}
```

### 子コンポーネントのテンプレート

```html
<input type="checkbox" (change)="onChanged()">
</input>
```

### 親コンポーネントのクラス
```typescript
fromChildData: string = '';

onChangeFromChildData(eventData: String) {
  this.fromChildData = eventData;
}
```
### 親コンポーネントのテンプレート

```html
<app-child (event)="onChangeFromChildData($event)"></app-child>
<span>{{ fromChildData }}</span>
```



https://angular.jp/tutorial/toh-pt3


https://qiita.com/ksh-fthr/items/db6a48d072d5e9a33f0b
【Emacs】Ubuntu22.04でJediを入れたらTypeErrorが起きた話

# 起こったこと

- Ubuntu22.04
- Python 3.10.4
- GNU Emacs 28.1


の環境で

```bash
pip install jedi epc
```

したあと、emacs上で`company-jedi`パッケージをインストール。
で、pyファイルを開いて編集すると、補完がされない。

Messageバッファでログをみると、以下のエラーメッセージを発見。


> jedi deferred error : (error "\"TypeError('Script.__init__() takes from 1 to 2 positional arguments but 5 positional arguments (and 1 keyword-only argument) were given


# 解決

emacsパッケージの方が、jedi（pythonライブラリ)の最新バージョン0.18に対応していないみたい。
古いバージョンをインストールしたら解決。

```
pip install jedi==0.17.2
```

参考：https://github.com/davidhalter/jedi/issues/1802
コマンドラインからエミュレータをkillする

# 概要
AndroidStudioで下記のエラーでエミュレータが起動できなくなった際の対応法を備忘録として残します。
```text:エラーメッセージ
ERROR | Running multiple emulators with the same AVD ERROR | is an experimental feature. ERROR | Please use -read-only flag to enable this feature.
```
GUI上で起動しているエミュレータがなくても起動できなくなるため、コマンドラインからの停止を試しました。
# 環境
- macOS Monterey 12.4
- Android Studio Bumblebee

# 対応
adbコマンドを使用して起動しているエミュレータをkillします。
*adbコマンドの詳細については割愛します。
```text:起動中のデバイスを確認
adb devices
```
```text:実行結果
List of devices attached
emulator-5554	device
```
GUI上で閉じていても起動していることがわかります。
```text:起動しているエミュレータをkill
adb -s emulator-5554 emu kill
```
```text:実行結果
OK: killing emulator, bye bye
OK
```
killが成功したらAndroidStudioからエミュレータを起動する
# 参考
https://stackoverflow.com/questions/20155376/android-stop-emulator-from-command-line/20155436#20155436