OmniAICreator/Qiita-1.07M huggingface dataset:
「Interview with Vadim Pisarevsky on class cv::Mat in OpenCV」を読み解く

この記事は[OpenCV Advent Calendar 2022](https://qiita.com/advent-calendar/2022/opencv)の22日目の記事です。

## 1. はじめに

<https://www.youtube.com/watch?v=DEWr-iOEuvE>にてOpenCV Development Team LeaderであるVadim Pisarevskyさんのインタビュー動画が公開されており、そこで`cv::Mat`の設計経緯が語られています。古くからOpenCVを使っている人、最近OpenCVを使い始めた人どちらにも興味深い内容だと思われるのでこの動画の内容を紹介していきます。<br><br>

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

## 2. IplImage時代

- OpenCVはIntelのIPL(Intel Image Processing Library)に追加する形で開発が始まったため、OpenCV開発初期のデータ構造はIplImageであった
  - <https://docs.opencv.org/2.4.13.7/modules/core/doc/old_basic_structures.html#iplimage>
- しかし、コンピュータビジョンの用途で使うにはIplImageでは不十分であることがわかった
  - カメラ幾何を扱おうとすると汎用的に行列を扱えるクラスが必要
  - 3次元以上の多次元配列が必要
- そのような背景もあり、CvMat、CvMatND、CvSparseMatを追加した
  - <https://docs.opencv.org/2.4.13.7/modules/core/doc/old_basic_structures.html#cvmat>
  - <https://docs.opencv.org/2.4.13.7/modules/core/doc/old_basic_structures.html#cvmatnd>
  - <https://docs.opencv.org/2.4.13.7/modules/core/doc/old_basic_structures.html#cvsparsemat>
- ・・・が、IntelはIPLの開発を停止したため、IPLとの互換性を維持する必要がなくなった

## 3. IplImageからcv::Matへ

- 2008年にWillow Garageが資金提供を開始し、リソースも増えたので、以前から要望があったC++ APIを追加するためにOpenCVを再設計することにした
- C++ API設計の参考になるものを探していたところ、MATLABが非常に良い例であることわかった
  - MATLABのmatrixやarrayのデータ構造はツールボックス間で共通であり、互換性に優れている
  - 画像、行列を同じデータ構造で扱え、変換処理が不要
- そのため、MATLAB APIを参考にしてC++でcv::Matを実装し、IplImageから置き換えることにした

## 4. Q&A

### 4.1 cv::Matでスマートポインタを使わなかったのはなぜ?

- スマートポインタが使えるようになるのはC++11からだが、cv::Matを作ったのが2009年。C++11が標準化されるまでcv::Matの開発を待つことができなかった
- メモリ管理については参照カウントを使った実装を独自に入れているが、開発初期からアトミック操作となるようなメカニズムで実装したため、cv::Matは複雑なアーキテクチャになっている

### 4.2 cv::Matをテンプレートクラスにしなかったのはなぜ?

- テンプレートクラスにするとコンパイルに時間が掛かるため
- Pythonにテンプレートがないため。当時からPythonに注目していたが、cv::MatをテンプレートクラスにしてしまうとPythonラッパーが実現しにくくなるため採用されなかった。

### 4.3 なぜcv::Mat_\<T\>を作った？

- 要素にアクセスする便利な操作を提供するため
- この機能を使うとOpenCV内部のコード量が減らせる、くらいの意味合いが強い

### 4.4 cv::Matは異なるデバイスのメモリをサポートできるようになる？

- GPUなどのアクセラレータでコンピュータビジョンの処理を高速化するのがトレンドであることを理解している
- 10年ほど前にこれから標準になるであろうOpenCLをサポートしようという話になり、UMatを実装した
  - <https://opencv.org/opencl/>
  - <https://docs.opencv.org/4.6.0/d7/d45/classcv_1_1UMat.html#a5111ebd4f3199062e3205e4791f00542>
- ・・・が、OpenCLは今や半ば放棄された規格になってしまっており、多くのメーカーは他のフレームワーク（Vulkanなど）を使おうとしているように見える
- 現状、皆がそれぞれ異なるフレームワークを使っていて今後どのAPIに依存するかわからないため、cv::Matを異なるデバイスで汎用的に使えるユニバーサルなクラスにするのは難しい状況であると考えている

### 4.5 cv::Matのアップデート計画

今のところ、cv::Matから新しいものに完全に置き換えるような計画はないが、以下のようなアップデートを予定している。

- BFloat16(<https://cloud.google.com/tpu/docs/bfloat16>)サポート追加
  - GoogleのTPUやIntelのハードウェアでサポートしている
- 1-dimensional tensorsサポート追加
  - ディープラーニング分野のニーズに合わせて
- cv::Matにデータの中身を表すようなタグを追加
  - 例えば、データの中身がRGBなのかBGRなのかを表すタグ <https://github.com/opencv/opencv/wiki/OE-5.-OpenCV-5#extended-set-of-basic-types-built-in-color-space-information>
  - 意図せず不適切なチャンネルの画像を入力するとDNNで得られる精度が低下してしまうため、このタグを使ってチェックするとこの問題を防ぐことができるはず

## 5. おわりに

この記事では「Interview with Vadim Pisarevsky on class cv::Mat in OpenCV」の動画の内容を紹介しました。間違っている箇所があればコメント等でフィードバックください。
[Day25] 最後に

本記事は一人アドベントカレンダー企画の一つです。
[30代未経験エンジニアが25日後にJavaScriptをマスターするカレンダー](https://qiita.com/advent-calendar/2022)

[JAVASCRIPT.INFO](https://ja.javascript.info/)を元にJavaScriptを勉強していき、そこで学んだ知識をアウトプットしていきます。
２５日でJAVASCRIPT.INFOをやりきり、未経験エンジニアがJavaScriptをマスターする過程を投稿していきます。



## アドベントカレンダー
### 最後に
私のアドベントカレンダーをここまで読んでくださり、ありがとうございます。

[JAVASCRIPT.INFO]の全てを記事で書くことはできませんでしたが、今後もjavascriptの勉強は続けていきます。
特に正規表現などは、javascriptに限らず使うものなので、必ず習得したいと思います。
これまで学んできたところでも、ドキュメントの概念や役割は何回も復習して理解していかなければいけない程難しいと思いました。

javascriptの基礎が理解できた後は、React.jsの記事を書きながら勉強をしていく予定なので、また機会があれば記事を読んでいただけたら嬉しいです。

ありがとうございました。
djangoのDB操作で私が気にかけていること

最近会社内のサイトリニューアルに追われる日々です。
実務で機能の一部にしろリプレースする際のDB設計は、一番脳のメモリを食いますね。
それでも大体作ってて、設計を見誤ることが多いです。

さて今回は、djangoのDB操作上、常々気をつけていることを載せまーす。
（決してアドベンドカレンダーのネタがなかったとかじゃないよ）

## N+1にならないようにする。
動作が遅いと思った瞬間、N+1ではないか疑って欲しい。（indexがうまく付けれてないとかもあるけど）
djangoのadmin画面とか気をつけないと、普通にN+1になってたりするので・・・。
そのためにも絶対settingsにDBのはつけるべき。
``` python:settings.py
LOGGING = {
    'version': 1,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        }
    },
    'loggers': {
        'django.db.backends': {
            'level': 'DEBUG',
            'handlers': ['console'],
            "propagate": False
        },
    }
}
```

複数回テーブルが呼ばれている時は、prefetch_relatedかselect_relatedを設定すべし。
```python:
def hoge():
    db.objects.select_related('parent').prefetch_related('child_set').all()
```

現職場において、「サーバーサイドで一番もっさりする作業はDBとの通信じゃ！」と教わった人間からすると、
日々いかにSQLの回数を減らせるかが見せどころだと思っている。


## bluk_updateとbluk_createを多用しろ。
実際DBに書き込む際に複数回想定してなくても、絶対updateとcreateは一回で済ませれるように設計から考慮しろ。
ロジック的に無理な時以外は認めるべきじゃない。
```python
from django.db.models import QuerySet
from dokano.models import Huga, Hoge

hugas:list = [] # setに変えたらユニークしてくれるかな？と思っても意外としてくれないから気をつけて
for r in range(100):
    hugas.append(Huga(title=f'huga{r}'))

Huga.objects.bulk_create(hugas)

# bluk_update
hoge_set: Queryset[Hoge] = Hoge.objects.all() #　ちゃんと型はつけような
for h in Hoge.objects.all():
    h.active = True

Hoge.objects.bulk_update(hoge_set,fields=["active"])
```

## exsits()とcount()は使わない。
「querysetを使え、querysetを」
この方の記事が一番参考になりました。
[querysetの存在確認にexists()とcount()はどちらの方が早い？](https://chico-shikaku.com/2020/01/queryset-which-exists-count/)
[exists()を使うよりもif querysetの方が実は早い？公式ドキュメントとは逆](https://chico-shikaku.com/2020/01/if-queryset-more-than-exists/)

もしかして以下のようなコード書いてないよね？
```python
qs = Fuga.objects.all()

# exsitsの場合
if qs.exists():
    pass
# ↓ こっちじゃない？
if qs:
    pass

# return で　exists()使ってる場合
return qs.exists()
# ↓ こっちじゃない？
return bool(qs)


# 個数が欲しくて、脳死でcount()した場合
return qs.count()
# ↓ こっちじゃない？
return len(qs)

```

ちなみに記事書いた人に習ってテストケースを書いてみたけど

```python
def setup():
    for _ in range(100):
        HogeFactory.create()

def test_bool_queryset(self):
    setup()
    hoge_all = Hoge.objects.all()
    start = time.time()
    for i in range(10000):
        if bool(hoge_all):
            pass
    process_time = time.time() - start
    print('time:', process_time)

# time: 0.020615577697753906
# time: 0.013532400131225586
# time: 0.01642584800720215

def test_len_queryset(self):
    setup()
    hoge_all = Hoge.objects.all()
    start = time.time()
    for i in range(10000):
        if len(hoge_all):
            pass
    process_time = time.time() - start
    print('time:',process_time)

# time: 0.014984607696533203
# time: 0.01348114013671875
# time: 0.015105962753295898

```

といった感じ。これをみた後に　`exists()`　と　`　count()`　を使うってことはないよね・・・。

## 最後に
みなさんのDB上、気をつけておきたいことがあれば、ぜひ教えてください。

あと、どうでもいいこと言っていい？
「ぼっち・ざ・ろっく」のギターサウンド痺れません？
OPとかエンドレスに聴いていられます。「あのバンド」とか青春腐ってた人間には染み渡る。
令和の「けいおん」とか言ってますけど、音楽性的には個人的には「涼宮ハルヒの憂鬱」なんだけどねー。
ReactHooksについてまとめる（Other Hooks useDebugValue）

# 概要

ReactHooksの[Other Hooks](https://beta.reactjs.org/apis/react#other-hooks)についてのメモ記事です。基本的にReactの公式ドキュメントの咀嚼記事となっています。

今回はuseDebugValue編です。

## useDebugVlue
useDebugValueは、React DevToolsのカスタムHookにラベルを追加するためのReact Hookです。

### カスタムHookにラベルを追加する
useOnlineStatusを呼び出すコンポーネントには、
OnlineStatus: "Online "のようなラベルが表示されます。

```jsx
import { useDebugValue } from 'react';

function useOnlineStatus() {
  // ...
  useDebugValue(isOnline ? 'Online' : 'Offline');
  // ...
}
```

![スクリーンショット 2022-12-21 1.16.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154845/f09ca6fb-dd17-5d8f-1a5d-f02df4963fc6.png)

### デバッグ値のフォーマット関数を使用できる
useDebugValueはフォーマット関数を受け取り、コンポーネントが検査される時、React DevToolsはフォーマット関数を呼び出し、その結果を表示させることができます。

```jsx
useDebugValue(date, date => date.toDateString());
```

![スクリーンショット 2022-12-21 1.22.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154845/57748541-e274-a9df-ae09-efb606df2aec.png)


### 最後に
useDebugValueは特に使用する必要はなく、複雑なフック時やフックの状態が明らかになっていなく確認したい場合のみ必要になる時があるかもしれません。

## 参考
https://beta.reactjs.org/apis/react/useDebugValue
DenoでChrome拡張機能のプロジェクトテンプレートを作りました

Denoを使ったChrome拡張機能のプロジェクトテンプレートを作成したので紹介です。

https://github.com/keyhole0/ChromeExtensionTemplateForDeno

概ね次のようなことが達成できています。
- denoツール以外の依存関係無し。
- Manifest V3
- Typescriptサポート
- 主要なグローバル変数の型安全サポート
- Javascriptファイルへのビルド
- VSCodeの設定諸々

かなり簡素ですが、必要最低限は揃っていると思います。

# 前提
Deno:`v1.29.1`で動作確認しています。

え？Denoをまだ入れていない？
こちらから秒でインストールできますよ！
https://deno.land/manual@v1.29.1/getting_started/installation

# ビルド方法

```
deno task build
```
アウトプット先は`/dist`にしています。このファイルをchromeで読み込んでください。

ビルドにはこんなスクリプトを用意しました。

```jsonc:deno.jsonc
{
  "tasks": {
    "build": "rm -rf ./dist/ && cp -r ./public ./dist && deno bundle ./src/content.ts ./dist/content.js & deno bundle ./src/background.ts ./dist/background.js"
  }
}
```

処理ごとに分解するとこんな感じです
```bash
rm -rf ./dist/ # distディレクトリリセット
cp -r ./public ./dist # public内容をdistにコピー
deno bundle ./src/content.ts ./dist/content.js # content.tsをcontent.jsにバンドル
deno bundle ./src/background.ts ./dist/background.js # background.tsをbackground.jsにバンドル
```

chrome extensionの最小構成はmanifest.jsonとjsファイルがあれば良いので、jsファイルを`deno bundle`で作ります。

# 主要なグローバル変数の型安全サポート
主に以下のグローバル変数の型安全が効くようになっています。
- `chrome`
- `Document`や`Element`等のWeb標準型

型の設定はこちらに定義しています。
```jsonc:deno.jsonc
{
  "compilerOptions" :  {
    "lib": [ "dom" ,  "dom.iterable" ,  "dom.asynciterable" ,  "deno.ns" ],
    "types": [
      "https://unpkg.com/chrome-types@0.1.153/index.d.ts"
    ]
  }
}
```

`lib`で指定しているのはdenoの標準ライブラリです。DOM等は標準でサポートされています。
`chrome`は[npmの`chrome-types`](https://www.npmjs.com/package/chrome-types)を利用しています。
なので本来なら`npm:chrome-types`で型解決できるはずなのですが、残念ながら`deno bundle`はまだnpmに対応していないようです。
今回見つけたnpm参照の回避策は urlでコードがそのまま参照できる https://unpkg.com を利用しました。
この手は他でも使えそうです。

# VSCode設定
別途[deno拡張](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)も必要です。

以下の設定を有効にしてあります。
- Deno有効化
- Lint有効化
- フォーマット自動保存有効化

設定ファイルはこんな感じです。
```json:.vscode\settings.json
{
  "deno.enable": true,
  "deno.lint": true,
  "editor.formatOnSave": true,
  "[typescript]": { "editor.defaultFormatter": "denoland.vscode-deno" }
}
```

フォーマットの設定はこちら
```jsonc:deno.jsonc
{
  "fmt": {
    "files": {
      "include": ["src/"],
      "exclude": ["src/testdata/"]
    },
    "options": {
      "useTabs": false,
      "lineWidth": 80,
      "indentWidth": 2,
      "singleQuote": true,
      "proseWrap": "always"
    }
  }
}
```

# 直近の不満点・改善点
- ビルドファイルのマッピングが分かりづらい
- フロント周りのサポートが無い

まだまだたたき台程度なので改善点はもっと出ると思いますが、気になるところは適宜改善していきます。
Azure Monitorの機能の１つ「アラート」について

●アラート
Azure Monitorの機能の１つにアラートがある。使用すれば、Azure Monitorによって収集されるログやメトリックに関する条件指定を行い、その条件に一致する状況が発生したときに特定のアクションを自動的に実行できる。

・スコープ
アラートを出す対象の範囲を指定する。Azureに存在するサブスクリプションやリソースグループ、あるいは任意のAzureリソースを指定できる。

・条件
アラートを出す条件を指定する

※１つのアラートルールの条件内に複数のメトリックシグナル(最大５つまで)を指定可能だが、その場合にアラートルールがトリガーされるには全ての条件が満たされる必要がある。また１つのアラートルールの条件で指定できるアクティビティログシグナルは１つだけであり、2つ以上のアクティビティログシグナルを指定することはできない。
メトリックシグナルとアクティビティシグナルの同時指定はできない。


・アクション
条件に一致したときに自動実行する内容をアクショングループという単位で指定。
アクショングループには通知を送信したりAutomation Runbookなどを呼び出すための構成情報が含まれる。
日常の育児でリサーチの手法を知らず知らずのうちに試していた話

この記事はHRBrain Advent Calendar 2022カレンダー1の24日目の記事です。
https://qiita.com/advent-calendar/2022/hrbrain


## はじめに


こんにちは、HRBrainでプロダクトデザイナーをしています@mioinです。


今年一年を振り返ると、2022年は0→1の開発に携わっており
その過程でユーザーヒアリングやユーザビリティテストなどを用いて検証し、PdMと協働しながら、UIデザインに繋ぎ込みをする機会がかなり増えた一年だったなあと思います。
自分はHRBrainに来るまでは別業界におり
入社してから初めてUXリサーチというものに触れました。
（以下の記事でも別業界から来た所感等を書いています）
[別業界からきて４ヶ月！今思っていること](https://times.hrbrain.co.jp/entry/4months)

UXリサーチについて補足すると
UXリサーチはプロダクト開発の過程で定性的な情報をヒアリングやリサーチなどで集めながら
ユーザーが抱えている要求だけではなく、その人が抱える心情までを読み解き
仮説を立ててそれを検証することを繰り返しながら、適切な改善策を探っていくことを目指しています。
また、それにより何を作るのか・作らないのかを決める判断情報を得られるため
プロダクト開発をする上で重要なプロセスと言えます。
企業によっては専任のリサーチャーを雇用するなど、近年徐々に注目度が上がってきているなと感じています。

UXリサーチという言葉だけを見ると、すごく難しそうでハードルが高く感じてしまいますが
プロダクト開発のためだけのものではなく、普段の生活の中でもリサーチの機会は転がっています。
なので今回は手法の紹介というよりは
身近なところにもリサーチの機会はあるよ、という話を書こうと思います。

### 虚無Tubeって知ってますか？

突然ですが「虚無Tube」という言葉をご存知でしょうか。

虚無Tubeとは、
>「無暗に付けられた効果音はひたすらうるさく」
「視覚的に美しくなく、聴覚的にも聴きやすさがなく、内容も面白くない」

上記のような動画を指し、大人には理解し難い世界観を持っています。
詳しく知りたい方は以下を読んでみてください。

引用元：[子どもに人気、YouTubeで数千万回も再生される「虚無動画」 大人はカオスしか感じないのに幼児が夢中になる理由](https://news.careerconnection.jp/entame/49913/)

息子は虚無Tubeの中でも、踏切のボディ部分が左右に激しくスウィングして踊り狂ったり
なぜか踏切達が集まってランチをする...
という謎の世界観が繰り広げられている動画が好みのようですが
親の目線では、内容的にもリビングで流しっぱなしにするのは辛い思いがあり
「観せるのであればもっと安心して流せる動画はないだろうか...？」と
日々悶々と考えていました。

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

サムネの時点で既に色々ツッコミたい。


### 実は日常生活でも課題を発見しヒアリングをしている

そんなタイミングで、同級生の親同士で話す機会がありました。
虚無Tubeから抜け出せない、という悩みを話した時に
「YouTubeのキッズアプリから見せたい動画だけ視聴制限モードで選んでるよ」
という知見を得ました。
「視聴制限モード、そういうのもあるのか」という気持ちになりつつも
「息子が好きなあの国民的人気キャラクターの動画を登録しておけば、虚無Tubeがサジェストされないのではないか？」という仮説を得ました。

早速検証してみたところ、見事に虚無Tubeはタイムラインから姿を消し
安心して動画を観せられるようになりました。

### 知らず知らずにリサーチから仮説検証をしていた

結局YouTubeの使い方の話かい！というツッコミが聞こえてきそうですが・・・。

誰かの話を聞き、それを自分の育児でも検証する、という手法はかなり日常的に行なっていることですが
課題を発見し、ヒアリングやインタビューで得た仮説を
日常で検証する一連の流れの中で知らず知らずのうちにリサーチの手法を試していることに気づきました。
![Frame 8997.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294721/d0bb3558-a018-0df2-4b38-79aa78a13a58.png)


もちろん実際のプロダクト開発は、より複雑なリサーチプロセスを踏むことにはなりますが
リサーチ手法で出てくる難しい言葉を日常生活に置き換えるとイメージがつきやすくなり
UXリサーチをより身近に感じることが出来るのではないでしょうか。

### さいごに
UXリサーチに関しては、カスタマーサクセス、セールスと連携を取りながら進められており
開発だけではなくビジネスサイドとプロダクトを作っている感覚があり
個人としてもここに非常に面白みを感じています。
UIデザインのみならず、UXリサーチにも幅広く興味がある方、ぜひご応募お待ちしております！

https://www.hrbrain.co.jp/recruit
ReactHooksについてまとめる（Performance Hooks useDeferredValue）

# 概要

ReactHooksのPerformance Hooksについてのメモ記事です。基本的にReactの公式ドキュメントの咀嚼記事となっています。

今回はuseDeferredValue編です。

## useDeferredValue

### 新しいコンテンツがロードされているときに古いコンテンツが表示される

UIの一部の更新を遅延させるために、コンポーネントのトップレベルでuseDeferredValueを呼び出します。


例を見たほうがわかりやすいので、一気に例から見てみます。

https://codesandbox.io/embed/priceless-cannon-lcqe7b?fontsize=14&hidenavigation=1&theme=dark

この例では、検索結果を取得する際に、useStateの更新関数のsetQueryによって、Suspenceが発火し、`Loading...`が表示するようにfallbackされます。

このコード内で、useDeferredValueを使用して、クエリの遅延の際に、古い結果を表示させるようにします。

```jsx
export default function App() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  return (
    <>
      <label>
        Search albums:
        <input value={query} onChange={e => setQuery(e.target.value)} />
      </label>
      <Suspense fallback={<h2>Loading...</h2>}>
        <SearchResults query={deferredQuery} />
      </Suspense>
    </>
  );
}
```

クエリはすぐに更新されるので、入力には新しい値が表示されます。しかし、deferredQuery はデータがロードされるまで以前の値を保持するので、SearchResults は少しの間、古い結果を表示します。

下の例で "a" と入力し、結果がロードされるのを待ってから、入力を "ab" に編集してください。サスペンスのフォールバックではなく、新しい結果が読み込まれるまでの間、古い結果のリストが表示されることがわかります。

https://codesandbox.io/embed/modest-napier-qzlby7?fontsize=14&hidenavigation=1&theme=dark


## 参考
https://beta.reactjs.org/apis/react/useDeferredValue
【M5Stack 2022】わりと最近ポチった「 #M5Stack 用計量ユニット 20kgレンジ（HX711）」を #UIFlow で使ってみる

## はじめに
こちらは、[M5Stack Advent Calendar 2022](https://qiita.com/advent-calendar/2022/m5stack) の 21日目の記事です。

内容は、スイッチサイエンス さんのサイトでわりと最近ポチっていた、
「M5Stack用計量ユニット 20kgレンジ（HX711）」を UIFlow で使ってみたというものです。

●M5Stack用計量ユニット 20kgレンジ（HX711） — スイッチサイエンス
　https://www.switch-science.com/products/8498

## 試した内容の動画
最初に、今回のお試しをした結果を、動画で示します。
近くにあった 600ml のペットボトルのお茶を使って試したのですが、おおよそ 600グラムくらいの数値が出ました。

https://twitter.com/youtoy/status/1605217722979078146

## UIFlow で「M5Stack用計量ユニット 20kgレンジ（HX711）」を使う
今回、M5Stack Core2 を使い、UIFlow で「M5Stack用計量ユニット 20kgレンジ（HX711）」を使うためのプログラムを作りました。

### ファームウェアについて
そのための下準備として、M5Burner で UIFlow用のファームウェアを書きこみます。ファームウェアについて、バージョンが v1.10.5.1以上という条件がつくようなので、ご注意ください（※ 以下は、UIFlow で表示される、バージョンの制約に関するテキストです）。
![バージョンの話](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/acca8950-b4d4-0391-8acd-ecd64d57a693.png)

### UIFlow でプログラムを作る
それでは、UIFlow でプログラムを作っていきます。

ユニットの一覧から SCALES を選ぶと、「M5Stack用計量ユニット 20kgレンジ（HX711）」を扱えるようになります。
![ユニットの一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/b7cccef1-9e51-674c-59d7-9b00daad8b5b.png)

その後、「Load Examples」という部分を押すと、サンプルプログラムを読み込むことができます。
![Load Examples](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/c07466df-9e8b-543e-3c3c-29570f18bc12.png)
※ https://flow.m5stack.com/?examples=unit_scales_demo という URL にアクセスすることでも、見ることができそうです

サンプルとして、以下のような内容が出てきます。
![サンプル](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/57eccd24-5c3c-1342-2489-f670855f0aff.png)

プログラムを見てみると、フルカラーLED に関する処理など、重さを計測する処理以外も混じっているようでした。それで、必要な部分のみを残すようにしてみました。

その結果、ブロック 4つとラベルを 1つがあれば計測（※ 基準値の補正も含む）が行えそうであることが分かりました。
![作ったプログラム](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/2d743a4f-9799-d575-060b-e2340e35abff.png)

上記のプログラムを動かすと、冒頭に掲載した動画の内容のように、重さを計測することができました。
スワイプして〇〇するモジュールを作ってみた。

# スワイプして〇〇するモジュールを作ってみた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612874/ae7ef596-b09b-f90b-0264-69453d9fb124.png)

よく見かける、スワイプして〇〇する機構(↑画像みたいな)を現在のPJのアプリ内に導入したかったのですが、
軽く検索してもライブラリ？や紹介記事がぱっと出てこなかったのでComposeの勉強も兼ねて自作することにしました。(絶対探せばあると思うけど。。。)
パラメータ類を調節すれば各々の好きな挙動が実現できるかと思います。
参考

https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary?hl=ja#(androidx.compose.ui.Modifier).swipeable(androidx.compose.material.SwipeableState,kotlin.collections.Map,androidx.compose.foundation.gestures.Orientation,kotlin.Boolean,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function2,androidx.compose.material.ResistanceConfig,androidx.compose.ui.unit.Dp)

挙動としては以下のようになります。ある程度の初速を与えてスワイプすると一番右までスライドし、
一番右まで到達すると左に戻るというような具合です。
// TODOとコメントしているところにスワイプ後のロジックを書くと`スワイプして〇〇する`が実現できると思います。
![animationTest_–_MainActivity_kt__animationTest_app_main__2022-12-20_14-04-41_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612874/5a918926-1722-770c-ba0e-8d60ce45d239.gif)

このテストアプリのGitはこちら

https://github.com/takumashanai/animationTest
【Java】リクエストパラメータの取得

## はじめに
今回はリクエストが送られてきたときの値(リクエストパラメータ)の取得方法をメモとして残しておきたいと思います。
実際にどうコーディングするのかも記載していきます。

## リクエストを送信する側の処理
送信側ではまず、formタグのaction属性に送信先のパス、method属性にリクエストメソッドを指定します。
そうすると、指定した送信先にフォームに入力された値がリクエストパラメータとして送信されます。その後リクエストパラメータは、アプリケーションサーバによってHttpServletRequestインスタンスに格納され送信先に渡されます。
```
/* xxxxx.jsp */
<form action="/hoge/tyome" method="post">
	ユーザー名：<input type="text" name="name"><br>
	パスワード：<input type="password" name="pass"><br>
	<input type="submit" value="ログイン">
</form>
```

## リクエストパラメータの取得処理
リクエストパラメータの取得処理では、getParameter()メソッドで渡されてきた値を取得します。
getParameter()メソッドの引数には、送信元のname属性で指定した値をここでも指定します。

ここではdoPostメソッドを定義していますが、送信元formタグのmethod属性にpostを指定しているためdoPostメソッドでなければいけません。
※送信元formタグのmethod属性にgetを指定した場合は、doGetメソッドを使用する

```
/* xxxxx.java */
protected void doPost(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
	// リクエストパラメータの取得
	request.setCharacterEncoding("UTF-8");
	String name = request.getParameter("name");
	String pass = request.getParameter("pass");

                         ︙
                         ︙
                         ︙
}
```


リクエストパラメータの取得処理は以上です。
BITB (Browser In The Browser)を試してみる

# はじめに
ここに書いてある方法を実際に利用し、第三者のログイン情報を不正に入手する事は不正アクセス禁止法に抵触します。
ローカル環境で試すか、または誰かを使う場合は必ず相手の許可を得ましょう。

# BITBとは
Browser In The Browserの略です。
簡単に言うとブラウザ内にCSSやiframeでブラウザのウィンドウを再現する手法です。
正規のログインウィンドを装ったフィッシング詐欺とかで使われます。
偽のブラウザを用意することで、URLで偽サイトを見分けられなくするのが狙いらしいです。

# 実際に試してみる
https://github.com/mrd0x/BITB
ここにいい感じのデモがありました。
ですがフォークを探したらもっと良さそうなのがあったのでそちらを使います。
https://github.com/Spiderpig86/BITB
適当に
```
git clone https://github.com/Spiderpig86/BITB
```
します。
今回はWindows-Chromeを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/73e976e5-585c-1bb6-dff7-ecc861c913eb.png)

このままだと../phish/phish2.htmlがないと怒られるのでどこかから中身を持ってくる必要があります。
GoogleのログインページのBITBなのでGoogleからとってきましょう。
`
https://accounts.google.com/v3/signin/identifier
`
のhtmlを流用します。
今回は一部を改変して、パスワード入力のために「次へ」を押した時点でpipedreamにformの情報を送信するようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/23f74485-1e28-9543-fabf-2f61e54e20e2.png)

早速試してみましょう。
リンクにマウスカーソルを合わせた場合ですが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/63c72d52-d0d3-591b-8fee-81ed03c7aaa0.png)
このように本物のURLが表示されています。
ですが、実際のaタグは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/29219b6c-80ae-fadf-dca6-2fc5b9bbb63b.png)
クリック時にBITBが起動するようになっています。

このリンクをクリックすると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/95a3b687-ea0d-65c2-99a7-5b880cd77a2c.png)
あぁ...
これは私でも普通に騙されそうです。

実際に入力して"次へ"を押してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/de7cc752-cd72-7f0a-eaa0-a676e6e532ea.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/48bf3c81-7ab1-a3fc-532a-a865e6d0b9cb.png)
しっかりと入力内容が送信されていますね。
(pipedreamを使ったのは最近ハマってるからです。)

# 対策方法
BITBのウィンドウを動かしたときに本体のChromeの外に出すことが出来なければ偽物です。
あとURL欄がうまく選択できなかったりウィンドゥサイズを上手く変更できなかったりとか...
何とも言えない対策方法しか思いつきませんでしたごめんなさい。

と調べていたらこういう拡張機能がありました。
https://chrome.google.com/webstore/detail/enhanced-iframe-protectio/efankjkjendcjahollcfkfhdaffmpkck
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/aabc1654-6ca0-7d05-38e8-2457d43a02e7.png)
おおおおぉ
これでそれなりには対策できると思います。

...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984781/c34e70cd-2169-d947-9b48-620e8e8b2b59.png)

っておーい
画家モンドリアンの絵画っぽいSVGが並んでいるサイトMondrian Land

# 作った

![スクリーンショット 2022-12-21 0.04.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92027/8f797b81-3de6-9ebb-eaf4-f5330c5ce421.png)

[Mondrian Land](https://mi-ki-ri.github.io/mondrian_land/)

読み込むたびにランダムに絵画っぽいSVGが出てきます。

# コンセプト的な解説

カラーパレットをギャラリー状に閲覧できるサイトは

[Color Hunt](https://colorhunt.co/)や[Coolors](https://coolors.co/)など数多くありますが、

それらのサイトではパレットの構成色が均等に扱われているな、と気づきました。

（5色なら5色の各色の面積が均等だということです）

実際に色を扱う際には背景色、前景色、アクセントなど用途によって面積を変えたりしているはずです。

そこで出てきたのがモンドリアンです。

https://www.artpedia.asia/piet-mondrian/

抽象画、特に白または黒のキャンバスに三原色を並べるという作風が、今回の件にマッチしているなと思いました。

結果として、なんとなくモンドリアンっぽい絵画をSVGで作って並べることになりました。

# 技術的解説

SVGの操作に[Snap.svg](http://snapsvg.io/)を採用しました。

[color-names](https://github.com/meodai/color-names)というリポジトリから色のデータと名前を取得しました。

基本は **HTMLベタ書き** で `fetch` APIを用いてcolor-namesのCDNからカラー一覧をJSONで取得し、ランダムにベースカラー、アソートカラー、アクセントカラーを決めています。

（本当はベースカラーに応じたアソートカラー、アクセントカラーにしたかったです）

その後 `document.createElementNS()` でSVG要素を作っています。

HTMLに含まれる要素以外は `createElementNS()` を使う必要があるようです。

あとはそのSVG要素にSnap.svgを適用し、正方形を3つかぶせています。

超シンプルな[リポジトリ](https://github.com/mi-ki-ri/mondrian_land)があるのでそちらもご覧ください。

# 終わりに

本当はカラー同士の関係性（補色とか）も考慮したパレットにしたかったのと、正方形の配置もランダムにしたかったのですが、

時間切れです。

でも全くのランダムのわりには調和して見えるのでモンドリアンのコンセプトがすごいんだと思います。
Angualr ディレクトリ構成

## はじめに

本記事は[Angular Advent Calendar 2022](https://qiita.com/advent-calendar/2022/angular)の3日目の記事になります。
約5年AngualrjsおよびAngularの開発を行っており、
その中での個人的ベストと感じたフォルダ構成について話を書きます。

ちなみに今回のAdvent Calenderの内容が被りました。

https://qiita.com/rukutelialove/items/d7d15b4853565a382851

私が学んだ良いところを書いていくつもりでやっていきます。


## フロントエンドデザインパターン

今年やっていく中で見直していく中で参考にしたものがありました。
それがデザインパターンです。

https://zenn.dev/morinokami/books/learning-patterns-1

注目のデザインパターンは、コンテナ・プレゼンテーションパターンです。

### 簡単な説明

コンポーネントに役割を持たせてロジックの分離をおこなっています。
大まかな説明は

- コンテナ
情報の取得や処理などをここで行います。
ここではテンプレートの表示などは行いません。
ここで処理した情報は下のプレゼンテーショナルコンポーネントに渡します
-  プレゼンテーション
このコンポーネントが表示をします。
コンテナコンポーネントから受けた情報を使って表示のみに特化させます

このような役割に分けてコンポーネントを構成するようにします。

Angularに寄せたディレクトリ構成

```
src/
 └ app/
    ├ page
    |  ├ <各ページのコンポーネント>/
    |  |  ├ <ページコンポーネントのコンテナコンポーネント>
    |  |  ├ <ページコンポーネントのプレゼンテーションコンポーネント>
    |  |   ├ fetures
    |  |  ├ <機能コンポーネント>
    |  |  |  ├ <機能コンポーネントのコンテナコンポーネント>
    |  |  |  └ <機能コンポーネントのプレゼンテーションコンポーネント>
    |  |  └ …
    |  └ …
    ├ shered-components
    |  ├ <機能コンポーネント>
    |  |  ├ <機能コンポーネントのコンテナコンポーネント>
    |  |  └ <機能コンポーネントのプレゼンテーションコンポーネント>
    |  └ …
    ├ shered
    |  ├ <共通処理を行うservice>
    |  └ …
     …

```

上記のようになればスッキリしてみやすいのではないかと考えています。
コンポーネントもdata層とview層が分かれているので操作が簡単になっていくのではないかと考えています。

まだまだこれから実装を煮詰めていくところですので、何かまた新しい発見があったら更新をしていこうと思います。

来年もAngualrで楽しみながら開発していきたいです。
【Android】Active Build Variantを切り替えたときにエラーが発生した時のまとめ

# エラーが発生した時の状況

ビルドバリアントが４つ設定されていた。

```
- freeDebug
- paidDebug
- freeRelease
- paidRelease
```

`freeRelease`を選択した状態で、**Run 'ExampleScreenPreview'** を実行した。

次のウィンドウが表示された。

![名称未設定のデザイン (24).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/10cf5710-3a00-90d4-f977-14c801bb5716.png)

**Fix**をクリックした。

**Select Signing Config**ウィンドウで、**debug**を選択し、**OK**をクリックした。
そして、**Run**をクリックした。


![名称未設定のデザイン (26).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/e59b667e-c388-b251-62be-7d9a6369d627.png)

今思い返すと、この操作が今回のエラーを発生させた原因かと思われる。
ここで行うべきだった操作については、こちらの記事でまとめてある。

https://qiita.com/takagimeow/items/b941a0fa96367fdff987

この操作の後に、Active Build Variantを**paidRelease**に切り替えてみた。

**Build**にエラーが表示された。

```shell
removeContentEntry: removed content entry url 'file:///Users/takagimeow/AndroidStudioProjects/xxx-xxx-xxx/app/src/freeRelease' still exists after removing
```

# エラーを解決した手順

エラーを解決したというよりか、エラーを発生させなくした手順について紹介する。
もしかしたら、読者の環境によっては参考にならないかもしれないが、あくまで参考程度に読んでほしい。

- main以外の各ビルドバリアントのパッケージをすべて削除する
    - freeReleaseディレクトリやpaidReleaseディレクトリなどを削除する。

- .ideaディレクトリを削除する

- Android Studioのウィンドウを閉じる。そして、再度プロジェクトを開く

- build.gradleの**buildTypes**や**productFlavors**の内容を元に戻す
    - **buildTypes**の内容をプロジェクト作成時と同じ**release**ビルドタイプのみにする

```gradle
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.debug
    }
}
```

- Android Studioの**Sync Project with Gradle Files**をクリックして同期する。

![スクリーンショット 2023-01-08 18.56.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/eac47410-ed49-d22e-9bf8-9d31ad2f010e.png)

- **build.gradle**の内容を修正して、もう一度**productFlavors**などを追加する。

```gradle
flavorDimensions "plan"

productFlavors {
    paid {
        dimension "plan"
    }
    free {
        dimension "plan"
    }
}
```

- もう一度、Android Studioの**Sync Project with Gradle Files**をクリックして同期する。

この手順を実行したあとに、Active Build Variantを切り替えた。

`BUILD SUCCESSFUL`がBuild部分に表示されてエラーは消えた。
【Git】Gitで使用するエディタ設定の優先順

## 設定の優先順位

Gitのエディタ設定の優先順位は次のとおりです。

1. `GIT_EDITOR`環境変数 
2. `core.editor`設定
    - `/etc/gitconfig` 
    - `~/.gitconfig`または`~/.config/git/config`
    - `.git/config`
3. `VISUAL`環境変数
4. `EDITOR`環境変数 
5. vi（Debian、Ubuntu の場合は editor）
Pythonにおける2次元配列へのアクセス

Pythonでプログラムを組んでいると、2次元配列へのアクセスで混乱することがあるので、改めてまとめておきます。

# 2次元配列の種類
ここでは、以下の方法で2次元配列を扱います。
- リスト
- numpy
- DataFrame

# リストの場合
リストの場合は、正確には2次元配列ではない（多重リスト）のですが、そのように扱うこともできます。
```python
list = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
# [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
```
1つの値を取得する場合は、直接指定します。
```python
value = list[1][2]
# value = 5
```
スライスでの取得は、期待するようにできません。
```python
# [[4,5], [7,8]]を期待するが．．．
new_list = list[1:][1:]
# new_list = [6, 7, 8]となる
```
これは、まず
```python
new_list1 = list[1:]
```
で[[3, 4, 5], [6, 7, 8]]となり、次の
```python
new_list2 = new_list1[1:]
```
で[6, 7, 8]となるためです。

ということで、純粋な2次元配列ではないので要注意です。

# numpyの場合
numpyは、一番わかりやすい（現実と一致している）です。
```python
import numpy as np

array = np.array(([0, 1, 2], [3, 4, 5], [6, 7, 8]))
# array([[0, 1, 2],
#       [3, 4, 5],
#       [6, 7, 8]])
```
まずは1つの値を取得します。
```python
value = array[1, 2]
# value = 5
```
array[n][m]という書き方ではないのがやや気になりますが、それほど大きな問題ではありません。

スライスで、配列の一部を取得します。
```python
array1 = array[1:, 1:]
# array([[4, 5],
#       [7, 8]])
```
なにも問題ありません。

# DataFrameの場合
DataFrameは、ちょっと指定の仕方が違っていますので、要注意です。
（扱えないわけではない）
```python
import pandas as pd

df = pd.DataFrame([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/5d6f44aa-a7ba-e4d9-3b3d-bac743c16759.png)
まずは、直接1つの値を取得します。
```python
value = df[1][2]
# value = 7
# 縦と横が逆になる
value = df[2][1]
# value = 5
```
先に列番号を指定し、そのあとに行番号を指定するのがしっくりしない感じです。

ということで、ちゃんと行→列でも指定する方法があります。
```python
value = df.iloc[1, 2]
# value = 5
```
基本的には、こちらのやり方で行います。
（numpy同様、array[n][m]での指定ではありませんが）

スライスでの取得も、この「iloc」を使用します。
```python
df2 = df.iloc[1:, 1:]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/97ecbca4-08f4-7017-b4a3-b2b7e91de174.png)

なお、「iloc」ではなく「loc」というのもありますが、こちらはラベル名で区間を指定するので、ここでは省略します。

また、一つ気を付けないといけないのは、
```python
df2 = df[1:][1:]
```
これだとリストと同じ結果になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/2ba35853-7fb8-ce7a-cdbc-dd1c82d0daed.png)

# まとめ
とりあえず2次元配列を扱う場合はnumpyを使っておけば安心です。
状況によってはDataFrameを使用することもあるかと思いますが、その際には「ilocを使うんだぞ」と忘れないようにしたいと思います。
また、2次元配列でリストを使うことは、極力避けたほうが良いかと思います。
Windows10でDockerを商用利用でも無料で使いたい。

Windows10のPCで Dockerの勉強を始めるにあたって、
Docker Desktop for Windows は 
> 従業員数 250 名以上または年間売上高 1,000 万ドル以上に該当する企業は有料

とのことだったので、

Docker Desktop を使わずに、
慣れないLinux(Ubuntu)環境をVirtualBox上に作って、
なんとかDockerでイメージを作成しDockerコンテナを動かすとこまできたわけですが、
その後、ググっていたところ、
WSL2というのを使えばVirtualBoxは不要という記事を発見！
ということで参考になるサイトなどを自分用にメモしておくことにします。
※WSL＝Windows Subsystem for Linux。Windows10上で動かせるLinuxのこと。

:::note warn
追記
Windows10にWSL(ubuntu)をインストールして
Docer(Docker CE)をインストールするのは簡単にできました！

~~しかし、手始めにDockerでVS Code+Pythonの開発環境のDockerイメージを作ってみようと思い、
VS Codeで「Remote - Containers」という拡張機能を入れて使おうとしたのですが、
Docker Desktopが無いと動かないようなので、結局、VirtualBox上のLinux上にDockerで勉強を続けることにしました。~~

【入門】VSCodeでDocker環境構築
https://qiita.com/tsuyotobi26/items/9d48fa676f4d55170b5e
によりますと
>Docker Desktopを使わない場合、WSLでDockerを起動させることが条件となるが、
VSCodeのDefaultの設定ではDevContainersをWSLで実行することが有効になっていないらしい。
Settingsを立ち上げwslと検索し、□Dev>Containers:Execute in WSLにチェックを入れることで解消できる。

とのこと！！！
:::

# 前提
Dockerを動かすためにはLinuxのカーネルが必要。

# Windows環境でDockerを動かす方法いろいろ
 1. Docker ToolBox →　古い。非推奨。
 2. Docker Desktop for Windows (Ver2.4？以降からWSL2 必須)
 3. VirtualBox上のLinux上にDocker →　[VirtualBox上のUbuntu20.04にDockerCEをインストールしてみた。](https://qiita.com/nacanaca/items/d1b1267cd3aac087a37b "VirtualBox上のUbuntu20.04にDockerCEをインストールしてみた。")
 4. WSL2のLinux上にDocker 
 5. Rancher Desktop (WSL2 必須) :new: → [Windows11でDockerを無料で使う。](https://qiita.com/nacanaca/items/201e7ea7d3671e279fe9 "Windows11でDockerを無料で使う。")

# Windows10でのWSL2のインストールはコマンド１つ
やってみたら簡単でした。
コマンドプロンプトで　`wsl --install` これだけです。
![Windows10_WSL_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611568/40b7025d-44f6-5c6b-2fa5-b67859c2c70e.png)

`wsl --list --online`で確認してから、ディストリビューションを指定してインストールすることも可能です。
![Windows10_WSL_install_list_online.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611568/5da82a80-0e81-0f59-0594-4bbfa47a6312.png)

# 参考サイト
https://xtech.nikkei.com/atcl/nxt/column/18/01937/020100001/ 

上記のサイトによりますと

>少し前までは、Windows 10でWSLをインストールして使えるようにするには、システム設定の「Windowsの機能の有効化または無効化」からWSLと仮想マシンプラットフォームを有効にしたり、WSL用のLinuxカーネルをインストールしたり、WSL2をデフォルトにしたり、ディストリビューションをインストールしたりと、何段階もの手順が必要でした。

　これに対してWindows 11（あるいは2020年5月リリースのWindows 10バージョン2004以降）では、WSLを実行するためのwslコマンドが最初から利用でき、そのwslコマンドから一発でWSLをインストールできるようになりました。



Windows で Docker Desktop を使わない Docker 環境を構築する (WSL2)

https://blog.jp.square-enix.com/iteng-blog/posts/00024-wsl2-docker-ce/

いまさらWSL2でDocker

https://qiita.com/tnakagawa/items/9982af1f8abced5e1a26

WindowsでWSL2を使って「完全なLinux」環境を作ろう！

https://www.kagoya.jp/howto/it-glossary/develop/wsl2_linux/

# 参考 [Microsoft公式]WSL を使用して Windows に Linux をインストールする
https://learn.microsoft.com/ja-jp/windows/wsl/install

# 参考 [docker公式]WindowsにDocker Desktop
https://docs.docker.jp/docker-for-windows/install.html

# 参考 [docker公式]Linuxの場合
Linux への Docker Engine 導入ガイド
※最近、Linux用のDocker Desktopもリリースされたらしいです。

https://docs.docker.jp/linux/index.html

# 参考 [docker公式]MacOSの場合
Mac OS X 導入ガイド

https://docs.docker.jp/mac/index.html
Googleプロジェクト管理：開始フェーズの重要性と主要なコンポーネント

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/a1cc3407-8d1d-b37c-1d3a-50bf9ea5159f.png" width="800">

# 開始フェーズの重要性

開始フェーズはプロジェクトの最初の段階ですから、それを正しく行うことは本当に重要です。

プロジェクトマネージャーとしてのあなたの責任は、ステークホルダーとの最初の話し合いに基づいて、

- プロジェクトの目標
- リソース
- その他の詳細

を特定することを支援することです。

開始フェーズは、ステークホルダーに適切な質問をし、調査を行い、リソースを決定し、プロジェクトの主要な構成要素を明確に文書化するための重要な時間である。こうすることで、プロジェクトのスコープを固めることができます。

もし、プロジェクトが適切に開始されないと、物事はあっという間にうまくいかなくなります。

例えば、

- プロジェクトの目標を十分に理解していないと、必要なリソースやプロジェクトにかかる時間を過小評価してしまうかもしれません。
- また、プロジェクトがどのような成功を収めるかについてステークホルダーと合意していない場合、自分は成功したと思っていても、ステークホルダーは目標を達成できなかったと思うかもしれません。

## 適切な質問を検討する

開始フェーズの段階で、ステークホルダーが同じ考えを持ち、明確にしておくことで、プロジェクト期間中、多くの時間と余分な労力を節約することができます。

また、プロジェクトの成果による利益がプロジェクトのコストを上回ることを確認することができます。

そのために、適切な質問を検討します。

#### プロジェクトのベネフィットを決定するために：

- このプロジェクトは、どのような価値を生み出すのか？
- このプロジェクトは、組織をどれだけ節約できるのか？
- 既存の顧客からどれだけの利益を得られるか？
- どれだけの時間が節約できるか？
- ユーザー体験はどのように改善されるのか？

#### プロジェクトのコストを決定するために：

- このプロジェクトにどれだけの時間を割かなければならないか？
- 1回限りのコストは？
- 継続的なコストは？
- 長期的なコストは？

:::note info
プロジェクトの利益は、常にコストを上回るものでなければなりません。
:::

# 開始フェーズの主要なコンポーネント

#### <font color="MediumBlue">ゴール(Goals)</font>

ゴールとは、『何を達成しようとしているのか』ということである。すべてのプロジェクトには明確なゴールがあるべきで、多くの場合、それはあなたの協力を得て、会社のシニアリーダーが決定します。

#### <font color="MediumBlue">スコープ(Scope)</font>

プロジェクトを完了させるために必要な作業を定義します。

#### <font color="MediumBlue">成果物(Deliverables)</font>

顧客、プロジェクトの目標達成のために、クライアント・プロジェクトスポンサーに対して、納品する製品やサービスのことです。

また、成果物には有形のものと無形（トレーニングなど）のものがあることを念頭に置いておくことが大切です。


#### <font color="MediumBlue">成功基準(Success criteria)</font>

プロジェクトが目標に到達するために、どれだけ成功したかを測るための基準です。

#### <font color="MediumBlue">ステークホルダー(Stakeholders)</font>

ステークホルダーは、開始フェーズを含むプロジェクトのすべての段階において、十分な情報に基づいた意思決定を行うための鍵になります。ステークホルダーとは、プロジェクトの完了と成功に関心を持ち、影響を受ける人々のことです。そのため、プロジェクトの目標、目的、成果物、成功基準を決定する際、アイデアの立案からその結果に対する期待値の概説に至るまで、しばしば重要な役割を担います。

開始フェーズでは、ステークホルダーのニーズを早い段階で把握することが重要です。また、次のフェーズに進む前に、すべてのステークホルダーがプロジェクトの目標や全体的なミッションに同意していることを確認するのもあなたの役割です。

#### <font color="MediumBlue">リソース(Resources)</font>

リソースとは一般的に、

- 予算
- 人材
- 資材

など、自由に使えるものを指します。

これらの項目について、早い段階から慎重に考えることが非常に重要です。プロジェクトに着手して、途中で資金や人手が足りないことに気づくのは、誰にとっても避けたいことです。

#### <font color="MediumBlue">プロジェクト憲章（Project charters)</font>

プロジェクト憲章とは、上記コンポーネントがすべて記載された文書である。

プロジェクト憲章を作成することで、整理され、何をしなければならないかの枠組みを設定し、それらの詳細を他の人に伝えることができるようになります。

プロジェクト憲章を作成したら、主要なステークホルダーと文書をレビューし、承認を得て、計画フェーズに移行します。
【動かして学ぶ! Python Django開発入門】2023年で本番運用するためのメモ

# はじめに

この記事は2019年初版発行「動かして学ぶ! Python Django開発入門」の
・Chapter12 Djangoとクラウドを連携して本番運用を行う
・Chapter13 独自ドメイン化とセキュリティ対策
に掲載されている内容についての、2023年時点のクリティカルなメモです。
※SES系は範囲外となります

# Chapter12 Djangoとクラウドを連携して本番運用を行う

◆12-07 Python3をインストールする
EC2には既にインストールされているため対応不要。

◆12-08 pip 管理モジュールをインストールする
ローカルのインストール済みDjangoと、EC2のインストール可能なDjangoバージョンが異なる場合がある。
必ず両者の差異を確認して、必要に応じてrequirement.txtの書き換えを行う。
※ローカルとデプロイ環境のモジュールは、バージョンが合わないと動作しないケースがある

◆12-10 本番運用環境Djangoプロジェクト設定ファイルを作成する
`ARROWED_HOSTS = ['os.environ.get('ALLOWED_HOSTS')']`
.bash_profile(Linixの設定ファイル)を呼んできてくれるらしいが、うまくいかなかったので
`ARROWED_HOSTS = ['*']`
としている。

◆12-17 Nginxのインストールと設定を行う
nginx.confについて
・listen(待ち受けポート番号)はEC2のセキュリティ設定を必ず合わせる
・server_nameは<>(ダイアモンドの括弧）は**不要**

◆12-18 NginxとGunicornを起動する
Gunicorn起動時に、.wsgi(ウィズギー)ファイルの名称が正しいか確認する。
**誤っていてもエラーは出ない**ので、`ps ax | grep gunicorn`で必ず起動確認をする。

# Chapter13 Djangoとクラウドを連携して本番運用を行う

◆13-02 ドメインプロバイダーでDNS設定を追加する

以下の記事を参考にする。※HTTPS化を含む

https://qiita.com/nakanishi03/items/25278fb4dfad60ebfac4

https://qiita.com/nakanishi03/items/3a514026acc7abe25977

※ターゲットグループのポートは「HTTP:80」で対応
Firebase CLI を使用出来るようにする

# はじめに
最近、個人でwebサービスを運営する人が増えてきました。個人運営からはじめたサービスが、ビジネスとして成長していくケースも少なくない状態になっています。Firebase を使用すると、webサービスの開発で独自のサーバー インフラストラクチャを構築することなく、webサービスを実装できます。

Firebase公式のコマンドラインインターフェース（CLI） [Firebase CLI](https://firebase.google.com/docs/cli) の設定方法をまとめました。

## 参考になる本
- [サーバーレス開発プラットフォーム Firebase入門](https://amzn.to/3ZgCj9r)
- [Firebase Authenticationで学ぶ ソーシャルログイン入門 ID管理の原則にそった実装のベストプラクティス](https://amzn.to/3ZgLTt4)
- [良いコード／悪いコードで学ぶ設計入門―保守しやすい　成長し続けるコードの書き方](https://amzn.to/3Xb9HwG)

## Firebase コンソール

Firebase CLI は、Firebase プロジェクトを管理、表示、およびデプロイするためのさまざまなツールを提供します。
Firebase CLI を使用する前に、Firebase プロジェクトをセットアップします。

npm (Node Package Manager) を使用して CLI をインストールし、グローバルに使用可能なfirebaseコマンドを有効にします。

https://nodejs.org/en/

:::note alert
注: Firebase CLI にはNode.js v14.18.0 以降が必要です。一部の Firebase 機能には特定のバージョンの Node.js が必要な場合があるため、特定の Node.js 要件については、各 Firebase 製品の開始ページを確認してください。
:::

### Firebase CLI を使用出来るようにする
Firebase CLI を使用することで、拡張機能をインストールして管理することができます。
以下の手順でセットアップします。

ステップ 1: 次の npm コマンドを実行して、CLI をインストールするか、最新の CLI バージョンに更新します。
```
$ npm install -g firebase-tools
```
インストールが終わったら、firebase コマンドを実行できるか確認しておきます。
```
$ firebase --version
```
ステップ 2:新しい Firebase プロジェクト ディレクトリを設定するか、既存のプロジェクト ディレクトリに移動する

ステップ 3: を実行して、この拡張機能を拡張マニフェストに追加します。
```
$ firebase ext:install stripe/firestore-stripe-payments --project=projectId_or_alias
```

ステップ 4 (オプション): Emulator Suiteを使用してこの拡張機能をローカルでテストする
```
$ firebase emulators:start
```

ステップ 5:マニフェスト内の拡張インスタンスをプロジェクトにデプロイする
```
$ firebase deploy --only extensions --project=projectId_or_alias
```

# まとめ
Firebase CLIの設定方法をざっくりとまとめました。
参考にして頂けると幸いです。
Discord、Cocos Creatorのゲームが表示されるアクティビティを追加

ユーザーとのコミュニケーションは、ココスで成功するための重要な鍵です。私たちは中国語や英語に関わらず、常に開発者の声に耳を傾け、フォーラムで話す場を提供してきました。このフォーラムは私たちの製品だけでなく、業界のあらゆることについて話し合い、より大きなグループへと成長してきました。しかし、状況は常に変化し続けています。

中国ではQQやWeChatを加えて直接会話できるようになりましたが、中国以外の多くのゲーム開発者にとってのゲーム開発について話す方法は、人気のチャットソフト"Discord"にあります。DiscordはIRCの新しい方法となり、多くの古い開発者が初期にあったらいいなと思っていた素晴らしい機能がたくさん追加されました。ファイルの共有、コメントにエモーティコンをつける、サーバー用のセクションを用意するなどがそれです。現在では、1億5千万人以上のMAUがあると推定され、成長を続けています。CocosでもDiscordサーバーはあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852397/53a2620f-f84a-6809-eebf-a80949001bd0.png)
昨年、Discordはユーザー同士がサーバー上でコミュニケーションするための新しい方法を構築し始めた。その1つのアイデアが、個々のサーバー内でプレイできるゲームやアプリをベータテストする場である「games lab」です。このベータサーバーで最初に利用できたゲームやアプリは、poker, checkers、そしてYouTube viewerなどでした。

今月、Discord はすべてのサーバーにゲーム (アクティビティと呼ばれる) を導入しました。一部のゲームは無料で、一部のゲームはサブスクリプションの背後にあります。 誰でも無料で利用できる最初のゲームは、Cocos Creator を使用し、Discord チームによって作成されたゲームだ。 Putt Party は、プラットフォーム上で最大のゲームの 1 つになり、リリース以来ファンのお気に入りになっています。
![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852397/af82405f-9de5-f00e-354c-cc2a8fc21475.png)
私たちは、このグループが私たちのサーバーに来て以来、リリース前とリリース後にゲームを改善する方法について質問や議論をしてきました。YouTubeに楽しい動画がたくさんアップされ、ゲームラボでプレイしている人たちからも積極的な関心が寄せられ、Putt Partyの成功に喜んでいます。
![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852397/2f70ca8a-74e3-2278-3c69-23dec148a877.png)
Putt Partyはミニゴルフの要領で、コース上にあるさまざまな障害物をパットで突破していくゲームです。Putt Partyでは、ホールに向かって吹く風や逆風、反転操作、大きな障害物を越えられるゴーストボールなどのパワーアップが追加されています。一度に多くの人がプレイするため、多くの人に当たってしまったり、パワーアップで低スコアを阻止されたりする可能性があります。

このゲームは数ヶ月前からDiscord Games Labのサーバーで公開されていましたが、サーバーで利用できるゲームが発表されたことで、ゲームの制作についてチームに話を聞くことができるようになりました。早速、Cocos Creatorを使用することになった理由を聞いてみました。メンバーの一人は、ゲームをウェブやPC/Macのアプリケーションに載せるまでのスピード感についてコメントしています。
![スクリーンショット 2023-01-02 15.52.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852397/fa22f13e-ceb7-00df-d2d4-939eef806f69.png)
ホールインワンを打ったり、仲間に罠を仕掛けたりする楽しみがありますが、チームにとってCocos Creatorで作った最初のゲームとなりました。Discord のチームは、HTML5 と WebGL を簡単に使用できる Cocos Creator を高く評価しています。

チームはまた、彼らのゲーム作成をサポートできたことに満足しています。 私たちは彼らとゲームについて話したり、ゲームエンジンの改善について話し合ったりすることに対して、非常にオープンです。

Cocos Creator を試し、このプラットフォームでさらに多くのアクティビティを構築し始める際のサポートを提供してくれた Discord のチームに感謝します。 彼らのリクエストと提案は、開発者が何を望んでいるのかだけでなく、私たち自身の Discord グループに対する彼らのサポートを理解する上でも、より多くの助けを与えてくれました。![image-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852397/fd8375f9-ce39-4c4b-1786-972509f11ced.png)
Discord が Cocos Creator でゲームをプレイできるようになったことで、Tesla、HooRoo、Rokid、飛行機など、私たちが使用しているさまざまなプラットフォームに名前をもう 1 つ追加できます。

Cocos Creator はどこにでもあり、あらゆる技術分野の開発者に素晴らしい新しい機会を構築するために、すべての人とあらゆるプラットフォームをサポートしています。 

[引用元](https://www.cocos.com/en/post/e7c26e48b7ee853cbf5e49de5d800745)
ubuntu 22.04 で Terminal が開かなかった

# 概要
ubuntu 22.04 をインストール直後、Terminal が開かず何もできない！

## 環境
- Virtual Box 7
- ubuntu 22.04.1 LTS (https://jp.ubuntu.com/download)

## まずは xterm
とりあえず xterm を入れる。
1. Ubuntu Software を起動する
1. 左上の虫眼鏡アイコンを押下する
1. xterm を検索してインストールする

## syslog
/var/log/syslog を見る
~~~:/var/log/syslog
Jan  9 22:27:50 ubuntu systemd[1543]: Starting GNOME Terminal Server...
Jan  9 22:27:50 ubuntu gnome-terminal-server[2254]: Non UTF-8 locale (ISO-8859-1) is not supported!
Jan  9 22:27:50 ubuntu systemd[1543]: gnome-terminal-server.service: Main process exited, code=exited, status=8/n/a
Jan  9 22:27:50 ubuntu systemd[1543]: gnome-terminal-server.service: Failed with result 'exit-code'.
Jan  9 22:27:50 ubuntu systemd[1543]: Failed to start GNOME Terminal Server.
~~~
UTF-8 じゃない?

locale を確認する。
~~~:localectl
# localectl
   System Locale: LANG=en_US
                  LANGUAGE=en_US:
                  LC_NUMERIC=ja_JP.UTF-8
                  LC_TIME=ja_JP.UTF-8
                  LC_MONETARY=ja_JP.UTF-8
                  LC_PAPER=ja_JP.UTF-8
                  LC_NAME=ja_JP.UTF-8
                  LC_ADDRESS=ja_JP.UTF-8
                  LC_TELEPHONE=ja_JP.UTF-8
                  LC_MEASUREMENT=ja_JP.UTF-8
                  LC_IDENTIFICATION=ja_JP.UTF-8
       VC Keymap: n/a
      X11 Layout: us
       X11 Model: pc105
~~~
LANG が UTF-8 になっていない。

面倒くさいので /etc/default/locale を直接編集する。
~~~:/etc/default/locale
- LANG="en_US"
+ LANG="en_US.UTF-8"
~~~
んでリブートしたら、とりあえずは解決。

## 結論
LANGだけ en_US になっているあたり、多分 Virtual Box 7 の自動インストールが悪いんかなー?
【祝】2023年の初投稿　簡単な自己紹介とブログ運営について

# はじめまして！　からの自己紹介

## 目次
1. [ジョニーってどういう人?](#introduction)
    1. はじめに
    1. 宣伝(笑)
1. [ブログ運営について ](#todo) 
    1. 更新タイミング
    1. 配信内容

## ジョニーってどんな人？
<a id="introduction"></a>
どんな人？ それは僕が一番聞きたいですが、都内のとある会社でエンジニア業を営む23歳の現役SEです。名前に突っ込みを入れないでください。れっきとした日本人です。

主に次のような業務に携わっています。 
- 業務用アプリケーションの開発
- kubenetes基盤の維持管理(今後やるよてい）
- 機械学習系

あんまり細かく書くと身バレするのでこれくらいにします(笑)
日々の業務での日記や、技術的な発信を行っていこうと思います。
配信は、週１くらいでやっていきます。新人SEの日記なので読み物感覚で読んでください✨

## ブログ運営について
<a id="todo"></a>
基本的に毎週金曜の退勤したあとに更新していこうと思います。
Gitの改行コード

## スクリプトがWindowsのLinux仮想環境でエラーになる

他の環境では動いているのに……

```bash
line 2: $'\r': command not found
line 5: $'\r': command not found
line 35: syntax error near unexpected token `$'do\r''
line 35: `do
```

改行コードの「\r\n」のうち、「\r」で引っかかっている模様。
「\r\n」はWindowsの改行コードですからね。
Linuxの仮想環境の中では動くはずもありません。

で、なんでこうなってしまっているのかというと。

WindowsでGit pullしたときに、改行コードが変更されてしまうからなんですね。

```
$ git config --global -l
core.autocrlf=true
```

上記のようになっていると、Windows環境では自動的に改行コードが変換されてしまうんですね。

```
git config --global core.autocrlf false
```

上記のようにして、 `autocrlf` を無効化する必要があります。

スクリプト自体の改行コードがどのようになっているかは、

```
cat -e {file}
```

で確認できます。

行の最後の方に「^M」があったら、Windows改行コードになっています。
Shields.ioのGitHubのワークフローバッジルートが変更されていた件について

## はじめに

ふと自分の制作物のリポジトリを見に行ったときに気がついたのですが、Shields.ioのbuildバッジが下記のようになっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544280/a5111df9-3c93-0c25-b4ad-a3cf9f1559bd.png)

んん、何か仕様が変わった？？とりあえずバッジに表示されているissueを見に行くことに…！

https://github.com/badges/shields/issues/8671

## 結論

githubのワークフローに`test.yml`が存在する場合、バッジのURLを変更する必要がありました。 

```yaml
name: Run Tests
...
```

**変更前**

```txt
https://img.shields.io/github/workflow/status/<user>/<repo>/Run%20Tests
```

**変更後**

```txt
https://img.shields.io/github/actions/workflow/status/<user>/<repo>/test.yml?branch=main
```

## 具体的にどう変わった？

変更点は2つあります。

1. ワークフローのパラメータがyaml で定義された`name:`ではなく、ワークフローのファイル名になった
1. branch パラメータを指定することが推奨されるようになった。

branch パラメータが指定されない場合は、まずデフォルトブランチのビルドを見に行き、デフォルトブランチに何も見つからない場合は任意のブランチまたは参照の最新のビルドの内容が正となるようです。

また、ワークフローが`.github`下のサブディレクトリにある場合は、サブディレクトリをルートに含める必要があります。
(ワークフローのファイル名/パスは大文字と小文字が区別されるそうです。)

```txt
https://img.shields.io/github/actions/workflow/status/<user>/<repo>/sub_directory/test.yml?branch=main
```

## おわりに

無事に置き換えが完了しました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544280/fb84c8d1-48b4-9d5f-1ab0-093c16bc1aaf.png)

issue の方にこの変更の経緯とかが長々と書いてあるので、読んでみると面白いですよ。  
また、この変更を済ませていないリポジトリをいくつか見かけたので、知り合いにそういう方がいたらこの記事を見せてあげてください。  

良いOSS・開発ライフを！
Cocosを使ったゲームのご紹介 - 2022年9月まで

https://www.youtube.com/watch?v=ayrGEoxozJ0

Cocosエンジンを使っている会社が作ったゲームを紹介するのは、いつも素晴らしいことですが、今回は私たち自身のゲームもリストに加えました！ Steamにある私たちの無料ゲームをチェックしてみてください......と言いたいところですが、これについては後述します。

ショーケースには、中国でかなり話題になっているゲームやトップ10に入るような大作がたくさん並んでいます。多種多様なものを見て、私たちがデベロッパーと共有できるものは、私たちと一緒に作ることに興奮するような素晴らしいものでした。このリストを楽しんでいただければ幸いです。そして、今年12月に開催される最終ショーケースに向け、準備を整えています。

**Paper Wedding Dress 4 - Red Silk Wrap**
中国では規制の関係でホラーゲームはあまり見かけませんが、当たる時は超当たりますね。このゲームは、半年ごとに発売されているマルチシリーズの一つで、中国では非常に好調です。『ペーパーウェディングドレス4』は発売初日に1位を獲得し、ゲーマーはすでに第5弾の準備に取り掛かっています。このゲームについては、翌週のブログで少し紹介しました。

**isles**
多くの開発者は「ゲームエンジンの能力を試すために自分で作ったゲームがあってこそ、ゲームエンジンの開発者としての資質がある」と言っています。そして、それがislesという、ジャンプしたり、浮いたり、集めたりして全レベルをクリアするプラットフォーマーゲームを作るための作業の始まりです。また、このゲームのソースコードを当社のストアで販売していますので、そこから学びたい方はご利用ください。ゲームについての詳細は、ブログ記事からご覧ください。

**Hero Village**
この3Dボクセルシム経営ゲームは、中国での競争や規制によって開発者が国外に出ざるを得なくなり、多くの中国製ゲームが出始めている中の1つです。RPGの要素だけでなく、タワーディフェンスやフュージョンも加わって楽しいゲームです。[開発者がフォーラムでこのゲームについて少し話してくれました。](https://discuss.cocos2d-x.org/t/lessons-from-hero-village-developer-on-graphic-optimizing/56926)

**Archer Castle**
今年の Discord で共有されたゲームの 1 つです。このHTML5ゲームは、ブラウザとスマホでたくさんのゲームプレイを楽しめます。これは、多くのクレイジーなモンスターとアップグレードを備えたシンプルなタワー ディフェンスです。午後のリラックスタイムに最適なゲームです。現在、poki.comでプレイ可能です。

**Call Me Mister Big Boss**
過去に取り上げた他の多くのゲームと同様に、この都市管理ゲームは古代中国の時代にさかのぼり、都市でできることを拡張します。 中国のユーモアがたくさん詰まった楽しいストーリーゲームです。 私たちはフォーラムでそれについて少し共有しました。

**Pause! Let Me Check The Guide**
新作アニメ『Pause! Let Me Check The Guide 』が中国の動画サイト「Bilibili」で超人気となっています。このゲームの面白いところは、アニメのファーストシーズンの最後にキャラクターの一人を視聴者が操作できるようになっているところです。これはサイトのビデオ画面から直接プレイできる最初のゲームの一つで、HTML5ゲームを使って番組を拡張するという点で、かなり画期的なことだと思います。

**Jaws & Claws**
このゲームは、開発者がゲームのリリースを間近に控えているため、当フォーラムを通じてお届けすることになりました。このプラットフォームファイターゲームでは、ゴリラ、ワニ、サイ、クマなど、クレイジーなキャラクターと一緒に戦うことができます ストーリーモード、フリープレイ、サッカーなど、楽しいゲームモードが搭載されています。

**Panda Pizza Parlor**
Bitcakeは、今年の初めにGamesnacksに登場したゲームで紹介されました。彼らはその経験を生かし、今ではピザ屋のオーナーとして、ピザやスナックをお客さんに提供するという素晴らしい3Dタイムマネージメントゲームを作り上げました。モバイルとPCの両方で楽しめる楽しいゲームです。

**Reincarnated As A Monster**
モンスターとしての自分を作るだけでなく、勧誘、アップグレード、隠し装備の発見などが可能なカジュアルなアイドルゲーム。このゲームの大きな特徴は、戦いに挑み、親の力を融合させ子孫を作ることができる点です。 非常に小さなチームで作られたこのゲーム、中国のアプリストア「TapTap」で9.0を超える大ヒットを記録しています。[フォーラムへの投稿で、彼らのUIに関する技術について話をしました。](https://discuss.cocos2d-x.org/t/ways-to-improve-ui-and-loading-from-a-430k-downloaded-app-developer/56929)

**Coward Toraghi**
冒険的なパズルゲームではありませんが、かわいらしさと巧妙なパズルは、物語の半分に過ぎません。また、このゲームは、新婚の二人の開発者が共同で開発したゲームであることも、多くの人が知っています。最近のブログで紹介されたので、どんなゲームなのか見てみてください。

**Ghost Fight IO**
このIOゲームは、ペレットを食べながら走り回り、より強いゴーストを撃退するゲームです。このゲームの素晴らしいところは、GoogleのDeveloper Summitで披露したCocos Creator 3.xのインフラで動いているところです。私たちは、webaudioだけでなく、将来のアップグレードも含めて、HTML5を改善するために努力しています。

[引用元](https://www.cocos.com/en/post/6b913a2317d00f7bfa0abdaff1a1f67f)
ChatGPTでスクレイピングする（その4、フォーム）

# ケース1 カラムヘッダーとローヘッダの両方が存在するフォーム

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/e1380555-b5e0-504a-bc23-3bd64962c649.png)

#### 質問
Could you normalize this table in this html?  Show me all data as key-value table which has key and value column.  All headers and values must be normalized. Nested header must be concatenated by '_'.

#### 回答

Here is an example of how the table could be normalized:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660/a182b8cc-2914-22dd-80eb-386b04a760d0.png)


####　評価

これまでで一番複雑なテーブルなのに一発で正解。これはたまたまなのかな？安定して正解を出力する方法がわからない。神Excelっぽい部分の正規化も完璧。

# ケース2 スクレイピングを行うプログラムの生成

#### 質問
Could you show me the program to reproduce this result?

#### 回答
```
from bs4 import BeautifulSoup

# Replace `html_string` with the actual HTML string of the table
soup = BeautifulSoup(html_string, 'html.parser')
table = soup.find('table')

# Create an empty list to store the normalized data
data = []

# Iterate over each row in the table
for row in table.find_all('tr'):
    # Create an empty dictionary for the row data
    row_data = {}
    # Get the columns in the row
    cols = row.find_all(['th', 'td'])
    # Iterate over the columns
    for i, col in enumerate(cols):
        # Get the column span
        col_span = int(col.get('colspan', 1))
        # Get the cell value
        value = col.text.strip()
        # Get the previous column header
        prev_header = headers[i - 1] if i > 0 else None
        # If the column has a row span, use the value of the previous column header as the key
        if col.get('rowspan'):
            key = f"{prev_header}_{value}"
        # If the column does not have a row span, use the value as the key
        else:
            key = value
        # If the column span is greater than 1, concatenate the values
        if col_span > 1:
            next_cols = cols[i + 1: i + col_span]
            value = ''.join([c.text.strip() for c in next_cols])
            # Update the headers to skip the concatenated columns
            headers = headers[:i] + [''] * (col_span - 1) + headers[i + col_span:]
        # Add the key-value pair to the row data
        row_data[key] = value
    # Add the row data to the list of normalized data
    data.append(row_data)

print(data)
```

#### 評価

出力されるプログラムは微妙。これ本当に動くのかな。今は細かい点はどうでも良い。