OmniAICreator/Qiita-1.07M huggingface dataset:
【PHP基礎復習11】配列要素の和

[問題]
1から入力値Aまで1ずつ増えていく整数の値の和を求めよ。
なお、Aは2以上とする。

# コード
```PHP
$input1 = fgets(STDIN);
$input2 = range(1,$input1);
echo array_sum($input2),PHP_EOL;
```

↓　140と入力

# 結果
```
9870
```


☆ range(a,b)
→　aからbまでの配列

☆array_sum()
→　配列の要素の和
symfony4のローカル環境構築

# 経緯
symfony4の勉強しようと思っても買った本のコマンドをコピペするとsymfony5が入ってきて、微妙に仕様が変わっているのであえてバージョン指定したかった。

なお、2022-9-8現在、DB操作に必要なクラスがどうやっても動きませんでした。
特定のライブラリをダウングレードすれば動くとあるけど、それでも動かないので他もサポート切れてるかも？
勉強するだけなら諦めて5をインストールしたほうがよさそうです。

# インストールコマンド

バージョンを指定するにはインストールコマンドの最後にスペースあけてバージョン番号を書く。
ところがzshの場合これではアスタリスクが想定外の解釈を起こすらしくエラーになるので、ここだけbashにして終わったらzshに戻す。
（他の解説サイトでは.zshrcを書き換えていたけど、今回は一行動かすだけだしこれでいいかな、と。）

```
bash
composer create-project symfony/website-skelton project_name 4.4.*
zsh
```

簡易サーバを使いたい場合は以下のコマンドで追加のインストールが必要になっている。

```
cd project_name
composer require symfony/web-server-bundle --dev
```

これをしないと 

```
bin/console server:run
```

しても以下のエラーでサーバが起動しない。

```
  Command "server:run" is not defined.

  Did you mean one of these?
      dbal:run-sql
      server:dump
      server:log
```


MAMPとかちゃんとしたhttpdソフト使うなら不要だけど、使い捨てのプロジェクトにvertual hostの設定するのも億劫だったりするのであると便利。

# DB設定

プロジェクトルートフォルダにある .envを自身の環境に合わせて書き換える。

## .env
勉強用の場合、以下の行を有効化して他のDATABASE_URL=で始まる行を#でコメントアウトするだけでいい。

```
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
```

## ormライブラリをダウングレードする
bin/console make:entity　すると
以下のエラーで動きませんでした。

```
Class Doctrine\Persistence\Mapping\Driver\AnnotationDriver does not exist
```

>symfony 4.4 のサポートが終了したため、symfony 5.4 に移行するまでは composer.json を変更し、doctrine/orm を 2.11 にダウングレードする必要があります。

出典：https://github.com/symfony/symfony/discussions/46403

だそうです。

この参考ページにcomposer.jsonを書き換えてupgradeすれば治るとかいてありますが、
そのとおりやっても動きませんでした。
メモ：Android 12(API Level 31)で通知のアプリアイコンをタップしてもアプリが起動しない現象について

原因
-
これ。

https://developer.android.com/about/versions/12/behavior-changes-12?hl=ja#notification-trampolines

通知トランポリンが正式名称らしい。
対応方法は各自で調べて下さい。
SGD vs Adam Optimizerを選ぶときの単純な法則

# 概要(モデルの精度 vs 学習の収束性)
Optimizerって沢山あって、結局どれが良いの？ってなる。論文でよく使われているやつを使えば良いのだが、様々な条件(モデルの大きさ、タスクの難易度、データの複雑性、lossの関数、etc...)によってBestなOptimizerは変わってくる。
Optimizerを選ぶときの単純な法則を知っていると、迷わずに済むと思う。

今回はモデルの精度と学習の収束性の2点が大きくある。
* modelの性能を上げたい場合は、local minimaに収束しないようにしないといけない。local minimaから脱出するために、gradientを大きく更新させる必要がある。しかし学習が安定しにくい。
* 学習を早く滑らかに収束させたい場合は、learning rateの調整やgradientのmoving average(移動平均)を取ったりする事で、パラメーターの突発的更新を抑制出来る。しかしlocal minimaに陥いる可能性が高く、精度が出にくい。

幾つかの有名なOptimizerを例に見ていく

# SGD
SGDはシンプルにGradient方向へ重みをupdateする。故にlocal minimaから脱出しやすく精度が高くなる。余談ですが、[PytorchのSGDのimplementationはrandomにサンプルするという確率的機能は無いらしい](https://discuss.pytorch.org/t/is-the-sgd-in-pytorch-a-real-sgd/9714)。じゃあSGDじゃなくて、GD(Gradient Descent)じゃんという会話があり、その通りだと思った。

# SGD with momentum
SGDにgradientのmomentumを付ける事で学習をsmoothにする。故にSGDより精度が落ちるが学習の収束性が増す。

#  Adam
AdamはSGD with momentumにRMSPropという学習率を調整する機能が付いている。故にSGD with momentumより精度が落ちるが学習の収束性が増す。


# 結論
より多くのSmoothingの機能を付けることで学習速度が早く安定するが、一方で精度が落ちてくる(local minimaに陥りやすい)。まずはAdamで学習してみて収束するかを確認して、精度を上げたいのであればSGD with momentumまたはSGDを使ってみるのが良いと思う。
エリック・エヴァンスのドメイン駆動設計 1部 1章を読んでまとめてみた

# はじめに
私はエンジニア未経験です。現在はエンジニアへ転職活動中です。
なのでここに記載してあることは一個人の考え方・理解であり、間違っている箇所は多々あります。
とあるきっかけでこの本を買い、読んでいるので、自分なりにまとめていこうと思います。


## 本題に入る前に

**ドメイン駆動設計（DDD「Domin driven designの略」）** とは
特定のドメイン領域において**モデリング**という手法を使って、
ソフトウェアの価値を高めることを目指す開発手法のことを言う。
DDDは過去のプロジェクトの成功パターンを抽出したものである。

<br>
・・・？
<br>
<br>
一旦ここでは細かいことは置いておく。
早速本題へ。

# 1部　ドメインモデルを機能させる
「モデル」って何？
　　　↓
「モデル」とは、問題解決のために、物事の特定の側面を抽象化したものである。
抽象化とは必要な要素を重点的に抜き出して、不要な要素は捨て去って解決していくという意味であると考える。
複雑な物事を軽減して、効率的な設計と実装を可能にすることである。極限的に言えば簡単にしていくってこと。
モデリングとはモデルを作ること。
<br>
「ドメイン」って何？
　　　↓
業務や事業のことを指していると考える。

よって「ドメインモデル」は特定の取り組んでいる課題（ドメインの）を抽象化したものであると考える。
<br>
「ドメインエキスパート」って何？
　　　↓
ドメインについて詳しい人。ビジネスをよく知っている人。

ここら辺の単語はひっきりなしにでてくるから頭の中に入れておく。

### モデルの３つの基本的用法
①モデルとコードを結びつけていく。（プログラミングをするためにモデルを作っていこう。）
②チームメンバーの共通言語にする。
③考えや課題を表現していく。

### 開発者がすべきこと
ドメインを使って、ビジネスの知識を積み重ねていきましょう！
　　　↓それによって
ユーザーのために何が必要なのかを見失わない。

# 1章　知識をかみ砕く
### モデルを効果的に成長させていくために
**ドメインエキスパートと開発者は協力していきましょう！**

※1. モデルについてチームで話し合ってスケッチしていく。
　　　↓
2. 言語を洗練させて共通の理解をし合おう。
　　　↓
3. モデルにさまざまな知識を取り込んでいく。
   （ドメインエキスパートの知識）
　　　↓
4. 役に立たない、核心でないものは取り除く。
　　　↓　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　
5. モデルと実装を結びつけて開発していく。
　　　↓　
※1. に戻る。（以下ループ）
**ループすることでモデルを成長・改良させ続けていく。**

最初にできたモデルは大したできでもなく、これといった気付きもないので、
改善しつつ、しっかりと精査していこうね！ということ。
**知識をかみ砕いて、チームの持つ知識が価値のあるモデルへと変わっていく。**

### 知識をかみ砕いて本質をシンプルに説明していく
より役立つモデルを作るには知識をかみ砕く必要がある。
　　　↓　
知識のかみ砕きは、ドメインエキスパートと開発者のチームで協力して行い、
開発者がリードしていく。

知識をかみ砕くと、ビジネスルールの矛盾に気づける。
（ドメインエキスパートの頭の中でいい感じに調整している矛盾はシステム化できない。）
知識をかみ砕くことによって、ルールが明確になり、具体化されていく。

### ドメインモデルは改良し続ける
改良をし続けることにより、モデルはプロジェクトに流れ続ける情報を
表現するツールとなる。
そのためには、**継続的学習**が必要である。
継続的学習とは、ドメインモデルの知識と技術的な知識を向上させること。

**モデルは完成しない。進化していくもの。**
最初からいいものはできないということだろう。

# まとめ
- ドメイン駆動設計とは開発者とドメインエキスパートがより良いモデルを探求しながら
システムを作り上げていく開発手法である。

- フィードバックループの点が、アジャイル開発に類似していると思った。

次回は2章　コミュニケーションと言語の使い方を記載したいと思います。
cURL error 77: error setting certificate verify locationsが発生したときに行った対象法

## 環境情報
+ PHP 7.4.28
+ Composer version 2.3.3  
+ Laravel Framework 8.82.0
+ xampp 3.3.0

## 何があったのか？
Laravelでアプリケーションを作成していた時に、画面を遷移させようとするときに下記発生した。

## 直面したエラー
下記エラーが発生した。
```:エラー文
cURL error 77: error setting certificate verify locations: CAfile: C:\xampp\apache\bin\curl-ca-bundle.crt CApath: none
```

**どうやらエラー文はCAPathが見つからないとのこと**


## 修正方針
**CAPathのパスを設定していく**

>CAPathとは
cafile が指定されていなかったりその場所にファイルが 見つからなかったりした場合、capath が指す ディレクトリを検索して認証ファイルを探します。capath は認証ファイルのディレクトリを正確に指している必要があります。

>cafileとは
ローカルファイルシステム上の証明書ファイルの場所。 verify_peer コンテキストオプションで リモートサーバーとの認証の際に使用します。

参考: [PHP公式マニュアル](https://www.php.net/manual/ja/openssl.configuration.php)


上記からもわかるように
CAFileの場所がわからないからCAfileかCAPathを指定して、証明書の位置がわかるようにしてくれとのこと。

## 修正方法
今回はcafileのパスを修正したいと思います。

```:修正前
openssl.cafile="C:\php-7.4.11\extras\ssl\cacert.pem" 
```

```:修正後
 openssl.cafile="C:\xampp\apache\bin\cacert.pem”
```

参考: [参考サイト](https://jpdebug.com/p/1700914)
※現在は記事がなくなってしまい、見れなくなってしまっています。


## 終わりに
今回はLaravelを作成するときに困ったことを記載してみました。
最後まで読んで下さり、ありがとうございました。
プライベート・出張先での　「今日何食べる？」を解決してくれるLINE Botを作ってみた

# 自己紹介
はじめまして。某会社で働く一会社員です。
今回は、LINE Botの制作に初めて挑戦してみました。これまで、SNSなども含めて余りデジタルというものに触れてこなかったため、制作にあたりつまづく事ばかりでした。
本当にド初心者ですが、試行錯誤の結果を投稿します。

## 制作の意図
プライベートや出張で、行ったことがない街へ行ったとき、ご飯何食べよう？と悩んだことないですか？
「どうせなら美味しいものを食べたい！」「せっかくなら地元の食材・料理を食べたい！」と思うもの。
そんなときに、LiNEに打ち込んだら、おすすめのお店の情報が返ってくる。
そんなLINE Botを作ってみたいと思いました。

## 目標とするところ
最終的な完成型としては、
-現在地を入力⇒LINE側から「何食べたい？」というメッセージが返ってくる
-「〇〇が食べたい」と返信⇒「予算は？」というメッセージが返ってくる
-「〇〇千円」と返信⇒「何人で？」というメッセージが返ってくる

のような、会話形式でお店を絞り込んでいくようなものを作りたい。

# 実際の動作
https://twitter.com/kou_n2405/status/1567474968912621568

# 使用したツール
-LINE　Developers
-Make
-hotpepper API

# 作成の過程（プロセス）
①APIを探す
　レストランやお店検索に必要な情報があるのは、ぐるなびやhotpepper。最初は、ぐるなびで試みるも、無料のAPIは終了しており、hotpepperであれば個人登録可能であったため、これに決定。
②オウム返しBotを作り、MakeからAPI情報を取り出せるように設定
![画像①.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/8c3b3728-2371-db27-edb3-16db4d812b98.jpeg)
③JSONモジュールを追加し、お店情報を取り出せるように設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/f3817600-d67b-5988-1c7b-4f6587f20e27.png)

❕問題発生❕　API情報がXml形式？？URLの変更、エクセルに一度Xmlファイルを貼付ける等、何度も変換を試みるも、うまくいかずエラーメッセージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/f5cb48d5-2b93-d296-7c33-3b8e8906e326.png)

![画像②.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/a19276cd-c28e-b46b-cada-ec609787ad24.jpeg)


# 総括
今までは、某グルメサイトを検索したり、情報誌から調べてみたりと意外と面倒くさい。
そんな時に、気軽に会話形式でお店が見つけられれば、楽だなと思ったのが制作のきっかけだった。
まだまだコロナ禍という事もあり、外食をするのが難しい方もおられるかもしれませんが、
いつか終息し、またみんなでワイワイできるようになれば、その時はぜひ使ってみたい。
ただ、このLINE Botは今回完成までは至りませんでした・・。
APIキーを設定し、店コードを入力すると、URL付きのメッセージが返ってくるところまでは出来たが、本来の意図する地域・店・予算などの情報返却までは出来なかった。
JSONの変換のところでどうしてもうまくいかなかった。
形式が違うようですが、その変換の仕方が理解できなかった。要改良。
メモアプリ開発メモ③　ひとまずMySQLから採ったデータをブラウザで表示

第一回https://qiita.com/pothos/items/7801daffc504ad85f475
前回→https://qiita.com/pothos/items/da0fa78d222c7fdb1383

# 進捗
本日はMySQLからとったデータをブラウザに表示できるようにコードを加筆しました。jsファイルよりejsファイルに、テーブル(questions)内から全行を取得した結果を送り、受け取ったデータの中からidと見出し文(smallQ)を呼び出して表示しています。
```home.ejs
 <ul class="table-body">
                    <% questions.forEach((quests) => { %>
                      <li>
                        <div class="item-data">
                        <span class="id-column"><%= quests.id %></span>.
                          <span class="smallQ-column"><%= quests.smallQ %></span>                       
                        </div>
                      </li>
                    <% }) %>
                  </ul>
```


```app.js
app.get('/sql', (req, res) => {
  connection.query(
    'SELECT * FROM questions',
    (error, results) => {
      console.log(results);
      res.render('forestion.ejs',{questions: results});
    }
  );
});
```
結果は以下の通り。まずはホーム画面でデータベースにしまってあった値をリスト形式で表示できるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822374/fcbd78b4-96c5-d424-fe05-411bad199a6d.png)
さて、しかしCSS内で背景に指定していた画像が表示されなくなってしまいました。

この原因は…?もしや今一つルート処理についての勉強が足りていないかな・・・？
次回はこのミスがなぜ生じたか調べつつ考えつつブラウザに想定通りのレンダリングが行われるよう調整していきたいと思います。

では今回はこの辺りで。
【ブルスク】SSDクローンしたら0xc0000225が出たので直した

# はじめに
タイトルの通り、SSDをクローンしたら0xc0000225のブルスクが出ました。
色々調べてガチャガチャコマンド打ったら直せたので、備忘録を書いておこうと思います。
# 状況
OSはWindows10 Pro。

Cドラ（OS入り）のSSDをM.2に換装したかったので、Acronis True Imageというソフトでディスクイメージをクローンしました。
その後クローン先のM.2をCドラに指定、クローン元SSDはデータドライブとして再利用するためフォーマットしてGドラあたりに設定。

ここで再起動したら0xc0000225が出ました。OSぶっ壊れたと思って泣いちゃった。
# 原因
**ブート構成データ（BCDファイル）が迷子になっていたため。**

ブート構成データとはOSを起動する方法が載ってる手順書みたいなものです。
起動時にコイツを読み込めないとOSちゃんは自分の立ち上げ方が分からず、動作を停止してしまいます。（かわいいね）

多分クローンソフトがちゃんと仕事してなくて、まだクローン元のSSDにブート構成データがあるとOSが誤認していたんですね。

でもクローン元SSDは空っぽ　→　BCDドコー( ﾟдﾟ) 　 →　あぼーん　って感じ。
# 対処方法
## 簡単に言うと
**BCDファイルを作り直す。**

そもそもの話、クローンしてるのでブート領域自体が消滅しているわけではありません。
OSが場所を認識できてないだけです。

BCDファイルを新しく作り直すことでOSが場所を覚えてくれるので、起動できるようになります。

## 詳細な手順
私がトラブルシューティングする上で参考にした記事があるので、リンクを貼っておきます。

https://freesoft.tvbok.com/tips/efi_installation/uefi_bootrec.html

と言うかぶっちゃけここからは↑のサイトの内容をほぼ丸パクリしています。（殴
この記事より5億倍丁寧に書かれていますので、上記サイトを見るだけで大丈夫です。先駆者に感謝。

手順としては以下の4ステップです。

1. インストールメディアからWindowsを立ち上げ、コマンドプロンプトに入る
1. diskpartからブート領域を探しだし、ドライブレターを付ける
1. BCDファイルを作り直す
1. 回復パーティションを再認識させる

### 1. インストールメディアからWindowsを立ち上げ、コマンドプロンプトに入る
このエラーが出ている時点でそもそもOSが完全に沈黙しているはずですが、
以降の手順でコマンドプロンプトを触る必要があるため、インストールメディアからWindowsを立ち上げます。

インストールメディアは別のPCからUSBに焼くか、なければお友達にお願いして作ってもらってください。（適当）

https://www.pasoble.jp/windows/10/kidoudekinai-cmd.html

### 2. diskpartからブート領域を探しだし、ドライブレターを付ける
早速ブート領域をいじりたいですが、デフォルトでは隠しドライブになっているため触れません。
ブート領域のボリュームにドライブレターを付けてcdできるようにします。

```
> diskpart
diskpart> list volume
```
FsがFAT32、Infoがシステムになっているボリュームがブート領域です。（たいてい100MBらしい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551480/a3ef2327-b201-9722-8fc8-8130b203e3ae.png)
こいつを
```
diskpart> select volume x (画像では6)
diskpart> assign letter=b: (ドライブレター例)
diskpart> exit
```
してやれば、ブート領域にドライブレターが付きます。

### 3. BCDファイルを作り直す
ここが本命です。
前項まででブート領域ちゃんを好きにできる状態になっていますので、（BCDファイルの場所を）わからせます。
```
> b:
b:> cd /d b:\EFI\Microsoft\Boot
b:> ren BCD BCD.bak
b:> bootrec /Rebuildbcd
b:> bootrec /fixboot
b:> bcdboot c:\Windows /l ja-JP /s b: /f ALL
b:> exit
```
2行目まででBCDファイルのあるディレクトリまで移動して、3行目でもともと存在するBCDファイルをリネーム、
以降のコマンドでBCDファイルを新しく作り直しています。

4行目で「インストールをブート一覧に追加しますか？YES(Y)/NO(N)/ALL/(A)」と聞かれますので、Yを入力してください。

6行目で「ブートファイルは正常に作成されました。」と表示されたら成功です。
一度シャットダウンしてインストールメディアを取り外し、電源ボタンポチーしてください。

### 4. 回復パーティションを再認識させる
成功していれば、ブルスクが出ずにWindowsが上がってくるはずです。

ただ、BCDファイルを作り直すと今度は回復パーティションが迷子になってしまうらしいです。（かわいいね）
このままだとシステムの復元とかができなくなって困るので、見つけてあげます。

コマンドプロンプトを管理者権限で開き、
```
reagentc /enable
```
を実行するだけ。

このあと
```
reagentc /info
```
で、「Windows REの状態」がEnabledになっていればおｋ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551480/7fab8e7b-86fb-4be5-bd26-ef85bc98d12a.png)

# おわりに
ディスクのクローンソフトってマジで罠ですよね。
ユーザーフレンドリーな雰囲気出しておきながら割と致命的なエラーを残していくという。

EaseUSとかでHDDからSSDにアップグレードだぜ！っつって泣きを見た人も結構多いんじゃないでしょうか？
（おま環なのかもしれないけど……）

安定した最強クローンソフトの情報お待ちしています。
【Swift】文字列を比較する

# はじめに
文字列を比較する方法を学んだので記録しておきます。

# 使い方
```swift
import Foundation
let A = "123"

let B = "456"

let compare = A.compare(B, options: .numeric)

switch compare {
case .orderedAscending:
    print("Aの方が小さいです")
case .orderedDescending:
    print("Aの方が大きいです")
case .orderedSame:
    print("AとBは同じです")
}
```

# 解説
数字と数字の比較ならわかりやすいですね
しかし、`compare`は数字以外も比較できます。

なぜ数字以外が比較できるのでしょうか
どのようなルールで比較してるのでしょうか

これは文字列の順序が上か下か同じかを判定しているものであると思います。

よって、数字とひらがなであっても比較できます。

```
数字 < アルファベット(大) < アルファベット(小) < ひらがな < カタカナ
```
```
数字
1 < ... < 9

アルファベット(大)
A < ... < Z

アルファベット(小)
a < ... < z

ひらがな
あ < ... < ん

カタカナ
ア < ... < ン
```

# おわり
不思議だったので調べてみました
もし間違ってたらコメントください
JavaScript 文字列の末尾を除去する

文字列の末尾1文字のみを削除する方法を学んだので記載する．（初心者が書いてます．）

### 方針
[length](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/length)プロパティで文字列の長さを取得し，[slice()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/slice)メソッドで文字列の先頭から(文字数 - 1)文字目までを抜き取る．

追記：@shiracamusさんよりご指摘を受けました．lengthプロパティを使う必要はなく，slice()メソッドだけで末尾1文字のみの除去ができました．サンプルコードに追記します．

#### サンプルコード
```javascript
let hello1 = "おはよう" //文字列を定義
console.log(hello1)

let hello1Length = hello1.length  //定義した文字列の長さを取得．4文字．
let hello2 = hello1.slice(0, hello1Length -1) //hello1の1~3文字目の文字列を抜き取り．
console.log(hello2)

//追記：
let hello3 = hello1.slice(0, -1) //hello1の1~3文字目の文字列を抜き取り．
console.log(hello3)
```
#### 実行結果
```javascript
> "おはよう"　　//hello1の値
> "おはよ"　　//hello2の値

//追記：
> "おはよ"　　//hello3の値
```
### 少し応用：文字列内の指定位置に文字列を挿入
上記の考え方で文字列内の指定位置に文字列を挿入することも可能．

追記：こちらについても，slice()メソッドだけで対応できそうです．

#### 考え方
1. 文字列Aの指定位置までの文字列Bを取得．
1. 文字列Aの指定位置以降の文字列Cを取得．
1. 文字列DをB, Cの間に挿入("文字列B" + "文字列D" + "文字列C")．
詳細は以下参照．
[JavaScriptで指定位置の文字列を置換する方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/28415)

### 参考
MDN Web Docs
>[length](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/length)プロパティ
>[slice()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/slice)メソッド
Pulsar Flexを使ってみた

## はじめに

こんにちは。

本稿では、[Pulsar](https://pulsar.apache.org/)のサードパーティのNode.jsクライアントライブラリである、[Pulsar Flex](https://github.com/ayeo-flex-org/pulsar-flex)(以下、pulsar-flex)を使って、簡単なメッセージの送受信をしていきます。

内部でC++クライアントライブラリを使用する[公式のNode.jsクライアントライブラリ](https://github.com/apache/pulsar-client-node)とは異なり、pulsar-flexはC++クライアントライブラリに依存しないライブラリとなっています。

今回は、MacOS 1台の上に以下の環境を構築して試していきます。

* サーバ
  * OpenJDK 1.8
  * Pulsar(standaloneモード) v2.10.1

* クライアント
  * Node.js v16.15.1
  * pulsar-flex 1.1.1

## サーバの準備
ここでは、メッセージの送受信を行うためのサーバを準備していきます。

まず、Pulsarのstandaloneモードを動かすために、Javaが必要になります。
Javaのインストール後、Pulsarのバイナリファイルが入ったアーカイブファイルをダウンロードします。

```
$ wget https://archive.apache.org/dist/pulsar/pulsar-2.10.1/apache-pulsar-2.10.1-bin.tar.gz
```

ダウンロード完了後、アーカイブファイルを展開します。

```
$ tar xzf apache-pulsar-2.10.1-bin.tar.gz
$ cd apache-pulsar-2.10.1
$ ls
LICENSE    NOTICE     README     bin/       conf/      examples/  instances/ lib/       licenses/
```

これでサーバの準備は完了です。

## pulsar-flexのインストール
下記のコマンドを実行し、pulsar-flexをインストールします。

```
$ npm i pulsar-flex
```

## メッセージの送受信

サーバとクライアントの準備ができたので、実際にメッセージの送受信をしていきます。

### サーバの起動

まず、Pulsar standaloneモードでサーバを起動させます。

```
# サーバ側のターミナル
$ ./bin/pulsar standalone
```

### Consumerの起動

次に、メッセージを受け取る側(以下、Consumer)を起動させ、サーバに接続させ、メッセージを受け取る状態にさせます。
Consumerに使用するコードは以下になります。

```javascript:consumer.js
const { Consumer } = require('pulsar-flex')

const consumer = new Consumer({
  topic: "persistent://public/default/my-topic",
  subscription: "my-subscription",
  discoveryServers: ['localhost:6650'],
  subType: Consumer.SUB_TYPES.EXCLUSIVE,
})

const run = async () => {
  await consumer.subscribe()
  await consumer.run({
    onMessage: async ({ ack, message, properties, redeliveryCount }) => {
      await ack();
      console.log(message.toString())
    }, autoAck: false,
  })
}

run().catch(console.error)
```

下記のコマンドを実行するとConsumerが起動されます。

```
# Consumer側のターミナル
$ node consumer.js
```

### Producerの起動

次に、メッセージを送る側(以下、Producer)を起動させ、サーバに接続させ、メッセージを送ります。 
Producerに使用するコードは以下になります。

```javascript:producer.js
const { Producer } = require('pulsar-flex')

const producer = new Producer({
  topic: "persistent://public/default/my-topic",
  subscription: "my-subscription",
  discoveryServers: ['localhost:6650'],
})

const run = async () => {
  await producer.create()
  await producer.sendMessage({
    payload: "Hello World!"
  })
}

run().catch(console.error)
```

下記のコマンドを実行すると、Producerが起動されます。

```
# Producer側のターミナル
$ node producer.js
```

上記が実行されると、Producerから送信されたメッセージがConsumerに流れ、Consumer側のターミナルで以下のように表示されます。

```
# Consumer側のターミナル
{"level":"INFO","timestamp":"2022-09-07T10:09:10.419Z","logger":"pulsar-flex","message":"Changing consumer state -> consumer: undefined(0) STATE: INACTIVE"}
{"level":"INFO","timestamp":"2022-09-07T10:09:10.420Z","logger":"pulsar-flex","message":"Changing consumer state -> consumer: undefined(0) STATE: ACTIVE"}
Hello World!
```

## おわりに
本稿では、pulsar-flexを使ったメッセージの送受信を行いました。
今回、シンプルなProducer、Consumerを作成して試しましたが、他にも様々な機能が実装されています。 
下記のドキュメントが参考になるかと思います。
- [Pulsar Flex](https://github.com/ayeo-flex-org/pulsar-flex)
- [Apache Pulsar](https://pulsar.apache.org/)
eslint-plugin-react をアップデートしたら、 emotion 関係のエラーが多発した件

Next.js, emotion で開発しているプロダクトの、 eslint-plugin-react をアップデートしたら、めっちゃ ESLint に怒られましたので、どのように対処したのかを書いていきます。

最近アップデートしようとして苦しんでいる方や、
今後、 emotion, eslint-plugin-react を組み合わせて使う方の参考になればと思います。

ではいきましょう！

## 前提

### アップデート前のバージョン

```
react               18.2.0
next                12.2.4
@emotion/react      11.10.0
eslint              8.21.0
eslint-plugin-react 7.30.1
```

### アップデート後のバージョン

```
react               18.2.0
next                12.2.5
@emotion/react      11.10.0
eslint              8.23.0
eslint-plugin-react 7.31.6
```

## 現象

アップデート後に、いつものように ESLint を実行すると、次のようなエラーが至る場所で発生しました。

```
Error: Unknown property 'css' found  react/no-unknown-property
```

## 原因

直接的な原因は、 emotion を使う際に、下記のように、 css という prop を使うからです。

```tsx
const SomeComponent = () => {
  return (
    <div css={{ padding: "10px" }}>
      This is SomeComponent.
    </div>
  )
}
```

本来、 div には css という prop はありませんので、このようなエラーが出るわけです。

### なぜアップデート後にエラーが

とはいえ、なぜアップデート後に急にエラーが出るようになったのか、気になりますよね。
そこで、 [eslint-plugin-react の CHANGELOG](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md) を見ると、ここ最近、 `no-unknown-property` にかんするアップデートが活発に行われていることがわかります。
なので、 `no-unknown-property` ルールがより厳密に判定されるようになったのではないかと推測できます。
（まだちゃんと内容見れていないので推測になります。詳しい方、教えてください :bow: ）

## 対処

というわけで、 `no-unknown-property` ルールにて、 css prop を無視するように設定すれば良さそうです。
そこで、 ESLint 設定ファイルを下記の通り修正します。

```diff_jsondoc:.eslintrc.json
  {
    // 略
    "rules": {
      "react/prop-types": "off",
+     "react/no-unknown-property": ["error", { "ignore": ["css"] }]
    }
  }
```

その後、 ESLint 実行し、エラーが出なくなったことを確認すれば完了です！

```
✔ No ESLint warnings or errors
```
なんでおまえASCIIやねん

# 事の顛末
https://twitter.com/ahoxa1rx/status/1567448077841362944

# 解決法について
## 結論
 `toInt` -> `asDigit`
 `Char`ではなく`Char#asDigit`として変換すればヨシ！
## 原因の予測

まず該当のコードがこれ
```scala
import scala.io.StdIn.readLine

object Main extends App {
  var marble = readLine.toList map(_.toInt)
  //println(marble)
  //
  //input: 100
  //output: List(49, 48, 48) <- は？
  print(marble.foldLeft(0) (_ + _) % 48)
}
```
文字から整数`Int`に変換すると[ASCII](https://www.k-cube.co.jp/wakaba/server/ascii_code.html)で解釈するらしく、結局[今回](https://atcoder.jp/contests/abs/tasks/abc081_a)の場合は`1`が何回でるかで計測したかったので結合した結果を48の剰余計算で結果をゴリ押ししました。

## 解決策の予測

例えば普通に整数に変換する場合はこうなんですが、
```scala
var a = readLine split " " map(_.toInt) // 空白文字が分割文字として設定されている
```

今回の場合入力で渡される形式が詰め詰めだったので[苦肉の策](https://stackoverflow.com/questions/42320394/scala-string-toint-int-does-not-take-parameters)で`toList`(文字列を1文字づつ分解してListに格納するやつ)にして
```scala
var marble = readLine.toList map(_.toInt)
```

これで解決を図った結果が`Char`として、つまり中身は整数として格納されているのを~~表示でごまかしていた~~整数に変換したので意図しない値になってしまったわけです。

## 解決法 --verbose

[つよつよぷろぐやま集団](https://approvers.dev/)に色々聞いた結果
[公式ライブラリ](https://www.scala-lang.org/api/2.12.1/scala/Char.html#asDigit:Int)によればASCIIではなく表示の数字と同じ数値として解釈するらしくこれで当初意図していた変換が達成できるということです
改良後のコードがこちら
```scala
var marble = readLine.toList map(_.asDigit)
```

改良後のコードも[提出したらAC](https://atcoder.jp/contests/abs/submissions/34672260)したのでヨシ！


## 補遺

コレクションはまだ不慣れなので他にもこの問題自体を解決するのに`1`が何個含まれるかを計上すればいいためこのような解法もあるらしい
```scala
print(readLine().count( _ == '1')
```

[結果](https://atcoder.jp/contests/abs/submissions/34672532)はAC！ シンプルなコードでよみやすい(個人的感想)
GoogleChromeの標準フォントを「カスタム」に戻そうと思ったけど戻らない！

# はじめに
結論から、、、
「Googleアカウント別に設定があるので、該当アカウントの設定を直しましょう！」です。

## 経緯

制作業務を行なっている際、
「英語や数字のフォントが太字になってるからfont-family見直してください」
という依頼がありました。

自分の端末で表示確認してみたところ、特に崩れもなく、OSやブラウザのバージョンを確認してみても自分と同じで変わったところはありませんでした。
他の社員にも表示確認してもらいましたが、特に崩れはありませんでした。
これは個人の設定の範囲で何か起きているので確認依頼したところ、フォントカスタマイズが影響していたので、初期設定の「カスタム」に修正する方法を伝えました。

が、「カスタム」に直らず。

改めて、設定の書かれている「Preferences」というファイルを探したところ、
「~/Library/Application Support/Google/Chrome/Default/」の配下に「Profile」というフォルダがあり、
その中にも「Preferences」がありました。

「Default/Preferences」の記述を直しても直らない or standerdの記述がないときは、「Profile（アカウントが複数ある場合通し番号あり）」の中のファイルを確かめてみてください。

直ります。（ •̀ω•́ ）ｷﾘｯ

## 修正方法
①
Google Chromeを閉じます。

②
Finderを開き「Command＋Shift＋G」で出る検索窓に「~/Library/Application Support/Google/Chrome/Default/」を入力

③
「Preferences」というファイルをテキストエディタで開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646665/7875815e-efe9-15ae-8abf-e4247b63aeff.png)

:::note warn
注意
アカウント別に設定があるので、複数アカウントあって直したいアカウントがある場合は「Profile」を探してその中の「Preferences」の記述を直してください。（下記参照）。
:::


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646665/97fb36aa-f3d2-2a91-29fd-668602bb8a08.png)

※「Profile」が複数あるときは「Accounts」の中にアカウント画像があるので、そこをみて確認してみるといいかもです。

④
下記のような設定コードがあるので、文字列検索（Command＋F）などで探しましょう。(fontsで探すとすぐ見つかるかと)

```text editor
"webkit":{"webprefs":{"fonts":{"fixed":{"Zyyy":"Osaka"},"sansserif":{"Zyyy":"Hiragino Sans"},"standard":{"Zyyy":"設定しているフォント"}}}}
```

修正したいフォント種類を{"Zyyy":""}に変更します。

おしまい
(｀・ω・´)つﾖｼ!


## 終わりに
「Preferences」の中にstandardの設定がなくても、
「Default」直下のファイルの記述を修正してもフォントが直らないくても、
諦めずに仮定の想像をしましょう。「他にも設定している箇所あるかも、、、」とか

問題発見能力、解決能力、が鍛えられた回でした！
GitHub Actionsの`outputs.<output_id>`に不正な記号が使われている場合の対処法

## 要約

`[]`を使って以下のように書く。
```
${{ steps.hoge.outputs['hoge/fuga'] }}
```

※記事末尾の[所感](#所感)も見てね。

## 背景

GitHub Docsにはactionsの出力(`outputs`)について以下のように書かれている。

> `<output_id>`は、`outputs`オブジェクト内でユニークな識別子でなければなりません。 `<output_id>`は、文字あるいは`_`で始める必要があり、英数字、`-`、`_`しか使用できません。

https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_id

しかしMarketplaceにあるactionsの中には、`output_id`に`/`などの許可されていない記号を含む場合がある。

↓以下はrelease-please-actionの例。

https://github.com/google-github-actions/release-please-action/issues/297#issuecomment-907697951

release-please-actionでは`output_id`にディレクトリ名を含む場合があり、以下のようなidが生成される場合がある。
```
"packages/one--release_created"
```
これを利用しようとして以下のように指定するとエラーになってしまう。
```
${{ steps.release.outputs.packages/one--release_created }}
```

```
Invalid workflow file: .github/workflows/ci.yml#L27
The workflow is not valid. .github/workflows/ci.yml (Line: 27, Col: 9): Unexpected symbol: 'packages/one--release_created'. Located at position 23 within expression: needs.release.outputs.packages/one--release_created
```

## ワークアラウンド

`[]`を使って次のように記述すると正しく解釈される。

```
${{ steps.release.outputs['packages/one--release_created'] }}
```

## 所感

ドキュメントで「英数字、`-`、`_`しか使用できません」と書いてある以上、いつ動かなくなるかも分からないので、該当のactionにissueを立てるなりして対応してもらうのが良いと思います。
配列のcloneメソッドについて

Java silverの学習において、
何度か配列のcloneメソッドで間違えたので、備忘録を残す。

## 配列のcloneメソッド
名の通り、配列のコピーを行うもので、同じ値を持った配列インスタンスが複製される。

```java:
int[] arrayA = {1,2,3};
int[] arrayB = arrayA.clone();
System.out.print(arrayA == arrayB); //false
```

上記だと、arrayAとarrayBには同じ{1,2,3}の値が入っていることになるが、
配列のインスタンスを複製しているので同一ではない。

### 注意したい点
配列をcloneすると同じ値を持った配列インスタンスが複製されますが、
参照先は同じなので、以下はtrueになる。

```java:
int[][] arrayA = {{1,2,3},{4,5,6}};
int[][] arrayB = arrayA.clone();
System.out.print(arrayA[0] == arrayB[0]); //true
```
<br>

また、clone後にarrayAの値を変更しても、arrayBの値に影響はない。

```java:
int[] arrayA = {1,2,3};
int[] arrayB = arrayA.clone();
arrayA[0] = 5;
//arrayB= {1,2,3}
```
Why are Exception(s) excepted?

Q:
　何故，例外はmap&lt;EventListener&gt;を用いないのか．
　例外機構が局所的なEventListeningであることは論を俟たない．

A:
　例外機構は「後続の処理を行わずにlistenerをkickさせる」．

```

/**
 * When toss generate an Exception then throw it, smash won't be kicked.
 */
const doItStandard = () => {
  try {
    toss();
    smash();
  } catch (e) {
    console.log(e);
  }
}

/**
 * When toss generate CustomEvent: {type: 'exception arose'} then dispatch it to hoge, smash will be kicked.
 * [toss, smash] could generate CustomEvent: {type: 'exception arose'}.
 * [toss, smash] could dispatch CustomEvent: {type: 'exception arose'} to hoge
 */
const doItExtra = () => {
  hoge.addEventListner('exception arose', (e) => { console.log(e);  });
  toss();
  smash();
}
```
Android  View Bindingを組み込む

# はじめに
学習記録
View Bindingを使用してビューを直接参照する
# View Bindingを導入
build.gradle(Module: ~)のandroid {・・・}内に以下を追加
```java:build.gradle
    viewBinding {
        enabled = true
    }
```
# レイアウトとActivity
```java:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/main_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/main_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintTop_toBottomOf="@+id/main_text"/>

</androidx.constraintlayout.widget.ConstraintLayout>
```
```java:MainActivity
package com.example.sampleapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.sampleapp.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val message = binding.mainText
        message.text = "This is sample."

        val button = binding.mainButton
        button.setOnClickListener {
            message.text = "clicked"
        }
    }
}
```
初期表示↓
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1231945/5938c935-062c-cd00-c866-f3fca46f23ee.png">

ボタンクリック後の表示↓
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1231945/6791daf3-909c-f113-8286-93f6cdec0e58.png">

# ポイント
```java:MainActivity
private lateinit var binding: ActivityMainBinding
```
・バインディングクラスのインスタンスを保管するための変数
・バインディングクラスのクラス名は「レイアウトファイル名をキャメル記法にしたもの」+「Binding」(今回の場合、レイアウトファイル名が「activity_main.xml」なので、クラス名は「ActivityMainBinding」となる)

```java:MainActivity
binding = ActivityMainBinding.inflate(layoutInflater)
```
・activity_main.xmlを直接参照するインスタンスを生成

```java:MainActivity
        val message = binding.mainText
        message.text = "This is sample."

        val button = binding.mainButton
        button.setOnClickListener {
            message.text = "clicked"
        }
```
後はプロパティを参照するだけです。

# おわりに
以前Webの開発をしていたのでJavaScriptやjQueryみたいだなと思い、ここに関しては実際Androidの開発業務で初めてソースコード見た時でもすんなり入れたと思います。
もっとスラスラ記事書けるようになりたいですね。。。
ありがとうございました。

# 参考
https://developer.android.com/topic/libraries/view-binding
Codeigniter4で出力バッファをフラッシュし結果を出力する方法

# 概要
* PHP 8、 Codeigniter4
* Codeigniter4で、ob_flash() flush() を使っても処理途中での結果出力がされない
* Codeigniter4を通さないでob_flash() flush()を実行するとちゃんと処理途中で結果表示できる

# 対処方法
* `ob_end_flush();` を途中出力したい処理の前でコールする。

# 原因
app/Config/Events.php Events::on にてob_start()がコールされている。
通常の処理を実行すると、ob_start()で出力がバッファされるため、一旦　ob_end_flush()　で内部バッファの内容を出力してしまう必要がある。

出力バッファはスタッカブルなので、ob_end_flush()をせずに
```
ob_start();
ob_end_flush();
ob_flush();
flush();
```
としてしまうと、すでにバッファされているob_start() からさらに入れ子でバッファされることになるので、そのあとflushしても、最初のob_start()によりバッファされてしまう。

# 参考
https://www.php.net/manual/ja/function.ob-start.php
「terraformを利用してVPC内のlambda起動→VPC外（パブリック）に戻す」の注意点

結論：VPCを「なし」に設定する（できない場合がある） or 再作成してください
vpc_configを消してterraform applyしようとすると・・・こんなエラーが
```
 error deleting Lambda ENIs using Security Group (sg-XXXXX): error waiting for Lambda ENI (eni-XXXXX) to become available for detachment: timeout while waiting for state to become 'available' (last state: 'in-use', timeout: 45m0s)
```
手動は良くないですが色々手動でいじって以下のことがわかりました


１．ENIはセキュリティグループが利用していて削除できない
２．セキュリティグループはこんなエラーで削除できない
```
3 のネットワークインターフェイスが関連付けられています。 ネットワークインターフェイスを削除するか、異なるセキュリティグループに関連付ける
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/3aefa1ee-7929-c729-73e8-ce6ce1d24941.png)
３．VPC接続を「なし」に設定するとEFSのアクセスポイントが削除されてエラーになっている例もあるみたいです
https://dev.classmethod.jp/articles/try-delete-lambda-eni-with-lambda-eni-finder/

４．再作成すると成功する
【Quick JUnit】～JUnitテストケースを選択してください～ Ctrl + 0 でテストを実行できない

## 環境 
- eclipse
- JUnit4
- Quick JUnit 0.7.0 

## Quick JUnitのショートカットが使えなかった話
初めてJavaでテストコードを書いたとき、以下のサンプルのようにコードを書いた。
Quick JUnitというプラグインを使えば、`Ctrl+0` のショトカが使えるらしい。
テストコードにフォーカスがあたっている状態であればそのテストクラスに定義されたすべてのテストが、メソッド内にフォーカスがあたっている状態であればそのメソッド単体が実行される。

```Java:SomeTest.java
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class SomeTest {
    @Test
    void publicがないとショトカ実行できない() {
        assertEquals(1,1);
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611084/c7ba8bd7-7cdb-4b29-68b4-346eccc61ae1.png)

**JUnitテストケースを選択してください。**
というエラーが発生し、実行されず。
ショトカ自体は呼ばれている模様。

## 解決策
publicをつける。
```Java:SomeTest.java
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class SomeTest {
    @Test
    public void publicをつけるとショトカ実行できる() {
        assertEquals(1,1);
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611084/c61a8b43-9e58-2fba-8f73-89a41ea9576f.png)
クラス、メソッドにpublic修飾子をつけるとQuic JUnitのショートカットで実行することができました。

## 終わりに
この程度で記事を書いていいのか悩みポイントでしたが、調べても意外とヒットしなかったので書いてみました。
同じ事象に陥った方の助けになれば幸いです。
121.ブラウザとJavascriptについて,122.非同期処理

# 覚えておくべきごく
#### スレッド
連続して実行される1本の処理のこと
今回のスレッドは
＊Main Thread:Javascriptの実行とレンダリングを行う
＊Service Worker:
＊WebWorker
#### レンダリング
データ（ここでいうとソースコード）をもとに何らかを表示させるということなので
rendering（レンダリング）」意味は表現に近い。
今回の意味合いは
javascriptのソースコードを用いてブラウザに表示させるという意味で使われる
#### FPS 
FPSとは1秒あたり画面の更新頻度のこと
例えば
60fpsだと
1秒間で60回画面更新になります
ちなみに
＊24fps 遅いけど、重い処理はこのくらいかな
＊60fps なめらか
ちなみにMaxは120くらいらしい
＜参考＞
https://qiita.com/umi_kappa/items/d9656f6083fbee6add70

## 同期処理の問題
同期処理ではメインスレッドでコードが順番に実行される
同期処理では１つの処理が完了するまで次の処理には進まない
つまり、前に重い処理がある場合は次の処理に進むまで何もできません。

## 同期処理と非同期処理の比較
#### ①5秒間かかる処理です
#### ②ボタンをクリックします
```js
// ①5秒間かかる処理です
function sleep(ms) {
  const startTime = new Date();
  while (new Date() - startTime < ms);
  console.log('sleep done');
}
// ②ボタンをクリックします
const btn = document.querySelector('button');
btn.addEventListener('click', function(){
  console.log('button clicked');
});

sleep(5000);
```
#### 5秒間ぐるぐるだよ
![スクリーンショット 2022-09-07 17.25.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/8777d61d-0c8f-7b2f-6159-96c693d5db1d.png)

#### やっとボタン押せた、、、
![スクリーンショット 2022-09-07 17.26.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/5d02b0d7-e05c-b08d-ad39-922a6f814e65.png)

# 待機時間解決方法
＊WEBAPIを指定する
1.setTimeout<実はsetTimeoutもAPI>
2.Promiseなど　//次回
## setTimeoutとは？
ー秒まって実行する関数
グローバルの setTimeout() メソッドは、時間切れになると関数または指定されたコードの断片を実行するタイマーを設定します。
### 使い方
setTimeout(コールバック関数, -秒後に実行)
```js
// 例
setTimeout(function() {
	sleep(3000)
}, 2000)
```
こうすると、
1.まっている2秒間だけ、次の処理（ここでいうとボタンを押すこと）ができる
2.Timeoutが終わり3秒かかるsleep(3000)が始まり、再び次の処理ができなくなる
3.sleep(3000)が終わったのでボタンが押せるようになる
ということ
# つまり非同期処理とは
一時的にメインスレッドから切り離して処理を行うこと

APIの定義をもう一度見直そう
rails generateコマンドを取り消す方法

はじめに
--
railsを使うならほぼ確実に使うであろう"rails g(generate)"コマンドですが、model名を間違えて記述してコマンドを叩いてしまったら修正するのに時間がかかるな。。と思って毎回このコマンドを叩く際に毎回少し緊張していました。

今回"rails g"を取り消すコマンドの存在を知ったので備忘録として残そうと思います。

rails destroy
--
"rails g"コマンドを取り消すためには、"rails destroy"コマンドを使用します。

~~~
#rails g modelコマンドを取り消したいの場合
bundle exec rails destroy model モデル名

#rails g controllerコマンドを取り消したいの場合
bundle exec rails destroy controller controller名
~~~

"rails g"の箇所を"rails destroy"に変更してコマンドを叩くだけで簡単に削除をすることができます。
失敗しても戻し方がわかるとストレスが激減しますね。

ちなみに実際に削除した際の挙動は下記になります。
quizを複数形にし忘れてファイルを作成してしまい、削除したい時に叩いたコマンドです。
~~~
~# bundle exec rails generate controller quiz
Running via Spring preloader in process 349
      create  app/controllers/quiz_controller.rb
      invoke  rspec
      create    spec/requests/quiz_spec.rb

~# bundle exec rails destroy controller quiz
Running via Spring preloader in process 360
      remove  app/controllers/quiz_controller.rb
      invoke  rspec
      remove    spec/requests/quiz_spec.rb
~~~

参考
--
https://railsguides.jp/command_line.html#bin-rails-destroy
Go言語ginを用いたモジュラモノリス構造について

Go言語(gin)を用いたサーバを構築する際に、モジュラモノリス構造を実現するためのフォルダ構成等を試行錯誤した結果を示す。
モジュラモノリス構造は時が来た時にマイクロサービスへ簡単に切り出せるし、素晴らしいアーキテクチャですね(^_^)

[こちら](https://github.com/tnakamura512/go-modular-monolith-base)にサンプルコードがあるのでそれをベースに..

# アーキテクチャ
サーバとしてはモバイルアプリから呼ばれるAPIサーバである。(Viewは存在しない)
今担当してるプロダクトに準拠してユーザ管理、メッセージ送信、歩数ランキング機能を保有しているものとする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200860/bb7b8079-cffc-f518-b29c-0b532dba9918.png)

 - User Model
     - ユーザ登録、Tokenによる認証等、よくあるやつ
 - Message Model
     - ユーザ間のメッセージ送信機能
 - StepRank Model
     - ユーザ間で歩数を競う機能を提供

 - DB
     - DBは単一のDBを採用して、スキーマを分けることによりそれぞれのモジュールが専用のDBを保有しているようにしている
     - MySQLベースでの考え方だが、スキーマじゃなくてそれぞれ別のDBを採用することも当然可能である

 - Module API
     - Model同士を橋渡しするAPI。ユーザ認証等。どうやって図に書けばいいかわからなかった…
     - 将来それぞれのモジュールをマイクロサービスへ分離した際にはAPI(HTTP等)として実現するべき境界線となる

# ファイル構成

```shell
┣main.go
┣database
┗modules
 ┣module_api.go
 ┣user
 ┃┣ucon
 ┃┃┗user_controller.go
 ┃┣umodel
 ┃┃┣repository_interface.go
 ┃┃┗user_model.go
 ┃┗urepo
 ┃ ┗user_repository.go
 ┣message
 ┃┣mcon
 ┃┃┗message_controller.go
 ┃┣mmodel
 ┃┃┣repository_interface.go
 ┃┃┗message_model.go
 ┃┗mrepo
 ┃ ┗message_repository.go
 ┗steprank
  ┣srcon
  ┃┗steprank_controller.go
  ┣srmodel
  ┣repository_interface.go
  ┃┗steprank_model.go
  ┗srrepo
   ┗steprank_repository.go
```

- main.go
    - routeの設定、DB接続、modulesへの依存の注入等を担う
- modules
    - 今回の要各モジュールが独立して存在している
- module_api.go
    - モジュール間インターフェース定義箇所
- repository_interface.go
    - 各ModelとRepositoryの依存を反転させ、テストコードの記載等を簡単にする
    - Controllerとの反転まではしてない

main.go等一部を除いて将来各サービスがある程度大きくなったりした場合には最低限の労力で切り出してマイクロサービス化できる構造になっている。
TypeScriptでPromiseの決定後の型を抽出する方法

はいさい！ちゅらデータぬオースティンやいびーん！

また、TypeScriptの便利な`UtilityType`紹介をしたいと思います！

# 概要

`Awaited`のUtilityTypeを使って、Promiseの決定後の型を推測する方法を紹介します。

## 背景

先ほど投稿した`ReturnType`についての記事を書きましたが、非同期処理のPromiseだったら、どうやってそのPromiseが履行された時の値を推測できるのかと気になった方がいらっしゃったかと思います。

https://qiita.com/tronicboy/items/a5578741e74d299a3f42

実は、`ReturnType`と同じように、TypeScriptにはもう一つ便利なUtilityType、`Awaited`があります。

このUtilityTypeは比較的に新しく、TypeScript 4.5から使えるようになっています。

その使い方を説明してまいりましょう。

# `Awaited`の使い方

以下のようなコードを例に書いてみました。APIからTodoを取得して、`{ id: number; title: string ... }`のように、数値もしくは文字列が入っているオブジェクトが返って来るはずです。

```typescript
const getTodo = async (id: number)=> {
    const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");

    if (!response.ok) throw Error(`Reponse failed: ${response.status}`);

    const data = await response.json() as Record<string, string | number>;

    return data;
}
```

URLは以下の無料Dummy APIのものです。遊びにとても便利なので、お勧めします。

https://jsonplaceholder.typicode.com/

前回の記事と同じように、この`getTodo`が返してくれる値を推測してみましょう。

```typescript
type Todo = ReturnType<typeof getTodo>;
```

TypeScriptインタープリターにこの型定義の結果を聞いてみると、以下のような結果になります。

```typescript
type Todo = Promise<Record<string, string | number>>
```

関数だから、ReturnTypeを使うと`Record<string, string | number>`が返って来るはずなのですが、今回は違うのですね。

なぜなら、**`async`の関数は**、_糖衣構文_ であり、実際は`.then().then()`の、ばりばりの**Promiseだからなのです**。

ここで、本当の、Promiseが履行した結果の戻り値がほしいので、以下のような型定義をします。

```typescript
type Todo = Awaited<ReturnType<typeof getTodo>>;
```

さぁ、TypeScriptのインタープリターの結果は？

```typescript
type Todo = {
    [x: string]: string | number;
}
```

よろしい！

## FileReaderの例

次、Fetch API以外の例も紹介してみます。

以下のような`File`をBase 64の文字列に変換するPromiseを返す関数があります。

```typescript
const convertFileToBase64 = (file: File) => new Promise<InstanceType<typeof FileReader>['result']>((resolve, reject) => {
  const reader = new FileReader();

  reader.addEventListener("error", () => reject(reader.error), { once: true });

  reader.addEventListener("load", () => resolve(reader.result), { once: true });

  reader.readAsDataURL(file);
});
```

これの戻り値の履行後の値を抽出すると、以下のようになります。

```typescript
type ConvertedFile = Awaited<ReturnType<typeof convertFileToBase64>>; // type ConvertedFile = string | ArrayBuffer | null
```

## JSDocで書く場合

JSDocでも同じような表記ができます！

```javascript

/** @typedef {Awaited<ReturnType<typeof getTodo>>} Todo */

/**  @param {number} id */
const getTodo = async (id)=> {
  const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");

  if (!response.ok) throw Error(`Reponse failed: ${response.status}`);

  const data = /** @type {Record<string, string | number>} */ (await response.json());

  return data;
};
```

# まとめ

`Awaited`の使い方を紹介してきましたが、いかがでしたでしょうか？

`ReturnType`と一緒に使うと、どの関数でも戻り値の型を定義することができます。

JSDocsでもぜひ使ってみましょう！
【完全独学】SQL勉強法(Bigquery)

<h1>この記事でわかること</h1>
<ul>
<li>独学でSQLを学ぶためのおすすめ教材</li>
<li>SQLの勉強法</li>
</ul>

<h1>おすすめ教材</h1>
以下の2点がおすすめです。
<ul>
<li>集中演習 SQL入門 Google BigQueryではじめるビジネスデータ分析 (できるDigital Camp)</li>
<li>ビッグデータ分析・活用のためのSQLレシピ</li>
SQL入門はインプット、アウトプットのバランスが良く、独学にはとてもおすすめです。SQLレシピはアウトプットメインの教材で様々な分析手法の説明と共にコードを書いて知識を定着させる形をとっています。写経をするだけでも力が付きます。
</ul>

<h1>SQL勉強方法</h1>
<ol>
<li>SQL入門を読み、基本文法を学ぶ</li>
<li>SQL入門の演習ドリル(全230問)を解き、わからない箇所は参考書やネットを使って調べる</li>
<li>SQLレシピを写経する</li>
<li>オープンデータを使って実際に分析してみる</li>
</ol>

<h1>1.SQL入門を読み、基本文法を学ぶ</h1>
まずはSQL入門を読んで基本文法を学びましょう。ここで100%覚えるのは難しいと思うので、「こんなことができるのか」程度で大丈夫です。(演習ドリルでたくさん出てくるので)　テーブルの結合や日付や時刻を扱う関数はしっかり理解しておくのがおすすめです。

<h1>2.SQL入門の演習ドリル(全230問)を解き、わからない箇所は参考書やネットを使って調べる</h1>
この演習ドリルがとても優秀です。後半に行くにつれて徐々に難しくなっていくので、力がつきやすいと感じました。サンプルデータも付属しており、環境構築が楽なので臨みやすいと思います。最初はわからない問題も多くあると思うので、その都度調べて解いていきましょう。このドリルが終わったころにはデータを自由に扱えるだけの力がついていると思います。

<h1>3.SQLレシピを写経する</h1>
基本的な力がついていると思うので、よく使う分析手法を学び、分析の幅を広げましょう。ABC分析やRFM分析といった分析手法の説明と実装方法が書かれているので、写経をしてインプットしましょう。自力で挑戦したい方は最終的なテーブル結果だけ見て実装練習するのもおすすめです。

<h1>4.オープンデータを使って実際に分析してみる</h1>
ここまで来たら後はアウトプットを繰り返すだけです。オープンデータを使って実際に分析をしてみましょう。オープンデータは扱いやすい形で保存されているとは限らないのでデータの分析だけでなく、加工や整形も経験できます。一からデータを集めて加工、抽出、分析ができれば仕事でも問題なく使えるでしょう。

<h1>まとめ</h1>
この記事ではSQLの勉強方法を紹介しました。SQLを学んだあとはBIツールやPythonなどキャリアプランに合わせた勉強をするのがおすすめです。
Androidアプリ開発をして気づいたメリット

# はじめに
Androidアプリ開発をしていて気づいたメリットを3点を紹介。iOSアプリ開発との比較記事ではなく、個人的に思ったことを記述。

# 開発しやすい
生産性が高く開発ができる。理由としては以下の2点が挙げられる。

#### Android Studioが使いやすい
Android StudioはIntelliJ IDEAをベースとした統合開発環境。IntelliJ IDEAに関して[こちらのリンク](https://pleiades.io/help/idea/discover-intellij-idea.html)には、生産性を高めるだけでなく**楽しい体験を提供**するとのこと。確かにプログラミングが楽しい。

https://developer.android.com/studio/intro?hl=ja

https://www.jetbrains.com/idea

#### Kotlinが使いやすい
Kotlinは2011年に登場した比較的新しい言語。簡潔に書けるので生産性が高く、エラーも抑えられる。

https://kotlinlang.org/

# 多くの人に使って貰える
多くの人に使って貰える理由としては以下の2点。

#### AndroidのOSシェアがトップ
[こちらの記事](https://www.qbook.jp/column/20220720_1390.html)によると、世界のOSシェアはAndroidが44.2%、Windowsが29.0%、iOSが17.4%らしい。つまり、PCとモバイル合わせても、***Androidが世界で最も使用されているOS***であることがわかる。さらに、Windows11ではAndroidアプリが使えるらしい。

#### プラットフォームがしっかりしている
Google Playストアというプラットフォームのおかげで、多くの人にアプリを届けられている気がする。

# スキルが身につく
汎用性の高い技術が身につく。メリットとしては以下の2点。

#### 他企業でもスキルが活かせる
前職では社内独自のライブラリを使っていたが、それをマスターしたところで他の場面に活かすことはできなかった。しかしAndroidアプリ開発は色々な企業が行っているので、他の場面で活かすことができる。そのため、転職時の一つの武器になりえる。

#### 個人開発ができる
前職では大規模なシステムの一部に組み込むことが多かったので、個人での開発は不可能だった。しかしAndroidアプリ開発においては、個人で開発したアプリをGoogle Playストアにリリースできる。

# おわりに
Androidに感謝。
Raspberry Pi Zero 2 Wを使ってADS-Bを受信する

# 用意したハード
* Raspberry Pi Zero 2 W
* Nooelec NESDR SMArt v4
* アンテナ(D130)
# ラズパイのセットアップ
いつも通りRapsberry Pi Imagerを使ってSDカードにOSを書き込む。
予めWiFiの接続設定とSSHの設定を行いモニタを接続せずに進めます。
今回はRaspberry Pi OS(32-bit)を選択。Zero 2 WはCortex-A53搭載なので64bitでも大丈夫そう。
あと今回はミスってRaspberry Pi OS Liteではなく通常の必要のないデスクトップ版を入れています。（ここガバ）
下記コマンドでGUIは後からオフにしました。
```
sudo raspi-config nonint do_boot_behaviour B1
sudo reboot
```
再起動後下記コマンドでCLIブートかGUIブートを確認
```
raspi-config nonint get_boot_cli
```
CLIなら0が、GUIなら1が返ります。
# dump1090-faのビルド
Flightrader24やFlightAwareのバックで使われているデコードアプリはdump1090やそのフォークのdump1090-mutability、更にそのフォークのdump1090-faらしい。Flightrader24の自動セットアップスクリプトを使うとmutabilityの方が入ってしまうので今回は別個でdump1090-fa単体からまずは導入したいと思います。ラズパイでdump1090-faを実行しデコードしたデータは各データタイプ毎に設定した各ポートから吐くことができるので、追加でフィード先を増やしたり、他のクライアントからデータを取るにせよとりあえずdump1090-faを導入し信号の受信を確認できればまず問題がないということが確認できるため。
完全に参考元からの受け売りですがDebian用パッケージとしてビルドを行う。
```
git clone https://github.com/flightaware/dump1090 dump1090-fa
cd dump1090-fa
# 通常ビルド
dpkg-buildpackage -b --no-sign
# RTL-SDRレシーバ専用でのビルド
dpkg-buildpackage -b --no-sign --build-profiles=custom,rtlsdr
```
少し待てば(実測3分弱)ビルドが完了し親ディレクトリにdump1090-fa_○.○_armhf.debが作成されるはず。(今回は32-bitなので)
インストールを行います。
```
sudo dpkg -i dump1090-fa_7.2_armhf.deb
```
systemctlで有効化と起動を行う。
```
sudo systemctl enable dump1090-fa.service
sudo service dump1090-fa start
```
# 動作確認
Raspberry Pi Zero 2 W本体へチューナーとアンテナを接続する。
ラズパイZeroのUSBポートは端よりにあるのが電源用で中央よりが通信用ポートなので逆にするとデバイスと電源を逆に接続すると起動はできるけどデバイスを認識できなかったりするから気をつけよう！(ガバ2)
デバイスを接続しちゃんと認識できていればlsusbで下記のような結果が表示される。
```
 $ lsusb
Bus 001 Device 002: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```
RTL2832Uが見えているから問題なさそう。
ちなみにSDRチューナーを挿す前にdump1090-faを起動させようとするとデバイスが見つからずプロセスが再起動を繰り返すかもしれないので先に接続したほうがいいかもしれない。
http:\//IPアドレス/skyaware/に接続するとこんな画面が確認できるはず。
![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1533066/f7b97120-5db4-6f43-c89a-846cf2bb54d4.png)
以上で動作確認完了！FR24とかFlightAwareへのフィード方法は気が向いたら書きたいけど日本語記事いくらでもあるしまあ…
ちなみにかなり雑な設置方法をしている。
![設置場所](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1533066/7505e7a3-4d60-620e-6141-4acfa02b3bc8.jpeg)
# 参考サイト

https://gato.intaa.net/archives/21187

こちらのがとらぼさんは各種サイトとの連携やアンテナの自作、Prometheusとの連携などかなりされているのでADS-B受信でやりたいことはここ見れば全部できるので今回の記事は実質ここからコピペした内容の自分用メモみたいな感じで独自性はないです。はい。
2022年9月 AIOps 定点観測

# 概要
AIOps の動向や学習のため、Google で AIOps を検索した結果を記録している記事です。

# 2022年9月5日の検索結果 (リスティング広告)

![20220905_AIOps_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/0d95d0b2-4b5d-0436-388e-126d57d23914.png)

* IBM
* ServiceNow
* Splunk
* Dynatrace

先月消えた IBM が再び 1位に戻ってきました。 ServiceNow、Splunk、Dynatrace が続いています。

先月の結果はこちら --> [2022年8月 AIOps 定点観測](https://qiita.com/mkodera/items/eee8eb00265737075668)

# 2022年9月5日の検索結果 (広告以外)

![20220905_AIOps_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/c6a1dfd1-cf10-c80d-e03a-ca0b4bbdb2d1.png)

* Splunk
* JBSVC
* ServiceNow
* ITmedia
* テックファーム株式会社
* NTTデータ

広告以外だと、上位1～4位は先月と変わらずです。

先月の結果はこちら --> [2022年8月 AIOps 定点観測](https://qiita.com/mkodera/items/eee8eb00265737075668)
Ansible Tips: shellモジュールで使用されるshell


# ansible.builtin.shellにおいて使用されているshellを確認してみる

## 環境
- Fedora Linux 36 (Workstation Edition)
- ansible [core 2.11.6] 
- ansible.cfg
[defaults]
verbosity = 1
stdout_callback = ansible.posix.debug


## デフォルトで使用されているshellを確認する例




```yaml:tasks:
- shell: ps -elf | grep -w $$
```


```
TASK [shell] *****************************************************************************************************************************************************************
changed: [localhost] => {
    "changed": true,
    "cmd": "ps -elf | grep -w $$",
    "delta": "0:00:00.029938",
    "end": "2022-09-07 16:43:31.348422",
    "rc": 0,
    "start": "2022-09-07 16:43:31.318484"
}

STDOUT:

0 S hiroyuk+  697087  697086  0  80   0 - 55758 do_wai 16:43 pts/5    00:00:00 /bin/sh -c ps -elf | grep -w $$
4 R hiroyuk+  697088  697087  0  80   0 - 56790 -      16:43 pts/5    00:00:00 ps -elf
0 S hiroyuk+  697089  697087  0  80   0 - 55578 pipe_r 16:43 pts/5    00:00:00 grep -w 697087
```

/bin/shが使用されている。
ただし、実行環境では/bin/shは/bin/bashへのシンボリックリンク。

```
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4  1月 20  2022 /bin/sh -> bash
```


### /bin/bashを指定して実行する例


```yaml:tasks:
- shell:
    executable: "/bin/bash"
    cmd: ps -elf | grep -w $$
```

```
TASK [shell] *****************************************************************************************************************************************************************
changed: [localhost] => {
    "changed": true,
    "cmd": "ps -elf | grep -w $$",
    "delta": "0:00:00.030358",
    "end": "2022-09-07 16:43:31.605923",
    "rc": 0,
    "start": "2022-09-07 16:43:31.575565"
}

STDOUT:

0 S hiroyuk+  697106  697105  0  80   0 - 55758 do_wai 16:43 pts/5    00:00:00 /bin/bash -c ps -elf | grep -w $$
4 R hiroyuk+  697107  697106  0  80   0 - 56790 -      16:43 pts/5    00:00:00 ps -elf
0 S hiroyuk+  697108  697106  0  80   0 - 55578 pipe_r 16:43 pts/5    00:00:00 grep -w 697106
```

executableで指定した"/bin/bash"が利用されている。

## 参考
```
$ ansible-doc shell
> ANSIBLE.BUILTIN.SHELL    (/home/hiroyukionodera/.local/lib/python3.10/site-packages/ansible/modules/shell.py)

        The `shell' module takes the command name followed by a list of space-delimited arguments. Either a free form command or `cmd' parameter is
        required, see the examples. It is almost exactly like the [ansible.builtin.command] module but runs the command through a shell (`/bin/sh') on
        the remote node. For Windows targets, use the [ansible.windows.win_shell] module instead.

  * note: This module has a corresponding action plugin.

OPTIONS (= is mandatory):
...
- cmd
        The command to run followed by optional arguments.
        [Default: (null)]
        type: str
...
- executable
        Change the shell used to execute the command.
        This expects an absolute path to the executable.
        [Default: (null)]
        type: path
        version_added: 0.9
        version_added_collection: ansible.builtin
...
```