OmniAICreator/Qiita-1.07M huggingface dataset:
NimでWebAssemblyをやる【2021年版】

最近のところ、WebAssemblyがアツいですね。NimでもWebAssemblyを試してみたという内容の記事がいくつか見つかります。
というわけで、$n$番煎じ($n \geq 2$)どころかもはや出涸らし気味ですが、Nimでもお手軽にWebAssemblyできるよということを知ってもらうために、この場を借りて私もやってみたいと思います。

## 必要なもの
- Nim
- emscripten

以上です。

## やり方

### 1. Nimのプロジェクトを作る
まずは普通に作ります。プロジェクト名は `nim_emscripten` として話を進めます。

```sh
$ nimble init
```

できたnimbleファイルの設定のうち、次の2つを以下のように書き換えます。

```nim
# 拡張子まで書く必要あり。
bin           = @["nim_emscripten.html"]
# c以外はダメ(ではないが、諸々面倒なのでcだけにする)
backend       = "c"
```

注意点として、binに指定する出力ファイル名には拡張子まで含める必要があるというものがあります。`.html` であればemscriptenが出力するデフォルトのHTMLが出力され、そのままプレビューできますし、`.js` であれば、wasmを読み込むjsのコードが出力されます。拡張子を指定しなかった場合、たとえばWindowsであれば拡張子が `.exe` なのに中身がjavascriptという謎ファイルが出力されますし、Linux/MacOSでも同様に拡張子なしのjsファイルが出力されます。

### 2. コンパイラオプションを書く
emscriptenでは、gccのかわりにemccを使います。Nimが吐いたCのソースコードをemccでコンパイルするために、コンパイラオプションを設定する必要があります。そこで、nimbleファイルと同じディレクトリに以下のような `nim.cfg` ファイルを作ります。

```nim:nim.cfg
cc = gcc
# windowsの場合は、"emcc.bat"にする
gcc.exe = "emcc"
# windowsの場合は、"emcc.bat"にする
gcc.linkerexe = "emcc"
gcc.options.linker = ""
# WebAssemblyのVMは32bitアーキテクチャです。
# なので、i386(32bit architecture)をターゲットにします。
cpu = "i386"
# windows.hなどのOS固有のヘッダは利用できないため、常にlinuxをターゲットとしてビルドします。
os = "linux"
# コンパイラに渡すオプションです。
# WASM=1 を指定しなかった場合、emccはデフォルトでasm.jsを出力します。
# EXIT_RUNTIMEが1 (またはNO_EXIT_RUNTIMEが0)の場合、main関数の実行が完了した後にjsから
# Nimで書いたコードが呼べなくなります。
# EXPORTED_RUNTIME_METHODSには、ccall または cwrap、もしくはその両方を指定します。
# 両方を指定する場合は、EXPORTED_RUNTIME_METHODS=ccall,cwarp のようにコンマで区切ります。
passC = "-s WASM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=ccall -O3"
# リンカに渡すオプションは、コンパイラに渡すものと揃えます。
passL = "-s WASM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=ccall -O3"
```

これでプロジェクトのセットアップは完了です。あとは好きにコードを書くことができます。

### 3. コードを書いてみる

例えばこんなコードを書いてみます。

```nim:src/nim_emscripten.nim
var memo = newSeq[int]()

# void __attribute__((used)) hello();
proc hello() {.exportc, codegenDecl: "$# __attribute__((used)) $#$#".} =
  echo "Hello, World!"

# int __attribute__((used)) fibonacci(int n);
proc fibonacci(n: int): int {.exportc, codegenDecl: "$# __attribute__((used)) $#$#".} =
  if (n < 2):
    return n
  else:
    if memo.len < (n-1):
      memo.add(fibonacci(n - 1) + fibonacci(n - 2))
    return memo[n-2]

hello()
echo fibonacci(10)
```

javascriptから呼びたいコードには、`exportc` プラグマと、 `codegenDecl` プラグマをつける必要があります。`codegenDecl` プラグマで変なコード片を生成する必要があるのは、emccがデッドコードを削除してしまったり、インライン関数化する最適化を施してしまったりするからです。
コンパイラ対して、コンパイラの把握していない場所で関数が使用されていることを明示的に通知しなかった場合、吐かれたWebAssemblyのバイナリにはその関数が含まれないことがあります。
ちなみに、emscriptenのツールキットにおいては、この`__attribute__((used))`は`EMSCRIPTEN_KEEPALIVE`マクロとして提供されています。

このコードを保存したら、普段通りに `nimble build` します。
生成された `nim_emscripten.html` を開き、こんな画面が表示されたら成功です。

![emscripten output](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209421/97305df5-c6e8-676d-90d5-7c88f99118c7.png "emscriptenの出力結果")

javascriptからfibonacciを呼び出すには、以下のようにします。

```js:fibonacciを呼び出す
console.log(ccall('fibonacci', Int32Array, Int32Array, new Int32Array([10])));
// -> 55
```

## 最後に
WebAssemblyのツールキットが随分と充実してきているように感じます。昔はもっとしんどかった。
NimがCのコードを吐いてくれるので、かなりお手軽にWebAssemblyを試すことができました。
Dynamics365/PowerAutomate簡易的な承認フローのサンプル

Dynamics365からPowerAutomateの承認機能を利用して承認を行う簡単なサンプルを説明させていただきます。
■処理概要 
①営業案件のレビューの設定をトリガーとしてPowerAutomateを起動する。
②PowerAutomateの承認機能を利用して、承認依頼を送信する。
③承認された場合、営業案件の承認状態を「承認」に更新する。
■画面イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/cc8581d0-7103-661f-b703-95d69723519b.png)
■PowerAutomate実装イメージ
①ソリューションにて自動化→クラウドフロー→自動を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/a43b6e34-dab3-6120-1285-7d731f2ee288.png)
②フロー名に「レビュー者承認通知」、トリガーに「行が追加、変更、または削除された場合」を選択して、「作成」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/c5493f84-0056-8b91-b802-68f4fb082e25.png)
③以下のようにトリガーを設定する。列を選択するに「new_reviewperson」(レビュー者)を入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/e266efc6-45be-98cd-db77-c543f3e77d32.png)
④「メール情報と承認者メールアドレス取得」アクションを追加し、メール内容情報と承認者メールアドレスを取得する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/3215ed34-ae59-0422-17a3-ae727982ff4e.png)
⑤「開始して承認を待機」アクションを追加する。レビュー者へ承認を求めるメールを送信する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/2e181347-6063-3a72-858d-db8a934fbd91.png)
⑥「承認するかの判定」条件アクションを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/c4dfc7dc-8611-bd5c-2f71-f91b1e3e1faa.png)
⑦承認されたら（はいの場合）、「承認状態」と「社内レビュー完了」フィールドを更新する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/fc3a1cdd-2f41-d238-e841-647ae0171cef.png)
⑧実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/6ee1cbb6-f5e0-dbb8-48a5-b8f0bd69d11b.png)
今更ながらQiitaを始めます。

2021/12/01より投稿をはじめます。

<h1>今日の収穫</h1>


https://www.northdetail.co.jp/blog/1749/



---

学習の中でSVGアニメーションは飛ばしていたのでこの投稿は新しい気づきとなった。

就職活動が始まったので企業探しをしている中で、社内Blogの内容が自分にマッチすると選択がしやすい。

選考備考にOSS活動の提出が必要とあったので、始めるきっかけとなったことに感謝をしたい。

ポンコツコーダーをたたき上げて頂ける企業など存在しないので、精進します。
コロナ禍の地方民における技術同人活動って結局どうだったのか２０２１

本記事は [技術同人誌・商業執筆 Advent Calendar 2021](https://adventar.org/calendars/6410) の２日目です。

昨日(12/1)はうめりんさんの[技術同人活動履歴まとめ](https://qiita.com/umerin/items/e10143b32cc436b0e3dd)です。

明日(12/3)はさっぴー川原さんの[2021年の技術同人活動を振り返る #技書博 #技術書典]
(https://kawahara-ci.hatenablog.com/entry/2021/12/03/furikaeri)です。

## 自己紹介

受諾開発ＳＥを１５年弱やったあと、現在社内ＳＥを５年強やってるのですがそろそろ転職検討中の人です

## はじめに

今年ってコロナ禍などもあって非常に特殊な年だったので、備忘も兼ねて書き残しておこうかな・・・と

## 経緯

そもそもの技術同人誌活動を始めたきっかけは２０１９年に開催されたイベント[「技術書を執筆しよう！初心者向け勉強会＠大阪」](https://gishohaku.connpass.com/event/142422/)です。

技術書ってそんな楽に組めるようになっているのかという驚きがあり、ちょっとしたカルチャーショックを受けました。
（母校の大学のサークルが技術系サークルで、年１で技術会報を書いて発行し、ＯＢに送付する運用だったので、頑張って版元を作って輪転機回してたんですよね…　あの頃と比べると隔世の感が。）

ここでありがたいことに、第２回技術書同人誌博覧会に寄稿しませんか？というお声掛けを頂きまして、
基本情報技術者試験のカリキュラム変更に伴う試験傾向の予測・解析記事を寄稿させて頂きました。

実はその内容については全文Qiitaにも掲載済みです。
[情報処理技術者試験の基本情報技術者試験における、試験範囲「試験要綱」Ver. 4.2～4.4改定について(2020CBT試験※2021/1から)](https://qiita.com/ditflame/items/c6d36bedfcebcda475e6)


そこからの流れで[おやかたさん(@oyakata2438)](https://twitter.com/oyakata2438)にお声掛けを頂いておやかたさんのサークルの合同紙に寄稿する形で執筆するようになり、現在に至ります。

※細かい話は去年書いたアドカレ記事の方が詳しい気がする(何故か去年はnoteに書いているが)

https://note.com/ditflame/n/n51f89cc1ed0a


## 今年あったこと（去年までの流れで）

３冊執筆に関わり（基本的には寄稿するだけのスタンスですが要望があればレビューなどもしてます。）
１冊は今記事を書いているところです。

 * [エンジニアのための目標設定の技術(著：親方Project)](https://nextpublishing.jp/book/13635.html)

 * [エンジニアのためのカンファレンス参加の楽しみ方(著：親方Project)](https://nextpublishing.jp/book/13842.html)

 * [カジュアル面談のトリセツ(著：ブライトシステム)](https://techbookfest.org/product/4725849699909632?productVariantID=5146928268443648)

 * （冬の新刊で安定化電源の話を執筆中…）


## 今年新たににできたこと（１）：何故か会社の金で技書博にスタッフ参加できた

弊社の場合、会社から別にこの手のイベントに補助が出ているわけではないのですが、うっかり前日に福島県への出張が発生しまして、ついうっかり（実費で）東京で一泊してしまったので、技書博にスタッフ参加させて頂く事になりました。
（ほとんどは移動費なので実質タダみたいなもんです。　いやーうっかりうっかりｗ）

なお一般参加じゃなくスタッフ参加したのは、[ありあきさん(@ariaki4dev)](https://twitter.com/ariaki4dev)が人足りない助けてオーラを出してたせいですね（笑）

リアルイベントは良いですね…　コロナ禍ではありましたがうまく参加できてよかったです。


## 今年新たににできたこと（２）：なんか他の方の技術同人誌もレビューをさせてもらえる機会が増えた

随分と技術同人誌関連の知り合いが増えたため、イベント前になると「技術同人誌レビューしていただきたいです」的なのが私の元にも流れてくるようになりました。

そんな経緯でレビューさせていただいたのが以下の本。

サークル「共鳴効果」さんのS-REACH本です。
https://techbookfest.org/product/4911720315224064?productVariantID=5995147198201856

化学は実はけっこうちんぷんかんぷんなのですが（高校から工業科を選んだ関係で化学は中学止まりでして…）
データベースについては一通り見れるかなー　と思ってその観点を中心にフルレビューさせて頂きました。

（結局私の環境で動作検証までやって、その動作検証フィードバックまで全部お伝えすることになったのですが、それはそれで面白かったので大変良かったです（笑））

レビューは勉強になりますし力が本当につきますね…　タダで見させてもらえる時点で感謝しかないです。


## おわりに

コロナ禍の割には意外にアウトプット量としては去年と変わらなかったような印象です。チャネルが増えたのが大きいのかなやはり。

昨今のコロナ禍もオミクロン株やらなんやらで緩めたり絞ったりという状況が続く昨今ですが、来年には心穏やかにイベントが開催できるようになっているといいな…　と節に願います。

あと、来年どこ転職してるんだろうな私…（笑）
コンテナからコンテナを操作する

## なぜコンテナからコンテナを操作するのか？

「コンテナからコンテナを操作したい！」なんて思ったことはないでしょうか？
以下は私が開発したブラウザでプログラムを実行できるアプリのアーキテクチャ図です。いわゆる、Paiza.IOのようなものです。

![online-code (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1295942/515cf07c-3639-9758-8059-be36f44237dc.png)


あれ？コンテナ（Golang）からコンテナ（Python）に矢印が向いていますよね。これはコンテナ（Golang）で外部コマンドを叩き、公式のPython Imageからコンテナを起動しPythonファイルを実行してもらい結果を取得しています。

そんなことしなくてもEC2にDockerをインストールしてホストからDocker起動する方が良くね？って思うかもしれません。ですが筆者はどうしてもECSにまるっと任せたかったのです。その方がEC2に１からインストールしなくていいしデプロイも簡単だと思ったからです。（興味本位でDockerからDockerを起動したいと思ったのもある）

## コンテナからコンテナを操作する方法
DinD(Docker in Docker)とDooD(Docker outside of Docker)の２パターンがあります。詳しく見ていきましょう。

## DinD(Docker in Docker)

Dockerがインストールされているコンテナを使用しコンテナ内でホストとは別にDockerデーモンを動かす方法です。

https://hub.docker.com/_/docker/

現在起動中のコンテナを確認してください。（最低１つあると今回の検証が理解できます）

```shell
$ docker ps
```
dockerがインストールされているコンテナをバックグラウンドで実行します。

```shell
$ docker run --privileged --name dind -d docker:dind
```
コンテナの中に入ります。

```
$ docker exec -it dind sh
```
起動中のコンテナを確認してください。何も表示されないはずです。

```
$ docker ps
```

DinDではホストのDockerとは別のDockerが利用することができます。

## DooD(Docker outside of Docker)

コンテナ側からホストのdocker.sock (/var/run/docker.sock)をマウントすることでコンテナ上のDockerコマンドはホスト側のDocker環境で実行される。Dockerがインストールされているコンテナを使用するのはDinDと同じ

先程と同じように起動中のコンテナを確認します（最低１つあると今回の検証が理解できます）

```shell
$ docker ps
```

コンテナを起動して中に入ります。この時、ホストのdocker.sockをマウントする。

```shell
$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker sh
```

起動中のコンテナを確認してください。ホストのコンテナ一覧が表示される。

```shell
$ docker ps
```

このようにDooDではホスト側のDocker環境を共用することができる。

## マルチステージングビルド

じゃあコンテナ（Golang）にDockerをインストールしなければコンテナ（Python）を使用することができません。結論から言うと今回はマルチステージングビルドを用いました。

```dockerfile:Dockerfile
FROM golang:latest AS builder

RUN mkdir /go/src/work

WORKDIR /go/src/work

COPY main.go .

RUN CGO_ENABLED=0 GOOS=linux go build main.go

FROM docker:latest

COPY --from=builder /go/src/work/main ./

EXPOSE 10000
```


## おまけ（コンテナ間マウント）

このアプリを作成する上でコンテナ間マウントという技を使ったのでメモ代わりに --volumes-from ＜マウント元のコンテナ＞ とすることでコンテナ間マウントができる。サンプルは以下の通りです↓

```shell
$ docker run -it --volumes-from code python bash
```

しかしここで注意です、ECSのタスク定義にて決定したコンテナ名になっていないようでコンテナの名前をつけ変えるには以下のようにすることで名前を変更できます。

```
$ docker rename <Container ID> code
```


# 参考文献

https://blog.nijohando.jp/post/docker-in-docker-docker-outside-of-docker/

https://qiita.com/t_katsumura/items/d5be6afadd6ec6545a9d
OpenCV自分用メモ

メモです．

### 動画ファイル読込み
```c++
video.open("D:\\Download\\cart1.mp4");
if (video.isOpened() == false) {
  return 0;
}
video >> currentFrame;  //1フレームずつ取り出し
```

### 動画ファイル書き出し
　そのファイル名でファイルが存在する場合は，最後尾に追加する

```c++
int width = video.get(cv::CAP_PROP_FRAME_WIDTH);
int height = video.get(cv::CAP_PROP_FRAME_HEIGHT);
int fps = video.get(cv::CAP_PROP_FPS);
int fourcc = cv::VideoWriter::fourcc('M', 'P', '4', 'V');
cv::VideoWriter output("D:\\Download\\cart1a.mp4", fourcc, fps, cv::Size(width, height),0);
output << calcFrame;  //1フレーム書き込み
```

### グレースケール化
`cv::cvtColor(currentFrame, calcFrame, cv::COLOR_BGR2GRAY);`

### GaussianBlur（ガウシアンブラー）
`cv::GaussianBlur(currentFrame, currentFrame, cv::Size(3,3), 0);`

### Canny Edge(キャニーエッジ）
`cv::Canny(currentFrame, currentFrame, cannyValue1, 200);`

### absolute difference（2枚の画像の差分）
`cv::absdiff(baseFrame, currentFrame, calcFrame);`

### erode
cv::erode(calcFrame, calcFrame, cv::Mat(), cv::Point(-1, -1), 1);  //カーネル3x3
cv::erode(calcFrame, calcFrame, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)), cv::Point(-1, -1), 1);  //カーネル5x5
	

### 2値化

```c++
cv::cvtColor(currentFrame, currentFrame, cv::COLOR_BGR2GRAY);  //まずグレースケールにする
cv::threshold(inputFrame, outputFrame, value, 255, cv::THRESH_BINARY);  //value＝閾値
```

### morphologyEx（クロージング）
`cv::morphologyEx(currentFrame, currentFrame, cv::MORPH_CLOSE, cv::Mat(), cv::Point(-1, -1), 1);`

### BackGroundSubtractor
```c++
cv::Ptr<cv::BackgroundSubtractor> bgsubtractor = cv::createBackgroundSubtractorMOG2();
bgsubtractor->apply(calcFrame, calcFrame, 0);  //背景更新しない
bgsubtractor->apply(currentFrame, calcFrame, 1);  //最終フレームで背景を更新
```
Raspberry Pi上のenebular editorでフローを自動起動

enebularウフル社員版のアドベントカレンダー2日目の記事はちょっとした小ネタです。
# RaspberryPi上でも動作するenebular editor

enebularのデスクトップアプリケーションである[enebular editor](https://docs.enebular.com/ja/EnebularEditor/)は、RaspberryPi上でも動作するように今年の2月にリリースされました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/ef9150af-b55b-b8cf-2ce1-5d0b797e979f.png)

これにより[enebular-agent](https://docs.enebular.com/ja/EnebularAgent/Overview.html)を使わなくてもRaspberryPi固有の機能を使うフローの開発を行うことができるようになりました。

RaspberryPi上のターミナルにて、以下のコマンドでインストールできます。(Nodejsがインストールされていることが前提です)

```
wget -4qO- https://enebular.com/editor-install | sudo -u "$USER" -E bash -s -- --arch=arm
```
※"$USER"はインストールするユーザー名です。基本はpiで良いと思います。

しかし、enebular editorは基本、あくまでエディターなのでRaspberryPiを画面無しで起動してフローを動作させることがそのままではできません。
本記事では、RaspberryPiを起動した際、自動的にフローを動作させる方法を紹介します。

# フローを指定して起動

enebular editorは以下のように起動オプションで、```フローID```やログイン情報を指定すると直接フローを起動することができます。（パスは標準でインストールされるパスです。）

```
/home/pi/Applications/enebular-editor/AppRun.AppImage --flow_id=フローID --email=enebularログイン時のメールアドレス --password=enebularログイン時のパスワード
```

　```フローID```というのは、enebularでフローのOverview画面を開いたときのアレです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/d4c26430-22a3-2021-1ac3-a5636391e974.png)

# 起動時に自動起動
OSの機能としてデスクトップアプリを自動起動する方法があるのでそれを使います。

まず、以下のコマンドで.desktopファイルを作って下さい。ファイル名は他でも良いです。

```
$ sudo touch /etc/xdg/autostart/enebular-editor.desktop
```

次に作成したファイルを編集します。

例：nanoで開く

```
$ sudo nano /etc/xdg/autostart/enebular-editor.desktop
```
ファイルに以下のようにenebular editorの起動コマンドを書きます。```フローID```やログイン情報は書き換えて下さい。

```
[Desktop Entry]
Name=PiCounter
Exec=/home/pi/Applications/enebular-editor/AppRun.AppImage --flow_id=フローID --email=enebularログイン時のメールアドレス --password=enebularログイン時のパスワード
```
これで再起動すればenebular editorが自動的に起動し、指定したフローを開いて動作します。
ただし、enebular editorはenebularからフローを読み込むので、インターネットに繋がっていることが前提です。

# 起動時間について
先程も書いたとおりenebular editorはenebularからフローを読み込んでインストールを行うため、起動にちょっと時間がかかります。フローにもよりますが電源を入れてからフローが起動するまで、RaspberryPi 4Bで```3分```程度、RaspberryPi 3Bで```6分```程度かかります。

この点に関しては、enebular-agentの場合はデプロイされたフローを開くだけなので```50秒```程度です。
そのため、enebular editorはあくまでプロトタイピング用途でお考えてもらえればと思います。
実運用する場合は、enebular-agentをぜひ。

enebular-agentのインストール方法については、以前にも詳しく書いているので、ご参考に！
[enebular-agentをRaspberry Piにインストールする](https://qiita.com/jksoft/items/e007c94e7673374ddf7c)
TypeScriptのテンプレートリポジトリ集（TS Templates）をつくった

TypeScriptプロジェクトを新たに始める際、毎回一から環境を構築するのは面倒なものです。
そこで、テンプレートリポジトリをつくってGitHubの[TS Templates](https://github.com/ts-templates/)というOrganizationで公開することにしました。

## TS Templatesのテンプレートリポジトリ

TS Templatesでは、実行環境ごとに最適化されたいくつかのテンプレートリポジトリを公開しています。
今のところは、Node.jsのLTSバージョン向けに4つのリポジトリがあります。

- [ts-templates/node10](https://github.com/ts-templates/node10)
- [ts-templates/node12](https://github.com/ts-templates/node12)
- [ts-templates/node14](https://github.com/ts-templates/node14)
- [ts-templates/node16](https://github.com/ts-templates/node16)

これらの違いはほぼNode.jsのバージョンのみですが、一部のライブラリは古いNode.jsバージョンのサポートを終了しているため、古いバージョンのままになっていたりします。
たとえば、ESLintは[v8.0.0](https://github.com/eslint/eslint/releases/tag/v8.0.0)でNode.js v10/v13/v15のサポートを終了したので、ts-templates/node10ではv7のままです。[^1]

## TS Templatesの特徴

READMEにも記載していますが、TS Templatesには以下のような特徴があります。

- [ESLint](https://eslint.org/) + [JavaScript Standard Style](https://standardjs.com/)
  - pre-commitフックで実行（[husky](https://typicode.github.io/husky/)と[lint-staged](https://github.com/okonet/lint-staged)による）
  - プルリクエストで実行（GitHub Actionsによる）
- [Jest](https://jestjs.io/)によるテスト
  - プルリクエストで実行（GitHub Actionsによる）
- Node.jsのバージョンを[nvm](https://github.com/nvm-sh/nvm)で管理
- 依存パッケージのバージョンを[Renovate](https://renovatebot.com/)で管理

初めて見る人でもプロジェクト構成を把握しやすいように、各種設定はなるべくシンプルに留めています。
それもあって、TSConfigでは[TSConfig Bases](https://github.com/tsconfig/bases)を使っています。

https://qiita.com/munieru_jp/items/a67ac782bbf099d90128

## TS Templatesの課題

GitHubのテンプレートリポジトリではリポジトリの内容がそのまま使われるので、動的にファイルを生成するようなことはできません。
これでは、パッケージマネージャーとしてnpmではなくYarnを使いたかったり、テストフレームワークとしてJestではなくMochaを使いたいといったユースケースに対応できません。
また、GitHubにリポジトリをつくらなければならないという制約が、ちょっと試してみたいユーザーにとっては障壁となりえます。
したがって、[create-nuxt-app](https://github.com/nuxt/create-nuxt-app)のように対話式で選んだ構成のプロジェクトを生成できるようなCLIツールをつくるのが目下の課題です。[^2]

[^1]: https://github.com/ts-templates/node10/blob/master/.github/renovate.json
[^2]: https://github.com/orgs/ts-templates/projects/2#card-63436672
プロキシが原因でT-DASHを起動できない問題の対処

# この記事について
T-DASHという自動化ツールのOPENβ版がリリースされていたので、
インストールしてみたところツールが起動できない問題が発生した。
その対処方法に関して主に記載しています。

# 使用した環境・バージョン
- OS : Windows10 64bit
- ブラウザ：Microsoft Edge 96.0.1054.34
- T-DASH： 0.1.004b

## 事象
T-DASHをインストール→EXE実行→取得したライセンスキーを入力して認証したところ下記エラーが発生して起動ができなかった・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2343225/e1f52a27-5323-2417-88f4-7669e7944ea9.png)

## 問い合わせてみた
こんな感じで丁寧な回答が返ってきた。

>お問い合わせいただきました内容を確認させていただきましたところ、
>貴社のプロキシサーバーから弊社のライセンスサーバーへ
>アクセスができないことが原因の可能性が高いと思われます。

>対処方法としては以下となります。
>大変お手数お掛けして申し訳ございませんが、ご確認のほどよろしくお願い致します。

>①プロキシの例外設定でライセンスサーバーのホスト「mypage.quintee.io」を追加して
>　T-DASHアプリの起動および認証を行う
>　参考URL
>　https://milestone-of-se.nesuke.com/nw-basic/grasp-nw/proxy-configuration/
>②プロキシサーバー上でライセンスサーバーのホスト「*quintee.io」をホワイトリストに追加して
>　T-DASHアプリの起動および認証を行う
>③プロキシサーバーを使わずにT-DASHアプリの起動および認証を行う

確かに、、開発用PCはプロキシを経由しているのでアクセスできるサイトが制限されているかも・・

## 回答の対処をしてみた
### ①プロキシの例外設定でライセンスサーバーのホスト「mypage.quintee.io」を追加してT-DASHアプリの起動および認証を行う

`Windowsの設定 -> ネットワークとインターネット -> プロキシ`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2343225/440ad7c5-322a-c2ab-36d3-8e7dab68b1eb.png)

### 再度、T-DASH起動してライセンス認証する

#### 起動できた！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2343225/fb0feb97-4c6b-c383-5e21-0d891955f613.png)

## サイトを一回見てみると
#### がっつり書いてあった・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2343225/21333f2f-0582-e367-6ffe-aa078b778ff3.png)

```urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='mypage.quintee.io', port=443): 
Max retries exceeded with url: /tdash/api/v1/license-key (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection
```
↑このメッセージはおそらくライセンスサーバーにアクセスできてないよってことぽい

T-DASHのインストーラが置いてある下記サイトへ開発用PCではプロキシ問題でアクセスできなかったので、アクセスできる違うPCから開発用PCにインストーラを置いて起動したのがダメだったようだ・・・

https://mypage.quintee.io/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2343225/2a6cdc33-16bf-1bbf-c3ae-bdaab9b6b418.png)


## まとめ
- `https://mypage.quintee.io/`にアクセスできる環境じゃないとツールは起動しない
- プロキシサーバーの例外設定ができない環境の場合は②の対処にあるプロキシサーバー側で`mypage.quintee.io`ドメインをホワイトリスト追加しないとだめそう

## 最後に
外に繋がる環境であれば確かに導入がすごいカンタンでした。
(seleniumとかは環境構築だけですごい時間かかるので・・・・・)
次はT-DASHを色々動かしてみてローコードでの自動化に挑戦してみたいです。
make, configure, ビルド周りの知識を学ぶのにいい記事


この記事最高！ めっちゃわかりやすい。10年前の内容なのに、いまだに同じエラーが発生して同じ手順でトラシューできたりする。神。

> 「ビルド」という作業は何を指しているのか
> https://atmarkit.itmedia.co.jp/ait/articles/1105/23/news128.html

第６回から10個くらい連続で読んだ。神だった。


さっとメモ


- configure
    - Makefileを作る
    - 環境ごとに Makefileを変えるため。例えば gcc コマンドをintel特有の icc にしたりとか。
- make
    - 実行ファイル (command) を作る
- makeナニソレオイシイノ
    - a + b を作って a+b にしたいとき便利
    - a + c もほしいとき
        - cにtouch c すると、a+bは変わらず a+c だけ再コンパイルしてくれる
    - make は単純に生成物の コマンド と、要素のファイルの mod timeを比較してるだけ。コマンドより新しいファイルがあったら依存部分を再コンパイルする。
- make install
    - Makefileのなかにある　`install:` の行を実行してるだけ。実態はとあるパスに makeで作ったコマンドcpしたり、manual filesをcpしたりしてる
- make clean
    - 作ったcommandや中間物であるところの .o ファイルを削除してきれいにする。もっかい makeすればそれらファイルは再作成される。
- Makefile
    - .PHONY:clean ってすると、pwdに clean というファイルが有っても実行できる、ダミー要素。makeはfileを作成するためのものだけど、ただコマンドを実行したいだけのときに使う。
    - all:
        - 一般的に make内のものを全部まとめて実行するために用意されてる。 make all で実行される。
    - macro
        - Makefileの中にCC=gcc 書いておくとgccでbuildされる。デフォは gccのsymlinkのcc. CC=echo ってするとただ出力されるだけになったりする
        - CC=gcc make でも同じことが起こる
    


# curl の 7.x.x が使いたいんじゃ！！っていうとき

curlが慣習的なbuildができると想定して書く（試してない

```
wget curl の tarball
tar xzvf
cd 
./configure --prefix=/opt/curl-7.x.x/          <------- /optに置くのが監修ぽい。バージョン名指定すると楽。
make 
make install
できたら、必ず ldd でlibがリンクされてるか確認する

ldd /opt/curl-x.x.x/bin/curl
curl version的な
```

## condigureでコケる場合
ライブラリが足りない場合

```
yum search zlib
```
こんなんで探して、 `yum insatll zlib zlib-devel` を入れる。

-develは、こうしてbuildしたいときに使うヘッダファイル。makeするときは必須。


## lddに問題ある場合は 

```
LD_LIBRARY_PATH="/opt/curl-x.x.x/lib" /opt/curl-x.x.x/bin/curl
```

こうするとうまくいったりする


LD_LIBRARY_PATHはコマンドがlibを探すときに参照するパス。
defaultは /usr/lib , /usr/lib64 最近は64の方に大量に入ってる。
libを動的に参照する仕組みがdynamic linkで、ほとんどのコマンド/libがそうなってる

libから始まるのがそれ。
.so は static object だったっけ、なんだったけ

/usr/lib64 な中が symlinkだらけなのは、/usr/lib64でライブラリを共有してるけど、それだとバージョン依存壊れたときにだめじゃん。コマンドごとに違うバージョンどうやって使うの？ってのが、結局複数バージョンの .so を入れて、symlinkを参照するコマンドの数だけおいて、それぞれのコマンドが参照するのを切り替えてる。
データマネジメント入門

# この記事は何？

この記事は [ちゅらデータ Advent Calender 2021](https://qiita.com/advent-calendar/2021/churadata) 2日目の記事だよ。
1日目の記事は[こちら](https://qiita.com/Intel0tw5727/items/1ab1cb144564d3b516bf)。

データマネジメントシてますか？って来年は聞いていこうと思っているので、まずはみんなに入門してもらおうと思いこの記事を奏上いたします。

# データマネジメントとは

まずはデータマネジメントという用語の定義を知りましょう。
データマネジメント知識体系ガイドには下記のように書かれています。

>データマネジメントとは、データとインフォメーションという資産の価値を提供し、管理し、まもり、高めるために、それらのライフサイクルを通して計画、方針、スケジュール、手順などを開発、実施、監督することである。
「データマネジメント知識体系ガイド 第1章 1 イントロダクション」より

要するに、「データから価値を取り出す全てのこと」がデータマネジメントということなんですね。

お？
ということは
**データドリブン経営とか、DXとか、ビッグデータとかAIとか、ぜーんぶ、データマネジメントの中に含まれているのでは？？？？**

はい、実際そのとおりなんだと思います。
データから価値を得る組織はすべて大なり小なりデータマネジメントに取り組んでるんですね。

だから、データマネジメントの知識体系を抑えることは、とっても重要になるわけです。

# データマネジメントの対象者

データマネジメントは、**ITスキルと非ITスキルの両方が必要です**。

**テックとビズのどちらか片方が頑張るだけではデータマネジメントは成せません**。

なぜならデータから価値を取り出すにはビジネスや業務のスキルが必須ですし、そもそもデータを提供するにはテックの力が欠かせません。

だから、ITスキルを持ったテックと、非ITスキルを持ったビズの両者が必要になります。

# 用語整理：データとインフォメーション

ここで整理のために下記の用語の違いを抑えておきましょう。
両者は同じ実体を指す場合がありますが、コンテキストや呼ぶ人間によって名前が変わります。

- データ：事実を観測した値、またはそれを統計化された値、インフォメーションよりテック側の呼び方
- インフォメーション：データにコンテキストがふかされ意味を持った値、データよりビズ側の呼び方

例：売上金額は、単に金額としてみればデータですが、「その金額は売上である」というコンテキストを付与することでインフォメーションと呼べるようになります。

# データマネジメントの知識領域

データマネジメントには下記の知識領域カテゴリがあります。

- データガバナンス
- データアーキテクチャ
- データモデリングとデザイン
- データストレージとオペレーション
- データセキュリティ
- データ統合と相互運用性
- ドキュメントとコンテンツ管理
- 参照データとマスターデータ
- データウェアハウジングとビジネスインテリジェンス
- メタデータ管理
- データ品質

基本的にはこれらの知識領域をマスターして、データから価値を引き出し続けような！っていうコンセプトとなっています。

これらの知識領域の中で一つだけ特殊なのが、「データガバナンス」で、他の知識領域の基盤という位置づけです。

# 知識領域コンテキスト図

データマネジメント知識体系ガイドには、各知識領域には知識領域コンテキスト図と呼ばれる図が定義されており、その領域でどのようなアクティビティがあるのかや、成果物などが定義されています。

アクティビティには「計画」「開発」「運用」「統制」のように、データのライフサイクルを通じた活動が定義されているため、それらのアクティビティを必要に応じて参照するような使い方ができます。

# 進め方はDMBOKピラミッドを見ると良い

データマネジメント知識体系ガイドには、DMBOKピラミッドという、各知識領域やアクティビティの位置関係を示すピラミッドが紹介されています。
この図に従って、導入するフェーズごとにピラミッドの中心から徐々に知識領域を増やし、データから価値を取り出す高度な機能へ進むように、進め方も示されています。

自分の所属する組織の状況とフェーズを照らし合わせて使うことができて便利です。

# データマネジメント原則をいくつか紹介

ここでデータマネジメント原則をいくつか紹介したいと思います。

## データの管理はデータ品質の管理

データを管理するってなんだ？と普通は思うのですが、その質問に対する答えはデータ品質の管理と定義されています。
データ品質、すなわち、データが目的に沿っていることを保証することです。
そのためにはステークホルダの要求を理解し、実装し、それが要求に答えているかを計測していく必要があります。

## データマネジメントには予め計画が必要

アジャイルなど未知の領域へのアプローチがソフトウェア工学では発展してきておりますが、データマネジメント領域では計画が必要とされます。
なぜかというと、データマネジメントを推進したいはずの組織にはすでに複雑な業務プロセスが走って日々データが生まれているはずだからです。
それらを把握しコーディネートしていくのにはアジャイルな探索的アプローチではなく、既存のドキュメントを把握し、しっかりと計画立てて統合していくSI系の計画する能力が必要となります。

## 効果的なデータマネジメントにはリーダーのコミットが必要

当たり前ですが、データは統合していくことで価値を増すことになります。そのため政治的にサイロ化されるアーキテクチャや分断されたプロセスなどが残るとその価値をげんじていくことに繋がります。
だから組織のリーダーがそれらの垣根を超えるための後押しをすることが強く要望されるんですね。

# まとめ

いかがでしたでしょうか？データマネジメントの触りの概念をかいつまんで紹介しました。

もしまあ機会があれば、各知識領域の部分や、私の好きなSnowflakeだったらここはこう実装して運用できるみたいなそういう話を書こうかなとも思っています。
自己肯定感上げbotを作りました！(LINEbot)

# はじめに
こんにちは、[室蘭工業大学 Advent Calendar 2021](https://adventar.org/calendars/7200)の2日目担当のオオスミです。
私はLINEbotで自己肯定感上げbotを作りましたのでそれについて記事に書きました。

# 経緯
昔から自分でメッセージを送ったら返答が返る形のLINEbotを作りたいと考えていました。
自己肯定感上げbotにした経緯としては私自身気持ちが沈み込みやすい性格なのでbotと対話することで緩和できたらいいと思い作成しました。bot作成にGoogle Apps Scriptを選択した理由としては関数を使って、Webサーバーとしても利用することができるからです。さらにスプレッドシートやカレンダーなど、Googleのサービスとの連携も簡単に行うことができるのも決め手になりました。

# 事前に用意する物
- LINEアカウント
- Googleアカウント

# LINE Developersの設定

 まず「[LINE Developers](https://developers.line.biz/ja/)」にログインします。
「MessagingAPIをはじめる」を選択し、Bot用のアカウントを作成してください。
ボットのアカウントができたら、具体的に7つ設定を行います。
- ボット用のアカウントを友達登録
- アクセストークンを再発行
- webhookのURL(次の章で詳しく)
- 「Webhook」を「有効」
- 「ボットがグループチャットに参加できるようにする 」を「無効」
- 「メッセージの自動返信 」を「無効」
- 「あいさつメッセージ」を「無効」
これらを行えば基本的に設定完了です。
再発行したアクセストークンはGoogle Apps Scriptで使用しますので大切にメモしておいてください。

# Google Apps Scriptでの設定
まずGoogleアカウントにログインします。
「Google Drive」→「新規」→「Google Apps Script」のようにを選択します。
以前LINE Developersで再発行したアクセストークンをつけます。
下記のコードを書いて「公開」→「ウェブアプリケーションとして導入」をおしてGoogle Apps Scriptとの連携を受理してwebhookのURLを入手する。そちらをLINE Developersで設定する。これらを行えば完全終了です。
デプロイしたものを再度修正したいときは「Project version」を「New」にし忘れないようにしてください。

```
var CHANNEL_ACCESS_TOKEN = 'アクセストークン';

function doPost(e) {
  var replytoken= JSON.parse(e.postData.contents).events[0].replyToken;
  if (typeof replytoken === 'undefined') {
    return;
  }
  
  function getRandomInt(max) {
    return Math.floor(Math.random() * max);
  }
  var message=['かっこいい！','君がtouristだ！','生きてて偉いぞ！','すごい！','君の未来は明るい'];
  var user_message=message[getRandomInt(5)];
  var url = 'https://api.line.me/v2/bot/message/reply';
  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replytoken,
      'messages': [{
        'type': 'text',
        'text': user_message,
      }],
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
```
# ソースコードについて軽い解説
今回JavaScriptで実装しましたが他のプログラミング言語でも可能です。
doPost関数はWebアプリにPOSTリクエストが送られたときに、実行される関数です。LINEBotにメッセージが送られた場合、LINEのサーバーがWebhookURLに設定したURLにPOST形式でメッセージを送ります。それをGoogle Apps Scriptが受け取って、JSONをパースし、返信するためのリプライトークンとメッセージの中身をJSONフォーマットに入れてエンドポイントに返信しています。ちなみに変数user_messageが送られる文面なのでここを変更するだけで全く違うbotを作ることが出来ます。


# 開発で工夫したところ
上記のコードにmessageという文字列が格納された配列を用意しておいてそれをランダムで選択できるようgetRandomInt()関数を作成しました。これにより可読性が向上しました。

# 完成物
下のQRコードから実際に友達追加を押して使用することが出来ます。
最後まで見て頂きありがとうございました。
![スクリーンショット 2021-12-01 234750.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411274/71eb18f0-dad8-fba3-94ce-71fe212ec71d.png)
【p5.js】『Generative Design with p5.js』P_1_2_1_01 で登場する関数 part.1 int()

この記事は Qiita p5js アドベントカレンダー2日目の記事です。

## これはなに
書籍[『Generative Design with p5.js』P_1_2_1_01](https://editor.p5js.org/generative-design/sketches/P_1_2_1_01)に登場する関数をまとめた記事です。

## int()
int型以外のものを整数値に変えてくれる関数。
他の言語でもよくみると思います。

### Type
```typescript
int(n: string | boolean | number, radix?: number): number;
```

### リファレンスより
> Converts a boolean, string, or float to its integer representation. When an array of values is passed in, then an int array of the same length is returned.
> 
> boolean, string, floatを整数表現に変換します。値の配列が渡された場合は、同じ長さのint配列が返されます。（DeepL翻訳）

### 試してみる
console.logでそれぞれ出力してみました。
配列の場合はそれぞれ対応したint型の配列になってくれるみたい。

```javascript
console.log(int("aaa")) => NaN
console.log(int("123")) => 123
console.log(int(true)) => 1
console.log(int([true, false])) => [1, 0]
console.log(int([true, false, "123"])) => [1, 0, 123]
```

### どんなときに使えそうか
P_1_2_1_01のコードをみると、`map`の結果をラップしています。

```javascript
tileCountX = int(map(mouseX, 0, width, 2, 100));
```
map()はnumber型を返すそうなので、
なぜintを使用しているかはmapの中身を調べないとわかりませんが（ごめんなさい）、
想定できることは**浮動少数点を整数に変えようとしている**のでは？
と思いました。
`tileCountX`を分数の分母にしている記述があるためです。

```javascript
var tileWidth = width / tileCountX;
```

どんな言語でもint()のような関数は用意されていそうですが、
p5では座標やカラーコードで数値を多様するため、より登場頻度は増えそうですね。

## 参考
[p5.js reference | int()](https://p5js.org/reference/#/p5/int)
[『Generative Design with p5.js』P_1_2_1_01](https://editor.p5js.org/generative-design/sketches/P_1_2_1_01)
C#でカノジョをつくる（2日目）

お疲れ様です。たなしょです。
今日から本格的にC#を勉強していきたいと思います。
## C#のコードの全体像
基本的に一番初めにusing Systemが来ますね。

```c#
using System;
```

これはCでいうところのインクルードファイルなのでしょうか？
今のところ特に記載もないので**おまじない**ということで覚えておきます。

次に名前空間を書くのが一般的らしいです。（本ではしばらく書いてませんが…）

```c#
namesapce hogehoge
```

名前空間とはディレクトリみたいなものだそうです。詳しく進めばわかるようになるんですかね。

そのあとはclassを記載して中に変数やら式やらをいつも通り記載していく流れですね。

```c#
class Hoge
{
    int a = 1;
}
```

上記のことまとめるとこんな風に書くことができます。

```c#
using System;

namespace Sample
{
    class Render2D
    {
        public int A { get; set; }

        public int B { get; set; }

        public override string ToString() => $"({A}, {B})";
    }
    class Program
    {
        static void Main(string[] args)
        {
            var p = new Render2D { A = 1, B = 2 };
            Console.WriteLine(p);
        }
    }
}
```
こう見ると名前空間とクラスとメソッドがとても見やすい言語ですね！

## 脱線
[Visual Studio 2022](https://visualstudio.microsoft.com/ja/launch/)というIDEを開発では使っているのですがとても便利ですね。フォーマットも自動でただしてくれるし、予測変換はいい感じで効いてくれるのでとても楽に書けます。もうこれなしではC#の開発はできないです。（そういってvimmerなのでいつか環境がVimに移行してると思います）
IDEのライバルとしてJetBrains社の[Rider](https://www.jetbrains.com/ja-jp/rider/)があるのですがどちらのほうが使いやすいのですかね？個人開発するならVisual Studioで充分な気もしますが、エンタープライズになるとまた違った選択肢もあるのでしょうね。

## 変数、式、スコープなど
ここに記載することでもないので割愛します。
基本的にどの言語もこの辺は同じだなーという感じで眺めてました。

## 整数型、浮動小数点数型、文字型、文字列型
「C#はCと違ってstring型があるから文字列が簡単に代入できていいね！」（最近のどの言語でも言えますが）ってところでしょうか。（最近のCにはString型が実装されたのですかね？ANSIしか触ったことがないのでわかりません。）
あとはどの言語も同じ仕様なため割愛します。

## ビット演算、関係演算、論理演算、キャスト
ここも特にこれと言って目新しいものはなかったので割愛します。
ここら辺の分野を学習するなら本をちょっと読んで[競技プログラミング](https://ja.wikipedia.org/wiki/%E7%AB%B6%E6%8A%80%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)の問題を解いたほうが理解が早まると思いました。さすがにこのカレンダーに競技プログラミングに参加した旨を書いたら、アドベントカレンダーの趣旨と食い違うため書きません。（たぶん）

## 最後に
ざっとこんな感じで二日目は終了しました。
割と本が読めたので満足しています。
C#のソースはとてもきれいに書けるので見やすくて個人的には好きになりました。
明日も引き続きよろしくお願いします。
ApacheによるTLS1.0→TLS.1.2中継(API通信用)

## はじめに
セキュリティの観点から、TLS1.2以上でなければ受け付けないシステムがほとんどかと思います。

但し、古いシステムが社内で動いており、外部とAPI連携をしている。
API連携先はTLS1.2以降しか受け付けされない。。。
でもシステムが古くTLS1.0の通信しかできない。。。

現状TLS1.0からTLS1.2に変更する為には
現在のシステムへの影響が。。。という場合の暫定対応として

APIを中継し、TLS1.0→TLS1.2へ変更を中間サーバで吸収してしまおう！という内容です

あくまで暫定対応用です。

## 環境
* CentOS7.9
* Apache2.4

## 前提
Apache2.4の導入はされているものとする

## 必要モジュール

```
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
```

## http.conf 追加

```
ProxyRequests Off
SSLProxyEngine On

# 中継定義
# 以下であればapacheサーバに/if_from_urlでアクセスしたものをhttps://xxxx.com/if_to_url.phpに中継
ProxyPass /if_from_url https://xxxx.com/if_to_url.php
ProxyPassReverse /if_from_url https://xxxx.com/if_to_url.php
```

あとは必要に応じて、Firewall等のセキュリティ上必要な設定！
CSV/TSVファイルのセル内改行に正規表現で対応する

ダブルクォーテーションで囲ったセル内改行がある場合、そのまま改行コードでsplitしてしまうと結果の配列が崩れてしまいます。
行列の改行コードとセル内改行の改行コードを分けることで対応できます。

```js
const csvDelimiter = ","
const tsvDelimiter = "\t"
xhr.responseText
    .replace(/(?<=\t)(?!\"\")(?!\\\")\"[\s\S]*?(?!\"\")(?!\\\")\"(?=\t)(?=\r\n)/g, (match) => {
        return match.replace(/\r\n/g, "\n")// セル内改行の改行コードCRLFをLFに変換
    })// / \t + [""|\"]でない + " + 行またぎ含んだ文字列 + [""or\"]でない + " + [\t|\r\n]である  /
    .split(/\r\n/)//CRLF改行で区切る LFはセル内改行なので区切らない
    .map(line => line.split(tsvDelimiter ))//区切り文字で区切る
```
WordPressのマルチサイトでドメイン変更する時の備忘録

WordPressで構築しているサイトのドメインを変更したい時は
DBに保存されているドメインを置換してあげればだいたいOKなのですが、マルチサイトの場合はもう一箇所直さなくてはいけない場所が

それは **wp-config.php**

```
define('DOMAIN_CURRENT_SITE', 'hogehoge.co.jp');
```

DB置換しただけでもサイト表示はうまく切り替わるのですが、管理画面に行くと「サイトネットワーク管理」が404になってしまう。
追っていくと、`network_home_url()`の返却値が古いドメインになってしまっている。
DBには旧ドメイン残っていないのになー...としばらくgrepとかして辿り着きました。

思えば初期構築の時にwp-configにマルチサイトの設定追記してましたね。でもそんなことすっかり忘れて唸っていたので備忘録。
【Unity】AddComponentが重い件への対処

# はじめに
こUnityのAddComponentの呼び出しの負荷が高いことは度々話題になります．
[Unity AddComponent Very Inefficient and Slow (StackOverflow)](https://stackoverflow.com/questions/60357703/unity-addcomponent-very-inefficient-and-slow)

この記事では， **AddComponentが重い件**への1つの対処法について解説します．

# 概要
ざっくり結論としては，**一度に大量のGameObjectを生成しAddComponentをするようなケース** においてはAddComponentを呼び出す回数をなるべく減らすため， **すでにAddComponentが行われたGameObjectをInstantiateするとよい** というものです．

# 実行環境
実行時間などの参考に検証をした環境を明示しておきます．

- Ryzen 9 5900X
- Unity 2020.3.8f1
- Windows 10 64bit
- Performance testing API 2.8.0-preview

# 検証
今回の記事では，Unityの[Performance testing API](https://docs.unity3d.com/Packages/com.unity.test-framework.performance@2.8/manual/index.html)を使った簡単なベンチマークテストで以下の2パターンの速度について検証します．

- 100000回GameObjectを生成し，都度AddComponentした場合
- 1度AddComponentしたGameObjectをInstantiateで複製した場合

```c#
    // GameObject生成 -> AddComponent
    // x 10000
    [Performance]
    [Test]
    public void AddComponentProfilingTest()
    {
        Measure.Method(() =>
            {
                for (int i = 0; i < 10000; i++)
                {
                    var obj = new GameObject();
                    obj.AddComponent<EmptyComponent>();
                }
            })
            .WarmupCount(1)
            .IterationsPerMeasurement(1)
            .MeasurementCount(20)
            .Run();
    }

    // AddComponent -> Instantiate
    // x 10000
    [Performance]
    [Test]
    public void InstantiateProfilingTest()
    {
        Measure.Method(() =>
            {
                var template = new GameObject();
                template.AddComponent<EmptyComponent>();

                for (int i = 0; i < 10000 - 1; i++)
                {
                    var obj = Object.Instantiate(template);
                }
            })
            .WarmupCount(1)
            .IterationsPerMeasurement(1)
            .MeasurementCount(20)
            .Run();
    }
```

# 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170854/84accbcf-4fce-82be-36a8-7aded9acdee8.png)

測定した結果，

- 都度AddCompnent : 481.79ms (Median)
- Instantiateで複製 : 93.67ms (Median)

と**およそ5倍高速化**される結果となりました．
実行環境によっては更に差が出ることもありそうに思えます．

AddCompnentはComponentの重複チェックなどの処理が行われるためオーバーヘッドが大きく，大量に行う場合はInstantiateで複製したほうが効率が良さそうです．

# 最後に
AddComponentは重いので気をつけよう，といった趣旨の記事でした．

そもそもMonoBehaviourの使用やAddComponent自体が比較的負荷の高い処理となるので，大量に生成する必要があるオブジェクトなどにはなるべく使用しないのが得策と言えそうです．
午前問vsゆーさく

#僕が基本情報を受けるにあたっての問題
さあ、こんなぼくもITというなにやら難しそうな世界に飛び込んで約半年がたったわけだが、そろそろ考え始めるのが基本情報技術者試験の取得についてだ。こいつの取得において、僕はとても大きな壁にぶつかっている。結論から述べさせていただくと、僕に午前問は無理だ。無理なのだ。午後問は良い。だが、午前問は無理だ。僕は昔から暗記が苦手だ。中学の時から社会で90点を取ったためしがないくらいだ。そんな僕に、あの広い範囲を覚えるなんて無理なのだ。午後問題はまだゲーム感覚で取り組めるというか、解けた時の達成感が楽しいから好きだ。でも午前問題は無理！そう思っていた。

##そんな中僕は出会ってしまった。
僕に基本情報は無理なのか。そう思っていた中、僕は見つけてしまった。基本情報午前問対策アプリを。スマホでいつでも気軽に午前問題を解ける。これはスマホ中毒の僕にはとてもありがたいものだった。授業間などの隙間時間を見て、少しずつ勉強を進められるし、前に自分が間違えた問題を見ることもできるのでおすすめだ。現在僕は、このアプリを活用し、午前問に向き合っているところだ。これで僕も基本情報技術者に近づく、、、！はず。
CharucoBoardつくーる（Windows 10、OpenCV 4.0.0、Python 3.6.12）

# 開発環境
- Windows 10 PC
- OpenCV 4.0.0
- Python 3.6.12
- ImageMagick-7.1.0-16-Q16-HDRI-x64-dll.exe

# 実装

1．ImageMagickのインストール

https://www.imagemagick.org/script/download.php#windows

2．下記コードを実行

~~~CreateCharucoBoard.py
import cv2
import subprocess

aruco = cv2.aruco
dictionary = aruco.getPredefinedDictionary(aruco.DICT_6X6_250)
charucoBoard = aruco.CharucoBoard_create(5, 7, 0.04, 0.02, dictionary)
image = charucoBoard.draw((round(5 * 40 / 25.4 * 350), round(7 * 40 / 25.4 * 350)))
cv2.imwrite("charuco_board.png", image)
subprocess.run(['magick.exe', 'convert', '-density', '350', '-units', 'pixelsperinch', 'charuco_board.png', 'charuco_board.png'])
~~~

![charuco_board.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/0ca59770-af2a-936f-a66a-839ee21b17e9.png)

https://openi.jp/blogs/main/software-opencv-aruco-charuco
GitHubのデスクトップ通知をするChrome拡張機能を作ってみた

最初に結論（作ったもの）↓

https://chrome.google.com/webstore/detail/github-desktop-notificati/iecnfgcbbajncgiianhoaongialneaam

## 背景
現場でGitHubを使っていて、issueのアサインや更新、プルリクのレビュー依頼等の通知に気づきにくく、これを解決したいと思っていました。
通常GitHub側の通知設定ではメールかWEB（https://github.com/notifications ページ）での通知になっているものの、理想はデスクトップ通知でした。

## 最初に検討したこと

https://www.gitify.io/

調べてみるとGitifyが良さそうだったのですが、現場のアカウントで行う以上アプリ内で認証を行う懸念と、組織のGitHubアカウントの方でサードパーティアプリの連携許可をする必要があり、残念ながら候補からは外れました。

他には https://github.com/notifications ページをRSSリーダーで検知する、も考えたのですが、意外とデスクトップ通知ができるようなちょうど良いアプリやChrome拡張などがなく（しかも信頼性があるもので）、これも断念しました。

結構色々調べたものの、自分が調べた限りではどうしても無さそうだったので、今回自分でchrome拡張機能を作ることにしました。

## 完成したもの
https://chrome.google.com/webstore/detail/github-desktop-notificati/iecnfgcbbajncgiianhoaongialneaam

最初は自分のローカルだけにインストールして使っていたのですが、せっかくならと公開してみました。
ちょこちょこ修正したりして今はv1.3です。
安全性の担保のためソースコードも公開しています。（ぜひ確認して頂ければと）
https://github.com/hisw-29/github-desktop-notification

この拡張機能のポイントとしては下記のあたりです。

* 拡張機能側に認証情報等を渡す必要が無い
* やってることは https://github.com/notifications のDOM要素を毎分見て変更をチェックしているだけ
    * 差分はブラウザのローカルストレージに保存
* デスクトップ通知をクリックすると https://github.com/notifications を開く
    * 既に開いている場合、タブをアクティブにする

作った本人としては処理が分かってるので安心して使えるのと、実際使ってみるとかなり便利でした。
レビュアーにされたりしたら気づいてすぐapproveしたりするので、きっと~~気味悪がられて~~感謝されていると思います。
今思ったのですがレスポンスが早いとチームの開発も加速するのではないでしょうか！

## 改善したいこと
必要最小限のpermissionになるよう注意して作ったりはしたのですが、より安心して使えるように改善できるところは改善していきたいと思っています。

例えば今だと`host_permissions`で`https://github.com/notifications`を指定しているのに、`https://github.com/`（ホスト単位）で許可になってしまっているような感じで、これはなんとかならないかなと思っています。（ちょっと調べた限りmanifestの設定には無さそうで）

他にも、自分が今回chrome拡張を初めて作成したので、きっと知らない部分で改善できることがあるかなと思っています。
Laravelについて

#Laravelとは
PHPのフレームワークで、webアプリケーションを制作に用いられる。
## 1 MVCモデルを活用している。 
MVCとは<b>ビジネスロジックをModelが担当し、表示などをViewが処理に、全体の制御を Controllerで行う形態いなる。</b>
## 2パッケージ管理はComposerを行なってくれている。
依存関係などもまとめてインストールしてくれる。
## 3 Eloquent(エロクアント) ORM
　データベスの操作を行なってくれている。
Eloquent Object Relational Mappingの略で、データベースとモデルにリレーションを持たせて、データを柔軟に扱えるようにしたもの。

#Laravelのディレクトリ構成
`````
─── Laravel
    ├── app      
    ├── bootstrap 
    ├── config    
    ├── database 
    ├── public   
    ├── resources 
    ├── routes   
    ├── storage   
    ├── tests    
    └── vendor   
````
##App
アプリケーションのコアコードを配置されている。ほとんどの全部のクラスは、このディレクトリに設定されている。

##bootstrap
フレームワークを初期起動処理するapp.phpファイルを設置している。。このディレクトリには、ルートやサービスのキャッシュファイルなど、パフォーマンスを最適化するためのフレームワークで生成されたファイルを含むcacheディレクトリも含む。通常、このディレクトリ内のファイルを変更する必要はない。

##config
アプリケーションの全設定ファイルを設置している。

##database
マイグレーションとモデルファクトリ、初期値設定（シーディング）を配置している。
このディレクトリをSQLiteデータベースの設置場所としても利用できます。

##public
アプリケーションへの全リクエストの入り口となり、オートローディングを設定するindex.phpファイルがある。また、このディレクトリにはアセット（画像、JavaScript、CSSなど）を配置する。

##resources
Viewと、CSSやJavaScriptなどの未加工のコンパイルされていないアセットを含む。すべての言語ファイルも格納してる。

##routes
```
web.php
api.php
console.php
channels.php
```
アプリケーションのすべてのルート定義を配置している。デフォルトでルートファイルをいくつかLaravelは用意されいる。
web.phpファイルは、RouteServiceProviderがwebミドルウェアグループへ配置するルートを記述する。これにより、セッション状態、CSRF保護、およびクッキー暗号化が提供される。アプリケーションがステートレスのRESTful APIを提供しない場合は、すべてのルートがweb.phpファイルで定義される。

api.phpファイルは、RouteServiceProviderがapiミドルウェアグループへ配置するルートを記述しる。これらのルートはステートレスであることが意図されているため、これらのルートを介してアプリケーションに入るリクエストは、トークンを介してで認証されることを意図しており、セッション状態にアクセスできない。

console.phpファイルは、クロージャベースのコンソールコマンドをすべて定義する場所。各クロージャはコマンドインスタンスと結合されるため、各コマンドのIOメソッドを操作する簡単なアプローチが可能。このファイルはHTTPルートを定義しませんが、アプリケーションへのコンソールベースのエントリポイント(ルート)を定義している。

channels.phpファイルは、アプリケーションがサポートするすべてのイベントブロードキャストチャンネルを登録できる場所。

##storage

```
app
framework
logs
```
ディレクトリに分離される。
appディレクトリは、アプリケーションが作成したファイルを保存するために使用できる。
frameworkディレクトリは、フレームワークが作成したファイルとキャッシュを保存するために使用する。
最後に、logsディレクトリにはアプリケーションのログファイルを保存している。

##tests
自動テストを設置する。

#vendor
Composerによる依存パッケージが配置されます。
【12月1日開始】Python初心者が学習初日にまず考えたこと

#はじめに

初めての記事なので練習を兼ねてPythonを勉強わたしが何を学んでどう活かしたいかを書き連ねていこうと思います。

まず、Pythonと調べるとできることは

>・機械学習させたAI
・仕事の自動化、効率化
・Webスクレイピングによる情報収集
・データ集計
・Webアプリケーション作成
・etc...

等、できることが幅広い印象です。
その中でも気になっている AND 実践したい事柄は
**仕事の自動化**と**Webスクレイピング**です。

時間があれば、話題の機械学習の勉強もしたいなと考えてます。


#学習方法
まずは、Qiitaセンセイにお世話になろうかと思いましたが、
ちょうど手元に参考書があるので、そちらをベースに進ませていただきます。


-------

####参考教材
書籍名・・・作業が一瞬で片付くPython自動仕事術
※もちろんのこと転載が禁じられているので、書籍の内容を直接書けませんが、著作権を守る範囲で記事にさせていただきます。

<font color='gray'>読了後の感想は送らせていただきます。</font>
Amazon EventBridgeでAmazon S3のイベント通知を試してみた

## Amazon S3 Events via Amazon EventBridge
Jeff先生のブログがおすすめ。もうこれ読んだらこの記事読まなくていいぐらい。

https://aws.amazon.com/jp/blogs/aws/new-use-amazon-s3-event-notifications-with-amazon-eventbridge/

## 何がうれしいの？
今までは
 - S3のイベント通知機能でイベントは取れたが、Lambda、SNS、SQSにしか送れなかった
 - CloudTrailでオブジェクトレベルの認証を有効化（別途課金）しないとEventBridgeでS3オブジェクトのイベントを取れなかった


## やってみた
1. S3バケットのイベント通知でEventBridgeの設定をオンにします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/bb4a0847-122e-fdfc-4051-3a8c565211d7.png)

2. EventBridgeでイベントタイプ「Amazon S3 Event Nortification」が選択可能に！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/9f901fb3-27fd-6fc4-1f0c-e5c9e499191d.png)

3. S3の特定のイベントを選べるよ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/473fabd6-bc66-f75f-bb5c-e88c01b3dfc2.png)

4. ターゲットはAPIにしてみました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/c9e656e3-3424-047e-21d3-2056d734c2b6.png)
今回は、自社のクラウドサービス Qanat Universe（Node-RED）に API リクエストしてみます

5. 適当なファイルをPUSH
`aws s3 cp test.txt s3://niida-test/test.txt`

6. EventBridge経由で通知を取得できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/a813dc80-520c-cfce-76a5-c23762618ac1.png)

## まとめ
EventBridgeでS3の通知を受けられるようになったことで、Lambdaを挟むことなく様々なサービス連携することが可能になりました！
- 画像がアップロードされたら、機械学習する
- ログがアップロードされたら、解析系のバッチを回す
上記のような処理が直接ECSタスクやStepFunctionsに投げられるようになったのはかなり嬉しいです！
EventBridgeのルールをうまく書くことでバッチ系の処理をシンプルにできそうかなと思います！
偏差値43の高卒非IT者が基本情報技術者試験を受けてみた



こんにちは！基本情報技術者試験を受けようか迷っている人の背中を少しでも押すことができたらと思い、記事を書くことにしました。

タイトル通り、義務教育をしっかりと受けてこなかった非IT者が基本情報技術者試験を受けてみた結果と勉強方法について書いていきます。


<h2>結果</h2>

午前問題 70点
午後問題 44点


以上の結果でした。

受かった雰囲気で書いてごめんなさい。笑



午前は合格点は取れましたが、午後は取れなかったので次受ける時の対策など共有できたらと思います。


-----


<h2>おすすめ勉強期間</h2>

僕の場合8月から勉強スタートしたので試験までは午前試験は3ヶ月、午後試験までは4ヶ月ありました。

未経験の人は勉強期間を半年〜1年続ける気でスタートするのがおすすめです。
3ヶ月で取れました！とかいった記事も見かけますが毎日４〜5時間くらい勉強する必要があるので僕は死にそうでした。笑


<h2>勉強する順番</h2>
1.アルゴリズム
2.ソフトウェア開発
3.午前問題
4.情報セキュリティ
5.データベース


僕がもし、もう一度初めから勉強をやり直すならこの順番でやります。

1番にアルゴリズムとソフトウェア開発な理由は

アルゴリズム・ソフトウェア開発は配点が高く、それぞれ25点ずつあり
極端な話、アルゴリズムとソフトウェア開発で満点をとれば50点になり、他で10点取れば午後試験はクリアできるからです。
それからアルゴリズム・ソフトウェア開発はすぐに身につくものではなく時間をかけて身についていくものなので、できるだけ早くスタートしたほうがいいです。


<h2>勉強方法・ルーティーン</h2>

<h3>1〜3ヶ月目</h3>

<h4>アルゴリズム対策・・・1日1時間</h4>

> 教材 http://xn--tpto73d.jp/mobile/

このふっくゼミのアルゴリズム対策がとてもいいです。
解説動画もついていてかなりわかりやすいものでした。


<h4>午前問題対策・・・隙間時間</h4>
こちらは移動時や少しの時間しか取れない時に
過去問道場で問題を解きまくるのをお勧めします。


> 過去問道場 https://www.fe-siken.com/fekakomon.php

過去10回分を遡れば大丈夫です。*10年分ではありません。

<h4>午前知識を身につける</h4>

この書籍を1日1章読み進めてください。

> https://gihyo.jp/book/2020/978-4-297-11716-0


<h3>3ヶ月〜6ヶ月</h3>

<h4>アルゴリズム対策・・・1日1時間</h4>
大丈夫です。わかるようになります。

<h4>午前問題対策</h4>
午前問題を一回分通して正解率80%になるまで繰り返し解く。
(1日1回分)



<h3>6ヶ月〜12ヶ月</h3>

午後試験対策
1日大問2問ずつ(過去問)

この教材がお勧めです。

>https://honto.jp/netstore/pd-book_30975640.html

この教材を理解して3周したら合格できるはずです。




以上が基本情報技術者試験必勝法でした！


最後にお勧め教材まとめて貼っておきます！


<h3>おすすめ教材</h3>


<h5>午前試験対策</h5>
>栢木先生の基本情報技術者教室 イメージ＆クレバー方式でよくわかる 令和０３年 
https://honto.jp/netstore/pd-book_30608001.html



これ一冊で大丈夫です。

<h5>午後試験対策</h5>

パーフェクトラーニング 基本情報技術者過去問題集
>https://honto.jp/netstore/pd-book_30975640.html

C言語の切り札
C言語の過去問1行1行解説がある
>https://gihyo.jp/book/2017/978-4-7741-8748-8

スッキリわかるC言語入門
C言語の基本文法が学べるのとパズルRPGゲームを作成することができる

>https://book.impress.co.jp/books/1111101149

うかる！ 基本情報技術者　[午後・アルゴリズム編]　2022年版
書籍だけでなく動画教材も合わせて見ることができるのでかなりおすすめ

>https://www.hanmoto.com/bd/isbn/9784532415648



過去問道場
とにかくやるべし
>https://www.fe-siken.com/fekakomon.php



次は春に向けて頑張りましょう〜！
CentOS7でモダンなApache環境を構築する

# 結論

モダンな環境を試したい場合は最新のOSを利用しよう！

それでもCentOS7を使いたい場合は
以下のバージョンをインストールできる想定です

* Apache 2.4.51
* OpenSSL 1.1.1



# 環境

* AWS EC2
    * インスタンス m5.xlarge
    * OS CentOS 7 (x86_64)
    * セキュリティグループ
        * http, httpsは全開放
        * sshは自分の環境のみ

EC2インスタンスの場合はfirewallではなくセキュリティグループで大抵は保護されます

# 手順

ルートユーザで作業します

```
# sudo su -
```

ある程度のツール群はインストールされている想定です

```
# yum install -y vim
```

1. OpenSSLのインストールと適用

```
必要なモジュールをインストール
# yum install gcc zlib-devel

定石だとソースダウンロード以下で実施される
# cd /usr/local/src/

ソースをダウンロード
# wget https://www.openssl.org/source/openssl-1.1.1l.tar.gz

ダウンロードしたファイルを解凍する
# tar xzvf openssl-1.1.1l.tar.gz

解凍したディレクトリに移動
# cd openssl-1.1.1l

インストールディレクトリの指定
# ./config --prefix=/usr/local/openssl shared zlib

ビルド
# make

インストール
# make install

bashにパスを通す
# echo 'export PATH="/usr/local/openssl/bin/:$PATH";' >> ~/.bashrc

再読込み
# source ~/.bashrc

バージョン確認
# openssl version
OpenSSL 1.1.1l  24 Aug 2021
```

2. Apacheのインストール

```
必要なモジュールをインストール
# yum -y install openldap-devel expat-devel libdb-devel mailcap system-logos

Apacheがインストールされている場合は関連モジュールも含め削除
# yum remove httpd*

リポジトリのインストール
# yum -y install https://repo.ius.io/ius-release-el7.rpm

Apacheのインストール
# yum  -y install --disablerepo=base,extras,updates --enablerepo=ius httpd httpd-devel mod_ssl

バージョン確認
# httpd -v
Server version: Apache/2.4.51 (IUS)
Server built:   Oct  8 2021 16:46:12
```

この状態では`mod_ssl.so`が`OpenSSL 1.0`を参照してしまっている
イレギュラーだがApacheをビルドし直して`mod_ssl.so`を頂戴する

mod_ssl.soの作成と適用

```
ディレクトリの移動
# cd /usr/local/src/

共有ライブラリに追加するためにインストールディレクトリのパスを記載
# vim /etc/ld.so.conf.d/openssl-1.1.conf
# cat /etc/ld.so.conf.d/openssl-1.1.conf 
/usr/local/openssl/lib/

共有ライブラリの読み込み
# ldconfig

OpenSSL1.1.1を参照するように変数をセット
# export PKG_CONFIG_PATH=/usr/local/openssl/lib/pkgconfig/

必要なモジュールをインストール
# yum install bzip2　pcre pcre-devel　prelink

ソースをダウンロード
# curl http://ftp.riken.jp/net/apache//httpd/httpd-2.4.51.tar.bz2 -O

ダウンロードしたファイルを解凍
# tar jxvf httpd-2.4.51.tar.bz2 

解凍したディレクトリに移動
# cd httpd-2.4.51 

設定は必要ないがmakefile作成のため実施
# ./configure 

ビルド
# make 

インストールせずにファイルのみ頂戴する
# cp modules/ssl/.libs/mod_ssl.so /etc/httpd/modules/

実行の許可
# execstack -c /etc/httpd/modules/libcrypto.so.1.1 

Apacheの起動
# systemctl start httpd
```

セキュリティ設定の細かいことは他の方におまかせしますが、
ここまで対応すればTLSv1.2までの暗号スイートには対応できるはずです

# 補足

可能であればCentOS8以降を使いましょう
素直に最新版が入れられるはずです

# 余談

* アドベントカレンダー担当日
    * 2021年12月2日0時0分
* 執筆開始
    * 2021年12月1日11時02分
* 執筆終了
    * 2021年12月2日00時05分

来年はやる前提で記事を用意します、、

それでは皆様よいお年を！
アドベントカレンダーを始めた話

##はじめに
今年も残り30日となってしまいました。気が付けばあっという間です。
残り日数を有意義にする為に、そして今年の備忘録を記録するべくアドベントカレンダーを作成しました。

https://qiita.com/advent-calendar/2021/sre-nitijyou

内容としては、主に失敗談やら成功談やらを載せる備忘録を考えています。
もし気が向いたら見てください。

##おわりに
qiitaで記事を投稿するようになって早2年半くらい経ちそうです。
今後も記事投稿やら更新をしていこうと思っていましたが、qiitaにするべきかはてブにするべきか、正直ぶれぶれです。
住み分けを自分なりに決めて、書いていこうと思います。
早くつよつよエンジニアになりたい
GTMのデバックはローカル環境でも出来る

# 概要
GTMでデバックに使用する「プレビューモード」はローカル環境でも使える。

# 方法
## 1. ローカル環境を起動してブラウザでアクセス出来る状態にする
この記事では下記URLでローカル環境にアクセス出来る状態とする。
http://localhost:8080/

## 2. GTMの「プレビュー」リンクからTag Assistantを起動

## 3. Tag Assistantの「Your website’s URL」にローカル環境のURLを入力する
![スクリーンショット 2021-12-01 23.51.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131603/9d757b36-a493-aadd-11d0-8b5af624b4b3.png)



## 4. 「Connect」ボタンを押すと、ローカル環境が「プレビューモード」で開く
これで普通にデバックできる

# ローカルだけ別のGTMコンテナに変えて検証も出来る
GTMのJavascriptタグのコンテナIDが合っていれば「プレビューモード」が使える。
検証用のコンテナを用意して下記のタグのコンテナIDの部分を書き換えれば、ローカルだけのGTMコンテナで検証が出来る。

```
<!-- Google Tag Manager -->
< script > (function (w, d, s, l, i) {
  w[l] = w[l] || [];
  w[l].push({
    'gtm.start': new Date().getTime(),
    event: 'gtm.js'
  });
  var f = d.getElementsByTagName(s)[0],
    j = d.createElement(s),
    dl = l != 'dataLayer' ? '&l=' + l : '';
  j.async = true;
  j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
  f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', '{GTMのコンテナID}'); < /script>
<!-- End Google Tag Manager -->
```

GTMが狙い通り動かずHTMLを調整する時の手間が減るはず。
卒業した推しメンに電話して次の推しメン候補をSMSで教えてもらう

長らく応援してきた乃木坂46の大園桃子さんが2021年9月4日にグループを卒業、そして芸能界を引退しました。毎回全力投球していた握手会（最近ではオンラインのお話し会）もなくなってしまい、今は推しロスで夢も希望もない毎日を過ごしています。

**次の推しメンは見つかるのだろうか。。。**

そんな気持ちになれないよ...と未練たらたらな自分から脱却するためにTwilioで**「推しメンに電話すると卒業の旨が告げられて次の推しメン候補が送られてくる」サービス**を作りました。デモはこちら（音声Onにしてください）。

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

<br>
仕組みはとてもシンプルです。Twilioの電話番号を1つ購入してTwilio Studioで次のようなフローを組みました。

![2021-12-01_17h45_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47737/60b97853-c4b8-4a1e-fff6-03223c10a0cd.png)

以下3つだけです。

- 電話がかかってきたらSay/Playでアナウンスを流す
- Functionでランダムに現役の乃木坂メンバーを選ぶ
- Send Messageで選んだメンバーの名前をSMSで送る

Functionの中身もシンプルです。

![2021-12-01_23h45_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47737/61afd60c-d622-20c5-e6f4-fffc877c90a5.png)

```javascript
const got = require('got'); 

exports.handler = function(context, event, callback) {
  
  (async () => {
    try {
      const response = await got('http://xxxxx.sakamichi46.com/sakamichi46api/api/nogizaka46/profile');
      const members = JSON.parse(response.body);
      callback(null, members[Math.floor( Math.random() * members.length )].name);
    } catch (error) {
      console.log(error);
    }
  })();
};
```

乃木坂46のメンバーは自作のWeb APIで取得してます。

https://github.com/kikutaro/Sakamichi46Api


推しメンに電話！！とテンションがあがった後、淡々としたアナウンスで卒業を改めて認識させられて悲しみが沸いたあと、次の推しメン候補がきて、一歩前に進んでみようと思う。そんな自分のためだけの自己満サービスです。

ちなみにデモ動画で次の推しメン候補として送られてきた「新内眞衣」さんは来年1月末で卒業です orz

今年は乃木坂ちゃんの卒業ラッシュが辛すぎました。そろそろ5期生が入るので来年からの新生乃木坂に期待です...！