OmniAICreator/Qiita-1.07M huggingface dataset:
KDoc メモ

# KDoc とは

JavaのJavaDocに相当する、Kotlinのドキュメンテーションコメントからドキュメントを生成する仕組み。
参考：https://kotlinlang.org/docs/reference/kotlin-doc.html

# 構文

`/**`と`*/`で囲み、その間の行は`*`で始まる。
最初の空白行までのブロックは要素の概要説明、次のブロックは詳細説明。
ブロックタグは新しい行で`@`から始まる。

# ブロックタグ

| タグ          | 内容                     |
|--------------|-------------------------|
| param        | クラス・関数のパラメータ・型引数 |
| return       | 関数の戻り値               |
| constructor  | クラスのプライマリコンストラクタ  |
| receiver     | 拡張関数のレシーバ          |
| property     | クラスのプロパティ           |
| throws       | メソッドがスローする例外       |
| exception    | メソッドがスローする例外       |
| sample       | 要素の使用例を関数で示す     |
| see          | クラス・メソッドのリンク        |
| author       | 要素の作成者              |
| since        | 要素が導入されたバージョン    |
| suppress     | 要素をドキュメントから除外する  |

# サンプルコード

```kotlin:KDocMemo.kt
package com.example.kdocsample

/**
 * クラスの説明
 *
 * クラスの詳細な説明
 *
 * @see X
 * @see X.y
 * @see X.z
 *
 * @author 作成者の名前
 *
 * @since 導入されたバージョン
 *
 * @param T 型変数の説明
 *
 * @constructor プライマリコンストラクタの説明
 *
 * プライマリコンストラクタの詳細な説明
 *
 * @param a プライマリコンストラクタの引数の説明
 *
 * @property b プロパティの説明（プライマリコンストラクタ）
 */
class KDocMemo<T> (a: Int, val b: Int) {

    /**
     * セカンダリコンストラクタの説明
     *
     * セカンダリコンストラクタの詳細な説明
     *
     * @param a セカンダリコンストラクタの引数の説明
     */
    constructor(a: Int) : this(a, a)

    /**
     * プロパティの説明（クラス内宣言）
     */
    val c = 1

    /**
     * メソッドの説明
     *
     * @receiver レシーバの説明
     *
     * @param d メソッドの引数の説明
     *
     * @return メソッドの戻り値の説明
     *
     * @throws Throws 例外の説明
     * @exception Exception 例外の説明
     *
     * @sample sample
     */
    fun method(d: Int, e: Int.() -> Unit) = 2

    /**
     * @suppress ドキュメントから除外
     */
    fun suppressMethod() = Unit
}

fun sample() {
    val memo = KDocMemo<Int>(1)
    memo.method(2) {}
}

class X {
    val y = ""
    fun z() = ""
}
```

#出力結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506759/fa460ba4-2f75-b9ff-c863-c9c03769e641.png)

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506759/1ff3ab22-dd94-d456-c094-ab7d74be906d.png)

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506759/82cc6144-f289-e5b7-9198-fb282d6545b8.png)
Ubuntu 20.04にOpenJDK 13をインストール（Zulu Community）

# はじめに

Zulu Communityを利用してUbuntu20.04にOpenJDK13をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Download OpenJDK Java Linux Windows macOS Alpine Java 11 Java 8](https://www.azul.com/downloads/zulu-community/)

## サポート

本手法で導入した場合、[Zulu Community Java OpenJDK free download TCK tested](https://www.azul.com/products/zulu-community/)より、2023-03がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update; apt install -y software-properties-common
# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0xB1998361219BD9C9
# apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y zulu-13
... 略
```

### 各種確認

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

# java -version
openjdk version "13.0.3" 2020-04-14
OpenJDK Runtime Environment Zulu13.31+11-CA (build 13.0.3+3-MTS)
OpenJDK 64-Bit Server VM Zulu13.31+11-CA (build 13.0.3+3-MTS, mixed mode, sharing)
```
docker の備忘録

##  概要`
Docker周りの備忘録を書き、随時更新していきます。

## 記録

### remote ssh できるようにセットアップ

```bash
apt-get update &&\
apt-get install -y openssh-server &&\
mkdir ~/.ssh && \
echo 'root:password' | chpasswd &&\
sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config &&\
/etc/init.d/ssh restart
```

この時、`~/.ssh` フォルダの下に`authorized_keys ` を作り、公開鍵情報を書き込む。
詳しくはhttps://qiita.com/kenmaro/items/a548a302228029c5c870　　


### docker と docker-compose を　ubuntu18.04 にインストール　
https://qiita.com/iganari/items/fe4889943f22fd63692a
まとめていただきありがとうございます。

```bash
sudo apt update &&\
sudo apt install -y \
     apt-transport-https \
     ca-certificates \
     curl \
     software-properties-common &&\
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - &&\
sudo add-apt-repository \
     "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
     $(lsb_release -cs) \
     stable" &&\

sudo apt update &&\
sudo apt install -y docker-ce &&\
export compose='1.25.5' &&\
sudo curl -L https://github.com/docker/compose/releases/download/${compose}/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose &&\

sudo chmod 0755 /usr/local/bin/docker-compose

```

をやって、

```bash
sudo systemctl status docker
docker-compose -v
```

などをやって確かめる。


### docker image を tar file でエクスポート

```bash

docker save <docker_image_name> -o <docker_image_name>.tar
```

### エクスポートされた image を　ロードする

```bash
docker load < <docker_image_name>.tar
```

### 上のロードしたイメージをコンポーズアップするときのエラー

``` 
[6] Error loading Python lib '/tmp/_MEItTTce4/libpython3.6m.so.1.0': dlopen: libexpat.so.1: cannot open shared object file: No such file or directory
```


### docker コンテナをそのままイメージにする

```
docker export <container id> > <file name>
cat <file name> | docker import <image name>:latest
```

### docker in docker できるように第一コンテナをランする

```

```
Ubuntu 20.04にOpenJDK 11をインストール（Zulu Community）

# はじめに

Zulu Communityを利用してUbuntu20.04にOpenJDK11をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Download OpenJDK Java Linux Windows macOS Alpine Java 11 Java 8](https://www.azul.com/downloads/zulu-community/)

## サポート

本手法で導入した場合、[Zulu Community Java OpenJDK free download TCK tested](https://www.azul.com/products/zulu-community/)より、2027-09がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update; apt install -y software-properties-common
# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0xB1998361219BD9C9
# apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y zulu-11
... 略
```

### 各種確認

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

# java -version
openjdk version "11.0.7" 2020-04-14 LTS
OpenJDK Runtime Environment Zulu11.39+15-CA (build 11.0.7+10-LTS)
OpenJDK 64-Bit Server VM Zulu11.39+15-CA (build 11.0.7+10-LTS, mixed mode)
```
UiPath ロボットの名前を変えてみる！

ロボットをとりあえず作ってみるといった場合、ロボットの名前も"とりあえず"付けてしまうことって、あるかと思います。
今回は、"*テキトーに付けたロボットの名前*" を後から変更する方法を紹介します。


# ロボットの名前が表示される場所
ロボットの名前は、UiPath Studioの画面上部、またはプロセスを開くときの画面で表示されます。
このプロセスでは、**"TestRobo"** と名前が付けられています。
![2020-04-25_10h51_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626057/323b18f6-6ce7-f22f-868e-2222b2deeb69.png)

![2020-04-25_10h52_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626057/da1affb4-9105-168c-d8f8-502eb5fa0157.png)

# ロボットの名前の変更方法
1. UiPathでは、プロジェクトディレクトリにある `"project.json"` でこの名前を管理しています。
![2020-04-25_11h08_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626057/afbba3a8-d3fa-6fe3-8ad0-a35be2911046.png)

2. このファイル(`project.json`)をテキストエディタなどで開き、`"neme": "TestRobo"`の部分を変更し、保存します。

```javascript:元のコード
{
  "name": "TestRobo",
  "description": "Test Process",
  "main": "Main.xaml",
  
  //(省略)
},
```
```javascript:変更したコード
{
  "name": "Report_Create_Robot",
  "description": "Test Process",
  "main": "Main.xaml",

  //(省略)
},
```

# ロボットの名前の確認
`project.json`を変更したロボットを再度開くと、変更を確認できます。
![2020-04-25_11h28_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626057/9beff787-ee83-357e-16b0-5e5c27e1be34.png)
![2020-04-25_11h30_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626057/4c35b206-016a-1212-0f46-206299e4ff3d.png)

>ちなみに、上記画面に表示されている "Test Process"も、`project.json`の`description: `を変更することで、修正することができます。

ロボットの名前の変更方法の説明は、以上で終わりです。
ロボットの名前を変更した場合のOrchestratorへの影響については、別の記事に記載します。

<br>
<br>
Ubuntu 20.04にOpenJDK 8をインストール（Zulu Community）

# はじめに

Zulu Communityを利用してUbuntu20.04にOpenJDK8をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Download OpenJDK Java Linux Windows macOS Alpine Java 11 Java 8](https://www.azul.com/downloads/zulu-community/)

## サポート

本手法で導入した場合、[Zulu Community Java OpenJDK free download TCK tested](https://www.azul.com/products/zulu-community/)より、2026-03がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update; apt install -y software-properties-common
# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0xB1998361219BD9C9
# apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y zulu-8
... 略
```

### 各種確認

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

# java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (Zulu 8.46.0.19-CA-linux64) (build 1.8.0_252-b14)
OpenJDK 64-Bit Server VM (Zulu 8.46.0.19-CA-linux64) (build 25.252-b14, mixed mode)
```
attributesとは、、？

##attributesとは
モデルに含まれるすべての属性を指します。

###attributesを更新する方法
・　一括更新し、そのあとに保存する

```

@post = Post.find(1)
@post.attributes = { title: '日常の眺め' }
@post.save()
```

・一括更新し、すぐに保存する

```

@post = Post.find(1)
@post.update_attributes({ user_id: 1, title: '日常の眺め' })
```
英語とエンジニアリングをYouTubeで学ぶ

# はじめに
私は英語があまり得意ではありません。リーディングやリスニングは大学受験レベルでライティングは英語圏の人と意思疎通はなんとか取れるレベル、スピーキングに関してはほぼほぼできません。
また、システムエンジニアとしても2020年4月現在文系新卒3年目というIT業界に入って日が浅い新人です。
そのようなレベルの私が、英語圏のテック系YouTuberの動画を視聴することで英語とエンジニアリングを効率よく学べているのでジャンルごとのおすすめYouTuberを紹介いたします。
リスニング能力が足りていない場合は、英語の字幕をつけて視聴することをおすすめします。

なお、TOEICの点数を上げるために視聴するというのはあまり効率的ではないと思うのであまりおすすめしません。

# 目次

1. コンピュータサイエンス
2. プログラミング
3. ネットワーク
4. DevOps
5. 番外

# 1.コンピュータサイエンス

## CrashCourse
[CrashCourse YouTube Channel URL](https://www.youtube.com/user/crashcourse)

先述の通り、私は文系出身のためComputerScienceの基礎を身に付けずにIT技術を学んでいました。
業務に慣れたため一通りComputerScienceの基礎を学んでおこうと思い幾つか基礎的な内容を視聴しました。日本人にも聞き取りやすいはっきりとした発音で低レイヤーな内容を視覚的にもわかりやすく説明していて体系的に学ぶにはとても良いコンテンツだと思います。


# 2. プログラミング

## Corey Schafer（Python）
[Corey Schafer YouTube Channel URL](https://www.youtube.com/channel/UCCezIgC97PvUuR4_gbFUs5g)

Pythonに特化した内容のチャンネルです。
基礎文法やPython特有機能からDjango，FlaskといったフレームワークPandasライブラリまでジャンルごとに丁寧に説明しているため、Pythonを学びたい初学者から経験者まで幅広い層におすすめできるチャンネルだと感じました。

## freeCodeCamp.org 
[freeCodeCamp.org YouTube Channel URL](https://www.youtube.com/channel/UC8butISFwT-Wl7EV0hUK0BQ)

様々な言語やフレームワーク、技術に関して複数人で動画を投稿しているチャンネルです。
好きなジャンルの動画を見つけて視聴するにはとてもいいと思います。
動画の時間が最低でも１時間長いもので１０時間に及ぶため、私は途中で挫折してしまいました。


## Programming with Mosh(Python,JavaScript,Java)
[Programming with Mosh YouTube Channel URL](https://www.youtube.com/channel/UCWv7vMbMWH4-V0ZXdmDpPBA)

各言語のチュートリアルがメインですが、おすすめはデザインパターンを説明している動画です。リンクを貼っておきます。
（https://www.youtube.com/watch?v=NU_1StN5Tkk&list=RDCMUCWv7vMbMWH4-V0ZXdmDpPBA&start_radio=1&t=2608）


# 3. ネットワーク

## Network Engineer Academy

[Network Engineer Academy YouTube Channel URL](https://www.youtube.com/channel/UCLT5uVgq4vok5rOys7bL4UQ)

個人的に最もおすすめするチャンネルです。ネットワークの概念についてとてもわかりやすく説明されている動画がたくさんあります。英語とネットワークに加えてプレゼンテーションについても見て学ぶことができ、とても素晴らしいチャンネルだと思っています。是非一度ご覧ください。

# 4. DevOps

## IBM Cloud
[IBM Cloud YouTube Channel URL](https://www.youtube.com/channel/UCKWaEZ-_VweaEx1j62do_vQ)

今回紹介する唯一の企業が持つチャンネルです。私は業務上コンテナオーケストレーションやInfrastracture as Codeに関わることが多くとても理解に役立つ内容だと実感しています。コマンド操作の説明ではなく図を使った概念説明となっており、インフラ系の最新技術学ぼうと思っている人には最適な内容かと思います。

# 5. 番外

## Ted
[Ted YouTube Channel URL](https://www.youtube.com/user/TEDtalksDirector)
ご存知の方も多いかと思いますが、オンラインの講演を発信しているメディアです。
自己啓発や社会問題など、興味がある分野を探して視聴してみるといいかと思います。
専用のアプリがあるので是非ダウンロードしてみてください。
Ubuntu 20.04にOpenJDK 7をインストール（Zulu Community）

# はじめに

Zulu Communityを利用してUbuntu20.04にOpenJDK7をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Download OpenJDK Java Linux Windows macOS Alpine Java 11 Java 8](https://www.azul.com/downloads/zulu-community/)

## サポート

本手法で導入した場合、[Zulu Community Java OpenJDK free download TCK tested](https://www.azul.com/products/zulu-community/)より、2023-07がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update; apt install -y software-properties-common
# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0xB1998361219BD9C9
# apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y zulu-7
... 略
```

### 各種確認

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

# java -version
openjdk version "1.7.0_262"
OpenJDK Runtime Environment (Zulu 7.38.0.11-CA-linux64) (build 1.7.0_262-b10)
OpenJDK 64-Bit Server VM (Zulu 7.38.0.11-CA-linux64) (build 24.262-b10, mixed mode)
```
【Go】echoを使ってさくっとAPIサーバを構築する

# はじめに
Goはインストールしてあるものとします。
echoはGoの軽量フレームワークとして有名です。

Goはフレームワークが群雄割拠しているので、一強なものがあるとわかりやすくていいですよね。
JavaのSpring、RubyのRails的な。

# echoの動作確認
## echoをインストール
echoをインストールします。

```
$ go get -u github.com/labstack/echo
```

## Hello, World!
### 1. 実装
任意のディレクトリに以下のファイルを作成します。

```go:server.go
package main

import (
	"net/http"
	
	"github.com/labstack/echo"
)

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}
```

### 2. 起動
1.でファイルを作成したディレクトリで以下のコマンドを実行します。

```
$ go run server.go
```

### 3. 動作確認
http://localhost:1323/ にアクセスして「Hello, World!」が表示されていることを確認します。

# GETパラメータを受け取ってJSONを返す
以下の通りです。
直観的でいいですよね！

```go:server.go
package main

import (
	"net/http"

	"github.com/labstack/echo"
)

type User struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

func main() {
	e := echo.New()
	e.GET("/user", show)

	e.Logger.Fatal(e.Start(":1323"))
}

func show(c echo.Context) error {
	u := new(User)
	if err := c.Bind(u); err != nil {
		return err
	}
	return c.JSON(http.StatusOK, u)
}

```

http://localhost:1323/user?name=yagi_eng&email=hoge@gmail.com
などとアクセスすると、以下のようにJSONが返ってきます。

```
{"name":"yagi_eng","email":"hoge@gmail.com"}
```

# POSTパラメータを受け取ってJSONを返す
GETをPOSTに変えるだけです。

```go:server.go
import (
    "net/http"
 
    "github.com/labstack/echo"
)
 
type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}
 
func main() {
    e := echo.New()
    e.POST("/users", display)
 
    e.Logger.Fatal(e.Start(":1323"))
}
 
func display(c echo.Context) error {
    u := new(User)
    if err := c.Bind(u); err != nil {
        return err
    }
    return c.JSON(http.StatusOK, u)
}
```

# 参考
- [echoの公式ドキュメント](https://echo.labstack.com/guide)
- [【第4回】Go言語（Golang）入門～REST API環境構築編～](https://rightcode.co.jp/blog/information-technology/golang-introduction-rest-api)
ゼロから始めるLeetCode Day2 「1108. Defanging an IP Address」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

その対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイト。

せっかくだし人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

基本的にeasyのacceptanceが高い順から解いていこうかと思います。

前回
[ゼロから始めるLeetCode Day1 「1389. Create Target Array in the Given Order」](https://qiita.com/KueharX/items/58d288348a5b39f7898d)

# 問題

[1108. Defanging an IP Address](https://leetcode.com/problems/defanging-an-ip-address/)

`Input: address = "1.1.1.1" Output: "1[.]1[.]1[.]1"`

`Input: address = "255.100.50.0" Output: "255[.]100[.]50[.]0"`

与えられたIPアドレスの.を[.]に代えるだけです。

```Python
class Solution:
    def defangIPaddr(self, address: str) -> str:
        address = address.replace('.','[.]')
        return address
# Runtime: 24 ms, faster than 88.37% of Python3 online submissions for Defanging an IP Address.
# Memory Usage: 14 MB, less than 100.00% of Python3 online submissions for Defanging an IP Address.
```
replace()を使うだけで終わり！

・・・と思っていたのですが、そもそもaddressに代入せずに直接returnした方が速いのでは？と思い、書き直す。

```Python
class Solution:
    def defangIPaddr(self, address: str) -> str:
    return address.replace('.','[.]')
# Runtime: 24 ms, faster than 88.37% of Python3 online submissions for Defanging an IP Address.
# Memory Usage: 13.7 MB, less than 100.00% of Python3 online submissions for Defanging an IP Address.
```

メモリの使用量が少し減っただけでした。

Discussをチラッとみてみたら他にはこれがメジャーっぽい。
一旦split関数を使ってリストに代入し、join関数を使って数字の間に`'[.]'`を挿入するというもの。

```Python

class Solution:
	def defangIPaddr(self, address: str) -> str:
		return "[.]".join(address.split("."))
# Runtime: 28 ms, faster than 65.40% of Python3 online submissions for Defanging an IP Address.
# Memory Usage: 13.7 MB, less than 100.00% of Python3 online submissions for Defanging an IP Address.
```

ちなみにsplit関数とjoin関数はそれぞれ以下のような仕様です。

>str.split(sep=None, maxsplit=-1)
文字列を sep をデリミタ文字列として区切った単語のリストを返します。maxsplit が与えられていれば、最大で maxsplit 回分割されます (つまり、リストは最大 maxsplit+1 要素になります)。 maxsplit が与えられないか -1 なら、分割の回数に制限はありません (可能なだけ分割されます)。
sep が与えられた場合、連続した区切り文字はまとめられず、空の文字列を区切っていると判断されます(例えば '1,,2'.split(',') は ['1', '', '2'] を返します)。引数 sep は複数の文字にもできます (例えば '1<>2<>3'.split('<>') は ['1', '2', '3'] を返します)。区切り文字を指定して空の文字列を分割すると、 [''] を返します。
例えば:

```Python
'1,2,3'.split(',')
['1', '2', '3']
'1,2,3'.split(',', maxsplit=1)
['1', '2,3']
'1,2,,3,'.split(',')
['1', '2', '', '3', '']
```

>sep が指定されていないか None の場合、異なる分割アルゴリズムが適用されます。連続する空白文字はひとつのデリミタとみなされます。また、文字列の先頭や末尾に空白があっても、結果の最初や最後に空文字列は含まれません。よって、空文字列や空白だけの文字列を None デリミタで分割すると [] が返されます。
例えば:

```Python
'1 2 3'.split()
['1', '2', '3']
'1 2 3'.split(maxsplit=1)
['1', '2 3']
'   1   2   3   '.split()
['1', '2', '3']
```

>str.join(iterable)
iterable 中の文字列を結合した文字列を返します。 iterable に bytes オブジェクトのような非文字列の値が存在するなら、 TypeError が送出されます。要素間のセパレータは、このメソッドを提供する文字列です。

細かい関数は使いながら覚えていくのがいいとは思いますが、この問題に関して言えばreplace関数を使った方がシンプルでわかりやすいと思いました。
AtCoder Beginner Contest 154の復習, E問まで(Python)

競プロ初心者の復習用記事です。

ここで書く解は解説や他の人の提出を見ながら書いたものです。自分が実際に提出したものとは限りません。

# [A - Remaining Balls](https://atcoder.jp/contests/abc154/tasks/abc154_a)

二種類の文字列とそれぞれに属するボールの数を与えられ、どちらか指定されたボールを一個取り出してからそれぞれの数を出力する問題です。

入力`U`はどちらかの文字列には一致することが指定されているのはポイント。

```python
S, T = input().split()
A, B = map(int, input().split())
U = input()

if U == S: A -= 1
else: B -= 1
print(A, B)
```


# [B - I miss you...](https://atcoder.jp/contests/abc154/tasks/abc154_b)

指定された文字列を'x'に置き換えて出力する問題です。

入力された文字数分だけのxを返しました。

```python
S = input()
print("x" * len(S))
```

# [C - Distinct or Not](https://atcoder.jp/contests/abc154/tasks/abc154_c)

入力された配列に重複がないか調べる問題です。

set型に入れることで重複なしの配列長を調べました。出力が'Yes'じゃなくて'YES'であることに注意しましょう(一敗)。

```python
N = int(input())
A = list(input().split())

if len(set(A)) == N:
  print('YES')
else:
  print('NO')
```

# [D - Dice in Line](https://atcoder.jp/contests/abc154/tasks/abc154_d)

値$p_i$を最大値とするサイコロから、隣接した番号のサイコロK個を抜きだして期待値を答える問題です。

期待値はそれぞれのサイコロごとに独立した値なので、足し算引き算が可能です。まずそれぞれの期待値を求めて、それぞれのサイコロの持つ最大値を上書きしてしまいます。

あとはインデックスをずらしながら（ずらして抜ける値は減らし、加わる値は増やして）最大値を探しました。

```python
N, K = map(int, input().split())
P = list(map(int, input().split()))

P = [(1+p)/2 for p in P]

tmp = sum(P[:K])
maxV = tmp

for i in range(N-K):
  tmp += P[i+K] - P[i]
  maxV = max(maxV, tmp)
print(maxV)
```

# [E - Almost Everywhere Zero](https://atcoder.jp/contests/abc154/tasks/abc154_e)

十進数表記で1~9までの数字がK個入るN桁の数字の数を答える問題です。

1からN桁の999...までの数字に条件を満たす数は
$$ {}_N C _K \times 9^K $$
だけある...で、だから？という感じで探索の方法がわからず諦めました。以下の解答にこの計算式は使用しません。

解説を見ました。桁DPというアルゴリズムを使うそうです。[こちら](https://qiita.com/pinokions009/items/1e98252718eeeeb5c9ab)を参考に桁DPを学びました。

このような三次元配列を作成します。

```
dp[i][smaller][k]
```

ここで`i`は左端を1として数えた桁数(もう一つ左に値0の0桁目が存在すると考える)、`smaller`は1ならそこまでの桁が取りうる最大値を取っていないこと、`k`はその桁までの登場した0以外の数字の個数を表します。

こういうルールで左から順番に数えたものが以下のコードです。処理の細かい解説は厄介なので省略します。

これで通りました。

```python
N = [0] + list(map(int, input()))
N = [0] + list(map(int, input()))
K = int(input())
n = len(N)

DP = [
      [[0] * (K+2) for _ in range(2)] for _ in range(n)
]

# 0桁目(0)で最大値を取っていてk=0の要素は1個。
DP[0][0][0] = 1

for i in range(1, n):
  for k in range(K+1):
    if N[i] != 0:
      DP[i][0][k+1] += DP[i-1][0][k]
      DP[i][1][k] += DP[i-1][0][k]
      DP[i][1][k+1] += DP[i-1][0][k] * (N[i] - 1)
    else:
      DP[i][0][k] += DP[i-1][0][k]
    DP[i][1][k] += DP[i-1][1][k]
    DP[i][1][k+1] += DP[i-1][1][k] * 9
print(DP[n-1][1][K] + DP[n-1][0][K])

```

この記事はここまでとします。
Ubuntu 20.04にOpenJDK11 + OpenJ9をインストール（AdoptOpenJDK）

# はじめに

AdoptOpenJDKを利用してUbuntu20.04にOpenJDK11 + OpenJ9をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Installation | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/installation.html)

## サポート

本手法で導入した場合、[Support | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/support.html)より、2024-10がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update;apt install -y wget software-properties-common
# wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | apt-key add -
# add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y adoptopenjdk-11-openj9
... 略
```

### 各種確認

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

# java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.20.0, JRE 11 Linux amd64-64-Bit Compressed References 20200416_574 (JIT enabled, AOT enabled)
OpenJ9   - 05fa2d361
OMR      - d4365f371
JCL      - 838028fc9d based on jdk-11.0.7+10)
```
Rails6  Webpack  Jsファイル  precompileできない。

どうもチャンクノです。
個人的に開発してるアプリで、webpackで管理しているjsファイルが急にprecompileに失敗してしまいました。
今回はそれを解決したお話です。

https://qiita.com/chimame/items/8d3d6f4afea675cffa7d
解決できたのはこの記事の

```
config/webpack/environment.js

const { environment } = require('@rails/webpacker')

+ // デフォルトのセッティングでいいならこの行を足すだけで有効になる。
+ environment.splitChunks()

+ // カスタムなセッティングを入れるなら以下のようにファンクションで処理をする
+ //environment.splitChunks((config) => Object.assign({}, config, { optimization: { splitChunks: false }}))

module.exports = environment

上記を書いたらこれに書き直す。
<%= javascript_packs_with_chunks_tag 'hoge' %>
```
この部分です。
webpack4系と3系で記述が異なるみたいなので注意しましょう。
ちなみに自分は4系です。
この内容を記述して、本番に反映したら無事precompileできました。
めでたしめでたし。

5つめのjsファイルを作成したら何も記述していなくても失敗するというところまで原因が特定できていたので、容量の問題か何かなのかなと思い

```
Rails webpack precompile 容量 上限
```
みたいな感じでググったら出てきた気がします。
最近は検索力がついてきたのか自分1人で調べて解決できることが多くなってきて多少なりとも成長を感じています。
この調子で引き続き頑張っていきたい所存です。

それでは今日はこの辺で！
皆様よきプログラミングライフを🙏
Podに親オブジェクトを設定する

モチベーションは、OperatorでGo言語使ってCRの子オブジェクトを作るのがかったるいのでkubectl+yamlで出来ないかと思ったから。試したら出来たのでメモ。

例えばPodをConfigMapの子オブジェクトとして作成することが出来、ConfigMapを削除するとその子供であるPodも削除される。Namespaceを削除すると、そのNS内のオブジェクトが全部削除されるのと一緒。

#１．ConfigMapを作る
```
# kubectl create cm parent --from-literal key=value
# kubectl get cm parent
NAME     DATA   AGE
parent   1      8m37s
```

#２．ConfigMapのUIDを取得する
```
# CMUID=$(kubectl get cm parent -o jsonpath='{.metadata.uid}')
# echo $CMUID
e48f82ed-1f18-4534-ae4a-73985aad9c41
```

#３．子Podのyaml
ownerReferencesに親オブジェクトを指定する。
「CMUID」は後で置き換える。

```yaml:child.yaml
apiVersion: v1
kind: Pod
metadata:
  name: child
  ownerReferences:
  - apiVersion: v1
    kind: ConfigMap
    name: parent
    uid: CMUID
spec:
  containers:
  - name: child
    image: nginx
```

#４．子Podを作る
```
# sed child.yaml -e "s/CMUID/$CMUID/" | kubectl create -f -
# kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
child                          1/1     Running   0          2m28s
```

#５．親のConfigMapを削除する
子Podも一緒に削除される。

```
# kubectl delete cm parent
# kubectl get pod
NAME                           READY   STATUS        RESTARTS   AGE
child                          0/1     Terminating   0          3m48s
# kubectl get pod
No resources found in default namespace.
```


(参考) Kubernetes - Owners and dependents
https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/#owners-and-dependents
find_or_initialize_byとは、、？

## find_or_initialize_byとは
オブジェクトを探してあった場合は取得し、ない場合は新規作成するメソッド。

###find_or_create_byの違いとは？
find_or_create_byは、オブジェクトを探してあった場合は取得することは同じですが、ない場合は新規作成しそれを保存するメソッドです。
保存まで行いたい時はこちらのメソッドを使用します。

##使用例

```

@user = User.find_or_initialize_by(name: 'test')
  unless @user.persisted?
      # @user が保存されていない場合の処理を書く
      @user.save
    end
end
```

##　参考
find_or_create_byとfind_or_initialize_byの違い
https://mom0tomo.hateblo.jp/entry/2018/09/14/151910
SEOは終わったという根拠

SEO対策の最前線とは。2020年は更に変化の波が訪れてきました。2018年頃から今までの方式は通用しにくくなってきた。2019年は更に大きな変化。もはや「ユーザーのニーズに合いさえすればいい」はまったく通用しないのです。

SEO業者のコンサルティングではすでに昔から終わったとされてました。SEO業者自信が「オワコン」というくらい。被リンクが有効ではなくなり、ドメインの価値で決まるようになった。

<a href="https://stamp-purchase-value.net/how-much-stamp-purchase-price-list/" >切手の買取相場価格</a>サイトのように一般では全く評価があがらない。SEOとはホワイト、ブラックという二極化にも意味がなくなってきたのです。

昔のSEOです。ホワイトハットというアルゴリズムはない。ドメインに価値があるのか、ないのか。今多くのブロガーが辞めています。長く続けていて、オールドドメインになっても無価値なのです。<a href="https://medium.com/@ant07420mm/%E3%81%BE-f83fbf6eedb3" >Medium</a>でSEO対策しても評価は上がりにくくなりました。
Ubuntu 20.04にOpenJDK 11 + HotSpotをインストール（AdoptOpenJDK）

# はじめに

AdoptOpenJDKを利用してUbuntu20.04にOpenJDK11 + HotSpotをインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Installation | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/installation.html)

## サポート

本手法で導入した場合、[Support | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/support.html)より、2024-10がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update;apt install -y wget software-properties-common
# wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | apt-key add -
# add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y adoptopenjdk-11-hotspot
... 略
```

### 各種確認

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

# java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)
```
tomcat 7.0.100 から ajp 1.3 Connectorタグ の secretRequired属性 の デフォルト値が trueになりました

# 現象
tomcat7 を 7.0.100 にバージョンアップすると、ajpでのapache との接続がエラーになるようになった。

# 原因
https://tomcat.apache.org/tomcat-7.0-doc/changelog.html　
にあるように、 7.0.100 から server.xml の Connectorタグ の secretRequired属性 のデフォルト値がtrueになったようです。

secretRequired=false にすることにより解消しました
Turbolinksについて

# 背景
 Turbolinksが原因でエラーが起きることが数回あったため、どういったものなのかを調べて自分なりにまとめました。備忘録として使います。

##  Turbolinksとは
Turbolinksは Asset Pipeline を活用しているアプリケーションにおいて画面遷移を高速化するライブラリ。

## 特徴
・　デフォルトで（プロジェクト生成時点で）有効になっている。
・　Turbolinks を導入すると Javascript のイベント発生タイミングが異なる。
・turbolinksでページをロードすると、jQueryのreadyイベントとDOMContentLoadedベントが発火しない。
代わりにいくつかイベントが用意されている。

```
page:fetch ページ読み込み開始
page:receive ページ読み込み完了(parse前)
page:change ページ更新完了
page:load 全ての処理終了
```
・aタグのリンクをクリックした時の遷移をajax化して画面遷移なしにページ遷移する。
・clickイベントの挙動を変えている
・・・etc

たくさんの特徴を持っており便利な部分があるがその反面使うのはしっかり理解していないと難しそう。。

##  Turbolinksを無効化する方法
もしもどうしても挙動がおかしくなる、turbolinksを消すとうまくいくといった場合は無効化してみましょう。

1.Gemfile から「gem ’turbolinks’」を削除する。

```ruby

gem ’turbolinks’ # この行を削除する
```

2.app/assets/javascripts/application.js から「//= require turbolinks」を削除する。

```application.js
//= require turbolinks  //この行を削除する
```

3.app/views/layouts/application.html.erb の javascript_include_tag や stylesheet_link_tag から「"data-turbolinks-track" => true」を削除する。



## 参考
6.Turbolinks
https://www.techscore.com/tech/Ruby/rails-4.0/turbolinks/

Rails 4のturbolinksについて最低でも知っておきたい事
https://kray.jp/blog/must-know-about-turbolinks/

Turbolinksを調べてみた
https://gist.github.com/saboyutaka/8727377
openJDKをインストールしているwindowsでlaunch4jでexe化したJavaアプリケーションが動かない時の対応

Oracle-Javaのライセンスがうんたらかんたら、ということなのでいろんなOpenJDKディストリを使っている。
仕事の関係上、クライアント型アプリを作ることもあり、（割と簡単に）Mac・Win対応できるということでJavaで作っていた。
jarファイルのままだと関連付けの問題から使えない人が出てきたりするので大変、exeできるということでlaunch4jでexeにラップさせていたが、
それだと特定のOpenJDKでは起動しないことがわかった。
以下はその対処法。
（なお、レジストリを編集する箇所があるので例によってトラブルに責任は負えません）

## lanunch4jで起動できるOpenJDKディストリ
・Amazon Coretto
・AdoptOpenJDK

けどAmazonCorettoはJavaFXのメディアサポートがまだ実装されていなかったり、Adoptの方はJavaFXがないこともあって、LibericaOpenJDKを使っている。
このLibericaはlaunch4jが動かせない。
（試してないけどzuru OpenJDKもだめみたい）

## Libericaがインストールされている状態では
・JAVA_HOMEは設定されている。
・PATHにも追加されているので、コマンドプロンプトなどから`java`コマンドは使用可能
・ただしlaunch4jは「JDKがない」と言われて起動できない。

## OracleJDKの公式ドキュメントより
https://docs.oracle.com/javase/jp/9/install/installation-jdk-and-jre-microsoft-windows-platforms.htm#JSJIG-GUID-47C269A3-5220-412F-9E31-4B8C37A82BFB
通常のJDKインストーラではWindowsのレジストリキーを書き込む。
launch4jは上記のレジストリキーを読み込み判断する方式のため、OpenJDKディストリによってはレジストリキーを書き込まないため動かない。

## レジストリキー追加
**お約束：レジストリ変更の前は念の為バックアップとりましょう。**
いろいろ試したところ、このキーを追加すれば起動できた。
`HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment`
`HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.8`
ということで、追加のコマンド（管理者モードのコマンドプロンプトから）

```
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment" /v CurrentVersion /t REG_SZ /d "1.8.0_252"
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.8" /v JavaHome /t REG_SZ /d "%JAVA_HOME%\jre"
```

一行目の"1.8.0_252"は適宜Javaのバージョンに書き換える。またパスの「1.8」の部分も同様にバージョンに合わせる。

(もしかしたらこれもいるかも)
`reg add "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.8.0_252"`

## 余談
jarがダブルクリックで立ち上がらない場合は、
`HKEY_CLASSES_ROOT¥.jar`
のレジストリキーを削除して、JREを再インストールするとうまくいくときがある。


### 参考にしたURL
https://sourceforge.net/p/launch4j/feature-requests/103/
https://github.com/AdoptOpenJDK/openjdk-installer/issues/64
Ubuntu 20.04にOpenJDK 8(1.8) + OpenJ9をインストール（AdoptOpenJDK）

# はじめに

AdoptOpenJDKを利用してUbuntu20.04にOpenJDK8 + OpenJ9をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)

参考：[Installation | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/installation.html)

## サポート

本手法で導入した場合、[Support | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/support.html)より、2026-05がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update;apt install -y wget software-properties-common
# wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | apt-key add -
# add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y adoptopenjdk-8-openj9
... 略
```

### 各種確認

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

# java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-b09)
Eclipse OpenJ9 VM (build openj9-0.20.0, JRE 1.8.0 Linux amd64-64-Bit Compressed References 20200416_608 (JIT enabled, AOT enabled)
OpenJ9   - 05fa2d361
OMR      - d4365f371
JCL      - cfa47e66cd5 based on jdk8u252-b09)
```
method@Class

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235834/856d536b-2353-6dc6-ffd9-d5fb81d884d3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235834/f89ef85d-28f1-b8a7-c5d9-a4ede5c5c764.png)
matplotlib で画像表示とかのメモ

## 背景

Jupyter Lab で Python でお手軽に画像の表示したり解析結果を表示したりしたい.

## プロットするときの画像サイズや解像度

デフォルトではやや小さい + 文字がぼやける

```py
from pylab import rcParams

rcParams['figure.figsize'] = 10,10 # figure size(in inches)
rcParams['figure.dpi'] = 300 # increase dpi
```

などとする.

Jupyter + Matplotlib > Figureのサイズを拡大する | 字のぼやけを緩和する
https://qiita.com/7of9/items/5851e542f4041ec33f2b

figsize はインチで指定している.

matplotlib逆引きメモ（フレーム編）
https://qiita.com/cnloni/items/20b5908fbae755192498

ありがとうございます.

## ヒストグラムを計算する

numpy.histogram

https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html

pytorch だと `torch.histc`
https://pytorch.org/docs/stable/torch.html#torch.histc


## matplotlib でヒストグラムを表示する

plt.hist を使う.

Pythonでヒストグラムをさくっと描画
https://qiita.com/uichi/items/9f3a0d21f8690bbedb43

## 画像評価

skimage に SSIM 機能がある

https://scikit-image.org/docs/dev/auto_examples/transform/plot_ssim.html

画像品質評価のPSNR, SSIMの実装と速度比較
https://qiita.com/redshoga/items/5e36d784a322c940f38e


## 画像比較, 誤差計算

OpenCV で頑張るのが楽かしら

Image Difference with OpenCV and Python
https://www.pyimagesearch.com/2017/06/19/image-difference-with-opencv-and-python/

## 拡大図を表示する

xlim, ylim で範囲していできる.

いろいろ組み合わせると inset 図として表示できる
https://matplotlib.org/3.1.1/gallery/subplots_axes_and_figures/zoom_inset_axes.html
 
## TODO

* [ ] HDR, floating point 画像をよろしく tone mapping したり, false color 表示する
「不具合を発見しちゃった・・・」のときの嫌な気持ちの正体を考えてみた

## あ、やっべ不具合発見しちゃった・・・

こんな気持ち、なったことありませんか？
自分は不具合見つける度にこんな気持ちになります。そして、めちゃくちゃ嫌です。
今日はそんな嫌な気持ちと決裂を告げたいと思い、この正体について考えてみることにします。

## 不具合を発見したときのわたしの気持ち

「嫌な気持ち」というのをもう少し具体的に表現していきます。
考えてみればいくつかの気持ちが重なり合って、「嫌だ」となっていることに気づきます。

- 説明するのが嫌だな
    - 正直不具合報告する時間があったら開発したい。そっちのが楽しい。
- 不具合ってなるとだいたいみんなテンション下がる
    - ので、気づいていても言い出しづらい
- 自分たち埋め込んでないのに・・・
    - だいたい発見する不具合は自分たちが埋め込んでいないものです
- 「直さなきゃいけない」という義務感
    - 期限つきだったりすると残業がちらついてさらに嫌な気持ちになります

まあどれも「仕方ない」の一言で片づけられそうな気もしますが、嫌なもんは嫌です。
自分は忍耐力が無いので、耐えろと言われても耐えたくありません。

## それぞれの嫌な気持ちを生み出している「力」

自分自身になんかしらの力が働いて、上で挙げたような気持ちになっていると考えます。
例えばですが、同じ不具合でも家でゲームしてて不具合を発見しても嫌な気持ちになりませんよね。
(そのバグの結果自分に不利益になる結果になれば別ですが、不具合を発見したこと自体については何とも思わないはずです。)
その自分に働いている「力」ってどんなものがあるかなと考えてみました。

- 説明するのが嫌だな
    - 不具合を発見したらユーザーに**説明しなければならない。**
    - の前に、社内ステークホルダーに**報告しなければならない。**
- 不具合ってなるとだいたいみんなテンション下がる
    - 不具合を修正しても、価値を届けられない
    - 不具合を発見すると、**仕事が増える**(のに、期間は変わらない)
- 自分たち埋め込んでないのに・・・
    - 責任感が出にくいので、やる気が出ない
- 「直さなきゃいけない」という義務感
    - テンション下がるという話と似ている気がします。

これらの力が全て無くなったら、不具合を発見しても嫌な気持ちにならないかという思考実験をしてみます。(不具合の性質上のものは仕方ないのでそのまま)
つまり、

- 不具合を発見しても報告する必要なし
- 不具合を修正する分、今週の仕事のゴールが手前になる
- 自分たちが埋め込んだ

であれば、不具合を発見しても「嫌な気持ち」にならないか？ということです。
自分は上記3点の条件下であれば、不具合を発見しても楽しく仕事ができそうです。

## 「力」を生み出している要因

- 不具合を発見したら、報告しないといけない
- 不具合を発見したら、仕事が増える(のに期間は変わらない)

についてこれらの「力」を埋め込んでいるものを考えてみます。(自分たちが埋め込んだは事実でしかないので、考えても仕方ないと思いここでは省きます。)

### 不具合を発見したら、報告しないといけない

- うちのシステムは○○できますと宣言している
- その機能を担保することでお金をいただいている
    - ので、会社に「責任」が発生している

### 不具合を発見したら、仕事が増える(のに期間は変わらない)

- 次のリリースで何をやるかを宣言している
    - し、それでお金をもらっている

どちらも「期間」と「仕様」を「約束」しているから起こっているのかなと。
(ちょっと頭が疲れてきて論理が飛躍しちゃっている気がする・・・)

## というわけで、20200425時点での私の結論

「期間」と「仕様」を約束してしまうのがよくない。
まあこれがないとお金にならないのなら、「仕方ない」んですかねぇ。。
→請負型開発をしている限りはここを抜け出せないと思ってます:frowning2:


結局尻すぼみな感じでまとまってないですが、最後まで読んでいただきありがとうございます！
[Rust] async-stdで非同期I/Oを試す

何度 async/await の解説を読んでもいまいちわかった感じがしないので, ともかく使ってみようと試行錯誤した成果です. エコシステムの進化が速すぎて情報集めに苦労しました. 個人的に一番 async/await の必要性が高かったファイル I/O を題材として取り上げます.


# 問題設定

コマンドライン引数としてあるディレクトリのパスが与えられるので, そのディレクトリ直下のファイルすべてについてチェックサムを計算せよ, という課題が与えらえたとしましょう. もちろん同期版のコードならすぐに書けます (ちょっと冗長ですが非同期版と比較しやすいようにしてあります).

```rust
use std::env;

fn main() {
    use std::{fs, io::Read};

    let directory = env::args().nth(1).unwrap();
    let entries = fs::read_dir(&directory).unwrap();

    for entry in entries {
        let entry = entry.unwrap();
        if entry.file_type().unwrap().is_file() {
            let filepath = entry.path();
            let mut file = fs::File::open(&filepath).unwrap();
            let bytes = {
                let mut bytes = Vec::new();
                file.read_to_end(&mut bytes).unwrap();
                bytes
            };
            let checksum = bytes.iter()
                .fold(0u8, |acc, b| acc.wrapping_add(*b));
            println!("{:?}: {}", filepath.file_name().unwrap(), checksum);
        }
    }
}
```

ここで, 計算対象のファイルサイズがバラバラで, 小さなものからかなり大きなものまで存在するとしたらどうでしょう？ このコードでは, 大きなファイルの I/O 待ちが発生している間, CPU はやることがありません. なんだかもったいないですね. 読み込みに時間がかかると思ったらそれはとりあえず後回しにして, 別の小さなファイルを読み込んでそのチェックサムを計算する, という風にできれば効率的な気がします. これこそが async/await が可能にしてくれる処理です.


# async-std 版

`std` とできるだけ同じ API を提供するという触れ込みの [`async-std`](https://crates.io/crates/async-std) を使って書き換えてみます.

```rust
use std::env;

fn main() {
    use async_std::{fs, io::ReadExt};

    let directory = env::args().nth(1).unwrap();
    let entries = std::fs::read_dir(directory).unwrap();

    let mut handles = Vec::new();
    
    for entry in entries {
        let entry = entry.unwrap();
        if entry.file_type().unwrap().is_file() {
            let handle = async_std::task::spawn(async move {
                let filepath = entry.path();
                let mut file = fs::File::open(&filepath).await.unwrap();
                let bytes = {
                    let mut bytes = Vec::new();
                    file.read_to_end(&mut bytes).await.unwrap();
                    bytes
                };
                let checksum = bytes.iter()
                    .fold(0u8, |acc, b| acc.wrapping_add(*b));
                println!("{:?}: {}", filepath.file_name().unwrap(), checksum);
            });
            handles.push(handle);
        }
    }
    
    async_std::task::block_on(async move {
        for handle in handles.into_iter() {
            handle.await;
        }
    })
}
```

なんだか `std::thread::spawn` するのと同じような感じで書けました. `time` により時間を計ると, 同期版と非同期版で `sys` 時間はほぼ同じですが, 同期版ではおおよそ `real` = `user` + `sys` であるのに対して, 非同期版では明らかに `real` < `user` + `sys` になっています. ファイルサイズが小さい順にチェックサムが表示されますし, たぶんこれで意図通りに動いているはずです.

__2020-04-26 追記__ @blackenedgold さんに [コメント](https://qiita.com/osanshouo/items/671c45072a79c7b27aba#comment-4a7842e34d862bcaf412) でこのコードの問題点と改善案を教えていただきました. ありがとうございます!

# 参考文献

- [Rustの非同期プログラミングをマスターする - OPTiM TECH BLOG](https://tech-blog.optim.co.jp/entry/2019/11/08/163000)
- [2019 年の非同期 Rust の動向調査](https://qiita.com/legokichi/items/53536fcf247143a4721c)
- [async-std - Announcing async-std](https://async.rs/blog/announcing-async-std/)
FlutterでNavigatorでの遷移で戻り値を受け取る

下記環境でFlutterアプリを開発中です。

|ツールなど|バージョンなど|
|:--|:--|
| MacBook Air Early2015|macOS Mojave 10.14.5|
|Android Studio |3.6.1|
|Java |1.8.0_131|
|Flutter|1.12.13+hotfix.5|
|Dart |2.7.0|

リスト画面-詳細(編集画面)-戻って画面更新、という非常によくあるパターンで、`Navigator.push`で起動した画面から、結果を戻す方法についての調査メモ。

# 戻るときの値セット

`Navigator.pop`で戻る時に、値をセットする方法です。

```dart
Navigator.pop(context, 戻したい値/オブジェクト);
```

とするだけ。

# 受け取る方法

起動元で、結果を受け取る方法です。

## 1.通常

特に複雑なことをしないで、普通に`Navigator.push`している場合です。
あるボタンで`push`している例です。

```dart

RaisedButton(
  child: Text('Next'),
  onPressed: () async {
      final result = await Navigator.pushNamed(context, '/next');
      debugPrint(result.toString); // 結果を処理
    );
  }
```

`Navigator.push`を呼ぶ関数は、非同期処理として`async`を付けます。
その中では、pushが戻ってくるのを待つという意味で、`await Navigator.push`とします。
`Navigator.push`が値を返してくれるので、それを受け取って処理をすれば良いです。


## 2.NavigationServiceを使っている場合

以下の記事で紹介した方法を使っている場合です。
[Flutter/Navigator遷移にBuildContextを不要にする/遷移のWidgetTest](https://qiita.com/kasa_le/items/8c80ae565186c9ac275a)

基本的にやることは同じですが、コードのサンプルとして残します。

```NavigationService.dart
class NavigationService {
  final GlobalKey<NavigatorState> navigatorKey =
      new GlobalKey<NavigatorState>();

  Future<dynamic> navigateTo(String routeName, {Object args}) async {
    return navigatorKey.currentState.pushNamed(routeName, arguments: args);
  }

  bool goBack() {
    return navigatorKey.currentState.pop();
  }
}
```

`navigateTo`に`async`を付けます。

```dart
class MyViewModel with ChangeNotifier{
  void navigateNextPage(final LogData data) async {
       // ルート遷移
      final NavigationService _navigationService = locator<NavigationService>();
      final result =
          await _navigationService.navigateTo('/next', args: data);
      if (result) {
        // trueなら更新があったのでウィジェットを再ビルドしなければならない
        notifyListeners();
      }
  }
}
```

`push`を呼んでいる関数を`async`にしています。
`NavigationService#navigateTo`を`await`で待って、結果を受け取ってます。
このクラスは`ChangeNotifier`で、更新があったら再描画させたいため`notifyListeners`を呼んでいます。


これで、[Flutter 画面遷移でデータを渡す](https://qiita.com/kasa_le/items/06797ebbd582f0d171e2)と合わせると、Androidでいう

- Intentで次の画面にデータを投げる
- その画面でデータを書き換える
- 呼び出し元の画面にそのデータを返す

というのと同じことが出来るようになりました。

# 参考サイト

FlutterのNavigatorの使い方と仕組み
https://qiita.com/heavenosk/items/9e43298955a371221393
Ubuntu 20.04にOpenJDK 8(1.8) + HotSpotをインストール（AdoptOpenJDK）

# はじめに

AdoptOpenJDKを利用してUbuntu20.04にOpenJDK8 + HotSpotをインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Installation | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/installation.html)

## サポート

本手法で導入した場合、[Support | AdoptOpenJDK - Open source, prebuilt OpenJDK binaries](https://adoptopenjdk.net/support.html)より、2026-05がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# apt update;apt install -y wget software-properties-common
# wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | apt-key add -
# add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
```

### インストール

```shell-session
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

# apt update; apt install -y adoptopenjdk-8-hotspot
... 略
```

### 各種確認

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

# java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)
```
Ubuntu20.04LTSのブートUSBをMacで作成する

# 目的
Ubuntu20.04LTSのブートUSBをMacで作成する際の備忘録です

#### 2020/4/23 に Ubuntu20.04LTSが公式リリースされました
> [Ubuntu 20.04 Release Date & New Features (Updated)](https://www.omgubuntu.co.uk/2019/10/ubuntu-20-04-release-features)
> Ubuntu 20.04 LTS is released April 23, 2020, succeeding Ubuntu 19.10 as the latest stable release of this hugely popular Linux-based operating system 

# Ubuntu20.04LTSをダウンロード

以下からOSイメージ（ubuntu-20.04-desktop-amd64.iso）をダウンロードします

[日本国内のダウンロードサイト](https://www.ubuntulinux.jp/ubuntu/mirrors)
→Ubuntuのリリースイメージから、http://で始まるミラーサイトへアクセス
 ※ Ubuntuのパッケージアーカイブミラーではなくリリースイメージから選ぶ
→Ubuntu 20.04 LTS (Focal Fossa) 
→64-bit PC (AMD64) desktop image

# USBメモリをフォーマット

OSイメージを書き込むために、USBメモリをFAT32にフォーマット

> [Macでデータ損失なくUSBメモリをFAT32にフォーマットする方法](https://jp.easeus.com/mac-data-recovery/format-usb-flash-drive-to-fat32-on-mac.html)

# OSイメージをUSBメモリへ書き込み

[Ethcer](https://www.balena.io/etcher/)を使い、
ダウンロードしたOSイメージ（ubuntu-20.04-desktop-amd64.iso）を書き込む


> [Ethcer](https://www.balena.io/etcher/)
> [ラズパイ の OS イメージを焼くときは Etcher が 便利 ＆ UI カッコいい](https://azriton.github.io/2017/11/12/ラズパイのOSイメージを焼くときはEtcherが便利＆UIカッコいい/)

# その他

インストールはこれまでの手順と変わらない

> [Ubuntu 18.04 LTSインストールガイド](https://linuxfan.info/ubuntu-18-04-install-guide)

ubuntuだと以下の方法でインストールできるようです

https://remylog.com/ubuntu-20-04-balenaetcher-install/

```
sudo apt update
curl -1sLf 'https://dl.cloudsmith.io/public/balena/etcher/setup.deb.sh' | sudo -E bash
sudo apt update
sudo apt install balena-etcher-electron
```

# 参考
[日本国内のダウンロードサイト](https://www.ubuntulinux.jp/ubuntu/mirrors)
[Ubuntu 20.04 LTS arrives](https://ubuntu.com/blog/ubuntu-20-04-lts-arrives)
[日本国内のダウンロードサイト](https://www.ubuntulinux.jp/ubuntu/mirrors)
[Ubuntu 20.04 LTS (Focal Fossa)](http://ftp.jaist.ac.jp/pub/Linux/ubuntu-releases/focal/)
[Ethcer](https://www.balena.io/etcher/)
[ラズパイ の OS イメージを焼くときは Etcher が 便利 ＆ UI カッコいい](https://azriton.github.io/2017/11/12/ラズパイのOSイメージを焼くときはEtcherが便利＆UIカッコいい/)
[Ubuntu 18.04 LTSインストールガイド](https://linuxfan.info/ubuntu-18-04-install-guide)
[Macでデータ損失なくUSBメモリをFAT32にフォーマットする方法](https://jp.easeus.com/mac-data-recovery/format-usb-flash-drive-to-fat32-on-mac.html)
【CircleCI】MySQLで複数DBを構築する

# 環境

- Circle CI 2.1
- [circleci/mysql:5.7](https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/mysql/images)

# 設定例

```yaml
version: 2.1

executors:
  docker:
    - image: circleci/node:14.15.4-buster
    - image: circleci/mysql:5.7
      environment:
        MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
        MYSQL_DATABASE: first_database_comes_here
:
:
commands:
  set_up_multiple_databases:
    steps:
      - run:
          name: Set up multiple databases
          command: |
            sudo apt-get update
            sudo apt-get install default-mysql-client
            mysql -u root -e "CREATE DATABASE IF NOT EXISTS second_database_comes_here" --protocol=tcp
```

# 参考URL

https://discuss.circleci.com/t/how-can-i-create-multiple-mysql-databases-in-the-same-docker-image/24762

# リンク

- [ローカルのDockerで複数databaseを設定する例](https://qiita.com/luigiii/items/2096258dc45a6bbe2a19)
UIとは、、？

# 背景
いつも分からないことを調べている時に、「UI」という言葉をたくさん目にすることがあり意味が分からないがなんとなくで調べていなかった。
あまりにもたくさん出てくるので流石に大事な言葉なのだと思い調べてみました。。

## UIとは
UIとは、ユーザーインターフェイス（User Interface）の略です。
簡単に言うと「ユーザーに見える（使用する）部分」のことです。
似たもので、UXと言うものもあります。

## UXとは
UXとは、ユーザーエクスペリエンス（User Experience）の略です。
UXとは「ユーザーが製品・サービスを通じて得られる体験」のことです。


## 参考
UIとは？UXとは？違いを理解しよう！
https://ferret-plus.com/655
Excelの列番号(1, 2, 3, ...)を列文字(A, B, C, ...)に変換する関数

マクロの処理の中でも使えるし、ワークシート関数としても使えます。

列番号 ⇒ 列文字
 1 ⇒ A
26 ⇒ Z
27 ⇒ AA
52 ⇒ AZ
52 ⇒ BA



```vb:ColumnLetter.bas

Function ColumnLetter(ColumnNumber As Long)

    Dim q As Long
    Dim r As Long
    Dim s As String

    If ColumnNumber <= 0 Then
        ColumnLetter = CVErr(xlErrValue)
        Exit Function
    End If

    q = Int((ColumnNumber - 1) / 26)
    r = (ColumnNumber - 1) Mod 26

    If q > 0 Then
        s = ColumnLetter(q)
    End If

    ColumnLetter = s & Chr(65 + r)

End Function

```

参考：[Excel の列番号を英文字に変換する方法](https://docs.microsoft.com/ja-jp/office/troubleshoot/excel/convert-excel-column-numbers)