OmniAICreator/Qiita-1.07M huggingface dataset:
何かを伝える時は Gif動画を簡単に ScreenToGif で作っちゃおう

# 背景

理解のしやすさって、やっぱり　文字 ＜　画像　＜　動画　ですよね。
でも、動画って制作が面倒そうって思いますが、Screen to Gif 使ったら非常に簡単に編集まで可能です。

そんな Screen to Gif でこれだけは使おうっていう三点の機能を紹介

https://www.screentogif.com/

# キーストローク（操作内容）挿入

自動記録したキー操作を簡単に動画内に挿入出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/f8bdd71e-9672-90b1-9791-b0dfaf00c193.png)

## Sample 動画

![キーストローク付加.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/c8e570fe-356e-3607-9edc-e192c8bafe3a.gif)

# キャプション（字幕）挿入

動画内の状況を説明する為のコメント（字幕）を挿入出来ます。
挿入したいフレームを選択してから、キャプション選択して、色とかサイズ、位置を調整するだけ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/dd535247-0792-add5-fff5-26f7ab367181.png)

## Sample 動画
真ん中に黄色い文字で字幕追加
![キャプション追加.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/3bdb98ab-d496-f8ef-5509-ea9c6f2ac8ac.gif)

# ぼかし追加
見せたくない個人情報だったり、社内被情報は、これで隠せます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/fb3770ae-8943-1b6d-d717-48d0cf9eb67e.png)
## Sample 動画
右上がぼかされてます。
![ぼかし追加.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/cd91c324-36b4-5d99-8df9-9537d4ed6486.gif)

# 公式の使い方はここ

https://www.screentogif.com/how-to-use

# Source Code
GitHub で公開されてるので、Sponser や Contributor にもなれます。

https://github.com/NickeManarin/ScreenToGif
WSL2 + WSLg＋ROS2 Launch でGDBのバックトレースをしてみる

# はじめに
LD06 LiDARをラズパイのUARTからROS2で直接触れるようにする作業をしています．が，進捗が芳しくないので，途中で見つけたデバッグ方法について書きます．

# launch.pyに細工
デバッグをしたいノードを起動する`Node`なり，`LifecycleNode`の引数に
`prefix = ['xterm -e gdb -ex run --args']`を追加します．

LDLidarのlaunch.pyでの例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238384/5f35290a-699d-629b-966a-ca4fba6d0ec0.png)

参考
https://navigation.ros.org/tutorials/docs/get_backtrace.html#from-a-launch-file

# ssh
WSL2のターミナルからX11転送をするため`-X`オプションを付けてSSHコマンドを叩きます．

# 実行
`ros2 launch`で細工したlaunch.pyを起動し，ノード内でSEGVなどが起こると，WindowsにWSLg経由でGDB用ウィンドウが表示されます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238384/88e2b4bb-a18b-dd6e-744a-7cacc258ce2c.png)

# さいごに
かなり薄味な記事になってしまいましたが，お役に立てば幸いです．

# 使用ソース
 - [ldrobot-lidar-ros2] 
   (https://github.com/Myzhar/ldrobot-lidar-ros2)
（MITライセンス）
Laravelの.envファイルで設定した環境変数を、Vueで取得する

# やりたいこと
Laravelの.envファイルで設定した環境変数を、Vueのコンポーネントの中で取得する。

# 動作環境
PHP 7.4.9
@vue/cli 4.5.4

# 困った

```php:.env
SAMPLE_WORD="sample!!!"
```

```js:SampleComponent.vue
console.log("サンプル")
console.log(process.env.SAMPLE_WORD)
console.log("サンプル")
```


![「undefined」になってる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/f7892e65-9849-373d-3eb3-54d4700a42d8.png)


envで確かに設定した環境変数なのに「undefined」になる。
サーバを立ち上げ直しても変わらず…

# こうやったら上手くいった
環境変数の変数名を「MIX_hogehoge」というようにMIXから始まるようにします！

```php:.env
# before
SAMPLE_WORD="sample!!!"

# after
MIX_SAMPLE_WORD="sample!!!"
```

```js:SampleComponent.vue
console.log("before")
console.log(process.env.SAMPLE_WORD)
console.log("after")
console.log(process.env.MIX_SAMPLE_WORD)
```

一度サーバを立ち上げなおして再度見てみると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/ef07d079-b8f9-724c-e29b-8f1d620084b7.png)

「MIX」をつけたほうは、ちゃんと「sample!!!」と表示されてますね。


# 参考にさせていただいた記事
助かりました、ありがとうございますmm
[おしうみなおき様　vue側でlaravelのenvファイルの値を使用する方法](https://zenn.dev/naoki_oshiumi/articles/0b8e8b7863b4f2)
ただただC#でReactive Extensions(Rx)を使ってみる ~非同期処理~

# はじめに

本記事はRx初学者の筆者が、Rxをただただ使ってみて学びや気づきなどをまとめたものです。

# Reactive Extensions(Rx)とは

ざっくり表現すると、LINQで非同期やイベント関連の処理も扱えるようにする仕組みのことです。
詳細は[こちら](https://atmarkit.itmedia.co.jp/fdotnet/introrx/introrx_01/introrx_01_01.html)の記事を参照ください。

# 非同期処理を使ってみる

C#で非同期処理を実現する際によく利用されるTaskとRxを使って非同期処理を書いてみます。
以下が実際のコードです。
重い処理を非同期処理で実施しつつ別の処理を行って、あるタイミングで非同期処理の完了を待つといったありがちなケースをTaskとRxの両方を使って書いています。

- Taskの場合

```csharp
/// <summary>
/// サンプル用プログラム
/// </summary>
class Program
{
    static async Task Main(string[] args)
    {
        // Taskで非同期処理を実行
        var taskAsyncFunc = Task.Run(() =>
        {
            // 重い処理を実行している想定
            Thread.Sleep(1000);
            Console.WriteLine("Taskによる非同期処理完了");
        });
        // 非同期処理中に別処理を実施
        Console.WriteLine("Taskによる非同期処理中の処理");
        // 非同期処理の完了を待つ
        await taskAsyncFunc;
    }
}
```

- Rxの場合

```csharp
/// <summary>
/// サンプル用プログラム
/// </summary>
class Program
{
    static async Task Main(string[] args)
    {
        // Rxで非同期処理を実行
        var rxAsyncFunc = Observable.ToAsync(() =>
        {
            // 重い処理を実行している想定
            Thread.Sleep(1000);
            Console.WriteLine("Rxによる非同期処理完了");
        }).Invoke();

        // 非同期処理中に別処理を実施
        Console.WriteLine("Rxによる非同期処理中の処理");
        // 非同期処理の完了を待つ
        await rxAsyncFunc;
    }
}
```

確かに非同期処理は書けますが、上記のコードではRxならではの利点が分からないです。
Rxの特徴は非同期処理、イベントをシーケンスとして表現できる点にあるというのが私の理解です。
なので、例えば非同期処理完了後にやらなければならない処理を登録したいという場合にはRxの場合、非常に簡単に実現できます。
具体的には以下なコードで実現できます。

```csharp
/// <summary>
/// サンプル用プログラム
/// </summary>
class Program
{
    static async Task Main(string[] args)
    {
        // Rxで非同期処理を実行
        var rxAsyncFunc = Observable.ToAsync(() =>
        {
            // 重い処理を実行している想定
            Thread.Sleep(1000);
            Console.WriteLine("Rxによる非同期処理完了");
        }).Invoke();

        // この部分を追加
        // 非同期処理完了後の処理を設定
        rxAsyncFunc.Subscribe(unit =>
        {
            Console.WriteLine("非同期処理完了後の後処理");
        });

        // 非同期処理中に別処理を実施
        Console.WriteLine("Rxによる非同期処理中の処理");
        // 非同期処理の完了を待つ
        await rxAsyncFunc;
    }
}
```
上記コードではObservable.ToAsyncメソッドで作成した非同期処理をInvokeメソッドで実行しています。
実行時には変数`rxAsyncFunc`でIObservableオブジェクトを受け取っています。IObservableオブジェクトは非同期処理の状態を観測します。IObservableオブジェクトにSubscribeメソッドでハンドラを設定することで、IObservableオブジェクトが非同期処理の完了を観測した時点で設定したハンドラを呼びだします。
このようにRxを使うと非同期処理の完了を補足して追加で処理を行わせるといったことが簡単にできます。

# さいごに

記事を書くことで「Rxは非同期処理やイベントをシーケンスとして扱い、そのシーケンスを流れるイベントや非同期処理の完了を登録したハンドラに伝えている」というイメージが少し湧きました。
今後もRxについての記事を(理解のために)書かねばと思いました。
ラズパイにWEBカメラを接続してGStreamerを使った際に小一時間ハマった話

## はじめに

先日、ジャンク品のWEBカメラを手に入れたので、手元にあったラズパイに接続して遊んでみようと思い、その過程で「GStreamer」を使ってみました。
その時に小一時間ハマった事がありましたので、ここにまとめておきたいと思います。

## 環境
- ラズパイ 3 Model B+
  - Raspbian GNU/Linux 10 (buster)）
- GStreamer 1.14.4
- WEBカメラ（300円のジャンク品）

## ハマった事
以下のコマンドはWEBカメラの映像を画面に表示するコマンドで、このコマンドを実行するだけで、カメラの映像を画面に表示することができます。
※WEBカメラでGStreamerの公式サイトのトップページを撮影している際のスクリーンショットです。

```bash
gst-launch-1.0 v4l2src ! videoconvert ! ximagesink
```
![2021-12-12-210433_1280x1024_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/7e588a78-41e1-b1bb-4dcb-b10c810067d9.png)


そして、例えば、任意のサイズやフレームレートでキャプチャを行いたい場合は、`video/x-raw,width=1280,height=720,framerate=30/1` のような指定を行います。

```bash
gst-launch-1.0 v4l2src ! videoconvert ! video/x-raw,width=1280,height=720,framerate=30/1 ! ximagesink
```

ただし、サイズやフレームレートを指定する場合、当然ではありますが、**そのWEBカメラが対応している値**を指定する必要があり、カメラが対応していない値を指定した場合はエラーとなります。

具体的に言うと、今回手に入れたWEBカメラは最大解像度が **640x480** なのですが、それを把握せずに上記のように **1280x720** でキャプチャしようとしたため、エラーになっていました。

以下のようなエラーメッセージが表示されるのですが、サイズ指定が原因だとは気づかず、小一時間ハマってしまいました。。

```bash
$ gst-launch-1.0 v4l2src ! videoconvert ! video/x-raw,width=1280,height=720,framerate=30/1 ! ximagesink
パイプラインを一時停止 (PAUSED) にしています...
Pipeline is live and does not need PREROLL ...
パイプラインを再生中 (PLAYING) にしています...
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Internal data stream error.
追加のデバッグ情報:
gstbasesrc.c(3055): gst_base_src_loop (): /GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
streaming stopped, reason not-negotiated (-4)
Execution ended after 0:00:00.000240937
パイプラインを一時停止 (PAUSED) にしています...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

```

## 最後に
とりあえず、GStreamer で（上記みたいな）`streaming stopped, reason not-negotiated (-4)` エラーが表示される場合は、サイズやフレームレートの指定を確認してみると良いかも知れません。

今回手に入れたWEBカメラ、調べてみたら2008年頃に発売開始されたものらしく、既に販売終了になっているようです。
カメラが古すぎて、（今では当たり前に対応しているであろう）1280x720 に対応していなかったというオチでした。
営業出身20代女性の未経験エンジニア転職記

#はじめまして

Qiita初投稿です。
今回は母校🏫であるDMM WEBCAMPさんのAdvent Calendarに参加させて頂けることになり、アウトプットの第一歩を踏み出す事ことが出来ました。有難うございます！✨

今回はわたしの未経験エンジニア転職について書こうと思います。
誰かの人生における大きな決断への手助けになれば幸いですし、何よりお世話になったDMM WEBCAMPさんへの恩返しになれば嬉しいです😊

:::note warn
数多あるうちの一つの成功体験です。
わたしの体験を一つのヒントにしてやろう〜👀
ぐらいの感じで読んで頂けると有り難いです🙏
:::

本題に入る前に私の経歴を軽く説明します。
４年制大学(大学)卒業後、専門商社へ新卒入社しました。その後3年間勤務し、DMM WEBCAMPへ入学、そして今年の秋に自社開発企業へ就職しました。現在は、研修中で毎日頑張っております！

#結論

「コードと毎日触れ合える環境への転職」を最終目標にしてスクールへ入学しました。
また、「受託企業だと嬉しいな〜自社開発企業なんて私には絶対無理だ」と思っていましたが、自社開発企業へ入社が決定したことで、当初の目標はもちろん、自分の予想をはるかに上回る結果を出すことができました。

正直わたしは自分の技術力にあまり自信はありませんでした。（今もないですが…😅）
そんなわたしがなぜ今回目標を達成することができたのか自分なりに分析しました。

**・めちゃくちゃ自己分析した**
**・「この人と一緒に働きたいと思ってもらう」戦略**

大きくこの２点が大きな決め手になったように思います。それでは一つずつ説明していきたいと思います。

#めちゃくちゃ自己分析した

本当に何度も自問自答を繰り返しました。

<dl>
  <dt>したいことリスト100</dt>
  <dd>案外100個も出てこない…</dd>
  <dt>未来の理想像</dt>
  <dd>５年後、１０年後、１５年後の自分が何をしていたいか、根拠と今すべきこと、現在の自分の未達部分について書き出しました。ちなみにこれはスクールからの宿題でした。</dd>
  <dt>面接質問集を通して、自分への理解を深めていく</dt>
  <dd>自分インタビュー1000本ノックって感じでした、キツイです。</dd>
  <dt>自分の自己認識と、周囲の私への認識の間にあるギャップを無くす</dt>
  <dd>自分が仮に最高のPF仕上げたと思っていても、周囲の評価がイマイチであればおかしなことになるので、その現象を防ぐためにしました。</dd>
</dl>

上記に挙げた例は、わたしがやってみて効果があったなと思った方法です。
自己分析を固めていれば、"正しく"自己PRができるので、企業とのミスマッチも発生しにくいと思いますし、転職活動中を振り返っても、面接中用意していない質問がきた際、自己分析のおかげで柔軟に対応できたような気がします。

#「この人と一緒に働きたいと思ってもらう」戦略

先ほども述べたのですが、なにせ私は技術力への自信があまりありませんでした。
何故そう思ったかと言うと、スクールの同期や先輩方の中には私の何倍も努力を重ねてきてらっしゃる方が大勢いらっしゃったからだと思います。

**そんな中で就活という戦場で勝ち抜いていくにはどうしたらいいのか？**

尊敬できる方々のように努力するのも一つですが…わたしはここで「未経験エンジニア転職」ではなく、「転職」にスポットライトを当ててみることにしました。
全く異なる業界・業種とはいえ、社会人生活の中で培った私だけの経験ある！！

そこでまず私がしたのは、「もし私がエンジニア５年目、未経験から転職してきた子の教育係を任されたらどんな後輩がいいだろう…」という妄想でした。
その結果編み出したMY戦略が**「この人と働きたいと思ってもらう」戦略です。**（長い）

<dl>
  <dt>素直な方</dt>
  <dd>お互いにストレス無く、楽しく同じ時間を過ごせます</dd>
  <dt>コミュニケーションが滞りなくとれる方</dt>
  <dd>仕事が進みやすいです</dd>
</dl>

上記はほんの一例ですが、ここで浮かぶ理想像はその人の価値観によるものなので、企業と一致すれば、本当の意味でマッチする企業なんじゃないかと思います。その場合、我々は採用されたいし、企業側も採用したいと思うのではないでしょうか？

#その他

エンジニア転職にも関わらず技術のことにはあまり触れていないので、恐縮ですが😳
上記よりもダイレクトに転職結果に結びついたかどうかは分かりませんが、念の為やっていたことを記しておきます。

<dl>
  <dt>スクールで出された勉強プラスα</dt>
  <dd>Railsを中心にスクールでは学習するので、Rubyを書籍(チェリー本)を使用して自学習しました。また、業界理解の為に、ITパスポート合格を目指して学習しておりました。(なんとか合格しました💮)</dd>
  <dt>ITニュースの情報収集</dt>
  <dd>かなりアンテナを高く持っていました。これから挑む業界の状況と自分の価値観との擦り合わせを繰り返してました。</dd>
  <dt>実際に働いてらっしゃるエンジニアの方とのコミュニケーション</dt>
  <dd>現場のことを誤解したまま面接に挑みたくなかったのと、自分のキャリアプランを設計したくて積極的に参加してました。</dd>
</dl>

#まとめ

DMM WEBCAMPを選んで次のステップに踏み出せて本当に良かったです。
卒業した今でも一緒に学習や情報交換をし合えるような、素敵な仲間に出会えました。
皆さんには沢山の刺激を頂きましたし、コロナ禍で励まし合いながら学習し続けることができました✨

また未経験エンジニア転職における"プロ"である、キャリアアドバイザーさんには感謝してもしきれません。少ない情報からも私の希望する企業を持ってきて下さいました🙇‍♀️
歳の近い女性の方でしたが「プロってすげぇ〜〜」と思ってました。リスペクト…🙏

わたしも1日も早く、自分の会社はもちろん、社会の役に立つことができるエンジニアになれるよう精進しますっ✊
ここまで読んで頂き、有難うございました！！
gulp ejs パンくずbreadcrumb（オブジェクトkey, value展開）メモ

# gulp ejs パンくずbreadcrumb（オブジェクトkey, value展開）メモ
パンくずリストはサイトでは欠かせないほど実装されている。パンくずをejsで実装する際に、key, valueセットでテンプレートに渡して展開する方法をメモしておく。

## 環境の整理
- gulp v2.3.0

## 方法
1.以下のようなパンくずを作成するとする。
![スクリーンショット 2021-12-08 075557.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/c80ef25b-994e-c538-9e8d-e7559a4b3f74.png)

2.index.ejsにて、commonDataのbreadcrumbsにkey, valueセットを書く。
  /assets/inc/_breadcrumb.ejsテンプレートにcommonDataをcommonという変数名で渡す。

```
<%
  var commonData = {
    ...
    breadcrumbs: {
      'トップページ': '/',
      '会社概要': '/company/',
      '資産': '/assets/',
    }
  };

  ...

  <%- include('./../assets/inc/_breadcrumbs',{common:commonData}); %>

%>
```

3._breadcrumb.ejsテンプレートにて、common.breadcrumbsのkey, valueを展開する。

```
<div class="c-breadcrumbs">
  <div class="c-breadcrumbs-box">
    <% Object.keys(common.breadcrumbs).forEach(function (key) { %>
    <a href="<%= common.breadcrumbs[key] %>"><%= key %></a>
    <% }); %>
  </div>
</div>

```

＊補足
breadcrumb.scssは以下

```
// breadcrumbs
.c-breadcrumbs {
  background-color: #f2f2f2;
  .c-breadcrumbs-box {
    max-width: 1280px;
    margin: 0 auto;
    padding: 20px;
    a {
      display: inline-block;
      padding: 0 10px;
      font-size: 13px;
      color: #24588d;
      &:not(:first-of-type) {
        border-left: 1px solid #24588d;
      }
    }
  }
}

```

OK
Node-REDのログをCloud Loggingにキレイに出力したい

# はじめに
こんにちは。
これは、2021年 NI+C Advent Calendar 12日目の記事です。
毎年のごとく、（Google Cloudのはずだけど）私はNode-RED絡めて書きます。

# Node-RED Flowのログを出力する
Node-REDのフローからログを出力する際は、出力したいフローの箇所に[Debug Node](https://nodered.jp/docs/user-guide/nodes#debug)をつなげて出力します。GAE等でもこれは変わらずDebug Nodeの設定で「システムコンソール」にチェックを入れればCloud Loggingにちゃんと出力されるのですが、、、重要度指定なし、出力対象のオブジェクトは全てStringとして出力されてしまい、せっかくのCloud Loggingの便利さが活かせない残念な結果になってしまいます。お仕事で使うのであれば、こういったところも「運用しやすさ」を意識してやりたいですよね？でも、どうやればいいのでしょうか、、、？

# Cloud Loggingにログをキレイに出力したい（前準備）
[Google Cloud用にカスタムしたスターター](https://gitlab.com/ktsz/node-red-starter-googleappengine.git)を使いましょう。これを使うと、Cloud Loggingに合わせた出力が可能になります。もし、スターターコードは使わず進めたい場合は、以下を自分の環境に移植してください。

- [utils](https://gitlab.com/ktsz/node-red-starter-googleappengine/-/tree/master/utils) フォルダ（中身すべて）
- [settings.js](https://gitlab.com/ktsz/node-red-starter-googleappengine/-/blob/master/settings.js)

```js
// settings.js
// 8行目
const logger = require('./utils/logger');
// 9行目
const logHelper = require('./utils/logHelper');
// 74-78行目
      handler: function () {
        return function (msg) {
          logHelper.log(msg);
        };
      },

```

# Cloud Loggingにログをキレイに出力したい（フロー実装）
以下図のようにワイヤリングしてください。
![スクリーンショット 2021-12-12 21.09.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142110/61f0de68-0068-e0e6-1fac-212e70755e4d.png)
Function Nodeは以下のように記入ください
**LOG_MSG（Function Node）**

```js
let logMsg = "ログタイトル（一言メッセージ）";

let logObj = {
    "LOG_SEVERITY": "info", // Cloud Loggingの重要度
    "LOG_MESSAGE": logMsg,
    "payload": msg.payload // ログの詳細
};

msg.log = JSON.stringify(logObj); // Cloud Logging出力用 ※1
msg.payload = logObj; // Node-REDデバッグタブ出力用

return msg;
```
※1: Version2.0.6以降（だったかしら、、）のNode-REDからDebug出力になにか手が入ったっぽく、Debug Nodeでシステムコンソール出力する前にJSONをStringに変換しないと、フォーマットが崩れて出力されてしまいます。。ですので、`msg.log = JSON.stringify(logObj)`は今は必ず行いましょう。（いつか、問題箇所見つけて修正します。。）

# Cloud Loggingでログを確認
LOG NAMEは **winston_log** として出力されますので、winston_logで絞り込んでください。
LOG_MSG（Function Node）のコードとの対応は以下図のようになってますので、目的のログが出力されたか確認ください。
![スクリーンショット 2021-12-12 21.57.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142110/0496706b-4da0-2052-4166-851fda1db49f.png)


# まとめ
いかがでしたか？？
Cloud LoggingはGCP上の様々なログを統合し確認できる、フィルタリング操作にも優れたツールで、Cloud Monitoringと組み合わせてログ条件でのalert設定も可能です。運用面で非常に役に立つこの機能にNode-REDも少しの工夫で対応できますのでぜひご活用ください。
railsとmongoid環境で論理削除を導入する

※自分用の備忘録です。

```c#:Gemfile
gem 'mongoid'
gem 'mongoid_paranoia'
```

```c#:models/user.rb
class User
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Paranoia


  field :deleted_at, type: DateTime

end
```


```c#:pry
pry(main)> User.count
=> 1

User.first.destroy
=> true

User.count
=> 0

# モデル名+deletedで論理削除されたデータが全て表示される。
User.deleted.count
=> 1

User.deleted.first
=> #<User _id: 61b5d828746fc2954d25e61a, created_at: 2021-12-12 11:08:24.417 UTC, updated_at: 2021-12-12 11:43:42.249 UTC, deleted_at: 2021-12-12 11:43:34.534 UTC, email: "sample@gmail.com", password: "HKc7ZcfTAk2a5l8WmOGTLL9CMzIog4VsDoVgX5/YpsJBiC1XB9d25eIjY3Tj8gwWICZuYFo83stQE86StmxsywBsi0Y0Jb247DOs3S+iQpCdBQ==--43Y+l/g0UMhK9Eik--rjhdsO1gz+rBFg1+0eNy7Q==">

pry(main)> User.count
MONGODB | localhost:27017 req:279 conn:1:1 sconn:60 | event_book_development.aggregate | STARTED | {"aggregate"=>"users", "pipeline"=>[{"$match"=>{"deleted_at"=>nil}}, {"$group"=>{"_id"=>1, "n"=>{"$sum"=>1}}}], "cursor"=>{}, "$db"=>"event_book_development", "lsid"=>{"id"=><BSON::Binary:0x19900 type=uuid data=0x08c6bdf294194fac...>}}
MONGODB | localhost:27017 req:279 | event_book_development.aggregate | SUCCEEDED | 0.003s
=> 0
```
VB.NETでCalendarExtenderを使った

仕事でVB.NETを使用しているので、その関係で。
古い情報はあったけど、新しい情報がなかなか見つからなかったので備忘録として。

### VB.NETでScriptManagerをインストール
NuGetパッケージの管理から
``AjaxControlToolkit``と``AjaxControlToolkit.StaticResources``をインストール

### コード
```vb:カレンダー
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>

<table>
  <tr>
    <td>
      <asp:Label ID="lblCalendar" runat="server">日付を指定</asp:Label>                    
    </td>
    <td>
      <asp:ScriptManager ID="ScriptManager1" runat="server" EnableScriptGlobalization="True"></asp:ScriptManager>
      <asp:TextBox ID="txtCalendar" runat="server"></asp:TextBox>
      <ajaxToolkit:CalendarExtender ID="extCalendar" runat="server" TargetControlID="txtCalendar" Format="yyyy/MM/dd" PopupButtonID="btnCalendar" 
          PopupPosition="BottomRight" FirstDayOfWeek="Sunday" />
      <asp:ImageButton ID="btnCalendar" runat="server" ImageUrl="./Img/calendar_icon.png" Width="20px"/>
    </td>
  </tr>
</table>
```

### ブラウザ表示
カレンダーアイコンをクリックするとカレンダーが表示。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683664/bcf1c3bd-3ac8-95ae-77f4-0c2937bb0ea3.png)

土日の色とか、フォントなど、スタイル調整ができそうですが、一応表示できたので今回はこのまま。


### 参考資料
[新しいASP環境で、旧環境で動作していたCalenderExtenderが動作しない](https://teratail.com/questions/307969)
[Ajax Control Toolkit スクリプト バンドル](http://surferonwww.info/BlogEngine/post/2018/06/10/bundling-script-and-css-files-on-ajax-control-toolkit.aspx)
[CalendarExtender の日付の表示](http://surferonwww.info/BlogEngine/post/2013/07/26/show-japanese-style-date-on-calendarextender-of-ajax-control-toolkit.aspx)
[［ASP.NET AJAX］Calendarコントロールで日付入力ボックスを定義するには？［2.0のみ、C#、VB］](https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/575aspajaxcalendar/aspajaxcalendar.html)
[AjaxControlToolkit の CalendarExtender のカレンダーを日本語表記にする](https://devadjust.exblog.jp/7018028/)

### アイコン
カレンダーアイコン:[フリー素材](https://icooon-mono.com/12551-%e3%82%ab%e3%83%ac%e3%83%b3%e3%83%80%e3%83%bc%e3%81%ae%e3%83%95%e3%83%aa%e3%83%bc%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b34/)
貴様の幸せ度合いを数えろ ～ハピネススカウターを実際に使ってみた～

# 初めに
この記事は、@ymd65536さんの記事を実際に運用した記事になります。

https://qiita.com/ymd65536/private/f1d50596cdd1d76d1c7b

# 結婚式説明
## 経緯
来る12/11　僕の友人が結婚式をすることになりました。そこで余興を依頼されどうしようかなと思いました。
そこで@keeey999さんの記事を見つけ、この記事の内容を実施することにしました。

https://qiita.com/keeey999/items/7ce7c4bc342ca2ec7319

## 実装
実装は@ymd65536さんと協力しました。
今回の方針として、実装の記事と運用の記事を2点書き作ったものをどう活かすか、どういうフィードバックが返ってくるかという点も含めてエンジニアとしてどうやっていくべきかということを重要視して取り組みました。

## やったこと
Amazon Rekognitionを使用したLINE BOTの作成です。
構成自体はほぼ同一の構成となりました。技術的な点は@ymd65536さんの記事にて紹介されていますので、ご覧ください。

https://qiita.com/ymd65536/private/f1d50596cdd1d76d1c7b#%E6%A7%8B%E6%88%90%E5%9B%B3

## 要件定義
新郎新婦側と要件を詰めていくときに出てきたのは、ユーザーの画面だけで済ませられること(余計な画面遷移はしないこと)、ランキングがあとで見れること(少なくとも1位がわかること)が重要要件としてありました。
また、参加者の個人情報に配慮する点や、簡素にするという点も要望として挙げられました。

## 要件定義面での課題
まず、ユーザーの画面でどうすませるのかという点、ランキング機能を実装するときに余興としてどう組み立てるのかという点を考慮する必要がありました。

## 余興の設計
今回のLINE BOTをやる上で余興の構成を考える必要があったため、構成を検討しました。余興の時間は10分でしたので、
3分くらい説明、5分くらいアクティビティ、2分で集計と商品渡しとしました。
プレゼン資料としては、3分くらいで導入のスライド、アクティビティをやるスライドと集計用のスライドという感じです。
今回ランキング機能の実装を時間の都合上やらなかったので、DynamoDBで1位を人間的に判定しながら、1位の写真をダウンロードして、後から写真をスライドに貼るということをしました。

## 点数の考慮
年代が20代が大半だったので、スカウターネタで53万点(フリーザーさんのやつですね・w・）
をベースに点数をつけることにしました。
点数が100点よりも、余興なのでエンタメ性を考慮する、また世代的にフリーザさんわからない人はいないだろうという理由で、
55万点を最大値にしています。

余興時には、皆さんの戦闘力はフリーザさんを超えています？みたいな感じで参加者に呼びかけたので、参加率が高くなったかと思います。
また新郎新婦の親族の方も参加していただけたので、使ってもらうという点から導入は成功だったかなと。

## LINE BOT　

今回は以下のような画面が返ってくるようにしました。
単純にrecognition APIのレスポンスをそのまま返しつつ、幸せ度に550を掛けてフリーザさんのネタに近づけるようにしています。
また事前に測定した新郎新婦の点数を超えていると新郎新婦と同じくらい幸せですという文言も返すようにしました。

![スクリーンショット 2021-12-12 21.36.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1507944/7188fe7a-e5bd-2250-027f-e7c4f291e046.png)


## 余興
余興スライドはネタ満載なのでお見せできませんが・・・
QRコードはスクリーンに移せばいけたこと、意外とみんな乗り気で写真を撮ってくれたので良かったかなと。
実際には50名で200枚くらいの写真が取れました。

### 実際にはこんな流れです。
スクリーンにスライドを映しながら簡単な自己紹介
5分間時間を計り、その場で撮影した写真を測定してもらう。
最後に結果を確認し、幸せ戦闘力1位の写真を撮影した方に景品。
余興のあとも自由に使えるようにしておく。（二次会の間も）

## 余興振り返り
今回の余興で振り返り点がいくつかあったので、以下に記載をします。

### 技術的な話がわかりづらかった。
#####1.linebotを使っていたのですが、伝わりずらかったようです。実際にシステムって言って反応鈍かったので感情分析AIとか言って明日おけば良かった気がします。
### 一覧ページの実装
#####2.上位5名の得点と写真が映るページがあれば分かりやすかったかなと、スクリーンにはQRコードを5分間の時間の間に移していたのですが、スクリーンが綺麗だったので、意外と写りがよく、半分分割にして移して、現在の状況を表示するページがあってもいいかなと思いました。
### 顔認証の精度
#####3. 意外と顔認証はシビアにしていることがわかりました。実際に人間の測定を見ながら検証を重ねていく余地があったかと思います。

# 振り返り
今回の記事はどちらかというと技術記事から外れますが、実際にエンジニアが作成したものを自分で試すという機会はほとんどないのと、本番で使ってもらうことの難しさなど多くの学びポイントがありました。
次回も顔認証技術を使って色々遊んでみたいなと思います。
GIHOZのPictmaster味

#概要
GIHOZを使って組み合わせテストのテストデータ作成に取り組みます。
[前回](https://qiita.com/KazuhiroYoshino/private/86155ef144abd08ac7b9)まで、Pictmasterを利用した組み合わせテストについて紹介しましたが、[GIHOZ](https://www.veriserve.co.jp/gihoz/)にも、組み合わせテストに取り組めるツールが用意されていますので、それを使ってみます。
果たして、Pictmasterのように、あるいは、それ以上の特徴的なことがあるかが、今回の内容です。
#お題
前回までと同様の、ラーメン店のレシート発券システムです。

|因子|パラメータ1|パラメータ2|パラメータ3|パラメータ4|パラメータ5|
|:---|:---:|:---:|:---:|:---:|:---:|
|スープ|醤油|味噌|塩|豚骨醤油|あごだし|
|麺固さ|固目|柔らかめ|普通||
|背脂|多め|少なめ|||
|チャーシュー|肉厚|普通||
|ネギ|多め|少なめ|||

1. 麺の大盛りは、50円増し。レシートにも記載が必要。低カロリー麺では大盛り不可。
2. 煮卵、50円。レシートに記載要
3. 太麺（全てのスープで選択可）、極太麺（塩味では選択不可）、細麺（全てのスープで選択可）、極細麺（醤油味のみ）、低カロリー麺（全てのスープで選択可、50円増し）

#使い勝手の差
パラメータや値の並び入力については、Pictmaster同様の使い勝手で利用できます。
![gihoz001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/640730bd-b74a-598f-5ac7-3a73e996ad9b.png)
制約表ですが、因子別となっていて、制約条件のANDが制約表で作業できないのがちょっと不便ですね。
制約式を記述するしか方法無さそうです。
![gihoz002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/9c0904cb-0295-2e11-b4e7-77405e6f7755.png)
今回の事例では、麺の種類だけで、スープ味と麺大盛りが制約されたので問題ありませんが、例えば次のような仕様変更が発生したとします。

1. 低カロリー麺で背脂多めを選択した場合は、煮卵禁止

Pictmasterの制約表なら、以下のように記述できるのですが、
![gihoz005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/834c8278-edb9-9010-4bdd-243a31695102.png)
制約式自体は、難しいものでは無いのですが、Pictmasterに慣れてしまうと、Excel表のセル色塗り操作からなかなか抜け出せない感はあります。
#生成結果の比較
生成されたテストデータは、Pictmasterと同じ件数の22件でした。中身はよくよく見ると微妙に違うことに気がつきますが、いいことにします。
![gihoz003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/75bfb29b-351d-c5d2-fc49-d09060774682.png)

#クラフィシケーションツリーを使ってみる
制約表の使い勝手に、制約がある。　で終わってしまうと、GIHOZのいい味が出ませんので、他に使えるツールを試してみます。
![gihoz006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/66b11f2a-70ed-5a72-c59f-8ae12c8fafb2.png)
因子とパラメータをPictmasterでは、表にして扱いましたが、クラフィシケーションツリーでは、ツリーで記述します。ビジュアルで記述します。GIHOZ全般に言えるのですが、図にしたものからテストデータをボタン一発で生成できる点が、大きな特徴だと思います。
特に、テスト仕様レビューのような場合、表形式よりも、図の方が理解が早いです。
ALL Pair法だとあまり表とツリーとでは差が出にくいかもしれませんが、GIHOZで用意されている状態遷移図からテストデータのボタン一発生成は、図でレビュー後、「じゃあ、これでテストケース作っときますネー」で一気に片づくのは非常に便利です。
![gihoz007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/ecfd3a87-9226-00de-726e-4f2d6080b07f.png)
黒丸が付いたところでテストデータが作成されるという仕組み。勿論、この図の上で適宜修正も可能です。
制約については手作業になりますが。
#総括
ALL Pair法によるテストデータの生成をGIHOZを使ってPictmasterみたいに作業できるか試してみました。
制約条件の記述に関して、完全に同じようにはできない（制約式の学習が必要な場合もある）のですが、コミュニケーションツールとして使える点と、クラフィシケーションツリーのように組み合わせテストをビジュアルに扱えるツールが別途用意されている点で、ソフトウェアテスト活動に活用できるかと思います。
![gihoz008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/d1d82387-62e4-3fc4-7d7d-9df629170d51.png)

ツールがサポートしてくれると思うと、ドタ仕様変更やテスト項目抜け等の予測できないタスクが発生しても、落ち着いて対処できるのではないでしょうか。
Bootstrapは超便利だよって話

今回、僕が改めてBootstrapについて勉強してサイトをデザインする上でBootstrapがとても便利で使い勝手がいいと思ったのでその魅力を皆さんに伝えたくて記事にしました。
#そもそもBootstrapって何？
この記事を読む人の中には、そもそもBootstrapが何なのかということが分からない人もいるでしょう。Bootstrapとは一言で言うと**フロントエンドWebアプリケーションフレームワーク**です。Bootstrapは様々なファイル構成されており、あらかじめコンパイルされたcssファイルやjsファイルを使用します。それらのファイルの中にはテンプレートとしてタイポグラフィやフォーム、ボタン、ナビゲーションが予め書かれており、特定のクラスをhtmlタグにつけて使用します。
#Bootstrapの何が便利なのか
先ほどからBootstrapが便利だと何度も言っていますが、何が便利かはあまり伝わっていないと思います。Bootstrapの便利な点は主に二つあります。
#####1.他のプログラミング言語と一緒に使うのが便利
Webアプリケーションを作る際に色々なプログラミング言語を使うと思います。例えば、最近話題の``Vue.js``や``React``前からよく使われている``Ruby on Rails``などの言語でアプリケーションを作る際のデザインを整えるのにBootstrapをかけるようになっていれば、ある程度どの言語でもデザイン性優れたアプリケーションを作れます。
#####2.レスポンシブデザインが簡単に実装できる
最近ではスマホとパソコンだけでなく、iPadなどの様々な大きさのデバイスが使われ、どの大きさでもちゃんとデザインが崩れることなく、表示する``レスポンシブデザイン``についてフロントエンドエンジニアは考えなければいけません。そこでBootstrapのカラム・グリッドシステムを使うと、簡単に実装できてしまいます。

#まとめ
これらの点からフロントエンドのデザインを整えるのにBootstrapはとてもおすすめなので是非使ってみてください。
CodeDojoに参加してみた

こんにちは。

週末にCodeDojoというものに家族で参加しましたので紹介したいと思います。

# CodeDojoって何？

日本ではCodeDojo Japanが中心となって活動されています。
そのサイトによると

> CoderDojo は7〜17歳を対象とした非営利のプログラミング道場です。2011年にアイルランドで始まり、世界では112カ国・2,200の道場、日本には237以上の道場があります。

とのことです。

https://coderdojo.jp/


私自身は、数年前から活動は知っており、いつか子供連れて参加したいな、、と思ってましたが機を逸してしまい、そのままコロナ禍になってしまったので参加せず、という状況が続いてました。たまたま今回は参加募集の情報をSNSでキャッチし、家族を説得し参加したという次第です。
基本的には

- 参加者は作りたいものをもくもくと作り、最後に発表する
- 何をしたら良いか分からない人向けにはワークショップを開催してくれる
- 運営やメンター（お手伝いしたり、アドバイスしてくれる先輩方）は基本的に無償対応してくれているボランティア
- 参加費用も基本的には無償

といったもののようです。無償参加のコミュニティですので、有償のプログラミング教室ではありませんので、手取り足取りという感じではありません。過度な期待をせずに、自律的な参加が大事です。

# コロナ禍の影響

地域ごとのコミュニティ、Dojoということもあり基本的には現地参加だったようです。今回は場所の兼ね合いなどもあり、オンラインと現地のハイブリット開催でした。今回は様子を伺う意味合いも含めて現地とリモートで兄弟二手に分かれて参加してみました。私は弟の方と自宅からリモートで参加です。

ハイブリッド開催に関しては、

- oVoiceというサービスをつかってバーチャルでの共同空間を実現
- 教室の様子をカメラで写して常時共有する
- リモート参加者はワークショップはできないが、作っていて困ったことがあれば、チャット、画面共有、声かけでサポートしてもらえる

という工夫がされていました。今回は現地参加が５−６組、リモート参加が２組程度だったようです。

# 参加の様子と発表について

うちの子達はScratchという学校でもならったことのあるGUIのプログラミング言語、ツールを使ってゲームのようなものを作っていました。ScratchはNHKでも取り上げられています。厚切りジェイソンさんが出演されています。

https://www.nhk.or.jp/school/programming/start/

https://www.nhk.or.jp/school/sougou/programming/


学校でやった内容を思い出しながら、プラスアルファでこんな機能があったら楽しいのではないか？と想像しながら作り上げていく様は、興味が知識成長につながるんだな、と目の当たりにしました。

最後の30分は発表の時間です。誰かわからないリモート参加の人もいる意識もあったのか、ほとんどの人は発表しませんでした。（今回はやめとく、、的な）そこの緊張感に引きづられてか、うちからの参加メンバーも、緊張してやりたくない、と発表はパスしました。
参加ベテランの人の発表は見事であり、同じ小学生なの？とうちでは自信を無くしていました。。。


ただ、あんな風に自分も作りたいという意見や、次も参加したいと言ってましたので、何か始めるときには集団のコミュニティに飛び込むという体験は年代問わず、価値があるものなのかな、と思いました。

# 余談

ちょうどこの日はJavaのOSSライブラリに致命的な脆弱性が出た日でした。そこにはJavaで動くマインクラフトサーバーも影響が出とのニュースがでており、参加者の中でもJavaが、、、マインクラフトサーバーは選んだ方がよい、ログインしっぱなしなら再ログインしたほうが良い、、とこんな身近でJavaの話が及んでくるとは思いませんでした。

発表者の中でも、マインクラフトでこんな世界を作ってみました、と発表されている方もおり、さまざまなこだわりを感じました。

そんな中、以下のようなTwitterの書き込みも見かけ、すごいな、、と思いましたので共有します。情報が取ろうと思えばよく取れて、その情報を活用して育つ人はよく育つ良い時代ですね。。。

https://twitter.com/mana_cat/status/1469848534698852355

# まとめ

年代問わず、コミュニティやもくもく会の雰囲気、仕組みは人をやる気にさせます。コロナも落ち着いてきたタイミングですので、皆さんも何か初めてみてはいかがでしょうか？
[原因] docker login のときに Error response from daemon: login attempt to https://<IP>:<PORT>/v2/ failed with status: 401 Unauthorized 発生


## 概要

Docker Private Registry を構築中に発生したエラーとその対策．

BASIC 認証を使用した環境である


## エラーメッセージ

> Error response from daemon: login attempt to https://＜IP>:＜PORT>/v2/ failed with status: 401 Unauthorized


## 原因

`docker login` のあとに入力するユーザ名が間違えていた.
CQRS/ESのコマンドAPIレスポンスについて考える

この記事は　[ZOZO #4 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zozo) １6日目の記事になります。

今回のプロジェクトでCQRS/ESアーキテクチャの実装に挑戦しました。

![qiita1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150455/24faa8dd-0c73-bb7d-b0d1-c7e7accc0644.jpeg)

構成としては上記のような感じです。

今回は詳細なアーキテクチャ、実装の話はあえてしませんが、実装していて気になった点を１点だけ共有します。

いまさら言うまでもなく、コマンドで登録されたEventは非同期でクエリ側のDBに共有されます。
そこには時間差が生じますが、結果整合性はシンプルなアーキテクチャを実現するためのトレードオフとなります。


しかし、APIを使う側はそうもいかないこともあります。これまで慣れてきた強整合のアーキテクチャと比較した際の違和感もあるでしょうし、コマンドの結果変更されたステートの情報をすぐに使いたいというニーズもあるでしょう。

そんなとき、大事になってくるのはコマンドAPIのレスポンスです。
コマンドAPIのレスポンスを丁寧に返してあげることで、クライアント側の不満をかなり減らせると思います。

現在のステート全体を返すのか、変更されたものだけ返すのか、その仕様は状況によるかと思いますが、少なくとも、コマンドのAPIを叩いた直後にクエリ側を叩く必要がないように、またはAPIのレスポンスとクエリの組み合わせできちんと課題が解決するようにしてあげるのがよいでしょう。

と今回のCQRS/ES実装の反省点でした。

明日は @daikon510　さんの記事になります。自分もZOZO #３ Advent Calendar 2021の方に「モジュラーモノリスに対する考察」というタイトルで書きます。
[原因] docker login のときに Error response from daemon: Get https://<IP>:<PORT>/v2/: x509: certificate signed by unknown authority 発生


## 概要

Docker Private Registry を構築中に発生したエラーとその対策．

## エラーメッセージ

> Error response from daemon: Get https://＜IP＞:＜PORT＞/v2/: x509: certificate signed by unknown authority


## 原因

`/etc/docker/certs.d/＜IP＞:＜PORT＞/domain.crt` が存在していなかった

　

## その他

registry あるいは nginx のログを見ること
[原因] docker login のときに Error response from daemon: login attempt to https://<IP>:<PORT>/v2/ failed with status: 403 Forbidden が発生


## 概要

Docker Private Registry を構築中に発生したエラーとその対策．


### エラーメッセージ

> Error response from daemon: login attempt to https://<IP＞:<PORT＞/v2/ failed with status: 403 Forbidden

　

### 原因

アカウント・パスワードを定義したファイル (今回は `auth/htpasswd`) が存在しなかった

> https://docs.microsoft.com/ja-jp/azure/container-registry/container-registry-troubleshoot-login
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/af33cc08-00d2-77c6-08de-c21e49718081.png)

　

以上.
遊戯王で見るプログラミング

#はじめに
　みなさん遊戯王はご存じですか？実は遊戯王カードでは通常モンスターは効果の欄にフレーバーテキストが書かれています。そのフレーバーテキストの中でプログラミングを意識して作られたようなテーマがあるのは知っていますか？
　そうですご存知【クリフォート】ですよね。【クリフォート】でフレーバーテキストがみられるのはクリフォート・ツールとクリフォート・アセンブラの二枚となっています。ペンデュラムカードになじみがない方にはなんだこれと思う人もいるかもしれませんね笑
#テキストを見る
![ツール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2379781/bcd5659b-2af9-c26b-45ed-5de5f4d52820.jpeg)
![アセンブラ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2379781/16c3e801-6544-97bf-fe82-166163e8bcfe.jpeg)
クリフォート・ツール【モンスター情報】
システムをレプリカモードで起動する準備をしています...
C:¥sophia¥sefiroth.exe 実行中にエラーが発生しました。
次の不明な発行元からのプログラムを実行しようとしています。
C:¥tierra¥qliphoth.exe の実行を許可しますか？ ...[Y]
システムを自律モードで起動します。

クリフォート・アセンブラ【モンスター情報】
qliphoth.exe の 0x1i-666 でハンドルされていない例外を確認。
場所 0x00-000 に書き込み中にアクセス違反が発生しました。
このエラーを無視し、続行しますか？ 〈Y/N〉...[ ]
===CARNAGE===
たッgなnトiのoモdる知rヲu悪o善yりナnにoウよyノrりgトnひaノれsワiれワdはo人Gヨ見
イdなoレo知lもfカるeキr生iにf久永gベn食iてrッb取もoラtか木tノn命aベw伸ヲd手nはa彼

#解説
　クリフォートの語源は「クリフォト(Qliphoth)」＋「フォート（砦）」の合成語であると考えられています。
「クリフォト」とは、ユダヤの神秘主義カバラにおける悪の勢力もしくは不均衡な諸力を表す概念であり、セフィロトの裏の存在とも言われており、一説によればクリフォトは邪悪なものではなく、通常のリアリティの裏に隠された虚のリアリティの世界であるともされ、表裏一体の関係であると考えられています。
　またクリフォートには「機殻」という漢字表記もあてられますが、「クリフォト」という言葉自体がヘブライ語で「皮」「殻」を意味する「クリファ(Qlipha)」の複数形である事に由来するのだと考えられますね。

　ツールのテキストではパスが「C:」で始まっており、区切り記号にバックスラッシュではなく円記号が使われている所を見ると、このコンソールは日本語版のWindowsかMS-DOS互換環境で動いているのだろうか？と予想されます。
　また「sophia」フォルダ、明示の無い「次の不明な発行元」を始めとして、「Y」を選択した（この時点では『自律モード』でない）操作者の存在を匂わせるなど、内容には多くの謎の存在が示されていて、「レプリカモード」が「sophia」内部を参照しているのに対し、起動する「自律モード」は「tierra」直下「qliphoth」を要求しているのも作中世界観の【端末世界】何らかの示唆を感じられます。

　アセンブラのテキストでは    前半部分にはメモリアドレスを指していると思われるコード「0x1i-666」および「0x00-000」が見られますが、「0x」で始まるアドレスは16進記数法（０～９およびＡ～Ｆで数を表す方法）で記されるので、「i」が出現することは通常考えられないですよね。ここでクリフォートがクリフォトをモチーフにしているであろうことを考えると、これは虚数単位を表しているのだろうと読めますね。
　また「666」は新約聖書においてサタンにつながると言われる「獣の数字」であり、転じて悪魔、「ヨハネの黙示録」においては人間を指す数字とされています。
　これらを総合すると、「0x1i」は第一クリファであるバチカルを、「0x1i-666」はバチカルに割り当てられた悪魔であるサタンを指していると考えられます。
　メモリアドレスの下１桁が「６」になるのは８ビットOSか16ビットOSであるため、「qliphoth.exe」の動作環境はそのいずれかであると推測されます。
　また「0x00-000」のように仮想アドレスが全て０で示されるメモリ（０番地）は、殆どのOSではアクセス不能な領域としてマッピングされており、プログラミング言語では無効なポインタとしてこのアドレスを示すことが多いので、このフレイバー・テキストのように０番地の書き込み・読み込みを行おうとして発生するエラーの原因は大抵プログラムそのものの欠陥なのですが、「qliphoth.exe」はバグを抱えたアプリケーションなのでしょうか？
#おわり
　このようにクリフォートの基軸カード二枚から遊戯王で見るプログラミングについて解説してみました。ちなみに【クリフォート】の海外版のテーマ名は【Qli】なんです。なんだかエッチな響きですよね♡♡♡
SPRESENSE Wi-Fi Add-onボードiS110BのLチカ

Qiita Advent calendar2021の記事です。

:::note
Spresenseの関係会社に勤務していますが、業務外の個人活動の紹介です。
当記事は会社と関係ありません。
:::

:::note alert
誤った基板上のピン接続により故障する可能性があります。
自己責任でお願いします。
:::

Wi-Fi Add-onボード iS110Bを使っていましたが、モジュールについたLEDを光らせたことがありませんでした。

idy様のページ
https://idy-design.com/product/is110b.html

同ページにリンクが記載されているgithubにあるPassThroughを使いました。
https://github.com/jittermaster/GS2200-WiFi

PassThroughはATコマンドを入力してGS2200を直接制御するようです。

ATコマンドはシリアルモニターからも入力できます。

Githubにリンクがある"GS2200M, S2W Adapter Command Reference Guide"の10.3 GPIO Commandsを読むとGPIOの命令が書いてありました。

<img width="500" alt="211212t1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/3aaf2449-8f61-9f9c-45dc-0d2492217998.png">

LEDオン

```
at+dgpio=30,1
```

LEDオフ

```
at+dgpio=30,1
```

https://youtu.be/GO0TgCsBSjU

GPIO30をオンするとLEDを点けられる話は、上述のidy様のページの一番下にあるカタログをダウンロードすると基板のピン配から分かりました。

モジュールについているスイッチはGPIO25のようなので、何か機能を割り振れそうです。

Telit様のリンク先が404だったり、Githubやドキュメントは全部英語だったり、Telit様の登録時はGmailなどのフリーメール以外のアドレスが入力必須だったり、探し方が悪いのか日本語の参考情報がほとんど見つからなかったりと、私のような初心者にはスパルタすぎる。
Vysorでスマホの画面をMacBookにミラーリングする

この記事は [ディップ株式会社 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/dip-dev) の 12日目の記事です。

## はじめに
こんにちは〜☺️
ディップ株式会社でAndroidエンジニアをしております、ほりたです。
リモートワークになり画面共有の機会が増えて「端末の画面どうやってミラーリングしてるの?」とよく聞かれるので、「Vysor」を使ったやり方をご紹介します。

## Vysorとは
スマホ画面をPCにミラーリングすることができるツールです。
無料版と有料版がありますが、無料版で十分使えるので私は無料版を使っています。

公式サイトは[こちら](https://www.vysor.io/)💁
※Windows、Mac両方に対応していますが、ここではMacBookでのやり方を書いています！

## 用意するもの
- ミラーリングしたいスマホ端末(iOS、Androidどちらでも)
- スマホとPCを繋ぐケーブル

## 事前準備
- PCにVysorをダウンロードする([ここから](https://www.vysor.io/download/?return=https%3A%2F%2Fwww.vysor.io%2F))
- スマホのUSBデバッグをONにする

## 使い方
1. スマホとPCをケーブルで繋ぐ
1. Androidの場合はファイルの転送(MTP)モードにする、iOSの場合は「このコンピュータを信頼する」を選択する
1. PCでVysorを立ち上げる
1. ミラーリングしたいスマホを選択する(※iOSの場合は最初だけBluetooth接続設定が必要です)
![advent2desu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587653/14a2d68a-013b-f12c-2f71-46fef042d552.png)

1. ミラーリングできた☺️
![advent6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587653/4cff28d9-ff74-cd0d-49ff-54b10015eabf.png)

## おすすめポイント
### PCからスマホ画面が操作できる
Vysorを繋いでいるとPCでボタンタップやスワイプ等の操作ができるんです！🙌
画面共有している相手にもどういう操作をしているのか分かりやすくて重宝しています。

### 文字入力が楽
長文やメールアドレスを入力しないといけない時、PCスマホで入力するよりPCのキーボードで入力する方が楽〜という時、ありますよね。
それ、Vysorでできます🙋

### キャプチャツールと組み合わせると画面収録も簡単
バグ発見時など、スマホ画面を収録したい時にはキャプチャツールを使えばPCから簡単にできます。
PCでキャプチャすればスマホからPCに転送する手間も省けて良いですよね〜🙆
ちなみに私は[GIPHY Capture](https://giphy.com/apps/giphycapture)というキャプチャツールを使っています。

## ちょっと不便なところ
### 画質がそんなに良くない
動きを見る分には全く問題ないのですが、もう少し画質がよかったら最高なのにな〜と思います。
Vysorの有料プランに入れば「High Quality Mirroring」が使えるようになるのでどうしても画質が気になる場合は検討してみてはいかがでしょうか〜。まぁ他のツールを探すという手もありますが。

## おわりに
エミュレーターでビルドするとかなり時間がかかってしまうのが悩みだったので、Vysorにはかなりお世話になっています。
みなさんもぜひ使ってみてください〜そしてもしVysorよりも良いツールがあれば教えてください！
新人エンジニアとしての振り返り1

こんにちはnishioです

今週の振り返りと来週どうしたいかを記述していきたいと思います。

# 今週やったこと
* スッキリわかるJava入門の学習
    - 演算子
        - 算術演算子、比較演算子
    - 配列
        * 参照型でメモリ上に番地で管理される
    * メソッド
        * 渡す値、受ける変数を引数。渡す値が実引数、受ける変数が仮引数
        * オーバーロードの条件として引数の型、引数の数が異なること
        * コマンドライン引数はプログラム起動時の追加情報
    * クラスの分割
        * メソッドが多くなり管理しやすくするのが目的
        * コンパイルや実行の際は完全修飾クラス名(FQCN)で書く
        * import文はFQCNの入力負担を減らす目的がある
    * パッケージ
        * クラスをひとまとめにすることで処理の内容を把握しやすくする
        * パッケージが異なると同じクラス名を使用することができ
        * パッケージ名は企業のドメインを逆順にし、調整する
        * パッケージを含んだクラスを実行する際は、階層に合わせてフォルダを作成する
    * オブジェクト指向
        * 目的は大規模な開発を楽に行うこと
        * 属性(情報保持責任)と操作(行動責任)には責任がある
        * オブジェクトの3台機能は継承、多態性、カプセル化
        * 視点によって属性と操作が異なる
        * クラスの定義方法としてクラス図にまとめコードに記述する
        * クラス定義によってインスタンスを生成でき、型として利用できる
        * クラスが金型、インスタンスが金型から生成されたもの

# 来週はどうしたいか
今週は練習問題をやっていった際、上の方から出された応用問題に答えられずにいたので、課題を出されないようにその場で答えられるようにしたいです。そのためには当事者意識をもって取り組もうと思います。
でかいサイズのDBを一瞬で削除する

2GBごえのDBを削除する必要があり、`drop database {DB名};`でやったら、すごく時間がかかってしまっていろいろ問題があり、大変だった。

そこでググってみて、一瞬で削除できる方法が見つかったので、メモメモ。

## 直接データファイルを削除する

以下の手順で直接データファイルを削除する

今回削除したいDBは`testdbとする`

``` SQL
# MySQLにログイン
$ mysql -u {ユーザー名} -p
Enter password:

MariaDB [(none)]> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| testdb                 | ←存在する

MariaDB [(none)]> show variables like 'datadir';データファイルの場所を探す
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| datadir       | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.00 sec)

# 一度MySQLからログアウト or 別のタブで実行
$ sudo rm -rf /var/lib/mysql/testdb

-- もう一度DB一覧を表示
MariaDB [(none)]> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
|                        | ←削除されている
```

## 最後に
DBの削除は`drop database`しか知らなかったけど、こんなやり方もあるんだなと勉強になりました。


## 参考
[MYSQLでDROP DATABASEがエラーになる（ ERROR 1010 (HY000): Error dropping database ）](https://qiita.com/yaboojp/items/85e6356622e30cff88cb)
ExpressでWebSocket通信を実施する。

#アジェンダ
 ①WebSocket通信とは　
 ②WebSocket通信の実装
 ③WebSocketの実行結果
 ④コード解析 

#1. WebSocket通信とは
　双方向の通信を低コストで実施するための通信規格。SNSやゲームなどで双方向のリアルタイム通信を確立する場合に利用する。
　☆HTTP通信ではダメなのか？？
　　・各リクエスト毎にコネクションを確立する必要があるため、処理速度が遅い。
　　・クライアント→サーバへの方方向の通信であるため、双方向の通信が実現できない。
　　・HTTPヘッダーが長いため、通信するための情報量が多く処理速度が遅い。

通信確立までの流れ。通信確立はHTTP通信のハンドシェイクによって行われ、通信確立後、WebSocket通信に切り替わる流れとなる。

※詳細な規格はRFC6455を参照のこと。

#2. WebSocket通信の実装
なにはともあれ、実装して実際に動かして見るのが一番いい方法である。githubに公開されたwebsocket通信を実装する。

```javascript:ディレクトリ構成
~/develop/coop/webSocketDemo $ tree -I node_modules 
.
├── README.md
├── package.json
├── public
│   ├── index.css
│   ├── index.html
│   └── websocket.js
├── server
│   ├── server.js
│   └── websocket.js
└── yarn.lock
```

```javascript:server.ts
const express = require('express')
const app = express()
const expressWs = require('express-ws')
const websocket = require('./websocket')

expressWs(app);

app.use(express.static('public'))
app.use('/websocket', websocket)
app.get('*', (req, res) => {})
app.listen(3000, () => {
  console.log('server is listening on port 3000')
})
```

```javascript:websocket.js
const express = require('express');
const expressWs = require('express-ws')
const router = express.Router()
expressWs(router);

router.ws('/test', (ws, req) => {
  ws.send('接続成功')
  console.log('接続成功');
  let interval
  interval = setInterval(() => {
    if (ws.readyState === ws.OPEN) {
      console.log('test')
      ws.send(Math.random().toFixed(2))
      ws.send('test')
    } else {
      clearInterval(interval)
    }
  }, 1000)

  ws.on('message', msg => {
    ws.send(msg)
    console.log(msg)
  })
})

module.exports = router

```

#3. WebSocketの実行結果
①yarn startで実行。
　→この状態では3000番でlisten状態。
![スクリーンショット 2021-12-12 20.36.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/2808ca03-370d-9eb8-2b24-5b2fb63e65c9.png)

②ブラウザで3000番ポートにアクセス。
　→動き始めた。コネクション確立をトリガーに動き始めたことを確認。
　ブラウザ側でも、メッセージが出続ける。
![スクリーンショット 2021-12-12 20.38.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/e26abf20-3662-a555-41d9-5632332d9534.png)

![スクリーンショット 2021-12-12 20.38.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/1659c5b5-6927-e0bc-f180-77b8df084a85.png)

③クライアント(ブラウザ)からメッセージを送信
→「クライアントからのメッセージ」というメッセージでサーバに送信。サーバログにも出力されたことを確認。

![スクリーンショット 2021-12-12 20.40.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/eb9be92b-06df-0703-0c63-3526235bba0c.png)

![スクリーンショット 2021-12-12 20.40.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/4e6a921a-0b42-4e35-2b1d-116660b2a4ec.png)

④切断
　切断した際に通信が止まり、サーバログの出力も止まった。

#4. コード解析
 server.jsでlisten状態で待機。フロントでHTTP通信で画面を取得。取得後、WebSocket通信で「ws://127.0.0.1:3000/websocket/test」でサーバにリクエスト。リクエスト後、通信状態が確立。WebSocket通信にて双方向のコミュニケーションが実現される。

#参考文献
https://github.com/neroneroffy/webSocketDemo

https://qiita.com/chihiro/items/9d280704c6eff8603389

https://datatracker.ietf.org/doc/html/rfc6455
C#でカノジョをつくる（12日目）

お疲れ様です。たなしょです。
今日はLINQのプログラムを書きました。
写経したおかげである程度分かった気がしてきました。
## Containsメソッド
指定した文字が含まれているか判定します。文字検索とかで使えそうです。
## string型は値が変わるたびに新たなインスタンスを生成する

```c#
string name = "test1"
name = "test2"
```
nameの中身が変わったのではなくインスタンスの参照先が変わります。

## object型

```c#
object ob1 = 100;
object ob2 = 100;
bool b2 = ob1 == ob2; // b2はfalse
```
## foreachで多重配列も順番に出力できる

```c#
int[,] Test2D = new int[3,2] {{1, 2}, {3, 4}, {5, 6}};
			 
foreach (int i Test2D)
{
	Console.WriteLine("{0}", i);
}
```
## TryParseメソッド
数値に変換できた場合はtrue, それ以外はfalse。エラー回避に便利そうです。

## イテレーターの使い方
土日以外の曜日を1日ずつ取得して、年月日を表示することを10回繰り返すプログラムです。
こんな感じでイテレーターを使っていくんですね

```c#
class Sample
{
    static void Main()
    {
        foreach(DateTime dt in Test(10))
        {
            Console.WriteLine(dt.ToString("yyyy年MM月dd日（ddd）"));
        }

        static IEnumerable Test(int days)
        {
            DateTime dt = DateTime.Today;
            for (int i =0; i < days;)
            {
                if ((dt.DayOfWeek != DayOfWeek.Saturday) &&
                    (dt.DayOfWeek != DayOfWeek.Sunday))
                {
                    yield return dt;
                    i++;
                }
                dt = dt.AddDays(1);
            }
        }
    }
}
```

## LINQの使い方
初めてLINQのコードを書きました。これは2以上4以下の条件でデータを抽出します。
こう書いてみるとデータセットを条件つけて抽出する際に見やすいコードになりますね。

```c#
class Sample
{
    static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };
        var query = from n
                    in numbers
                    where n >= 2 && n <= 4
                    select n;
        foreach (var a in query) Console.WriteLine(a);
    }
}
```

## 最後に
LINQの書き方が理解できました。
これでC#の基礎となる部分は少しは理解できたと思います。
明日からオブジェクト指向プログラミングを軽く再度復習します。
Mac で rpiboot を build する

Compute Module 4 (CM4) を触ってみたくて reTerminal を手に入れた。

環境をぶっ壊したときに備えて、 OS のインストール手順を確認しておこうと、 OS のインストールをやってみることにした。

# reTerminal の CM4 への OS イメージの書き込み手順

reTerminal に付属の CM4 への OS イメージの書き込み手順は、以下のブログ記事を参考にさせてもらった。

https://lab.seeed.co.jp/entry/2021/07/13/120000

手順は以下の通り。

1. バックパネルを外す
1. ヒートシンクを外す
1. CM4 の横のスライドスイッチを切り替える
1. CM4 に対して OS イメージを書き込む側の環境（以下、作業環境）で rpiboot を動かす
1. USBで接続する
1. 作業環境で Compute Module 4 の eMMC 領域をディスクとして認識する
1. 認識したディスクに OS のイメージを書き込む
1. （補足：もし起動時に `ssh` を有効にしたいなら、などのいつもの作業はここでやっておく）
1. USBでの接続を解除する
1. CM4 の横のスライドスイッチを戻す
1. ヒートシンクを装着する
1. バックパネルを装着する

この中で、「Compute Module 4 に対して OS イメージを書き込む側の環境（以下、作業環境）で rpiboot を動かす」に関して、上記の記事では Windows 環境になっているが、手元の環境は MacBook Air (M1, 2020) だったので、ここだけ手順が大きく異なることになる。

# Mac で rpiboot を動かす方法

## Seeed Wiki を参考に進める

前述の記事には、「MacやLinuxの場合は、[こちら](https://wiki.seeedstudio.com/reTerminal/#for-maclinux)をご参照ください。」とあるので、辿ってみる。

https://wiki.seeedstudio.com/reTerminal/#for-maclinux

"FOR MAC/LINUX" と書かれているが、完全に Linux を前提にした記述しかないように見える。

## `rpiboot` のレポジトリを参考に進める

`rpiboot` のレポジトリ https://github.com/raspberrypi/usbboot を確認すると、 [`Readme.md` に macOS の項目](https://github.com/raspberrypi/usbboot/blob/master/Readme.md#macos) があったので、それに従って進めてみる。

```
$ git clone --depth=1 https://github.com/raspberrypi/usbboot
$ cd usbboot
$ brew install libusb
$ make
bin2c.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
         ^~~~~~~~~
1 error generated.
make: *** [bin2c] Error 1
```

`Readme.md` に書いてある通りにはいかない。まぁ、そんなもんだ。

## 問題点
解決作に至るまでにエラーを1つずつ解決していったが、問題点を整理すると以下の通り。

- 自分の環境では、シェルの設定で `cc` コマンドが `/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc` を向いてしまっていて、それが悪影響を与えていたっぽい
    - この設定、何のために入れたんだろう・・・？
- Homebrew でインストールした `libusb` のヘッダファイルやライブラリファイルが参照できていない

## 解決策
先に挙げた問題点に対応すれば、問題なく build できた。

以下、上で上げた `git clone` から手順の修正版である。

```
$ git clone --depth=1 https://github.com/raspberrypi/usbboot
$ cd usbboot
$ brew install libusb
$ export CC=/usr/bin/cc
$ export CPATH=$CPATH:/opt/homebrew/include
$ export LIBRARY_PATH=$LIBRARY_PATH:/opt/homebrew/lib
$ make
/usr/bin/cc -Wall -Wextra -g -o bin2c bin2c.c
./bin2c msd/bootcode.bin msd/bootcode.h
./bin2c msd/start.elf msd/start.h
./bin2c msd/bootcode4.bin msd/bootcode4.h
./bin2c msd/start4.elf msd/start4.h
/usr/bin/cc -Wall -Wextra -g -o rpiboot main.c -lusb-1.0
```

## 参考 : Intel Mac での手順の例
Intel Mac の場合、自分の環境では同様に `cc` が変なところを向いていたので、それだけ修正した。
Homebrew でインストールした `libusb` の `include` や `lib` は自動的に解決してくれた。 `/usr/local` 配下にインストールされていると、こういうとき楽なのかな。

```
$ git clone https://github.com/raspberrypi/usbboot
$ cd usbboot
$ brew install libusb
$ export CC=/usr/bin/cc
$ make
/usr/bin/cc -Wall -Wextra -g -o bin2c bin2c.c
./bin2c msd/bootcode.bin msd/bootcode.h
./bin2c msd/start.elf msd/start.h
./bin2c msd/bootcode4.bin msd/bootcode4.h
./bin2c msd/start4.elf msd/start4.h
/usr/bin/cc -Wall -Wextra -g -o rpiboot main.c -lusb-1.0
```
Clean ArchitectureのInputPortとOutputPortの引数には必ずコンテナクラスを使おう

# Clean ArchitectureのInputPortとOutputPortの引数には必ずDTOを使おう

Kotlin使ってるからコンテナクラス(DTO)なんていらんでしょ！ってサボってたら、思わぬところで罠にかかったので供養します。

## Clean Architecture

InputPortとOutputPortの二つはそれぞれControllerまたはPresenterに実装します。
当然ですが、**複数のUseCaseを一つのクラスに実装する**場合もあります。

## 同じメソッド名に潜む罠

複数のUseCaseを一つのクラスで実装する場合、実装したメソッドがどのUseCaseに対応するのか特定できる状態である必要があります。
UseCaseごとにメソッド名を変えてしまっても良いですが、同じメソッド名(execute(), handle()など)で統一し、オーバーロードによって解決することがほとんどだと思います。
その場合、書き方によってはUseCaseによっては一つのクラスに引数が完全に一致するメソッドを複数実装しなければならず、オーバーロードによる識別が不可能になります。

## 解決策

UseCaseごとにユニークなメソッド名、または引数にする必要があります。
メソッド名を統一する選択を行なった場合は、UseCaseの引数の代わりとして**UseCase名に基づいたコンテナクラス**を作ってあげると良いでしょう。

## 例

``` HogeUseCase.kt

data class HogeUseCaseInputPortInput(val hoge: String)

interface HogeUseCaseInputPort {
    fun execute(input: HogeUseCaseInputPortInput)
}

data class HogeUseCaseOutputPortInput(val hoge: String)

interface HogeUseCaseOutputPort {
    fun execute(input: HogeUseCaseInputPortInput)
}

```

~~コンテナクラスの名前がダサいのは置いといて、~~このようなUseCaseを徹底すれば引数が被ってオーバーロードできなくなるという問題はなくなります。いくら同じクラスに大量のUseCaseを実装使用が全て一意にユースケースを特定できます。

## まとめ

ユースケースとコンテナクラスはセットで作りましょう。
作らないと後々地獄を見ます。私は見ました。
Auroraをリードレプリカに「えいやっ」したら死んだ話

この記事は「[本番環境でやらかしちゃった人 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/yarakashi-production)」13日目の記事です。

# はじめに
初めまして
出張撮影マッチングプラットフォームのOurPhotoというサービスのエンジニアリングマネージャーをしているdoueと申します。

当サービスでは、データベースにAWSのAurora(MySQL)を使用しています。
2021/8に、AzureからAWSへのインフラ全面移行を果たし、その後、2021/10に当サービスでの繁忙期が迫ってきたため
Auroraのリードレプリカをオートスケールするように変更いたしました。

その際に起きてしまったことを懺悔したいと思い、記事を書かせていただきました。

# 当時の心構え
当時、当サービスの本番環境では
Auroraが１台構成で稼働していました。

Azure時代から元々DBが一台構成となっており、とりあえずはその形を踏襲して
Auroraでも1台構成にしていました。

繁忙期が10月に来ることはわかってはいたため
「まあリードレプリカ＆オートスケールの設定はすぐできるし大丈夫」くらいの感覚で
その時にサービス負荷に耐えるようと考えていました。

そしてその時は突然やってきました。。

# サービス負荷が爆発した
![スクリーンショット 2021-10-14 23.14.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73081/95215aff-8c90-e93a-1cd4-151729619533.png)

サービス繁忙期が10月と言ってはいましたが
実は、10月中旬までは、負荷もあまり上がらず、気にしていなかったのですが
突然、夜の時間帯にCPUが100%に張り付く事態になってしまいました。

例年、ユーザー数も増加してきていたのもあって予想を超えた負荷になってしまいました。

# 早急な対応
元々、リードレプリカを入れて、オートスケールをすることでCPU使用率は緩和されることは予想できていて
さらにその設定事態難しくもないため
問題が起きたのち、「してやったり」の気持ちで、即座にリードレプリカを設定しました。

![スクリーンショット 2021-10-15 15.36.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73081/7ce7beba-1f91-5ef7-e896-188b5df9ac9e.png)


結果、CPU使用率もガクンと減ってくれ、一件落着しました。

# 謎のエラーが多発

リードレプリカを導入した後、謎のエラーが多発しました。。
その後開発チームで原因調査をした結果

> アプリケーションのプロセス内で
リードインスタンスと、ライトインスタンスを行ったり来たりしていたため
DBに不整合が起きてエラーになっている

という問題が起きてしまいました。
いわゆるレプリケーションの遅延です。

書き換えたはずのレコードが、直後のプログラムで参照した時に反映されてないためエラーが発生してしまっていました。

「いやいや、仕組み的にはそれはそうだけどさ〜・・・」
という気持ちにはなりつつ、そんなことある！？と内心半信半疑でした。

# 原因はstickyオプションの設定だった

当サービスでのサーバーサイドは、Laravelで動いていますが
[stickyオプション](https://readouble.com/laravel/6.x/ja/database.html#:~:text=%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82-,sticky%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3,-sticky%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF)というものが存在します。

Laravel公式ドキュメントからの引用
> 現在のリクエストサイクルにデータベースに対して「書き込み(write)」処理が実行されると、すべての「読み込み(read)」操作で"write"接続が使われるようになります。

「そうそうこれこれ〜〜〜〜〜〜」と、なぜか感動してしまいました。

Laravelではこちらを設定するだけで、リードレプリカが問題なく動くようになります。

# 懺悔
リードレプリカ自体は、弊社の他プロダクトでも当たり前のように導入しており
設定が超簡単なので油断していました。

ユーザーや社内メンバーに多大なご迷惑をかけてしまったのは
マネージャーである私の責任に他ありません。

さて、今回の問題はちゃんと調べてればよかったよね、という話ではありますが
しっかりと、検証環境で確認しておくことが、やっぱり非常に重要だったなと
僕たちに気づきを与えてくれました。

ソフトウェアの世界では、何が起きるか本当にわかったものではありません。
今後はしっかりと検証を重ねて本番リリースをしていきます。

# 最後に(告知)
ここまでお読みいただいた方々、ありがとうございました。
[OurPhoto](https://our-photo.co/)という出張撮影サービスを少しだけ紹介させていただきます。

OurPhotoでは、「あたらしい写真文化をつくる」というビジョンのもと運営をしているサービスです。
特に七五三やお宮参りと言ったイベントは
従来、スタジオ撮影といった方法で思い出として写真に収めるのが通例となっています。

また、カップルや家族などの記念日などだけではなく
日常も含め、その素敵な瞬間をもっと気軽に安心して写真に残せたらという思いでOurPhotoを運営しています。

ご興味を持っていただけた方は
ぜひOurPhotoで、大切な方との思い出を写真に残してみてください。