OmniAICreator/Qiita-1.07M huggingface dataset:
【Go言語】リテラル・変数宣言

## リテラル
Goのプリミティブなリテラルでよく使われるもの
* 整数
* 浮動小数点数
* ブール型
* 文字列
* nil
> `nil`は無効な参照先を表す値で、初期化されていない状態を表すのに利用される

```go
// 整数
1
// 浮動小数点数
1.5
// 文字列
"あいう"
`Hello
World`
// プール値
true
false
// nil
nil
```

## 変数宣言
`var`の後に`変数名`、`型`で宣言する
初期値を代入する場合は、`=`の後に`初期値`を記述する
初期値の値から型が明らかな場合は、`型`を省略できる

```go
// 整数型の宣言
var num1 int = 10

// 右辺から型が決まるので型の記述を省力できる
var num2 = 20
```

変数名と初期値の代入を`:=`演算子で行うことができる
ただし、関数の中でしか使えない

```go
package main

import "fmt"

// コンパイルエラーになる
num1 := 10

func main() {
    // num2に整数を代入できる
	num2 := 10
	
	fmt.Println(num1)
	fmt.Println(num2)
}

```
ぜんぜん「IoT・ハードウェア」っぽくないけど、ちょっとPyScriptのMicroPythonサポートについて書いておく

# はじめに

2022年5月に発表されたWebブラウザ上で動く[PyScript](https://pyscript.github.io/docs/)ですが、その後も高速化などの改善が行われ、いつのまにかMicroPythonの実行もできるようになっていたので、紹介しておきます。

Pyodide (WebAssembly 用にコンパイルされた CPython)に比べて、まだまだサポートが弱そうですが、ランタイムが170KB程度と小さいので、DOM操作程度であればMicroPythonを用いたほうが高速に処理できるでしょう。

# PyScriptのテンプレート

PyScript

基本は、HTMLの `<head>` タグのコンテンツとして次の１行を加えるだけで PyScript が使えるようになります(本記事の執筆時点)。

```html
<script type="module" src="https://pyscript.net/releases/2023.11.2/core.js"></script>
```

実際は charset や関連のCSSも指定することが推奨されているので、まとめると
次のテンプレートのようになります。この中の `<body>` タグのコンテンツ内に PyScript を書いていくことになります。

```html
<!doctype html>
<html>
    <head>
        <!-- Recommended meta tags -->
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <!-- PyScript CSS -->
        <link rel="stylesheet" href="https://pyscript.net/releases/2023.11.2/core.css">
        <!-- This script tag bootstraps PyScript -->
        <script type="module" src="https://pyscript.net/releases/2023.11.2/core.js"></script>
    </head>
    <body>
        <!-- your code goes here... -->
    </body>
</html>
```

# MicroPython タグ

MicroPython スクリプトは `<mpy-script>` タグか `<script type="mpy">` タグに記載します。たとえば、次のように記載します。

```html
<mpy-script>
    from pyscript import display
    display("Hello, world(1)!")
</mpy-script>
<script type="mpy">
    from pyscript import display
    display("Hello, world(2)!")
</script>
```

※　`print()` 関数では表示できなかったので `pyscript.display()` 関数を使って表示しています。

Webブラウザで表示すると、次のようになります。

![スクリーンショット 2023-12-03 11.35.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/3bf0d6cc-7023-1c9b-3a6e-08fe4e924526.png)

# DOM の操作

簡単な DOM 操作の例を示します。ボタンを押すと、`<div>` タグのコンテンツとして MicroPython バージョンの情報を挿入するものです。

```html
<button mpy-click="display_mpy_version">Display MPY Version</button>
<div id="output"></div>
<script type="mpy" config='{ "packages": ["arrr"] }'>
    import sys
    from pyscript import document

    def display_mpy_version(event):
        output_div = document.querySelector("#output")
        output_div.innerText = str(sys.implementation)
</script>
```

Webブラウザにロードして、ボタンを押すと次のように表示されます。

![スクリーンショット 2023-12-03 11.39.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/b618b1da-5b10-b8ca-f2be-1a6a9518a622.png)

PyScriptの　MicroPython は現状、バージョン 1.20.0 の [WebAssembly版](https://github.com/micropython/micropython/blob/v1.20.0/ports/webassembly/README.md)がベースになっているようです。
【Flutter】フォームバリデーションとユーザー入力

[chatGPT に立ててもらったスケジュール](ceecf4a987d3f75b6d93)に準じてFlutterの状態管理を勉強。
> - Day 7: フォームバリデーションとユーザー入力
# フォームのバリデーションとサブミットの処理
1. `Form`ウィジェットでフォームをラップする
   - Formウィジェットを使用してフォームをラップする。
   - これにより、フォーム内のフィールドが連携して動作し、バリデーションが可能になる。
2. `TextFormField`を使用して入力フィールドを作成する
    - `TextFormField`ウィジェットは、ユーザーがテキストを入力できるフィールドを作成する。
    - `validator`プロパティを使用してバリデーションロジックを指定する。
3. バリデーションロジックの定義
    - `validator`プロパティで指定した関数が、ユーザーが入力した内容の妥当性を検証する。不正な場合はエラーメッセージを返すことができる。
    - 例：入力されてなくて空だったら「入力してください」を返す
4. `Form`のサブミット処理の実装
    - 通常、Form内に配置された「Submit」ボタンなどが押されたときに、`Form`ウィジェット内の`onSaved`プロパティに指定した関数が呼び出され、フォームのデータを処理する。
<details><summary>サンプルソース</summary>

``` dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyForm(),
    );
  }
}

class MyForm extends StatefulWidget {
  @override
  _MyFormState createState() => _MyFormState();
}

class _MyFormState extends State<MyForm> {
  final _formKey = GlobalKey<FormState>(); // フォームの状態を管理するキー
  String _name = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Form Validation'),
      ),
      body: Form( // `Form`ウィジェットでフォームをラップする
        key: _formKey, // keyを割り当てる
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              // テキスト入力フィールド
              TextFormField(
                decoration: InputDecoration(labelText: '名前'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '文字を入力してください';
                  }
                  return null; // バリデーション成功
                },
                onSaved: (value) {
                  _name = value!;
                },
              ),
              SizedBox(height: 16.0), // ボタンとフォームの間に空白
              // サブミットボタン
              ElevatedButton(
                onPressed: () {
                  // フォームのバリデーションを実行
                  if (_formKey.currentState!.validate()) {
                    // バリデーション成功の場合、onSavedが呼ばれる
                    _formKey.currentState!.save();
                    // ここでデータを送信するなどの処理を行う
                    ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('名前: $_name'),), // 下から入力した文字出てくるよ
                  );
                  }
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

```
</details>
エンジニア採用のアプローチで色々やったこと

# エンジニア採用を進めたモチベーション

筆者はスタートアップで働いています。
シリーズCを迎えて、事業を多く進めるためにエンジニアを採用し続けています。
1-2年くらい、ずっとエンジニアが足りません。

あらゆる手段を使ってエンジニア活動をしました。

１つ１つのチームは少人数で活動しており、高いレベルのエンジニアのみを採用しています。
若手メンバーはスタートアップという環境の中でフォローしながら動くということは難しい状況でした。

# この記事でのエンジニア活動の手段

採用手段としては色々ありますが、エンジニア向けの手段を使うことに絞っています。

全職種向けの手段は相対的にエンジニア向けにフィットすることの調整が効きにくいこともあり、初級者レベルから中堅レベルであれば問題ないですが、ハイレベル向けのエンジニア採用ではコミュニケーション難易度が上がります。


エンジニア向けという観点で、色々な採用チャネル手段があると思いますので、転職エンジニアの人からも参考になるように、また、採用面からも様々な手段を検討してもらえるように、今回私が経験した採用チャネルについて、思いつきで一覧化してみました。

# ここから採用アプローチ手段の一覧

## 転職サイト掲載
- リクナビNext
- Wantedly
- Findy
- Forkwell
- Green
- indeed
- エン転職
など


自社の募集を載せて、応募があるまで待つ形です。
エンジニア以外の職種では普通のアプローチですが、エンジニアの採用では初級者エンジニア中心となり、採用できるエンジニアのレベル的には中堅までになります。

人気のエンジニアは、会社の方からアプローチが必要なことが常識です。

私はハイレベルなエンジニアの採用がメインだったため、積極的に運用していませんでした。


## ダイレクトスカウト
- ビズリーチ
- Wantedly
- Findy
- Forkwell
- Green
- LAPRAS
- Qiita Jobs

など

一番の王道だと思います。
それぞれの媒体で特徴があるので、メディアに合わせたアプローチが必要です。
自社情報のメンテナンスは定期的に行うことと、エンジニアの興味を惹くキーワードを入れると良いと思います。

ダイレクトスカウトが強い媒体、検索マッチが強い媒体、潜在層にアプローチできる媒体、エンジニア向けの力が強い媒体などの特色があり、採用したいエンジニアに合わせた活用が重要です。


## イベント型
- 転職ドラフト

月ごとに参加の宣言が必要なため、転職温度感が高い人が多い
競合も多いので、あなたへのメッセージという１人１人へのメッセージの作り込み、自社の強みをしっかり表現できる必要があります。

## SNS型
- Linkedin
- X 

エージェントさんにお任せするか、ダイレクトスカウトの一環として行います。
SNSだと半分リファラルに近い部分があります。

## エージェント
- 数十社に契約し、フィットする会社を探しながら絞り込みます。

エージェントさんも得意不得意があり、あまりフィットしないエージェントさんとずっとやりとりすることはお互いのリソースを無駄にしてしまうので、改善に向かうか、やりとりをやめるかを定期的に判断した方が良いです。

ずっと付き合いのあるエージェントさんだけでやっている場合、本当に良いエンジニアの採用が他にある可能性もあります。

## リファラル
- メモリーパレス

全くやっていないのであれば、まず最初に推進すべき施策
しかし、無限に友達は居ないので、長期的に同じ人から紹介してもらうことは難しいです


## 自社応募促進
- 技術広報
- 採用マーケティング

全ての採用活動の効果を高める
短期的効果は見えにくいが、中長期的にエンジニア採用をするのであれば、絶対にすべき

## VC経由での相談
スタートアップで出資してくれているVCがあれば相談する手段もあります
様々なコネクションを持っていて、かなりハイレベルな人材に出会えることがあります

## 業務委託採用
- 正社員採用は足が長くなりがちです。業務委託の採用で開発を進めることができます。
- 業務委託向けの採用手段も同様にいくつかのアプローチがありますが、今回は割愛します。


# まとめ

採用を強化するために使っていないチャネルがないかを確認に使ってもらえればと思います。

もし、エンジニアの採用活動でお困りのことがあれば、連絡ください！

エンジニア採用は難しいので色々な方とお話してみたいですー
google colab でLatexを使ってルートの中に日本語を入れるときに隙間を調節する方法

自分用の忘備録で簡単に書いています。他にいい方法があれば教えてください。

google colab でLatexを使ってルートの中に日本語を入れるときに隙間が出来てしまうのを調節する方法

・日本語の前に　\\[3pt] を入れて、後ろの棒線が足らない分を全角スペースで調節する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181170/db23b709-f5cf-81bf-8345-574556b33ce8.png)
【CSS・学習ログ7】レスポンシブデザインについて

## レスポンシブデザインとは
デバイスの画面幅に応じて表示が最適かされるデザインのこと。
対応させるには*メディアクエリの使用*と*ビューポート*の設定が必要になる。

### 1.メディアクエリについて

##### @media screen and
screenにはメディアタイプ（どのデバイスにcssを適用させるか）を指定する。screenはpc、タブレット、スマートフォンを指す。
##### (max-width:1024px)
メディア特性（画面幅）などを指定する。この場合、横幅が1024px以上の場合にスタイルが適応される。

※ブレークポイント
レスポンシブデザインにおけるブレークポイントは、デザインが切り替わる画面幅のこと。

### 使用方法
画面幅768pxをブレークポイントにする
ブレークポイントより画面幅が広ければ要素を横並びにし、狭いときは縦並びにする
![スクリーンショット 2023-12-02 141234.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520365/a1eaebad-82a1-c677-b848-de851b88e52a.png)
![スクリーンショット 2023-12-02 141437.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520365/4bac2352-20ac-753d-fb18-840e5e2886e9.png)
```html
<!DOCTYPE html>
<html>
	<head>
		<title>タイトルです</title>
		<meta charset="utf-8">
		<link rel="stylesheet" href="media-queries.css">
	</head>
	<body>
		<div></div>
		<div></div>
		<div></div>
		<div></div>
	</body>
</html>
```
```css
div {
	display: inline-block;
	width: 100px;
	height: 100px;
	margin: 10px;
	background-color: orange;
}
@media screen and (max-width:768px) {
	div {
		display: block;
	}	
}
```

### 2.ビューポートについて
ビューポートはwebページが行事されている領域のこと。
PC向けのページからメディアクエリをスマートフォンにも適応させる設定。

【確認方法】

![スクリーンショット 2023-12-03 090442.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520365/9620fdd1-5e70-35a8-a205-78fc0873a7e7.png)

ビューポートの設定はmeta要素で行う。基本的に下記の記載があればok。
```html
<meta name="viewport" content="width=device-width, initial-scale=1.0">
```
設定項目としてwidth、heightなどがある。initial-scaleでズームの初期倍率を設定できる。
(Node-RED MCU Edition作例①) ゲーミングねこ耳LED

# はじめに

アドベントカレンダー2023の記事として、Node-RED MCU Editionの作例を紹介します。

# ねこ耳LED

2023年4月29日 Maker Faire KyotoでM5Stack社のJimmyさんへ書籍「はじめてのNode-RED MCU Edition」を渡したお返しに「ねこ耳LED」をいただきました。

https://twitter.com/Zakkiea/status/1652499205297147905

書籍はM5Stack社のオフィスの書棚に置いていただいています。

https://twitter.com/necobut/status/1723998560956645691

現在はスイッチサイエンス(Switch Science)のサイトで購入可能です。

https://www.switch-science.com/products/9128

# 材料

マイコンデバイスはM5StickC Plusを使用しました。

https://www.switch-science.com/products/6470

マイコンデバイス本体にNeoPixel(WS2812)が搭載されていると、Moddable SDKのデバイス定義ファイルでそちらが優先されてしまう(M5Atom Lite、M5Atom Marixなど)ので、搭載されていないデバイス(M5Stack、M5Stack Core2、M5Atom S3など)を使用します。

ヘアバンドにねこ耳LEDを取り付けて、Groveケーブルでマイコンデバイスと接続します。

https://twitter.com/ayatokura/status/1728385071705677930

# Node-REDフロー

![スクリーンショット 2023-12-03 10.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/840c59a2-6579-02af-3b55-ac6df201e5e8.png)

Githubにフローファイル(flows.json)を置きます。

https://github.com/kitazaki/flow-sample/blob/master/20231203_flows_neko_mimi.json

## ゲーミング仕様

10色からランダムに色を選択し、発色を繰り返します。「complete」ノードを使用して、「neopixel」ノードの処理が完了したら処理を継続(ループ)させています。

## ボタン仕様

M5StickC Plus本体のボタンAを押すと発色(LEDの数を70個に指定)し、ねこ耳LED本体のボタンを押すと消灯(LEDの数を0個に指定)します。

# さいごに

ねこ耳LEDをつけていると、イベントで目立つこと間違いなしです！
Node-RED MCU Editionを始めるきっかけとして、ぜひ試してみてください！
System.Net.Sockets.SocketException (0x80004005)

ArduinoでWifiサーバーを作成してWindowsで受け取れなかった場合など、

```
System.Net.Sockets.SocketException (0x80004005): 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。
```
ネットワークとインターネット>Wi-Fi>[Arduinoで作成したAP] -> プライベートネットワーク
を試してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/d510e731-5cc4-7502-d05c-f4b1dc998c9f.png)

macならIPv4の設定を手動にしてIPアドレスを自分が送る（udp.beginPacket()等で指定した）アドレスにセット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/7f8f9295-2593-c3ad-62b2-9516ea9f0571.png)


以上、自分用備忘録でした。
Bun を使用して HTTP サーバーをホットリロードする

Bun は、インポートされたファイルが変更された時に、プロセスを再起動・シャットダウンせずにコードを更新するフラグ --hot ホットリロード(hot-reload)と、プロセスをハード的に再起動する --watch をサポートしています。

Svelte、Vue、Reactなどにもある、いわゆる編集内容が即時反映される機能ですが、Bun  --hot は、サーバー側で自動的に再実行してくれます。

今回は、この  --hot の方をみていきます。

 --hot は、プログラム編集時に、アプリケーションを再起動する手間が省かれ、変更を加えたコードを即座に反映できるので、開発やデバッグを効率的に進行できます。

たとえば、サーバー自体をシャットダウンせずに HTTP リクエスト ハンドラーを更新できるようになります。これにより、リフレッシュ速度が非常に速くなります。

```sh:ホットリロードフラグ付きで起動する
$ bun --hot run index.ts
```
このフラグ付きで下記のHTTPサーバーを起動すると、ソース ファイルが変更される度に bun プロセスを再起動せず、fetchハンドラーをリロードします。

念のために、一点だけ付け加えておくと、開発には便利なこの機能ですが、本番環境で万が一typoのひとつでも紛れ込んで壊れるなどという事は避けるなら、まあこのフラグを付けなければ良いだけではありますね。

プロセスを再起動しない利点とどちらをとるかはシステムなどにより違うかな。
```js:index.ts
Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response(`Hello world`);
  },
});
```
したがって、例えばこのソースで「Hello world」を「Hello Bun」に書き換えると、サーバーを再起動しなくても、ブラウザ画面の表示も即座「Hello Bun」へ切り替わります。

ちなみに、このindex.tsファイルはTypeScriptの拡張子ですが、Bunではそれをトランスパイルする必要もありません。TypeScript/JSXで書かれたコードもそのまま自動的にトランスパイルされます。楽々。

# 最近 Qiita に書いた Bun 関連の記事10選

https://qiita.com/advent-calendar/2023/bunjs

https://qiita.com/toshirot/items/94961b6dde72be80ab0c

https://qiita.com/toshirot/items/7a0555b46b3a64a4f643

https://qiita.com/toshirot/items/c4d090bc38f9b85d8cdd

https://qiita.com/toshirot/items/4e8e571dd50a45c651f0

https://qiita.com/toshirot/items/e4eb635596ae4f63bdfd

https://qiita.com/toshirot/items/a81f2073e373b0351493

https://qiita.com/toshirot/items/06a992af8cf8aca9ff95

https://qiita.com/toshirot/items/3af83303f95ac7baa546

https://qiita.com/toshirot/items/9f12715e88f0d5060b41
propsでタグとなる文字列を受け渡して動的にHTMLタグを生成するコンポーネントを作り方

propsでタグとなる文字列をpropsで渡して、HTMLタグとしてレンダリングするコンポーネントの作り方を紹介します。

:::note info
TypeScriptやReactを学び始めて間もない方にオススメの内容だと思っております！
:::

## 【結論】利用したいタグを直接渡せるようにする
私のような初心者はコンポーネントを作成する時に下記のような作り方をしてしまいます。

```javascript
import React, { FC } from 'react';

type Props = {
  ordered?: boolean;
};

const List: FC<Props> = ({ ordered }) => {
  const ListTag = ordered ? 'ol' : 'ul';

  return (
    <ListTag>
      <li>listItem</li>
      <li>listItem</li>
    </ListTag>
  );
};

export default List;
```

別に悪くないとは思いますが…微妙だと思う点が2点あります。

- orderedという余計なpropsを増やしてしまっている
- 変数に入れるワンクッションが少し煩わしく感じる

:::note warn
今の仕様だとul`と`ol`どちらかしか入らないにもかかわらず、**orderedというpropsを必要とすることを知らないと使えないコンポーネント**となってしまっているのがスマートではありません…。
:::

下記のようにコードを修正してみます。

```javascript
import React, { FC } from 'react';

type Props = {
  as: 'ul' | 'ol';
};

const List: FC<Props> = ({ as: Tag }) => {
  return (
    <Tag>
      <li>listItem</li>
      <li>listItem</li>
    </Tag>
  );
};

export default List;
```

asというpropsを定義し、ulとolが必ず入るようにリテラル型にしました。
さらにpropsで渡された値を`Tag`に代入して利用できる形にしました。

:::note info 
asを必須の値と設定していますが「?」をつけることで任意の値とした上で、propsにデフォルトの値を設定することも可能です！
```javascript
type Props = {
  as?: 'ul' | 'ol';
};

const List: FC<Props> = ({ as: Tag = 'ul' }) => {
```
:::

## asってなんだ？
asプロパティは、ReactのコンポーネントがレンダリングするHTMLタグを指定するためのものです。
なので先ほどのpropsのtype定義を`string`に変更するとエラーになります。

```diff_typescript
type Props = {
-  as?: 'ul' | 'ol';
+  as?: string
};

// エラー内容
'Tag' を JSX コンポーネントとして使用することはできません
Its type 'string | undefined' is not a valid JSX element type.
型 'undefined' を型 'ElementType' に割り当てることはできません
```

HTMLタグの名前しか受け取れないはずのasプロパティに対してstring、任意の文字列を許容する形式に変えたことでHTMLタグとして認知できない文字列を渡せてしまうためエラーとなります。


## 【propsでタグとなる文字列を受け渡して動的にHTMLタグを生成するコンポーネントを作り方】まとめ

propsでタグとなる文字を受け渡す場合はasプロパティを使うことで安全なコンポーネントかつシンプルな記述を実現できます！

コンポーネントの性質によりますが、実装方法として覚えておくと便利だと思います！
AndroidStudioのlogcatを見やすくする方法

# 概要
AndroidStuioを最新版にアップグレードしたところ、logcatが見にくくなった。
![スクリーンショット 2023-12-03 10.57.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183689/bd1c86e5-152c-bece-09c9-5fcf652b195b.png)
「com...ew.rebuildingsagaanotherstory」の表示などが出るようになり、元々表示したいログが改行されてしまう。（元々のlogcat設定が消えてしまったからかも）
# 解決方法
Logcatの以下のアイコンをクリックする。

![スクリーンショット 2023-12-03 11.00.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183689/e4c35a19-c107-5917-5c36-fede4a9d6547.png)

デフォルトで「StandardView」にチェックが入っているため「CompactView」にチェックを入れる
![スクリーンショット 2023-12-03 10.59.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183689/b3ef8ea5-84f2-6d1e-94f5-a6203086c458.png)
するとpackage名などが消えて、コンパクトな表示に！
![スクリーンショット 2023-12-03 11.02.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183689/f4d2c17f-ca90-f848-6e43-2db893cc43d0.png)

MacPCなど比較的小さな画面で開発している人は
是非「CompactView」にしてみましょう！！
Vue.js グローバルな css と併用する場合、コンポーネントは CSS Modules を利用するのがよさそう

- 現在: 汎用＆コンポーネントなセレクタ含めて、グローバルな css ファイルに定義されている
- 将来: コンポーネント用のセレクタはコンポーネントに移動しつつ、汎用的なセレクタは Tailwind 等を利用 -> purge させたい

という状況で、コンポーネントは Scoped CSS or CSS Modules どちらが良さそうか調べたときのメモ。

# 結論

- Scoped CSS だとグローバルな css で定義されたセレクタが適用される場合がある
    - グローバルな cssを変更すると、Scoped CSS で定義したコンポーネントに影響ある可能性あり
- 前述の理由から、コンポーネントでは CSS Modules を利用した方がよさそう
- 参考: [【Vue.js】Scoped CSSよりCSS Modulesの方がベターだった件](https://qiita.com/mascii/items/3202b9e18fd4a7366ac1)

# デモ・検証

https://stackblitz.com/edit/nuxt-scoped-css-css-modules?embed=1&file=app.vue

:::note info
デモは Nuxt3 を使用しているが、Scoped CSS, CSS Modules の仕組みは Vue.js と同じ。
:::

`npm run build` -> `_nuxt/dist/client/_nuxt/entry.[hash].css` を見てみると、次のようにビルドされる。

```css
/* ScopedCssComponent.vue */
.flex[data-v-af7180a1] {
  align-items: center;
  display: flex;
  font-size: 16px;
  justify-content: center;
}
.flex span[data-v-af7180a1] {
  font-size: 12px;
}
.flex .label[data-v-af7180a1] {
  font-size: 14px;
}
.flex .underline[data-v-af7180a1] {
  text-decoration-line: unset;
}

/* CSSModuleComponent.vue */
._flex_z1ykh_1 {
  align-items: center;
  display: flex;
  font-size: 16px;
  justify-content: center;
}
._flex_z1ykh_1 span {
  font-size: 12px;
}
._flex_z1ykh_1 ._label_z1ykh_10 {
  font-size: 14px;
}
._flex_z1ykh_1 ._underline_z1ykh_13 {
  text-decoration-line: unset;
}

/* app.vue(グローバルなセレクタ) */
.grid {
  display: grid;
}
.flex {
  color: green;
  font-size: 10px;
}
.flex span {
  color: #00f;
  font-size: 10px;
}
.flex .label {
  color: red;
  font-size: 10px;
}
```

 Scoped CSS は元の class 名が残り、グローバルなセレクタと合わせて適用されてしまう。
 [コンポーネントの一番外側の要素のクラス名をプロジェクト内でユニークにする](https://qiita.com/yassh/items/7fb75904de19ff3bd3e8#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E4%B8%80%E7%95%AA%E5%A4%96%E5%81%B4%E3%81%AE%E8%A6%81%E7%B4%A0%E3%81%AE%E3%82%AF%E3%83%A9%E3%82%B9%E5%90%8D%E3%82%92%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E5%86%85%E3%81%A7%E3%83%A6%E3%83%8B%E3%83%BC%E3%82%AF%E3%81%AB%E3%81%99%E3%82%8B)ことで対策可能。

だが、コンポーネント作成するたびに名前を意識するのも億劫のため、CSS Modules を使った方がよさそう。
VSCodeで「インポート "boto3" を解決できませんでした」というメッセージが出たら


インポート "boto3" を解決できませんでした」というメッセージが出た。

[![Image from Gyazo](https://i.gyazo.com/072d34147b89865dae0c5bd4e7f8c6f5.png)](https://gyazo.com/072d34147b89865dae0c5bd4e7f8c6f5)


VSCodeの左下にあるPythonバージョンをクリックし、インストールした ラライブラリ が存在するPythonインタープリタを選択すると、直ります。

[![Image from Gyazo](https://i.gyazo.com/e00433a468fa686f30c07e5591da7725.png)](https://gyazo.com/e00433a468fa686f30c07e5591da7725)


以上です。
第一世代　バッテリー改造（電池変更）

「aibo ers-11x/210で遊ぶ Advent Calendar 2023」の5日目です。

ers-11xの外部電源の適用を検討してきましたが、バッテリーセルの変更についても検討してみました。

:::note alert
警告
この記事について作者はいかなる責任も負いません。
バッテリーの分解、改造は非常に危険な行為です。
:::

:::note
業務外の個人的な検討活動です。
:::

#### 先行事例
こちらはKratax社のLiPo電池を使用しているようですが、動作中に停止したとのことです。
残念ながら、検索しても放電電流の仕様が見つからなかったです。
https://qiita.com/ABK28/items/68143f632133f07084cf

#### 今回のセットアップ
構成は先行事例と同じですが、配線には元のバッテリーで使用されていたニッケルリボンとケーブルを流用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/d9547d58-9bba-8869-e436-9d8785c89247.png)

電池はNLAセレクトのLiPoを使用しました。専用充電器と合わせると比較的高価ですが、性能と安全には代えられないです。
放電電流は最大3.4Aです。
https://led-outdoorgear.biz/products/detail.php?product_id=833

充電はaiboのステーションの充電仕様が不明なので、電池を取り出して専用充電器を使用します。

#### 動作確認
起動、動作できました。約1時間経過をみましたが、途中で止まることもありませんでした。
実験後の電池の発熱はありましたが、先行事例の紹介にあるような触って熱いと感じるほどではありませんでした。
ただ駆動部の渋さなど機体の状態にも影響受けると思います。
OSPO SWG(第4週)の紹介

# はじめに
OSPO SWGで第４週の議論のリードをさせていただいている大和田です。昨日の第２週の紹介に続いて、OSPO SWG（第4週）を紹介します。

# OSPO SWGの成り立ち
OSPOという言葉を耳にする機会が増え始めた頃に、関心を持ったOpenChain Japan Work GroupのメンバーがOSPOを理解したいと集まったのがOSPO SWGのきっかけです。現在は、TODO Groupとの共同活動となっています。

# OSPO Simple FAQ検討活動
OSPOが扱う対象は広く、いろいろな側面があります。そのため、OSPOとは何？と問われたときに、なんとなくわかるけれど、うまく説明できないです。
そもそも、OSPO（Open Source Program Office）のProgramという言葉の意味がソフト屋さんの最初に思いつく意味とは全く違っていて、それもOSPOを理解しにくくしている要因になっていると思います。
そこで、そういったシンプルな問いかけに対する答えを集まったメンバーで考えを共有し、いろいろな面から意見を出し合って、答えをまとめられないか、という活動を毎月第４週の金曜日に行っています。
答えをまとめられれば、それが一番良いのですが、まとまらなくても、この活動の中で、自分の考えを言葉にしてみる、他の人の考えを聞く、それらに対して自分とは違った面から見た意見を聞く、それにさらに自分の意見を述べる、という活動そのものが参加メンバーにとって有益なものになっていると思います。
The Linux Foundationのイベントでの講演やTODO Groupの文献などにすでに多くの答えが見つかりますが、自分たちの言葉にしてみることで、より理解を深め、よりうまく周囲に説明できるようになれると思います。

# どんな問いについて検討しているか
集まったメンバーで出し合った問いは次のようなものです。
- OSSの扱いに気を付けなくてはいけないのはなぜですか？
- OSSを活用する、OSS活動のメリットは何ですか
- OSPOって何ですか？
- そもそもOSPOを一言で説明するなら？
- OSSの管理はなぜ必要なのですか？（なぜ今更、既にOSSは多く使われているのに）
- OSPOをどう進めればいいですか
- (TO:OSPO組織を既に持っている企業)どうしてOSPOを作ったのですか？
- OSPOを作りたいのですが、何から手を付ければいいですか？
- OSPOの組織構成やメンバ構成は？ 
- （などなど）

話を進めてゆく中で新しい問いが生まれてゆきます。

# FAQの例
なかなかまとまらないのですが、何とかまとめができたものを２つ紹介します。
### 「OSSを活用する、OSS活動のメリットは何ですか」
OSPOが目指しているOSSのメリットが何かについて考えを集めたとき、様々な意見が集まりました。まとまりがつかないと諦めかけていたとき、OSPOの成熟のステージによって重点が置かれるメリットが異なっているのだと気が付きました。そこでOSPOの成熟のステージの図に集まったメリットを置いてみたのが次の図です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2333862/90a34129-cac1-6c4f-63fe-7dec4283a465.png)

### 「OSPOってなんですか」
これもいろいろな考え、意見が集まり、OSPOの成熟のステージごとにまとめてみました。”Your OSPO is not my OSPO"（あなたのOSPOは私のOSPOではありません）といわれるのは、それぞれの人が今いるステージが異なっていることも理由の一つではないかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2333862/3989a66f-f689-df04-cff6-755e550d5f94.png)

このまとめを元に、今は、そもそもOSPOとは何かを一言で表せないか議論しています。


その人その人が今いるステージによってOSPOの見え方が違うことがOSPOを理解し、説明し、立ち上げることを難しくしている要因だと、今は考えています。

# おわりに
ご興味を持っていただけ方は、ぜひ、活動をのぞいてみてください。どなたでも自由に参加いただけます。普通のOSSコミュニティと変わりありません。参加条件は、[独禁法](https://www.linuxfoundation.org/legal/antitrust-policy)、[LF行動規範](https://events.linuxfoundation.org/about/code-of-conduct/)、および、[チャタムハウスルール](https://www.chathamhouse.org/about-us/chatham-house-rule)に従うことです。
ミーティングの開催案内は[OSPO Local Meetup - Japan (Japanese Speaking)](https://community.linuxfoundation.org/ospo-local-meetup-japan-japanese-speaking/)に掲載されます。

## English summary
Every 4th Friday of the month, we discuss about OSPO Simple FAQ in OSPO Local Meetup.
Having a discussion for answering simple questions about OSPO, such as "What is OSPO?", is valuable for participants to understand OSPO deeply.

Here are two results of our discussion.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2333862/6f1b17de-95a2-e23d-a4d9-e99091c51377.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2333862/adae503e-6a34-58af-575c-dd6685743d6f.png)

OSPO is seen differently from different stage, and I think this is why OSPO is difficult to understand, explain and build up.
形式的意味論ってなんですか？

## はじめに

これは[RetailAI Adventurers Advent Calendar 2023](https://qiita.com/advent-calendar/2023/rai-adventurers)の3日目の記事です．

昨日は@mizoguchi_ryosukeさんの記事「[初めてのpython cvxpy](https://qiita.com/mizoguchi_ryosuke/items/a9033203742be09b1127)」でした

最近，社内の読書会で「[プログラミング言語の形式的意味論](https://www.maruzen-publishing.co.jp/item/b304793.html)」という本を読み進めています．まだまだ勉強中ではありますが，得られた知見をまとめていきます．

本稿の中では，取り扱う主題の性質上，数式を使わせていただきます．また，あまり聞き慣れない用語も出てくるかと思いますのでご留意ください．

## 早速本題へ

「一言で説明してください！」と言われても適切な言葉が出てこないので，早速本書の冒頭の一文を引用します．

> プログラミング言語に形式的な意味論を与えるとは，数学的なモデルを与えることである．これによって，プログラムの挙動に関する理解や推論の基礎づけが可能となる．

「プログラミング言語を数学的に扱おう」ということです．この**数学的なモデル**というのがまた引っかかるところですが，単に意味を与えると言っても様々な与え方があり，それをざっくりと表しているくらいで捉えてください．この意味の与え方から，操作的意味論，表示的意味論，公理的意味論の大きく3つの分野に分けられます．本稿では操作的意味論についてどういったものかをできるだけ簡単に説明します．操作的意味論では，プログラムの動作を数学的モデルで表します．

### 扱う対象を考える

まず，「そのモデルの中で取り扱う対象は何か？」ということを考える必要があります．整数を扱う問題を解くとすると，当然整数が必要になります．$\cdots -3,-2,-1,0,1,2,3,\cdots$のように，正の数，負の数，0ですね．ただ，これらをいちいち羅列するのは面倒なので，集合$\mathbf{N}$としてまとめておきます．また，この後の議論で集合$\mathbf{N}$の要素を表すときに$m$，$n$の文字を使うことがあります．

次に，整数に対する算術式$m*n$も考えます．ひとまず四則演算$+, -, \times, \div$を見てみます．2つの整数$m$，$n$に対して，$m + n$，$m - n$，$m \times n$の結果はいずれも整数になりますが，$m \div n$は（1つの数で表すなら）必ずしも整数になるとは限りません．よって，$+, -, \times$を扱います．これらを集合$\mathbf{Aexp}$としてまとめておきます．

上と同じように，真偽値の集合$\mathbf{T}$，プログラム変数の集合$\mathbf{Loc}$，ブール式の集合$\mathbf{Bexp}$，コマンドの集合$\mathbf{Com}$というようにまとめておきます．大事なのは，扱う対象を閉じた集合として定義することです．

### 状態を定義する

状態とはなんですか？？ 引用します．

> 状態とはプログラム変数から整数への関数$\sigma: \mathbf{Loc} \to \mathbf{N}$のことである．すなわち，$\sigma \left(X\right)$は状態$\sigma$のもとでの変数$X$の値を返す．

例えばあるプログラムを書いて，変数$X$に5を代入したとします．このような状態を$\sigma$とすると

$$
\left< X, \sigma\right> \to \sigma \left(X\right) \to 5
$$

というように，5が返されます．直観的には，至極当たり前のことだと思いますが，厳密なモデル構築のために必要な定義です．任意の算術式は状態$\sigma$によって値を返され，このことを評価といいます．

状態を定義しても，変数$X$が常に5を返すように，ずっと同じ状態を維持していたのでは面白くないですね．何かしら状態が変化しないといつまでも問題は解けません．上でさらっと出しましたが，コマンドがその役割を担います．上の例で，「変数$X$に5を代入した」と書きましたが，最初から5が入っているわけではありません．

$$
X:=5
$$

という操作を行う必要があります．先程，$\left< , \sigma \right>$の記法を出しましたが，初期状態（定義済みのすべてのプログラム変数の値が0の状態）を$\sigma_{0}$として

$$
\left< X:=5, \sigma_{0} \right> \to \sigma
$$

というように状態が$\sigma$に遷移します．コマンド$c \in \mathbf{Com}$の実行によって状態が遷移していきます．

### 前提から結論を導出する

これも直観的に至極当たり前の話だと思いますが，前提があって結論が導かれます．プログラム中で，$3+5$という演算をするときに，任意の状態$\sigma$において，$\left<3,\sigma\right> \to 3$，$\left<5,\sigma\right> \to 5$という前提が成立するから，$\left<3+5,\sigma\right> \to 8$という結論が導かれます．$\left<3,\sigma\right> \to 4$となるプログラムでは上記の結論は導かれません．書籍の記法を使って，

$$
\frac{\left<3, \sigma \right> \to 3 \qquad \left<5, \sigma \right> \to 5}{\left<3+5,\sigma\right> \to 8}
$$

と書きます．前提0で得られる結論を公理といい，プログラム中では当たり前に成り立つもの（$\left<3, \sigma \right> \to 3$など）を指します．

$$
\frac{}{\left<3, \sigma \right> \to 3}
$$

公理からスタートし，前提から結論を導き，導いた結論を前提に次の結論を導くというプロセスで解くべき問題を導出してやります．これを導出木といいます．

## 閑話休題

導出木を書くための良いツールを探していたのですが，見つけられませんでした．．．

## まとめ

本記事では，形式的意味論のなかの操作的意味論についてざっくり説明しました．具体的な問題の例示もなく，話がかなり抽象的になってしまいました．また，かなり端折って書いたことで，情報の欠損が多々あるかと思いますので，コメントで忌憚なきご意見をお聞かせ願います．今後別の記事で，さらに詳しく説明していきたいと思います．

明日は引き続き，@yoshitake_tatsuhiroが別の内容で担当します．

## 参考

- [プログラミング言語の形式的意味論](https://www.maruzen-publishing.co.jp/item/b304793.html)
エンジニア・非エンジニア間コミュニケーションの橋渡しをする上で気をつけていること

# はじめに
先日、Qiita主催のイベント「[Qiita Night～エンジニア×非エンジニアのコミュニケーション～](https://increments.connpass.com/event/297115/)」に参加しました。
そこで紹介されていた方法が、意外と自分が普段気をつけていることと似ていたので、
もしかしたら自分の事例も参考になるかも？　と思いこの記事を書きました。

https://increments.connpass.com/event/297115/

https://youtu.be/UiXQ5VECi9w?si=apFY5s07iCV0M57b

### 想定読者
非エンジニア寄りの立場で、エンジニア・非エンジニア間コミュニケーションの橋渡しに困っている人

※私自身は業務では非エンジニア・非システム部署の立場（経理・営業支援）で、他の人よりはちょっとだけパソコンが分かるレベルです。
そのため、部署内（営業）からのシステムへの要望を取りまとめ、システム部署の担当者とやりとりすることが多いです。

## メリット・デメリット

### メリット

* システムへの要望が通りやすくなる（感謝される）
* 自部署内で頼りにされる
* 分からないまま放置されて手遅れになる前に相談してもらえる
* システム部署とお互い相談がしやすくなる
　※普段からシステム要望を上げている関係で、システムに新しい機能を追加する際は、現場からの意見代表としてモニターで呼んでもらえるようになりました。

### デメリット

* とりあえずIT系のサポートは全部あいつに投げておけば良い（システム部署とも交渉してくれる）という立場になる可能性あり
* 基本的に追加の手当は出ない

ですが、その分、通常業務だけでは培えない知識はついたかなと思います。
（調べたりするのも好きなので）

※全国の情シス・サポート部門の方々、私とは比べ物にならないほどの労力を割かれているかと思います。いつもお疲れ様です…。

# 気をつけていること

対　非エンジニア・エンジニア、シチュエーション別で対応方法が異なるため、分けて記述します。
特に、二つのシチュエーションで使っています。

1. システムエラーの問い合わせ
2. システムへの要望取りまとめ

また、一番重要なことは **「それぞれが相手へのリスペクトを持つ」** ことだと思います。
「とにかく急ぎで対応してください」といった **相手の状況を全く考慮していない言葉は避ける** ようにしています。
ただ、個人的には丁寧に問い合わせをした方が、優先的に対応してもらえている実感があります。

## 対非エンジニア

### エラーの英語メッセージが出ても怖くないことを伝える
　プログラミングの勉強をしているとエラーメッセージを読むことは普通のことですが、
あまりシステムに慣れていない方にとっては一大事です。
　システムが、エラーの原因や、「操作している人にしてほしいこと」を教えていてくれるんですよと伝えると安心してくれます。
冷静になってから話してもらうことで、状況の聞き取りがしやすくなります。

### 難しい用語は使わない
　弊社は「ブラウザって何？」レベルの方も多いので、ふとした説明の時に出る「ウインドウ」や「タブ」、「ホームボタン」などのワードでも混乱させてしまいます。
説明の時は、「画面の右上」や「星のマーク」など、パッと見て分かるワードで伝えます。
私も全然知らない業界の用語をいきなり言われてもチンプンカンプンなので、**相手の理解度に沿った用語選び**が重要です。

### 画像など視覚的な表現を添える
　チャットやメールなどで伝えたり、マニュアルを作る際は、スクリーンショットにメモを書き込んだものを渡すことが多いです。
　一度誰かと一緒に操作して成功していても、いざ一人でやろうとすると難しいので、実際の操作を丁寧に追えるようにすると、再問い合わせがグッと減ります。

### 解決策だけではなく、今後の調べ方も伝える
　その場限りの対応だけをしても、似たエラーが発生した時の対応力は身につきません。
余裕があれば、エラーメッセージの読み方や、対応策の検索の仕方を教えています。
　魚を与えるのではなく、魚の釣り方を教えるイメージです。
　数年かけて根気強く伝えたところ、私の上司の場合は、簡単なエラーは自分で対処できるようになりました。

## 対エンジニア

### 発生までの経緯・前回の問い合わせ履歴を添付する
　**エラーの場合**は、できれば時系列に沿って、経緯を箇条書きで伝えます。
 サービスのアップデートの問題なのかシステム更新が原因なのかなど、すぐ判断してもらえます。
　また、再発したエラーでこちらで対処できないものについても、前回の問い合わせ状況・システム部署からの回答も添えて伝えます。
　システム部署には全国の支店から問い合わせが来ているので、１から履歴を探す手間を省くためです。

　**要望の場合**も、同様のことを記載します。
 できればどこがボトルネックになっているのか、社内システムや部署のどれが絡んでくるのかも添えると、短期的な改修になるのか長期的な改修になるのかを判断しやすくなるようです。

### 画像など視覚的な表現を添える
 対非エンジニアにも同じ項目がありますが、こちらは画面で説明した方が簡単というのが大きな理由です。

### 公式ドキュメントを参照・該当箇所を添付する
**エラーの場合**は、公式ヘルプやフォーラムを参照し、似た事例がないかを探します。
　それでも解決できず問い合わせする場合は、とにかく自分がどこまで調べたかを明記します。
まとめるのに時間がかかりすぎることもあるので、緊急かそうでないかで調査のやめ時を判断します。
　理想としては、簡単に問題の切り分けができると話が早いです（機器側の問題なのか、管理者権限が必要なのか等）。プロではないので断定ではなく、こうではないか……という主旨で記載します。

**要望の場合**は、現場からの意見を取りまとめた後、参照できれば公式が出している説明資料を読みます。
　簡単なカスタマイズが必要なのか大規模な改修になってしまうのかの判断材料にします。

　あくまでも下調べなので、実際の開発に貢献できているかは分からないですが、どういったイメージで要望を出しているのかを分かりやすくするのが主目的です。

　弊社ではSalesforceを使用しているので、Salesforceが出している学習サイト「Trailhead」で空き時間に勉強しています。
開発側の操作を知ることができるのでとても助かります…！
※2023年12月現在では、まだMOUNTAINEERランクです。精進します。

https://trailhead.salesforce.com/ja

# まとめ
草の根的な活動ではありますが、コミュニケーションコストを減らすことで、お互いに良いフィードバックができる環境を整えられたらいいなと思います。
異常終了時の気づき

## 初めにログを見る理由
異常終了時に初めにログを見るのは、異常終了したプログラムと状態を教えてくれるから。

## 異常終了を分析するのに助けてくれるLinux コマンド
①複数ファイルから特定の文字列を検索する
find . -type f -name "*.txt" | xargs grep '検索文字'
find: ファイルやディレクトリを検索するコマンド
. : カレントディレクトリ配下全て
f :通常のファイルタイプを検索する
-name "*.txt":ファイル名がpatternと同じファイルを検索する。
|：呼び名はパイプ。findでの検索結果をxargsに渡す性格を持つ
xargs:標準入力から受けた内容を実行する
grep:文字列を検索するコマンド

②より簡単に特定の文字列を検索
grep -r '検索文字' ディレクトリ名

③文字コードの変更
iconv -f JIS -t UTF8 ファイル名1 -o ファイル名2
JISのファイル名1を UTF8 に変換し、ファイル名2で出力します。
bash で単体テスト

## 概要

ファイル操作をするような bash スクリプトを書くことって多いですよね。
そんなとき、単体テストが書けると便利ですね。
ここでは diff を使って簡単にテストする方法を紹介します。

## 結論

1. スクリプトをテスト可能に書く
    - ファイルパスはすべて相対パスで記述（本番とテスト環境とで起点となるパスを変えられるように）
    - 本日の日付は外部から渡す
1. テストに使うファイル群を用意する
    - data: 処理開始時点でのファイル群
    - expected: 結果としてあるべきファイル群
1. テストの際には:
    1. ひな型から work/actual, work/expected を生成
    1. テストケースに応じて work の内容変更
    1. work/actual エリアでスクリプト実行
    1. work/actual と work/expected の diff をとって比較

これらを便利にする関数を定義して可読性を上げます。


## 具体的に

### ファイル構成

- `some_action.sh` というスクリプトがあるとして、それをテストする場合のファイル構成です。

```sh
some_action.sh  # テスト対象のスクリプト

tests/
    _common.sh  # テストで使う共通スクリプト
    some_action/
        data/  # テストで使うファイル群
            1-init/      # 初期状態
            2-expected/  # 最終的な期待値
        test.sh  # テスト実行ファイル  
```

### 実行

```bash
cd tests/some_action
./test.sh
```

### 各ファイルの中身

```bash:some_action.sh
if [ -f aaa.txt ]; then
  mv aaa.txt bbb.txt
else
  echo "ccc" > ccc.txt
fi
```


```bash:test.sh
#!/bin/bash

set -eu

source ../_common.sh

TARGET_SCRIPT=../../some_action.sh

test_init "ファイルが揃っている場合"
test_exec $TARGETSCRIPT
test_diff

test_init "ファイルが存在しない場合"
rm work/actual/aaa.txt
rm work/expected/aaa.txt
echo "ccc" > work/expected/ccc.txt
test_exec $TARGETSCRIPT
test_diff
```


```bash:_common.sh
# テストケース実行共通関数

test_init() {
  local TITLE=$1
  echo "$TITLE"
  rm -rf work
  mkdir -p work
  cp -rp data/1-init work/actual
  cp -rp data/2-expected work/expected
}

test_exec() {
  pushd work/actual > /dev/null
    echo "$@"
    bash "$@"
  popd > /dev/null
}


test_diff() {
  echo "diff -r work/actual work/expected $*"
  diff -r "work/actual" "work/expected" "$@"
  RES="$?"
  if [ $RES -eq 0 ]; then
    echo "（OK. 差分なし）"
  fi
  echo
  return $RES
}
```


## 個々のテクニックの具体的な説明

### 1. 実行に失敗したら即終了するように

ファイルの先頭で下記を書きます。
`-e` は未定義の変数を参照したらエラーにし、
`-u` はエラーがあったらその時点で中断するようにします。

```bash
set -eu
```

### 2. ファイル群の比較

実行結果と期待結果を比較する際に便利な関数を定義しておきます。

```bash
test_diff() {
  # 実行内容を出力します
  # $* は引数で与えられた内容を文字列的に取り出します
  echo "diff -r work/actual work/expected $*"
  # 比較します
  # -r は階層的に比較します
  # "$@" は引数で与えられた内容を展開して取り出します（空白区切りで別々の文字列として）
  diff -r "work/actual" "work/expected" "$@"
  # 差分有無を取り出します
  RES="$?"
  if [ $RES -eq 0 ]; then
    echo "（OK. 差分なし）"
  fi
  # 差分がある場合はこの関数をエラーとしてシェルを終了させるために戻り値で成否を返します
  return $RES
}
```

```bash:使い方
test_diff -x zzzz
```
- 新旧のディレクトリを引数で渡します。diff と同様のオプション引数が使えます。
  たとえば `-x` で除外するディレクトリを指定できます。

```:出力(OK)
diff -r work/actual work/expected -x zzzz
（OK. 差分なし）
```

```:出力(NG)
diff -r work/actual work/expected -x zzzz
diff -x zzzz -r work/actual/file1.txt work/expected/file1.txt
1,1c1,1
< aaa
---
> bbb
```

### 3. date の扱い

date で現在日時を扱っている場合、それを Mock するのは面倒です。
なので大元のスクリプトの方でも date の値は引数で渡すようにします。

```bash:テスト対象のスクリプトの冒頭
set -eu
CURRENT_YMD=${1:-第１引数にてYYYYMMDDで本日の日付を指定してください}
```
```bash:テスト実行
./script.sh "20231204"
```
```bash:本番実行
./script.sh "$(date +'%Y%m%d')"
```

## 参考

[Bashメモ #Bash - Qiita](https://qiita.com/waterada/items/406c6c55b77249f56778)
自動運転AIチャレンジ2023インテグレーション大会挑戦してみた

# 概要
本記事は、自動運転AIチャレンジを著者が挑戦してみた、という記事です。
本記事、ほぼお蔵入り確定だったのですが、アドベントカレンダーのネタとしてはいいかなということで思い出しつつ書いてみます。
もうほとんど覚えてないのでメモ書き程度です。

# 自動運転チャレンジについて
以下の通り。

https://www.jsae.or.jp/jaaic/

# チームの紹介文
チーム名：ミックファイア
チーム人数：1人（著者のみ）

# 参加した動機
Autowareに興味があり、パラメータやモジュールをいじったりしてみたかったので。
当初は高価なグラボを保持してなく様子見のつもりだったのですが、7月の下旬頃思い立ってグラボ買って参加しよう！となりました。
参加にあたりRTX 3090買いました。中古で9万しました！さすがに結構しましたね。。。

# 取り組んだ期間
・8月1週：グラフィックボード購入&パラメータ調整
・8月2週：Autoware-Mini環境構築
・8月3週：夏休み
・8月4週：パラメータ提出&スコア改善
ほぼ2週間くらいしかやってないですね。。。

# 取り組んだ内容
ひたすらplanningモジュールのパラメータ調整のみ。
時間がなかったので、ほとんどドキュメントは読まず、Slack並びに他参加者様の記事を参考にしてました。
本当はドキュメント読んで理解したかったのですがちょっと時間がなくて。。。

# 工夫した点
2つ目のL字クランクでカラーコーンを倒すので小回りがうまく効くようにパラメータ調整しました。

# 結果
最終順位は13位でした。（決勝進出ならず。。。）
3つ目のL字クランクでOut Of Laneとなってしまい、最後まで改善できず。。。

# 終わりに
今回は初参加かつ短期間ということでドキュメントの読み込みがほぼ行えなかったので
次回大会はちゃんとドキュメント読み込みたいと思います。
あとOSS連携とかやってみたいと思います。
自分流正規表現の考え方

全国の正規表現に対して苦手意識のある方へ

正規表現の基本の考え方を知って正規表現は頑張ればできます状態になりましょう。

## そもそも正規表現とは

英語では Regular Expressionと言います。

文字の検索といえば`cmd + F` Windowsなら `ctrl + F` が思いつくと思いますが

基本的には完全に一致した文字列を検索します。

これが正規表現を用いると更に柔軟な検索が可能となりURL、電話番号、メールアドレスなどののパターンの検索が可能になります。

例えばURLは`^(http|https)?://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$`のような書き方ですべての形式を表すことができます。

それではどう考えて書けばよいか筆者なりの考えを書いていきます。

## 個人的に正規表現を書くときの考え方

1. パターンを言語化する

1. 特殊な文字とエスケープが必要な文字を調べる

1. 位置を気をつけながら書き始める


### パターンを言語化する

初手でどんなパターンを正規表現で表すかを考えます。

- 文字数に制限はあるか？
- 使わない文字はあるか？ （英数記号など）
- 固定されている文字はあるか？（URLであれば先頭はhttp or https://{ドメイン}/{パス}）

といった感じでまとめます。

最初から書くのではなく最初に考えましょう。

### 特殊な文字とエスケープが必要な文字を調べる

目に見える文字と見えない文字を分けながら考えると書きやすいです。

#### 見える文字

半角英語、数字、記号などよく見るものを指しています

半角英語は`[a-zA-Z]`

半角数字は`[0-9]`, もしくは`\d`

半角英数は`\w`, もしくは[a-ZA-Z0-9]

ちなみに`O`と`0`を利用文字から外すという要望があれば`[A-NP-Z]`, `[1-9]`と書くことで実現できる。

記号に関しては正規表現で使われる`\, ., +`などの文字はエスケープする必要があるので注意。

#### 見えない文字

タブや半角スペース、改行なども含める場合は追加で調べましょう。

よく使うのは`\s`（すべての改行、スペース、タブ）, `\n`（LFの改行）, `\t`（タブ）などですね。


### 位置を気をつけながら書き始める

さぁ、準備ができたら書いていこう。

位置だけは気にする必要があるが下の例題を見ながら考えていくことにする。

ちなみにここで言う位置とは先頭、末尾と途中の固定文字だと思ってもらいたい。

## 練習

### 日付形式

個人的には最もシンプルでたくさん考えられる日付を練習の最初に入れたい。

日本では`YYYY-MM-DD`, `YYYY年MM月DD日`がよく使われ、イギリスでは`DD/MM/YYYY`がよく使われる。

`YYYY-MM-DD`を考えてみましょう。

#### 1. パターンの言語化

自明である気がするが順番を守って説明させてほしい。

`数値4桁` -> `-` -> `数値2桁` -> `-` -> `数値2桁`

となる。

#### 2. 特殊な文字とエスケープが必要な文字を調べる

今回はハイフンがあるもののエスケープは必要ない。

#### 3. 位置を気をつけながら書き始める

さぁ実際に書いていこう。

位置について、`^`と`$`をここで紹介したい。

`^`は先頭を示し、`$`は末尾を示す。

YYYY-MM-DDのみの文字列である場合は`^{YYYY-MM-DD部分の正規表現}$`と書くと良い。

そして数値は`\d`、N回連続は`{N}`とするから`^\d{4}-\d{2}-\d{2}$`となる。

## おまけ

VSCodeで検索をするときに正規表現を使うことが可能。

やり方は`cmd+F`で検索バーを出したら入力欄の一番右の`*`マークを含むアイコンをクリックすると正規表現の検索が可能になる。
音楽データでのSpecAugmentの最適なパラメーターは？

# はじめに
**SpecAugment**は、音声認識分野の分野で広く採用されてきたデータ拡張の手法です。この手法は、音声データに周波数方向や時間方向へのマスキングを適用することで、モデルがより汎用的で堅牢な学習を行えるようにするものです。
一方で、音楽データへのSpecAugmentの適用は、まだあまり探究されていません。音楽は、リズム、メロディ、ハーモニーなど、一般的な音声データとは異なる特徴を持っています。
この記事では、音楽データでのSpecAugmentの最適なパラメーターを検証していきます。


# セットアップ
音楽データと言っても予測するタスクによって性質は変わってきます。
キーやセクションなどは時間における長期的な依存関係があります。コードやリズムなどはそれよりかは短い依存関係があるでしょう。
今回予測するタスクとしては、ノート（構成音）、コード、コード（ルートノート）、コード（ベースノート）、キーの５つです。

モデルは[wav2vec2.0を改造して音楽の特徴量を作成する](https://qiita.com/anime_magic_2/items/69e4b8554be301a3b01d)という記事で作成したwav2vec2.0のフレームワークを利用したものです。特徴エンコーダーはフリーズし、Transformerのみをファインチューニングします。
特徴エンコーダー前にSpecAugmentを挿入して検証します。

マスキング方法は[SpecAugment++](https://arxiv.org/abs/2103.16858)で提案された**Mini-batch based mixture masking**を利用します。ゼロマスクの代わりにミニバッチ内の別のサンプルとミックスするというものです。

今回検証するパラメーターは、**マスクスパン**、**マスク率**です。時間方向のみを検証していきます。

# 検証
特徴エンコーダー前にSpecAugmentを挿入した場合を検証していきます。
特徴エンコーダー前にレイヤーは存在しないので入力のスペクトログラムに直接SpecAugmentを適用するということになります。

#### マスクスパン: 20ms
![d5587ab4-98ed-4614-b632-4bfeb9f6ebcd.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1275467/81b1d6a7-22d7-913f-2f76-cb60c8011836.jpeg)
マスクスパン20msの時のマスク率ごとの各タスクのロスです。ばらつきはありますが、全体的にマスク率40%くらいがよいようです。ただコードやノートは改善が少なく、あまり効果が見られませんでした。

#### マスクスパン: 80ms
![9fc56869-e78b-4a5f-ab7c-62539dd5f718.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1275467/7c9eee36-f9cb-3f13-6859-e64b2e9696db.jpeg)

#### マスクスパン: 200ms
![d4fd224b-60e7-49a4-a3fa-b488135a134b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1275467/09f22992-a1c0-2287-fe07-72f8c2c16b52.jpeg)
80ms、200msでは、マスクスパン20msの時と比較すると全体的に改善幅が少なくなっています。マスクスパンが長くなると予測が難しくなり、周囲のコンテキストから補完するようにモデルが学習してくれると期待していたのですが、あまりよくない結果となりました。

#### マスクスパン: 2080ms
![f840bf84-b090-4448-ab50-b675f6e46a73.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1275467/67205ee0-7b8c-a875-524a-80256b9b26e3.jpeg)

これはマスクスパン2080msのものです。80msや200msの時よりも改善幅が大きくなり、20msの時のものに近いです。2秒という長い期間をマスクしているのに正しく学習できていることに驚いてます。


# 結果
短いマスクスパン(20ms)か長いマスクスパン(2080ms)が有効で、中途半端な長さのマスクスパンはあまり精度を改善できないことがわかりました。マスク率はだいたい40%くらいが有効なようです。
周波数方向のマスクも試しましたがコードの精度が急激に悪化したため検証はスキップしました。
PowerBIサービスを使って、個人で他人にレポートを共有する方法

# 概要
PowerBI(以下PBI)デスクトップを使って作成したレポートを、せっかくなら他人に共有したいと思ったので、その方法の備忘メモです。

※自分で調べた内容なので、何か間違いやもっと良い方法があれば指摘いただければ助かります。

## 簡単な結論
以下のどちらかのアカウントが必要
- Office 365 E5(4750円/月)
- Office 365 E1(1250円/月) + Power BI Pro(1250円/月)

# 調査内容
## 前提
まず、前提としてPBIデスクトップは無料です。これでできるのは、自分のローカルPC内でPBIレポートを作るまでです。
実際に不特定多数に公開するにはPBI サービスを使うのが現実的です。

## PBI サービスについて
PBIサービスを使うには「Power BI Pro」(もしくはその上位版のPower BI Premium)が必要です。
https://powerbi.microsoft.com/ja-jp/pricing/

じゃあ1250円/月で使えるかというともう一つ問題があり、上記のライセンスはMicrosoftの企業アカウントでないと使用できません。

## 企業アカウント
PBIサービスを使うには企業アカウント(に紐づいたメールアドレス)が必要です。
https://learn.microsoft.com/ja-jp/power-bi/fundamentals/service-self-service-signup-for-power-bi

個人では作れないのかというとそんなことはなく、企業アカウントを個人で作ることは可能です。
https://www.microsoft.com/ja-jp/microsoft-365/enterprise/office365-plans-and-pricing

ただし、企業アカウントは有料でなおかつE1,E3,E5などのランクがあります。

## どの企業アカウントを作るか
E1は基本的な機能を持った企業アカウントですが、これ単体ではPBIサービスを使って公開する機能は持っていません。(E3も同様です)
一方で、E5は値段が高いですがPower BI Proのライセンスがデフォルトで含まれています。

なので、Power BI Proを使いたいだけなら、E1+Power BI Proのライセンスが安くすみます。
E5の他の機能も使いたい方や富豪の方はE5が楽でいいと思います。

## PowerBI Serviceを使うだけなら
Microsoft Fabric Previewという無料のライセンスがあり、これを使用すればPBIサービスを使用できます。
https://powerbi.microsoft.com/ja-jp/pricing/
ただし、
- 企業アカウントは必要です
- 他人には公開できません

Power BI Proのライセンスには無料期間がないので、とりあえずPBIサービスの使用感を試したい場合はこちらで良いかと思います。
第一世代　USB・PD給電

「aibo ers-11x/210で遊ぶ Advent Calendar 2023」の4日目です。

ers-110を外部電源から駆動できるように改造できました。
一方で、屋外のお散歩もできるようにしてみたいという考えもありました。
この機種の発売当初は存在しなかったUSBのPD給電を使う方法を考えました。

今回はポータブルバッテリーを利用し、一緒に歩きながら駆動するように工夫します。

:::note alert
警告
この記事について作者はいかなる責任も負いません。
バッテリーの分解、改造は非常に危険な行為です。
:::

:::note
業務外の個人的な検討活動です。
:::

### 部品調達
3Aを供給するためのポータブルバッテリーとトリガーケーブルを選定しました。

#### USB PD給電のポータブルバッテリー
少なくとも3Aを供給できるポータブルバッテリーを選定しました。
https://www.yodobashi.com/product/100000001007870882/

低価格の商品もあったのですが、使用中に供給電流が下がるとのレビューがあったので、デモの安定性を図るため高めの商品にしました。

#### PDトリガーケーブル
15V5AのPDトリガーケーブルを選定しました。
https://www.yodobashi.com/product/100000001006049964/

プラグが5.5/2.2mmだったので、変換アダプタを別途使用しました。

#### 動作確認
aiboのコントロールはサウンドコマンダーの仕組みを流用しました。その説明は後日行います。

サウンドコマンダーのエミュレータをスマホ用に作成し、1時間ほど散歩できました。

本物の犬の散歩よりとても遅い速度でしたが、強く引っ張ったりしないので、お年寄りの散歩用には向いているのかもしれないです。
Good&Newを取り入れたらアイスブレイクの時間がちょっと楽しくなった話

## アイスブレイクのマンネリ化をどうにかしたかった
定例MTGだったり、コミュニケーションを目的とした時間だったりに冒頭に **アイスブレイク** を行うケースってあると思います。
最初の方は話題があるので特に困ることもないのですが、しばらく経つと話題がなくなりマンネリ化してきた経験ありませんか。

私自身も何度かそうのような経験をしたことがありまして、その度にもうちょっと上手いことできないかなーと思ってました。

そんな中あるプラクティスを見つけて2ヶ月ほどやってみたのでその共有をしようと思います。
そのプラクティスは**Good&New**です。


## Good&Newとは？
```
・ 24時間以内に起こった「良かったこと（Good）」と「新しい発見（New）」を発表
・ 1分程度で話す
・ 発表した人に対して、全員で拍手をする
```
こういった内容のプラククティスです。
アメリカの教育学者ピーター・クライン氏がチームの活性化のために開発したとのことです。

ググった限りだとエンジニア組織に取り入れた例は見かけませんでしたが、非常にシンプルなルールなので取り入れやすいと思いやってみました。


## ちょっとルールを変えてやってみた
Good&Newを見つけたとき「まずはやってみませんか」とチームに提案しました。

社内でプロジェクトとは別にチーム制を導入しており、一週間に一度、コミュニケーションを目的として時間を取っていました。

Good&Newのルールを見た時 **24時間以内は自分達には当てはまらない** なと思ったので、MTGの頻度に合わせて **一週間以内で起こった出来事** にルールを変更しました。

また、話題に困ったときはエンジニアらしくその週の技術的な新しい学びを発表しよう、としました。


## やってみた感想
- 良い出来事を共有してもらうのは単純に気持ち良い
- 1分ほどの短い時間であれば準備せずに話せる。(みなさんも話せていた)
- 全員に喋る機会が回ってくるので若手のメンバーの様子がわかるのは良い
    - アイスブレイクと言いつつ人数が多いと発言しないメンバーも出てくるがそれを防げる
- リモートで普段合わないメンバーの様子がわかるのは良い
- 考えたこともない視点で良いことや新しいことを聞く事は新しい発見になる
    - 弊社は離島でリモートワークしているメンバーもおり、離島の様子を聞くのは特に面白かったです
- アイスブレイク終わった後に雑談のネタになる
- 司会の人が話題を考えて話を人に振るコストがかからないのが良い
    - これが一番良い効果かもしれないです。人が少ないとそこまで苦じゃないと思いますが、多いと大変なので

## 最後に
以上の感想をまとめて、Good&Newを取り入れたアイスブレイクは以前よりポジティブな時間になりました。

しかし、Godd&Newも長期間続けるとマンネリ化するかもしれません。
チーム状況に応じてはGood(良いこと)だけ発表するとか、僕らのチームみたいに一週間の出来事を対象とするなど工夫していくと良いかもしれません。

また、そもそもアイスブレイクを実施するorしないを検討するとよいかもしれません。

それでは！良いチーム開発を。

## 参考
参考としていくつかGood&Newの記事を貼っておきます。
- https://thanks-gift.net/column/communication/good-new/
- https://ideapoint.co.jp/blog/ceoblog025/
- https://satorunoblog.com/good-and-new/
【時短？】Sigilでラクラク！？APIリクエスト

Elixir Advent Calendar 2023 15日目に参加させていただきます。

https://qiita.com/advent-calendar/2023/elixir

# TL; DR
**目指せcurlの書きごこち** :triumph:

```elixir
iex(1)> Mix.install [{:websigil, "~> 0.1.0"}]
:ok

iex(2)> import Websigil
Websigil

iex(3)> ~g{https://httpbin.org/user-agent}
%{"user-agent" => "req/0.4.5"}

iex(4)> ~g{https://qiita.com/api/v2/users/Syuparn}
%{
  "description" => "見習いエンジニア、記憶をあきらめ記録に頼ります",
  "facebook_id" => "",
  "followees_count" => 12,
  "followers_count" => 18,
  "github_login_name" => "Syuparn",
  "id" => "Syuparn",
  "items_count" => 109,
  "linkedin_id" => "",
  "location" => "Kanagawa, Japan",
  "name" => "",
  "organization" => "",
  "permanent_id" => 239887,
  "profile_image_url" => "https://avatars3.githubusercontent.com/u/36665200?v=4",
  "team_only" => false,
  "twitter_screen_name" => "syuparn",
  "website_url" => "https://volatile-notepad.netlify.app/"
}
```

# はじめに
Sigilを使うことで、文字列リテラル等を手軽に作成できます。

```elixir:
# 式の埋め込み
iex(1)> ~c/2 + 7 = #{2 + 7}/
'2 + 7 = 9'
# 文字列リスト作成
iex(2)> ~w/i love elixir school/
["i", "love", "elixir", "school"]
```

https://elixirschool.com/ja/lessons/basics/sigils

このSigil、ユーザーが定義することも可能です。そこで今回は、URLを書くとレスポンスボディを返すSigilを作ってみました。

# しくみ

https://github.com/Syuparn/websigil

中身はいたってシンプルです。Sigilは `sigil_{文字}(string, [])` という関数で定義できるため、`sigil_g` 内部でHTTPリクエスト(`GET`)を行っています[^g]。

```elixir:lib/websigil.ex
defmodule Websigil do
  def sigil_g(string, []) do
    string
      |> URI.encode()
      |> Req.get!()
      |> Map.get(:body)
  end
end
```

エラーハンドリング等は一切考慮していないのでご了承ください :innocent:

# おわりに
「プログラミングElixir」を読んだ時から頭の片隅にあったネタを放出できました。~~Sigil本体よりもhexの公開に時間がかかりました~~
他にも面白いことに使えそうなので、アイデアが出たら作ってみたいと思います。

# 参考記事

https://qiita.com/torifukukaiou/items/4d842c6acae2b8967467

https://dev.classmethod.jp/articles/publish-elixir-library/

https://qiita.com/ma2ge/items/0e19bf3f03078f589096


[^g]: 当初はwebの `w` にしようと思ったのですが、`~w` は既にあるので GETの `g` にしました。
ブラウザのタブ間でのリアルタイム通信を p5.js で 1つずつ試す： Broadcast Channel API【完走賞ゲット-3】

:::note info
※ [Qiita の完走賞をゲットするための条件は「単一／複数のカレンダーに投稿した記事が合計25」です](https://twitter.com/Qiita/status/1593441648796524545)
:::

この記事は、「[完走賞ゲットのため小ネタ 25記事を投稿しようとチャレンジ v2 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/youtoy)」の 3日目の記事です。

## 今回の内容
今回の記事の内容は、2年以上前に以下の記事で紹介していた内容の続きです（ずいぶん時間がたってしまいましたが...）。

●ブラウザのタブ間でのリアルタイム通信を行う 4つの方法【概要編】 #JavaScript - Qiita
　https://qiita.com/youtoy/items/b202209d0eb36bad830f

 上記は、ブラウザのタブ間でリアルタイムに通信を行う場合、以下の 4つの方法があるという情報などを見かけ、そのソースコードがどんな感じになるか、概要を書いていたものでした。

1. Local Storage Events
1. Broadcast Channel API
1. Service Worker Post Message
1. Window Post Message

その後は、上記を試す機会がなかったのですが、以下の内容に関するテスト実装をやりたくなり（とりあえずは　MQTT を使った部分があり、それを置きかえたかった）、上記の内容を久しぶりに発掘してきました。

●「スクリーン上でブラウザのウィンドウを動かしたら描画に影響」「2つのブラウザのウィンドウの一方を動かすと他方に影響」という方向の実装作品の技術メモ #JavaScript - Qiita
　https://qiita.com/youtoy/items/945edb13856417c8c901

 ### Broadcast Channel API
そして、まずは「Broadcast Channel API」を試してみることにしました。

MDN では、以下のページで書かれているものです。

●ブロードキャストチャンネル API - Web API | MDN
　https://developer.mozilla.org/ja/docs/Web/API/Broadcast_Channel_API

 ## p5.js で簡単な実装を試す
 この Broadcast Channel API に関し、p5.js　を使った簡易な動作確認をやってみます。その際、それを試す環境として、Web上に用意されている「p5.js Web Editor」を使ってみます。

### 試した内容
それでは、試した内容について概要を以下に書きます。

#### 動作している様子
実際に、こんな感じで動作確認ができました。

以下では、「mouseMoved() が発生した時に mouseX・mouseY で円を描画しつつ、それらの 2つの座標の値を Broadcast Channel API で送信 ／ Broadcast Channel API で受信した 2つの座標を使って円を描画」ということをやっています。

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

#### ソースコード
上で紹介した内容の、送信側と受信側のソースコードを掲載してみます。

以下は送信側です。
mouseMoved() が発生した時に mouseX・mouseY を `channel.postMessage()` で送っています。それと、setup() のところで、 ブロードキャストチャンネルへの接続のための `new BroadcastChannel()` を入れています。

必要な実装は、非常にシンプルです。

```javascript:送信側
let channel;

function setup() {
  createCanvas(400, 400);
  background(220);

  channel = new BroadcastChannel("mouse_channel");
}

function mouseMoved() {
  if (channel) {
    const x = mouseX, y = mouseY
    channel.postMessage({ x,y });
    circle(x, y, 30)
  }
}
```

以下は受信側です。
setup() のところで、 ブロードキャストチャンネルへの接続のための `new BroadcastChannel()` を入れています。また、その後に `channel.onmessage` で、データを受信した時のイベントをトリガーに実行される処理を書いています。

必要な実装は、非常にシンプルです。

```javascript:受信側
let channel;

function setup() {
  createCanvas(400, 400);
  background(90);
  noStroke();
  fill(100, 150, 200);

  const channel = new BroadcastChannel("mouse_channel");

  // データを受信したときの処理
  channel.onmessage = (e) => {
    const { x, y } = e.data;

    background(90);
    text(`x: ${x}`, 10, 20);
    text(`y: ${y}`, 10, 40);

    circle(x, y, 100);
  };
}
```


## おわりに
ブラウザのタブ間でのリアルタイム通信を実現する方法に関して、今回「Broadcast Channel API」を試しました。その際に、オンラインの環境の p5.js Web　Editor を使って p5.js と組み合わせる形で試しました。

今回試したもの以外にも、冒頭に書いた方法が複数あるので、それらも試していければと思います。
プロダクト開発におけるフィードバックサイクルを加速させる為のリリースステージという考え方について

この記事は[MOSH Advent Calendar 2023](https://adventar.org/calendars/9548)3日目の記事です。

プロダクティビティーチームの[@soartec-lab](https://github.com/soartec-lab)です。

一日目に[スタートアップ企業で社内初のアドベントカレンダーを実施する技術](https://qiita.com/SoarTec-lab/items/44f4c4131a0a42a69bb4)で、アドベントカレンダーを通して組織としての新しい取り組みを行う際にもプロダクト開発の考え方を活かせた事について書きましたが、もう二週目が回ってきてしまいました。

プロダクティビティーチームとして普段は開発組織全体の生産性をシステム的なアプローチで解決する傍らプロダクトの開発プロセスや組織的なアプローチも行っている為、この記事ではプロダクト開発における開発プロセスの一つの考えを共有します。

**※ 現時点では私の考えに留まっており、MOSHの開発組織として実践している内容ではありません。**

# 背景

MOSHではプロダクトの開発におけるフィードバックサイクルの改善に目を向けており以下のような課題が見えていました。

- 仮説が不明瞭でユーザーの反応を見ながら検証を行いたい状況でもシステムを全て完成させる事を前提としているためリリースまでの見積もり及び実際の開発期間が長くなる
- 合わせてプロダクトのニーズが不明確なまま機能を作り込みすぎている

そこで、リリースステージと言う概念から、今の開発は何を目的としているのか明確にすることで、今必要な品質とデリバリーの認識を揃えたり過剰な作り込みを避けることができるかもしれないと思いアウトプットしてみます。

# リリースステージ

リリースステージとはプロダクト開発のフェーズを区切り目的を明確にする考え方です。

書籍[プロダクトマネジメント](https://www.oreilly.co.jp//books/9784873119250/)内では、別の書籍[Product Roadmaps Relaunched](https://www.amazon.co.jp/Product-Roadmaps-Relaunched-Direction-Uncertainty/dp/149197172X)を引用し、プロダクトのロードマップの構成要素の1つとして開発ステージを4つのフェーズに分けています。

私なりに解釈してプロダクト開発においての視点で私の理解をまとめてみました。

| ステージ | ゴール | 実験の対象 | 方法 | プロダクトの提供 | プロダクト利用の制約 |
| --- | --- | --- | --- | --- | --- |
| 実験 | 問題を理解し解決する価値があるかどうかを判断する | 問題の調査とソリューションの探索 | プロダクションコードは書かない、オズの魔法使いやコンシェルジュなどの方法 | - | - |
| アルファ | ソリューションが顧客にとって望ましいかどうかを判断する | 最小限の機能または、適切なソリューションの実験 | プロダクションコードのリリース | 少数のユーザー | ユーザーの課題を解決できなかった場合は機能が変更されたり削除される可能性がある |
| ベータ | 技術的な観点からソリューションがスケーラブルであるか判断する | プロダクション運用が可能か技術的な検証 | プロダクションコードのリリース | アルファよりも多いが一部のユーザー。 | 技術的に不安定な場合に機能が変更されたり削除される可能性がある |
| GA | 一般公開 | - | プロダクトの一般公開 | すべてのユーザー | なし |


それぞれのフェーズは段階的な実験であり、前フェーズの実験が完了しないまま次のフェーズに進めるのは非効率だと考えています。

具体的には、実験フェーズで「ユーザにとって解決する価値がどうか」が判断できない、開発自体無くなる可能性がある状態でプロダクションコードを書く事や、スケーラビリティーのあるアーキテクチャを考え念入りな計画を立てても、そのフェーズにおいては過剰である可能性があるので別のよりスピードが速い実験の方法を模索したいですね。

もちろん、対応する開発によってはこのフェーズをスキップすることもありますし、既存のプロダクトに対しスピードを持って実験が出来るなら実験フェーズでプロダクションコードをリリースすることもあると思います。

## リリースステージの事例

参考に段階的なリリースを行っているサービスをいくつか紹介します。

- Google Workspace
  - https://support.google.com/a/answer/11202276?hl=ja
- Google Cloud Platform
  - https://cloud.google.com/blog/ja/products/gcp/google-cloud-gets-simplified-product-launch-stages
- Dropbox
  - https://help.dropbox.com/ja-jp/account-settings/alpha-beta-product

# まとめ

リリースステージによる段階的なリリースを活かす事で、より高速にプロダクト開発のフィードバックサイクルを回す考えについて書いてみました。皆さんのプロダクト開発における1つの観点として役に立てますと幸いです。

明日は、同じプロダクティビティチームの[鳴瀬さん](https://github.com/ryy)です！よろしくお願いします〜！