OmniAICreator/Qiita-1.07M huggingface dataset:
電源ONか再起動時、RTSPストリーミングを自動で実行開始する方法

#はじめに
　v4l2rtspserverを電源ONか再起動時に自動で実行開始するように設定する方法を記します。

#使用した開発環境＆実行環境

+ Raspberry Pi zero W
+ Raspberry Pi Imager v.1.6.2 で標準的なOSを64GBのSDカードに書き込んだ
+ HDMI入力→CSI2変換基板
+ v4l2rtspserverはmake installで入っている


# サービスファイルのコピー
```
$ sudo cp /usr/lib/systemd/system/v4l2rtspserver.service /etc/systemd/system
```
※必要ならviなどテキストエディタでv4l2rtspserver.serviceファイルを編集しておく。
# サービスの登録
```
$ sudo systemctl daemon-reload
$ sudo systemctl enable v4l2rtspserver
```
# 再起動
```
$ sudo reboot
```
これでストリーミング再生可能な状態。
ポート番号などを明示的に指定したい場合は、.serviceファイルをテキストエディタで修正後、登録/再起動実行。


# 参考URL

https://qiita.com/karaage0703/items/ed18f318a1775b28eab4

https://minicode.dev/archives/129
【問題解決方法】エラー範囲を確認してから調べ始める！

#はじめに

気づけば社会人になって半年が経とうとしています。
入社してからこれまで、SIerとしてシステムの設計と構築を行ってきました。
その中で、問題解決能力が自身に足りないことを強く感じました。
また、問題が起きた時、対応方法を調べる前にやるべきことがあることに気づきました。

そこで、問題が起きた時の対応手順をまとめました。
この記事での「問題」とは、コマンドの実行時やサービス利用時に発生するエラーのことを指します。

以下、エラーが起きた時の対応方法をまとめます。

#エラー原因を調べ始める前の手順

**１．エラーが起きる**

自身の作業中や、作業を依頼した先などでエラーが起きることがあります。

**２．エラー状況を確認する**

エラーが起きると、使っているサービスごとにエラーメッセージが表示されます。
作業を依頼している場合には、人伝にエラー状況が報告されます。
人伝に報告された場合は、担当者に追加で状況の説明を求める必要があるかもしれません。

**３．エラーが起きている範囲を確認する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/f2186c91-edbd-f294-2410-f1da87652c98.png)

早速エラーに対応していきたいところですが、その前に確認することがあります。
それは、エラーが起きている範囲が自身の要件範囲内であるかどうかです。

もし、要件の範囲外であれば、対応を担当者に投げます。
投げるときに、自身ができるサポートを伝えるとよいと思います。

**４．解決までにかかる時間を見積もる**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/d818b14a-28ab-55eb-7606-00634eb11e14.png)

エラーが自身の作業範囲内であると確認できた場合は、対応しなくてはなりません。
しかし、対応する前にまだ確認することがあります。
それは、時間内に解決できるかどうかです。

調べ始めてわかることもあるかと思いますが、先のスケジュールも考え、早めに解決できそうかは判断しておきたいです。

もし、時間内に解決できなさそうであれば、対応を他者と相談する必要があります。
相談結果によっては、別で作業時間が設けられたり、別担当者が就くかもしれません。

時間の見積もり方法は色々あります。

https://qiita.com/syobochim/items/2b95fb669f0dfe5928f8

**５．エラー原因を調べ始める**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/a21c7a7c-565c-6549-5760-65ff3e25e32f.png)

こうしてやっとエラーを調べ始めることができます。

エラー原因を探る際には、先入観を持つことが何よりも危険であると思っています。
エラーが発生すると、まずサービスが表示するエラーメッセージを確認します。
エラーメッセージには、なぜエラーが起きたのかや、親切な場合には対処方法が書かれています。
しかし、その内容をうのみにするのは危険だと思っています。
根本的な原因が潜んでいる可能性があるからです。

そのため、私はまずエラー文をそのままにブラウザで検索をかけます。
すると、全く同じエラーが起きている人がいたり、その解決策が載っている場合があります。
解決策が出てこない場合は、エラー文のキーワードを抽出して再度検索します。

https://qiita.com/

https://ja.stackoverflow.com/

それでも、どうしてもわからない場合は有識者に聞いたり、方針転換したりといった対応になります。


**６．解決策を基にエラーを解決する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/9de7e287-bc98-7af7-6e02-d66b1a401777.png)

解決策がわかった場合は、その方法を実践することを考えます。
しかし、何も考えず実践すると、後で痛い目に会うかもしれません。
もしかしたら、解決策による変更はシステムへの影響が大きく、新たな問題を引き起こしてしまうかもしれません。
そのため、解決策を実施する前には、変更内容と影響を理解しておく必要があると思います。
解決策の内容を理解しておくことは、他の作業者へ事態の説明をする際に役立ちます。

また、スケジュールも頭に入れて作業しなくてはなりません。
たとえ、解決策がわかり、実践もうまくいきそうなときでも、スケジュールに間に合わなければ問題になります。
スケジュールを調整しながら問題に取り組めるとよいと思います。

#スムーズにエラーに対応するために心がけること

エラーを調べ始める前に色々やることがある以上、日ごろから準備が必要だと思います。
心がけることとしては、自身の作業領域と進捗をはっきりさせておくことです。
こうしないと所々で不明確になってしまい、問題が起きた時、原因が特定できなかったりやり直しになったりします。

#おわりに

私はエンジニアとしてまだまだできていないことがあると考えさせられました。
良い仕事に近道はないんだなーと思う日々です。
今後とも頑張ります。
メソッドにおいての引数と返り値

◾︎ メソッドにおいて引数と返り値は非常に重要な役割をしている。
　
まず初めにメソッド内と外で領域が展開させれいるルールを頭に入れてもらいたい。その中でこの領域に値を打ち込む際に必要になってくるのが、引数と返り値である事。引数と返り値を定義する時、名前に関して好きな名前をつけて良い。

今回は短いが大事な要素なので書かせていただきました。

wagaでした。
EmbulkでRDS→S3へ転送する際に、Access key,Secret keyを使わず、IAMロールを使う

## What's this~これは何~
[こちらの記事](https://qiita.com/namely_/items/f67ac0268a189b6f8da7)で、S3 API callを行う際に、IAMユーザーを作成し、Access key,Secret keyを設定ファイルにベタ書きしていたのですが、やはりこれはセキュアとは言えないなと感じておりました。

冷静に考えてみたら、IAMロールでできないはずがないよな、となり、方法を探してみました。

今回は、IAMロールを使ってS3 API callを行いました。

## 前回との相違点

Access key,Secret keyをコメントアウトしています。
AmazonS3FullAccessをポリシーとして、IAMロールを作成し、EC2へアタッチしています。
auth_method: instanceを追加しています。
これでインスタンスプロファイルを見に行ってくれます。

```
/// Embulk設定ファイル編集
/// configファイル作成する。ディレクトリなども適当にconfigファイルを作成する。
/// yamlファイルは空白の数を間違えると、エラー吐くので注意。
vi embulk_mysql/config.yml

 in:
   type: mysql
   user: "admin"
   password: "パスワード"
   database: "test_"
   table: "item"
   host: "RDSエンドポイント"
   parser:
    type: json
 out:
   type: s3
   path_prefix: mysql/out(任意の名前を設定)
   file_ext: .json
   bucket: バケット名
   endpoint: s3-ap-northeast-1.amazonaws.com(使用しているS3のリージョンに合わせる)
   #access_key_id: アクセスキー
   #secret_access_key: シークレットアクセスキー
   formatter:
    type: csv
   auth_method: instance
```

## 総括
メモではありますが、どなたかの手助けになれば幸いです。
どこか変な点、誤まり等あればコメントでお知らせいただければ助かります。

## 参考

```
https://github.com/embulk/embulk-input-s3
https://dev.classmethod.jp/articles/do_you_know_iaminstanceprofile/
https://techblog.lclco.com/entry/2018/04/03/080000
```

参考にさせていただきました。ありがとうございます。
logger.debugの使い方

##環境
Rails 6.1.3.2
ruby 2.7.1

##使い方
1. Controllerなどオブジェクトの中身を見たい箇所に下記を書く
（1行目と3行目はログを出力したときの見やすさのために書いた）
配列やハッシュを扱うときはinspectメソッドを使うとより中身が見やすい

```rails
logger.debug '-------------------'
logger.debug (中身を見たいオブジェクト).inspect
logger.debug '-------------------'
```

2. ターミナルなどで下記コマンドを叩く

```ターミナル
$　tail -f log/development.log
```


##参考

https://railsguides.jp/debugging_rails_applications.html#inspect
Workato：SlackでトリガーとなったメッセージのURL（パーマリンク）を取得するには

以下のようなSlackイベントをトリガーとしたレシピにおいて、トリガーとなったメッセージのURLを取得したい場合があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8d5a755d-f412-a565-5275-2566e9f1b17a.png)

# 手順

WorkatoでSlackメッセージのURLを取得するには、SlackコネクターのCustom Actionを利用して、次の通り設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/251050c6-5474-85b0-b778-4e2a25116b6b.png)

## Action name
任意の名称

## Method
GET

## Path
chat.getPermalink

## Response type
JSON response

## Response URL parameters
それぞれ次の通りフィールドを追加

### channel
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/dc119627-41db-cfe6-b6ac-af4666b5c461.png)

### message_ts
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/1a29a184-4b41-2bbd-63a4-7c921a47d45c.png)

トリガーのレスポンスを利用する場合は、次の通りデータピルよりセットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/a4c9f7bb-446b-e199-8292-3c4f2c1cccf9.png)

## Response body
以下のページの「Example responses」の『Common successful response』を利用してスキーマを作成します。

https://api.slack.com/methods/chat.getPermalink

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/cdda548c-27e0-45d8-8ef1-1989ff9c2b21.png)

※ スキーマの作成手順を以下を参照ください。

https://qiita.com/tabimoba/items/ce4215eda99b23d73828

# 参考

https://api.slack.com/methods/chat.getPermalink
【Ruby】filter / detect / mapの違い

##filter
要素に対して{}内が真であった要素を全て含む**配列**を返す
真になる要素がひとつもなかった場合は空の配列を返す

```ruby
[1, 2, 3, 4, 5].filter { |num| num.even? }
# => [2, 4]

[1, 3, 5].filter { |num| num.even? }
# => []
```

https://docs.ruby-lang.org/ja/latest/method/Array/i/filter.html

##detect
要素に対してブロックを評価した値が真になった**最初**の要素を返す
真になる要素が見つからない場合はnilを返す

```ruby
[1, 2, 3, 4, 5].detect { |num| num.even? }
# => 2

[1, 3, 5].detect { |num| num.even? }
# => nil
```

https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/detect.html


##map
各要素に対してブロックを評価した結果を全て含む**配列**を返す

```ruby
 [1, 2, 3, 4, 5].map { |num| num.even? }
# => [false, true, false, true, false]
```

https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/collect.html
【Vue.js】条件分岐について

#はじめに
こんにちは。
Vue.jsの条件分岐についてアウトプットしていきます！

##条件分岐（v-if,v-else）
真偽値により表示と非表示を切り替えることができます。

trueのときに`GOOD`、falseのときに`OK`と表示させる処理を記述します。


```html:HTML
<div id="app">
  <h2> "{{ toggle }}"のとき </h2>
  <p v-if="toggle">
    GOOD
  </p>
  <p v-else>
    OK
  </p>
</div>
```

```javascript:Vue.js
var app = new Vue({
  el: '#app',
  data: {
    toggle: true
  }
})
```
<img width="400" alt="true" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/21c1fb02-d21d-7cbc-686c-d36a38a9dceb.png">

<img width=“300” alt="false" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/9f35449f-bc81-b5aa-3869-e743d1abc272.png">

上記のように真偽値によって表示・非表示を切り替えることができる。ただし、正常に動作させるにはv-ifの直下にv-elseを配置する。

<br>

##複数の条件分岐（v-else-if）
JavaScriptのelse-ifのように、複数の条件分岐も処理できる。

```html:HTML
<div id="app">
  <p v-if="foods === 'tofu' ">tofu</p>
  <p v-else-if="foods === 'egg'">egg</p>
  <p v-else-if="foods === 'rice'">rice</p>
  <p v-else> Not food</p>
</div>
```

```javascript:Vue.js
var app = new Vue({
  el: '#app',
  data: {
    foods: 'tofu'
  }
})
```

それぞれ、条件が一致する時はその食べ物を表示し、それ以外は`Not food`を表示させる。

<img width=“200” src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/ab10889e-f7fe-ade6-1665-b6da4fc37237.png">

#最後に
ここまでv-ifを用いた条件分岐についてまとめました。
これからもコツコツアウトプットしていきます！
BPE サブワード分割の論文に出てくるコードをベースに理解してみた

初めましてAnother works CTOのソルです。

弊社ではいまsentencepieceを導入検討していて、今回はその中で出てきたサブワード分割というものについて調べてみました。

# Sentencepieceの特徴
Sentencepieceは教師なし学習で、テキスト分割を行うことができます。
MeCabなどの形態素解析ツールでは、辞書データを事前に学習した状態で分割を行うため、辞書にない単語を分割することができませんでした。

Sentencepieceではそこの辞書にない単語を検知できるという点が強みとなっています。

# サブワード分割のアルゴリズム解説
コードはサブワードに関する論文から拝借しました。
https://aclanthology.org/P16-1162.pdf


```py
import re, collections

# {'l o w </w>':5, 'l o w e s t </w>':2, 'n e w e r </w>':6, 'w i d e r </w>':3}を分割された文字ごとに隣り合う出現回数を計算して、隣り合う文字と、その出現回数を返す
# この場合はerが9回出現したことになる
def get_stats(vocab):
    pairs = collections.defaultdict(int)
    for word, freq in vocab.items():
        # print(word, 'word', freq, 'freq') 
        symbols = word.split()
        # ['l', 'o', 'w', '</w>']
        for i in range(len(symbols)-1):
            pairs[symbols[i],symbols[i+1]] += freq
            # print('pairs', pairs)
    return pairs

def merge_vocab(pair, v_in):
    v_out = {}
    # 二つの文字をくっつけて一文字に処理（例：('e', 'r') => er）
    bigram = re.escape(' '.join(pair))
    # つまるところ 〜er〜 を検出する正規表現
    p = re.compile(r'(?<!<\S)' + bigram + r'(?!\S)')
    # vocab の中の全角が半角で置換される
    for word in v_in:
        print('join pair', ''.join(pair))
        w_out = p.sub(''.join(pair), word)
        print('w_out', w_out)
        v_out[w_out] = v_in[word]
    # 'l o w </w>':5, 'l o w e s t </w>':2, 'n e w e r </w>':6, 'w i d e r </w>':3 => {'l o w </w>': 5, 'l o w e s t </w>': 2, 'n e w er </w>': 6, 'w i d er </w>': 3}
    return v_out

# keyは単語名でvalueは出現回数
# </w>は終端の文字という意味を表す
vocab = {'l o w </w>':5, 'l o w e s t </w>':2, 
         'n e w e r </w>':6, 'w i d e r </w>':3}

num_merges = 10
for i in range(num_merges):
    pairs = get_stats(vocab)
    # ループごとにpairs の値が変わるので best の値も変わる
    best = max(pairs, key=pairs.get)
    print('best', best)
    # vocab を変えるのでループごとに結果が更新されていく
    vocab = merge_vocab(best, vocab)

print('vocab',vocab)
# => vocab {'low</w>': 5, 'low e s t </w>': 2, 'newer</w>': 6, 'wid er</w>': 3}
# 言いたいこととしては、「小文字変換されている low, newer, wid, er は意味のある単語として使う」（wid は微妙ですね）
```

まずは学習データのvocabですが、これはそれぞれの単語を空白で一文字ずつ区切っていて、valueは出現回数を表しています。

```py
vocab = {'l o w </w>':5, 'l o w e s t </w>':2, 
         'n e w e r </w>':6, 'w i d e r </w>':3}
```

ここの処理では、vocabの文字で隣あう文字のペアをカウントしています。
各キーを空白で区切られている単位で文字のペアをカウントしていきます。
例えば、l o w e s tだと出現回数が二回なので
lとo, oとw, eとs, sとtのペアがそれぞれ2回出現したとカウントされます。
l o wの場合だと、
lとo, oとwがそれぞれ5回出現
l o w e s tの時にlとoのペアが二回出現しているので、
lとoのペアは7回出現しているというふうにカウントされるため、loは単語としてみなせる可能性があるみたいな感じで、文字の区切り方を調整していきます。

```py
def get_stats(vocab):
    pairs = collections.defaultdict(int)
    for word, freq in vocab.items():
        symbols = word.split()
        for i in range(len(symbols)-1):
            pairs[symbols[i],symbols[i+1]] += freq
    return pairs
```
Elasticsearch を WSL2（Ubuntu）にインストールする

# はじめに
業務で Elasticsearch の導入検討を行ったので、自分のPCにも環境構築をしてみた。その手順を備忘録を兼ねて記事にしておく。なお、基本的に公式のwebページの手順通りにインストールを行った。
https://www.elastic.co/guide/en/elasticsearch/reference/7.15/deb.html#deb-repo

# インストール手順
まずは Elasticsearch の PGP Key をインポートする。

```bash
$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
```

APTのリポジトリからインストールする。そのためには `apt-transport-https` が必要。

```bash
$ sudo apt-get install apt-transport-https
```

リポジトリの情報をリストに加える。

```bash
$ echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list
```

あとはapt-get でインストールする。

```bash
sudo apt-get update && sudo apt-get install elasticsearch
```

# Elasticsearch の起動&停止 (SysVinit)
最初だけ以下コマンドを実行

```bash
$ sudo update-rc.d elasticsearch defaults 95 10
```

`service`コマンドで起動、停止が可能。logは`/var/log/elasticsearch/`に記録される。

```bash
$ sudo -i service elasticsearch start
$ sudo -i service elasticsearch stop
```

# Elasticsearch の起動&停止 (systemd)
WSL で systemd を使う方法は、https://snowsystem.net/other/windows/wsl2-ubuntu-systemctl/ を参考にした。
最初に以下のコマンドを実行する。

```bash
$ sudo /bin/systemctl daemon-reload
$ sudo /bin/systemctl enable elasticsearch.service
```

以下のコマンドで起動、停止が可能。

```bash
$ sudo systemctl start elasticsearch.service
$ sudo systemctl stop elasticsearch.service
```

# Elasticsearch の起動確認
`localhost:9200`にアクセスして起動していることを確認する。最新版(7.15.0)がインストールされている。

```bash
$ curl http://localhost:9200/
{
  "name" : "XXXXXXXXXX",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "XXXXXXXXXX",
  "version" : {
    "number" : "7.15.0",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "XXXXXXXXXX",
    "build_date" : "2021-09-16T03:05:29.143308416Z",
    "build_snapshot" : false,
    "lucene_version" : "8.9.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```

# おわりに
とりあえず今回は公式 Web に従ってインストールを行ったのみだったので、今後 Elasticsearch の使用方法や、Logstash や Kibana についても記事にしていきたいと思う。
EPUBアクセシビリティ検証ツール「Ace」の日本語化

EPUBのアクセシビリティチェックツール、Aceの日本語化に関するメモです。
[以前試した記事](https://qiita.com/shunito/items/8392152205e1aa6ffa1a)のは2019年でしたが、最新でもさほど大きな違いはありませんでした。

※内部で利用されているaxeは日本語化済みなので扱いません。

# Ace (Core) の日本語化

- [公式ドキュメント Ace Localization](https://github.com/daisy/ace/wiki/Localization)
- 以下の3つのnpm packageそれぞれに対しi18nの言語設定ファイルを準備し、設定する。
  - ace-core
  - ace-report-axe
  - ace-report

設定ファイルはJSONなので [POEditor](https://poeditor.com/projects/) などをよしなに使うと楽。
各々、以下のpackagesが本体になる。

## ace-core
Aceの本体のメッセージ等エラーなどメッセージ類はここにある。
- https://github.com/daisy/ace/tree/master/packages/ace-core/src/l10n/locales
- https://github.com/daisy/ace/blob/master/packages/ace-core/src/l10n/localize.js

## ace-report-axe
レポートのAxe固有のメッセージ類。
- https://github.com/daisy/ace/tree/master/packages/ace-report-axe/src/l10n/locales
- https://github.com/daisy/ace/blob/master/packages/ace-report-axe/src/l10n/localize.js

## ace-report
レポートのUI用のメッセージ類。
- https://github.com/daisy/ace/tree/master/packages/ace-report/src/l10n/locales
- https://github.com/daisy/ace/blob/master/packages/ace-report/src/l10n/localize.js

# Ace-GUIの日本語化

[Ace公式サイト](https://daisy.github.io/ace/)にあるGUIのアプリへの適用は以下を参考に。
本来は、ace本体に対して多言語化のプルリクを送って取り込んでもらうのが常道だけど、以下、手元で試すためのメモ。

- [公式ドキュメント Ace (GUI) Localization](https://github.com/daisy/ace-gui/wiki/Localization)
- ビルドはyarnを前提にしているので[Ace-guiのリポジトリ](https://github.com/daisy/ace-gui)をcloneしたら`yarn install`する。
   - `src/shared/l10n/`が多言語設定になるので、上記同様に翻訳したメッセージのファイルと設定を追記する。 
   - GUIの日本語化はこれだけで完了。レポートを日本語化するには以下を実行する。
- axe-coreのpackeagesが`node_modules`の以下の位置にあるので、手元で手軽に試すのであれば上記の翻訳ファイルを配置し、言語設定を編集してアプリをビルドする。
  - `node_modules/@daisy/ace-core/lib/l10n` 
  - `node_modules/@daisy/ace-report/lib/l10n` 
  - `node_modules/@daisy/ace-report-axe/lib/l10n` 

ビルド環境の整備でちょっと詰まるかもしれませんが、うまくいくとこんな感じ。設定画面で言語を日本語に切り替えれば、レポートも自動的に日本語で出力されます。
機械翻訳なのでところどころおかしいけど調整すればほぼ使えそう。

![ACE-GUIの日本語化アプリのスナップショット。警告やルール、位置などがリストで表示されている。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2827/fed43451-dbaa-f172-8a63-cf6f0b7b96c5.png)

# チェック項目のカスタマイズ

axeにAce独自のチェック項目を追加しているのは以下の部分。
カスタマイズするのであれば、このあたりにロジックを追加していく必要がありそう。

- https://github.com/daisy/ace/blob/master/packages/ace-core/src/checker/checker.js
- https://github.com/daisy/ace/blob/master/packages/ace-core/src/checker/checker-epub.js
- https://github.com/daisy/ace/blob/master/packages/ace-core/src/checker/checker-chromium.js

メタデータの設定はこのあたりを調整か。

- https://github.com/daisy/ace/blob/master/packages/ace-core/src/core/a11y-metadata.js

以上
Apachセキュリティー対策

自分のメモとして




###参考サイト
https://qiita.com/bezeklik/items/1c4145652661cf5b2271

https://www.rem-system.com/apache-security01/

https://s8a.jp/apache-security#linux%E3%81%AEiptablesfirewalldselinux%E3%81%AE%E5%88%A9%E7%94%A8

https://www.ssk-kan.co.jp/topics/topics_cat05/?p=11458
Debian11デスクトップに追加で入れているアプリケーションのリポジトリとか

目的
ちょくちょくDebianのデスクトップ環境を再セットアップするので、いつも入れているアプリケーションのリポジトリと導入のコマンドを記録する。

アプリケーション
【Wine】
32bitアーキｔクチャの有効化
sudo dpkg --add-architecture i386

1.FAudioのリポジトリ追加
$ wget -O- -q https://download.opensuse.org/repositories/Emulators:/Wine:/Debian/Debian_11/Release.key | sudo apt-key add -

$ sudo vim /etc/apt/sources.list
>deb https://download.opensuse.org/repositories/Emulators:/Wine:/Debian/Debian_11 ./

2.Wineのリポジトリ追加
$ wget -qO - https://dl.winehq.org/wine-builds/winehq.key | sudo apt-key add -

$ sudo vim /etc/apt/sources.list
>deb http://dl.winehq.org/wine-builds/debian/ bullseye main

3.Wineのインストール
$ sudo apt-get update
$ sudo apt-get install --install-recommends winehq-stable

【スワップの抑止】
$ sudo vim /etc/sysctl.conf
>vm.swappiness = 10

【Audioの初期化】
Let's Noteだと起動時にAudioの初期化をしないと音が出ないので、スタートアップにコマンドを追加。
>amixer -c 0 sset headphone 100%

順次追記予定
【React】URL直打ちによるページスキップを防ぐ

#はじめに
複数ページにステップを分けた入力フォームを作成した際、必須項目を入力しなくてもURL直打ちでページスキップができてしまうということに気が付きました。
一瞬で登録完了！みたいなことをされたくなかったので、`history.push()`を少しいじってスキップを制御しました。

#実装
「保存して次へ」ボタン`NextButton`を押したときに`history.push()`でページ遷移を行いますが、この中に`state: { referrer: '/profile/one' }`を付加します。

```tsx:NextButton.tsx
export NextButton = () => {
  const history = useHistory()

  const handleClick = () => {
    history.push({
      pathname: '/profile/two',
      state: { referrer: '/profile/one' },
    })
  }

  return (
    <div style={{ marginBottom: 20, textAlign: 'center' }}>
      <Button
        type='submit'
        variant='primary'
        size='lg'
        style={{ width: 300 }}
        onClick={handleClick}
      >
        <span style={{ fontSize: 14, fontWeight: 'bold' }}>保存して次へ</span>
      </Button>
    </div>
  )
}
```
遷移先のページに`useEffect`を追加し、`history.location.state`に要素が入っていなければ`/profile/one`にリダイレクトするようにします。
このようにすることで、URL直打ちでこのページに遷移しようとしても、'/profile/one'にリダイレクトされます。

```tsx:ComponentTwo.tsx
export ComponentTwo = () => {
  useEffect(() => {
    if (!history.location.state) history.replace('/profile/one')
  }, [])

  return (
    // (省略)
  )
}
```
PostgreSQLを複数バージョンインストールするとport5432,5433,5434を使い複数立ち上がる件

## 環境

* LinuxMint20.1(ubuntu base linux)

## 状況確認

```bash
# portの使用プロセスの確認（下記のどちらか実行で良い）
sudo ss -pluten | grep 5434
sudo lsof -i:5434
```

```bash
$ dpkg -l | grep postgres
ii  postgresql                                 14+231.pgdg20.04+1                     all          object-relational SQL database (supported version)
ii  postgresql-12                              12.8-1.pgdg20.04+1                     amd64        The World's Most Advanced Open Source Relational Database
ii  postgresql-13                              13.4-4.pgdg20.04+1                     amd64        The World's Most Advanced Open Source Relational Database
ii  postgresql-14                              14.0-1.pgdg20.04+1                     amd64        The World's Most Advanced Open Source Relational Database
ii  postgresql-client-12                       12.8-1.pgdg20.04+1                     amd64        front-end programs for PostgreSQL 12
ii  postgresql-client-13                       13.4-4.pgdg20.04+1                     amd64        front-end programs for PostgreSQL 13
ii  postgresql-client-14                       14.0-1.pgdg20.04+1                     amd64        front-end programs for PostgreSQL 14

$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
13  main    5433 online postgres /var/lib/postgresql/13/main /var/log/postgresql/postgresql-13-main.log
14  main    5434 online postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log

```

```
■コンフィグファイルのportが5432から始まり、5433,5434と上がっている（使うバージョンだけ5432にした）
/etc/postgresql/12/main/postgresql.conf
/etc/postgresql/13/main/postgresql.conf
/etc/postgresql/14/main/postgresql.conf
```

## 対応

不要ファイルを削除するときの方法
（postgresqlもALLとなっていて最新が出ると、どんどん入ってしまうので消しておく。）

```bash
sudo apt-get --purge remove postgresql postgresql-12 postgresql-14 postgresql-client-12 postgresql-client-14
```


## 全消しするなら

下記は、全消しするならやる。特定バージョンだけ残しておくなら消してしまうとデータも消えるのでやらない。

```bash
sudo rm -rf /var/lib/postgresql/
sudo rm -rf /var/log/postgresql/
sudo rm -rf /etc/postgresql/

sudo deluser postgres
```

## なぜこの記事を書いたのか？

ローカルで5434ポート指定で起動していたのものが起動せず困ったため。
原因は、PostgreSQL 14 が昨日（2021-09-30 ）出て、アップデートしたらv14が5434ポートで起動したため。

インストールしたら勝手に起動するのもダメかと思うが、複数起動するのはもっとダメだと思った。
react-native-dotenvのインストールからセットアップまで(TypeScript向け)

#はじめに
React Nativeで環境変数を使う際に [react-native-dotenv](https://github.com/zetachang/react-native-dotenv) という便利なライブラリがあったので紹介(TypeScript向け)

#STEP 1
以下のコマンドをターミナルから実行

```
npm install -D @types/react-native-dotenv
 または     
yarn add -D @types/react-native-dotenv
```

#STEP2
`babel.config.js`ファイルに以下を記述

```javascript:babel.config.js
module.exports = function (api) {
    api.cache(true);
    return {
        presets: ["babel-preset-expo"],
        plugins: [
            [
                "module:react-native-dotenv",
                {
                    moduleName: "@env",
                    path: ".env",
                },
            ],
        ],
    };
};
```

#STEP3
**ルートディレクトリ**に`config.env`, `env.d.ts`ファイルを作成し以下のようにする

```env:config.env
API_KEY="hoge"
SECRET_KEY="secret-hoge"
```

```typescript:env.d.ts
declare module '@env' {
    export const API_KEY: string;
    export const SECRET_KEY: string;
}
```

また, `tsconfig.json`にも以下を追加する

```json:tsconfig.json
{
,,,
"typeRoots": ["./types"]
,,,
}
```
#STEP4
変数を使用したいファイル内で以下のように`import`できる

```
import { API_KEY, SECRET_KEY } from "@env"
```
完了。
#最後に
どうやら`react-native-config`なるものもあるらしいですがどっちがいいのかは好みかなーって感じです。
【TidalCycles】ピンポンディレイの実装

# はじめに

ピンポンディレイとは、音が一度鳴ったあとのディレイ音が左右のpanに交互に振れていくようなディレイのことです。
おそらく言葉で説明するよりも音を聴いてもらったほうが早いと思うので、まずはこちらを聴いてみてください。

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

通常のディレイが同じpanに対して反響音が鳴り続けるのに対し、ピンポンディレイは一度音がなったあとに「右→左→右→左」と音量が減衰しながらpanが卓球(ピンポン)球のように移っていくのがわかるかと思います。

# ピンポンディレイの実装

まず、動画で実行しているコードです。

```haskell
-- BPM:120
setcps (120/60/4)

d2 $ s "click:2*4" # gain 0.9 # lpf 400

-- ディレイなし
d1
  $ slow 2
  $ s "notes:2 [~ ~ ~ [~ notes:2]] notes:2 ~" # up "0 [0 0 0 -4] -2 0"
  # pan 0.5
  # gain 1.1

-- 通常のディレイ
d1
  $ ((# delay 0.8).(# delayt (3/16)).(# delayfb 0.2).(# lock 1))
  $ slow 2
  $ s "notes:2 [~ ~ ~ [~ notes:2]] notes:2 ~" # up "0 [0 0 0 -4] -2 0"
  # pan 0.5
  # gain 1.0

-- ピンポンディレイ
d1
  $ stut' 2 (3/16) ((|* gain 0.9).(|> pan (1)))
  $ stut' 8 (3/8) ((|* gain 0.8).(|> pan (0)))
  $ slow 2
  $ s "notes:2 [~ ~ ~ [~ notes:2]] notes:2 ~" # up "0 [0 0 0 -4] -2 0"
  # pan 0.5
  # gain 1.1

```

通常TidalCyclesでディレイをかけたかったら、delay, delayt, delayfb, lockあたりを組み合わせて実装すると思います。(参考: [公式ドキュメント](https://tidalcycles.org/docs/reference/audio_effects#delay))

ただ、この方法だとディレイ音に対してエフェクトをかけたり、panを振ったりなど細かい調整ができず不便です。そこで登場するのが`stut'`で、これは

```
stut’ x z (function)　(x：フィードバック回数　z：ディレイタイム)
```

とすることでディレイ音にfuctionで指定したエフェクトをかけることができます(参考: [公式userbase](https://userbase.tidalcycles.org/stut#stutWith))


`stut`, `stut'`の使い方についてはmoistpeaceさんのページでわかりやすく解説されているので是非こちらもみてください。

https://moistpeace.com/2020/06/25/tidalcycles-day7-stut-speed-up/

それではなぜ

```haskell
$ stut' 2 (3/16) ((|* gain 0.9).(|> pan (1)))
$ stut' 8 (3/8) ((|* gain 0.8).(|> pan (0)))
```

でピンポンディレイができるのか？ということなんですが、実をいうと自分でもよくわかっていません。(わかる方いらっしゃれば是非コメントください..!)

実装方法としては、

- 1つ目のフィードバック回数を2
- 1つ目のディレイタイムに指定したいディレイタイム、2つ目のディレイタイムはその倍の値にする
- 2つ目のフィードバック回数を増やしたり減らしたりすることで欲しいフィードバック回数をコントロールする
- 1つ目と2つ目のpanを逆にする
- 1つ目の`|* gain`は1以下にして、2つ目の`|* gain`は1つ目の2乗くらいの値にする

といった感じです。

ちなみに、

```haskell
$ stut' 2 (3/16) ((|* gain 0.9).(|> pan (1)).(|> lpf 1000))
$ stut' 8 (3/8) ((|* gain 0.8).(|> pan (0)).(|> lpf 1000))
```

などのようにすればディレイ音にのみローパスフィルターをかけたりできます。

# おわりに

TidalCyclesはライブコーディングができるだけでなく、作曲ソフトとしても使えるので、普段DAWで作曲している方にとっても表現の幅が広がる良いツールです！他にもTidalCycles関連の記事を書いているのでよければみていってください！

https://qiita.com/s2hap/items/620082b82a4bbe475823
CDK(Python)のテストコード内で任意のContextをSetして利用する方法


PythonでCDKのテストを書いていたのですが、contextの内容を任意の値で設定したいところがありました。

# 現象

ネットを探したところ `set_context()` を利用することで任意のcontext値を設定できそうだったので以下のように書いてみたのですが、

```python
def test_set_context():
    test_key = "context_key"
    test_context = {"dummy_key": "dummy_value"}

    app = cdk.App()
    app.node.set_context(test_key, test_context)
    context = app.node.try_get_context(test_key)
    assert context == test_context
```

例外が発生してしまいました。

```
raise JSIIError(resp.error) from JavaScriptError(resp.stack)
jsii.errors.JSIIError: Cannot set context after children have been added: Tree
```

# 対応
`App` の初期化自に名前付引数の `context` で渡してあげると設定することができました。

```python
def test_set_context():
    test_key = "context_key"
    test_context = {"dummy_key": "dummy_value"}

    app = cdk.App(context={test_key: test_context})
    context = app.node.try_get_context(test_key)
    assert context == test_context
```
htaccessが動かない（リファラ制限）

リファラ制限を設定したhtaccessファイルを設置しているのに、所定のURLから遷移した際閲覧できない不具合が発生していた（ChromeとEdgeのみ）。大きな範囲から検証していく。
（IPアドレス制限も記述に含んでいるが今回検証範囲ではないので説明は割愛）

```
SetEnvIf Referer "^http[s]*://~~~~~~~~" chk_url

order deny,allow
deny from all
allow from env=chk_url
allow from XXX.XXX.XXX.XXX
```

###前提
開発環境で本番のリファラを設定するわけにもいかないので、開発環境内同士でリファラを設定し検証していた。その時点では問題なし。

###リファラ元HTMLのチェック
- aタグリンク先のURLをスラッシュで終わる形に修正
- キャッシュ削除

☞意味なし。

###そもそも
特定のブラウザでのみ発生する不具合……ということで、（嫌な予感）「リファラ　ブラウザ対応」で検索する
☟
https://www.rectus.co.jp/archives/964
Chromeはver.85以降、Edgeはver.86時点、Safariは14.0.1 604.1時点で参照元がトップページレベルでしか取得できなくなっている　とのこと。セキュリティ対策らしい。

マークアップ側はブラウザ対応について逐一調べて使用しているけど、リファラは盲点だった……💀

###対策（ブラウザ対応）
3種類ある。1つめは**リファラを受け取る側で可能な設定**、後の2つは**リファラを渡す側で可能な設定**となるので注意。
1つはhtaccessのリファラ元の設定を個別のページからTOPページ（ルートレベル）に変更する方法。構造上支障がないかは要確認。

```
SetEnvIf Referer "^http[s]*://~~~~~~~~/test/test/top.html" chk_url
☟
SetEnvIf Referer "^http[s]*://~~~~~~~~/" chk_url
```

もう1つは遷移元のaタグに従来のリファラを渡すよう、rel属性を記述する方法。

```
<a href="https://~~~~~~/" rel="no-referrer-when-downgrade">設置ページへ</a>
```

最後1つは遷移元ページのhtaccessに従来のリファラを渡すよう、命令を記述する方法。

```
<IfModule mod_headers.c>
Header set "Referrer-Policy" "no-referrer-when-downgrade"
</IfModule>
```

これでリファラ制限の不具合は解消されたが、所定ディレクトリ内での遷移（たとえばpdfファイルを開くなど）は403エラーになる。
これはhtaccessが設置ディレクトリ以下ですべて効いているため、対象ファイルへの遷移時にも同一のリファラ制限が効いてしまうことによる。

###対策（同ディレクトリ内遷移）
2つある。
1つは対象ファイルを別ディレクトリに設置し、htaccessの影響範囲の外に出す方法。
注意点は、アクセス制限の外に置かれるため、URLさえ知っていれば移動後の対象ファイルに誰でもアクセス可能なことがある。

もう1つはhtaccessのリファラ元URLに、遷移先のトップページを追加する方法。
トップページをリファラ元に設定しても支障ないか構造の確認が必要。

```
SetEnvIf Referer "^http[s]*://~~~~~~~~" chk_url
SetEnvIf Referer "^http[s]*://~~~~~~~~" chk_url　☜遷移先のトップページを追加
```

このほか、特定のディレクトリのみアクセス制限を解除する…という解決法もありそうだが、ややこしいわりにセキュリティ面では1つめと同様不安が残るので割愛。

###それにしても
開発環境の段階でリファラの不具合を発見できればよかったのに、なんで動いてたんだ。Chromeも同じver.85以降だったのに……と思っていたけど、Referrer-Policyはオリジンが同一か別物かで挙動がだいぶ変わってくるらしい。それこそhtaccessに特別な指定のない限り「同一オリジン間でリクエストを行う場合はオリジン、パス、クエリ文字列を送信」するようになっているようだ。
以下はReferrer-Policyのドキュメント。オリジンごとの挙動などが記載してある。
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Referrer-Policy
Referrer-Policyの解説記事は以下
https://qiita.com/n3_x/items/c2bafd5872af61147c89

検証したければ、リファラはブラウザのconsoleで以下コードを入力すれば確認できる。
https://www.nishishi.com/javascript-tips/encodeuri.html

```
alert( document.referrer );
```

あるいはChrome検証のNetworkタブを開くと、各通信ごとのRequest HeadersやGeneralの欄でreferrerの情報が確認できる。

どちらにせよReferrer-Policyに関する十分な知識のない限り、開発環境の検証では発見できなかったミスといえる。ﾖﾎﾞﾎﾞ
もしECサイトの人気商品に秒間100万リクエストが来たとしたら

# 売過ぎ

ECサイトにおいて、人気商品に同時に沢山の購買リクエストが来ることがあります。
今のシステムは複数のサーバーを使ってリクエストを分散させて処理することが多いが、
同じ在庫データに複数の購買処理が走ったらどうなるか？

商品の在庫数: 100
サーバー1とサーバー2が同時に在庫数を取得する。
サーバー1.在庫数取得() -> return 100
サーバー2.在庫数取得() -> return 100

購買処理をする
サーバー1.在庫数更新(100 - 1) -> return 99
サーバー2.在庫数更新(100 - 1) -> return 99

つまり、実際商品2個売ったけど、
プログラムの処理で在庫数1しか減らない。
これを繰り返すと、売過ぎが発生し、
顧客が商品を買ったのに、最終的に商品を供給できないことが起きます。

# Lockをかける

上記のような売過ぎを防ぐにはLockを使うとうまく解決します。
ここで性能を考えてMySQLなどのロックではなくredisによるLockの実装方法を考えます。

## オリジナル販売ロジック
```php
$stock = $redis->getStock($productCode);
if ($stock > 0) {
	$this->makePurchase();
	$stock -= 1;
	$redis->setStock($productCode, $stock);
}
```
これはストックを更新するもっともシンプルなコード。
シングルサーバーの場合は何も問題ないが、
マルチサーバー x 並行処理になると売過ぎが発生します。

## Lockをかける
```php
$lockKey = 'lockKey';
$lock = $redis->setnx($lockKey, 'lock'); # ロックをかけてみる return bool
if (!lock) {
	# ロックがすでに存在していて、購入を進めるべきではない
	return "errorCode";
}

$stock = $redis->getStock($productCode);
if ($stock > 0) {
	$this->makePurchase();
	$stock -= 1;
	$redis->setStock($productCode, $stock);
}

$redis->delete($lockKey);
```
これで複数スレッドが来でも、最初のスレッドしかストックを更新することができず、
ストック数の一致性が保証されました。

しかし問題がありました。

ロックを確保できるのは`$redis->setnx($lockKey, 'lock');`の実行が成功したスレッドのみ、
他のスレッドはエラーで返すようになる。並行処理を使っているのにシングルスレッドかのようにしか実行できません。
処理が遅くなります。

もし`$redis->delete($lockKey);`が実行されるまでエラーになって、ロックを開放できなくなると、
デッドロックが発生し、その後のスレッドがもうロックをかけることも、解くこともできず、
購入ももちろんできません。
機能として破綻します。

## try finallyを追加する
```php
$lockKey = 'lockKey';
try {
	$lock = $redis->setnx($lockKey, 'lock'); # ロックをかけてみる return bool
	if (!lock) {
		# ロックがすでに存在していて、購入を進めるべきではない
		return "errorCode";
	}

	$stock = $redis->getStock($productCode);
	if ($stock > 0) {
		$this->makePurchase();
		$stock -= 1;
		$redis->setStock($productCode, $stock);
	}
} finally (\Throwable $th) {
	$redis->delete($lockKey);
}
```

これでスレッド内に何があっても最終的にロックを解放することができます。
しかし、もし`$redis->delete($lockKey);`が実行される前にプロセスがkillされ、あるいはサーバーがダウンしたらロックは解放されないまま残っています。

## ロックにexpired timeを追加する
```php
try {
	$lock = $redis->setnx($lockKey, 'lock'); # ロックをかけてみる return bool
	$redis->expired($lockKey, 60);
	// ...
} finally (\Throwable $th) {
	$redis->delete($lockKey);
}
```

これでシステムがダウンしても時間になったらロックが自動的に外されます。
ただ、タイミング的に`$redis->expired($lockKey, 60);`が実行される前にプロセスがkillされたらデッドロックが発生します。

```php
try {
	$lock = $redis->setnx($lockKey, 'lock', 60); # ロックをかけてみる return bool
	// ...
} finally (\Throwable $th) {
	$redis->delete($lockKey);
}
```
それでロックをかける時にexpired timeを設定してあげます。
ここまでできればある程度に本番環境で使えるコードになりました。
ただ、本当にリクエスト数が多い場合問題はあります。

下図のようにスレッドの実行時間がことなるから、スレッド1がスレッド2のロックを解くという意図しない動きをすることがあります。

![名称未設定.002.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81957/e199c899-cb18-3885-d68a-82f709895410.jpeg)

この場合はロックのexpired timeを都度延長してあげるといいでしょう。

## redisson

上記の機能を簡単に実装してくれるリポジトリがすでに存在しています。
redisson https://github.com/redisson/redisson
を使うと簡単に実装することができます。
ESXi 6.7 に realtek NIC のドライバを追加する 

realtek NIC のPCにインストールするためにカスタムISOイメージを作成してインストールする手順ではなく、すでにインストールして起動してるESXi にドライバを追加する手順のメモ。

1. ドライバダウンロード
https://vibsdepot.v-front.de/wiki/index.php/Net55-r8168 からドライバをダウンロード。

1. scp で ESXi に転送
$ scp net55-r8168-8.045a-napi-offline_bundle.zip root@192.168.1.20:/vmfs/volumes/datastore1

1. ESXi に root でログイン

1. 先に、コミュニティのドライバを適用できるように設定。
```
[root@esxi-2:/vmfs/volumes] esxcli software acceptance set --level=CommunitySupported
Host acceptance level changed to 'CommunitySupported'.
```
1. ドライバインストール
```
[root@esxi-2:/vmfs/volumes] esxcli software vib install -d /vmfs/volumes/datastore1/net55-r8168-8.045a-napi-offline_bundle.zip
Installation Result
   Message: The update completed successfully, but the system needs to be rebooted for the changes to be effective.
   Reboot Required: true
   VIBs Installed: Realtek_bootbank_net55-r8168_8.045a-napi
   VIBs Removed:
   VIBs Skipped:
```

無事に入ったら再起動。

問題なければ realtek NIC が認識しているはず。
【React】遷移後のページを最上部から表示する

#はじめに
React Routerでページ遷移を行う際、前画面でスクロールした状態が残ってしまいます。
遷移後のページを最上部から表示させるために、`window.scrollTo(0, 0)`を利用します。

#実装
`useLocation`と`useEffect`を利用し、パス名が変わったときに`window.scrollTo(0, 0)`が実行されるようにします。

```js
const ScrollToTop = () => {
  const { pathname } = useLocation()

  useEffect(() => {
    window.scrollTo(0, 0)
  }, [pathname])

  return null
}
```
作成した`ScrollToTop`を`Router`でラップします。
これで`ComponentOne` `ComponentTwo` `ComponentThree`のどこに遷移しても、ページ最上部から表示されるようになります。

```jsx
    <Router>
      <ScrollToTop />
      <Switch>
        <Route path={'/one'}>
          <ComponentOne />
        </Route>
        <Route path={'/two'}>
          <ComponentTwo />
        </Route>
        <Route path={'/three'}>
          <ComponentThree />
        </Route>
    </Router>
```
FluentdでEC2→S3へ転送する際に、Access key,Secret keyを使わず、IAMロールを使う

## What's this~これは何~

[こちらの記事](https://qiita.com/namely_/items/acfe699fdf2a69b6cb41) で、S3 API callを行う際に、IAMユーザーを作成し、Access key,Secret keyを設定ファイルにベタ書きしていたのですが、やはりこれはセキュアとは言えないなと感じておりました。
今回は、IAMロールを使ってS3 API callを行いました。

## 前回との相違点

**IAM ロールのポリシー**
[GitHub](https://github.com/fluent/fluent-plugin-s3/blob/master/docs/howto.md#iam-policy)に推奨のポリシーが置いてありました。
my-s3bucketはバケットの名前を記入。
作成後はEC2にロールをアタッチします。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": "arn:aws:s3:::my-s3bucket"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::my-s3bucket/*"
    }
  ]
}
```

**設定ファイルの編集**

今回、
aws_key_id 
aws_sec_key
はコメントアウトしています。

```
vi /etc/td-agent/td-agent.conf

/match
で、該当の行を消去

最下行に以下追記
<source>
  @type tail
  path /var/log/httpd/access_log
  tag td.messages.access
  pos_file /var/log/td-agent/messages.pos
  format syslog
</source>

<match td.messages.access>
  @type s3
  #aws_key_id 
  #aws_sec_key 
  s3_bucket バケットの名前
  s3_region ap-northeast-1（利用リージョンに合わせて、任意）
  time_slice_format %Y%m%d%H%M
</match>
  <buffer>
    @type file
    path /var/log/td-agent/s3
    timekey 3600  # 1 hour
    timekey_wait 10m
    chunk_limit_size 256m
  </buffer>
```

## 参考

```
https://github.com/fluent/fluent-plugin-s3/blob/master/docs/howto.md#iam-policy
https://qiita.com/dz_/items/224607c84112ccafa2d6
```

参考にさせていただきました。ありがとうございます。
「notion API」の ruby ライブラリ比較してみた(gem)

notion APIのBeta版が公開されてから５ヶ月ほど経ちましたね！
リリース当初は各言語でAPIのマッパーライブラリが多く乱立しており、比較も難しかったですね。。。
今回は **2021/07/01以降に更新があった ruby の gem 3つ** を比較し、どのライブラリを使用すべきかまとめていこうと思います！

https://rubygems.org/search?query=name%3A+notion++++updated%3A+%3E2021-08-01

notionAPIの導入を検討している方の参考になれば幸いです。

# 1. notion-ruby-client
https://github.com/orbit-love/notion-ruby-client

https://rubygems.org/gems/notion-ruby-client

累計ダウンロード: 4205
GitHubスター数: 22
最終更新日: 2021/08/29

## 特徴
Notionを利用したソフトウェアを開発している会社でOSS開発されているライブラリ。
そのため継続的な更新が行われており、今後のメンテナンスも期待できる。

# 2. notion-sdk-ruby
https://github.com/mgmarlow/notion-sdk-ruby

https://rubygems.org/gems/notion-sdk-ruby

累計ダウンロード: 3490
GitHubスター数: 9
最終更新日: 2021/09/30

## 特徴
PRを積極的に受け入れておりOSS感が強い。
最終更新日は最も新しい。
ただ、更新が不定期。

# 3. notion-ruby
https://github.com/decoch/notion-ruby

https://rubygems.org/gems/notion_ruby

累計ダウンロード: 744
GitHubスター数: 1
最終更新日: 2021/07/11

## 特徴
日本人が開発者。コンタクト取りやすいかも。
ただ、更新はファーストコミット以降止まっている。

# 結論
どのライブラリも使用感は変わらなさそうです。
ひとまず**notion-ruby-clientを使えば問題なさそう！**
今後の継続的な開発が期待できる点が他ライブラリとの決定的な違いですね！

# まとめ
今後開発が止まる、新たなライブラリが誕生するかもしれないので定期的にgemを監視し、記事も更新していきたいと思います！
多くの方の参考になれば幸いです。
Trailblazer Communityが表示できない

朝から、ログインはできるけど表示できないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4f0fca64-470a-9e1a-a37c-8a3720b92178.png)

調べていくと SSLのエラーのようです。
証明書の期限が切れています。

```
Failed to load resource: net::ERR_CERT_AUTHORITY_INVALID
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f909d12d-c79d-eaf3-baff-7d6cc861c99f.png)

他の人達は繋がっているらしい。（海外の人達に聞いたら、問題ないらしいねぇ）

あと不思議なことにiphoneからは問題なく閲覧できた。しかし、社内のネットにつなぐと同じエラーです。

ええええ、回線の問題？

分からんようになった。

このサイト以外も見えないサイトが出てきています。

#信頼されたルート証明書が消せない。
どうやって消すの？

https://www.accuphase.co.jp/manual_pdf/usbdriver2set_a.pdf


#何かしらないけど、突然つながった。
何故だろう？

やっぱり回線の問題なのかな？
社内のネットにつないだiphoneからも表示できた。
HTMLの基本2（要素・属性・属性値）

# HTMLの記述の仕方
HTMLは要素をタグで書きます。
タグとは、

```html
<html>
```
の様に、<>で囲まれた文字の事です。
タグには開始タグと終了タグというものがあります。

```html
<div>   開始タグ
</div>  終了タグ
```

上記の様に表現します。
終了タグには < の後に / を入力するところが、開始タグと違うところです。 
終了タグが無いものもあります。

次にHTMLを成立させるために必須なタグを紹介します。

#### <!DOCTYPE html>　（ドックタイプ　エイチティーエムエル）

```html
<!DOCTYPE html>
```
上記の様に記述します。
DOCTYPE　は　Document Type　（ドキュメントタイプ）の略で、
このコードはHTMLで書かれていることを示しています。
必須タグです。

#### ＜html＞　（ＨＴＭＬタグ）

html タグは、開始タグと終了タグがあります。

```html
<!DOCTYPE html>
<html>
</html>
```
html言語でどこからどこまで記述を行っているのかを示しています。
必須タグです。

####　＜head＞タグ　（ヘッドタグ）

headタグは、実際にブラウザに表示される情報を記述する部分ではなく、
関係するファイル、CSSやJabaScriptといったデータとhtml文章を連携させるための情報を記述したり、
記述する文字コードの種類を指定するなどの情報を開始タグと終了タグの間に記述します。
必須タグです。

```html
<!DOCTYPE html>
<html>
  <head>
  </head>
</html>
```
の様に記述し、htmlの開始タグと終了タグに挟まれるような形で記述します。
この場合、htmlタグはheadタグの親要素という関係になります。
反対に、headタグはhtmlタグの子要素という関係になります。

#### インデント

子要素は親要素よりも右にずらして記述します。
そうしなくても実際にブラウザでの表示のされ方は変わりませんが、
コードの記述が長くなってきたり、親要素、子要素、孫要素など
要素同士の階層が複雑になってくる場合は、このように右にずらして記述しないと、
コードを書いている自分自身も読み取りにくくなってしまうため、
可読性を上げるために右にずらしています。
この右にずらすことを"インデント"と言います。

【例】

```html
<!DOCTYPE html>
<html>
  <head>
    <title>例えば、このタイトル要素はhtml要素の子要素の子要素（孫要素）となる</title>
  </head>
</html>
```

#### ＜body＞　（ボディータグ）

body タグはhtmlタグの子要素、headタグと同じ階層に記述します。
bodyタグは、実際にブラウザ上に表示される情報を記述する場所です。
開始タグと終了タグの間に、文字情報、画像、リンク、フォームなどの情報を記述していきます。
必須タグです。

```html
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
  </body>
</html>
```

#### ＜title＞ (タイトルタグ）
headタグ内に記述する要素です。
タイトルタグは開始タグと終了タグの間にブラウザのタブに表示される文字を設定することができます。
タイトルタグの文字列は、検索などでもヒットするので重要な要素です。

```html
<!DOCTYPE html>
<html>
  <head>
    <title>ここにタイトルを記入すると...</title>
    <meta charset="utf-8">
  </head>
  <body>
  </body>
</html>
```
上記の様にタイトル要素を設定すると、
![3e1c5119814ca90288953d534e71b846.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1420298/92aa9743-e151-435d-4454-5a81af462e81.png)
このようにブラウザのタブにタイトルが表示されるようになります。

#### ＜meta charset="utf-8"＞　（メタタグ）（キャラセット属性）（属性値はutf-8）

メタ要素は、文字コードの種類などを宣言できる要素です。
charset の部分は属性と言います。
それに続く、="utf-8" の　utf-8　の部分は属性値と言います。
「meta要素のcharset属性はutf-8にします。」という意味です。
utf-8は文字コードの種類の事です。
2021年現在はutf-8を使用することを強く推奨されています。
他の文字コードCESU-8, UTF-7, BOCU-1, SCSU等を使用すると、
クロスサイトスクリプティング攻撃を受けやすくなります。
簡単なハッキングのようなもので、サイトを利用した人の情報が漏洩するなどの被害につながる心配があるため、
注意が必要です。

詳しくはこちらを見てください。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/meta

```html
<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
  </head>
  <body>
  </body>
</html>
```

以上が、HTMLの必須タグの紹介となります。

#### 要素・属性・属性値

要素とは、今まで説明してきたようなものです。
例えば、bodyに画像を読み込みたい場合は以下の様に記述することができます。

```html
<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
  </head>
  <body>
　　<img src="sample.png">
  </body>
</html>
```

img　が要素　イメージタグです。
src　が属性　ソース属性（画像データの場所は・・・と言っています。）
="sample.png"  のダブルクォーテーション " に挟まれた文字列が属性値となり、実際のファイルの場所をパスで示しています。

詳しくは次回以降にお伝えします。

#　次回予告

次回からは、実際に文字や画像をbody内に記述し、ブラウザに表示させていきます。
トランザクション

いつもお世話になっております。
今日はトランザクションについてのお勉強してきました。
「トランザクションを学ぶオオカワウソ」
はい、ありがとうございます。
酒飲み駆け出しエンジニアラッパー、韻踏みました。

# トランザクション

トランザクションとは***データベースに対して行われる一つ以上の更新処理***のことです。
トランザクションによってデータの更新処理や取り消しを管理できます。

何いうとんねんどういう意味や。

データベースで考えるからややこしいんすよね。

## Mサイズのライダースジャケットが3枚足りない時

日常生活で考えてみましょう。
QiitaStoreは日本に数店舗展開している人気アパレル会社です。

QiitaStoreのB店はライダースジャケットの売り上げが非常によかったそうです。
Mサイズが売り切れてしまったので、在庫過多になっているA店から3点取り寄せすることにしました。
OKを出したA店は早速ライダースジャケット3点をB店へ送りました。
ここで起こる事としては、B店の在庫が3点増えたと同時にA店から在庫が3店減ったという事です。
これがトランザクションです。
トランザクションを言い換えると、
複数の処理を一つにまとめたものってことですよね。
トランザクションの一つ一つの処理を分離することはできません。

>A店はライダースジャケット3点差し引く

これだけを処理してしまうと
B店はライダースジャケットが３点増えますが、
A店は？？となってしまいます。

そこで***B店からA店への取り寄せ願いというトランザクション***は
①A店はライダースジャケット3点差し引く
②B店のライダースジャケットの在庫が３点増加
になります。
よってトランザクションは複数の処理を分離することができません。

# トランザクションを作成

> トランザクションとは***データベースに対して行われる一つ以上の更新処理***のことです。

これについて考えていきましょう

トランザクションの使用にはトランザクションの開始宣言をしてから
各SQL文を記述していきます。
そしてトランザクションの最後にはトランザクションの確定、もしくは取り消す終了文を記述します。

```sql
START TRANSACTION;

UPDATE `magicians`
SET NAME = '虎杖悠仁'
WHERE ID = 1;

UPDATE `magicians`
SET NAME = '伏黒恵'
WHERE ID = 2;

COMMIT;
```

## COMMIT

COMMITはトランザクションを確定させる処理です。
一度COMMITすると取り消しができないので注意。

## ROLLBACK

ROLLBACKはトランザクションを取り消す処理です。
ROLLBACKするとトランザクション開始前の状態に戻ります。


# トランザクションの4つの特性

トランザクションにはACID特性があります。
ACID特性はトランザクションに必要な4つの要素の事です。
それを最後に一つずつ。

# Atomicity(原子性)
まず、AはAtomicity(原子性)です。
トランザクションの複数の更新処理は「すべて実行される」か「全く実行されない」の
2択だという事です。中途半端な処理結果になってはならないことを保証します。

# Consistency(一貫性)
CはConsistency(一貫性)です。
トランザクションの終了状態にかかわらず、データベースの整合性が保たれていることを
保証します。、データベースのデータに矛盾を生じさせないという要素です。

# Isolation(独立性)
IはIsolation(独立性)です。
複数のトランザクションが行われても、単独処理と同じように
他の処理からの影響は受けないことを保証します。

# Durability(永続性)
トランザクションの更新結果は、障害が発生してもデータベースから失われないという保証です。
ハードウェアの障害が起こっても、更新処理に影響を与えないという要素です。
最後に、DはDurability(永続性)です。

この4要素いつまで経っても覚えられません。
どなたかいい覚え方ありませんかね…。
active storage使用時のseedファイル作成方法（ruby on rails）

## 使うコード
seeds.rbでデータを作る際にActive storageを使った画像データをどうすれば良いかわからなかったので、メモとして残しておきます！

結果から行くと...

```ruby
image: ActiveStorage::Blob.create_and_upload!(io: File.open(Rails.root.join("app/assets/images/hogehoge.jpg")),filename: 
```

このコードを使います！
```"app/assets/images/hogehoge.jpg"```がサンプルの画像データです。

## 例

```ruby
１０.times do
  Model.create!(
    image: ActiveStorage::Blob.create_and_upload!(io: File.open(Rails.root.join("app/assets/images/hogehoge.jpg")),filename: 'no_image.jpg'),
    column1: "aaaaaaa",
    column2: 3,
    column3: 5,,
    column4: "texttexttexttexttexttexttexttexttexttexttexttexttexttext",
    user_id: 2
  )
end
```
```10.times do```で10回繰り返せば10個データができるわけですね！
Error: Non-finite values are not allowed in the covariates.

#はじめに
MatchItのバージョン4.3.0ではmatchitのformulaの共変量に*character*型を使用すると，
``Error: Non-finite values are not allowed in the covariates.``
とエラーが出てしまうというお話です．

*character型*の共変量を*factor*型に変換するか、MatchItを4.2.0にダウングレードすることで解決できます．

#状況
[効果検証入門〜正しい比較のための因果推論／計量経済学の基礎](https://www.amazon.co.jp/dp/B0834JN23Y/)のコードの写経をしていた所，
傾向スコアマッチングの章で

```r:ch3_pscore.R
> m_near <- matchit(formula = treatment ~ recency + history + channel，
                  data = biased_data，
                  method = "nearest"，
                  replace = TRUE)
> ###エラー: Non-finite values are not allowed in the covariates.
```
というエラーが出現しました．

※ formula内の``channel``のみ*character*型．``recency``と``history``は*double*型．

#環境
windwos 10 
R version 4.1.1

```r:MatchIt以外で使用しているライブラリ
library("tidyverse")
library("broom")
library("WeightIt")
library("cobalt")
library("Matching")
```


#原因
[MatchIt4.3.0のコード](https://rdrr.io/cran/MatchIt/src/R/matchit.R)(2021/9/13更新)によると，

```r:matchit.r
> if (any(!is.finite(covs[[i]]))) stop("Non-finite values are not allowed in the covariates."， call. = FALSE)
```

の部分が該当するようです．
``!is.finite()``は数値型や*factor*型は``FALSE``，*character*型は``TRUE``となり，これが*character*型でエラーが出ている原因のようです．

```r:matchit.r
> if (is.character(covs[[i]])) covs[[i]] <- factor(covs[[i]])
```

と次の行にはあるので順番を間違えた可能性も．

#解決策
*character型*の共変量を*factor*型に変換するか、MatchItを4.2.0にダウングレードすることで解決できます．
どちらでも解決できるので，必要に応じて使い分けてください．

##character型の共変量ををFactor型に変換する
共変量として渡すものをfactor型に変換します．

```r
> biased_data <- mutate(biased_data，channel=as.factor(channel))　#factorへ変換
> m_near <- matchit(formula = treatment ~ recency + history + channel，
                  data = biased_data， 
                  method = "nearest"， 
                  replace = TRUE) 
```

再現にこだわらないのであればこちらで問題ないと思います．

##MatchItを4.2.0にダウングレードする
CRANからMatchIt4.2.0をダウンロード，再実行します．

[R パッケージのバージョンを修正する](https://docs.microsoft.com/ja-jp/azure/databricks/kb/r/pin-r-packages)によるとダウングレードの方法は以下の三通りあるそうです．

> - devtools パッケージ を使用します．
> - CRAN アーカイブ からパッケージ ファイルをダウンロードして インストールします．
> - CRAN スナップショットを使用します．

今回は**CRANアーカイブからパッケージファイルをダウンロードしてインストール**する方法で実行しています．

MatchItのアーカイブは以下のリンクからダウンロードできます．

https://cran.r-project.org/src/contrib/Archive/MatchIt/

適当な場所に保存して

```r
> remove.packages("MatchIt") #MatchItパッケージの削除
> install.packages("パッケージをダウンロードしたディレクトリ/MatchIt_4.2.0.tar.gz"， repos = NULL， type = "source")
```

読み込めれば完了です．

```r
> Warning in install.packages :
   パッケージ ‘MatchIt’ は使用中のため，インストールされません 
```

とエラーが出る場合は

```r
> detach("package:MatchIt"， unload=TRUE)
> remove.packages("MatchIt") #MatchItパッケージの削除
> install.packages("パッケージをダウンロードしたディレクト/MatchIt_4.2.0.tar.gz"， repos = NULL， type = "source")
```

Rで読み込んだライブラリをunloadしてからパッケージを削除して再インストールすれば完了です．

https://qiita.com/kawachi/items/3c7d1d44a7df43a47987

#参考文献
https://github.com/ghmagazine/cibook/tree/master/R

https://stats.biopapyrus.jp/r/basic/package.html
TemplateMethodについて勘違いしていたこと

# はじめに

本記事はTemplateMethodについての筆者の勘違いをまとめます。

# オーバーライドできるメソッドはTemplateMethodたりえない

例えば計算機の基底クラスであるCalculaterBaseクラスで足し算の前処理をMethodとして切り出して、サブクラスがオーバーライド可能にした場合を考えます。

```cs
class CalculaterBase
{
    /// <summary>
    /// 足し算をする。
    /// </summary>
    int Add(int arg1, int arg2)
    {
        OnAdding(arg1, arg2);

        return arg1 + arg2;
    }

    /// <summary>
    /// 足し算の前処理
    /// </summary>
    virtual OnAdding(int arg1, int arg2)
    {
    }
}
```

基底クラス(つまりは具象でないクラス)にメソッドを用意して、具象クラス側で実装をオーバーライドすることでカスタマイズできるからTemplateMethodに近いのではと私は思っていたのですが、これはただのvirtualメソッドです。
TemplateMethodは、抽象クラスでいくつかの抽象メソッドを利用して処理の流れだけをあらかじめ決めて、具象クラスがそれらの抽象メソッドを実装するパターンです。抽象メソッドを実装することで具象クラスごとに処理の内容のカスタマイズを可能にし、処理の流れが変わった場合にも抽象クラスだけを変更すればよくなるという利点があります。
なので、大事なのは抽象メソッドが抽象クラスに存在し、それを具象クラスは必ず実装する必要がある点だと思います。
ある振る舞いを追加したい具象クラスのためにvirtualメソッドを用意する場合には、そのメソッドのオーバーライドは強制されないので、TemplateMethodパターンにはなりえないと思います。

# まとめ

この記事では筆者がTemplateMethodについて勘違いしていたことをまとめました。
デザインパターンの意味やメリットをよく考えないと誤った使い方をしてしまうと強く認識したので、注意したいですね。
StepFunctionsでAWS SDK統合が使えるようになった

# やれること

今まではDynamoDBでqueryするときなどで, Lambdaを呼んでaws-sdkを利用して色々叩いていました.
これがなんと, StepFunctionsのStateから直接叩けるようになりました🎉

![スクリーンショット 2021-10-01 115349.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765956/d1ef2842-3bfb-1220-2c7f-e38b83c50477.jpeg)![スクリーンショット 2021-10-01 125948.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765956/0476cbc6-f3b0-2385-9116-9f6f7e175f30.jpeg)


## 例

DynamoDBにQueryを発行してみます. SDKを利用するときに入れる値と同じ値を入れるだけです.

```jsonc
{
  // ...
  "States": {
    "ExecuteQuery": {
      "Type": "Task",
      "Resource": "arn:aws:states:::aws-sdk:dynamodb:query",
      "Parameters": {
        "TableName": "MyTable",
        "KeyConditionExpression": "#pk = :pk AND begins_with(#sk, :sk)",
        "ExpressionAttributeNames": {
          "#pk": "Key",
          "#sk": "Value"
        },
        "ExpressionAttributeValues": {
          ":pk": {
            "S.$": "$.input.hoge"
          },
          ":sk": {
            "S": "fuga_"
          }
        }
      },
      "Retry": [
        // ...
      ],
      "Catch": [
        // ...
      ],
      "InputPath": "$",
      "ResultPath": "$.ExecuteQuery",
      "OutputPath": "$",
      "Next": "aaa"
    }
}
```

出力はこんな感じ

```jsonc
{
  "name": "ExecuteQuery",
  "output": {
    // ...
    "ExecuteQuery": {
      "Count": 1,
      "Items": [
        {
          "Value": {
            "S": "fuga_12345"
          },
          "Key": {
            "S": "hogehoge"
          }
        }
      ],
      "ScannedCount": 1
    }
  },
  "outputDetails": {
    "truncated": false
  }
}
```

あとはStateMachine内で適当に使いましょう

## 使えるAWS SDKの中身

多分ほぼ全部使えます 👏👏👏

ただ, StepFunctionsの仕様上大きなデータは引き回せないため, S3周りなどで小さいデータ以外を扱う場合は, 普通にLambdaでするほうが安定すると思います.

## さいごに

ようやくStepFunctionsでノーコードがまともにできるようになるのでしょうか, 期待しています.
改行コード入り文字列を"\r"、"\n"、"\r\n"でそれぞれ文字列変換(replace)してみた結果

```
param = "A\rB\nC\r\nD"
r = param.replace('\r', '')
n = param.replace('\n', '')
rn1 = param.replace('\n', '').replace('\r', '')
rn2 = param.replace('\r\n', '')
print(r)
print("=================================")
print(n)
print("=================================")
print(rn1)
print("=================================")
print(rn2)

# 結果
#AB
#C
#D
#=================================
#DC
#=================================
#ABCD
#=================================
#B
#CD
```