OmniAICreator/Qiita-1.07M huggingface dataset:
Eth Indiaでプライズを取ったプロダクト(MeData)

さて、順序間違えたかなと思うのですが今回はEth Indiaで何を作ったか？についての記事です。

私たちはMeDataという、ZkPのユースケースを増やすためのCompute engineを作りました。 https://devfolio.co/projects/medata-3d92

→ZkPとは？証明者と検証者の二人の間で行われるプロトコル（対話のルール）の一種。
-証明者が持っている秘密が正しいことを検証者に対して証明をするときに、その秘密自体を渡すことなく証明する。つまり、検証者はゼロ知識。
上記がZkPとはなんぞや？に対する答えです。これだけだと情報不足かと思われるので、補足はこちらの動画がおすすめです。https://youtu.be/eAp2HSjDPPk

さて、具体的にはMina(というブロックチェーン)上でZkPを使いたい人やThird partyがスマコンを都度deployしなければいけない課題を、ZkPのアウトプットを出してあげる汎用性が高いengineを作ることで解決しました。
ZkPのことは知ってるけど、日常でどう使うの？とか自分が普段使ってるアプリで使うにはどうすればいいの？という課題を解決、その一部事例として今回はヘルスケア全般を採用しました。

実際のアーキテクチャはこんな感じです。
![スクリーンショット 2022-12-11 0.37.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3069912/be4d330e-a5ae-c9e2-0912-b4bfb08cf3ea.png)

他にも想定しているユースケースとしては下記のようなものがあります。
- ヘルスケア：健康データ全体を公開することなく、特定の危険因子をチェック。(1日の最大心拍数)
- ヘルスケア：特定の病気の治療を受けたい際に、住所や氏名を明かすことなくオンライン治療を受けれる。
- ファイナンス：実際のリターンを開示することなく、ポートフォリオの平均リターンが閾値以上であることを明らかにすること。

ちょうど本日(2022/12/16)、Aztecが100mのラウンドを発表していましたが、プライバシー領域は今後さらに重要になるので引き続きキャッチアップしていきたいと思います。

## 最後に
![appのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3069912/26d60ee7-716d-f872-d485-0e06b1d1b5c2.png)

Verooは、Blockchain技術を活用した「想いの巡るグルメSNSアプリ」です。食に対する熱量、例えばラーメンがめちゃくちゃ好きで年間400杯食べているとか、変態的に具材にこだわった中華料理を作っているなどのような、今まで直接お金にはならなかった食に対する情熱や熱量、その裏側にある想いがトークンを使うことで巡る世界。自分のラーメンに費やす熱量がコミュニティに承認される。自分がほんとにいいと思って作った食べ物がコミュニティで広まる。Verooは単なるSNSアプリではなく、クリエイターたちの想いが紡がれるソーシャルグルメアプリです。

Homepage: https://veroo.xyz/
Discord URL：https://t.co/VoT0gpsflA
【Linux】ディレクトリ構成について(FHS)

# Linuxのディレクトリ構成について
業務上でLinuxを扱っていれば、 /var/log 配下にsyslogが配置されている事や /home 配下にユーザーのホームディレクトリが配置されている事は、自然と覚えていく事だと思います。
上記のような構成は`FHS(Filesystem Hierarchy Standard)`というディレクトリ構造を定めた仕様書に基づいて、定められています。
ディレクトリの役割や格納されるファイルの場所等も、FHS内に示されています。

※FHSについては、以下リンクが参考となります。
[FHS_参考](https://www.pathname.com/fhs/)

FHSはツリー構造となっており、/(ルート)配下に複数のディレクトリが構成されています。
/(ルート)配下には、以下のようなディレクトリが存在します。

| ディレクトリ | 説明 |
|---|---|
| /(ルート) | ルートディレクトリ。ツリー構造の頂点となるディレクトリ。 |
| /bin | コマンド(cat,ps,mv等)の実行ファイルが格納されている。　　　　|
| /boot | システムの起動に必要なファイルが配置されている。 |
| /dev | デバイスファイルが配置されている。|
| /etc | システムやアプリケーションの設定ファイルが配置されている。 |
| /lib | /binや/sbinなどに置かれたコマンドが利用するライブラリが配置されている。|
| /media | リムーバブルメディア(CD/DVD)のマウントポイントとなっているディレクトリが配置されている。 |
| /opt | ソフトウェアのインストール先となる。(自身でインストールをしたソフトなど) |
| /proc | プロセスCPU使用率やメモリ使用率等の情報が保存されている。※仮想ファイルシステムで管理している為、ファイルは存在しない。 |
| /root | rootユーザのホームディレクトリ |
| /sbin | システム管理者が使用するコマンドの実行ファイルが格納されている。 |
| /tmp | 一時ファイルが配置されている。 |
| /usr | ユーザーが共有するデータが配置されている。(コマンドやライブラリ) |
| /var | システム起動中に可変されるデータが配置されている。(logなど) |
| /home | ユーザーのホームディレクトリ |
| /mnt | 一時的なマウントポイントにするためのディレクトリ |
| /run | 実行されているプロセスに関連する情報が配置されている。 |



上記の事を覚えておくと、どのディレクトリに何があるのかが分かりやすくなります。
index.htmlじゃないファイルをトップページにする方法

## はじめに
普通、サイトのトップページって```index.html```とか、```index.php```とかが普通ですよね。
でも、いろんな事情によって```top.html```をトップページにしたいとき、ありますよね。（ない?）

## .htaccessに書き込む
.htaccessに以下のように書き込みます。
```
DirectoryIndex top.html top.htm top.php
```
こうすることで、```top.html```をトップページにすることができるのです!

## 終わりに
なんに使うんだろ。
phpで改行ごとに配列で分ける方法

## はじめに。
備忘録。

## コード
```php
explode('\n',$mojis);
```

## 説明
```explode()```関数は区切り文字ごとに配列に分ける働きをします。例えば、
```php
$moji = "東京,神奈川,埼玉,千葉,茨城";
```
という文字列に
```php
explode(',',$moji);
```
とすると、
```php
array('東京','神奈川','埼玉','千葉','茨城');
```
というふうに返ってきます。

なので、区切り文字に改行を表す```\n```を入れてあげれば、改行ごとに配列になって出てくるわけです。

## 終わりに
データベースが使えない案件つらい...
ファイルのエンコードを EUC から UTF-8 に変換したい

20年も前のソースコードは EUC なので、これを UTF-8 に変換するのだ。。。

## iconv?
文字コード変換といえば iconv 一択なんだが、一括で変換するにはだるい。
~~~
$ iconv -f euc-jp -t utf8 README.ja
~~~

## nkf
今ではもう使われないと思われる nkf で行こうと思う。
~~~
$sudo apt install nkf
$ find -name '*.c' | xargs nkf --overwrite -w
$ find -name '*.h' | xargs nkf --overwrite -w
~~~

まぁ、これでいけたから良しとする。
Undefined class constant 'MYSQL_ATTR_MAX_BUFFER_SIZE'

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/f6de7206-ec28-f702-597c-a2528b083899.png)

# mysqlnd を指定してコンパイルした場合は、この定数はサポートされていません。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/a1e0063e-a17c-ba9d-1491-6fe9cf77fa8d.png)

PHP Fatal error:  Uncaught Error: Undefined class constant 'MYSQL_ATTR_MAX_BUFFER_SIZE'

https://www.php.net/manual/ja/ref.pdo-mysql.php#pdo.constants.mysql-attr-max-buffer-size

mysqlnd は PHP 5.4 以降のデフォルトです。

https://github.com/zeruniverse/Password-Manager/issues/90

m4 の方だと特別指定しなければ libmysqlclient が使用され、w32 の方だと逆に mysqlnd が使われるようです（公式のWindows版バイナリも mysqlnd を使うようにビルドされている）。

https://ngyuki.hatenablog.com/entry/20120618/p1

https://man.plustar.jp/php/mysqlinfo.library.choosing.html

https://qiita.com/smzk/items/d1792bcd9657835e21d9
PG16:Non-decimal integer literals

# はじめに
にゃーん。趣味でポスグレをやっている者だ。

この記事は[PostgreSQL 16 全部ぬこ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/pg16-all-nuko) 21日目の記事です。
今回はPostgreSQL 16で追加された整数定数の記法について書いてみます。

# 概要

|項目|内容|
|:--|:--|
|タイトル|[Non-decimal integer literals](https://commitfest.postgresql.org/41/3292/)|
|Topic|SQL Commands|
|ステータス|commited|
|Last Modified|2022-12-14|
|概要|整数定数値の2進、8進、16進記法の追加|

# 変更内容
これまで整数定数値の記法として、2進、8進、16進の記法はサポートされていませんでしたが、PostgreSQL 16からサポートされるようになりました。
MLの議論の最初に、「SQL:202x ドラフトに準拠」という記述があったので、SQL準拠が主目的の改善項目のようです。

## 追加された記法
開発中の文書を見ると、こういう記法が追加されたようです。

> 0xhexdigits
0ooctdigits
0bbindigits

なお、x、o、bは、小文字、大文字ともOKのようです。

## 実行例

それぞれ16進、8進、2進での定数表記例を示します。

```sql
=# SELECT 0x7F, 0X0FF;
 ?column? | ?column?
----------+----------
      127 |      255
(1 row)

=# SELECT 0o77, 0X017;
 ?column? | ?column?
----------+----------
       63 |       23
(1 row)

=# SELECT 0b1101, 0B01011;
 ?column? | ?column?
----------+----------
       13 |       11
(1 row)

=#
```

なお、2進、8進、16進表記と小数点や指数表記は併用できないようです。

以下は小数点を併用してエラーになる例です。

```sql
=# SELECT 0f11.1;
ERROR:  trailing junk after numeric literal at or near "0f"
LINE 1: SELECT 0f11.1;
               ^
=# SELECT 0o711.1;
ERROR:  syntax error at or near ".1"
LINE 1: SELECT 0o711.1;
                    ^
=# SELECT 0b011.1;
ERROR:  syntax error at or near ".1"
LINE 1: SELECT 0b011.1;
                    ^
=#
```

以下は指数表記と併用しようとしてエラーになる例です。

```sql
=# SELECT 0f11e2;
ERROR:  trailing junk after numeric literal at or near "0f"
LINE 1: SELECT 0f11e2;
               ^
=# SELECT 0o711e2;
ERROR:  trailing junk after numeric literal at or near "0o711e"
LINE 1: SELECT 0o711e2;
               ^
=# SELECT 0b011e2;
ERROR:  trailing junk after numeric literal at or near "0b011e"
LINE 1: SELECT 0b011e2;
               ^
=#
```

# おわりに
言われてみれば数値定数の2進、8進、16進の記法ってPostgreSQLのSQLを書くときに使ったことなかったなあと。
また、SQL標準に準拠しようという動きはPostgreSQLらしいなとも思いました。
「たのしいRuby」オブジェクト指向の特徴

Rubyの本、買ってきた。「たのしいRuby」勉強しながらtwitterに投稿した文を加筆訂正してQiitaに投稿する。今回はオブジェクト指向の特徴。
Twitter、Green_helmet@bethlehem4099
Qiita、@dosaidon
## 参考文献
この記事は以下の情報を参考にして執筆しました。
-[たのしいRuby、高橋征義、後藤裕蔵著、 まつもとゆきひろ監修、SBクリエイティブ株式会社、第6版2019年](https://www.amazon.co.jp/%E3%81%9F%E3%81%AE%E3%81%97%E3%81%84Ruby-%E7%AC%AC6%E7%89%88-%E9%AB%98%E6%A9%8B-%E5%BE%81%E7%BE%A9-ebook/dp/B07PNN3TYF/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=1671278506&sr=8-1)
-[『たのしいRuby 第6版』サポートページ、ソースコード](https://tanoshiiruby.github.io/6/index.html)


### オブジェクト指向の特徴
✅オブジェクト
・プログラムの処理の対象
・データとデータを操作するための手続き（メソッド？）をまとめたもの
✅カプセル化
オブジェクトが管理するデータを外部から直には操作できないようにすること
✅ポリモーフィズム
同じ名前のメソッドが複数のオブジェクトに属すること、そしてオブジェクトによって異なる結果が得られること
✅ダックタイピング
アヒルのように歩き、アヒルのように鳴くものはアヒルに違いない
ここの説明はよくわからなかった。この後の例題もよくわからない。
まあ、ダックタイピングでは、おなじメソッドで違う種類のオブジェクトを扱えると言うことか？

## 演算子、エラー処理と例外、ブロック
はい。

これで、たのしいRubyの第2部(文法編)まで終了
Green_helmet@bethlehem4099·9月5日

# Rubyを完全に理解した

で、この「たのしいRuby」本の評価だが点数は80点。
Rubyの勉強を始めようという人におすすめできる。
短い例題が豊富なので自分でタイプして実行すると自然にRubyの文法を理解できる。
ではなぜ20点減点なのかと言えば、クラスとインスタンスの説明がよくわからなかった。
もう一つ第2章が長くて途中で飽きた。ページ数を半分にして欲しい。
さらにもう一つ、自分はM1 MacBookではコマンドライン、iPhone/iPadではRubyistを使ってRubyを勉強したが巻末の実行環境準備は古くて参考にならなかった。

# 言語としてのRuby

さて、言語としてのRubyだが色々素敵な構文が、てんこ盛りだった。Rubyを一度みっちりやっておけば他の言語の習得はあっと言う間にできる思う。

どっと、はらい。
***Green_helmet@bethlehem4099·9月5日***
dj-rest-authとdjango-rest-authの違いについて

ちゃっかりハマったので誰かのために書いておきます。

Djangoには、ログイン周りのパッケージとして以下の2つがあります。

・django-rest-auth
・dj-rest-auth

むちゃくちゃ名前が似ているので、ややこしいですが、別物です。

僕はこれが別物と気づかず（というか2つ存在していることに気づかず）結構ハマりました。

## django-rest-auth
元からあったDjangoのログインライブラリ。

## dj-rest-auth
`django-rest-auth`をフォークして始まったライブラリ。

[こちら](https://github.com/iMerica/dj-rest-auth)の一番下に書いてました。

>Acknowledgements
This project began as a fork of django-rest-auth. Big thanks to everyone who contributed to that repo!


## 要するに
`django-rest-auth`は古くて、`dj-rest-auth`こっちが開発が続けられている最新版のライブラリって感じですかね。

元のライブラリ開発した人どこいっちゃったんですかね😢

でも、フォークしてまた開発してくれる人がいるのはマジありがたいですね。。。ライブラリなかったら何も出来ないなんちゃってエンジニアなので、感謝しつつ有り難く使わせてもらいます！！！

終わり。
NCMB Flutter SDKでボイスレコーディングアプリを作る（その3：ファイルストアの検索と録音データの再生）

NCMBのFlutter SDKを使ってボイスレコーディングアプリを作ります。録音した音声をNCMBのファイルストアへアップロードし、逆にダウンロードして再生できるアプリです。

[前回の記事では音声録音処理と、NCMBのファイルストアへアップロードする処理を実装しました](https://qiita.com/goofmint/items/c18cecb25c796dc04f81)ので、今回はファイルストアの検索と一覧表示、そしてデータの再生までを実装します。

## コードについて

今回のコードは[NCMBMania/flutter-voice-recorder](https://github.com/NCMBMania/flutter-voice-recorder)にアップロードしてあります。実装時の参考にしてください。

## 画面が表示された際の処理

ステートフルウィジェットが初期化されたタイミングで、ファイルの取得を行います。それは `_files` の中に入れます。

```dart
// ファイルストアにある既存録音データの一覧
List<NCMBFile> _files = [];

@override
void initState() {
	// NCMBのファイルストアからファイルを取得
	_loadFiles();
	super.initState();
}
```

`_loadFiles` の内容は以下の通りです。

この時、ファイル名 `fileName` に対して `regex` を指定しています。これは正規表現を使って検索する機能です。すべてのレコーディングデータは `record_` ではじまっていますので、それに該当するデータだけを抽出しています。

```dart
// NCMBのファイルストアからファイルを取得する処理
Future<void> _loadFiles() async {
	// ファイル検索用クエリー
	var query = NCMBFile.query();
	// 検索条件（ファイル名がrecord_で始まるもの）
	query.regex("fileName", "record_.*");
	// 検索実行して、NCMBFileのリストに変換
	final files = (await query.fetchAll()).map((f) => f as NCMBFile).toList();
	// ステートに適用
	setState(() {
		_files = files;
	});
}
```

## 一覧表示する

`_files` が更新されると、画面に録音データとして一覧表示されます。

```dart
Expanded(
	child: ListView.builder(
		itemBuilder: (BuildContext context, int index) =>
				AudioListPage(file: _files[index], onTap: _onTap),
		itemCount: _files.length,
	),
),
```

### AudioListPageについて

AudioListPageは受け取ったNCMBFileのインスタンスを表示するだけです。また、タップされたら親ウィジェットの `onTap` を呼び出します。

```dart
class _AudioListState extends State<AudioListPage> {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(widget.file.getString("fileName")),
      onTap: () => widget.onTap(widget.file),
    );
  }
}
```

### onTapについて

タップされると、 `_MyAppState` の `_onTap` が呼び出されます。これは単に選択されたファイルを `_file` に適用するだけです。

```dart
// 再生対象のファイル
NCMBFile? _file;

// 再生するファイルを選択した際の処理
void _onTap(NCMBFile file) async {
	// ステートに適用
	setState(() {
		_file = file;
	});
}
```

そして、 `_file` が更新されると、再生用ウィジェットが表示されます。

```dart
// ファイルが選択されたら、音声再生用ウィジェットを表示する
_file != null
		? PlayerPage(audioFile: _file!)
		: const Text("音声ファイルを選択してください")
```

## 録音データを再生する

PlayerPageの内容です。送られてきたNCMBFileから実データ（録音データ）をダウンロードし、バイト文字列をblob URIに変換します。NCMBFileでの実データ取得は `contents` メソッドになります。このメソッドを実行したタイミングでダウンロード処理が行われます。

```dart
Future<void> _loadAudioFile() async {
	// ファイルストアから実データをダウンロード
	var data = await widget.audioFile.contents();
	// Uint8ListをByteDataに変換
	var blob = ByteData.sublistView(data);
	// さらにByteDataをBlob URIに変換
	var path = webFile.Url.createObjectUrlFromBlob(webFile.Blob([blob]));
	// Blob URIを再生
	await _player.setUrl(path);
}
```

後は画面上の再生ボタンを押すと、音声が再生されます。

## 注意点

Androidはwebaとmp4両方を扱えるはずですが、iOSの場合はwebaファイルを再生できません。iOSの場合は拡張子によって再生できる、できないを判別した方が良いでしょう。

## まとめ

今回でボイスレコーディングアプリの実装は完了です。ファイルストアへのアップロードと検索、そしてダウンロードの方法が分かったかと思います。

Flutter SDKでは他にも認証、データストア、スクリプトなどの機能があります。ぜひお試しください。

[mBaaSでサーバー開発不要！ \| ニフクラ mobile backend](https://mbaas.nifcloud.com/)
NCMB Flutter SDKでボイスレコーディングアプリを作る（その2：音声録音とファイルストアへのアップロード）

NCMBのFlutter SDKを使ってボイスレコーディングアプリを作ります。録音した音声をNCMBのファイルストアへアップロードし、逆にダウンロードして再生できるアプリです。

[前回の記事では画面の説明とSDKの導入まで進めました](https://qiita.com/goofmint/items/ad456d5a1a14250a8a69)ので、今回は音声録音処理と、NCMBのファイルストアへアップロードする処理を実装します。

## コードについて

今回のコードは[NCMBMania/flutter-voice-recorder](https://github.com/NCMBMania/flutter-voice-recorder)にアップロードしてあります。実装時の参考にしてください。

## 録音処理について

録音処理は `lib/recording.dart` にて行っていますが、こちらについては[record \| Flutter Package](https://pub.dev/packages/record/example)をベースに、不要な部分（ポーズなど）を除外したものになります。実際の内容はそちらのURLを参考にしてください。

この録音処理が終わると、 `onStop` で指定した処理が呼び出されます。

```dart
// 録音用ステート（録音が終了すると、_onStopを呼び出す）
RecordingPage(onStop: _onStop),
```

## 録音終了時の処理

以下は `_onStop` 関数の内容です。

```dart
void _onStop(String? path) async {
	// この中に記述
}
```

### 録音データがなければ何もしない

最初に念のため、録音が拒否された場合の処理をしておきます。

```dart
// 録音ファイルがない場合は何もしない
if (path == null) return;
```

### ファイルストアにアップロード

NCMBの録音データをアップロードします（後述）

```dart
// ファイルをアップロードして、NCMBFileを取得
var file = await _upload(path);
```

### 録音データ一覧に追加

録音済みデータ一覧に追加します。

```dart
// ステートに適用
setState(() {
	_files.add(file);
});
```

### _onStopの全容

_onStopの全容としては以下のようになります。

```dart
// 録音終了時の処理
void _onStop(String? path) async {
	// 録音ファイルがない場合は何もしない
	if (path == null) return;
	// ファイルをアップロードして、NCMBFileを取得
	var file = await _upload(path);
	// ステートに適用
	setState(() {
		_files.add(file);
	});
}
```

## ファイルストアへのアップロード処理

`_upload` 関数の内容について解説します。

```dart
// ファイルをアップロードする処理
Future<NCMBFile> _upload(String path) async {
	// この中に記述する
}
```

### blob文字列からバイト文字列を取得する

レコーディングデータは `blob:http://` ではじまるURIになっています。これをバイト文字列に変換します。これはHTTPで取得するのが良いようです。

```dart
// blob:http://からバイト文字列を取得する
final res = await http.get(
	Uri.parse(path),
);
var bytes = res.bodyBytes;
```

### ファイル名を作成する

今回はrecord_ではじまるファイル名とし、タイムスタンプと拡張子（バイト文字列から取得）を使います。 mimeは `audio/mp4` のような形式になっていますが、場合によっては `audio/webm;〜` といった場合もあります。

```dart
// ファイル名作成
var ts = DateTime.now().millisecondsSinceEpoch;
// 拡張子を取得
final mime = lookupMimeType('', headerBytes: bytes);
final regExp = RegExp(r'^audio\/(.*)($|;)');
final ext = regExp.firstMatch(mime!)?.group(1);
var fileName = "record_$ts.$ext";
```

### アップロードの実行

ファイル名とバイト文字列を使って、NCMBへアップロードします。

```dart
// ファイルアップロード
return await NCMBFile.upload(fileName, bytes);
```

### _uploadの全容

_upload 関数の内容は以下の通りです。

```dart
// ファイルをアップロードする処理
Future<NCMBFile> _upload(String path) async {
	// blob:http://からバイト文字列を取得する
	final res = await http.get(
		Uri.parse(path),
	);
	var bytes = res.bodyBytes;
	// ファイル名作成
	var ts = DateTime.now().millisecondsSinceEpoch;
	// 拡張子を取得
	final mime = lookupMimeType('', headerBytes: bytes);
	final regExp = RegExp(r'^audio\/(.*)($|;)');
	final ext = regExp.firstMatch(mime!)?.group(1);
	var fileName = "record_$ts.$ext";
	// ファイルアップロード
	return await NCMBFile.upload(fileName, bytes);
}
```

## まとめ

今回はボイスレコーディングアプリの録音とファイルストアへのアップロード処理について解説しました。次は[ファイルストアの検索と一覧表示、録音データの再生までを実装](https://qiita.com/goofmint/items/58a579776d34885d9789)します。
NCMB Flutter SDKでボイスレコーディングアプリを作る（その1：画面の説明とSDKの導入）

NCMBのFlutter SDKを使ってボイスレコーディングアプリを作ります。録音した音声をNCMBのファイルストアへアップロードし、逆にダウンロードして再生できるアプリです。

まず最初の記事では画面の説明とSDKの導入までを進めます。

## コードについて

今回のコードは[NCMBMania/flutter-voice-recorder](https://github.com/NCMBMania/flutter-voice-recorder)にアップロードしてあります。実装時の参考にしてください。

## 利用技術について

今回は次のような組み合わせになっています。

- [NCMB Flutter SDK](https://pub.dev/packages/ncmb)
- [record](https://pub.dev/packages/record)
- [audio_session](https://pub.dev/packages/audio_session)
- [just_audio](https://pub.dev/packages/just_audio/)
- [http](https://pub.dev/packages/http)
- [mime](https://pub.dev/packages/mime)

## 仕様について

画面は1つになります。その画面上で録音、既存録音データの一覧表示、選択した録音データの再生を行います。

![localhost_57660_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ee7c56a4-379d-fe86-63ce-1d666c3dd8d0.png)


各ライブラリはWebに対応したものを利用しているので、iOS/AndroidはもちろんWebでも利用できます（iOS/Android向けにはパーミッション周りで追加設定が必要になりそうです）。

## 利用する機能について

ボイスレコーディングアプリで利用するNCMBの機能は次の通りです。

- ファイルストア
  - アップロード
  - 検索
	- ダウンロード

## 画面について

今回は以下のステートフルウィジェットがあります。

### MyApp

画面構成およびNCMBのファイルストアへのアップロードや検索を行います。

### RecordingPage

音声のレコーディングを行います。コードは[record \| Flutter Package](https://pub.dev/packages/record/example)を参考に、今回のデモでは使わない部分をなるべく削ったものになっています。

### PlayerPage

選択された音声データを再生します。[\[Flutter\] just\_audioで音を再生する](https://zenn.dev/r0227n/articles/085c234061235e)を参考に、今回のデモでは使わない部分をなるべく削ったものになっています。

### AudioListPage

ファイルストアの既存録音データを一覧する際の、1行辺りのデータを表示するウィジェットです。

### SDKのインストール

必要なライブラリ、SDKをflutterコマンドでインストールします。

```
flutter pub add ncmb
flutter pub add record
flutter pub add audio_session
flutter pub add just_audio
flutter pub add http
flutter pub add mime
```

## NCMBのAPIキーを取得

[mBaaSでサーバー開発不要！ | ニフクラ mobile backend](https://mbaas.nifcloud.com/)にてアプリを作成し、アプリケーションキーとクライアントキーを作成します。

## 初期化

初期化は `lib/main.dart` にて行います。まずNCMB SDKをインポートします。

```dart
import 'package:ncmb/ncmb.dart';
```

そして main 関数の中で初期化します。

```dart
void main() {
  // NCMBの初期化
  NCMB('YOUR_APPLICATION_KEY',
      'YOUR_CLIENT_KEY');
  runApp(const MyApp());
}
```

これでNCMBの初期化が完了します。

## まとめ

今回はボイスレコーディングアプリの仕様と画面、NCMBの初期化までを解説しました。次は[レコーディング処理を実装](https://qiita.com/goofmint/items/c18cecb25c796dc04f81)します。
HiveのARRAY、STRUCT型とNULLと空配列と

# はじめに
クエリエンジンとしてHiveを使用しています。
テストデータ作成等でARRAY、STRUCTなどのComplex型をNULLにしたいとき、そしてSTRUCT型のARRAYを空にしたいときのTips記事です。

# 結論
- ARRAY、STRUCT型などのComplex型をNULLにするときはIF関数が使えます。
- STRUCT型のARRAYを空にしたいときはIF関数とCOLLECT_LISTの組み合わせが使えます。

# Complex型をNULLにするとき
弊社のエンジニアブログで既に紹介されています。
https://developers.microad.co.jp/entry/2018/10/19/170001

具体的には以下のように書けます。

```hql
INSERT INTO example_table SELECT 1, IF(FALSE, NAMED_STRUCT('field', 1), NULL), IF(FALSE, ARRAY(2), NULL);
```

# STRUCT型のARRAYを空にしたいとき
今回メインで書きたかったのはこちらです。
検索してみると、例えば以下のような解決方法が提案されていました。

```hql
select a.id, collect_list(b.str) my_array
from
(select 2 id ) a
  left join (select 1 as id, named_struct('name',null,'value',null) as str) b
            on a.id=b.id
group by a.id  
```

https://stackoverflow.com/questions/56016700/how-to-create-an-empty-array-of-struct-in-hive より抜粋

こんなに大変なのか...と思ったのですが、前述したComplex型をNULLにする方法とCOLLECT_LISTを組み合わせることで簡単になりました。
具体的には以下のように書けます。

```hql
INSERT INTO example_table SELECT COLLECT_LIST(IF(FALSE, NAMED_STRUCT('field', 1), NULL));
```

NULLとして認識されているSTRUCT型を配列にするだけです。

# まとめ
HiveのARRAY、STRUCTなどのComplex型に関するTipsでした。
皆さまもHiveと上手く付き合っていきましょう。
NCMBのFlutter SDKを使ってカレンダーアプリを作る（その2：認証処理の実装）

NCMBのFlutter SDKを使ってカレンダーアプリを作ります。予定を登録したり、カレンダーライブラリ（[table_calendar](https://pub.dev/packages/table_calendar)）を使って予定を表示できるというアプリです。

[前回の記事では画面の説明とSDKの導入までを進めました](https://qiita.com/goofmint/items/0f44ad80ffeeb686758f)ので、今回は認証処理を実装していきます。

## コードについて

今回のコードは[NCMBMania/flutter\-calendar](https://github.com/NCMBMania/flutter-calendar)にアップロードしてあります。実装時の参考にしてください。

## 認証画面について

![localhost_56942_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/7751ea81-72b6-07b3-3af4-4bd02f1f68d4.png)


すでに紹介済みですが、認証画面は以下のようになります。ID/パスワード入力欄があって、ボタンを押すと `_login` 関数が実行されます。

```dart
@override
Widget build(BuildContext context) {
	return Scaffold(
			appBar: AppBar(title: const Text('ログイン&サインアップ')),
			body: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
				Row(mainAxisAlignment: MainAxisAlignment.center, children: const [
					SizedBox(
							height: 100,
							child: Text(
								'ユーザー名とパスワードを入力してください',
							)),
				]),
				SizedBox(
						height: 50,
						width: 250,
						child: TextField(
							decoration: const InputDecoration.collapsed(hintText: 'ユーザー名'),
							onChanged: (value) {
								setState(() {
									_userName = value;
								});
							},
						)),
				SizedBox(
					width: 250,
					height: 100,
					child: TextField(
						obscureText: true,
						decoration: const InputDecoration.collapsed(hintText: 'パスワード'),
						onChanged: (value) {
							setState(() {
								_password = value;
							});
						},
					),
				),
				TextButton(onPressed: _login, child: const Text("ログインする"))
			]));
}
```

## ログイン処理について

ログイン処理は、以下のような手順で行われます。

- ユーザーの新規登録
- ログイン処理

すでにユーザー登録を行っていた場合、ユーザーの新規登録はエラーになります。今回はユーザー登録とログインを兼ねているので、エラーが出たとしてもそのまま続けてログイン処理を行っていきます。

### ユーザーの新規登録

取得した入力値を使ってユーザー登録処理を行います。エラーが出たとしても無視します。

```dart
try {
	// ユーザー登録処理
	await NCMBUser.signUpByAccount(_userName, _password);
} catch (e) {}
```

### ログイン処理

そのまま続けてログイン処理を実行します。ログインがうまくいったら、 `widget.onLogin();` を呼び出して結果を通知します。

```dart
// 成功しても失敗してもそのままログイン処理
await NCMBUser.login(_userName, _password);
widget.onLogin();
```

ここまででNCMBを使った認証処理の完成です。

## 認証後のユーザー情報について

認証後にユーザー情報を取得する際には、下記のように記述します。

```js
var user = await NCMBUser.currentUser();
```

認証していない場合には `null` が返ってきます。これを使って認証状態の判別が可能です。

## まとめ

今回はカレンダーアプリの認証処理について解説しました。次は[カレンダー表示と予定の登録処理を実装](https://qiita.com/goofmint/items/43ae04f9d06b3c68268b)します。
Qiitaのエディタの「スクロール位置の同期」はどのように実現されているか

この記事は、 [Qiita株式会社のカレンダー | Advent Calendar 2022 - Qiita](https://qiita.com/advent-calendar/2022/qiita-inc) の 17 日目の記事です。

## はじめに

今年（2022年）の6月末にエディタのアップデートがベータ版としてリリースされました。（その後、7月末に正式版としてリリースされました）

https://blog.qiita.com/release-qiita-editor-beta-2022/

このアップデートでいくつか改善・変更された点がありましたが、その中でも
**「編集エリアとプレビューのスクロール位置の同期」**
は、大きなアップデートでした。

今回は、その **「編集エリアとプレビューのスクロール位置の同期」** をどのように実現しているかについて書きます。

## アップデート前でのQiitaのエディタについて

Qiitaのエディタは左右で分かれており、左側が「編集エリア」、右側が「プレビューエリア」になっています。（PCの場合）

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/bfbd1917-454c-deb0-27a2-4b3dbc503894.png)

（スクショはアップデート後のものですが...）

左側でマークダウンを編集し、右側でプレビューを見ることができるようになっています。

編集している内容をリアルタイムでプレビューできる良さがありますが、記事が長くなってくると左側と右側の対応がわかりにくくなります。
結果、執筆体験の悪化に繋がります。

## どのように同期させるか

### マークダウンとHTMLの対応関係

同期させるには、まず「マークダウン」と「マークダウンから出力されたHTML」との対応関係を取る必要があります。

Qiitaでは、以下のように行単位で対応関係を取るようにしています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/6bf6d487-acbd-98ad-e778-9ff221599301.png)

どのようにして対応関係を取るかですが、
マークダウンパーサーのライブラリで出力されたHTMLに **マークダウンでの行数** を出力してくれるものがあるので、それを使うと簡単にできます。

Qiitaでは、[qiita_marker](https://github.com/increments/qiita_marker)の`sourcepos`オプションを使うことで取得しています。

以下は`qiita_marker`の出力の例です。

```html
<p data-sourcepos="1:1-1:169">この記事は、 <a href="https://qiita.com/advent-calendar/2022/qiita-inc">Qiita株式会社のカレンダー | Advent Calendar 2022 - Qiita</a> の 17 日目の記事です。</p>
<h2 data-sourcepos="3:1-3:15">はじめに</h2>
<p data-sourcepos="5:1-5:192">今年（2022年）の6月末にエディタのアップデートがベータ版としてリリースされました。（その後、7月末に正式版としてリリースされました）</p>

...
```

これによってマークダウンのテキストとHTMLの対応関係が取れるようになります。

### スクロール位置の同期

上記で、マークダウンとプレビュー側のHTMLとの対応関係が取れるようになりました。

次に、編集エリアがスクロールされたときに、プレビューも対応する位置にスクロールしてあげる必要があります。

はじめに、編集エリアとプレビューのどこを対応させてあげるかを考える必要があります。
Qiitaでは、編集エリアで表示されている一番上の行を基準として、プレビューと同期するようにしています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/a4885653-2197-ba8a-461f-ae8a8c2497ce.png)

次に、どのようにして編集エリアで表示されている一番上の行数を取得するかです。

やり方としてはいくつかあると思いますが、Qiitaでは[CodeMirror 6](https://codemirror.net/)から行数を計算し、取得するようにしています。

そして、「マークダウンの行数」と「プレビュー側の要素のスクロール Height」のマップを用意しておき、編集エリアのスクロールイベントに応じてプレビュー側もスクロールさせてあげることで実現されています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/8c68e818-9e3c-5b06-73f0-9395b2cda497.png)

他に、

- 空行などの場合に対応する要素がない場合
- 「マークダウンの行数」と「プレビュー側の要素のスクロール Height」のマップの生成の頻度


などを考慮する必要がありますが、主に上記の方法でスクロール同期を実現できます。

## さいごに

Qiitaのエディタアップデートの「編集エリアとプレビューのスクロール位置の同期」について書きました。
エディタアップデートによっていくつか改善はされましたが、まだまだ改善の余地があると考えています。

ですので、ぜひエディタを使っていただき、フィードバックなどいただけると幸いです。

---

ぜひ、 [Qiita株式会社のカレンダー | Advent Calendar 2022 - Qiita](https://qiita.com/advent-calendar/2022/qiita-inc) を購読設定して、明日の記事もご覧いただけると嬉しいです。
LogyanGFXでグラフィックを横スクロールする

# はじめに
この記事では、LogyanGFXを使ってグラフィックスの横スクロールについて記載します。
ADコンバータで計測した電圧をオシロスコープのような波形表示を行う場合等に応用できます。

- ソースの修正
- Windows環境でのビルド・デバッグ
- 実機での動作確認

# LovyanGFX for Windowsの環境構築
LovyanGFX for Windowsを使ってみた(https://qiita.com/pokibon/items/4f6f9b1f733ad60c708a )を参考にPC上に環境を構築します。

# グラフィックスの横スクロール
以下の例では、M5Stackの画面の一部にグラフを横スクロール表示を実現しています。PC側でデバッグするために、本来ADCで電圧を取得する部分をSINカーブを表示するようにしています。
スプライト上にプロット点が画面上に収まる間は左から順にプロットし、画面の右端まで達した時には、graph.scroll(-1.0);で1ドットスクロールして、空いた右端に新しい値をプロットしています。スプライトの画像が完成後、描画エリアにpushSprite()で描画を繰り返すことにより横スクロールを実現しています。

```
void adc_get()
{
	char buf[128];
	static uint16_t volt_discharge = 0;
	static uint16_t volt_charge = 0;
	float  ohm_battery = 0.0;
	float  current = 0.0;

	if (etime % time_span == 0) {
		if (discharge == false) {
			//Serial.println("Start Discharge");
			//startDischarge();
			discharge = true;
			time_span = RECOVERY_TIME;
		}
		else {
			//Serial.println("Stop Discharge");
			//stopDischarge();
			discharge = false;
			time_span = DISCHARGE_TIME;
		}
	}

	//voltage = analogReadMilliVolts(ADC_PIN) * 2L;
	float rad = etime * 6 * -0.0174532925;
	voltage = sin(rad) *  1000 + 3000;
	plot_y = map(voltage - 2000, 0, 2000, GRAPH_HEIGHT - 2, 0);

	if (discharge == false) {			// charge state
		if (old_discharge == true) {
			volt_discharge = (count_discharge) ? volt_discharge_total / count_discharge : 0;
			current_discharge_total += volt_discharge / DISCHARGE_REG * (DISCHARGE_TIME / 3600.0);
			//Serial.printf("volt = %d, dischage = %7.2f\n", volt_discharge, current_discharge_total);
			volt_discharge_total = 0;
			count_discharge = 0;
		}
		ohm_battery = 0.0;
		volt_charge_total += voltage;
		count_charge++;
	}
	else {							// discharge state
		if (old_discharge == false) {
			volt_charge = volt_charge_total / count_charge;
			volt_charge_total = 0;
			count_charge = 0;
		}
		ohm_battery = abs(voltage - volt_charge) * DISCHARGE_REG / voltage;
		volt_discharge_total += voltage;
		count_discharge++;
	}
	old_discharge = discharge;
	if (plot_x >= GRAPH_WIDTH - 1) {
		graph.scroll(-1.0);
		plot_x--;
		graph.drawPixel(plot_x - 1, GRAPH_HEIGHT / 2 - 1, TFT_DARKGRAY);
		graph.drawLine(old_plot_x - 1, old_plot_y, plot_x - 1, plot_y, TFT_RED);
	}
	else {
		graph.drawLine(old_plot_x, old_plot_y, plot_x, plot_y, TFT_RED);
	}
	old_plot_x = plot_x;
	old_plot_y = plot_y;
	plot_x++;
	graph.pushSprite(&lcd, GRAPH_START_X + 1, GRAPH_START_Y + 1);

	current = voltage / DISCHARGE_REG;
	current = (discharge) ? current : 0.0;
	sprintf(buf, "%8u, %4u, %7.2f, %7.2f, %7.2f\n", etime, voltage, current, current_discharge_total, ohm_battery);
	disp_value(voltage, current, ohm_battery, current_discharge_total, etime);
	etime++;
}
```
- Windows環境でのビルド・デバッグ
Visual Studio上でデバッグ可能です。ドット単位に表示不正などを目視で確認することができます。
https://twitter.com/pokibon/status/1603535037005123584?s=20&t=8OfZQdGjVuRVe9Aw3BinEA


- 実機での動作確認
デバッグが完了したソースをM5Stack BASICで実行してみました。
再現性もばっちりです。
![IMG_2977.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337553/daa3bba0-c714-ddc2-5778-ae32ef534bdc.jpeg)

# まとめ
LovyanGFX for Windowsを使うことにより、組込みデバイス書き込み前にPC上で動作確認、デバッグができるようになった。
LovyanGFXのスプライトを使うことにより、グラフィックの横スクロールをちらつきなしに実現できた。
Monacaでボイスレコーディングアプリを作る（その3：ファイルストアの検索と録音データの再生）

NCMBとMonacaを使ってボイスレコーディングアプリを作ります。HTML APIだけを使うので、プラグインを使わずに開発できます。録音した音声をNCMBのファイルストアへアップロードし、逆にダウンロードして再生できるアプリです。

[前回の記事では音声録音処理と、NCMBのファイルストアへアップロードする処理を実装しました](https://qiita.com/goofmint/items/691a3a97024090e745c6)ので、今回はファイルストアの検索と一覧表示、そしてデータの再生までを実装します。

## コードについて

今回のコードは[NCMBMania/monaca\-voice\-recorder](https://github.com/NCMBMania/monaca-voice-recorder)にアップロードしてあります。実装時の参考にしてください。

## 今回の処理について

今回の処理はすべて `www/pages/home.html` に記述しています。

## 必要な準備

今回はファイルストアにあるファイルに対してHTTPSアクセスを行います。これはNCMBの管理画面で有効にする必要があります。

この設定を有効にすると、管理画面のファイルストアでファイルを選択した際にURLが表示されるようになります。

このURLは以下のように構成されています。

```
https://mbaas.api.nifcloud.com/2013-09-01/applications/(アプリID)/publicFiles/(ファイル名)
```

アプリIDというのは、画面ではなく、URLでしか確認できない文字列になります。このアプリIDと、ファイルストアのファイルURLが入る変数を定義します。

```js
// 既存の録音データが入る配列
let files = [];
// ↑前回はここまで↓この下に追加

// 再生用のURI
let uri = '';
// アプリID
const appId = 'YOUR_APP_ID';
```

## 画面が表示された際の処理

Frameworkでは画面が表示された（マウントされた）際に `$onMounted` 関数が呼ばれます。それを使ってファイルストアからレコーディングされたファイルをダウンロードします。

この時、ファイル名 `fileName` に対して `regularExpressionTo` を指定しています。これは正規表現を使って検索する機能です。すべてのレコーディングデータは `record_` ではじまっていますので、それに該当するデータだけを抽出しています。

```js
// 画面が表示された際の処理
$onMounted(async () => {
	// NCMBのファイルストアから録音データをダウンロード
	files = await ncmb.File
		.regularExpressionTo('fileName', 'record_.*') // recordからはじまるファイルを対象に検索
		.fetchAll();
	// 描画更新
	$update();
});
```

## 一覧表示する

`files` が更新されると、画面に録音データとして一覧表示されます。

```html
<div class="list simple-list">
	<!-- 既存の録音データを一覧表示する -->
	<ul>
		${ files.map(file => $h`
			<li @click="${() => listen(file)}">
				${ file.fileName }
			</li>
		`)}
	</ul>
</div>
```

![IMG_1173.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/7a8ada2e-4bb8-fc9f-6fc5-765ce0d735f0.png)


## 録音データを再生する

一覧されたファイル名をタップすると、 `listen` 関数が呼ばれます。この関数は先ほどのアプリIDと、選択されたファイルの名前を用いてHTTPSアクセス用のURLを生成します。

```js
// 録音データを選択した際の処理
const listen = async (file) => {
	// 公開URLに変換
	uri = `https://mbaas.api.nifcloud.com/2013-09-01/applications/${appId}/publicFiles/${file.fileName}`;
	// 描画更新
	$update();
}
```

後は画面上の audio タグのsrc要素に対して適用し、タップで再生できます。

```html
<!-- 録音データが選択されたら audio タグを表示する -->
${ uri !== '' ?
	$h`<audio src="${uri}" controls style="width:100%;"></audio>`
	:
''
}
```

![IMG_1174.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/cff03332-4413-4a97-a17b-d26e4bb6dcbd.png)



## 注意点

Androidはwebmやweba、mp4などを扱えるはずですが、iOSの場合はwebm(a)ファイルを再生できません。iOSの場合は拡張子によって再生できる、できないを判別した方が良いでしょう。

## まとめ

今回でボイスレコーディングアプリの実装は完了です。ファイルストアへのアップロードと検索、そしてHTTPSアクセスの方法が分かったかと思います。

HTML APIは充実しているので、多くの機能がネイティブプラグインを介さずに利用できます。ぜひお試しください。

※ ファイルストアの[HTTPS公開からWeb Audio APIを使う方式に変更](https://qiita.com/goofmint/items/653cfe12049a825d9881)した記事を追加しました
python-->matlab呼び出し芸人の落とし穴解説

# matlab の話

以前、下記の記事にてpython と matlab の接続について書かせていただきました。

この記事はその続きです、接続の方法や手順などはこちらの記事か[公式のリファレンス(Python からの MATLAB の呼び出し)](https://jp.mathworks.com/help/matlab/matlab-engine-for-python.html)をお読みください。

https://qiita.com/hinata/items/c775989b4b2bf40472ce


今回は実際にpython用のmatlab ラッパー📯を作る際に引っかかったことについてまとめました

### 1. matlab eng の起動と時間とquit

matlab を python 上で扱う際には matlab.eng.start()し、matlab 内での処理を eng に渡すことで行う必要があります。
注意すべきなのは、その起動時間。
1 起動当たり数秒時間がかかります

- 確認のためのコード (※matlabroot にはお使いの matlab のエンジンの場所を入力してください、詳しくは[参照記事]()をご覧ください)

```py
import time
import sys
sys.path.append('matlabroot')
import matlab


startTime = time.time()
eng=matlab.engine.start_matlab()
endTime = time.time()
print(f"time:{endTime-startTime}[sec]")
```

- 結果

```sh
time:1.810612440109253[sec]
```

eng は一度起動すれば他の関数を呼び出す際にも使いまわすことができます。
これによって起動時間を抑えることができます。

公式ではエンジンの停止について以下のように記載しています。

> エンジンの実行中に Python を終了すると、Python はエンジンとその MATLAB プロセスを自動的に停止します。

[MathWorks, Python 用 MATLAB エンジンの起動と停止](https://jp.mathworks.com/help/matlab/matlab_external/start-the-matlab-engine-for-python.html)

なので python が正常終了するのであれば明示的なエンジンの停止は必ずしも必要というわけではありません。

しかし、コード上明示的に停止したり、コードの実行中に matlab engine を停止したい場合は以下のように行います。

```py
eng.quit()
```

~~※使い始めた当初は勘違いして毎度 起動--> 関数呼び出し --> 直後に quit を繰り返していました~~

### 2. ワークスペース変数と実行階層

matlab 関数の python ラッパーを実装するにあたり引っかかりやすいのはその処理の実行階層だと思います。
たとえば以下のような階層構成で main.py から matlab の wrapper 関数を扱うと仮定しましょう

```sh
.
├── myFuncs/
│  ├── myMatFunction.m
│  └── myPyWrapper.py
└── main.py
```

```matlab:myFuncs/myMatFunction.m
fuction output = myFunction(a, b)
    output = a + b
end
```

```py:myFuncs/myPyWrapper.py
import sys
sys.path.append('matlabroot')
import matlab

def myPyWrapper(
        eng : matlab.engine.MatlabEngine,
        a : int,
        b: int
        ) -> int :
        return eng.myFunction(a, b)
```

- main.py

```py
import sys
sys.path.append('matlabroot')
import matlab
from myFuncs.myPyWrapper import myPyWrapper

def main():
    print(myPyWrapper(a = 1,b = 2))

if __name__ == '__main__':
    main()
```

main.py から myFunc 内の matlab wrapper 関数を扱おうとしています。
このままだと実は呼び出しても使うことができません。

実は実行階層が異なる場合、階層内のワークスペースに変数や関数が定義されていないため関数を呼び出しても代入する先がわからなくなってしまうのです。

公式の[ベース ワークスペースと関数ワークスペース](https://jp.mathworks.com/help/matlab/matlab_prog/base-and-function-workspaces.html)には以下のようにあります。

> 入れ子関数またはそれを含む関数内の変数は、すべて明示的に定義しなければなりません。したがって、変数に値を代入する関数やスクリプトを呼び出すには、関数ワークスペースにその変数が既に存在していなければなりません。

したがって、実行時には.mat とワークスペースが共有できる階層まで降りる必要があります。 このままだと面倒ですね。

そんな時に便利なのが os.chdir です。下記のように使います。

```py
import os
os.chdir(os.path.dirname(os.path.abspath(__file__)))
```

呼び出し wrapper 上部でこれをするだけで実行階層を呼び出した関数と同じ階層で実行できるので、matlab の関数ワークスペースにアクセスして変数を認識できるようになります。

## まとめ

以上、python wrapper を作るときの引っかかりポイントを幾つかあげました。

本当はこのような wrapper を量産するのではなく、そもそも書き直す必要があると思うのですが、ぱっとテストがしたい場合や動作確認をしたいときには有用なのかなと思っています。

よかったら参考にしてみてください

~~今後もしかすると配列関係のコツもこっそり追記するかもしれません。文量多かったので後出しになると思います、ごめんさい。~~
xkeropi をビルドする (Ubuntu 32bit)

xkeropi をビルドした。

# 環境構築

## OS をインストールする
nasm 使っているので 32bit の ubuntu を使う。
[ubuntu-16.04.6-desktop-i386.iso](https://releases.ubuntu.com/16.04/) を Hyper-V にインストールする。

## あると便利な ssh (任意)
~~~
$ sudo apt install openssh-server
~~~

## あると便利な samba (任意)
~~~
$ sudo apt install samba
$ sudo vi /etc/samba/smb.conf

[homes]
  comment = Home Directories
  browseable = no
  writable = yes
  create mask 0644
  directory mask = 0755

$ sudo smbpasswd -a yui
$ sudo service smbd restart

~~~

## 必要なライブラリなどをインストール
~~~
$ sudo apt-get install xutils-dev
$ sudo apt-get install libgtk2.0-dev
$ sudo apt-get install libsdl1.2-dev
$ sudo apt-get install nasm
~~~

## ビルド
$ wget https://www.nonakap.org/keropi/xkeropi-20101107.tar.bz2
$ tar xf xkeropi-20101107.tar.bz2
$ cd xkeropi-20101107
$ xmkmf -a
$ make

## 実行してみる
![xkeropi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821068/13d46f5c-f180-89b0-10b7-6fc100906bca.png)

うぐぅ

## 強制的に動かしてみる。
アサーションに引っかかってるのは下記の場所
~~~:windraw.c
	/* 15 or 16 bpp 以外はサポート外 */
	if (visual->depth != 15 && visual->depth != 16) {
		fprintf(stderr, "No support depth.\n");
		return FALSE;
	}
~~~
Hyper-V だと visual->depth = 24 だった(32じゃないのは意外だ)。

そんなん 24bppバッファに16bppで描画しても崩れはしてもバッファオーバーフローはしないので大丈夫やろってことでチェックを外す。

~~~:diff
-	if (visual->depth != 15 && visual->depth != 16) {
+	if (0) {
~~~

![xkeropi2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821068/5443d8cc-5562-e15a-5845-8fded13e4906.png)

おけおけ。
24bpp描画は書く面倒だけど windraw.c を改造すればなんとかなる。

その前に EUC を UTF-8 に変更しておこっと。
EMって普段なにやってるの？


# はじめに
この記事は、[Engineering Manager Advent Calendar 2022](https://qiita.com/advent-calendar/2022/em) の 19 日目の記事です。

私はエンジニア上がりの EM なのですが、エンジニアからすると意外と EM ってどんな仕事をしているのか見えづらかったりするので、この機会に EM の仕事内容や役割などを整理したいと思います。

## 3 行で自己紹介
- IT 業界歴は 10 年弱
- マネジメント歴は 3 年弱
- 前職は開発組織の部長（CTO, VPoE は不在）、現在は EM 兼 PjM

# 私が日々行っている EM 業務の実態
具体的に今の職場で私が EM として行っている業務は以下になります。
- 1on1, オンボーディング、目標管理、評価、採用、キャリア育成などのピープルマネジメント
- 組織ごとの人的リソース管理や組織横断のタスクフォースなどの推進、予算管理
- プロジェクトのスケジューリングやマイルストーン管理（アジャイル、スクラム）
- プロダクトの要件定義や優先順位付け

以下の広木さんの記事の画像が非常に整理されていてわかりやすいので抜粋しますが、EM と一口に言ってもこれだけ役割があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57002/f48eaac3-57ed-927b-b718-2667dec38be7.png)
※引用元：[エンジニアリングマネージャ/プロダクトマネージャのための知識体系と読書ガイド](https://qiita.com/hirokidaichi/items/95678bb1cef32629c317)

私は PjM としても並行して動いているので、やや強い EM ということになりそうです。
ドラクエで例えると、さまようよろいくらいの強さでしょうか？
これをデスタムーア最終形態くらいにしたいところです :smiling_imp:


# マネージャーの役割とは
私がマネジメント職に就いてしばらくたったときに、結局マネージャーの役割ってなんなんだろうと考えたときがありました。
そのときに私が読んだ本の中にとてもしっくり来た一文があったのでご紹介します。

>マネージャーの仕事は、部下に対して今の仕事の意義を説き、現場のメンバーの問題解決を支援することで前向きなエネルギーを作り出すこと

この引用は、以前私が読んだ書籍（`経営トップの仕事 戦略参謀の改革現場から50のアドバイス`）からの抜粋です。
※ちょっと本のタイトルからして固め・味濃いめ:ramen:ですが、わりと読みやすかったです

私はこの一文にマネージャーの仕事が凝縮されている気がしていて、かなりしっくり来ました。
個人的には、特に`仕事の意義を説き`という部分が重要だと感じています。
オーナーから依頼されたものを、そのままメンバーやエンジニアに横流しするだけでは、マネージャーの介在価値はありません。
その仕事をやることによるインパクトや価値をメンバーに咀嚼して伝えることが重要だと思います。


# EM に必要なスキルとマインドセット
EM の役割は多岐に渡りますが、ここでは私がメインで業務しているピープルマネジメントとプロジェクトマネジメントに分けて書きます。

### ピープルマネジメント

- 他人への共感力
    - メンバーの成長やパフォーマンス向上のために真剣に自分の時間と脳を使えるか
- 感情のコントロール
    - 感情を抑えて私情を挟まないようにできるか、逆に適材適所で感情表現が行えるか

老若男女、国籍問わず、色々な方をコミュニケーションを取るので上記は必須だと思います。
場合によっては、自分より人生経験やキャリアも豊富な方のマネージャーになることもあります。
マネージャーとはいえ、そこには上下関係は存在せず、役割が違うだけということを念頭におく必要があります。


### プロジェクトマネジメント
- 逆算思考
    - 成果や目標から逆算して考えられるか
    - これができないと QCDS をマネジメントできない
- 判断力（トレードオフを理解する）
    - やることだけでなく、やらないことも決められるか
    - 優先**度**ではなく優先**順位**を付けることが必要

プロジェクトマネジメントでは、ごちゃごちゃしているカオスな状態を整理整頓できることが重要だと思っています。
要望が多かったり優先度が高くても、使えるリソースは限られているので、順序立てて進めなくてはいけません。


# まとめ
色々書きましたが、ひと言でいうと EM は、`なんでもやる人` です。
正直なところ私は EM として １ 番重要なことは、仕事を選ばないことだと思っています。
会社や体制にもよりますが、人手不足なところでは、法務的なフィジビリの確認や関係各所との調整や根回し、議事録の作成など、雑用と思われるような仕事もあります。
ルーズボールを拾ったり、意識してファーストペンギンになることも必要です。
自分がやりたいことも重要ですが、事業やその時々に求められることを優先して泥臭く行動できる人が良い EM だと思っています。
興味がなかったことでも、やってみると案外楽しかったり、自分に向いていることが分かったりします。

読んでいただいた方が少しでも EM について理解が深まったらありがたいです。
Android StudioのLogcatにおける新しいKey-Value検索

## 概要

2022年9月15日にStable channelとなったAndroid Studio Dolphinからは、Logcatの機能が刷新されました。いくつか新しくなった機能がありますが、その中でもログの検索がKey-Value方式になったことが最も大きな変更点ではないでしょうか。

ところが、以下の公式ドキュメントには代表的な使い方しか書かれておらず、私は最初かなり戸惑いました。そこで改めてKey-Value検索で出来ることを整理し、まとめてみました。

[Android Studio Dolphin : 新しいLogcat](https://developer.android.com/studio/releases?hl=ja#logcat)
![スクリーンショット 2022-12-16 19.46.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281445/0a29981b-ab29-45b7-4d9b-575a165858ac.png)

## 使用可能なKey

ドキュメントに記載のもの以外も含めると、Android Studioのサジェストから確認できるKeyは全部で６種類あります。

Key名|使用例|説明
---|---|---
package|package:system_process|パッケージIDを指定できる（※1）
tag|tag:ActivityManager|タグを指定できる
level|level:INFO|ログレベルを指定できる（※2）
message|message:error|メッセージをフィルタリングするワードを指定できる
age|age:3d / age:2h|最新のxx日分やxx時間分のみ表示させるための値を指定できる
line|???|これだけ使い方が不明

※1: 自分のアプリは `package:mine` で指定できる。
※2: 指定可能なレベルは `VERBOSE`, `INFO`, `ASSERT`, `DEBUG`, `WARN`, `ERROR` のいづれか。

## Valueの使い方

Valueは値を指定する以外にも、特定の値を除外したり正規表現を使ったりすることも可能です。

### 特定の値の除外

Keyの前に `-` を付けて値を指定すると除外したログを表示できます。

**例）`-tag:System` : Systemのタグ以外を表示**
![スクリーンショット 2022-12-16 20.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281445/660d1503-87d6-249c-a943-aa64f311d450.png)

### 正規表現を使った検索

Keyの後に `~` を付けるとValueに正規表現を使えます。

**例） `package~:^com\.android` : パッケージIDがcom.androidで始まるログを表示**
![スクリーンショット 2022-12-16 20.45.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281445/d72955de-736b-5293-c0c9-12de25ce57b4.png)

## 検索条件の組み合わせ

丸括弧と論理演算子を使って検索条件を指定することもできます。

**例） `(message:error | level:ERROR)` : メッセージにerrorが入っているかERRORレベルのログを表示**
![スクリーンショット 2022-12-16 20.49.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281445/2c873460-617e-5a6f-ac29-8f88311372b4.png)
ちなみに同じ条件でもKey-Valueを並べるだけだとAND条件になってしまいます。
![スクリーンショット 2022-12-16 20.51.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281445/c2ef0a3b-528c-06c9-9524-67e9d04499a9.png)

## 検索条件の保存

検索クエリは履歴に残りますが、星アイコンをクリックすることで保存することもできます。
![スクリーンショット 2022-12-16 20.54.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281445/8e4f4164-ebca-b387-b349-47543d98f06f.png)

## まとめ

* Key-Value形式でログのフィルタリングができるようになった
* 引き続き正規表現を使ってのフィルタリングはサポートしている
* Key-Valueの組み合わせもある程度可能

慣れると以前のLogcatよりも、フィルタリングしやすくなったように感じます。`line` の使い方が分からなかったのが残念です。ご存じの方は、ぜひコメントで教えてください。
OpenStack Cinderについて

OpenStack Cinderについてまとめています。OpenStackとは何か？は書いていないので、知っている前提です。

# OpenStack Cinderとは

AWSで言うとAmazon Elastic Block Store(EBS)相当のサービスを提供します。
仮想マシンインスタンスに対して、永続的なブロックストレージを割り当てるために使用します。

## アーキテクチャ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960620/bc25113a-c39f-bae0-2cb3-0ee8954bad44.png)

https://docs.openstack.org/project-deploy-guide/openstack-ansible/newton/overview-storage-arch.html

上の図の①～③の説明は以下の通りです。
1. Cinderのサービス（cinder-volume service）によってAPIを通じてボリュームが作成される
1. Novaのサービス（nova-compute service）はストレージネットワーク経由でComputeホストのハイパーバイザーをボリュームに接続する
1. ハイパーバイザーはボリュームに接続された後、ボリュームをローカルハードウェアデバイスとしてインスタンスに提供する

## もう少し細かい話

Cinderの裏ではストレージバックエンドソフトウェア存在しており、物理ストレージとのやり取りを担います。
Cinderはストレージバックエンドに対して要求に応じたボリュームを作成するよう指示を行います。
イメージは以下です。（この図ではLinux Volume Managerがストレージバックエンド）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960620/aa019e0d-48af-4cb3-b8f4-87da872f9489.png)

https://www.unixarena.com/2015/09/openstack-configure-cinder-service-testing-method.html/

上のアーキテクチャの図で「Infrastructure control plane host」がこの図のCinderのホスト、「Compute host」がNovaのホストに対応します。

## Cinderのコンポーネント

Cinderには以下の4つのコンポーネントが存在します。

- cinder-api
    - 要求に応答し、メッセージキューに配置します。APIサービスはブロックストレージ要求のためのHTTPエンドポイントを提供します。
- cinder-scheduler
    - タスクをキューに割り当て、プロビジョニングするボリュームサーバーを決定します。
- cinder-volume
    - 仮想マシン用にストレージを指定します。
- cinder-backup
    - ブロックストレージボリュームを外部のストレージリポジトリーにバックアップします。デフォルトでは、OpenStack Object Storageサービス（Swift）を使用してバックアップを保管します。

それぞれの関係は以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960620/ec366306-92c1-d49c-be3b-226b54104801.png)

https://access.redhat.com/documentation/ja-jp/red_hat_openstack_platform/9/html-single/architecture_guide/index#comp-cinder

## ストレージバックエンド

ストレージバックエンドは、Cinderがドライバをサポートしている必要があります。
以下にサポート対象のドライバ一覧があります。

https://docs.openstack.org/cinder/latest/reference/support-matrix.html

LVMの他にCephやストレージベンダーのドライバなどが対応していますが、統計調査ではCinderのバックエンドとしてはCephが73%であり、圧倒的です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960620/e61d07df-6279-d6e0-4fd2-2845bdff57b4.png)

https://www.openstack.org/analytics

## おわりに

Cinderをきっかけにストレージ回りに興味が出てきたので、そのうちLVMやCephについてもアーキテクチャを調べて書いてみたいと思います。
また、OpenStackの他のストレージサービス（以下）についても機会があれば書きたいと思います。
* オブジェクトストレージ（Swift）
* ファイルストレージ（Manila）
* データベース（Trove）
🔰条件分岐の代入について。　

## 読んで欲しい人！
・未来の自分
・プログラミングを教えている人
→初学者がどのタイミングでモチベが下がるか知って欲しい！

[paiza](https://paiza.jp/works/mypage)のこの[レベルアップ問題集](https://paiza.jp/works/mondai/prob60/5_or_more_4)を解いていたら...

もしかして条件分岐の中に代入ってできるのでは？と思って
解答を間違えるのを覚悟して実行したら正解できた！
（エラーが出た時の精神汚染度高い。樹海で彷徨う感じ）

```c
#include <stdio.h>
int main(void)
{
    int array[8] = {4, 0, 5, -1, 3, 10, 6, -8};
    
    // printf("%d",array[0]);
    
    int i;
    int box = 0;
    for(i = 0; i < 8; i++){
        // printf(" %d",array[i]); // 4 0 5 -1 3 10 6 -8

        if(array[i] >= 5){
            
            box += array[i];
            // printf("%d",box);
        }
    }
    
    printf("%d",box);
    
    return 0;
}
```
今年の6月からプログラミングを学んで条件分岐を書いたら数値を何か出力する！
条件分岐を書いたらprintfする！
printf以外ありえないっしょ！って私の中のギャルが出てくる。笑

絶対printfする！という武器しか持っていなかったけど
代入を条件分岐のニョロかっこ（{}）の中に書いてみたらその代入の値が判定されることを知ったのでプログラマーのレベルが上がったこの日を記念日とする！
（やったー！）

20221221更新
イーサリアム 2.0：全体アーキテクチャ

The Merge が実施され、イーサリアムは順調に 2.0 に進んでいます。
コンセンサスアルゴリズムが PoS に切り替え、シャーディングも実装されるため、1.0 よりアーキテクチャが複雑になってきたので、整理してみました。

**2022 年 12 月では、シャーディングまだ実装できていません**

## チェーンレベル
![ethereum2_chain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4777/e1f115f9-9473-a095-4591-d2301ace7a42.png)

イーサリアム 1.0 は１つのチェーンでしたが、2.0 は、複数のチェーンから構成されます。

- ビーコンチェーン（Beacon Chain）：コンセンサスレイヤー
    - コンセンサスの為に、シャードチェーンの次のブロックに対する投票を収集・検証などの処理を実行します。
- シャードチェーン（Shard Chain）：現時点では Etheeum Chain １個しかないですが、今後シャーディングの実装ができていれば、複数（現在の設計では最大 64 個）できる
    - トランザクション（スマートコントラクトの関数呼び出しなど）は、シャードチェーンで実行します。

ブロック生成の詳細を知りたい場合、[Ethereum 2.0: PoS の新しいブロック生成流れを整理してみた](https://qiita.com/blueplanet/items/58839a15e721df7e6175) ご参照ください。

## ネットワークレベル
![ethereum2_network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4777/452ce2ac-3cc8-e0d6-e057-44310e093719.png)


ネットワークには、ビーコンチェーンとシャードチェーンのクライアントを実行するサーバーがあります

- ビーコンチェーンのクライアントを実行するサーバーは、バリデーターサーバー
- シャードチェーンのクライアントを実行するサーバーは、今までのイーサリアム 1.0 の RPC サーバー

になります。
- 詳細の流れは [Ethereum 2.0: PoS の新しいブロック生成流れを整理してみた](https://qiita.com/blueplanet/items/58839a15e721df7e6175) に書いていますが、バリデータサーバーは、スロット単位の委員会に割り振られて、そのスレットに対して、シャードチェーンのどのブロックが正しいかを投票します
- オレンジ色は正常な正しい投票ですが、青色のような間違った投票があったり、Slot 102 と Slot 103 の委員会の中、投票を収集できなかったりすることもありえます。
    - 間違った投票を行ったり、投票しなかったりなど、「ちゃんと仕事していない」、または、「悪意な行為をした」などの場合は、内容に応じて罰則も設けられています。別途記事にまとめる予定です。

## まとめ
イーサリアム 2.0 は、ビーコンチェーンを設けて、コンセンサスレイヤーとトランザクション実行レイヤーを分けることで、シャーディングの為のアーキテクチャができました。
AWS re:Invent 2022で感じたこと

[デジタルキューブ＆ヘプタゴン Advent Calendar 2022](https://qiita.com/advent-calendar/2022/digitalcube-heptagon)の16日目の記事です。

# re:Invent 2022に参加してきました

ラスベガスで行われたAWS最大のカンファレンス、AWS re:Invent 2022へ参加してきました。
約３年ぶり7回目のラスベガスは、物価高&円安で食事代が大変な感じでしたが、街の様子はそれほど大きく変わっていない印象でした。

<img width="600" alt="部屋からベラッジオの噴水が見れてラッキー" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52904/461e3384-6d69-c96e-bd9f-3e6b70b96482.jpeg">


AWSのCEOである[Adam Selipskyのキーノート](https://youtu.be/Xus8C2s5K9A)とAmazonのCTOである[Werner Vogelsのキーノート](https://youtu.be/RfvL_423a-I)を中心に今回のre:Inventで印象に残った２つのトピックについて感じたことを書きます。
(サービスや技術の話よりは今後のビジョン的なものがメインのポエムですのであらかじめ...)

# サステナビリティ
Adamのキーノート冒頭での再生利用可能エネルギーへの転換やウォーターポジティブへの言及(会場からの大きな拍手も起きる)から始まり、宇宙、深海、北極とサービスアップデートを自然になぞらえて話を進めていました。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52904/bee57760-fb50-709c-dcf6-61b6090cbd73.jpeg">


Wernerのキーノートでも現実の世界は、非同期でかつ並列的に動いているのでシステムもそうあるべきだと、システムの在り方を自然界と対比しながら説明していました。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52904/7925c2b1-8d93-2d11-f6cf-986aa8211a3b.jpeg">


また、多くの企業が出展している展示エリアでは紙のパンフレットの配布が全くありませんでした。知名度のある企業ならまだしも、これからという企業にとっては後から思い出してもらう機会が減るのはなかなかに辛い気がしましたが、(AWSからの指示なのかどうかはわかりませんが)これもサステナビリティを意識して当たり前になっているんだなと思い知らされました。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52904/be0cf5cb-0a94-0f41-effa-5c9044e31478.jpeg">

これらは今後AWSは自然、地球（あるいは宇宙）と共に歩んでいくという強いメッセージなのかなと私は受け取りました。
まだまだ日本では、事業が中心にあった上でのSDGsだったり、事業とは別にSDGsを考えるような企業はまだまだ多い印象(自社もそう)ですが、この辺もアップデートの必要性を痛感しました。

# 3Dシミュレーション
二人のキーノートでもう一つ印象に残ったテーマが、3Dデータによるシミュレーションでした。
Adamのキーノートで、空間シミュレーションの新サービスであるAWS SimSpace Weaverが発表されました。
また、Wernerのキーノートでも再度AWS SimSpace Weaverに言及があったり、Epicからスマホでスキャンすることで3Dデータを作成できるReality Scanが発表されたりと、３Dシミュレーションについての話題が非常に長かったように思えます。3Dデータを使ったシミュレーションがもたらす価値についても多く触れられていました。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52904/54fd3856-df0e-ec79-d04a-75c5b8b20955.jpeg">


また、今回たまたま3Dデータを用いたデジタルツインのワークショップに複数参加しましたが、グラフや数値での可視化以上に簡単に理解できるってすごい大事&直感的だなと感じました。ISSから送られてくるリアルタイムデータを使ったデジタルツインが動いた時ははちょっとしたした感動でした。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52904/fb61d6c9-3dc0-ab14-fae9-210f683229cf.png">


# この２つのトピックから考えたこと
自然、地球、宇宙などの現実世界とクラウドがシームレスに繋がっている世界こそAWSの目指しているものなのではないかと強く感じました。クラウド内のエコシステムに留まらず、本来の意味での現実世界でのエコシステム(生態系)の一部となり、よりよくしていこうというイメージです。
そのために、クラウド、IoT、機械学習の次の手として、３Dでのシミュレーションという技術が必須になってくるのではないかなと思いました。(日本ではメタバースなどバーチャルコンテンツとしての3Dが話題になっていると思いますが、それとはちょっと違う世界だなと)

ということで来年のre:Inventではさらに抽象化、民主化されたシミュレーション系のサービスが発表されるのではないかなと予想しています。

来年のre:Inventでの答え合わせを楽しみに、そして今年のre:Inventには大きな忘れ物をしたので来年取り返せるように１年を過ごしたいと思います！
![IMG_5304.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52904/b20bc437-dcd7-776c-4d04-3c1fa3774b6c.jpeg "Digitalcube & Heptagon will back!!")

(サステナビリティも3Dシミュレーションもまだまだ不勉強なのでもし間違っているところがあれば教えてください)
スクラム勉強メモ

## 第1回
https://schoo.jp/class/3812/room

### プロジェクト掛け持ちのチームメンバ

スイッチングコストがかかることの共通認識が必要。(0.5+0.5の仕事はできない)

### スクラムマスターが指示を出す

指示が出したいならPO側の人間になるべき。
開発リーダーとして開発チームにいるべきでは?
そもそもSMの仕事を分かっているか?
スクラムマスターという名前がよくない。
レトロスペクティブで、各メンバーがあげたプロブレムに対してのTryをどんどんスクラムマスターが決めていってしまう。
スクラムマスター当番制。

### POとあまり連絡が取れない

チーム内にPO代理を立てた。
POが参加してくれなくなることがある。
POもSMも「役割」なんだから、ダメなら辞める、変える。
「自分が機能すればうまくいく」ことに気づいてもらう。

### 「偉い」とは?
その人の発言を重要視しないといけない、ということ?
肩書?
年齢?

### お勧めコミュニケーションツール
Slack チャンネル乱立問題あり

### アジャイルやりたい
課題は何か?が必要。

https://ja.wikipedia.org/wiki/%E9%87%8D%E8%A6%81%E6%A5%AD%E7%B8%BE%E8%A9%95%E4%BE%A1%E6%8C%87%E6%A8%99

## 第2回
https://schoo.jp/class/3813/room

### スクラムのイベント

#### プランニングが時間通りに終わらない

2H予定に対して4Hかかってしまう。
かかるのは仕方がない。「かかっていること」を認識していることが重要。
プランニングを負担に感じるのがよくない。
制限時間で切るものあり。終わらなければ「それが俺たちの現状じゃん」って受け入れる。
「ふわっとした状態で初めてしまう」よりも、きっちりタスク定義やりきってから開始するほうがまだいい。
どこで苦労するか、だけの問題。

10人を超えると、他の人が何をやっているのか分からなくなる。 

#### デイリースクラムが進捗報告だけで終わる
「問題になっていること」を何故伝えなければいけないかを理解する必要がある。
ひねり出せ。
問題がないなら、「こういう課題がありましたが、こう解決しました」でもいいからいうようにする。
「自分の中で解決できているからいいや」ではダメ。
デイリースクラムで、課題が出なかった時、昨日帰った時間を一緒に発表するようにしてた事例。それが遅い時間だと「？」みたいな。
進捗確認の場ではなく課題発見の場である。
進捗報告なくてもいいくらい。
SMに話している人がいる。開発チームに向かってしゃべる(共有する)場である。
形骸化したらつまらない。何か楽しくする工夫。
今日の技術トピック
進捗報告はRedMineとか「ツール見といて」でいいじゃん。

#### スプリントレビューの準備が大変
その準備が必要な作業なんだったらタスクにしておけ。
開発チームのゴールのイメージが、デモを行える状態になっていないのでは?（機能を実装すればOKみたいに）

#### レトロスペクティブで同じ問題が何度もあがる
何度も同じ問題が上がり、誰も解決しようとしない。
タイトルは同じでも、中身が変わっている可能性はないか?問題のポイントが変わっているとか、問題の深堀のレベルが変わっていないとか。
Actionに落ちてないことは多い。なんでもいいからActionに落とす。やってみたら、得るものがあるはずで、同じトピックでも議論の進展があるのかも。
プランニングは終わるまでやるのに、レトロスペクティブは終わるまでやらないのはなぜか?
そのトピックだけを深堀する1～2時間を作るとか。
そのチームでは解決できない問題であるという可能性。
レトロスペクティブのマンネリ化。→場所を変える。ネタを変える。匿名性にする。
「アジャイルレトロスペクティブズ」https://www.amazon.co.jp//dp/4274066983
Problemにあげた切り
KPTからYWT
Problemに対して「〇〇をがんばる」というTryにしてしまうと、またProblemになってしまう。
問題が振り返りまで持ち越されている段階でNG。SM仕事しろ事例。

#### その他のイベントってない?
お茶会
お菓子タイム
余裕がないと改善は行えない
ランチバックログ

## 第3回
https://schoo.jp/class/3814/room

### コミットしたPBIを完成できないことが多い
できないことが続いて、それが普通になってしまってはいけない。
ビジネス側との信頼関係に問題が生じる。
「守れることをやる」
「期待にこたえたい」という思いがあるのはわかる。
良かれと思って頑張りすぎてしまうと、その場はいいかもしれないが、以降で正しい見積もりができなくなってしまう。
「開発側が仕事してない」「ただ遅延してるだけじゃん」って思われちゃう。

### PBIの優先順位がつけられない
どれも最重要になってしまう。
それって優先順位がついてないと同じ事。それでも順位付けしてください。
具体性があるかどうかを順位(着手順)の判断材料にする。
開発のしやすさの観点で開発チームに意見聞くとか。
優先順位に納得ができない場合は?POとすり合わせ。
比較基準が決まっていない。AとBはコスト観点で比較して、BとCではデリバー観点で比較したりして。
そこの基準作りをちゃんと考えるべきではないのか。決まれば自動的に優先度判断できる。

### タスクの割り込みが頻繁に発生
主にバグ
割り込み頻度、ボリュームを定量化して計画までもっていく
割り込みタスクの割合を可視化。(別の色のチケットで管理)それをPOや発生元と共有する。
「バグ」「他部署」「自己発見した作っていなかったタスク」
知らない間に割り込みをやっている(割り込みに気づいていない)のがまずい。

### 改善策が多すぎて消化できない
少しでもできてるならいいじゃん。ゼロなのは問題。
1回で済むものと、継続的にやらないといけないもの。区別してやる。
個数を制限して入れ替え制。
テンションが上がる改善策か、やってもテンション上がらない改善策か。
改善策と問題の解決は別の問題では?
暫定策と恒久策のバランス。
ものによってはプロダクトバックログに入れる。
全く改善策が浮かばないものは?
自分たちが解決できないものは、「制約条件」として扱うべきでは?