OmniAICreator/Qiita-1.07M huggingface dataset:
Androidの「CDD」と「CTS」を理解する

前回の記事では、「Android互換のOSを雑多に理解する」という記事を投稿させていただきました。
その記事の中で気になった「CTS」について掘り下げていきたいと思います。

(まだ見ていない方は良ければ下記URLより参照ください)
前回の記事>https://qiita.com/ydclab_0008/items/aa8687e4b74719627e38

という事で早速ですが
Androidが広く普及してきました。

今やスマートフォンだけでなく、
様々な製品に搭載されていますが、
その中にはAndroidの互換性の承認を受けている物と
そうでない物があります。

**例）** 
　**Amazon ：Fire OS（互換性の承認なし）**
　**SAMSUNG：One UI（互換性の承認あり）**


今回はAndroidの互換性を承認する「CDD」と「CTS」について記載したいと思います。


## Android互換性の承認
Android互換性を承認されたデバイスを作成するには、
「CDD」に準拠し「CTS」に合格する必要があります。

それ以外のデバイスは「Fire OS」の様に非互換のOSという事になります。


## CDD
「CDD」という言葉が出てきましたが、「CDD」とは何でしょう？

「CDD」（Compatibility Definition Document）
日本語で言うと「互換性定義ドキュメント」ですね。

#### Androidの互換性を証明する内容は「CDD」にて記載されています

「CDD」は、正規のAndroidと互換性を満たす為の要件を列挙しています。
また、新しいAndroidプラットフォームのリリースごとに、
新しく「CDD」が用意されます。

新規のデバイスをAndroid互換機としてリリースする際には、
その時の最新の「CDD」をGoogleGitからダウンロードして参照し、
要件を満たしている事を確認しなければいけないという事になります。

## CTS
「CTS」という言葉が出てきましたが、「CTS」とは何でしょう？

「CTS」の正式名称は「Compatibility Test Suit」、
日本語で言うと「互換性テスト」という事になります。

GoogleによるAndroidとの互換性を承認するテスト群を「CTS」といいます。

この認証にパスすることでAndroidの互換性が証明され、
Androidの互換端末と名乗れるようになります。
（具体的にはGooglePlay等を利用することが可能になります）

**注意)**
ただし、「CTS」は「CDD」を完全には包括しない為、
デバイスの互換性の証明には「CDD」に準拠している事を
確認することが必要となります。



#### 【テストケース】
「CTS」には以下の様なテストケースがあります。
　・使用可能なAPIの署名をチェック
　・プラットフォームAPIの正確性チェック
　・Dalvik Executable Formatのチェック
　・コアプラットフォームのデータモデルのチェック
　・コアプラットフォームのインテントのチェック
　・コアプラットフォームの権限のチェック
　・コアプラットフォームのリソースタイプのチェック

互換性チェックのテストはテスト環境としてLinux環境を用意し、
GoogleGitよりテストケースをダウンロードして実施します。

### 【テスト環境】
テスト環境として使用するLinuxには、下記をインストールする必要があります。
　・Android SDKツール
　・ADB
　・AAPT
　・JDK 
　・Virtualenv(Python環境)
　・Android 13 R2 CTS



### 【検証デバイス】
検証するデバイスにも準備が必要です。
　・API レベルの設定
　・CTS（シム パッケージ、メディア ストレス テスト用の動画等）
　・ディスプレイ（ディスプレイの無いデバイスの場合）
　・SIMカード（SIMカード スロットがある場合）
　・UICC（Universal Integrated Circuit Card）
　・デバイスのAndroid設定（データの初期化など）



## 最後に
今回の内容では「CTS」と「CDD」について書いてみました。

スマホを利用するだけの方にとっては
あまり関係のないお話に感じます。

ただ、アプリを開発する者としては、
「CTS」と「CDD」に合格しているデバイスの方が
Android互換に準拠して開発を進められる為、非常に助かります。

非互換の場合は、独自のアプリを開発しやすい面はあるのですが、
ライブラリが無いから作らないといけない・・・
ライブラリはあるけど仕様が違うといった問題があり注意が必要です。

個人的な感想ですが、互換性のあるデバイスの方が、
安心して開発できるので好きですね。

以上になります。
「1日にターミナルで入力した文字数」を可視化するコマンドを作ってみた

[新卒エンジニアによる全部俺カレンダー2022](https://qiita.com/advent-calendar/2022/arie_onlyme2022) 7日目投稿記事です。

## 概要
「1日にどのくらいターミナルでコマンド入力作業をしているんだろう・・」とふと可視化してみたくなったので、シェルスクリプトを書いてみました。


## 前提
- ターミナルはiTerm2を使用
- 任意のディレクトリに日付をprefixとしたターミナルの入力ログが保存されている。
    - 例: 20221020_140806.XXXX-XXXX-XXXX.log

## コード

シェルファイルを作成
`touch count_log.sh`

```count_log.sh
USER_NAME=hoge@fuga # ターミナル画面の左端に表示されるユーザー名をここで指定してあげます。
DATE=$@ # 日付のprefixを引数にする
COUNT=`cat $DATE*.log | grep $USER_NAME | sed 's/.*\%//' | wc -m # ユーザー名でgrepして入力コマンド部分をフィルターする
echo $DATE $COUNT # 日付と文字数を出力
```

たった4行コードを書くだけです。

```sh
COUNT=`cat $DATE*.log | grep $USER_NAME | sed 's/.*\%//' | wc -m
```
ターミナルのログから入力したコマンドの総文字数を計算するのには4つのコマンドをパイプさせます。


`cat` ログファイルの内容を出力する
`grep` $USER_NAMEが含まれる行のみを出力する
`sed` 指定した正規表現に従って、出力結果をフィルターする
`wc -m` 文字数をカウントする


### sedについてちょっと詳しく

```sh
sed 's/.*\%//'
```
上記のコマンドで指定した正規表現では、ログの出力結果から`[ユーザー名] [ディレクトリ]%`の部分をフィルターします。

```
hoge@fuga ~ % cd ~/hoge/fuga
↓
cd ~/hoge/fuga
```

**注意点**

`[ユーザー名] [ディレクトリ]%`の記号部分は環境によって異なるので、適宜正規表現を変えてください

- zsh (%)
    - `sed 's/.*\%//'`
- bash ($)
    - `sed 's/.*\$//'`
- rootユーザー (#)
    - `sed 's/.*\#//'`


## 実行してみる
2022年12月1日のログからコマンド入力文字数を出力してみます。
```
sh count_log.sh 20221201

20221201 1523
```

結果が出ました〜



## 参考資料
https://qiita.com/sosat117/items/2eec8552b6dafd35916a

http://hydrocul.github.io/wiki/commands/sed.html

https://atmarkit.itmedia.co.jp/ait/articles/1611/07/news026.html
食わず嫌いを克服したい：TypeScriptで苦手なところだけかいつまんでやってみた①

## はじめに
TypeScript、難しくないですか（少なくとも私は得意ではありません）？ 特に抽象度が高くなるとすぐに脳内メモリが足りなくなるので、ずっと食わず嫌いをしていたのですが...。そうこうも言ってられなくなったので（遅い）、今更ながら勉強してみることにしました。

## 使用テキスト
使用したのはこちらのテキスト。コードもこちらの書籍から引用しています。全てのコードには該当ページ数も書いておきます。

https://www.amazon.co.jp/dp/4297127474

## ジェネリクス
まずは基本的なこちら。 **「型引数に何を入れるかは関数を呼び出す際に決まる」** 関数を作る機能のことだそうですが、それだけでは何のことかわかりづらいですよね。。。

つまりこういうことだそうです。
下記の場合、`T`がジェネリクスで、 **①一つの呼び出し内でTには同じ値が入りますが、②Tにはどんな型でも入れることができます。**
```ts
const repeat = <T>(element: T, length: number): T[] => { // ここのTにはどんな型でも入る
  const result: T[] = [];                                // Tは関数の中で使ってもOK
  for(let i = 0; i < length; i++) {
    result.push(element);
  }
  return result;
}
```
> プロを目指す人のためのTypeScript入門:p.170

型引数は
- **引数の型**
- **返り値の型**
- **関数の中**

で使うことができます。（使える範囲が広すぎて鬼門だった）
こんなふうに呼び出しの際に型注釈をつけると、上記`repeat`関数内の`T`が全て型注釈でつけた型に置き換わります。

```ts
repeat<string>('hoge', 10) // T はstring型になる
repeat<number>(1, 10)      // T はnumber型になる
repeat(0, 10)              // repeatに型引数をつけなくてもOK（number型と推測される）
```
...が、**型注釈をつけなくてもTypeScriptが推論してつけてくれます。**（ここも鬼門だった）
なんなら**返り値の型が無くたって推論してくれます。**（さらに鬼門だった）
![スクリーンショット 2022-12-06 17.54.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393888/6b7beacd-c5e6-3867-ae83-2dff1f1dbd43.png)

どおりで、ある程度適当に書いていてもうまい具合にジェネリクスが当てはまってくれるワケですね。（そして適当に書いているが故にエラーが出た時にわかりづらくなる。。。。）

参考にしたテキストによると、この機能のおかげでTypeScriptは **"「好きな値で呼び出せばいい感じの返り値を返してくれる関数」として機能する"** (p.172)らしいです。「混乱する！」と思ってしまった自分はTSへの愛が足りなかったようです。頑張ります。

## ジェネリクスの応用
ジェネリクスって、本当に色々な使い方ができるんですよね。こちらも初学の時に一気に詰め込んだ故にわかりづらくなっていたので整理します。

### 複数の型引数
もちろん、型引数の複数使用も可能です。下記の例では`L`と`R`にそれぞれ好きな型を割り振れます。
```ts
const pair = <L, R>(left: L, right: R): [L, R] => [left, right]
const p = pair<string, number>("tanutanu", 10)
// この時、L...string, R...number 型となる
```
> プロを目指す人のためのTypeScript入門:p.171 のコードを一部改変

### extends
`extends`などを使って、型に一部だけ制約を付けることも可能です。下記は、`{name: string}`というプロパティを含むオブジェクトであればコンパイルが通ります。
```ts
const repeat = <T extends { name: string }>(element: T, length: number): T[] => {
  const result: T[] = [];
  for(let i = 0; i < length; i++) {
    result.push(element);
  }
  return result;
}

type PersonalInfo = {
  name: string;
  age: number;
  hobby: string[];
}

console.log(repeat<PersonalInfo>({
    name: "tanutanu",
    age: 10,
    hobby: ['eat', 'sleep']
  }, 3))
```
> プロを目指す人のためのTypeScript入門:p.171 のコードを一部改変

念の為解説です。
![スクリーンショット 2022-12-07 18.07.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393888/830d5fb8-a175-8887-ce96-d1d9fc1f38b1.png)

だいぶ複雑になってきましたが、丁寧に見れば読み解けそうですね:relaxed:

## 次回予告
**ユニオン型、インターセクション型**とジェネリクスを使って、さらに複雑な型を読み解けるようになろうかな。

▼この記事の続きはこちら
https://qiita.com/sazumy/private/83987f0abe773565b5c1
【Blender】Blender初心者が長期休みにBlender作品を毎日作って何を学んだのか

スキルというのは1日で身につくものではなく日々の鍛錬で「磨かれていくもの」だと思う。
角川ドワンゴ学園のプログラミング講師としてBlenderのスキルを少しでも身につけたいと思い、長期休みに毎日作品をつくることにした。

当時はBlender初心者なのでYoutubeから課題を見つけて、こなしていった。

＜1日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/77daa3de-985e-2c5c-d468-3e5ef4a9dba0.png)
とにかく「簡単でシンプルなもの」をテーマにした。最初から難しいテーマをやることは自分のモチベーション低下になる。とにかく「完成させる」ことを大事にした。

＜2日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/acffd794-2087-81e8-8685-1d3550f96a1e.png)
キャラクターものを作ってみたくなったのでやってみた。顔のテクスチャはフォトショップなどで描いて取り込んだ、わけではなくBlenderの機能で描いた。結果、フォトショップなどで描いて取り込んだ方がボケないし良いことがわかった。

＜3日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/c6ed6630-13b6-6d56-7c7a-ae2c384f5ddb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/6f1fee7f-962e-c62e-e1a7-6e3584397e27.png)
日輪刀を作った。刀なんて簡単だろうと思っていたが、はっきり言って2日目の動物より断然難しい。刀の先が綺麗に尖らないのだ。結局試行錯誤で完成したが刀の構造の勉強が必要だった。モデリングすることは対象の研究がものすごく重要だとわかった。

＜4日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/23a543c1-d56b-fe58-5639-7f6a03eff28b.png)
パーティクルヘアーの機能を使って草原を作った。１個の草を作ってそれをパーティクルヘアーで複製している。これはBlenderの強力な機能だ。この機能を知れたのは相当大きい。

＜5日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/25701d03-9827-d436-71d2-eaabf97b7922.png)
雲を作った。これはかなりのPCスペックを要するようだ。私の自前のPCでが悲鳴を上げた（後で新しいPCを買った）

＜6日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/a5323e20-67d3-8736-a16c-66b0965e2f13.png)
アドオンを使った木を作った。これはものすごく少ない時間で完成した。アドオンがどれだけ強力なのがわかった。Blenderの勉強をするならアドオンは使わないほうが良いかも知れない。

＜7日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/11dd8207-df5b-563c-8ef2-98182b4c92b0.png)
めちゃくちゃシンプルに見えるだろうが、パーティクルヘアーの応用だ。米粒を１つ作ってそれを複製している。
このような応用はまず機能そのものを知ることが必要だ。だから、草原を作った経験が生きている。

＜8日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/8bc1af64-be8a-de1e-24ab-1eea6aed9a9b.png)
アニメーションを作った。Blenderはアニメーションも作成できる。尻尾と耳がゆっくりと揺れる。とても時間がかかったがアニメーションを作るときの工数が体感でできるようになったのは大きい。

＜9日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/e8bdd87a-8323-e22c-ce2a-f999d689fa96.png)
これまでの応用で夜景を作った。我ながら綺麗な夜景ができたのではないだろうか

＜10日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/c943aa50-f8b1-9522-7880-9ba2ccd63f27.png)
生徒にテクスチャーの練習用に勧めるために自分でやったチュートリアル。テクスチャーの理解が深まった。

＜11日目＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293435/cf2853dc-6c6d-3626-6236-914c94119420.png)
ポケモンを作ろうとした。だが、これがとてつもなく難しかった。結局完成まではいけなかった。
２次元の情報から３次元のモデルを作るとき見えない部分は「自分の感性」が必要だった。
これは経験が足りなかった。また改めてチャレンジしたい。



ということで私のBlender修行の一部お見せしたがこの後も色々な作品を作っている。
結局は日頃から修行していれば「下手でもどんどん上手になっていく」これを改めて感じた。
続けるためには「モチベーション」をどうするかなのだが、私の場合は毎日成果を他人に見せることで保った。
生徒からのリアクションや友達からのリアクションをモチベーションにした。
人によってモチベーションの保ち方はいろいろあるだろうが、「モチベーション」に対しての解決方法を自分で考えるのが何よりも大切だ。
Android互換のOSを雑多に理解する

世に広くAndroidが普及してきました。

スマートフォンのOSとしてだけではなく、テレビ、冷蔵庫、自動車・カーナビ等
さまざまな製品に搭載されています。


それらの製品の多くに搭載されているのがAndroid OSなのですが、
純粋なAndroid OSではありません。


それぞれの製品用にカスタマイズされたAndroid互換OSになります。


## Android互換OS
スマートフォン用にカスタマイズされた一部の互換OSでは、
GooglePlayが使えたりして、通常のAndroid OSとほぼ変わらなかったりします。

##### しかし、
私の家で使用しているプロジェクタではカスタマイズされたOSが使用されているのですが、
動画系のアプリを使用する事に特化し、GooglePlayも使用できませんでした。
更にAndroidのバージョンアップに追従しづらいというデメリットも存在している様です。

Androidのバージョンアップが出来ないと、
バージョンアップによって得られる新機能を使えないですし
セキュリティー対策が取りづらいといったデメリットが存在します。

その代わり、
使いやすいユーザインターフェースや独自の機能を盛り込むことが出来、
他の類似デバイスとの差別化が図れることになります。

商品開発においてしっかりとした差別化が出来ていることは、
重要な要素になりますね。


##### では、
それらのカスタマイズされたOS達と
純粋なAndroid OSの差は何処にあるのかを見て行きます。




## ■Androidの構造
Android互換の有無の差を理解するために、まずはAndroidの構造を紹介したいと思います。
Androidの構造は大きく５層構造になっています。

##### １層：ユーザが直接使用
　「アプリケーション層」

##### ２層：アプリケーションをコントロールするサービスやマネージャが存在
　「アプリケーションフレームワーク層」

##### ３層：アプリケーションやサービスが共通で使用するライブラリ
　「標準ライブラリ層」
　「Android Runtime」(アプリケーションのデバッグ環境やRuntime)

##### ４層：Linuxベースのカーネル
　「カーネル層」　（各種ドライバ含む）

##### ５層：ユーザとの直接I/F
　「ハードウェア層」

##### 図にすると ↓↓↓ な感じです。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633696/777419e9-02dd-4f61-cc72-3e8f7a03cc85.png)

こうやってみると
Androidの構造は、ユーザI/Fで挟み込んだ
「ハンバーガー」のような構造ですね。

## ■Android互換の有無の差
ザックリとですが
Androidの構造を理解いただけましたでしょうか。

その上でのお話しですが

Androidの3層、4層の内容は、
Android OSのVersionが同じであれば基本的に同じです。
（機種に依存する専用ドライバ等は例外です）


では、正式に互換OSを謳っている物と
そうでない物の違いは何でしょうか。


### ■互換OSと非互換OS
有名どころでAmazonの「Fire OS」とSAMSUNGの「One UI」を挙げてみます。

「Fire OS」はAmazonが開発したOSで、KindleやFire TV Stickなどで利用されています。
ユーザインターフェースや独自のアプリストアなど、様々なオリジナル機能を実装したOSになります。

「One UI」はSAMSUNGが開発したOSで、主にスマホのGalaxyシリーズに利用されています。
独自機能も有していますが、ややAndroidに似たOSとなっています。

前者と後者での大きな違いは
Androidの互換性テスト(Compatibility Test Suit 以降CTS)に
合格できているかどうかです。
※CTSについては別で記事させていただきました。下記URLを参照ください。
参照>https://qiita.com/ydclab_0008/items/7c6780523b96f8b4c9ec


### Fire OS：互換性なし
### One UI ：互換性あり



そういえばFire OSではGooglePlay使えませんね。


### ■互換性とデバイスの差別化
Googleは各メーカーへ互換性の維持を推進しています。

##### 特に４層(カーネル)は改変しない様に促しているそうです。

つまりAndroid端末はCTSで互換性を有する限り
##### １、２、５層で差別化を図っているという事になります。


5層の差別化はハード的なスペックの差ですが、
1、2層のアプリケーションやサービスでは、
利便性のあるアプリケーションを加えることで差別化を行ているメーカーが多いようです。

## 最後に
という訳でAndroidの構造について書いてみましたが、
世に出回っているAndroidには、互換と非互換があることが分かっていただけたと思います。
違いとしても、「CTS」という互換承認テストに通っているか否かという明確な差があることも理解いただけたと思います。

今後何かAndroidっぽいOSを見かけた際には、互換OSか非互換OSかを確認してみてください。

以上になります。
Reactに挑戦した1年【一蘭アプリのポイントは半替え玉がコスパ最強】

# 挑戦するようになったキッカケ
[弊社ポータルサイト](https://bbt.ac/environment/aircampus)のUI大幅リニューアルがキッカケ。
10年以上djangoテンプレート(makoテンプレートも少々)を使ってhtml, css, backbone.jsで頑張ってきたが、リニューアルの際にモダンフロントエンドを採用しよう！ということで思い切ってReactに挑戦（フレームワークはNext.js）。

# Reactのつまずきポイント
**①keyにindexを使うのは良くない**
良くない例↓
```React
let todos = [
    { id: 1, name: "shopping" },
    { id: 2, name: "working" },
    { id: 3, name: "talking" }
  ];
const todoItems = todos.map((todo, index) =>
  // keyにindexを指定しているが良くない
  <li key={index}>
    {todo.name}
  </li>
);
```
良い例↓
```React
const todoItems = todos.map((todo) =>
  // keyには一意に決まるものを指定する
  <li key={todo.id}>
    {todo.name}
  </li>
);
```
[公式ドキュメント](https://ja.reactjs.org/docs/lists-and-keys.html#keys)にもあるが、配列の並び替えや要素の追加・削除をする可能性がある場合は期待した動作にならないので注意

**②配列を更新したのに再レンダリングされない**
良くない例↓
```Javascript
const [sampleArray, setSampleArray] = useState([0, 1, 2]);
copyArray = sampleArray; // stateの配列をコピー(参照コピー)
copyArray[0] = copyArray[0] + 1; // 配列を更新
setSampleArray(copyArray); // 再レンダリング
```
良い例↓
```Javascript
copyArray = sampleArray.slice(0, sampleArray.length); // stateの配列を値コピーする
```
[公式ドキュメント](https://ja.reactjs.org/docs/hooks-reference.html#bailing-out-of-a-state-update)にもあるが、参照コピーだとstateによる再レンダリングが行われないので注意

# 好きなラーメン
小腹が空き始め、夜中11時ごろ食べにいく一蘭のラーメンが至高の一杯。
多少の罪悪感を感じながらも、店に入れば替え玉をガッツリ頼んでしまう。
麺固め。ニンニク、秘伝のタレ多め。
ネギは白。たまに白と青のハーフ。
スープからいただきます。

-------------------
ちなみに、一蘭公式アプリのポイントは半替え玉がコスパ良し。
替え玉(210円・60ポイント)と半替え玉(150円・30ポイント)を1ポイントあたり円で算出した。
替え玉→1ポイントあたり3.5円
半替え玉→1ポイントあたり5.0円
Bootstrapの超簡単な導入をまとめた

自分用のメモとしてBootstrapの導入方法をここにまとめます。
ちなみに導入するBootstrapのVersionは**Bootstrap4**です。

# 導入の手順
1. ターミナルで`yarn add jquery bootstrap@4.5 popper.js`を実行
1. 「config/webpack/environment.js」に以下を記入
    ```ruby:config/webpack/environment.js
        :
        :#(省略)
        const webpack = require('webpack')
        environment.plugins.prepend(
          'Provide',
          new webpack.ProvidePlugin({
            $: 'jquery/src/jquery',
            jQuery: 'jquery/src/jquery',
            Popper: 'popper.js'
          })
        )
    ```
1. 「app/javascript/stylesheets/application.scss」に以下を記入
    ```css:app/javascript/stylesheets/application.scss
        @import '~bootstrap/scss/bootstrap';
    ```
1. 「app/javascript/packs/application.js」 に以下を記入
    ```javascript:app/javascript/packs/application.js
        :
        : //(省略)
        import "channels"
        
        import "jquery";
        import "popper.js";
        import "bootstrap";
        import "../stylesheets/application" 
        
        Rails.start()
        Turbolinks.start()
        ActiveStorage.start()
    ```
1. 「app/views/layouts/application.html.erb」を書き換え
    ```html:app/views/layouts/application.html.erb
       - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
      
       + <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    ```

以上の工程で導入できます。
SSH 公開鍵を ssh-rsa から強い暗号に書き換える


2021/9/26 にリリースされた OpenSSH 8.8 から `rsa-ssh` 形式の SSH 鍵がデフォルトで無効になりました。

良い機会なので、新しい暗号鍵形式に変更しましょう。

どうしても変えることができない人は、OpenSSH の設定ファイルを変更して ssh-rsa を再び使えるようにしましょう(非推奨)

# より安全な鍵を生成する (楕円曲線)

僕の周りでは ecdsa-sha2-nistp521 アルゴリズムを使っている方が多いような気がします。

その場合の鍵生成方法は

```
ssh-keygen -t ecdsa -b 521 -C "コメント(メールアドレスとか)"
```

Mac OS だと、以下のような感じで生成されます。

```サンプル
% ssh-keygen -t ecdsa -b 521 -C "katz@example.com"
Generating public/private ecdsa key pair.
Enter file in which to save the key (/Users/ユーザー名/.ssh/id_ecdsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/ユーザー名/.ssh/id_ecdsa
Your public key has been saved in /Users/ユーザー名/.ssh/id_ecdsa.pub
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx katz@example.com
The key's randomart image is:
+---[ECDSA 521]---+
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
| XXXXXカットXXXX  |
+----[SHA256]-----+

```

Windows であれば TeraTerm などのソフトで生成できます。参考「[Windows10からLinuxへのSSHにセキュリティの高い公開鍵認証を設定する手順](https://souiunogaii.hatenablog.com/entry/Linux-ssh-pubkey)」

鍵ファイルは `id_ecdsa` や `id_ecdsa.pub` などが生成されます。

上記の出力をよく見ると、鍵の保存場所がかかれているので、
それに応じて公開鍵などをゲットして必要なところへ渡すなどしてください。


# 各暗号形式と ssh-keygen での生成方法の相対表

他の暗号形式で鍵を生成したい場合の ssh-keygen コマンドのオプション例です。

暗号形式 | ssh-keygen コマンドオプション
-----|-------
ssh-ed25519 | ssh-keygen -t ed25519
ecdsa-sha2-nistp256 | ssh-keygen -t ecdsa -b 256
ecdsa-sha2-nistp384 | ssh-keygen -t ecdsa -b 384
ecdsa-sha2-nistp521 | ssh-keygen -t ecdsa -b 521



# 参考

- [OpenSSHがSHA-1を使用したRSA署名を廃止、BacklogのGitで発生した問題と解決にいたるまでの道のり](https://nulab.com/ja/blog/backlog/disables-rsa-sig-using-the-sha-1-in-openssh/)
- [RSA keys are not deprecated; SHA-1 signature scheme is!](https://ikarus.sg/rsa-is-not-dead/)
- [SSH で RSA/SHA1 が使えなくなったので対策する](https://zenn.dev/noraworld/articles/ssh-rsa-sha1-disabled)
- [Generating SSH keys](https://cloud.ibm.com/docs/hp-virtual-servers?topic=hp-virtual-servers-generate_ssh)
- [Windows10からLinuxへのSSHにセキュリティの高い公開鍵認証を設定する手順](https://souiunogaii.hatenablog.com/entry/Linux-ssh-pubkey)
- [MacからLinuxへのSSHにセキュリティの高い公開鍵認証を設定する手順](https://souiunogaii.hatenablog.com/entry/Mac-Linux-ssh-pubkey)
県のDX事業への挑戦と社内へPower BIの普及

## はじめに
　佐賀県の小売業（和服業）で情シスをしています。地方でＩＴリテラシーがとても低い業種ですが、社内にデジタル化が少しでも浸透するように少しづつ頑張っています。
　
  今回はオンライン勉強会(Power BI勉強会）やコミュニティに参加し勇気をもらい、県のＤＸ事業に挑戦したことを記事にしたいと思います。

## 県のＤＸ補助金事業に挑戦

### 　１．県のＤＸ補助事業に応募し採択される
　今年の５月に県のＤＸフラグシップモデル事業にPower Platformを活用しての内製化と業務改革（アプリ作成とデータ利活用）を提案し応募を行い、小売業は１社のみという狭き門でしたが採択されされることとなり、まさかＩＴとは程遠い業種（和服業）でＤＸフラグシップモデルになるとは思ってもいなかったです。

https://www.pref.saga.lg.jp/kiji00384868/index.html

　

#### Power Platform活用した図（赤枠部分は内製）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/44e3595d-12d3-59bb-962b-078935631ead.png)





またJapan Power Platform Conference 2022にも登壇することもでき、地方で非ＩＴ企業でも変革できることを伝えられてよかったです。


https://www.docswell.com/s/5270562/52VER5-2022-10-19-160116

### 　２．応募・採択に繋がった一番の要因（勉強会とコミュニティ）

　　約2年前に勉強会・コミュニティに参加していなかったら、和服業でＤＸなんて到底無理だと思っていたし、県のＤＸ補助事業に挑むことすらなかったと思います。
　　勉強会やコミュニティ（特にPower BI勉強会）に参加し様々な人が挑戦・勉強をして発表しているのを聞いて、私も出来るのではないかと勇気をもらった結果だと思っています。
　　
　

https://powerbi.connpass.com

### 　３．メジャー(DAX)を入力しているところ動画撮影（県事例紹介）
　補足ですが１１月に県事例の動画撮影があったのですが、作業（プログラミング）しているところを映したいと言われ、DAX言語（メジャー）を入力しているところを撮影されたのですが、スラスラとメジャーは書けるわけないだろうと思いつつも、まだまだ勉強不足だと改めて感じました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/998c8e7d-58e5-3484-06d2-9fde4818236b.png)

### 　４．アプリの現在の利用状況・登録状況の分析
Power Apps側の分析(Power BI)機能で調べたところ、日々のアプリ利用率は約３割程度だが、アプリへのデータ登録がされていない店舗もあるため、Power BIを使ったデータ利活用のために、アプリの利用率の向上とデータ登録を今後増やしていく必要がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/b0ffef1d-b116-467c-ac2e-133dc4e0a2cd.png)

アプリの利用回数と合わせて、アプリへの買上商品の写真登録の登録状況もPower BI側で分析してみた、アプリをリリースして1カ月程度で写真登録が８３０枚登録されており、約2割の店舗しかアプリへの登録しないだろうと思ってたが、約４割弱の店舗が登録していたので、やっぱり需要があったんだと再認識。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/41bb95ea-f1c0-1b52-9a07-25bdafecc3c7.png)

買上商品写真については、どのような写真を撮っているのかを把握するため、Power AUtomateにて画像分析を行っており、着物の認識率をメジャーで書いてみる。
着物は「ドレス」として認識するのとドレスでも「デイドレス」、「ウェディングドレス」等があるため、FIND関数にて部分一致検索を行うメジャーを作成

```
AI着物認識枚数 = 
CALCULATE(
        [写真枚数],
        FIND(
            "ドレス",
            'Photo'[分析結果],1,BLANK()
        )
    )
```


### 　５．Power BI Proのライセンス数も増大（数ライセンス⇒数十ライセンス）
　去年までは、Power BIの有償ライセンスは数ライセンスしかなかったのだが、県のDX事業にデータ利活用のためPower BI proのライセンスも含めていたので、数十ライセンスまで拡大することになりました。ただ、来年もライセンス更新出来るようＢＩレポートを作成出来る社員を増やす必要がある。


### 　６．ＰＣメーカー主催の講座（Power BI,Power Automate)を受けてみて
　社内でPower BIを普及させるために、中堅企業のＩＴ担当者向けのＤＸエンジニア講座（Power AUtomateが4回、Power BIが2回）の講座を受けてみたのだが、内容は初心者向けであり、かつ講座の内容に一部が？部分もあったが、この講座で改めて思ったのは初心者はまずは簡単なデータ可視化・分析でもいいので自身で行うことが重要であることを再認識することが出来ました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/68f403e5-808b-5949-886d-5a26f5b3b8c6.png)




## まとめ
　今年は厄年（本厄）だったので新しいことをするのは控えようとは思っていたが、蓋を開けてみれば去年以上のことをやっていたような気がします。
　地方で非ＩＴ企業だから難しいと思っている方も地方の着物屋さんでもデジタル化が可能だったので、頑張れる手助けになれたらと思います。
　
　また県のDX事業のデータ利活用(Power BI)は来年以降に本格的になるので、2023年は引き続きPower BIの勉強を続けて、業務部門がデータ分析出来るように普及出来るように頑張っていきたい。
GoでDB接続からテーブル作成まで

# はじめに

Goの開発環境をDockerで構築していることを前提にすすめます
前日の記事でまとめているので、こちらを参考にしていただければと思います

https://qiita.com/does_not_exist/private/0f948f137a926928ae07

# やりかた

まずサーバーを立てます
今回はginの公式ドキュメントを参考にしました

https://gin-gonic.com/ja/docs/quickstart/

その後、Postmanからサーバー(localhost:8080/ping)にアクセスして結果が返ってくることを確認します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/107ed424-e783-ca7a-722e-b0b78407d6ee.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/5d26ae4e-b544-6a2f-df6e-628aea3bc3eb.png)


https://www.postman.com/

DB接続の設定をします
今回はGormの公式ドキュメントを参考にしました

https://gorm.io/ja_JP/docs/connecting_to_the_database.html

```main.go
package main

import (
	"time"

	"gorm.io/driver/mysql"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type Post struct {
	gorm.Model
	Weight int
	Date time.Time
}

func main() {

	dbConn := "DBのユーザー名:DBのパスワード@tcp("コンテナ名":3306)/DB名?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dbConn), &gorm.Config{})
	if err != nil {
    panic("failed to connect database")
  }

	db.AutoMigrate(&Post{})
	
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
}

```



次にdbのコンテナに入ります
コンテナ名はdbにしたので以下コマンドを実行します

```
$ docker exec -it db sh
```



```docker-compose.yml
version: "3"
services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_USER: ${ROOTUSER}
      MYSQL_ROOT_PASSWORD: ${ROOTPASS}
      MYSQL_DATABASE: ${DATABASE}
      MYSQL_USER: ${USERNAME}
      MYSQL_PASSWORD: ${USERPASS}
      TZ: "Asia/Tokyo"
    volumes:
      - ./my.cnf:/etc/mysql/conf.d/my.cnf
    env_file:
      - .env
    container_name: db
    ports:
      - 3306:3306
```

```.env
ROOTUSER=root
ROOTPASS=password
DATABASE=sampledb
USERNAME=docker
USERPASS=docker
```


dbのコンテナに入ったらDBに接続できることを確認します
確認が出来たらデータベースを作成します

```
$ mysql -u root -p
// password入力(.envのROOTPASS)
mysql > create database hoge;
```

テーブル作成

https://gorm.io/ja_JP/docs/migration.html


main.goのこの部分です
```
db.AutoMigrate(&Post{})
```

以下コマンドを実行してテーブルが作成されていることを確認できればOK

```
mysql > use hoge;
mysql > show tables;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/20a1fb40-0c37-4df0-4d3b-9f6094287ad9.png)
地方過疎在住のへっぽこ非エンジニアでもできるマナビDXのTweet可視化、時々Python基本スプシ、クエリもあるよ。

こんにちは！

マナビDXクエスト参加中の非エンジニア44歳です。

マナビDXクエスト、およそ2000人が参加してるわりにはTwitterでそれほど盛り上がってる感が無きにしも非ずでして、データサイエンスを志すおっさんのはしくれとして、軽く勉強も兼ねてTweet具合を可視化してみました。


<iframe width="744" height="516" seamless frameborder="0" scrolling="no" src="https://docs.google.com/spreadsheets/d/e/2PACX-1vQeNmfIemrH6kP0AeZS-UrQFZ7ygJ9vPlqLkvX9UMZPctodVFrEdvS1XUx2Y1B9yNvHX4GwAjeV2ahn/pubchart?oid=363750611&amp;format=interactive"></iframe>


やっぱり入学式があった9月がピークなんですね。
しかし3月のピーク、これなんでしょかしら？？


## Tweet取得に使用したのはsnscapeです。

基本的にローコードしかできない人間なので、一つ一つ薄氷を踏むように
あれこれやっていますから、カタカタカタッターン！ってキーボードたたいて
魅せ映えチャートがドドーンっと出るこたぁありません。

## Tweet取得から可視化まではこんな感じ。
こちらのQiita記事を参考にさせていただいています。

+ [Pythonでsnscrapeを用いたツイート抽出](https://qiita.com/l1105819677/items/4b4451d23f13b90742f4)

## snscapeで** マナビDX を含むTweetを取得。

```python
!pip install snscrape
import pandas as pd
import snscrape.modules.twitter as sntwitter

#検索するキーワード
search = "マナビDX"
  
#Twitterでキーワードをスクレイピング
scraped_tweets = sntwitter.TwitterSearchScraper(search).get_items()

#データフレームに変換する
df = pd.DataFrame(scraped_tweets)
```


## スプレッドシートを手作業で新規作成
※GoogleColabから新規作成できるけど、1つのファイルに検索結果をシート分けしたいからこれは手作業で。
スクレイピングのたびにファイルができるとうざい。

これからColabに指示する用にスプレッドシートのURLを取得というかコピー。

## スプレッドシートに新規シート作成、dfを入力する。
```python
# シートを新しく挿入する。
st_name = "マナビDX_scrape"

st = ss.add_worksheet(title=st_name, rows=len(df_manabiDX), cols=5)
set_with_dataframe(ss.worksheet(st_name), df_manabiDX, include_index=False)

#行列を入れる意味があるのかはよくわからんけど。
```

# ここまでがTweet取得からスプレッドシートへの反映

## こっからはクエリ関数で集計可視化

クエリ関数便利よね。
詳しくはこちら。SQL書ける人は超重宝するはず。

+ [クエリ関数](https://support.google.com/docs/answer/3093343?hl=ja)

スプシの集計をピボットテーブルでやると見た目が雑くてスッキリしないんですよね。
クエリ関数なら、importrangeと組み合わせて他のファイルからの集計にもつかえて重宝します。
今日は基本的なカウント集計だけですが。

### ここで問題が
Colabからスプシに書き込んだ日付列が文字列扱いで使いにくいので一度分解してからdate()関数で日付に仕立て直す手間がかかる。
Colab側で年月日のカラムに分解してからスプシ上でdate()関数に渡してもいいけどあんまり手間はかわらん。好みの問題。

また別の機会に書きますが、こういうときはarrayformula関数いいよarrayformula。
大事なことだから2回言いました。

## 気を取り直してグラフを作る。
日付とTweetの2列にした縦型の表を選択します。
今回はA列とB列、1行目にヘッダ入れてます。

あとは、適当なセルに以下の関数を書きましょう・
```sql
=query(A:B,"select A,COUNT(B) group by A")
```

年月日でまとめられたTweet数カウントの表ができると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/71ee5b4d-7b42-135a-5199-877395fa99df.png)


あとはこの2列を選択してグラフを作成。
グラフ設定から、このグラフを公開をクリックして埋め込み用のコードを取得すれば、あとは好きなところに埋め込むだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/5390b74e-9e77-3b18-555c-46332edb77d1.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/99864495-fcfc-d4d5-0b56-e68d0bb5fdd2.png)


改めてみてみると、2000人規模で参加してる割には寂しいなぁ。
やっぱり身バレ意識してつぶやかない勢が多数なんでしょうね。

<iframe width="744" height="516" seamless frameborder="0" scrolling="no" src="https://docs.google.com/spreadsheets/d/e/2PACX-1vQeNmfIemrH6kP0AeZS-UrQFZ7ygJ9vPlqLkvX9UMZPctodVFrEdvS1XUx2Y1B9yNvHX4GwAjeV2ahn/pubchart?oid=363750611&amp;format=interactive"></iframe>

以上です。

データの可視化はPowerBIデスクトップやLookerStudioみたいなBIツールでダッシュボード作るのも楽しいけれど、スプレッドシートでもインタラクティブなものを作ることもできるのでまた後日記事化しようと思います。
モバイル開発初心者のモバイルアプリ開発日記

今日からペースはゆっくりになると思うが、RSSリーダーアプリを開発を始めるにあたって、
新米開発者の開発日記として主に手こずった箇所を記事にして投稿していきます。

使用する開発ツール：Xcode 14.0.1

1日目
今日はgitのリポジトリー作成とXcodeでプロジェクトを作成して、連携するところまで実施してみる。

1.プロジェクトの作成
Xcodeを起動し、「Create New Xcode Project」からプロジェクト名と使用する言語などを決定し、サクッと作成することができた。

2.Gitのリポジトリー作成
こちらもネットで調べながらではあったが、簡単にリポジトリーを作成することが出来た。

3.Xcodeとgitの連携
ここで少し手間取ってしまった。
最初にローカルのリポジトリーを作成するところまで良かったが、リモートリポジトリーの設定をする時にgitのユーザー名とパスワードが必要になるのだが、このパスワードがgitのログイン時に使用するパスワードだと勘違いをしており、エラーで何回も弾かれてしまった。
どうやらこのパスワードはgithubの個人アクセストークンを入力するものだった。
このアクセストークンはgithub右上の自分のアイコンをクリックし、「settings」→「Developer settings」(左側のメニューの一番下)→「Personal access tokens」から取得できるようだ。
直感だけでは辿り着けない罠であった。。
その後はすんなりとgitのリポジトリーにXcodeで作成したプロジェクトをアップロードすることが出来た。

まだ開発がスタートしていない1日目から苦戦。。
iOSでRSSreaderのアプリを開発しようと思っているがいつ完成できることやら。。
Rails Girls Gathering Japan 2022で初めて運営スタッフを経験して得たもの

この記事は、[Rails Girls Japan Advent Calendar 2022](https://qiita.com/advent-calendar/2022/railsgirlsjapan)の６日目の記事です。

今回の私の経験が、運営スタッフに興味のある方やコミュニティ参加に迷ってらっしゃる方のお役に立てれば幸いです。


# 自己紹介
みなさん、初めまして！フィヨルドブートキャンプ(プログラミングスクール)でwebエンジニアを目指して学習中の[@ai-24](https://twitter.com/ai_24_ai)と申します。
12/3に開催された[Rails Girls Gathering Japan 2022](https://gathering.railsgirls.jp/)で人生初めての運営スタッフを経験させていただきました。


# 運営スタッフに参加した経緯
私は去年Rails Girls Gathering Japan 2021（オンライン）に参加したのですが、その際に「Rails Girlsいいな。運営スタッフってどうやったらなれるんだろう？」と運営スタッフに興味がありましたが、参加者としてイベントを視聴させていただくことは出来ても、その後の懇親会に出席する勇気はなく、ギリギリまで迷った結果参加できず疑問に思った事を聞けずに終わってしまいました。

その後10ヶ月ほど経った時に、フィヨルドブートキャンプで受講生同士がペアレビューをされている様子を見学に行ったのですが、そこで昨年も運営スタッフをされていた方が、他の受講生の方に「運営スタッフやってみませんか？」と声をかけてらっしゃる場にたまたま居合わせ、その後その運営スタッフの方に「私もやってみたいです！」とお話させていただいたことがスタッフ参加へのきっかけでした。

そこから１度運営ミーティングに参加させていただき、流れを見学させていただいた上で実際にやってみたいかどうかを運営チームの皆さんに尋ねていただき、運営スタッフに参加させていただくことになりました。

# 運営スタッフに加わって感じた事
運営チームのメンバーは皆さんフレンドリーで、質問しやすい環境を作ってくださったり、分からないことは優しく教えてくださる方ばかりでした。
しかし初めての参加で何も分からない状態だったので、ミーティングに参加するだけでも緊張するし、折角チームに加えていただいたのにお役に立てるか分からず不安でいっぱいでした。

ですが当日に向けた準備や当日の役割は色々ある中から自分がやりたいことを選ばせていただけましたし、当日も先輩スタッフがフォローしてくださってやりきる事が出来ました。
自分１人であれば挑戦できなかった運営スタッフの役割も与えていただいて、終わった後は達成感と運営スタッフの皆さんへの感謝の気持ちでいっぱいでした！！

# 懇親会
また懇親会はとても良いです！！
昨年は勇気がなく断念してしまいましたが、今回Rails Girls Gathering Japan 2022を通して、Rails Girlsの温かさを実感しました。
懇親会の参加は初心者にはハードルが高く躊躇う方も多いですよね。でも実際に参加するとベテランの方々も本当に優しい方ばかりで、不安や緊張している気持ちを汲み取ってくださいます。そして今回私含めスクール生も参加されていたので、スクール生同士のお話でも盛り上がりました。
色々なお話を直接伺えるチャンスなので、ぜひ次回Rails Girlsで懇親会が開催されているイベントに参加された際は懇親会にも参加してみて欲しいなと思います。

# 最後に
Rails Girls Gathering Japan 2022の運営スタッフを経験させていただいて、とにかく楽しかったしRails Girlsの温かさを今まで以上に知りました。
登壇してくださった方々の発表を伺って、気づきや共感させていただける事がたくさんあったこともあり、新しい事に挑戦する不安が和らいだ気がします！

次の新しいことへの挑戦としてはコーチにトライしてみたい！と思っています。これは懇親会でemorimaさんが後押ししてくださったからこそ見つけられたものです！
そして、私が運営やってよかった、コーチにも挑戦してみたいと思えたのは運営スタッフの皆さん、登壇者の皆さん、参加者の皆さん全員の協力があってRails Girls Gathering Japan 2022が成功したからこそだと思います。本当にありがとうございました！！
プログラミング知識ほぼ０で学んだRailsの感想（メリット・デメリット）

## はじめに
本記事は[Progaku Advent Calendar 2022](https://qiita.com/advent-calendar/2022/progaku)6日目担当ひで丸です。
今回は、Ruby on Rails(以下略　Rails)を学んだ感想（メリット・デメリット）について書いていこうと思います！

## 背景
私自身、ほぼ知識０から何のプログラミングを学習すればいいんだろう？と思い、
初学者向けと聞いたRailsを学んで３ヶ月経ちますが、学んだことによるメリットやデメリットが少しずつ見えてきました。
そこで、「初めてプログラミングを学びたいけど、何を学べばいいんだろう？」という方に向けてメリット・デメリットをお伝えしたいと思い、この記事を書くことにしました。

## Railsとは？
そもそもRailsとはなんぞや？と思う方がいると思いますので、簡単に説明します。

**RailsはRuby on Railsのことであり、プログラミング「Ruby」に多く使われるフレームワークです。**

もう少し詳しく書くと、Rubyというプログラミング言語で開発をしようとした際に多く使われるフレームワークがRailsで、アプリケーション開発においてよく利用される機能をあらかじめ備えており、開発にかかる労力の削減と品質向上の両方が期待できるものとなっています。

## 結論
##### **Railsはプログラミング初心者におすすめです！！！**
理由は学びやすく、勉強が継続しやすいからです！

Railsを布教したいというわけではありませんが、プログラミングは挫折しやすく、
学習を辞めてしまう方が多いかと思いますので、その点で楽しく継続できるという点で勧められると思いました。

ただ、ある程度プログラミング知識がある方はRailsを学ぶ優先度はそんなに高くないのかなとも思っております。

具体的な理由は下記のメリット・デメリットに記します。

## メリット
#### 1. 簡単にサイトが作れる
プログラミングに触れたことのない方は、まずは学習しながらサイトやアプリを作りたいと考えるのではないのでしょうか？

そこで、Railsというフレームワークを使うと1月もあれば簡単な投稿サイトのようなものを作ることができ、慣れてしまえば、色んなサイトを次々と作成することができます。

これもRailsの特徴で、どちらかというと少人数開発向けのフレームワークなので個人でもそれなりのものができます。

そして、何より自分が作ったものや、追加した機能がすぐに確認できるので
**「作っていく楽しさを感じながら学ぶ」**
ことができるというのが最大の利点だと感じました。

#### 2. 学習できる教材が多い
Railsはネットでの情報が多く、日本語で書いてあることが多いので、**学びやすい環境が整っている**と感じました。
検索で「rails チュートリアル」「rails progate」と調べると無料である程度の基礎を学ぶサイトもあり、
まずはそれをやってしまえば十分に学習することができると思います。

また、学習中はエラーとの戦いになる場面が多いですが、基本的なエラーはQuitaの記事に解決方法が書いてあり、
私自身、Quitaの記事に助けられながら学習することができました。

#### 3. 汎用性が高い
Railsはtwitterやクックパッド、食べログなど様々なサービスに使われております。
Railsを通してできることは多く、SNSサイトやEC2サイト、コミュニティサイトなど作ることができ、
企業からの需要も多く、まだまだ活躍できるフレームワークだと感じています。

企業に就職活動をする際にも、ポートフォリオを作成する方がほとんどだと思いますが、
Railsではできることが多いので**自分の作りたいものを作りやすいフレームワーク**なのではと思います。

## デメリット
### 1. 言語とフレームワークの学習をする必要がある
当たり前のことですが、Railsはあくまでフレームワークであり、Railsを学ぶには言語を学ぶ必要もあります。
そのため、**言語とフレームワークの両方を学ぶ必要があり、学ぶにはある程度の労力が必要**になります。

私は、HTML,CSS,Rubyを学習してからRailsを学びましたが、一気にいくつもの言語やフレームワークを理解するのは苦労しました。

ただ、Railsを学んでからよりプログラミング学習が楽しくなり、理解を深めることができたのも事実です。

### 2. 環境構築が大変
初心者にはプログラミング学習の環境を整えるまでの環境構築が大変だと思います。
Railsだと色々と設定をする必要があり、私自身環境構築するのに3~4時間かかりました。
PCや使いたい言語によって環境構築難易度は様々だとは思いますが、苦労する場面が多いので、
**調べる能力が求められたり、詳しい人のサポートが必要**になるのではと思いました。

### 3. プログラミングの知識が浅くなりやすい
Railsでは自動である程度の機能を自動で作成できるコマンドがあり、
スピーディかつ簡単にアプリやサイトを作成でき、コードも膨大な量を書く必要がありません。

そのため、スピーディな開発が可能となっておりますが、初心者としてはコードを書いて理解しつつ慣れることが大事だと思いますので、Railsが自動で生成したコードでも自分で作成し直したり、コードを読んだりして、**意識的に一つ一つ理解を深めていくことが重要になります。**

## 最後に
今回はプログラミング初心者向けとしてRailsについてメリットとデメリットを書きました。

結論としてRailsをお勧めしてはおりますが、一番大事なこととしては
#### プログラミングに触れて、継続して学習できる
ことだと考えています！

その上で、実際にRailsを３ヶ月勉強して楽しいかつ継続して勉強できたと思ったので
お勧めさせていただきました！！

また、プログラミング自体の楽しさだけでは挫折しやすい部分もあるかと思いますので、
そういう時は、一緒に学習を頑張っている方や、教えてくれる方を見つけましょう！！

初めて書く記事で長文や読みにくいところもあると思いますが、
少しでも皆さんのためになればと思っております。

以上、[Progaku Advent Calendar 2022](https://qiita.com/advent-calendar/2022/progaku) 6日目でした！！！
Jest React TypeScript 環境構築

# 概要
ReactのテストフレームワークJestの環境構築を行います。

# 開発環境
IDE:GitHub CodeSpaces
OS:windows10
言語：TypeScript

├── @testing-library/jest-dom@5.16.5
├── @testing-library/react@13.4.0
├── @testing-library/user-event@13.5.0
├── @types/jest@29.2.3
├── @types/node@16.18.4
├── @types/react-dom@18.0.9
├── @types/react@18.0.25
├── jest@29.3.1
├── react-dom@18.2.0
├── react-scripts@5.0.1
├── react@18.2.0
├── UNMET DEPENDENCY test@jest
├── ts-jest@29.0.3
├── typescript@4.9.3
└── web-vitals@2.1.4


# 手順
## Reactを構築する
以下のコマンドを実行
```
npx create-react-app my-app
```

githubのログ
https://github.com/RYA234/my_learning_React_with_jest_and_ReactTestingLibrary/commit/645507004e4d2d60e3ae070114fb15afca074490
## Jestを構築する
以下のコマンドを実行
```
cd my-app

npm i jest @types/jest ts-jest -D
```
githubのログ
https://github.com/RYA234/my_learning_React_with_jest_and_ReactTestingLibrary/commit/f1eec85267fa74f8a6ec5ca658913896504c97f8



# Jestを使う
## プロダクトコード
2つの値を足し算するコードです。
``` foo.ts
export const sum
  = (...a: number[]) =>
    a.reduce((acc, val) => acc + val, 0);
```

## テストコード
``` foo.test.ts
import { sum } from '../src/foo';

test('basic', () => {
  expect(sum(1,4)).toBe(5);
});

test('basic again', () => {
  expect(sum(1, 2)).toBe(3);
});

test('basic  Pattern', () => {
    expect(sum(100, 2)).toBe(102);
  }
);
```

my-app以下で以下のコマンドを実行
``` コマンド.
npm test
```
## Good Pattern
補足：qボタンで戻る
![jestSuccessPatern.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/b85096fa-36e2-9cd8-f088-8f42b1620e2a.gif)



## Bad Pattern
結果がエラーになるようテストコードの値をいじります。
![jestFailPatern.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/13249b91-7153-c41a-4f31-97e8b60df6d8.gif)



# 感想
環境構築が楽で良いですね。
30分でできました。詰まるところなかったです。
# 参考
react 導入
https://code.visualstudio.com/docs/nodejs/reactjs-tutorial
CodeSpacesはクラウド版VSCodeなので、VSCodeのやり方をそのまま流用できます。

jest 導入「TypeScript を使用する」の項目から
https://jestjs.io/ja/docs/getting-started
録画映像の検索機能を作りたい

# はじめに
会社でアドベントカレンダーをやることになったのでQiitaに初投稿します。私の勤めているセーフィー株式会社は、ネットワークカメラの映像をクラウドに録画するサービスを提供している会社です。クラウド上に長時間（1カメラあたり1週間～1年）の動画が保存されているという特徴があります。

多数のカメラ・長時間録画データからユーザが自身の興味関心のある映像に効率的にアクセスするには、検索する仕組みが必要不可欠と考えています。今のところ、「映像の動き（背景差分）」、「人物の映り込み（物体検出）」、「音の大きさ」をもとに、興味のある時点にアクセスする仕組みがありますが、さらにいろいろなアクセス方法が提供できると面白そうだと思っています。

今回は、画像をクエリにして類似する映像を検索する方法を考えてみました。まだ自由研究程度のレベルなので、つっこみお待ちしています。

:::note warn
セーフィーのサービスおよび開発業務では、お客様の映像データにお客様の許可なくアクセスすることはありません。
:::

# やったこと
以下の方針で考えてみます。

1. なんらかの方法で特徴量空間にエンコードする 
1. 特徴量空間で近傍探索する

特徴量空間にエンコードする方法としては、
1. 表現学習済みのニューラルネットワークを使う
1. 特徴量を自分で設計する

のどちらから検討しようか考えました。表現学習済みのニューラルネットを使った場合、意味（semantic）の抽出は優れているかもしれませんが、画像選択の根拠の説明が難しいかもしれないと思いました。また、表現学習の仕方によって特徴量が変わってくるのも難しそうです。ということで、まずは自分で特徴量を設計してみることにしました。

似たような色の映像が抽出できたら役に立つかも？しれないので、色相とトーンで50パレット（=特徴量）を作ってみます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64694/69705001-30a3-f4b6-1b0d-bb20b0d7cbe5.png" width=60%>

パレットに含まれる色のピクセル数でヒストグラムを作ります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64694/f1ca4c3e-e32b-b85e-6193-e4f52bdbf05c.png" width=50%>

特徴量がうまく機能するのか確認するために、k-meansで3カテゴリにクラスタリングし、PCAで2次元に埋め込んで可視化してみます。（写真は私が適当に撮影したものです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64694/06095257-319e-ca3b-7e23-9c886313e203.png)



目論見どおり、うまく緑系、青系、茶系の3種類に分類されています。緑に分類されているmountain_path.pngですが、空（=青色）が多いため青に近い場所に位置しているのも良さそうです。

一方で、青色の少なそうなrobot.png（=地平ジュンこ）ですが、無彩色のパレットが不足しているため、グレーが青に分類されてしまっています。

# まとめ
画像検索のお試しとして、色をベースに特徴量を作り、クラスタリングしてうまく動作しているか確認をしてみました。筋は悪くなさそうだとは思いましたが、いくつか改善したい点もでてきました。

1. 無彩色系の色のパレットも必要
1. Perceptual uniformなカラーパレットのサンプリングが必要
1. 特徴量同士の距離の取り方。cosine 類似度 ($ = \phi \cdot \phi $ ) は類似するカラーパレットの類似度が考慮されないので、色空間の距離を重みに入れた方が良さそう

他の手法も色々と試してみたいですね。
環境変数の設定に困ったときに読むべき記事[備忘録]

この前[rbenv localでrubyのバージョンが変わらなかったので解決してみた](https://qiita.com/Ktsuki16/items/3dcfecac185006da5677)で、rubyのバージョンが変更できないエラーを解決しました。

ただ、ターミナルを再起動するとバージョンが戻ってしまうことや、そもそもexportとか環境変数とかについてよくわからないままだったので、今回は環境変数について調べてみました。


そこで以下の記事を見つけました。
・[PATHを通すために環境変数の設定を理解する (Mac OS X)](https://qiita.com/soarflat/items/d5015bec37f8a8254380)
・[.bash_profile ? .bashrc ? いろいろあるけどこいつらなにもの？](https://qiita.com/hirokishirai/items/5a529c8395c4b336bf31)

基本的に環境変数あたりのエラーに出会ったら上記の記事を読んでみるといいのかなと思いました。

記事の中により詳細な環境変数や.bashrc,.bash_profileの扱いについて書かれた記事へのリンクが貼ってあったりするので、また今度エラーに出会ったら参照しようと思います。

とりあえず、僕の現段階では開発を前に進められればいいので、source .bashrcを毎回実行してrubyのバージョンを変更しながら挑んでいこうかなと思います。

<h3>今回の記事で学んだこと</h3>
今回の記事で一番面白いと思ったのはexport -pコマンドでした。
このコマンドによって、どんな環境変数が定義されているのかをみることができます。

```
export -p

#出力結果一部抜粋
declare -x LANG="ja_JP.UTF-8"
declare -x LaunchInstanceID="70BE9758-E581-41F0-A8C7-1A5E8D7EC465"
```

環境変数の出力は全てexport -pで確認することができます。

自分でパスを設定したい時にもexportは使えるので詳細は[PATHを通すために環境変数の設定を理解する (Mac OS X)](https://qiita.com/soarflat/items/d5015bec37f8a8254380)こちらを読んだ方がいいのですが、またエラーに出会ったら読んでみようと思います。
openpyxlでエクセルの横幅を合わせる操作

エクセルを１行ずつ読み込み行の幅を行の最大文字数に合わせて
エクセルを開いた時に、全ての文字を見える状態にしたかった。
少しつまづいたのでメモで残しておきます。

```ruby:失敗例
wb = openpyxl.load_workbook('./targetExcelFile.xlsx')
ws = wb.worksheets[0]

for col in ws.iter_cols():
    max_length = 0
    column = col[0].column
    
    for cell in col:

        if cell.value == None:
            continue

        if len(str(cell.value)) > max_length:
            max_length = len(str(cell.value))

    ws.column_dimensions[column].width = adjusted_width
```


```ruby:実行結果
Traceback (most recent call last):
  File "pypy.py", line 10, in main
    ws.column_dimensions[column].width = adjusted_width
  File "/.pyenv/versions/3.7.8/lib/python3.7/site-packages/openpyxl/utils/bound_dictionary.py", line 25, in __getitem__
    setattr(value, self.reference, key)
  File "/.pyenv/versions/3.7.8/lib/python3.7/site-packages/openpyxl/descriptors/base.py", line 42, in __set__
    raise TypeError('expected ' + str(self.expected_type))
TypeError: expected <class 'str'>
```

エラーが出たので調査してみたら
こちらの記事が見つかった
https://teratail.com/questions/295219

記事の内容を見てみると...
> \-    ws1.column_dimensions[column].width = adjusted_width
> \+    ws1.column_dimensions[col[0].column_letter].width = adjusted_width
>openpyxl 3以降でcolumn_dimensionsの添字が列番号の数値から列名の文字列に変更されたから

だそうです。

```ruby:修正箇所
# 修正前
column = col[0].column

# 修正後
column = col[0].column_letter

```


```ruby:修正後コード
wb = openpyxl.load_workbook('./targetExcelFile.xlsx')
ws = wb.worksheets[0]

for col in ws.iter_cols():
    max_length = 0
    column = col[0].column_letter
    
    for cell in col:

        if cell.value == None:
            continue

        if len(str(cell.value)) > max_length:
            max_length = len(str(cell.value))

    ws.column_dimensions[column].width = adjusted_width
```

結果、問題なく修正が成功した。
MacでQiitaにアクセスできなくなった話

ある日突然Qiitaにアクセスしたとこ

インターネットに繋がっておりません　と表示されアクセスできず。

しかしiPhoneやwindowdからは問題なくアクセス可能といった状況。
ブラウザキャッシュクリアしたが改善せず。

MacBookの再起動でアクセスができるようになりました。
なんだったのだろう。
「10年使えるデータ活用システム」への一歩目

# 前書き
データ活用基盤開発やデータ分析コンサルなどを行っている統計屋のあんちべと申します。
本記事では、筆者らが12/5に出版した書籍「[実践]データ活用システム開発ガイド: 10年使えるシステムへのスモールスタート」を紹介します。
本書は「誰でも簡単にデータ活用ができるシステムを、少人数チーム・低コストという制約の中、将来的な拡張性を持った設計で開発・運用する」ための案内書です。
https://amzn.to/3itEm9d
<img width="300" src="https://www.tkd-pbl.com/files/%E3%80%90%E6%9B%B8%E5%BD%B1_%E5%B8%AF%E3%81%82%E3%82%8A(%E5%BA%83%E5%91%8A%E7%94%A8)%E3%80%91%E3%83%87%E3%83%BC%E3%82%BF%E6%B4%BB%E7%94%A8%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0.jpg">



# データ活用基盤とは

データ活用基盤とは、データ活用に関する様々な機能を有したシステムのことです。
具体的にどのような課題を解決すべく、どのような機能が求められるか説明します。

1. 必要なデータがどこにあるかわからない・アクセスできない → 社内に散らばるデータを一箇所に収集し、それを（適切な権限設定をしつつ）誰でもアクセスして閲覧できるようする
2. データの集計や加工、分析が大変 → SQLや色々な機能を用いて、誰でも簡単にデータの集計や加工、分析を行える
3. レコメンドやモニタリングなど高度なデータ活用がしたい。そのためにはデータの堅牢性（毎日必ず決まった時間にデータが用意されている、されなかった場合の自動対応がシステムとして組み込まれているなど）が必要 → データの状況監視や問題発生時の自動解決（失敗した処理を自動で再実行するなど）をシステムとして組み込む

本書ではこれらの内容について、解説→ハンズオン形式という流れで説明します。



# データ活用基盤開発の難しさと執筆の背景

データ活用に関する市場の声は年々大きくなってきています。高度な統計学や機械学習、また、AIやDXなどの話題に事欠きません。それらのデータ活用を実現するためには、兎にも角にもデータが必要です。
そして、データを用意するためには、データを収集・蓄積し、誰でも簡単にデータを集計や可視化できるようなシステムである「データ活用基盤」を開発することが大変有効です。


しかし、ここで大きな壁が立ちはだかります。実務のデータ活用では、AIの精度やデータ活用する人のスキルよりも、データ活用基盤を開発・運用する難しさこそがよくネックになります。なぜならば、データ活用基盤には「鶏が先か卵が先か」のような議論がついて回ってしまうからです。それは「どのようなデータ活用基盤があればいいのか、実際にデータ活用してみるまではわからない」と「データ活用するためには、まずデータ活用基盤がないと進められない」というループです。このループのせいで、ニーズを把握しないまま誰も使わないような重厚長大で扱いづらいデータ活用基盤を構築してしまったり、逆に、いつまでもデータ活用基盤がないまま現場のデータ活用者が非効率な作業に陥ってしまったりすることがよくあります。

筆者（と書籍の著者陣）も例外ではなく、各々でこのループに長らく苦しんで来ました。それでも、議論を重ね設計し、手探りで開発・運用を続け、時には設計レベルからの大きな変更を乗り越え、一歩一歩長い間改善を重ねることで、ようやく広く使われるような大規模なデータ活用基盤へと成長させることに成功しました。

筆者らは「この成功まで長い道のりの知見が、もし10年前にあったならば…」と痛切に思うようになりました。そんな思いを抱いていたある日、著者陣の1人である徳永氏が「この知見をぜひ共有したい」と筆者らに呼びかけ、「データ活用システム開発ガイド」を執筆することになりました。


# 本書のコンセプトについて

### 本書の目指すデータ活用基盤の方向性と完成度
データ活用基盤において、データそのものや利用者のニーズは様々なため、唯一無二の正解はなく、また「どんな時も100点満点の万能策」もありません。
そこで、筆者らは「大抵のケースで80点が取れるような汎用的な基礎、さらには将来的に95点が目指せるような段階を追ったデータ活用基盤開発の道のりを、誰もが知り得ること」を目指しました。

本書は主にGoogle Cloudを用いて説明しています。ただし、汎用性を目指しているため、Google Cloud特有の機能を利用することはほぼなく、容易にAWSやAzureなどへ移行可能なシステム構成を取っています。


### 本書の構成
本書は2部構成になっており、第1部でシステム化されていない状況からごく少人数・省コストで最低限稼働するデータ活用基盤開発を目指します。2部では1部で開発した基盤をより堅牢かつ多機能なシステムにすべく発展させる内容になっています。
このようにして、データ活用を検討する企業の成熟度次第で発生し得る様々なシチュエーションに対応できる構成を目指しました。


# 終わりに
本書はかなり地味で泥臭い本です。高度なトピックスや最新情報が網羅された書籍ではありません。それらは、言い換えるなら、データ活用の遥かなゴールを目指すための書籍といってもいいでしょう。
それに対して本書は、データ活用の一歩目を踏み出し、その歩みがその先へと続くための指針を得るべく、コスパよく最低限稼働するデータ活用基盤を開発し、そこで売上貢献し基盤の価値を全社的に認められ、徐々にシステムもチームも大きくする…という流れを目指して執筆しました。
本書が暗中模索のデータ活用へ果敢に挑もうとされる皆さんへのコンパスになることを心から願っています。


### 謝辞
本記事を作成するにあたり、SinkCapitalの @Booklin からアドベンドカレンダーの紹介を頂きました。本書の内容が、様々な規模や課題についてデータ活用を用いた解決を行うSinkCapitalのコンセプトに合致すると思い、喜んでJoinさせて頂きました。
ぜひ「今後データ活用基盤を開発したい」、あるいは「今あるデータ活用基盤をより良いものにしたい」とお考えの方に本記事が届けばと願います。
変数の変更を検知させる JavaScript

# はじめに
筆者はこれまで Vue などのライブラリ上でウォッチャーや算出プロパティを使用して変数の検知を行ってきた。
しかし今回、業務上でモダンなライブラリが使えなく、バニラのJSでの実装が必要になったためメモ。

## 実装方法
対象の値を保持させて新しい値と比べれば変更が認識できる。
監視し続けなくてはならないのでとりあえずタイマーを貼って監視する。
※タイマーなので実行され続けるのでご注意ください

```.js
// 検知関数
const observer = (getValueFunc, onChangeFunc, intervalTime) => {
  let previousValue = getValueFunc();
  const onObserve = () => {
    const currentValue = getValueFunc();

    // 変更がない時は何もしない
    if (previousValue === currentValue) {
      return;
    }
    onChangeFunc(currentValue);
    previousValue = currentValue;
  };

  setInterval(onObserve, intervalTime);
};

// 試しに実行
(function () {
  // 検知対象
  let targetValue = "初期値";
  // 検知間隔
  const intervalTime = 100;

  // 変更検知の対象の取得
  const getValueFunc = () => {
    return targetValue;
  };
  // 変更検知時の処理
  const onChangeFunc = (changeValue) => {
    console.log(`変更後の値は${changeValue}`);
  };

  observer(getValueFunc, onChangeFunc, intervalTime);

  // 値を変更させてみる
  targetValue = "変更後";
})();

```
Node.jsを使って、BigQueryからデータを取得するWebAPIを作る

## はじめに

これは 株式会社 RetailAI X Advent Calendar 2022 の 7 日目の記事です。
昨日は @murayamaxxx さんの記事でした。 [entで実行されたSQLを確認する](https://qiita.com/murayamaxxx/items/58dcff1e928977af559f)

本日は『Node.jsを使って、BigQueryからデータを取得するWebAPIを作る』です。

昨今、日本の企業間でクラウド化が進んでおり、一つのシステムを作るときGCPやAWSといったクラウドサービスと連携させた機能を実装する場面が増えてきているのではないかと感じます。

今回はGCPのBigQueryからデータを取得する簡単なWebAPIをNode.jsで作成してみました。

## 前準備
- BigQueryで任意のデータセット、テーブルを作成する
- 適切な権限を付けたサービスアカウントを作成し、jsonキーを任意のディレクトリにダウンロードする
- 開発するディレクトリを準備し、Node.jsの環境を構築する
```
mkdir test
cd test
npm init -f
npm install --save @google-cloud/bigquery,express
vi sample.js
```


## BigQueryからデータを取得する部分を実装する
Node.jsでGCPのサービスを使うためのライブラリが豊富にあるので、BigQueryのライブラリを使って実装していきます。
```sample.js
const { BigQuery } = require('@google-cloud/bigquery');

const bigquery = new BigQuery({
    projectId: 'xxxxxx-xxxxxx-xxxxxx',
    keyFilename: 'xxx/xxx/xxx.json'
});

const query = "SELECT * FROM test_dataset.test_table";

bigquery.query(query)
    .then(data => {
        const rows = data[0];
        rows.forEach(row => {
            console.log(JSON.stringify(row));
        })
    })
    .catch(error => {
        console.log(error);
    });
```
BigQueryへのアクセスには必ずjsonキーが必要になります。
```json
node sample.js

{"id":1,"name":"加藤","gender":"man"}
{"id":3,"name":"小松","gender":"man"}
{"id":2,"name":"関","gender":"woman"}
{"id":4,"name":"馬場","gender":"woman"}
```

## WebAPIを実装する
Node.jsのExpressというWebアプリケーションフレームワークを使っていきます。
Node.jsで多く利用されている3大フレームワーク(Express,Meteor,Sails)の一つで、
GET/POST通信などを簡単な記述で実装できる魅力があり、今回の実装でもその魅力を活用しています。
```javascript
const express = require("express")
const app = express();

app.get("/test/:gender", (req, res) => {

    const { BigQuery } = require('@google-cloud/bigquery');

    const bigquery = new BigQuery({
        projectId: 'xxxxxx-xxxxxx-xxxxxx',
        keyFilename: 'xxx/xxx/xxx.json'
    });

    const query = "SELECT ARRAY(SELECT name FROM test_dataset.test_table WHERE gender = '" + req.params.gender + "') AS human_list";

    bigquery.query(query)
        .then(data => {
            const rows = data[0];
            rows.forEach(row => {
                console.log(JSON.stringify(row));
                res.send(row);
            })
        })
        .catch(error => {
            console.log(error);
        });
});

app.listen(8080);
console.log("server listening...");
```
GETリクエストの際にgenderをman/womanで指定するとman/womanの名前がリストでレスポンスされる仕様です。
動作確認
http://localhost:8080/test/man
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3024825/47affa20-c499-fcdb-9d3e-49463657fb6e.png)

## 終わりに
Node.jsにあるExpressなどのフレームワークを使用すると、比較的簡単にWebAPIを作成できる印象で、
GCPなどのクラウドサービスと連携させた機能について、BigQuery以外にも試してみたいと感じました！！

明日 8 日目の記事は @atsukish さんの　『【MLOps】Vertex AIによるモデルモニタリングサービスの構築』　です。
個人的にもMLOpsに興味があるので楽しみです！次回もお楽しみに

## 参考
https://cloud.google.com/nodejs/docs/reference/bigquery/latest

https://qiita.com/nkjm/items/723990c518acfee6e473
さくらのレンタルサーバにPHP-sodium 拡張を入れようと思ったらてこずった話(解決編)

Laravelにて開発中のアプリケーションでJWTを使おうと思ったら、PHP-sodium が入ってないよって怒られた。

いまくいかなくて悩んでたら、@KCApps さんが助けてくれた話

[さくらインターネットのレンタルサーバーにsodium拡張をインストールする方法](https://www.kcapps.net/%E3%83%AC%E3%83%B3%E3%82%BF%E3%83%AB%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC/%E3%81%95%E3%81%8F%E3%82%89%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E3%83%AC%E3%83%B3%E3%82%BF%E3%83%AB%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%ABsodium%E6%8B%A1/)

## とりあえず結論

make じゃなくて gmake を使うとうまくいく
※ PHP8.3環境です。適宜バージョン調整してください。

```
# 作業用ディレクトリの作成
mkdir -p {~/usr/local/src,~/usr/local/php/extension}

# libsodium のダウンロードとコンパイル
cd ~/usr/local/src
wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.20.tar.gz
tar xzvf libsodium-1.0.20.tar.gz
cd libsodium-1.0.20
./configure --prefix=$HOME/usr/local
make && make check
make install

# PHP拡張のダウンロード＆コンパイル
cd ~/usr/local/src
wget https://github.com/php/php-src/archive/php-8.3.8.zip
unzip php-8.3.8.zip
mv php-src-php-8.3.8/ext/sodium ./sodium-php-8.3.8
cd sodium-php-8.3.8
/usr/local/php/8.3/bin/phpize
./configure --with-php-config=/usr/local/php/8.3/bin/php-config --with-sodium PKG_CONFIG_PATH=$HOME/usr/local/lib/pkgconfig/ LDFLAGS=-L$HOME/usr/local/lib/
make
gmake test

# インストール
cp modules/sodium.so ~/usr/local/php/extension/sodium.so
cat <<EOF >> $HOME/www/php.ini
extension=$HOME/usr/local/php/extension/sodium.so
EOF

# 確認
php -c ~/www/php.ini -m | grep sodium
# sodium と表示されればOK
```

### CLIで ~/www/php.ini を読み込む設定を追加（Optional）

```
cat <<EOF >> $HOME/.bash_profile
export PHP_INI_SCAN_DIR="$HOME/www/"
EOF

source ~/.bash_profile
php -m | grep sodium
# sodium と表示されればOK
```

## Waht's sodium?

> Sodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing, and more.

Sodium は、暗号化、復号化、署名、パスワード ハッシュなどのための最新の使いやすいソフトウェア ライブラリです。

これをPHPで利用するための拡張が PHP-sodium だそうな。
具体的にはJWTで `EdDSA signer` に対応する際に導入されたらしい。

うごかすためには、レンタルサーバに `Libsodium` と PHP拡張のコンパイルが必要。
かつて `intl` を入れるときにやった手順と同じような感じでできるやろう。と気軽に考えていたらどん詰りました。
改めて見返すと、 `intl` のときも `gmake` 使ってました。思い込みダメゼッタイ。

```
# スペック確認
$ uname -a
FreeBSD www0000.sakura.ne.jp 11.2-RELEASE-p16 FreeBSD 11.2-RELEASE-p16 #2: Mon Dec  9 13:33:15 JST 2024     (中略)  amd64

$ php -v
PHP 8.3.8 (cli) (built: Jun 11 2024 22:17:58) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.8, Copyright (c), by Zend Technologies
```

## make と gmake

Ref: https://system.blog.uuum.jp/entry/make

> make は歴史が長く、何度も rewrite されているので、様々な実装が存在します。基本的な処理は同じですが、実装によって処理が多少異なります。 主な実装は次の3つぐらいかなと思います。
> 
> - System V make
> - BSD make
> - GNU make
> 
> System V の make は恐らくオリジナルの実装に一番近いんじゃないでしょうか。僕は使ったこともないので詳細はわかりません。 BSD系UNIXを使っている方は BSD make を使う機会が多いんじゃないかと思います。
> 
> 最近のUNIX環境では、GNU make ほぼ一択じゃないでしょうか。機能的にも一番上だし、UNIX環境だとほぼ使えるし。

実装の違いにより、動作が変わってしまうのですね。
gmakeのほうがより一般的というか、環境に依存しない挙動が期待できるみたいなので、そちらを使用したほうが安定するみたいです。


## Special thanks!

@KCApps @imagou