OmniAICreator/Qiita-1.07M huggingface dataset:
OpenCVとPILでアクリルバッジの型枠画像を作成する

## 概要

こんな画像から
![side.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/a869d441-1bef-11ae-6acd-fba5aa194129.png)
出典：[フォクすけの画像](https://foxkeh.jp/downloads/materials/)

こんな画像を作成します。
![ret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/d8990a15-a2e2-3559-98f4-bd2e244ea65c.png)
画像は透過PNGであることが前提です。

## コード
```Python
import numpy as np
import cv2
from PIL import Image, ImageFilter

# 上下左右に縁取りを追加
def add_border(img, size):
    border_h = np.zeros((size, img.shape[1], img.shape[2]), dtype=np.uint8)
    border_v = np.zeros((img.shape[0] + 2*size, size, img.shape[2]), dtype=np.uint8)

    img2 = np.vstack([border_h, img, border_h])
    img2 = np.hstack([border_v, img2, border_v])

    return img2


# 輪郭をなめらかに膨張
# img  : 中身が白、背景が黒のグレースケール画像
# size : 膨張サイズ[pix]
def inflate(img, size):

    # 円形（なめらか）に膨張
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (size,size))
    img2 = cv2.morphologyEx(img, cv2.MORPH_DILATE, kernel)
    #cv2.imwrite('morph.png', img2)

    # モード（最頻）フィルターを適用
    img2 = Image.fromarray(img2) # cv -> PIL
    img2 = img2.filter(ImageFilter.ModeFilter(size))
    img2 = np.array(img2, dtype=np.uint8) # PIL -> cv
    #cv2.imwrite('mode.png', img2)

    # 外接する輪郭を取得して内部を塗りつぶす
    contours, hierarchy = cv2.findContours(img2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    img2 = cv2.drawContours(img, contours, -1, (255,255,255), thickness=cv2.FILLED)

    return img2


size = 50 # 膨張サイズ
img = cv2.imread('side.png', cv2.IMREAD_UNCHANGED) # 透過情報もそのまま読み込む

# 上下左右に縁取りを追加
img = add_border(img, size)

# 透過画像から中身が白、背景が黒のグレースケール画像を作成
img_gray = img.copy()
th = img_gray[:,:,3] >= 127
img_gray[th] = (255,255,255,255)
img_gray[np.logical_not(th)] = (0,0,0,0)
img_gray = img_gray[:,:,0:3]
img_gray = cv2.cvtColor(img_gray, cv2.COLOR_BGR2GRAY)
#cv2.imwrite('gray.png', img_gray)

# 輪郭画像を作成
img_inf = inflate(img_gray, size)
img_inf = cv2.cvtColor(img_inf, cv2.COLOR_GRAY2BGR)

# 元画像を透過情報を維持しつつ合成
img_ret = img_inf[:,:] * (1 - img[:,:,3:] / 255) + img[:,:,:3] * (img[:,:,3:] / 255)
cv2.imwrite('ret.png', img_ret)
```

## コード解説

まずは元の画像から、中身が白で背景が黒の２値画像を作成します。
![gray.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/70a2a907-0da2-8f8f-62f5-7e9a9731bf0b.png)

次に`cv2.morphologyEx`で周囲が円形になるように画像を膨張させます。
![morph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/8a9b5e26-1a14-22e9-3415-36f655a14889.png)
ただ、そのまま膨張させると凹部分が鋭角のままになってしまいます。
そこでPILの`ModeFilter`という最頻値をとるフィルターをかけます。
![mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/bb28afbe-526f-7387-20cb-aa3cab5af16b.png)
凹部分もうまくなめらかになりました。
あとは`cv2.findContours`で外接する輪郭を取得して内側を白で塗りつぶします。
これはドーナツのように内側に穴のあるような画像を考慮しての後処理になります。

最後に元の画像と合成して完成です。
![ret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/4a66f7e7-7c7f-caff-9a23-b113298756bf.png)

## その他
わりといいかんじにできました。
元ネタ：[画像輪郭のなめらか処理の方法](https://teratail.com/questions/glod0xjc398xr7)
fedora36でpyenvでのインストールがFailedするのをなおす

## エラー内容

fedora36にて

```sh
pyenv install 3.8.13
```

を実行し、python3.8.13をインストールしようとしたら

```
Downloading Python-3.8.13.tar.xz...
-> https://www.python.org/ftp/python/3.8.13/Python-3.8.13.tar.xz
Installing Python-3.8.13...
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
WARNING: The Python curses extension was not compiled. Missing the ncurses lib?
WARNING: The Python ctypes extension was not compiled. Missing the libffi lib?
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

Please consult to the Wiki page to fix the problem.
https://github.com/pyenv/pyenv/wiki/Common-build-problems


BUILD FAILED (Fedora Linux 36 using python-build 20180424)

Inspect or clean up the working tree at /tmp/python-build.20220918205119.66482
Results logged to /tmp/python-build.20220918205119.66482.log

Last 10 log lines:
	 ./python -E -m ensurepip \
		$ensurepip --root=/ ; \
fi
Looking in links: /tmp/tmpkvcgm8zh
Processing /tmp/tmpkvcgm8zh/setuptools-56.0.0-py3-none-any.whl
Processing /tmp/tmpkvcgm8zh/pip-22.0.4-py3-none-any.whl
Installing collected packages: setuptools, pip
  WARNING: The scripts pip3 and pip3.8 are installed in '/home/***/.pyenv/versions/3.8.13/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-22.0.4 setuptools-56.0.0
```
となってBUILD FAILEDとなった。

## 解決策

### openssl1.1-develをインストール

https://fedora.pkgs.org/36/fedora-x86_64/openssl1.1-devel-1.1.1n-1.fc36.x86_64.rpm.html

↑から`openssl1.1-devel`のrpmパッケージをローカルにダウンロードして
（[ダウンロードリンク](https://download-ib01.fedoraproject.org/pub/fedora/linux/releases/36/Everything/x86_64/os/Packages/o/openssl1.1-devel-1.1.1n-1.fc36.x86_64.rpm)）
```sh
sudo dnf -y localinstall ./openssl1.1-devel-1.1.1n-1.fc36.x86_64.rpm
```
を実行することで`openssl1.1-devel`をインストール。

### `pyenv install`を再実行
```
pyenv install インストールしたバージョン
```

### 参考

エラー情報に
https://github.com/pyenv/pyenv/wiki/Common-build-problems
を参照しろとのガイドがありました。

ただ、↑のwikiには
```sh
sudo yum install openssl11-devel --allowerasing
```
で`openssl11-devel`をインストールすることが書かれていたものの、Fedora36で実行すると
```
No match for argument: openssl11-devel
Error: Unable to find a match: openssl11-devel
```
となるので、RPMパッケージをローカルにダウンロードすることで解決しました。
色の塗り分け問題をアルゴリズムで解いてみる

## はじめに

身近なもので何かないかなと考えていたのですが、昔やった色塗り問題を思い出しました。例えば下のように3マスあって、3色で色を塗り分けた場合、塗り方が何通りあるかです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/22dacff6-5637-a8f4-3899-a56e3a8d44ef.png)

マスを区別するので全体は3×3×3=27通りです。この時、隣同士で色が重複しない塗り方は何通りあるか考えてみましょう。
・・・正直アルゴリズム使わなくても、ごり押しで求められます(★の部分で12通り)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/5cb97427-a171-4420-a942-8bce4061157d.png)

でもせっかくなので、アルゴリズムを使って考えてみることにしました。

## アルゴリズム的な何かを書いてみる

```python
import itertools

#重複を許して3種類の組み合わせを作成(赤：0　黄：1　青：2)
comb = itertools.product(range(3), repeat=3) 
l_comb = list(comb) #リスト化

result = []

#組み合わせの1番目と2番目、もしくは2番目と3番目が同じ場合は削除
for i in range(len(l_comb)):
    if l_comb[i][0] == l_comb[i][1] or l_comb[i][1] == l_comb[i][2]:
        continue
    else:
        result.append(l_comb[i])

#得られた組み合わせとその数を表示
print(result)
print(len(result)) 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/e5a86be1-dba4-1956-cdf9-5fa76c8732be.png)

まず組み合わせを作成しています。そこから1番目-2番目もしくは2番目-3番目の値が被っていないものだけを、新しいリストに入れて作りました。
ちゃんと12個作成されたことがわかります。

## まとめ
アルゴリズムってその道のプロじゃないと書けないかなと思っていたのですが、素人でもやりようによっては作れることがわかってよかったです。

## 参考
https://hibiki-press.tech/python/itertools/1796
https://docs.python.org/ja/3/library/itertools.html#itertools.product
LINUXのhistoryコマンド、初期設定で日時が分かるようにして欲しいですね

# 問題点
初期設定の`history`コマンドでは、いつコマンドが入力されたかが分からない。
# 特に参考になったサイト
https://linuxfan.info/add-datetime-to-history
# 解決
以下のコマンドを入力すると、各コマンドの入力日時が表示されるようになる。
```
export HISTTIMEFORMAT='%F %T '
```
ただしこれだと上記コマンド以前の入力コマンドの日付は全て、上記コマンド入力時点になってしまう。

そこで毎回自動的にこのコマンドが実行されるように、
環境作成時に、まずはこれを初めにやった方がいい。
```
$ echo "export HISTTIMEFORMAT='%F %T '" >> ~/.bashrc
```
```/home/USERNAME/.bashrc
# .bashrc
.
.
.
export HISTTIMEFORMAT='%F %T '
```

というかそもそも、
history表示は絶対初めからに日時が分かった方がいいと思うのだが・・・
RockyLinux8 vps環境設定10) /tmpフォルダのファイルの削除処理の変更

RockyLinux8 vps環境設定9) サーバ再起動時の設定
https://qiita.com/naga_kt/items/11026238e56b134e93ad
の続き。WebArena Indigo(RockyLinux8.4)及びKagoya(RockyLinux8.5)での環境設定について述べる。

## systemd-tmpfilesの設定変更

 /tmpに作成したファイルが時々削除されていることに気付いた。これはCentOS7以降の仕様とのこと（参考記事参照）。

　systemd-tmpfilesが/tmp以下のファイルの削除を行う。/tmp削除の設定は/usr/lib/tmpfiles.d/tmp.confに記述されている。

~~~linux
$ cat /usr/lib/tmpfiles.d/tmp.conf
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# See tmpfiles.d(5) for details

# Clear tmp directories separately, to make them easier to override
q /tmp 1777 root root 10d
q /var/tmp 1777 root root 30d

# Exclude namespace mountpoints created with PrivateTmp=yes
x /tmp/systemd-private-%b-*
X /tmp/systemd-private-%b-*/tmp
x /var/tmp/systemd-private-%b-*
X /var/tmp/systemd-private-%b-*/tmp

# Remove top-level private temporary directories on each boot
R! /tmp/systemd-private-*
R! /var/tmp/systemd-private-*
~~~

　上記にあるように/tmp以下のファイルが10日（10d）経ったら削除されるように設定されている。mtime(最終変更時間)、atime(最終アクセス時間)、ctime(最終属性変更時間)の全ての時間が削除までの期間を超過した時にファイルが削除される。

　設定を変更するためには、上記のファイルを/etc/tmpfiles.dにコピーして、設定を追加する。/etc/tmpfiles.d/での設定は、/usr/lib/tmpfiles.d/の設定より優先される。
　以下のように行った。

~~~linux
# cp -p /usr/lib/tmpfiles.d/tmp.conf /etc/tmpfiles.d/
# vi /etc/tmpfiles.d/tmp.conf
~~~

　ファイルに以下を追記した。
~~~linux
X /tmp/xxxxx
~~~

　systemd-tmpfilesの挙動の確認は、以下のようにするとデバッグログが吐き出されて、削除しなかった理由が述べられる。

~~~linux
$ SYSTEMD_LOG_TARGET=console SYSTEMD_LOG_LEVEL=debug /usr/bin/systemd-tmpfiles --clean

Running clean action for entry X /tmp/xxxxx
~~~


---

RockyLinux8 vps環境設定11) 権限の最終的な設定
https://qiita.com/naga_kt/items/6c42e031751876f36c97
に続く。

---

### 参考記事

お前らもさっさとハマって泣くべきCentOS7の落とし穴4つ
https://qiita.com/suemoc/items/e29285e8e67263298f35

tmpwatch（CentOS6まで）とsystemd-tmpfiles（CentOS7）の挙動の違い
https://qiita.com/kuroneko9/items/70a102a7bb1aa53661a2

【CentOS】/tmp配下のファイルが消える理由
https://densan-hoshigumi.com/server/tmp-file-disappearance

【systemd-tmpfiles】CentOS8でディレクトリ内のファイルを定期的に消す方法
https://mikemikeblog.com/how-to-use-systemd-tmpfiles-with-centos8/

tmpfiles.d(5) [centos man page]
https://www.unix.com/man-page/centos/5/tmpfiles.d/
デザインパターン Iterator(typescript) 

 Iterator パターンは、要素の集まりを保有するオブジェクトの各要素に順番にアクセスする方法を提供するためのパターン


 何らかの集約体が必ずAggregate インタフェースを実装する
Aggregate とは、集約を意味する単語で、Aggregate インタフェースでは Iterator インタフェースの実装クラスを返す、iterator() というメソッドを定義している
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2193053/271eaed3-d01b-da0e-a9c5-d857c7dba67d.png)



```typescript
interface Aggregate {
    itereter(): Itereter
}

interface Itereter {
    hasNext(): boolean;
    next(): Object;
}

class Student {
    name: string;
    sex: number; //male:1 female:2

    constructor(name: string, sex: number) {
        this.name = name;
        this.sex = sex;
    }

    getName() {
        return this.name;
    }

    getSex() {
        return this.sex
    }
}

class StudentList implements Aggregate{
    last: number = 0;
    students: Student[];

    constructor() {
        this.students = [];
    }

    public getStudentAt(last: number): Student {
        return this.students[last];
    }

get getLength() {
        return this.last
    }

    public add(student: Student): void {
        this.students[this.last] = student;
        this.last++;
    }

    public itereter(): Itereter {
        return new MyStudentIterator(this)
    }
}



class MyStudentIterator implements Itereter {
    index: number
    myStudentList: StudentList

    constructor(list: StudentList) {
        this.index = 0;
        this.myStudentList = list
    }

    hasNext(): boolean {
        if (this.index < this.myStudentList.getLength) {
            return true
        }
        else {
            return false;
        };
    };

    next(): Object {
        const s = this.myStudentList.getStudentAt(this.index);
        this.index++;
        return s
    }
}


function Main() {
    const myStudentList: StudentList = new StudentList()
    myStudentList.add(new Student('yuki', 1))
    myStudentList.add(new Student('aya', 2))

    const it = myStudentList.itereter()
    while(it.hasNext()){
        console.log(it.next())
    }
}

Main()
```

## 参考文献
* [TECHSCORE](https://www.techscore.com/tech/DesignPattern/Iterator/Iterator2)
VSCodeでprettierがどうしても動かない問題を解決する

 
「prettier 動かない」で検索して、いろんな記事を漁って試してみても解決しませんでした。

確認した項目
*　Editor:Format On Save
*　Editor:Default Formatter
*　disableLanguage

# 取り敢えず、setting.jsonへ　　
コマンドパレット ( Ctrl/Cmd + Shift + P ) から、 Open Settings (JSON) という項目を選択することで、 settings.json ファイルを直接開いてみます。
![スクリーンショット 2022-09-18 21.02.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729078/570ead87-7b95-c68d-51c8-2fd7dd1cefbe.png)![スクリーンショット 2022-09-18 20.52.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729078/7c79c992-455f-d19a-ed26-09824d71e08f.png)

editor.formatOnPasteはtrueになってる、editor.formatOnSaveもtrueになってる、んん、なんだこの3行目のパスは？？
```setting.json
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"prettier.prettierPath": "/Users/matsunakahikaru/.vscode/extensions/esbenp.prettier-vscode-8.0.1",
```

vscodeの拡張機能として、prettierを入れておいたつもりが、なんか変なパスを読んでしまっている。。
![スクリーンショット 2022-09-18 20.53.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729078/a964be0a-8f02-04fb-7aa1-264676fe66d2.png)　　
この行をコメントアウトしたら、使えるようになりました！

# まとめ
prettierが動かなくなった時は、取り敢えずsetting.jsonを見に行くのが良さそうです。めっちゃ雑な結論ですけど。
東北大学Quantum computing for you (QC4U) の解説コードをCirqに移植してみる

[2022/10/9 更新]
第4回分のCirq翻訳を完了しました。残すところ第5回分のみ。
第3回目に扱った手法をベースに、第4回はQAOAまで踏み込んだ内容となっています。

---
東北大学 大関教授による[QC4U](https://altema.is.tohoku.ac.jp/QC4U/)の解説コードの理解を深めるために[Qiskit](https://qiskit.org/)コードを写経をしているうちに、前から気になってた[Cirq](https://quantumai.google/cirq)への翻訳(移植)も同時にチャレンジしてしちゃおうと思い立って、まずはやってみました。

両方を見比べることで、それぞれの特徴や、使い方の向き不向きみたいなのも今後掴めてくれば良いなと思います。
今のところ、Qiskitは日本語のドキュメントやコンテンツが充実していて学びやすいことと、一方でCirqはTensorflowなど機械学習との組み合わせをしていったときに親和性が高いのかなと感じてます。

以下、Github(Google Colab Notebook)へのリンクと初回分の冒頭の抜粋です。

* [QC4U 第1回 Cirq写経翻訳](
https://github.com/yoshihiroo/programming-workshop/blob/master/QC4U_2022/qc4uchapter1_cirq_Japanese.ipynb)
* [QC4U 第2回 Cirq写経翻訳](https://github.com/yoshihiroo/programming-workshop/blob/master/QC4U_2022/qc4uchapter2_cirq_Japanese.ipynb)
* [QC4U 第3回 Cirq写経翻訳](https://github.com/yoshihiroo/programming-workshop/blob/master/QC4U_2022/qc4uchapter3_cirq_Japanese.ipynb)
* [QC4U 第4回 Cirq写経翻訳](https://github.com/yoshihiroo/programming-workshop/blob/master/QC4U_2022/qc4uchapter4_cirq_Japanese.ipynb)


>QC4U 第1回 Cirq写経翻訳
>2022.9.18版
>
>東北大学 大関先生によるQC4Uの解説コードをもとに、理解を深めるためにCirqへの翻訳をやってみているものです。Cirq初心者ですので、正しくないコードの書き方や理解が間違っているところがあるかも知れませんがご容赦ください。（掲載については大関先生の了解を得ております。ご承諾ありがとうございます。）
VBA : セルに記載したパスをエクスプローラで開く

最近、PowerQueryの処理の関係上、同じフォルダに保存した大量のエクセルファイルを連結していく状況が多いのですが、連結後のデータを確認した際に、ノイズが入っている場合は、元のフォルダに戻って該当ファイルを確認、ノイズを補正するような手動によるデータクレンジングする状況が増えてきました。

このため、PowerQueryで参照するフォルダ名を書いておいて、そのフォルダをエクスプローラで開くマクロの使用頻度が秒で増えており、特に今年に入ってからは大人気です。

## VBAコード
下記VBAコードを標準モジュールの中に仕込みます。
```vb:標準モジュール内
' in mUtils module
Option Explicit

Public Sub openWithExplorer()

    Dim row as Integer
    Dim col as Integer

    ' フォルダのパスが書いてあるセルの参照となる情報は、
    ' 各自の環境に置き換えてください。
    row = 3 
    col = 2
    Shell "C:\Windows\explorer.exe " & Sheet1.Cells(Row, Col), vbNormalFocus
End Sub
```

下記はシートのオブジェクト名を wsCONFとしたうえで、3行目、2列目にある場合のマクロの画像です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41223/649e1edb-863e-66fa-a34e-5ed8a2af89d0.png)

それこそ秒で仕込めるので覚えておいて損はないです。
RockyLinux8 vps環境設定8) ファイアウォールのポート設定

RockyLinux8 vps環境設定7) コマンドのインストール
https://qiita.com/naga_kt/items/50c50e298946d5acf558
の続き。WebArena Indigo(RockyLinux8.4)及びKagoya(RockyLinux8.5)での環境設定について述べる。

　ここまでの設定でWebArena Indigoのvpsはhttpdの設定でSELinuxを無効化したので、そのままでは不安がある。
　Kagoyaのvpsではファイアウォールの設定がされているので使用するポート番号を開ける設定をしないといけない。

　ここではファイアウォールのポート設定について述べる。

## コントロールパネルからのファイアウォールのポート設定【WebArena Indigo(RockyLinux8.4)の場合】

　WebAreana Indigoの場合はコントロールパネルからポートの設定を行う。
　「ネットワーク管理」－「ファイアーウォール」－「＋ファイアウォールの作成」をクリックすると、「ファイアウォールの作成」画面が開く。「ファイアウォール名」を入力する。
　「インバウンドルール」で「新規ルール」をクリックして「Custom」を選択する。「プロトコール」に「TCP」、ポートに開けたいポート番号、連番の時はハイフンでつないだもの例えば「12345-54321」を、IPアドレスに「0.0.0.0」を入力する。
　「新規ルール」をクリックして「Custom」を選択する。「プロトコール」に「TCP」、ポートにssh接続で用いる番号、IPアドレスに「0.0.0.0」を入力する。
　「新規ルール」をクリックして「HTTP」を選択する。IPアドレスに「0.0.0.0」を入力する。
「インスタンスの適用」にそのルールを適用したいインスタンスを選択して「更新」をクリックする。

## firewall-cmdコマンドでのファイアウォールのポート設定【Kagoya(RockyLinux8.5)の場合】

　Kagoyaの場合はfirewall-cmdコマンドでのファイアウォールのポート設定を行う。
　設定を確認すると、先にssh接続のために設定した番号だけが設定されている。

~~~linux
$ sudo firewall-cmd --list-ports --zone=public
zzzzz/tcp
~~~

　以下のようにして例えば12345番から54321番までのポート番号を追加設定できる。

~~~linux
$ sudo firewall-cmd --add-port=12345-54321/tcp --zone=public --permanent
success
$ sudo firewall-cmd --reload
success
$ sudo firewall-cmd --list-ports --zone=public
12345-54321/tcp zzzzz/tcp
~~~

---

RockyLinux8 vps環境設定9) サーバ再起動時の設定
https://qiita.com/naga_kt/items/11026238e56b134e93ad
へ続く。

---

### 参考記事

ファイアウォールの設定方法を知りたい（Indigo）
https://help.arena.ne.jp/hc/ja/articles/360048915573-%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95%E3%82%92%E7%9F%A5%E3%82%8A%E3%81%9F%E3%81%84-Indigo-

[Linux] firewalldでfirewallの設定をする
https://qiita.com/suzutsuki0220/items/4a62cc0e676a80ed79f1
ソリューションアーキテクト対策_ElactiCache篇

## はじめに
試験勉強した際のメモを自分用に記事化。
内容は公式やBlack Beltの写経ですので目新しいことはありません:pray:

## ElastiCacheのMemchashedとRedisの違い
### Memchached
・マルチスレッドで動作する
・CPUのコア数を上げるとパフォーマンスも上がる
・キーとバリューをシンプルな1：1で組み合わせて保存する

シンプルでメモリの使用効率というパフォーマンスの観点で優れている。

### Redis
・シングルスレッドで動作する
・snapshotベースでのバックアップ、リストアに対応
・マスターと複数のスレーブのクラスター構成により、負荷分散が可能
・クラスターモードについては、有効/無効を選ぶことができる

メモリ上のデータをディスクに保存することで、データを消失せずに済む。
Memchashedに比べて、pub/sub機能があったり、自動的なフェイルオーバーができたり、キーストアの永続性が必要であったりと、バックアップと復元性に優れている。

## おわりに
Elastic系使ったことが無いので難しい…！
引き続き追記します。

簡単ですが以上です。
親子関係のあるFragment間でactivityViewModelsを使わずにviewModelsを使ってViewModelを共有する

[Googleの公式ドキュメント](https://developer.android.google.cn/guide/fragments/communicate?hl=ja#viewmodel)では、`activityViewModels`を使ってFragment間でViewModelを共有する方法が紹介されています。しかし、どうにか`viewModels`だけで済ませられないかと思い、**親子関係のあるFragment間**であれば実現できそうなので紹介します。

## 実装

早速見ていきましょう。ここでは子のDialogFragmentを親のFragmentで生成して呼び出す場合を想定しています。

### 親Fragment

ViewModelの生成には`viewModels`を使います。子Fragmentを生成する際には`childFragmentManager`を渡してあげます。

```kotlin:ParentFragment.kt
class ParentFragment : Fragment() {
    val shareViewModel by viewModels<SampleShareViewModel>()

    private fun showDialog() {
        ChildDialogFragment().show(childFragmentManager, "Tag")
    }
}
```

### 子Fragment

こちらも`viewModels`を用いてViewModelを生成します。子Fragmentでは、`viewModels`の引数`ownerProducer`に「`requireParentFragment()`を返す関数」を指定することがポイントになります。

```kotlin:ChildDialogFragment.kt
class ChildDialogFragment : DialogFragment() {
    val shareViewModel by viewModels<SampleShareViewModel>(
        // 今回のポイントとなる部分
        ownerProducer = {
            requireParentFragment()
        }
    )
}
```

## 利用例

- DialogFragment
- ViewPager
- その他いろいろ

## 終わりに

コメントや質問指摘など随時歓迎しています。

## 参考にしたサイト

- [Android share ViewModel between fragment and dialog fragment? - Stack Overflow](https://stackoverflow.com/questions/63225618/android-share-viewmodel-between-fragment-and-dialog-fragment)
- [viewModels - Android Developers](https://developer.android.com/reference/kotlin/androidx/fragment/app/package-summary#(androidx.fragment.app.Fragment).viewModels(kotlin.Function0,kotlin.Function0,kotlin.Function0))
DOSBox-XでMASM

# DOSBox-XでMASMを実行する
この記事ではDOSBox-Xを用いてMASMを実行する方法についてご紹介します。

・Windowsの場合
[DODBox-Xのダウンロードページ](https://dosbox-x.com)から、setup.exeをダウンロードしましょう。
インストール手順は画面に沿って進めるだけなので割愛します。

・Linuxの場合
[snapコマンドでインストール](https://snapcraft.io/dosbox-x)で、お使いのディストリビューションを選択し、適切なコマンドを入力してください。
Ubuntuの場合であれば、
$```sudo apt update```
$```sudo apt install snapd```
$```sudo snap install dosbox-x```
という３つのコマンドをターミナルで入力し、
```dosbox-x```と入力することでアプリケーションが起動します。
# MASMのダウンロード
私が管理しているレンタルサーバーにアセンブラやリンケージエディタなどを準備しているので、それを使いましょう。
[私のサーバー](http://ikuchankai.html.xdomain.jp/MASM/Assembler.html)からダウンロードしてください。
ダウンロードしたzipファイルを展開してできた「MP」というディレクトリをC:（Linuxの場合home）直下に保存します。
MPというディレクトリが２つできるかと思いますが、EXEファイル等が保存されている方をC:に移動させてください。
これで準備完了です。
# Hello World!を出力する
DOSBox-Xを起動してください。
画面が開いて文字入力ができる状態になりましたら、
Windowsの場合
```mount c c:/MP```
Linuxの場合
```mount c /home/MP```
を入力してください。

```ｃ:```
と入力して、C:へ移動します。

私が公開しているMPというディレクトリには最初からHW.ASMというアセンブリファイルが保存されています。
中身を確認してみましょう。
```edit HW.ASM```
を入力すると、コードが表示されます。
そのコードがMASMでHello World！を表示する内容になっています。
本来であれば、そのファイルを
```masm HW.ASM```
と入力しアセンブルし、続いて
```link HW.OBJ```
と入力しリンクすることによってEXEファイルを作ることができます。
しかし、今回準備したMPというディレクトリにはもとから「HW.ASM」「HW.OBJ」「HW.EXE」という３つのファイルが用意されているため、皆さんは
```HW.EXE```
と入力するだけでHello World!が画面に出力されると思います。

これでDOSBox-Xを用いてMASMでHello World!を出力することができました！
この記事を参考にしてMASMの勉強を頑張ってください。
【背伸び初心者授業③】returnの小技！if文内の条件をreturnする

いつもどんな内容をreturnしていますか？
return $user;
return "登録しました";
このように、何かしらの「結果」を返していることが多いと思います。


以下は、お皿の数が足りているか確認する関数です。
```php
$plateNum = '9';
echo answerFromIdo($plateNum);

function answerFromIdo($plateNum)
{
    if($plateNum < 10){
        $less = 10 - $plateNum;
        return $less . "枚足りなぃぃい！";
    } else {
        return "足りてる。";
    }
}

// 出力結果
1枚足りなぃぃい！
```
なるほど、1枚足りないようです。


if文の中で一度 "$plateNumが10枚より少ないか" を確認していますね。
今回は10枚でしたが、次回は11枚数えないといけなくなるかもしれません。
枚数が変わっても対応できるようにしましょう。

今回の小技はこのif文内を関数にすることです。
## 本題 : if文内の条件をreturnする
"用意したお皿が$num枚より少ないかどうか"を関数にしてみると以下のようになります。

```php
function checkLessThanNum($plateNum, $needPlateNum)
{
    return $plateNum < $needPlateNum;
}
```
この関数を使用して、再度コーディングしてみます。
```php
$plateNum = '10';
$needPlateNum = '8';
echo answerFromIdo($plateNum, $needPlateNum);

function answerFromIdo($plateNum, $needPlateNum)
{
    if(checkLessThanNum($plateNum, $needPlateNum)){
        $less = $needPlateNum - $plateNum;
        return $less . "枚足りなぃぃい！";
    } else {
        return "足りてる。";
    }
}

function checkLessThanNum($plateNum, $needPlateNum)
{
    return $plateNum < $needPlateNum;
}
// 出力結果
足りてる。
```
足りているようで安心しました。これで井戸も当分静かでしょう！

if文内の条件をreturnすることで、どのような条件のif文なのか把握することができますね！
私は英語が苦手なので、どのような状況か見当もつかなくなりそうですが
他の人がわかるのならばこれでよしとしましょう！
ここまで読んでいただいてありがとうございました！
アフィン変換・射影変換の処理時間比較

## １．はじめに

Open CVを使って画像を回転させるとき、  
・アフィン変換  
　dst_img = cv2.warpAffine(src_img, Mat, (width, height))  
・射影変換  
　dst_img = cv2.warpPerspective(src_img, Mat, (width, height))  
という、よく似た2通りのやり方がある。  
（実は他にもあるかもしれないが、筆者は知らない）  

形の上での違いは、アフィン変換は変換行列が2×3であるのに対して、射影変換は3×3であること。  
これは、アフィン変換行列を求める  
　Mat = getAffineTransform(src_points, dst_points)   
が3点→3点の対応であるのに対し、射影変換の変換行列を求める  
　Mat = getPerspectiveTransform(src_points, dst_points)  
が4点→4点の対応であることと符合する。
  
厳密性を犠牲にすれば、  
・アフィン変換は矩形を平行四辺形に移す変換（あるいはその逆）  
・射影変換は矩形を任意の四角形に移す変換（あるいはその逆）  
と考えれば感覚的に理解できる。
  
単なる回転を考える場合はどちらでも構わないように思うが、どちらの処理が速いか、実際に処理時間を測定して調べてみる。

## ２．実装
### 2.1　準備


```python
import cv2
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
```


```python
# OpenCVの画像を画面表示する関数
def show_img_cv2(img_cv2):
    img_RGB = cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB)
    plt.imshow(img_RGB)
```


```python
# 処理の対象となる画像をread
img = cv2.imread('img/lenna.png')
h, w = img.shape[:2]
print(f'heit: {h}  width: {w}')
show_img_cv2(img)
```

    heit: 512  width: 512



 ![lenna.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352630/5e107fc8-7bd8-dba1-ec77-85279c10eb46.png)

    


### 2.2　アフィン変換：cv2.warpAffine()を使って画像を回転


```python
mat1 = cv2.getRotationMatrix2D((300, 200), 10, 1)
print('アフィン行列：')
print(mat1)
rotated_img1 = cv2.warpAffine(img, mat1, (w, h))
cv2.imwrite('affine_img.png', rotated_img1)
show_img_cv2(rotated_img1)
```

    アフィン行列：
    [[  0.98480775   0.17364818 -30.17196144]
     [ -0.17364818   0.98480775  55.1329027 ]]

![affine_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352630/ec0b636d-0f79-0448-03c9-7445f4ecf867.png)
  

    


### 2.3　射影変換：cv2.warpPerspective()を使って画像を回転


```python
mat2 = np.concatenate([mat1, np.array([[0, 0, 1]])], 0)
print('射影変換行列：')
print(mat2)
rotated_img2 = cv2.warpPerspective(img, mat2, (w, h))
cv2.imwrite('perspected_img.png', rotated_img2)
show_img_cv2(rotated_img2)
```

    射影変換行列：
    [[  0.98480775   0.17364818 -30.17196144]
     [ -0.17364818   0.98480775  55.1329027 ]
     [  0.           0.           1.        ]]


   
![perspected_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352630/96d4ced3-b7fd-c2e1-200c-e1e46f21dfe4.png)
    


#### アフィン変換、射影変換で、同じ回転画像が得られた。

### 2.4　処理時間の比較
timeitモジュールを使って、10000回ずつ処理を繰り返した際の平均処理時間を求める


```python
import timeit
loop = 10000
result1 = timeit.timeit(lambda: cv2.warpAffine(img, mat1, (w, h)), number=loop)
print(f'warpAffine : {result1 / loop}')

result2 = timeit.timeit(lambda: cv2.warpPerspective(img, mat2, (w, h)), number=loop)
print(f'warpPerspective : {result2 / loop}')

```

    warpAffine : 0.0010326173099980225
    warpPerspective : 0.0012882464599970262


## ３．結論
#### warpPerspective()はwarpAffine()に比べると少し遅い
リーダブルコードまとめ(第1章:理解しやすいコード)

# 目的
こちらの記事を投稿しようと考えた目的は、2点あります。
1つ目は、チーム開発する上で他の人のことを考えてコードを書く必要があることを再認識したから。
2つ目は、今後新たに開発に加わるメンバーのために読みやすいコードを書き、コードを読むコストを減らしたいから。

以上のことから、新米iOSエンジニアの僕がリーダブルコードを読んで各章を簡潔にまとめて不定期でアップしていきます。

# 第1章:理解しやすいコード
## 概要
理解しやすいコードに関する根本的な考え方を解説していて、5ページほどで本書を読む上で大事な概念を説明してくれている印象でした。

### まとめ
・コードは理解しやすくあるべき、かつ他の人が読んでも最短時間で理解できるように書かなければならない。
・コードは、短い方がいいがその「短い方がいい」という本質的な意味は、コードを理解する時間が「短い方がいい」という意味で、単に記述されたコードの長さが「短い方がいい」ということではない。
・「このコードは理解しやすいだろうか」と自問自答して開発に挑むべき。

### 学んだ点
・読みやすいコードを書くための根本的な考えは、「コードは理解しやすくなくてはならない」ということ
・コードに「簡潔」を求めるのか「安心」を求めるのかを考え直す必要がある。すなわち、コードは、「安心」して読む事ができるものであるべきで、必ずしもコードが「簡潔」であれば読みやすいとは限らないことの理解がまずは必要。短くても理解しにくければ意味がないこと

### 感想と振り返り
第1章で大事だと感じたことは、「個人開発では深く考えなくてもよかったことでも、チーム開発では考慮する点が多い」ということ。ここから業務に活かせるなと感じたことは、「このコードは誰から読んでも同じように理解できるか」ということを考えてコードを書くことです。最近、先輩にレビューしていただいているが、レビューするにも時間をもらっているので負担のないように最低限考慮してプルリクしないといけないと感じました。
ビギナーの今の時点で、この考えを植え付けておけて良かったです。
引き続き、リーダブルコードを読みつつ、開発関連の学習も行っていきます！
clang で C++ コードの stack size をチェックするメモ

C/C++ コードで(真の) stack overflow が出る...
再帰関数の呼び出しが深かったり, local variable が領域取っているのがたぶん原因ネ...

どこで stack を食っているのか調べます.

# stack-usage

gcc には `-fstack-usage` があります.

https://devlights.hatenablog.com/entry/2020/10/05/201142
https://syohex.hatenablog.com/entry/20110319/1300541703

clang も 12 以降あたりから使えるようです(11 では NG. 14 では OK).


## 実例

TinyUSDZ で再帰する関数で 103 KB も! 食っていました.

```
tinyusdz/src/usdc-reader.cc:1344:_ZN8tinyusdz4usdc10USDCReader4Impl26ReconstructPrimRecursivelyEiiPNS_4PrimEiRKSt13unordered_mapIjjSt4hashIjESt8equal_toIjESaISt4pairIKjjEEEPNS_5StageE	103848	static
```

# stack protector

https://qiita.com/kakinaguru_zo/items/f6e37beb2b77223a9282

stack protector は intel CPU だけかしらん.

SafeStack は overflow は検出してくれるんじゃろか?

https://www.pwnthebox.net/papers/2021/03/10/understanding-clang-safestack.html



# Linux で stack overfow の再現をしやすくする

Linux の場合はランタイム(OS)でスタックサイズを調整できます.

ulimit -s 1024 で stack size を減らしてみたり...
(ただ, セキュリティ設定によるのか一旦減らしてから戻すには一旦 shell を抜けるしかないっぽい)

# Windows

Windows は実行時スタックサイズ調整は出来るのかな?
MSVC ではコンパイル時(リンク時)に設定はできます.

https://learn.microsoft.com/en-us/cpp/build/reference/f-set-stack-size?view=msvc-170

https://stackoverflow.com/questions/40157847/increase-stack-size-in-c
STM32G071とSSD1306に豆腐を召喚する(スペルは、「40-FF」...)


x OLED096UNO-Aです。
x NUCLEO-G071RB



目的
OLEDのテスト



![o_con777.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/98278788-0a1a-7825-8f19-e7fbe25d60f7.jpeg)


![o_con778.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/8a87a7ea-6fea-2815-5c9f-103c42ea00b4.jpeg)



これでアカデミーは、強制卒業です。
僕の考えた最強のなになにを作ってください。



```c++



//ssd1306_int_071_1

#include <Arduino.h>
#include <Wire.h>

void write_s(uint8_t *str1, uint8_t len1) {

  Wire.beginTransmission(   0x3c  );

  for (int ii = 0; ii < len1; ii++) {

    //一文字出力
    Wire.write(*str1 ++);

  }//for

  Wire.endTransmission();

}//eeprom_write_s

//初期化
void setup() {

  //I2Cの初期化
  Wire.begin(); //071
  delay(200);

  //0x80,0x8d,0x80,0x14,0x80,0xAF
  write_s( (uint8_t*) "\200\215\200\024\200\257", 6);
  delay(100);

#define DATA_MODE                  0x40

    uint8_t databytes[2] = {DATA_MODE,0xFF};
    for (int icount = 0; icount < 8; icount++) {
        write_s(databytes, 2);
    }//for


}//setup

//無限ループ
void loop() {
}//loop





```
【Swift】Date型をデコード

# はじめに
いままでCodableでデコードする時にデータがあるとデコードに失敗してたのでStringでデコードしてました。

Dateでデコードする方法を学んだので記録しておきます。

# 方法
```swift
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let weatherModel = try decoder.decode(WeatherModel.self, from: weatherData)
```

# おわり
勉強になりました
CCNP 覚えておきたい英語表現

CCNP ENCORを英語受験してきました。
1から英語の勉強からはじめるより、技術資料等でよく出る単語/表現だけ覚えた方が効率いいなと思いこの記事にまとめました。
勉強中、よく見かけた英語たちです。ご参考になれば嬉しいです。

■表現
--特徴(用途/制限/デフォルト値等)に使われる表現--
a characterıstıc of　～:～の特徴
descrıbed	:～について述べている
dıfference between A and B	:AとBの違い
enables　～	:～を実現する
feature ıs～	:～の特徴
functıon of～	:～の機能
～ıs responsıble	:～の役割
regarding ～	:～に関して

--設定とかに使われる表現--
accomplıshes～	:～を完了させる
attempts to	:設定を試みる
deployed～	:～を設置した
modıfy～	:～を修正しする
suppose　～	:～と仮定する
has been asked～	:～を頼まれた

■反対語 
superior:優れる/inferior:劣る
prefer:好む/avoid:避ける
highest:(値が)大きい/lowest:(値が)小さい

■その他 なかなか覚えられなかった単語
accomplıshed:達成した
accumulation:累積
associate:参加する
assurance:保証
attempts:試み
characterıstıc:特徴
consıderatıon:考慮
defıne:定義する
deployment:配置、展開
descrıbed:説明された
enforce:実施する，施行する
features:特徴
functıon:機能
ımplementıng:実装する
improve:上がる
modıfy:(コンフィグの)修正
prevent:防ぐ
provıde:提供する
regarding:～に関する
requıred:要求される
resolve:解決する
responsıble:(機能の)役目
suppose:仮定する
survey:調査
threat:脅威
verıfy:検証


=====
半年ほどCCNP ENCORの勉強に費やしました。
英語のドキュメントが読めるようになり、ちょっとだけ自分に自信がつきました！
Shapの decision plotを画像として出力したい

# 結論から先に言うと
`decision_plot` の `show` パラメータを Falseにして 手動でmatplotの`savefig` を実行する

# 起こった問題

Shapは機械学習のモデルがどのようにデータを解釈しているのかを分かりやすく表示してくれる。
decision plotのデータをmatplot上で見れるのは良いが、画像として表示したい。
また、できれば表示する前に色々と設定したかった。

# 解決策

showパラメータをTrueにしていると、内部的にmatplotlibのshow()が呼ばれてしまう。
showを呼んだ後に、savefigしても真っ白な画像しか出力されないので、showを呼ばないようにする。
ので、showパラメータにFalseを設定する。
( 参考 [python　グラフ　保存　真っ白]: https://r-bxm-a.hatenablog.com/entry/2018/10/03/132320 )

showパラメータにFalseを設定してもmatplot側には表示するための値が渡されている。
ので、手動でsaveFigする。

```python
import shap
import matplotlib.pyplot as plt

# shapのデータ読み込みここは各々書いてね
shap_data = load_shap_data()
# Decision Plotを実行
ret =shap.decision_plot(
    base_value=shap_data.base_value,
    shap_values=shap_data.shap_values,
    feature_names=shap_data.feature_names,
    color_bar=False,
    legend_location="best",
    link='logit',
    # showをFalseにすることで内部のmatplot showが実行されなくなる
    show=False,
    feature_display_range=range(
        len(shap_data.feature_names) - 100, len(shap_data.feature_names)
    ),
    return_objects=True
)

# 良い感じにレイアウトを整えてもらう
plt.tight_layout(rect=[0,0,1,1])
# 画像として出力
plt.savefig("figure.png") 

```

上記のようにするとshowが呼ばれないので好きな設定で画像ファイルに書き出せる。
多分出力前にいろいろ設定とかもできるはず。

# 出力結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96675/918a2246-baf7-2280-0d53-333a627095a6.png)
うむ。(legendは消してあります)
Ubuntuで自分が設定したcron内容を確認するには？

# やり方

端末開いて下記コマンド。

```shell
crontab -l
```

rootユーザー以外でログインしている場合、rootユーザーで作ったcron内容は出てこない。


rootユーザーで作ったcron内容を確認したい時は ```sudo``` を先頭に付ける。

```shell
sudo crontab -l
```

# 参考サイトさん

https://www.server-memo.net/tips/crontabfile.html

# バージョン

Ubuntu 20.04.5 LTS
EC2のインスタンスタイプに応じてpostgresql.confを変更する

# インスタンスタイプを変更したときにPostgreSQLのDB設定も変更したい
PostgreSQLをAWS RDSではなくAWS EC2上で動かすとき、インスタンスタイプに応じてDB設定（postgresql.conf）を変えたいことがある。
例えば低スペックで良いときはt3.mediumで、高スペックが必要なときはr5a.xlargeで、というようなときである。
このときDB側もshared_buffersやwork_memといったメモリ関連のパラメータをインスタンスのメモリ容量に合わせて変更したいときどうすれば良いか。

インスタンスタイプ（メモリ容量）に応じてpostgresql.confを用意しておき、サービス起動時にインスタンスタイプを確認して読み込むpostgresql.confを選択する、という方法がある。
下記にその方法について書いておく。

# インスタンスタイプを確認し、DB起動時にpostgresql.confを指定する
手順としてDBはEC2インスタンス起動時にsystemdのサービスファイルによって自動起動されることを想定している。

## DB起動用のシェルを作成する
下記のようにDBを起動するためのシェルを作成し、それをサービスファイルから呼び出す形になる。

```shell:run_postgres.sh
#!/bin/bash

INSTANCE_TYPE=`curl -s http://169.254.169.254/latest/meta-data/instance-type`
if [ "${INSTANCE_TYPE}" = "t3.medium" ]; then
    CONFIG_FILE=${PGDATA}/postgresql_lowspec.conf
else
    CONFIG_FILE=${PGDATA}/postgresql.conf
fi

exec /usr/pgsql-13/bin/postmaster -D ${PGDATA} -c config_file=${CONFIG_FILE} 
```
インスタンスタイプはEC2インスタンスのメタデータから取得することができる。
これをサービスファイルがあるディレクトリに作っておく。
```
[root@host ~]# cd /usr/lib/systemd/system
[root@host system]# vi run_postgres.sh
[root@host system]# chmod +x run_postgres.sh
```


## サービスファイルを変更する
次に作成したこのシェルをPostgreSQLのサービスファイルから実行するようにする。
```
[root@host system]# vi postgresql-13.service
```
```shell:postgresql-13.service
# サービスファイルの変更箇所
# DBクラスタがデフォルトの格納先ではない場合
Enviroment=PGDATA=（格納先のdataディレクトリのパス）

# systemctl start する時の設定
# ExecStart=/usr/pgsql-13/bin/pg_ctl start -D ${PGDATA} -s -w -t 300
ExecStart=/usr/lib/systemd/system/run_postgres.sh

# タイムアウトの無効化
TimeoutSec=0
```
これにより systemctl start postgresql-13 としたときにrun_postgres.shが呼び出され、
インスタンスタイプに対して設定したpostgresql.confファイルが読み込まれることになる。

ただしこの方法では1点注意するところがある。
run_postgres.shの中にあるようにpostmasterでDBを起動するとカーソルがコンソールに戻ってこない。
コマンドの終了宣言がされず、処理待ちのような状態になってしまう。
そのためサービスファイル内で TimeoutSec=0 のようにタイムアウトを無効化する必要がある。

仮に TimeoutSec=300 のように設定されている場合、起動してから300秒後にDBが停止する。
Systemdではrun_postgres.shから終了宣言が帰ってこないためタイムアウトで失敗とみなし、ステータス：failed としてサービスを停止させるのである。

※タイムアウトを無効化することで回避はできるが、ここらへんちゃんと解決する方法があったら教えてほしい。
【Laravel 9.x】 artisanで失敗するエラーは./vendor/bin/sailが関係しているかも

この現象は、私同様、Laravelを試してみようという人が中心に引っかかる罠だと思われる。

## 背景と対策

Laravelを下記のように立ち上げた際に、その後マニュアルやチュートリアル通りに進めようとすると、artisan呼び出しの際に様々なエラーが発生する。

下記はWindows環境でDocker Desktopを入れた後に、WSLから下記のように入力するだけで環境の構築が終わるとLaravelのマニュアルにあるので、それに倣った形だ。
```bash
$ curl -s https://laravel.build/sample-app | bash
$ cd sample-app && ./vendor/bin/sail up
$ php artisan about
```

これらはartisanの呼び出しを `php artisan` から `./vendor/bin/sail artisan`に変更すると解決する。どこかに書いてあるのに、見逃しているんだろうな...。

## 見られる現象

少し試しているだけでもかなり引っかかった。

### 1. .env用のキー生成ができない

.envファイルのキー文字列を生成するために`artisan`を使用するとある。マニュアルで確認すると下記の１行で一発なのだが、これがうまくいかない。

```bash
$ cd sample-app
$ php artisan key:generate
```
結局、アレがないこれがないと入力し続けた結果処理を行うには下記の準備をして最小構成ではなくDocker形無しである

```bash
$ sudo apt update -y 
$ sudo apt upgrade
$ apt install php-cli php-dom
$ cd sample-app
$ php artisan key:generate
```
これは下記が正解。

```bash
$ cd sample-app
$ ./vendor/bin/sail artisan key:generate
```

### 2. migrateできない

```
$ php artisan migrate
   Illuminate\Database\QueryException
   could not find driver 
   (SQL: select * from information_schema.tables 
    where table_schema = sample_app 
        and table_name = migrations 
        and table_type = 'BASE_TABLE')
   at vendor/laravel/framework/src/Illuminate/Database/Connection.php:759
(...以下省略)
```
MySQL接続ドライバがないとかそんなエラーになると思うのですが、おかしいでしょ。
ネットを探索しても、解決方法は、MySQLConnectionエラーが発生する原因を特定するための特殊な`MySqlConnection`を作って..って遠回りなものが検索結果として出てきます。

難しいです。

Sailで準備した場合は下記が正解です。

```bash
$ ./vendor/bin/sail artisan migrate
```

### 3. migrationファイルの権限がない

上記のエラー試行錯誤して `./vendor/bin/sail artisan` で解決した後、
今度はファイルのアクセス権限がなくなります。

```bash
$ ./vendor/bin/sail artisan migrate
In Filesystem.php line 210:

  chmod(): Operation not permitted
```
私のような人は「今度は./vendor/bin/sail 使っているのに...？」となります。

これは、`php artisan migrate`で作成したファイルのアクセス権限がない事で発生します。`php artisan migrate`で生成されたファイルは権限を変更するか、いったん削除することで解決します。
slice!メソッドの備忘録

今日も学んだことを忘れない為にメモします

### slice!メソッドとは
配列や文字列から指定した要素を削除し、削除した後の要素を返すメソッドでもとの配列や文字列を変化させる破壊的メソッドの一種
```
string = "abcdefg"
string.slice!(2)

puts string
#=> "abdefg"  #2番目の要素のcが取り除かれている
```

このslice!メソッドを用いて任意の文字を削除したのち、残った文字を出力するプログラムを実装できる。

### 記述内容
```
def missing_char(str, n)
  str.slice!(n - 1)
  puts str
end

missing_char('hogehoge', 1)
missing_char('hogehoge', 3)

#=> "ogehoge"
#=> "hoehoge"
```
第一引数に対象の文字列、第二引数に何番目の文字を消すのか指定し、missing_charメソッドを呼び出す。
strには文字列"hogehoge",nには指定した数字が入る
strにslice!メソッドを使用して引数に指定した数字が入ったnを記述するが配列の文字は０からカウントするので(n-1)と記述して指定した文字を消せるようにする。

以上になります。
テーマ別アプリアイコン表示方法

今回はテーマ別アプリアイコンの端末での設定方法を紹介していきます。


まずは、端末の設定を開きます。

Walloaoer&Style(壁紙とスタイル)を選択します。
![Screenshot_20220918_184757.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/339ee1ef-af02-0d3a-91df-6a6adac981eb.png)


そしたら下にスクロースをして、テーマアイコンのスイッチをONにします。

![Screenshot_20220918_184902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/3fbd3c65-daf5-bd63-cd4c-5624011dc873.png)


そうするとこのようになります。

![Screenshot_20220918_184247.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/2dc7ab40-17af-bccb-fd0e-c25bb6515f9e.png)


対応しているアプリは多くないと思いますがこのようなこともできます。

以上です！
戻るボタンを押した時に、ページトップではなく元の位置に戻るようにしたい

CMSなど何らかの記事一覧ページがあったとして、
詳細ページに遷移後、また一覧に戻ったときも遷移前のスクロール位置を保持したい。

## 実装したこと
当初、以下の想定をしていました。
1) ローカルストレージに遷移前のスクロール位置を保存する。
2) 戻ったときにそこに移動する。


しかし、History APIが既にその仕様を取り扱っている模様。
history.back()を組み込んであげることで、ブラウザの[←戻る]ボタンを押したときと同じ動作を実現できます。

```html:index.html
<a href="javascript:void(0)" onclick="history.back()">前のページに戻る</a>
```

## 参考サイト
・[History.back()](https://developer.mozilla.org/ja/docs/Web/API/History/back)
・[History.scrollRestoration](https://developer.mozilla.org/ja/docs/Web/API/History/back)
Gitの基本の「キ」 part3 gitの基本的なコマンド

# はじめに
エンジニアを志して皆さん勉強を始めていきますが、gitに関して知らない方、結構多い印象ですね。
わかってしまえば非常に便利なgitですが、概念が少し分かりづらいですよね。
いきなり触るとなった場合にも困る事がないよう、経験のない方向けにシリーズとしてまとめていこうと思います。

今回は[前回](https://qiita.com/YuukiYoshida/items/d93eaa9ebfbb2cd29ba2)に続き、part3、基本的なgitコマンドについて説明していこうと思います。

# clone（クローン）とは？
ローカルまたはリモートリポジトリのコピーを作成する機能です。
プロジェクトの環境構築を行う際、すでにプロジェクトリソースが存在する場合は、git上に存在する成果物をcloneし、コピーを作成するところから始まるはずです。
ですので、コミットやプル、プッシュもこの後ご説明していきますが、このクローンも同じくらい重要なコマンドと言えますね。

# pull(プル)とは？
pullとはリモートリポジトリから最新の差分を取得し、ローカルリポジトリへ反映させる機能です。
gitではリモートとローカルという2種類のリポジトリがあります。

<dl>
  <dt>・リモートリポジトリ</dt>
  <dd>専用のサーバに配置し、複数人で共有するためのリポジトリです。</dd>
  <dt>・ローカルリポジトリ</dt>
  <dd>自身のPC上に作成されたリポジトリです。</dd>
</dl>

このリモートリポジトリから差分をローカルリポジトリへ反映させる機能です。

# commit（コミット）とは？
リモートにあげたい差分を登録する機能です。
gitではローカルリポジトリからリモートリポジトリへ反映させる際、いくつかのプロセスを踏む必要があります。
その一つがコミットになります。

初心者の方がよくやる問題として、このコミットを忘れてしまうというものがあります。
gitではまず差分を登録(commit)しておかないとリモートにあげることができないので、その点注意ですね。

# push(プッシュ)とは？
先ほどご紹介したcommitでしたが、こちらのpusは登録されている差分をリモートリポジトリへ反映させる機能です。
commitのご説明をした際に幾つかのプロセスを踏む必要があるとお話しましたが、これがその最後のプロセスです。

自身の差分をリモートリポジトリへ反映させたいとなった場合、commit→pushと2つ実行する必要があります。
こちらどちらが欠けていてもリモートリポジトリへ反映されることはないので、差分をあげたはずなのに反映されていないなどのトラブルの際は、両方実行したか確認してみると良いと思います。

# さいごに
ここまで覚えれば最低限使用する為の準備は整っているはずですので、次はもう少し踏み込んだご説明をしようと思います。
【Vim/Neovim】折りたたみのやり方

## 折りたたみ方法

例えば、Rubyで下記のようなGemfileがあったとする。

~~~:Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.6'

gem 'rails', '~> 6.1.6', '>= 6.1.6.1'
gem 'pg', '~> 1.1'
gem 'puma', '~> 5.0'
gem 'sass-rails', '>= 6'
gem 'webpacker', '~> 5.0'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.7'
gem 'bootsnap', '>= 1.4.4', require: false
gem 'bootstrap-sass'
gem 'bcrypt'

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails'
  gem 'rails-controller-testing'
  gem 'factory_bot_rails'
  gem 'rubocop', require: false
  gem 'rubocop-performance', require: false
  gem 'rubocop-rails', require: false
  gem 'rubocop-rspec'
end

group :development do
  gem 'web-console', '>= 4.1.0'
  gem 'rack-mini-profiler', '~> 2.0'
  gem 'listen', '~> 3.3'
  gem 'spring'
end

group :test do
  gem 'capybara', '>= 3.26'
  gem 'selenium-webdriver', '>= 4.0.0.rc1'
  gem 'webdrivers'
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

~~~

まずは、Visual modeに入って、
折りたたみたい部分を選択する。

選択したら、
**zf**を押すと、折り畳める


![Screen Shot 2022-09-18 at 18.17.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1290117/e736b300-9591-915a-bace-d36ea83069f1.png)

もう一度展開したいときは、
**zo**を押す。

デフォルトの折りたたみ設定は、
manualだが(:set foldmethod?コマンドで確認できる)、
変更できる。

indent単位で折りたたみたいなら、
```:init.vim
set foldmethod=indent
```

railsのspecのファイルを開くと、
このように最初から折りたたまれている。

![Screen Shot 2022-09-18 at 18.31.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1290117/32ec6b41-ff2a-a411-17ec-8bce5f43a3fb.png)


ファイル内の折りたたみを展開は、
**zr**を、
それらを再帰的に展開したい場合は、
**zR**を押せば、展開される

もう一度折りたたみたいときは、
**zm**を、
再帰的には、**zM**を。


設定は、indent以外にも色々あるので、
暇なときに色々試してみたい
Delphiっぽいフリーの開発環境を準備してみる

## はじめに
私は現在、職場でクラウドネイティブ技術に携わる仕事をしているのですが、`マネージドKubernetes環境でDelphiアプリケーションを動かしてみる`をテーマに自社の技術ブログを書いてみたいな、と思っています。

私は過去10数年ほどDelphiを使った開発をしていましたので、Delphiに愛着があります。
パブリッククラウドのPaaS/FaaSにおいてDelphiアプリケーションを動かせる環境を、少なくとも私は存じ上げませんが、DelphiのコードをLinux向けにコンパイルしてコンテナで動かすようにすれば、パブクラ上のマネージドKubernetes環境で動かせると思ったので、それを試したいなと思っています。

一方で、会社の技術ブログを書く = 業務扱いになるので、[Community Edition](https://www.embarcadero.com/jp/products/delphi/starter)は使わない方法でDelphi（互換の）アプリケーションを作れる方法を探していました。

そこで、[Free Pascal](https://ja.wikipedia.org/wiki/Free_Pascal)と[Lazarus](https://ja.wikipedia.org/wiki/Lazarus_(%E7%B5%B1%E5%90%88%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83))によるDelphi互換のアプリケーション開発環境を作ってみようと思いました。

## 開発環境
- OS
    - Windows 10
- Free Pascal
    - version 3.2.2
- Lazarus
    - version 2.2.2

## 構築手順
### Lazarusの導入
[Lazarusのサイト](https://www.lazarus-ide.org/)にアクセスします。そして、Windows 64 bitのインストーラーをダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411926/cb99fc0e-ac08-03a7-494a-5823ebdd45e0.png)

ダウンロードしたインストーラーを実行します。
インストールはウィザードに従って進めるだけでOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411926/df1aa96e-064b-d0f2-5acc-6c9900a6898b.png)

Lazarus入れたらFPCも勝手に入ってくるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411926/4fcea04e-6d05-3c55-e639-dd8fcf350053.png)


インストールが終わったら、LazarusのIDEを起動してみます。
ヒョウ（？）のアイコンをダブルクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411926/4051348f-f12a-20e1-425c-9de520153701.png)

こんな画面が出てきますが、プルダウンのところは空欄のままでOK（デフォルトの場所が選択される）ので、`Start IDE`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411926/9113481c-0da8-8f94-37f6-e297af627689.png)

おおお、懐かしい雰囲気ですね！（個人的感想）
`unit`、`uses`、`implementation`とか、Delphiを触ってた時のことを思い出しました。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411926/435f7363-ca6c-9e74-c9e8-4635028d1555.png)

## おまけ（Lazarusの名前の由来とアイコンがチーター（？）であることについて
[こちら](https://forum.lazarus.freepascal.org/index.php?topic=14620.0)で質問が上がってますが、`Object Pascalの復活`？みたいなのが含意されているのでしょうかね。。。
（Lazarus = ラザロ = イエスの友人、イエスによって死から甦らされたという話があるらしい）
（でもなぜアイコンがチーターなのかパッと見てまだわからない）

## さいごに
今回はとりあえずIDEを入れるところまで実施してみました。
情報が少ないので手こずるかな・・・？と思ったものの、IDEを入れるところまではすんなりできました。

次はDockerで動くサンプルプログラムを作ってみたいと思います。
【S3Select】列名がないCSVファイルの調べ方【Tips】 

# S3 SelectでRawデータを調べる
AWSのストレージサービスS3（Simple Storage Service）https://aws.amazon.com/jp/s3/
コスト面から利用企業の多いサービスであるS3。蓄積されたCSVファイルに対して調査を行えるのが、S3Selectである。
本記事は業務でS3Selectを利用する上でのRawデータ調査のTipsを紹介する。
早急に解決したい方は[解決](#解決)へ

*目次*
|No|ページ内リンク|
|:-:|:-:|
|1|[背景](#背景)|
|2|[課題](#課題)|
|3|[解決](#解決)|
|4|[注意](#注意)|

## 背景
S3にあるファイルはテーブルではなくCSVファイルである。データの中身の確認をするにはダウンロードするしか無いように思われる。
（あるいはRedshiftやAthenaなど別サービスにデータをロードし、確認）
しかし、大きなファイルをダウンロードして確認するのは非効率であるし、ローカルにデータを持つのはセキュリティ上制限される場合もある。
そこでS3Selectを利用して、SQLでファイルのデータを確認する。

## 課題
S3のCSVファイルをS3Selectで調査するにあたって困ったのが、条件での抽出である。
たとえば、下記のようなデータがCSVファイルとして保存されているとする。
| 1 | 2 | 3 |
|:-:|:-:|:-:|
| a |りんご|100|
| b |みかん|120|
| c |なし|150|
| d |もも|200|

DBであれば、id, name, priceなどのように列名をつけてcreate tableすれば
~~~ 
select * from table where name = 'りんご' 
~~~
のように簡単に抽出可能だが、列名がないCSVファイルではそうもいかない。
列名がないから列での条件付けが出来ないという問題があったのである。

## 解決
簡単に上記課題を解決する方法がある。
列番号での指定ができるのだ。
下記のように書けば、先ほどの抽出クエリと同じことができる。
~~~
select * from table where _2 = 'りんご'
~~~
こうして大きなサイズのCSVファイルをS3にある状態のまま、簡単に調査できる。

## 注意
S3SelectのクエリはCSVファイルの設定が影響する。
例えば、TSVファイルなのに区切りが,（カンマ）になっているなどでクエリのエラーとなる。
上記でうまくいかない場合は設定を確認されたし。

## 参考
公式のリファレンス

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-select-sql-reference-select.html

S3Selectについては下記がわかりやすい

https://dev.classmethod.jp/articles/s3-select-with-console/
STM32G071とOLED,SSD1306で初期化して遊ぶ(初期化魔法のスペルは、「80-8d-80-14-80-AF」)



x OLED096UNO-Aです。
x NUCLEO-G071RB


目的
OLEDの初期化

説明
スペルを唱える事により、OLEDを始動する

チャージポンプ　起動
ディスプレイオン　発動


画面が点いてノイズがでたらミッション完了
まず、スタートラインにつける


![o_con773.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/25946d73-6a7b-7fd3-7c1a-747d6812ae5a.jpeg)



![o_con774.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/ebafc08f-e113-8652-374b-470bbadcd926.jpeg)


![o_con776.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3ca75085-a237-1ad8-982c-d2dc9e32f119.jpeg)



![o_con775.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/09ed5516-04a3-ff10-f025-4cf807645575.jpeg)




```c++



//ssd1306_int_071_1

#include <Arduino.h>
#include <Wire.h>

void write_s(uint8_t *str1, uint8_t len1) {

  Wire.beginTransmission(   0x3c  );

  for (int ii = 0; ii < len1; ii++) {

    //一文字出力
    Wire.write(*str1 ++);

  }//for

  Wire.endTransmission();

}//eeprom_write_s

//初期化
void setup() {

  //I2Cの初期化
  Wire.begin(); //071
  delay(200);

  //0x80,0x8d,0x80,0x14,0x80,0xAF
  write_s( (uint8_t*) "\200\215\200\024\200\257", 6);
  delay(100);

}//setup

//無限ループ
void loop() {
}//loop




```
新・日本一わかりやすいReact入門【基礎編】をまとめてみる#02

# はじめに
この記事ではYoutubeチャンネル[【とらゼミ】トラハックのエンジニア学習講座](https://www.youtube.com/user/1492tiger)にて投稿されている[「新・日本一わかりやすいReact入門【基礎編】」](https://www.youtube.com/watch?v=XKSYF2aZnkQ&list=PLX8Rsrpnn3IWPoM7-1YPDksRRkamRY25k)をまとめることで自分のReactへの理解を復習し、より理解を深めていきたいと思う。

前回の内容: [Reactの基礎知識](https://qiita.com/sinnlosses/items/20998b93aa5a78353be2)
# 02 JSXの記法
ここではReactが扱う概念「コンポーネント」を表現するための記法「JSX」が説明される。

前回のおさらい:
コンポーネント = UI(見た目) + 機能(動画を再生、停止させるなど)

### JSXとは
どんな記法なのかということで、以下の例が挙げられていた。

```javascript
const BlueButton = () => {
    return (
        <button className={'btn-blue'}>
            Click me!
        </button>
    );
}
```

JSXの説明:
- JSXはjavascriptの拡張言語
    **HTMLライクな記述** + **javascriptの構文**が使える
    ちなみに[React公式ページ](https://ja.reactjs.org/docs/introducing-jsx.html#gatsby-focus-wrapper)にはこう書かれている
    > ```const element = <h1>Hello, world!</h1>;```
    > これは JSX と呼ばれる JavaScript の構文の拡張です

- 最終的にReact要素を生成する

##### React要素を生成するとは
Reactにはコンポーネント(component)という概念があり要素と訳せないでもない。
だからReact要素を生成するとはReact Componentを生成することだと**最初は思った**。

しかし、[Reactの公式ページ](https://ja.reactjs.org/docs/components-and-props.html)を見るとこのようにある。
> コンポーネントは JavaScript の関数と似ています。（“props” と呼ばれる）任意の入力を受け取り、画面上に表示すべきものを記述する React 要素を返します。

そしてコンポーネントの例が記載されている。
```javascript
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
```

これはJSXの記法の例で挙げられていたコードの構成と同じ。
つまり、**変数「BlueButton」はコンポーネント**だったということ。

```javascript
const BlueButton = () => {
    return (
        <button className={'btn-blue'}>
            Click me!
        </button>
    );
}
```

JSXの説明として「React要素を生成する」とあったが、
**正確には「コンポーネントはReact要素を生成する」** ということ。

では結局**React要素とはなにか**というと[公式ページ](https://ja.reactjs.org/docs/rendering-elements.html)にはこうある
> (日本語) 要素とは React アプリケーションの最小単位の構成ブロックです。
> (English) An element describes what you want to see on the screen.

**React要素とはReact Element**でありReact Componentではなかった。
また、例が挙げられている。

```javascript
const element = <h1>Hello, world</h1>;
```

つまり、関係性はこんな感じのよう。
```
             React App
                 |
        -----------------
        |               |
     React要素        React要素
        ↑(生成)          ↑(生成)
     コンポーネント      コンポーネント
```

# なぜJSXを使うのか
「HTMLライクに書けて楽」と理解しておけばいい。

使わない場合
```javascript
React.createElement(
    'button',
    {className: 'btn-blue'},
    'Click me!'
)
```
使った場合
```javascript
    <button className={'btn-blue'}>
        Click me!
    </button>
```

# JSXは何をしているか
コンパイル時にJSXを使った記法はJSXを使わない記法に変換される。

人間はわかりやすい書き方で、機械にとってわかりやすいようにするのはコンパイラのお仕事。

# JSXの基本構文 & JSXの特殊構文

```javascript
import React from 'react';

const BlueButton = () => {
    const yourMessage = "Click me!";
    return (
        <button className={'btn-blue'}>
            {yourMessage}
        </button>
    );
}
export default BlueButton;
```

注意点:
- Reactをimportすること
    - でなければ使えない
- 変数を埋め込む場合は{}で囲む
    - 囲まなければyourMessageとそのまま表示されることになる
- HTMLの場合と違い、cssを記述する場合はclass=...ではなくclassName=...の形式
- HTMLの場合と違い、変数はcamelCaseで
- HTMLの場合と違い、imgタグのようなタグでも閉じタグが必要



# 参考資料
[Reactのコンポーネント周りの用語を整理する](https://blog.ojisan.io/react-component-words/)