OmniAICreator/Qiita-1.07M huggingface dataset:
「エントロピーと秩序」のプログラムをpythonで書く～エントロピー


「エントロピーと秩序」のプログラムをpythonで書く第3弾。
「エントロピー」というタイトルがついているbasicのプログラムをpythonで書き直します。

[前回](https://qiita.com/pyjackal/items/0eef5c557f2a1566ac4f)100個の原子から成り立っている物質1(n1)と1500個の原子からなりたっている物質2(n2)にランダムに元気な原子を配置した時の、n1とn2の温度の揺らぎ可視化するプログラムをpython化しました。

今回のプログラムは、n1に配置されている100個の元気な原子がn2のほうへ一個ずつ移っていった時のエントロピーの変化を可視化するプログラムになっています。(モデル世界ということで、k=1で計算されています)
本家のプログラムにはグラフを表示する/しないを選択できる処理が入っていたのですが、グラフがないと面白みがないので省略しました。あと、各値をprintする処理も入っていたのですが、全体のエントロピーが最大となったポイントの値だけをグラフに表示するよう変更しています。

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

N = 100  # = int(input("ON状態にする原子数(1から100まで)"))

n2_values = []
s1_values = []
s2_values = []
s_values = []

max_s = 0
max_n2 = 0

for n2 in range(N):
    n1 = N - n2
    s1 = 0
    if n1 > 0:
        for i in range(0, n1):
            s1 += math.log((100 - i) / (n1 - i))
    s2 = 0
    if n2 > 0:
        for i in range(0, n2):
            s2 += math.log((1500 - i) / (n2 - i))
    s = s1 + s2
    if s > max_s:
        max_s = s
        max_n2 = n2
    n2_values.append(n2)
    s1_values.append(s1)
    s2_values.append(s2)
    s_values.append(s)

plt.plot(n2_values, s1_values, 'b', label="n1 entropy")
plt.plot(n2_values, s2_values, 'r', label="n2 entropy")
plt.plot(n2_values, s_values, 'y', label="total entropy")
plt.axvline(max_n2, label=f"max: {max_s:.1f} (n2={max_n2})", color="g")
plt.ylabel("entropy")
plt.xlabel("active atoms in n2")
plt.legend()
plt.show()
```

本家プログラムに

```text:basic
210 FOR I=0 TO N1-1:
220 S1=LOG((100-I)/(N1-I))+S1
230 ...
```

という部分があり、basicのfor文の場合N1 = 1のときにI = 0で一回ループが回るのですが、pythonで

```python:python
for i in range(n1 - 1):
    s1 += math.log((100 - i) / (n1 - i))
    ...
```

と書いてしまうと、n1 = 1の時にループが回らないので、どう書いたらよいのか少し悩みました。
このプログラムを実行すると、以下のようなグラフが表示されます。

![Figure_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109677/2eae3d70-7688-f710-db18-865855ce397c.jpeg)

グラフを見ると、n1から94個の元気な原子がn2に移った時に全体のエントロピーが最大となっています。
[前回](https://qiita.com/pyjackal/items/0eef5c557f2a1566ac4f)出てきた温度を計算する式を使って、元気な原子がn2に92～96個存在するときのn1とn2の温度を計算してみると、エントロピーが最大(n2=94)のときn1とn2の温度が一番近くなっていることがわかります。

```bash
>>> import math
>>> for i in range(92, 97):
...     n1 = 100 - i
...     n2 = i
...     t1 = 1 / math.log((100 - n1) / n1)
...     t2 = 1 / math.log((1500 - n2) / n2)
...     print(f"n2: {n2}, t1: {t1:.4f}, t2: {t2:.4f}, diff: {abs(t1 - t2):.4f}")
n2: 92, t1: 0.4094, t2: 0.3666, diff: 0.0429
n2: 93, t1: 0.3866, t2: 0.3681, diff: 0.0185
n2: 94, t1: 0.3634, t2: 0.3697, diff: 0.0062
n2: 95, t1: 0.3396, t2: 0.3712, diff: 0.0316
n2: 96, t1: 0.3147, t2: 0.3728, diff: 0.0581
```

「物事は自発的には全体のエントロピーが増大する方向にしか変化しない」
　 => 「部屋に熱いコーヒーを置いておくとやがて冷めて室温と同じになるが、それ以上に温度が下がったり、勝手に再び沸騰したりはしない」 

ということがわかります。
dataclasses-json：データクラスのフィールドの型に`list`などを使うと、`TypeError: 'type' object is not subscriptable`エラーが発生する

# 実行環境
* Python3.8.6
* dataclasses-json 0.4.5

# やりたいこと
[dataclasses-json](https://github.com/lidatong/dataclasses-json)を使って、dictからデータクラスに変換したいです。

# エラー発生

以下のコードを実行すると、`TypeError: 'type' object is not subscriptable`が発生しました。

```python:foo.py
from __future__ import annotations
from dataclasses import dataclass
from dataclasses_json import dataclass_json


@dataclass_json
@dataclass
class Person:
    name: str
    club: list[str]


d = {"name": "Alice", "club": ["tennis", "soccer"]}
person = Person.from_dict(d)
print(person)
```

```
$ python foo.py
Traceback (most recent call last):
  File "foo2.py", line 14, in <module>
    person = Person.from_dict(d)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/dataclasses_json/api.py", line 83, in from_dict
    return _decode_dataclass(cls, kvs, infer_missing)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/dataclasses_json/core.py", line 152, in _decode_dataclass
    types = get_type_hints(cls)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/typing.py", line 1232, in get_type_hints
    value = _eval_type(value, base_globals, localns)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/typing.py", line 270, in _eval_type
    return t._evaluate(globalns, localns)
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/typing.py", line 518, in _evaluate
    eval(self.__forward_code__, globalns, localns),
  File "<string>", line 1, in <module>
TypeError: 'type' object is not subscriptable
```

# 原因
フィールド`club`の型`list[str]`が原因のようです。
型が`typing.List`ならば、エラーは発生しませんでした。

```python
import typing
@dataclass_json
@dataclass
class Person:
    name: str
    club: typing.List[str]
```

またPython3.9.7ならエラーは発生しませんでした。
Git submodule 備忘録

たまに使う機会があると毎回忘れて調べるハメになるので、ここに備忘録を残しておきます。


## サブモジュールの追加

```
git submodule add <リポジトリのURL>
```

## サブモジュールのステータス確認

```
git submodule status
```

以下の情報が確認できます：

- サブモジュールが指すコミットのハッシュ値
- サブモジュール名
- サブモジュールが指すブランチ名（またはタグ名）

## サブモジュールの削除

```
git submodule deinit <サブモジュール名>
git submodule rm <サブモジュール名>
```

`git submodule deinit`実行直後は目立った変化がありませんが、`git submodule status`でステータスを確認するとハッシュ値の前に`-`が付いていることが確認できます。

その後`git rm <サブモジュール名>`を実行すると、`git submodule status`のリストからサブモジュールが消えます。

## サブモジュールの実ファイルを取得

```
git submodule update --init --recursive
```

# トラブルシューティング

## `git submodule status`で先頭に`-`がついている

`git submodule deinit <サブモジュール名>`直後の状態です。サブモジュールの削除がステージングエリアで保留になっているような状態というイメージで良さそうです。

サブモジュールを復活させたい場合は

```
git submodule update --init --recursive <サブモジュール名>
```

サブモジュールをそのまま削除したい場合は

```
git rm <サブモジュール名>
```

# まとめ

gitのサブモジュールは少しややこしいですね（自分だけ？）。コマンド体系を忘れたり、`.git/`内部の状態を把握できなくなってしまうことが何度もありました。

この備忘録が他の人にも役立てば嬉しいです。

# 筆者について

フォローしていただけると励みになります！

Twitter: https://twitter.com/_matoruru
GitHub: https://github.com/matoruru
ggplotでプロットの型を使い回す（%+%）

ggplotで、**異なるデータで同じ形のプロットしたい**ときの一つのやり方。
`%+%` を使うことで、事前に作ったggplotオブジェクトを使いまわして、データを入れ替えできる。

まずは、プロットの型を作る。

```R:R
g <- ggplot(data=iris, aes(x=Sepal.Length, Sepal.Width)) +
  geom_point() +
  xlim(4, 8) +
  ylim(1, 5)
```

※この時点で、dataは指定しなくても問題ない。（NULLなどでもよい）
　ちなみに、上記`g`を表示すると次のイメージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/a964b9cd-68a6-6f73-2d5d-27bd05e92695.png)

次に、データを入れ替える。（本題）

```R:R
g %+%
  filter(iris, Sepal.Length < 6)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/ae5040cf-2c8c-e573-8fe2-1882c4c055ac.png)

```R:R
g %+%
  filter(iris, Sepal.Length >= 6)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/3b16732c-9bcb-e84e-e7f7-71b575676d29.png)

もともとのプロットの型をアレンジすることも可能。
※なお下のコードは、もとの`geom_point()`の後で、`geom_point(color="blue")`が再度処理されているイメージ。

```R:R
g %+%
  filter(iris, Sepal.Length >= 6) +
  geom_point(color="blue") +
  geom_smooth(method="lm", color="black")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/bf03b41d-b9fe-b084-5be8-148483f8703f.png)
ブログを書くとき便利なブックマークレット

# 1. Chromeの拡張機能を使っていたがどんどん消えてった

まあなんかいろいろあるらしくいつの間にか使えないことが頻発した。

# 2. 代替案をさがしていたら良さげな方法が見つかった

```
javascript:prompt('ページタイトル + URL', '['+ document.title + '](' + location.href+')')();
```

簡単なブックマークレットを用意した。これをChromeのブックマークに登録して、
markdown形式でタイトルとURLを楽にコピーできるようになった。
何度も調べたCSSシリーズ

# 目的
これ毎回調べているな〜という詰まりがちなCSSの実装をまとめます。

## input type="text"のfocus時、border設定したのに反映されない
input type="text"にはデフォルトでoutlineが設定してあるため、
borderだけ設定してもoutlineが勝ってしまう。

* outlineにborderの時のように、設定を入れる


```
input[type="text"]:focus {
  outline: solid 1px #000;
}
```

* outlineは無効にして、borderに設定を入れる

```
input[type="text"]:focus {
  outline: none;
  border: solid 1px #000;
}
```

## opacity何にすれば透明になるの？問題

いつも迷うから覚えられる方法を見つけた。

**opacity = 不透明度（透明でない度）**

つまり、1(truthy)だったら透明でない度がマックス（バリバリ見える）
0(falsy）だったら透明でない度がゼロ（見えない）



### 参考
[フォームのinput要素をfocusした時の枠の色を変える方法！](https://qumeru.com/magazine/205)
N予備プログラミング　〜冬コンテスト作品制作過程を晒してみる④〜

みなさんこんばんわ

意外と強かった中ボス”18.【サービス開発3】データモデルの実装とユーザーの保存”を前に完全に足が止まる。カビゴンかよ！と。『これ、ピンチだよね？逆転できるよね？？』と心の声。焦ってキタｰｰｰ💦

分かってますよ。。泣き言いっても進まないんですよ。。いつもの写経ですよ！！
まずはmodels/sequelize-loader.jsから実装！ここのDB名を自分のに書きなないと意味なし芳一じゃーい。

![スクリーンショット 2022-01-26 21.29.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/0376648b-c8ac-c707-aaa6-b18ff372c8c2.png)

慎重に四行目＠以下を db/schedule_arranger から　db/covid_riskcalk
に書き換えます。

おつぎはmodels/user.jsを実装。いちおう変数名チェックして、、、これはそのままコピペで大丈夫そう。

問題は次のmodels/schedule.jpだぞと！！これは”covidリスク確認くん（開発用）”設計書で変えた変数なので、もれなく"schedule"から"dataset"に変更していきます。

ここで！ついに伝家の宝刀を抜く！🥷シャキーン！！
VSコードでmodels/schedule.js開いて、四行目の”Schedule”をシフトキーを押しながら選択して、右クリックからの〜！究極奥義！！”すべての出現箇所を変更”さくれーつ！！

![スクリーンショット 2022-01-26 22.21.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/470d8079-4b5d-d0a9-e8eb-851b4e8163f8.png)

って。。あれ？　オーイ！！　大文字と小文字を区別せず選択してしまってるぢゃーん！！💦
VSコードさん！分かってるでしょ！！PCさん神経質なんだから。。大文字小文字はちゃんと区別してもらわないと。（と泣き言たれること小一時間。）みなさんも気をつけてくださいね。
VSコードに大文字と小文字を区別させる方法あるんでしょーか？知ってる方いたらおしえてキボンヌ

ｰｰｰ（早送り編集中）ｰｰｰ

schedule.js改め、dataset.jsからはじめて山のようにあるmodelsフォルダ内のデータモデルをブツブツ言いながら全て書き直してたらもうこんな時間😱
でも、なんとか気合いで↓のSQL弾幕までたどり着く！ふへｰｰｰ。。
　![スクリーンショット 2022-01-26 20.18.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/ea6de465-4bc9-d5de-cfc4-94da2b03c816.png)

psqlコマンドでデータベース出来てるか確認したら致命的エラー出てんぢゃーん！！（泣）
とおもったら、データベース名末尾の文字をTYPOしてますた。。（cのつもりがkになっとる）これは、疲れてるな。。
余力があるうちにダンジョンを抜けて宿屋に泊まろう。そして、![スクリーンショット 2022-01-26 23.05.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/4bad645d-822f-f44e-faa4-2bb61bab160e.png)
あしたまたがんばろう。
Ruby: Splat Operator と Double Splat Operator

## はじめに

Ruby には `Splat Operator` と `Double Splat Operator` の２つの文法があることを知りました。以前より何回か見たことはあったが、ちゃんと理解できていなあった点もあるので、改めてその違いと特徴をまとめてみます。

## 前提
- Ruby 2.7.5

## Splat Operator 

### どんなもの?

メソッドの仮引数にある `*` を使用して定義した引数のことです。

```ruby
def method(*args)
...
end
```

要は可変長引数で配列として受けることができます。


```ruby
def method(*args)
  args
end

p method('Ruby', name: 'yamada') # => ["Ruby", {:name=>"yamada"}]
```

配列として受けることができるので、引数には文字列やキーワード引数などが渡すことができます。

## Double Splat Operator

### どんなもの？

メソッドの仮引数にある `**` を使用して定義した引数のことです。

```ruby
def method(**args)
...
end
```

可変長キーワード引数を受け取ることができます。

```ruby
def method(**args)
  args
end

p method(language: 'Ruby', name: 'yamada') # => {:language=>"Ruby", :name=>"yamada"}
```

渡し方がキーワード引数となるので、Splat Operatorの時のように `ArgumentError` が発生してしまいます。


`p method('Ruby', name: 'yamada') #=> `method': wrong number of arguments (given 1, expected 0) (ArgumentError)`


## まとめ
名前も似ているし、可変長という点では挙動も似ているのですが、引数の渡し方は異なるので実装時は注意が必要でした。改めて理解ができた点はよかったです。
【Project Euler】Problem 56: べき乗の数字和

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 56. べき乗の数字和

原文 [Problem 56: Powerful digit sum](https://projecteuler.net/problem=56)

**問題の要約：自然数$a, b < 100$で$a^b$**の数字和の最大値を求めよ

数字和は「[Problem 16: 2のべき乗の数字和](https://qiita.com/masa0599/items/9ffe4d027df4b51ed906)」で作った**digitsum**を使いました。

```python
from itertools import product
print(f"Answer: {max([digitsum(a**b) for (a,b) in product(range(1,100), repeat=2)])}")
```

（開発環境：Google Colab）
Python3でUUIDを生成する

##はじめに
PythonでUUIDを生成する方法です。
本記事はPython3.8を使用しています。

uuidというモジュールを使ってUUIDを生成するのですが、
Python3では標準ライブラリとしてバンドルされているので、
importしてすぐに使用できます。

https://qiita.com/shimajiri/items/464275c5027ab09bc330

##UUIDとは
UUID（Universally Unique Identifier）とは、世界で同じ値を持つことがない一意な識別子です。


##バージョン1

```python
uuid.uuid1(node=None, clock_seq=None)
```

バージョン1は、時刻とMACアドレスを利用したUUIDで、
uuid1はホストID、シーケンス番号、現在時刻からUUIDを生成します。

```python
uuid.uuid1()
```

引数なしでも利用可能です。
nodeがなければuuid.getnode()で、ハードウェアアドレスを取得しそれが適用されます。 

clock_seqは、シーケンス番号として使われ、
なければ14ビットのランダムなシーケンス番号が生成され適用されます。

>uuid.getnode()
48 ビットの正の整数としてハードウェアアドレスを取得します。最初にこれを起動すると、別個のプログラムが立ち上がって非常に遅くなることがあります。もしハードウェアを取得する試みが全て失敗すると、ランダムな 48 ビットを、RFC 4122 で推奨されているように、マルチキャストビット (最初のオクテットの最下位ビット) を 1 に設定して使います。"ハードウェアアドレス" とはネットワークインターフェースの MAC アドレスを指します。複数のネットワークインターフェースを持つマシンの場合、全域管理されたMACアドレス (最初のオクテットの下位より2番目のビットが 設定されていない MACアドレス) が、他の個別管理アドレスよりも優先的に使用されます。この優先順序は保証されません。

:::note warn
コンピュータのネットワークアドレスを含むUUIDを生成するので注意が必要。
:::

##バージョン3, バージョン5

```python
uuid.uuid3(namespace, name)
uuid.uuid5(namespace, name)
```

バージョン3と5は、ドメイン名など何かしら一意な文字（バイト列）を用いたUUIDで、
uuid3はMD5ハッシュから、uuid5はSHA-1ハッシュからUUIDを生成します。

namespaceに名前空間識別子を指定して、それに沿った文字列を渡してUUIDを生成します。
namespaceでは以下を指定します。

`uuid.NAMESPACE_DNS`
name文字列に完全修飾ドメイン名を指定する。


`uuid.NAMESPACE_URL`
name文字列にURLを指定する。

`uuid.NAMESPACE_OID`
name文字列にISO OID（オブジェクト識別子）を指定する。

`uuid.NAMESPACE_X500`
name文字列にX.500 DNのDERまたはテキスト出力形式を指定する。




##バージョン4

```python
uuid.uuid4()
```
バージョン4は乱数により生成されるUUIDで、
uuid4はOS固有の乱数でランダムなUUIDを生成します。


# 使用例

```python:sample.py
import uuid

print(uuid.uuid1())
print(uuid.uuid3(uuid.NAMESPACE_URL, 'www.google.com'))
print(uuid.uuid5(uuid.NAMESPACE_URL, 'www.google.com'))
print(uuid.uuid4())

print(type(uuid.uuid1()))
```

実行結果

```
57aa71b8-7ead-11ec-932c-acde48001122
d407cf76-ed73-3579-959e-78c80e8d4579
c74a196f-f19d-5ea9-bffd-a2742432fc9c
b9f9b678-bce8-49a1-bca3-dbbc32259abf
<class 'uuid.UUID'>
```

##まとめ
ドキュメントにも書いてある通りなのですが、単純にUUIDを生成したいのであればuuid4を利用すると良いです。
ちなみにuuid2はRFC 4122で指定されておらず、このモジュールではサポートされていないようです。

##参考
https://docs.python.org/ja/3/library/uuid.html

https://ja.wikipedia.org/wiki/UUID

https://dev.classmethod.jp/articles/how-generate-uuid-python-uuid4/
UnityでビルドしたアプリをOculusQuest2で実行するまでの備忘録

主に[こちら](https://www.amazon.co.jp/dp/B097GBR2N3/)の書籍を参考に進めました

# Oculusアプリのインストール

下記リンク先でインストール
[GooglePlayStore](https://play.google.com/store/apps/details?id=com.oculus.twilight)
[AppStore](https://apps.apple.com/jp/app/oculus/id1366478176)

Oculusアカウントの作成にはFacebookアカウントが必須なので、持ってない場合は作成
[Facebook](https://www.facebook.com)

アプリを起動してFacebookログイン
ガイド通りにすすめて、ペアリング時には OculusQuest2 を選択

自分の場合、ここでぐるぐるがで続ける状態に
同じ状態になったら[こちら](https://moshiare.com/game/21061001/)で紹介されてる解決法が参考になるかも？
自分の場合はアプリの再インストールで解決しました...謎

そこからはガイドに従って進めれば、特につまづくところはないはず

# Oculusの開発者設定

※ Oculusアプリのバージョン: 145.1
1. 画面右下の「メニュー」を押下
2. 「デバイス」を押下
3. ヘッドセットの設定の「開発者モード」を押下

開発者登録済みの場合、ここでトグルが表示されているので有効にする
開発者登録していない場合、開発者登録の画面のリンクが表示されるので登録する
組織名はアプリを公開する際にストアで見えるものなので、公開したい場合はちゃんと考えた方がよさそう
登録処理はすぐ終わる

# OculusとPCの接続

Windowsの場合はADBドライバのインストールが必要らしいので、[こちら](https://developer.oculus.com/downloads/package/oculus-adb-drivers/)からインストールして解凍してandroid_winusb.infをインストール
(自分はMacなので不要だった)

HMDとPCをUSBケーブルで接続
Questの画面に「USBデバッグを許可しますか」というポップアップが出るので許可

# Oculus Developer Hub のインストール

PCからOculusに対してさまざまな操作を行うためのツール
下記リンク先でダウンロードしてインストール
Macは[こちら](https://developer.oculus.com/downloads/package/oculus-developer-hub-mac/)
Windowは[こちら](https://developer.oculus.com/downloads/package/oculus-developer-hub-win/)

インストールが完了したら、OculusDeveloperHubを開く
PCとUSBで接続しているOculusのデバイス情報がDeviceManagerに表示されてればOK

# UnityでアプリをビルドしてOculusで実行

※ Unityのバージョン: 2020.3.4f1

1. Unityでプロジェクトを作成
2. File > Build Settings で次のように設定
    1. 「Android」を選択して SwitchPlatform
    2. Texture Complession で「ASTC」を指定
3. Edit > ProjectSettings > Player の Androidタブ で次のように設定
    1. Other Settings > PackageName を任意の名前に変更(なんでもいい)
    2. Other Settings > Minimim API Level を「Android 6.0 "Mashmallow"(API Level 23)」に設定
2. Edit > ProjectSettings > Quality で次のように設定
    2. Pixel Light Count: 1
    2. Texture Quality: Fill Res
    2. Anisotopic Textures: Per Texture
    2. Anti Aliasing: 4x
    2. Soft Particles: 無効
    2. Realtime Reflections Probes: 有効
    2. Billboards Face Camera: 有効
2. Edit > ProjectSettings > XR Plugin Management で次のように設定
    2. Install XR Plugin Management ボタンを押す
    2. AndroidタブのOculusにチェックを入れる
2. SampleScene を次のように設定
    2. ヒエラルキーにある Main Cameraを右クリック > XR > Comvert Main Camera To XR Rig で XRRig オブジェクトを作成
    2. 適当にオブジェクトを設置する Cubeとか
2. File > Build Settings から Build
2. PCにQuestをUSB接続した状態で、OculusDeveloperHub の DeviceManager を開く
2. ビルドされたapkを DeviceManagerの画面のドラッグ＆ドロップ
2. Questにapkがインストールされる　(右上のApps一覧に表示される)
2. インストールしたアプリの「Launch」をクリック

すると、Questで先ほどビルドしたアプリが実行される
[aws-sdk S3] 署名付きURLの発行

業務でS3の署名付きURL(GetObject)を発行を行いました。
備忘録として残しておきます。

## 環境
Docker node:16-alpine
"typescript": "^4.5.4"
"@aws-sdk/client-s3": "^3.46.0",
"@aws-sdk/s3-request-presigner": "^3.47.0",


## 結論
```typescript:s3.ts
import {
  GetObjectCommand,
  S3Client,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const client = new S3Client({
  region: 'ap-northeast-1',
});

/**
 * 署名付きURLを発行する
 *
 * @param bucket
 * @param key
 * @param expiresIn
 * @returns 署名付きURL
 */
const getPresignedUrl = async (bucket: string, key: string, expiresIn: number): Promise<string> => {
  const objectParams = {
    Bucket: bucket,
    Key: key,
  };
  const url = await getSignedUrl(client, new GetObjectCommand(objectParams), { expiresIn });
  console.log(url)
  return url
};

export { getPresignedUrl }
```


## 前提
- IAMRole等の設定を行なって、対象のs3バケットに対して以下の権限があること

```JSON:
"Action": ["s3:GetObject"]
```
これで動かなかったら`s3:ListBucket`もいるかも

- 以下のコマンドを実行し、必要なパッケージをインストールしておくこと


```
> npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
```



## 解説
- 引数
    - bucket: URLを発行したいS3バケット
    - key: URLを発行したS3バケット内のオブジェクトキー
    - expiresIn: 署名を有効にしておきたい時間(単位は秒)

上記のコードを実行して、ブラウザ上でURLにアクセスすれば、ファイルがローカルにダウンロードされます。
参考記事の1つ目を参考にすれば、putObjectも同様にできそうですね〜。

参考
https://aws.amazon.com/jp/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_s3_request_presigner.html
NuxtでSassを入れるとビルドエラー　Node Sass version 7.0.1 is incompatible with ^4.0.0 || ^5.0.0.

#NuxtでSassを入れる

https://qiita.com/Fumy72676433/items/6451ce416ea5676c5aa9

👆を参考に

```console
$ npm install sass-loader node-sass --save-dev
```

sassを入れる

```console
$ npm run dev
```

うまく行くか確認してみる

```console
 ERROR  Failed to compile with 1 errors                                                       friendly-errors 22:13:28


 ERROR  in ./pages/phase1/index.vue?vue&type=style&index=0&id=45894c12&scoped=true&lang=scss& friendly-errors 22:13:28

Module Error (from ./node_modules/sass-loader/dist/cjs.js):                                   friendly-errors 22:13:28
Node Sass version 7.0.1 is incompatible with ^4.0.0 || ^5.0.0.
                                                                                              friendly-errors 22:13:28
 @ ./node_modules/vue-style-loader??ref--7-oneOf-1-0!./node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--7-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--7-oneOf-1-3!./node_modules/vue-loader/lib??vue-loader-options!./pages/phase1/index.vue?vue&type=style&index=0&id=45894c12&scoped=true&lang=scss& 4:14-406 15:3-20:5 16:22-414
 @ ./pages/phase1/index.vue?vue&type=style&index=0&id=45894c12&scoped=true&lang=scss&
 @ ./pages/phase1/index.vue
 @ ./.nuxt/router.js
 @ ./.nuxt/index.js
 @ ./.nuxt/client.js
 @ multi ./node_modules/eventsource-polyfill/dist/browserify-eventsource.js (webpack)-hot-middleware/client.js?reload=true&timeout=30000&ansiColors=&overlayStyles=&path=%2F__webpack_hmr%2Fclient&name=client ./.nuxt/client.js
```

:sob::sob::sob::sob::sob::sob::sob::sob::sob::sob:

#どうやらnode-sassが不要みたい

```console
$ npm uninstall node-sass

$ npm install sass
```

`node-sass`はすでにdeprecatedになっているので、uninstallして無くしましょう！

#参考

https://stackoverflow.com/questions/70281346/node-js-sass-version-7-0-0-is-incompatible-with-4-0-0-5-0-0-6-0-0
AWS CloudFormation ymlの設定 【VSCode】

#AWS CloudFormation ymlの設定 【VSCode】
VSCodeで CloudFormation を書く時にエラーが出ないようにする。
さらに補完してくれる設定も追加しています。
エディタから離れると自動保存する設定など、CloudFormation 関連以外もそのまま載せています。

VSCodeの便利な拡張機能を見つけたら随時追加します。

##setting.json 
```
{
    "files.insertFinalNewline": true,
    "files.trimTrailingWhitespace": true,
    "files.autoSave": "onWindowChange",
    "editor.formatOnSave": true,
    "workbench.list.openMode": "doubleClick",
    "workbench.editor.enablePreview": true,
    "editor.minimap.enabled": false,
    "breadcrumbs.enabled": true,
    "extensions.autoUpdate": false,
    "workbench.startupEditor": "none",
    "security.workspace.trust.untrustedFiles": "open",
    "editor.renderWhitespace": "boundary",
    "yaml.schemas": {
        "https://d33vqc0rt9ld30.cloudfront.net/latest/gzip/CloudFormationResourceSpecification.json": [
            "*.cf.yaml",
            "*.cf.yml",
            "*.cfn/*.yaml",
            "*.cfn/*.yml",
            "cloud*formation/*.yaml",
            "cloud*formation/*.yml"
        ]
    },
    "yaml.customTags": [
        "!Ref",
        "!Sub scalar",
        "!Sub sequence",
        "!Join sequence",
        "!FindInMap sequence",
        "!GetAtt scalar",
        "!GetAtt sequence",
        "!Base64 mapping",
        "!GetAZs",
        "!Select scalar",
        "!Select sequence",
        "!Split sequence",
        "!ImportValue",
        "!Condition",
        "!Equals sequence",
        "!And",
        "!If",
        "!Not",
        "!Or"
    ],
    "diffEditor.ignoreTrimWhitespace": false,
    "redhat.telemetry.enabled": true,
    "editor.tabSize": 2,
    "settingsSync.ignoredSettings": [
        "editor.detectIndentation"
    ],
    "editor.dragAndDrop": false,
    "editor.detectIndentation": false,
    "workbench.tree.indent": 16,
    "explorer.compactFolders": false
}
```
ファイヤウォールを開け方

#1.ファイヤウォールの80と443番ポートの明け方
Apacheの起動でよくファイヤウォールの開放を忘れることがよくある！

#2.環境
cent os7,8

#3.やり方
以下の文をコンソールに入れるだけ

80番ポート（http）の開け方

```
firewall-cmd --add-service=http --zone=public --permanent
firewall-cmd --reload
```

443番ポート（https）の開け方

```
firewall-cmd --add-service=https --zone=public --permanent
firewall-cmd --reload
```
Dirクラスを解説

ruby silverの勉強をしていく中で間違えたところがあったのでその解説記事を挙げていきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485775/5d1866cb-e2ee-9696-2a44-6e410ffa3447.png)


今回の記事では、詳しい説明は省略させていただきます。[公式ドキュメント](https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#singleton_method)を読んでみてください。

結論からいうと、正解は、Dir.pwd以外の選択肢すべてです。
1つ1つの選択肢を調べましたので、ぜひ参考にしてください！

##そもそもDirクラスとは
めちゃザックリいうと、ディレクトリを色々操作できる、というクラスです。
今回問題で使われているpwdメソッド、globメソッドを例に紹介していきます。

###pwdメソッド
現在のディレクトリを出力するメソッドなんですね。
pwd(print working directory)という正式名称なんですね。


###globメソッド
指定した文字列が入っているファイル名を出力してくれるメソッドですね。

##directory?メソッド
このメソッドは、ファイルがディレクトリのときにtrue、そうでないときはfalseで返してくれるんですね。
例えば、

```
FileTest.directory?('/app')
=> true
```
これは、Fileクラスなので、今回の問題では不正解になるんですね。

##chmod chownメソッド
これは、ファイルの編集権限を指定するときに、使えるメソッドだそうです。
ググってもあまりヒットしなかったのですが、Qiitaで検索すると多くヒットしたので、気になる方は調べてみてください
ちなみにこれは、Fileクラスのメソッドなので、今回の問題では不正解になるんです。

以上です。何か間違いがありましたら、ご教示いただけますと幸いです。

【参考記事】

https://www.sejuku.net/blog/14367

https://docs.ruby-lang.org/ja/latest/class/Dir.html
pythonでtiktokのデータ取得

#1. 前提
| 項目       |       名前 |   
|:-----------------|------------------|
| OS             |              mac os |
| python           |            python3 |

#2. ライブラリを導入
TikTokApiとplaywrightを入れる

```console
pip install TikTokApi
python3 -m playwright install
```
#３. s_v_web_idを取得
[TikTok](https://www.tiktok.com/)のページで検証を開いて、
applicationsタブ→cookies→s_v_web_idの値を取得する。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2509814/939c3e51-fd49-d323-8484-cc218dcf085a.png)

#３. ハッシュタグからユーザーIDとユーザー名を取得する
s_v_web_idをverifyFpに入れて実行する

```sample.py
from TikTokApi import TikTokApi
# s_v_web_idをverifyFpに入れる
verifyFp=''
api = TikTokApi.get_instance(custom_verifyFp=verifyFp, use_test_endpoints=True)

# 取得数
count = 1
# ハッシュタグ
hashtag = '切りすぎた'
result = api.by_hashtag(count=count, hashtag=hashtag)

for t in result:
    print('----------------------------------')
    print('ユーザーID : ' + t['author']['uniqueId'])
    print('ユーザー名　: ' + t['author']['nickname'])
    print('----------------------------------')
```
【Unity】丸ボタンを作る方法

Unityで丸い形のボタンを作る方法です。

こんなボタンです。

![Screen Shot 2022-01-26 at 22.02.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/769620e5-2cb8-a9f0-8d60-d77129923538.png)

# 実装方法
まずは、Hierarchyで右クリックをして、
UI > Button を追加します。

この時点で追加されたボタンはいつも見慣れたボタンです。

続いては、
Inspector > Image > Source Image の右に丸いボタンがあるのでそれをクリック

![Screen Shot 2022-01-26 at 21.59.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/126aebb0-8ebf-435c-ea55-2eb1b596f2f5.png)

Select Strip の一覧から「Knob」を選択します。

![Screen Shot 2022-01-26 at 21.59.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/4d50248b-d256-15f0-8d9e-88c86542ddd5.png)

すると先ほど追加したButtonが以下のような形になります。

![Screen Shot 2022-01-26 at 22.00.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/366dcca1-29e2-4c73-56ef-6b2bfa439f57.png)

これをサイズ変更で丸になるように修正します。

![Screen Shot 2022-01-26 at 22.00.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/d6123526-1f9a-3e06-fcfa-59b8814b7e74.png)

これで形が丸いボタンの完成です。

以上となります。
お読み頂き有難うございました。
Qiitaのタイトルは255字以内で入力する必要があります

# 目的
Qiita記事を探す時にわざわざ開かなくてもタイトルだけで疑問解消すれば良いなと思いましたが、果たしてQiita記事のタイトルは文字数までいけるのか知りたくて調査しました。

# 結果
タイトルの文字数は255文字でした。
なお、255文字を超えると
「タイトルは255文字以内で入力してください」と表示されます。
![スクリーンショット 2022-01-26 21.31.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6280/996b1c41-5ac7-b382-bddb-d72ba3370f29.png)

# 参考記事
- [Qiitaのタイトルの最大文字数が気になって調べていたら、デベロッパーツールがクラッシュした件](https://qiita.com/kurararara/items/f42385d996bd4347cdea)
- [タイトルって何文字まで書けるんだろう？って思ったので，適当に打って試してるんですが，本当にこれ何文字まで書けるんでしょう？調べても出てこないし，検証してみようというのがこの記事の趣旨です．はい，ここ・←ここで100文字目です！本当にどこまで書けるんでしょうね？一度これで投稿してみよう…→普通に全部表示されてたので，限界に挑戦してみましょうか．ええ，タイトルの文字数に上限がないのかってことですよ．もうここまで来たらとにかく打ち込むのみですよ．あ，いま投稿しようとしたら255文字以上はダメって言われてし(ry](https://qiita.com/liveasnotes/items/ab993db5c64b29d92ebb)
-
環境変数にアクセスする方法（Node.js）[メモ用]

##手順

* npm i dotenv でインストール
* rootディレクトリに.envファイルと.gitignoreを作成
* require('dotenv').config(); を記入
* .envファイルに他の人に知られたくない情報を書く （APYKEYなど）
* GitHub等にコードを公開する場合は .gitignoreファイルに.envを記載
* .envファイルの情報にアクセスする場合は process.env.につなげる


##コードで解説

外部に公開したくない情報を記載

```php:.env

MONGODB_URL=mongodb+srv://.....cluster0.ysnsu.mongodb.net/myFirstDatabase?retryWrites=true&w=majority

```


GitHub等にコードを公開する場合は .gitignoreファイルに.envを記載


```php:.gitignore
.env
```


```php:index.js

import express from 'express';
import mongoose from 'mongoose';

//どちらか記載
import dotenv from 'dotenv';
dotenv.config();

//or

require('dotenv').config(); 

```

.envファイルの情報にアクセスする場合は process.env.につなげる
例の場合は.envファイルのMONGODB_URLの情報にアクセス

```php:index.js

import express from 'express';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();


//アクセス
const MongoDB = process.env.MONGODB_URL

```
Postman でアクセストークンを自動更新する方法

# Postman は `refresh_token` を使ってアクセストークンを自動更新してくれない
ので、Pre-request Script で以下のように設定すると、
毎リクエストごとに更新スべきかチェックでき、必要だったら更新してからリクエストを送れるようにする。

使えるケースは限定的です。（認証が OAuth2 のときとか）

```js
var todayOfLastYear = new Date(new Date().getFullYear()-1, new Date().getMonth(), new Date().getDate()); // ここは適当。もし環境変数 OAuth_Timestamp に値がなければ使用される
var tokenTimestamp = pm.environment.get("OAuth_Timestamp"); // 前回 access_token を取得した日時
var expiresInTime = pm.environment.get("ExpiresInTime") || (1000 * 60 * 60) - (1000 * 60); // 前回の access_token の期限切れ日時（環境変数 ExpiresInTime がなければ 59 分で設定している。ここは自由）
var tokenDate = Date.parse(tokenTimestamp) || todayOfLastYear

if((new Date() - tokenDate) >= expiresInTime) {
   pm.sendRequest({
      url:  pm.variables.get("Auth_Url"), 
      method: 'POST',
      header: {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: {
          mode: 'urlencoded',
          urlencoded: [
            {key: "grant_type", value: "refresh_token", disabled: false},
            {key: "refresh_token", value: pm.environment.get("refresh_token"), disabled: false},
            {key: "client_id", value: pm.environment.get("client_id"), disabled: false},
            {key: "client_secret", value: pm.environment.get("client_secret"), disabled: false}
        ]
      }
  }, function (err, res) {
        pm.environment.set("access_token", res.json().access_token);
        pm.environment.set("OAuth_Timestamp", new Date());
        
        if(res.json().expires_in){
            expiresInTime = res.json().expires_in * 1000 - 60000; // res の expires_in から 1 分引いた時間にしている
        }
        pm.environment.set("ExpiresInTime", expiresInTime);
  });
}
```
エンドポイントで認証チェックする方法

RestAPIを提供する際にHTTPリクエストにカスタムヘッダーを付けてもらって、チェック処理を入れたい場合、脳死状態で書くと下記のようになると思います。

このようにならないイケてる方は以降を見なくても大丈夫ですよ:wink:

```py
from bottle import route, run, request, HTTPResponse
import json

@route('/version')
def version():
    """バージョン情報を返戻します。"""
    api_key = request.get_header('X-Api-Key')
    # ここでAPIキーのチェック
    if api_key == 'XXXXXXXX':
        resp = HTTPResponse(status=200, body=json.dumps({'version': '1.0.0'}))
        resp.set_header('Content-Type', 'application/json')
        return resp
    else:
        resp = HTTPResponse(status=401, body=json.dumps({'message': 'Illegal key'}))
        resp.set_header('Content-Type', 'application/json')
        return resp

if __name__ == "__main__":
    run(host="0.0.0.0", port=8080, reloader=True)
```

これでもチェックするという要件は満たしているのですが、チェック処理が複数あるとどうでしょう?
どんどん`if文`が入れ子になっていってソースコードの見通しが非常に悪くなってしまいます。

そこで、大活躍するのが`デコレータ`です。
デコレータについては本記事の下部にある参考をご参照ください。

## デコレータを使ったチェックの実装方法

FlaskでもBottleでも実装方法は一緒です。
コードがスッキリしましたね :tada:

もし複数のチェック処理が必要であれば`check_api_key`のようなデコレータを作ってエンドポイントに追加してください。
チェック処理は上から順に実行されますので、実行順序を気にされる場合は注意しましょう。

```python:Bottleの例
from bottle import route, run, request, HTTPResponse
import functools
import json

def check_api_key(f):
    """X-Api-Keyを検証します。"""
    @functools.wraps(f)
    def _wrapper(*args, **kwargs):
        api_key = request.get_header('X-Api-Key')
        # ここでAPIキーのチェック
        if api_key == 'XXXXXXXX':
            return f(*args, **kwargs)
        else:
            resp = HTTPResponse(status=401, body=json.dumps({'message': 'Illegal key'}))
            resp.set_header('Content-Type', 'application/json')
            return resp
    return _wrapper

@route('/version')
@check_api_key
def version():
    """バージョン情報を返戻します。"""
    resp = HTTPResponse(status=200, body=json.dumps({'version': '1.0.0'}))
    resp.set_header('Content-Type', 'application/json')
    return resp

if __name__ == "__main__":
    run(host="0.0.0.0", port=8080, reloader=True)
```

下記のようにHTTPリクエストを投げて動作確認しましょう。

```sh
curl -H "X-Api-Key: XXXXXXXX" http://localhost:8080/version
```

## 参考

- [Pythonのデコレータを理解するまで](https://zenn.dev/ryo_kawamata/articles/learn_decorator_in_python)
[C#]バイト数と文字数の比較で、漢字とひらがなの入力を制限する　英数字のみ

##やりたいこと
画面上で入力した値を、「登録」ボタン押したら、
データベースにデータを登録するという実装を行なっています。

データーベースのデータ型はVARCHARだけど、漢字とかひらがなとか登録して欲しくなく、
英数字だけにして欲しい！というときにどう入力値チェックをすれば良いのか、
良い方法を教えてもらったのでまとめます。

##漢字、ひらがなをはじくにはどうしたら・・？

最初は正規表現で 0~9とかA~Z以外が入ってたらエラーを出すようにしようかな〜とか、
それだと制限かけすぎな気がするから、漢字とかひらがなを検知してくれる何かないかな〜とか考えました。

##文字数とバイト数の比較で出来る

全然浮かばなかったので、少し感動しましたが、
結構使う技なのでしょうか・・・？


:point_up:ひらがな、漢字が入力されてた場合に、文字の長さとバイト数が一致しない。

```
TextBoxに「こんにちは」と入力された場合、
Shift_JISでバイト数をカウントすると「１０」になります。
一方、文字の長さ（Length)は、「５」
不一致です。
```

:point_up:英数字なら一致する。

```
TextBoxに「hello」と入力された場合、
Shift_JISでバイト数をカウントすると「５」になります。
一方、文字の長さ（Length)も、「５」
一致です。
```

if文書いて、不一致の時にエラーを出せば、漢字、ひらがなをはじけそうです。

##実装時、参考になる記事

https://csharp.programmer-reference.com/string-byte-count/

http://jeanne.wankuma.com/tips/csharp/textbox/textlength.html


##終わりに
VisualStudioのTextBoxのIMEモードで入力制御をかけて、
漢字、ひらがなの入力に切り替えできないようにしても、
他から値をコピペすると、TextBoxに値が入ってしまうのが気になります。。
データを入力することも多いとは思いますが、コピペすることも多いと思うので、
漢字、ひらがなのコピペはできないようにするとか無いものなんでしょうか。。。
【Ruby on Rails】ActionMailer deliver_laterのrspecについての検討

## 前提
メール送信処理はすべて`deliver_now`で書いていましたが、処理が重過ぎてタイムアウトするので`deliver_later`に書き直しました。
結果rspecが軒並み死にました。FFF...
まぁ、そのままではうまくいかんだろうなという予感はしていました。
ということで、rspecの書き方を検討します。

## deliver_laterのrspecとして有効そうなこと
`deliver_later`は`ActiveJob`の処理なので、`ActiveJob`に近いテストを書くことはできそうです。

- jobの登録有無
- jobの内容

あとは、メール送信処理を即時にすれば、メールの内容などのテストも可能です。
`deliver_later`のテストは正直rails側で担保されていると思うので、deliver_laterを即時に変えるテストは有効かと思ってます。
意外と、deliver_later用！っていうrspecは用意されていないようです。調べ方が悪いかもしれないので、ありましたら教えていただきたいです…。mm

modelのテストをjobの登録の確認。
controllerのテストは即時でメールを送信して、メールの内容を確認する。
という役割でテストを書きました。model, controllerで担保するテストの切り分けが未だにわかっていないです。

一応、メールの送信と内容の確認は統合テストに近いのでcontrollerで担保するのが良いかなと考えた結果です。
job登録と即時への変更のテストをmodelとcontrollerで二重で書いてもよいのですが、すでにrspecはほとんど出来上がっており、`deliver_later`に変えたことによる影響範囲は莫大だったので止めました。
というかこれだけの変更でもかなり骨が折れました。はじめから`deliver_later`にしておけばよかった。

## 実際に書いたrspec

同期処理をrspecで使うために以下を追記

```ruby:rails/spec/rails_helper.rb
ActiveJob::Base.queue_adapter = :test
```

modelのテストは、jobの登録確認なので以下のように書きました。
Mailerのactionで登録されるようです。

```ruby:rails/spec/models/test_spec.rb
context "trueの場合" do
  it "メールのjobが登録される" do
    expect {
      test.hoge_method(true)
    }.to have_enqueued_mail(HogeMailer, :send_mail)
  end
end
context "falseの場合" do
  it "メールのjobが登録されない" do
    expect {
      test.hoge_method(false)
    }.not_to have_enqueued_mail(HogeMailer, :send_mail)
  end
end
```

controllerのテストは、即時実行に変更しました。
beforeで`perform_enqueued_jobs`囲うと、即時で実行してくれました。
requestsの今までのテストを全部これで囲いました（戦慄）。

```ruby:rails/spec/requests/users_spec.rb
context "postした場合" do
  after { ActionMailer::Base.deliveries.clear }

  before do
    perform_enqueued_jobs do
      post "/users/send_mail"
    end
  end

  it "メールが送信される" do
    mailer = ActionMailer::Base.deliveries[0]
    expect(mailer).not_to eq nil
    expect(mailer.to[0]).to eq "test@dev.hogehoge.jp"
  end
end
```
これでrspecはオールグリーンになりました〜！

## その他
`enqueued_jobs[0][:args]`でもjobに登録された値を取ってきて内容に関してのテストができそうでした。
が、私の環境だとbccあたりしか入っておらず、paramsでmailerのactionに渡したものしか入ってないのかも？と思ってます。ここの処理が怪しいので調べてわかったことがあれば追記しようと思います…。
【M1 Mac】brewでPostgreSQLいれるのになんか苦労した

# 経緯

Intel MacからM1 Macに移行して、突如ローカルでポスグレが動かなくなった。

homebrewがApple Siliconに対応したらしいのでまずはその移行を行った。

その後、

1. brew install postgresql

起動させるもError

2. brew install postgresql@13

起動させるもError

（Version13で動いたひともいるらしい）

3. brew install postgresql@11

起動できた

# まとめ

まだ安定していないのか、Version 11だと起動できた。

Version 13だと動くと聞いてなかなかの時間を費やしてしまったので、同胞の方に届けば幸い。

バージョンいろいろ試すの大事・・・
【jQuery】追加した要素にon()のイベントが付与されない


jQueryを書いていて、追加したボタンのクリックイベントが発火しない事象に遭遇。
調べてみると、on()の書き方に問題があった...教訓も兼ねて記事に残します。

#本題#
例を挙げて説明します。
次のようなコードがあったとします。

```html:example.html
<div class='parent'>
    <button id='a'>
</div>
```
```javascript:example.js
$('button').on('click', function() {
    // イベント処理
});
```
ここにappendなど使ってhtmlにbutton要素を追加します。

```html:example.html
<div class='parent'>
    <button id='a'>
    <button id='b'>
</div>
```
id が 'a' のボタンは正常にexample.jsのクリックイベントが実行されます。
しかし、id が 'b' のボタンはクリックイベントが実行されません。

これはon()で対象としている要素が追加されたとしても、追加された要素にはイベントが付与されないためです。
そのため、画面読み込み時から存在する要素に対してon()を適用させる必要があります。

#対処法#

###① $(document).on()を使う###

$(document).on()を使うことで追加要素にもイベントを付与できます。

```
$(document).on('イベント', '要素', '処理');
```

前述の例に適用すると下記になります。

```javascript:example.js
$(document).on('click', 'button', function() {
    // イベント処理
});
```

###② 親要素を指定する###

画面読み込み時から存在する親要素を指定し、その子要素に対してイベントを付与することで追加された要素でもイベントが発火します。

```
$('親要素').on('イベント', '子要素', '処理');
```

前述の例に適用すると下記になります。

```javascript:example.js
$('div').on('click', 'button', function() {
    // イベント処理
});
```

---
参考になれば幸いです。

#参考文献#
jQueryでclickイベントが効かない場合の対処法！
https://qumeru.com/magazine/401
【初心者向け】AWSでどのようなバックアップ設定をすべきか

# はじめに
AWSの利用にあたって、バックアップの取得はユーザーの責務となります。
自分たちで、自分たちの要件のもと、設定する必要があります。
近年、AWS Backup(*)の登場によって一元的に設定可能になりましたが、より適切なバックアッププランを検討・選択するには、概要を知っておいた方がいいので、簡単に解説しておきます。

(*) AWS Backup
AWS Backupとは、対応するサービスインスタンスのバックアップを一元的に管理するサービスです。
AWSの各サービスではBackupの仕組みは提供されているものの、以前は自動化するには、[こんな感じ](https://qiita.com/pict3/items/9fab02438dc22c0b85ea)で実装する必要がありました。

AWS Backupの登場により、複雑な独自要件がない限りは、自前実装がお役御免になりました。
当初は、マルチリージョンやタグなどの機能がなかったり、対応サービス数が少なかったのですが、今となっては非常に幅広い要件に対応しています。

# リテンションポリシー
データ管理要件において、バックアップのリテンションポリシー（保管に関する仕様）を定義することがほとんどです。
バックアップのリテンションポリシーは、期間と世代管理(間隔)の概念があります。

以下に例示します。
言い換えれば、24時間ごとに72時間まで確保するとも言えます。
![バックアップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51320/99a3770a-9206-a488-7702-25caeae90cf7.png)

当然、短い間隔で長期間保管すると、より求める状態に近い復元が可能になる確率が上がりますが、コストは上がります。
要件をもとに落とし所をつけましょう。

ただし、AWSの場合、バックアップは差分バックアップ方式が暗黙的に実現されています。
そのため、世代数の等倍でストレージ費用が増えるのではなく、変更量に応じたコスト増になります。この辺りはクラウドの恩恵を非常に感じるところです。

少し踏み込んだ話になりますが、RDSのリテンションポリシーには少し戸惑われる可能性があるポイントがあるので補足しておきます。
RDSのバックアップは、頻度と期間で設定します。
この期間には注意が必要です。停止中の時間は含みません。
したがって、頻度：毎日、期間：3日間の設定をしていた場合、常時起動のインスタンスであれば、３世代のバックアップになりますが、一時的な停止を行ったインスタンスについてはより多くのバックアップが作成されます。
ただし、先述のとおり、差分バックアップ方式のため、コストの観点では心配ご無用です。

本件はドキュメントにも記載されています。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html#USER_WorkingWithAutomatedBackups.BackupRetention


# 冗長化の種類と目的
私が知る限り、AWSでのBackupで保存するバックアップファイルは、裏側ではS3で保存されています。
S3自体が冗長化されているため可用性が高いのですが、より可用性を上げるために、マルチリージョンとマルチアカウントといった選択肢がとれます。
それぞれについて、どんな目的で設定するのかを紹介します。

## マルチリージョン
S3による冗長化は、リージョン内で行われています。
リージョン障害に備えておくには、別のリージョンにバックアップを複製しておく方が安全です。
リージョン障害の内容によりますが、状況によっては、せっかくバックアップをとっていても、そのバックアップファイルにアクセスできずに、DRを実行できないというようなことが起こりえます。

![Region Disaster.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51320/dccf86de-b748-49a1-1acf-771c0c9624b7.png)


## マルチアカウント
アカウントを間違って削除してしまう。
ありえないように思われるかもですが、想定されるミスは実際に発生する可能性があります。
必要に応じて、バックアップ専用のアカウントに集約保管する戦略も検討しましょう。

![Account Trush.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51320/f1a0d2b9-5c45-f9da-286c-becf10cfabcd.png)


# まとめ
RDSのスナップショット保管について、今更ながら知ったことを契機に、改めてバックアップに関する基本的な考え方を書いてみました。
AWSでは、オンプレよりもお手軽に、さまざまな形のバックアップを取ることができるため、要件に応じて適切なバックアップ戦略をとりましょう！
elasticache備忘録

・設定エンドポイントとノードエンドポイントについて（memcached）
・memcacedかredisか
・リーダーエンドポイント（redis）
・redisのクラスタ構成に関して


・設定エンドポイントとノードエンドポイントについて（memcached）

ノードがダウンしてしまうとアプリ側でノードエンドポイントを書き換えなくてはいけないので大変
→クラスターで設定エンドポイントを設けることでその辺をうまくやってくれる（詳しくは自動検出の動作を見てください）

https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/mem-ug/AutoDiscovery.HowAutoDiscoveryWorks.html

一方でこの原理ならばノードエンドポイントに直接アクセスすることも可能だが、設定エンドポイントをアプリ側のエンドポイントに設定することが望ましいと考えられる

・memcacedかredisか
この記事にもある通り基本的には機能が充実しているredisを使った方がよさそう・・・
しいて言うならmemcachedがマルチスレッドなのでredisよりも処理が早いくらいですね
https://dev.classmethod.jp/articles/which-choice-redis-memcached/

redisとmemcacedの比較図を見てもredisがすぐれているといえそうですね（udemyサイトから引用）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/82502ce7-b9e2-a2f8-44b0-a71ca4f3cc9e.png)

・リーダーエンドポイント（redis）

elasticacheの読み込みを行う際にアプリ側で複数のエンドポイントを管理する必要がありましたがリーダーエンドポイントというのが誕生したおかげで単一のエンドポイントを管理すればよくなりました。これは便利そう。
memcacedでいう設定エンドポイント的な利便性を感じます
https://aws.amazon.com/jp/about-aws/whats-new/2019/06/amazon-elasticache-launches-reader-endpoint-for-redis/

・redisのクラスタ構成に関して
Blackbeltとかほかのサイト見てまとめてみました。「ほーん」こんな感じねくらいの認識が欲しい方は是非参考に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/c03fe066-7721-45f5-dc83-38fcca2e22cf.png)



https://d1.awsstatic.com/webinars/jp/pdf/services/20171214_AWS-Blackbelt-ElastiCache.pdf
https://christina04.hatenablog.com/entry/redis-cluster
【N+1問題】ループ処理の中でクエリを実行しない！

##N+1問題

ループ処理の中でクエリを実行しない！
大量のクエリが発行されるのでめちゃくちゃ重くなるので、
ループを実行する前にあらかじめデータ取得しておく。

####良くない例

```ruby
books = Book.all

book_names = []
books.each do |book|
  book_names << BookSynopsis.find_by(book_id: book.id).name
end
```

####良い例

```ruby
book_synopsis = Book.includes(:book_synopsis)

book_names = []
book_synopsis.each do |book_synopsis|
  book_names << book_synopsis.name
end
```


##参考

https://qiita.com/shizen-shin/items/fffdf57feda979efb5d9
【Nuxt.js×Firebase】デプロイする方法

#はじめに
こんにちは！
今回はデプロイの仕方についてアウトプットしていきます！


#実践
ターミナルに以下の順番で記述する

```
npm run build
```

```
firebace deploy --onry hosting
```

#まとめ
今回はデプロイする方法についてアウトプットしました。

今後も引き続きQiitにポートフォリオ制作での学びをアウトプットしていきます！

今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

最後までご愛読ありがとうございました！
Ruby on Rails 7でselect2を導入方法

[Webpackerの場合はこちらの記事です](https://qiita.com/YutoYasunaga/items/5cbbd546f51d8b37dac8)

## select2とjQueryインストール

```
yarn add select2 jquery
```

## select2 コントローラー作成

```javascript:app/frontend/controllers/select2_controller.js
import { Controller } from "@hotwired/stimulus"
import $ from 'jquery';
import 'select2/dist/css/select2.min.css'
import Select2 from "select2"

export default class extends Controller {
  connect() {
    Select2()
    $('.js-select2').select2()
    // select2ドロップダウンをクリックすると入力フィールドにフォーカスする
    $(document).on('select2:open', () => {
      document.querySelector('.select2-search__field').focus();
    });
  }
}

```

```javascript:app/frontend/controllers/index.js
import Select2Controller from "./select2_controller"
application.register("select2", Select2Controller)
```

```javascript:app/frontend/entrypoints/application.js
import '../controllers'
```

## viewsで適用

select2を使いたいセレクトボックスに `data-controller="select2"`とCSSクラス`js-select2`を適用

```slim:*.html.slim
      div data-controller="select2"
        = f.input :product_id,
          collection: Product.all,
          include_blank: false,
          input_html: { class: 'js-select2' }
```

## 任意：スタイルを改善する

```scss:app/assets/stylesheets/select2.scss
$select2-height: 38px;

.select2-container {
  .select2-selection--single {
    height: $select2-height;
    line-height: $select2-height;
    .select2-selection__arrow, .select2-selection__rendered {
      height: $select2-height;
      line-height: $select2-height;
    }
  }
  .select2-search--dropdown .select2-search__field {
    font-size: 16px;
    padding: 4px;
  }
}
```
Go: 接種状況ダッシュボードのデータを使ってワクチン接種済者をカウントする

こちらで行ったのと同じ計算を Go で行いました。
[Python3: 接種状況ダッシュボードのデータを使ってワクチン接種済者をカウントする](https://qiita.com/ekzemplaro/items/e892ab821eef343d4860)

```go:count_vaccination.go
// ----------------------------------------------------------------
//
//	count_vaccination.go
//
//					Jan/26/2022
//
// ----------------------------------------------------------------
package main 

import (
	"fmt"
	"os"
	"log"
	"encoding/csv"
//	"reflect"
	"strconv"
	"time"
) 

// ----------------------------------------------------------------
func get_day_6months_proc () string {
	now := time.Now ()
	fmt.Printf ("%s\n" ,now)
	today := strconv.Itoa (now.Year()) + "-" +
		fmt.Sprintf ("%02d",now.Month()) + "-" +
		strconv.Itoa (now.Day())

	t3 := now.AddDate (0,0,-184)
	day_6months := strconv.Itoa (t3.Year()) + "-" +
		fmt.Sprintf ("%02d",t3.Month()) + "-" +
		strconv.Itoa (t3.Day())

	fmt.Println(today)
	fmt.Println(day_6months)

	return	day_6months
}

// ----------------------------------------------------------------
func count_proc(record [][]string,day_6months string){
	llx := len(record)

	second := 0
	second_6months := 0
	third := 0


	for it := 1; it < llx; it++{
		ss,_ := strconv.Atoi(record[it][2])
		second  += ss
		tt,_ := strconv.Atoi(record[it][3])
		third  += tt
		if (record[it][0] < day_6months){
			second_6months += ss
			}
	}

	fmt.Printf ("second = %d\n",second)
	fmt.Printf ("second_6months = %d\n",second_6months)
	fmt.Printf ("third = %d\n",third)
}


// ----------------------------------------------------------------
func main (){
	fmt.Fprintf (os.Stderr,"*** 開始 ***\n")

	file_csv := os.Args[1]
	fmt.Printf (file_csv + "\n")

	ff, err := os.Open(file_csv)
	if err != nil {
		log.Fatal(err)
	}

	rr := csv.NewReader(ff)

	record, err := rr.ReadAll()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%#v\n", len(record))
//	fmt.Println(reflect.TypeOf(record))

	day_6months := get_day_6months_proc()

	count_proc(record,day_6months)

	fmt.Fprintf (os.Stderr,"*** 終了 ***\n")
}

// ----------------------------------------------------------------
```

実行結果

```text
$ go run count_vaccination.go summary_by_date.csv
*** 開始 ***
summary_by_date.csv
290
2022-01-26 19:50:18.261192179 +0900 JST m=+0.000425766
2022-01-26
2021-07-26
second = 93846301
second_6months = 29646353
third = 2892327
*** 終了 ***
```
5分でPHPUnitをGitHub Actionsで動くようにする

5分は誇張ですが…
サクッとPHPUnitをGitHub Actionsで動かす際のメモ

### Step1 PHPUnitを動かす
[PHPUnitのGetting Started](https://phpunit.de/getting-started/phpunit-9.html)を参考にして

#### composerでPHPUnit追加

```shell-session
composer require --dev phpunit/phpunit ^9
```

#### composer.jsonにautoloadの設定を追加

```json:composer.json
{
    "autoload": {
        "classmap": [
            "src/"
        ]
    },
    "require-dev": {
        "phpunit/phpunit": "^9"
    }
}
```

#### テスト対象とテストコードを準備
[Getting Started](https://phpunit.de/getting-started/phpunit-9.html)にある、src/Email.phpとtests/EmailTest.phpをコピペすればOK

#### PHPUnit実行
↑まで終わったら

```
./vendor/bin/phpunit tests
```
で、PHPUnitが動くはず。

### Step2 GitHubActionsで動かす
後は、
.github/workflows/に適当な名前でyamlを作成してあげて

```build.yml
name: Build
on: push

jobs:
  phpunit:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - run: composer install
      - run: ./vendor/bin/phpunit tests

```

な感じに書いて、リポジトリにPush
以降はpushするたびにActionsが動いてテストされる

### 最終的な構成

```shell-session
$ tree -a -I '.git|vendor|LICENSE|README.md|.gitignore|.phpunit.result.cache' 
.
├── .github
│   └── workflows
│       └── build.yml
├── composer.json
├── composer.lock
├── src
│   └── Email.php
└── tests
    └── EmailTest.php

```
Chakra UI × react-shareでシェアボタンを作る

こんにちは！ミヤケイと申します。

今回はReactのコンポーネントライブラリである**「Chakra UI」**を用いて以下のようなFaceBook、Twitterのシェアボタンを作成していきます！

![スクリーンショット 2022-01-26 18.16.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644040/71e43dff-9768-de6d-3e0d-dcbf9e25cbf3.png)

ちなみに標準のreact-shareだと丸いボタンのみ用意されています。
![スクリーンショット 2022-01-26 18.32.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644040/58e022d5-58b2-a442-e824-25d1be00bd78.png)
こんな感じ。サイトでよく使われているような**長方形デザインのボタン**を以前作成したため、共有したいと思い今回執筆に至りました！


では早速作っていきましょう！

#必要なパッケージをインストールする
Chakra UIの導入手順は省いているため、もしまだインストールされていない場合は[こちら](https://chakra-ui.com/docs/getting-started)を参考に導入していただけたらと思います！

###【react-shareのインストール】
npmの方！

```
npm i react-share
```

yarnの方！

```
yarn add react-share
```

###【react-iconsのインストール】
npmの方！

```
npm i react-icons --save
```

yarnの方！

```
yarn add react-icons
```

#実際にボタンを作ってみよう！
インストールが完了したらファイルを作成し、呼び出してスタイリングしましょう！

###Twitterシェアボタン
```react
import React from 'react'
import { Box } from '@chakra-ui/layout'
import { TwitterShareButton } from 'react-share'
import { FaTwitter } from 'react-icons/fa'

type Props = {
  url: string
}

export const TwitterShareBtn: React.VFC<Props> = ({ url }) => {
  return (
    <TwitterShareButton
      url={url}
      style={{
        display: 'flex',
        padding: '0 12px',
        height: 18,
        background: '#359BF0',
        borderRadius: 10
      }}
    >
      <Box p={0.8}>
        <FaTwitter color={'white'} />
      </Box>
      <Box as="span" ml={2} fontSize={12} textColor={'white'} p={0.8}>
        ツイート
      </Box>
    </TwitterShareButton>
  )
}
```

###FaceBookシェアボタン
```react
import React from 'react'
import { Box } from '@chakra-ui/layout'
import { FacebookShareButton } from 'react-share'
import { FaFacebook } from 'react-icons/fa'

type Props = {
  url: string
}

export const FaceBookShareBtn: React.VFC<Props> = ({ url }) => {
  return (
    <FacebookShareButton
      url={url}
      style={{
        display: 'flex',
        padding: '0 12px',
        height: 18,
        background: '#1877f2',
        borderRadius: 4
      }}
    >
      <Box p={0.5}>
        <FaFacebook color={'white'} size={14} />
      </Box>
      <Box as="span" ml={2} fontSize={12} textColor={'white'} p={0.8}>
        シェア
      </Box>
    </FacebookShareButton>
  )
}
```

2つのボタンのコードを添付しましたが共通して言えることは
・「react-share」のボタンを呼び出してChakra UIのBoxタグでスタイリングする。
 (```<div>```タグと同じ認識でいいかと思います！)

・「react-icons」からSNSのアイコンを呼び出してサイズ、色を変更する。
です！


Chakra UIはコンポーネントのpropsの値に直接style属性を書くだけで**直感的にデザインが出来る**ため楽しいですね！

※TypeScriptを導入していない方はtype Props〜は省略して結構です👍

#まとめ
無事にアイコンは作成出来ましたでしょうか？
駆け足にはなりましたが今回はChakra UI × react-shareでシェアボタンの作成を紹介しました！もしいいなと思ったら**LGTM*いただけると励みになります！

**_Happy Hacking!!!!_**
Tomcatのサーバ状態をPowerShellでテキスト取得する

##はじめに
Tomcatの稼働状況をモニタリングしたいと思い
まずは、ステータス画面の情報をダウンロード。

↓以下の画面ですね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/487ef106-4a01-967a-52cd-6316a72fb535.png)

★環境
Windows10
PowerShell


##内容
・tomcatの設定
マネジャー画面にアクセスできるユーザを作成する。

「tomcat-users.xml」ファイルを開き以下2行を追加。
ここでは説明のため「admin」ユーザとする

```
  <role rolename = "manager-gui"/>
  <user username="admin"  password="admin" roles="manager-gui"/>
```


・PoerShellのファイルを作成する
　内容は以下

```
$baseurl="http://127.0.0.1:8080/manager/status/all"

$USER = "admin"
$PASS = "admin"
$mytime = Get-Date -Format "yyyyMMddhhmm" #ファイル名のタイムスタンプ
$Destination　= "C:\bat\test_" + $mytime + ".html"  #保存先フォルダとファイル名

# 認証用にCredentialを作成
$secpasswd = ConvertTo-SecureString $PASS -AsPlainText -Force
# ID,PASSを設定
$cred = New-Object System.Management.Automation.PSCredential($USER, $secpasswd)

# URL開いてダウンロードする
Invoke-WebRequest -Uri $baseurl  -Credential $cred -OutFile $Destination
```
上記のファイルをタスクスケジューラで自動実行させる。

###Busyスレッド数をテキストファイルにログ出力する
以下を追記。

```
#ファイルから文字列検索して結果を変数に
$Str = Select-String "Busyスレッド： [0-9]" $Destination -Encoding UTF8 | ForEach-Object { $_.Matches.Value }

$Str = $mytime + ' ' + $Str
#ファイルから文字列検索して結果をテキストファイル書き込み
Write-Output $Str | Out-File Tomcat-BusyLog.txt -Append | Set-Content -Encoding UTF8
```


##履歴
2022/1/26 作成
2022/3/27 ログ出力追記