OmniAICreator/Qiita-1.07M huggingface dataset:
TypeScript 4.5で入ったAwaitedは自作できるのか

https://devblogs.microsoft.com/typescript/announcing-typescript-4-5/#awaited-type

TypeScript 4.5で`Awaited`タイプが入りました。

```ts
// A = string
type A = Awaited<Promise<string>>;

// B = number
type B = Awaited<Promise<Promise<number>>>;

// C = boolean | number
type C = Awaited<boolean | Promise<number>>;
```

あれ、これって自作できそうな気もします。

```ts
type MyAwaited<T> = T extends Promise<infer R> ? MyAwaited<R> : T
```

これだけでいいのでは？

[TypeScript Playground](https://www.typescriptlang.org/play?#code/PTAEEFQXlBnAXATgSwHYHMBQ8CeAHAUwmggHcBDZeAgEwB4AFRAewFtlYC6EUMA+PgG5MmEKABCJVAFdWAIwKJs+IpJjgKVWoxbtOOthy4z5igUJFiAwiTnNmAGwLlUoAD6gTCpbkKgb6prU9HaOzq4eTIb6XmYWomAAtMkivkQAsjgalMF0ACp8JHmgBAAe1Kg0sKBRelxoAGaKoABKhQD8oJnZWvRtoABcoHmpKhAATCTdQdq1RtxIaOgCwsp+4pMw0zmzuvNzMbLe5qtp-ptdWTMh9k4u7jV7h6aIK5hAA)で確認、いい感じ。

実際のコードを覗いてみることにしました。

https://github.com/microsoft/TypeScript/blob/v4.5.3/src/lib/es5.d.ts#L1495-L1501

PromiseLikeと非strictNullChecksに対応している以外は基本同じ様子。もっと魔法のようなことをやっているかと思ってました。

これなら[downlevel-dts](https://github.com/sandersn/downlevel-dts)でも対応できるのではないでしょうか（最近アクティブじゃなさそう）。

以上、小ネタでした。
Java: Mavenプロジェクトの依存ライブラリを確認する(dependency:tree)

Javaプロジェクトが利用しているライブラリは、どのように確認すればよいのでしょうか。

単純に直接依存しているライブラリを確認するだけでは不十分です。たとえば、ある依存ライブラリがさらに別のライブラリに依存しているという関係性(推移的依存)があるからです。ほかにも、単純にwarファイルを展開して含まれているjarの名称を確認するだけでは、[fat jar(uber-jar)](https://qiita.com/seijikohara/items/ba259aedddff726d995a#fat-jaruber-jar-%E3%82%92%E4%BD%9C%E6%88%90) の存在をカバーすることができません。

誤った方法で確認してしまうと、調査漏れが発生してしまう危険性があります。このため、本記事では比較的容易かつ確実性の高い方法を紹介します。

# 前提

下記の両方を満たしていることが必要です。

- 調査対象がMavenプロジェクトとして構成されていること
- 作業端末において、Mavenにパスが通っていること (参考: [WindowsへのMavenインストール](https://qiita.com/Junichi_M_/items/20daee936cd0c03c3115))

# 具体的な手順

例として、[Apache Solr Core 8.11.0](https://mvnrepository.com/artifact/org.apache.solr/solr-core/8.11.0)の依存ライブラリを確認してみます。

[2021-12-10, Apache Solr affected by Apache Log4J CVE-2021-44228](https://solr.apache.org/security.html#apache-solr-affected-by-apache-log4j-cve-2021-44228) によると、`Apache Solr releases prior to 8.11.1 were using a bundled version of the Apache Log4J library vulnerable to RCE.` とのことです。このため、8.11.0には log4j 2.15 より前のバージョンが依存ライブラリに含まれているのではないかと思われます。

## 1. pomファイルの取得

pom(Project Object Model)ファイルとは、Mavenプロジェクトにおける設定を記述したファイルです。通常のMavenプロジェクトでは、pom.xmlというファイル名で利用されています。

今回は、[Maven Repository: org.apache.solr » solr-core » 8.11.0](https://mvnrepository.com/artifact/org.apache.solr/solr-core/8.11.0) のFiles欄にある[pomファイル](https://repo1.maven.org/maven2/org/apache/solr/solr-core/8.11.0/solr-core-8.11.0.pom)をダウンロードします。

## 2. ライブラリの依存ツリーを出力

pomファイルをダウンロードしたディレクトリに移動し、dependency:treeコマンドを実行します。

```
mvn -f solr-core-8.11.0.pom -DoutputFile=mvn_dependency_tree.txt dependency:tree
```

オプションの説明は下記の通りです。

|オプション|説明|
|----|----|
|-f|pomファイル名を指定します。指定しない場合は pom.xml が利用されます|
|-DoutputFile|出力先のファイル名を指定します。指定しない場合はコンソールに出力されます|

## 3. 結果の確認

出力された mvn_dependency_tree.txt ファイルを確認します。

```
org.apache.solr:solr-core:jar:8.11.0
(中略)
+- org.apache.logging.log4j:log4j-core:jar:2.14.1:compile
```

これらの文字列は、コロン区切りで `groupId:artifactId:packaging:version:goal`を意味します。結果を対照させると、下記の表にまとめることができます。

|Key|依存先モジュール|
|----|----|
|groupId|org.apache.logging.log4j|
|artifactId|log4j-core|
|packaging|jar|
|version|2.14.1|
|goal|compile|

つまり、`org.apache.logging.log4j:log4j-core:jar:2.14.1:compile` という文字列からは、「プロジェクトをcompileするとき」に「org.apache.logging.log4jグループ」の「log4j-coreアーティファクト」の「jarでパッケージ化された」「バージョン2.14.1」に依存していることがわかります。

# 関連記事

https://kazuhira-r.hatenablog.com/entry/20121206/1354805445
今新規でプロダクトを開発するときに気をつけたAPIの設計

[Web API Advent Calendar 2021](https://qiita.com/advent-calendar/2021/webapi)の13日目の記事です！

今年、新規に一から自社のプロダクトを設計、開発するチャンスがあり、どんな感じで進めたかを記録しておきたいと思います。
具体的な例があったほうが面白いかなと思い、出せそうなものは記載しました。

プロダクトはマルチテナントな建設向けの[IoTプラットフォーム](https://ncdc.co.jp/service/mierukoji/)です。
テナントごとに持っている現場単位で利用者やモノの管理を行います。

全体を通して気をつけたのは２点です。
1. ドキュメントやコードを拡張、メンテナンスしやすいこと
2. APIのクライアントの実装者が一般的なAPIのお作法に沿って使える。使いやすい、デバッグしやすいこと

# アーキテクチャ
フロントエンドはSPAやモバイルアプリなので、バックエンドの機能はすべてAPIになっています。
実行基盤としてはAWS ECS。言語・フレームワークはTypeScriptでExpressを使っています。

# サービスの設計
DDDでやりました。ドメインモデルを書いてスタートしたのですが、プロジェクトが進んでいった後も、ドメインモデルに立ち戻って会話したり、新しく入った人が概要を理解するのに良かったと思います。

社外秘のところはボカしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31063/23a06c54-f3cb-6000-28e1-a097c20443e5.png)

単純なAPIは良いのですが、いくつかの複雑になりそうなAPIはこんな感じの構成でやろうね、という認識合わせのためにモデリングしました。中間資料的な位置づけでメンテはしていかないつもりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31063/d91237f6-4062-a3f4-e2c7-9698c37fce6d.png)

# API Spec
API仕様はOpenAPIで書きました。
エンジニアだけじゃなくて、最近転職してきたばかりのコンサルロールの人にもOpenAPIで書いてもらいました。最初は[Stoplight Studio](https://stoplight.io/studio/)の癖や、使いやすいAPIの定義みたいなところで認識合わせが必要でしたが、結構うまくいったように思います。

今は内部的にしか公開していませんが、APIを社外の方からも使っていただけるように公開していきたいと考えています。

# RESTfulにした
原則としてAPIはRESTfulの考え方に沿ってデザインしました。
画面のワイヤーデザインと、ドメインモデルを見ながらリソースを定義していきました。

- 例
```
/sites/{siteId}/elements/{elementId}
```

## RESTfulにしなかったもの
検討した上で一部例外的にRESTfulにしなかった例です。

- コマンドっぽいやつ
    - 現場の施工開始 `POST /sites/{siteId}/start`
    - 現場の施工完了 `POST /sites/{siteId}/complete`
    - 現場の更新でstatus属性を更新というやりかたもあったのですが、開始、完了に伴うドメインルールがいろいろあったので独立させました
- バルクアップデート（一括登録・更新）みたいなやつ
    - 画面には複数件のフォームがあって、APIには配列で渡して一部は新規登録、一部は更新処理を行いたいケースです。新規と更新が混じるので、POSTとPUTで分けるようなことはできず、全部POSTでやりました
    - 削除だけは該当行のリソースIDを指定してDELETEメソッドで実装しました。んーどうなんだろう。トランザクションとか考えると、バルクアップデートの一部に入れたほうが良かったのだろうか。

## エラーの返し方
フロントエンドや、API連携先のクライアントアプリケーションが、どのAPIを使っても共通のルールに沿って例外処理を実装できるように心がけました。

- バックエンドが原因のエラー
    - HTTPステータスコード 500
- リクエストに起因するエラー
    - HTTPステータスコード 400系
    - エンドユーザーにメッセージを表示する際に使用するエラーコードを返す
    - APIのクライアントの実装者がデバッグできるように、エラーの内容を文章で返す

# 認証・認可
- 認証はAWS Cognitoで行っています
- テナント単位の認可はCognitoの属性にテナントの情報をもたせて、ミドルウェア的な領域でアクセスしようとしている先に、権限があるのかをチェックしています。

当然自分一人で上記をやったわけではなく、チームで議論しながら進めました。特に、[久光さん](https://zenn.dev/hisamitsu)が中心的に設計されたところも多いことを付け加えさせていただきます！

以上です。質問やアドバイスなど大歓迎です。
Excel365 ホイールでの横スクロールがデフォルトでできる!?

Office2016までは、横スクロール機能はなかったと思う(VBAで頑張って実装しようとしたこともあったが断念)
が、どうやらOffice365では、**ホイールでの横スクロール**がデフォルトで使えるよう

###ショートカット
Ctrl + Shift + ホイール


便利・・・
GAS よく使うメソッドとかもろもろ

# spreadsheet関連
### 1.スプレッドシートを取得する

```
SpreadsheetApp.getActiveSheet()
```

```
SpreadsheetApp.openByUrl()
```

```
SpreadsheetApp.openById()
```

```
getSheetByName()
```

### 2.スプレッドシートの範囲を取得

```
getRange()
```

### 3.行や列にまつわるもの

```
getRow()
getColumn()
```

```
getLastRow()
getLastColumn()
```

### 4.値の取得と挿入

```
getValue()
getValues()
```

```
setValue()
setValues()
```

# slack関連
### フォームの回答結果を取得する

```
function myFunction (e) {

}
```

### slackに送信する関数の雛形

```
function sendToSlack(body, channel) {
  const url = "あたなが使うSlackのIncoming Webhook url";
  let data = { "channel" : channel, "username" : "適当でいい", "text" : body};
  let payload = JSON.stringify(data);
  let options = {
    "method" : "POST",
    "contentType" : "application/json",
    "payload" : payload
  };
  UrlFetchApp.fetch(url, options);
}
```

###
Dart ImageSource.galleryが使えない時

以下のwidgetを使った際に、カメラは使えるが写真一覧を開けかなった時の理由を書きます。
https://pub.dev/packages/image_picker

<h2>原因</h2>
iOS simulator内のsettingで、カメラへのアクセスを許可していないことが原因でした。

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1878133/ba5bc429-e150-294f-9f69-e829862bb05f.png">

<h2>結論</h2>
XcodeやAndroid simulatorのdebugにはiOSの設定までは教えてくれないので、
コードでエラーがない時には、設定ミスを確認するといいのかもしれないですね。
RedshiftからBigQueryへのクエリ変換でハマったポイント

# はじめに
分析環境がRedshiftからBigQueryへ移行することに伴い、従来のクエリの書き換えをすることになりました。簡単に終わるだろう思っていたら、いくつかハマったポイントがあったので共有します。

# ハマったこと
### データ型が異なる比較はBigQueryが厳格
Redshiftでは、異なるデータ型を比較することがかなり許容されていたが、BQでは厳格。例えば、TIMESTAMP、DATETIME、DATEの比較はできない。
そもそも異なるデータ型で比較するのが気持ち悪いので、BQのほうが処理的には良いと思う。（Redshiftは良くも悪くも、異なるデータ型をよしなに比較してくれている）

```sql
-- Redshift 文字列とdateを比較してもエラーは出ない
select substring(cast(date('2021-12-01') as VARCHAR), 1, 10) >= dateadd(day, -365, date('2021-12-01'))
-- アウトプット true

-- BigQuery 異なるデータ型は比較することができない
select substring(cast(date('2021-12-01') as string), 1, 10) >= date_add(date('2021-12-01 00:00:00'), interval - 365 day)
/* エラーメッセージ
No matching signature for operator >= for argument types: STRING, DATE. Supported signature: ANY >= ANY at [4:1]
*/
```


### DATE_TRUNC関数で週の最初の曜日が異なる
デフォルトだと、WEEKの開始日が以下のように異なる。
Redshift: 月曜日
BigQuery: 日曜日
もしBigQueryで月曜開始にしたい場合は、DATE_TRUNC(date, WEEK(MONDAY)) とすれば挙動が揃う。

また戻り値も異なるので注意。
Redshift: TIMESTAMP（[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_DATE_TRUNC.html)）
BigQuery: DATE （[公式ドキュメント](https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#date_trunc)）

```sql
-- Redshift 
select DATE_TRUNC('week', date('2021-12-01'))
-- アウトプット 2021-11-29 00:00:00.000000

-- BigQuery
select DATE_TRUNC('2021-12-01', week)
-- アウトプット 2021-11-28

-- 参考：第2引数を変えると任意の曜日を開始日にできる
select DATE_TRUNC('2021-12-01', week(monday))
-- アウトプット 2021-11-29
```

### 特定の日時でのユーザーの年齢を算出するクエリ
RedshiftでMONTHS_BETWEEN関数を使用していたが、BigQueryにはMONTHS_BETWEENに相当する関数が無いので、以下のように修正。

```sql
-- Redash
select TRUNC(MONTHS_BETWEEN(date('2022-12-01'), date('2021-12-01')) / 12) as age

-- BigQuery 年齢を出すクエリは色々あるが、汎用的なものを採用
select TRUNC((CAST(FORMAT_DATE('%Y%m%d', date('2022-12-01')) AS INT64) - CAST(FORMAT_DATE('%Y%m%d',date('2021-12-01')) AS INT64)) / 10000) as age
```


### 緯度経度を使用した2地点間の距離計算の結果が微妙にずれる (BigQueryが世界測地系 WGS84での距離計算には未対応)
Redshiftでは2地点間の距離をより地球上の距離に近く（世界測地系　WGS84を使用して）計算できるが、Bigqueryでは現在、完全な球体の距離でしか計測できないらしい。

[公式ドキュメント](https://cloud.google.com/bigquery/docs/reference/standard-sql/geography_functions#st_distance)からの抜粋
>任意指定の use_spheroid パラメータは、この関数で距離が測定される方法を決定します。use_spheroid が FALSE の場合、完全な球体の表面上の距離が測定されます。
use_spheroid パラメータで現在サポートされている値は FALSE だけです。use_spheroid のデフォルト値は FALSE です。

```sql
-- 東京駅と神田駅の距離を計算してみる。

-- Redshift デフォルトでWGS84を使った距離を計算できる
select ST_DistanceSphere(st_point(139.7671, 35.6812), st_point(139.7709, 35.6918)) / 1000 as distance_in_km
-- アウトプット 1.2276163950893566

-- BQ　WGS84には対応しておらず、完全な球体の距離でしか計算できない
select ST_Distance(st_geogpoint(139.7671, 35.6812), st_geogpoint(139.7709, 35.6918)) / 1000 distance_in_km
-- アウトプット 1.227616631823407
```
気象庁xml を読み込む

掲載が遅れて申し訳ありません。
投稿したつもりができていなかったです。。

今回は[地震情報アプリ界隈 Advent Calendar 2021](https://adventar.org/calendars/6729)の13日目ですね

先週は、Discordでの防災情報提供を書きました
気になるかたは[こちら](https://qiita.com/jr226/items/5c276046eaaf2cfb1a49) (しれっと宣伝...)
#前書き
そして今回は気象庁xmlを読み込むです！！
あとで気付いたのですがこれ順番逆じゃね。。
まぁ、そんなことはどうでもいいです
（余計なことは気にしない気にしない)
まぁ、先週を見ていただいた方には再度とはなりますが簡単に自己紹介です
##自己紹介
現在、中3の受験nowです。
そして,Pythonでいろんなこと書いてます
（Node.js 勉強中)
ってよろしいかな、、詳しくは先週のを見てくれれば、
（また宣伝と思わんといて）
#やっと本題
さて、前書きが長すぎますはい
現在の情報の流れを簡単に書くとこんな感じです
![2021-12-12_10h39_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613330/3ca6f54e-112f-1ac6-c14e-fb2f2348a4fd.png)
こんな感じで処理してます。
そして処理時間をいれると
![2021-12-12_11h03_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613330/1368e3c1-b3d8-2b69-50e3-238e07560af6.png)

こんな感じになります。
まぁPython で稼働しているので、。うんまぁ。って感じです
そしてその一か月分を保存してるいる表の一部がこちらです![2021-12-12_11h05_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613330/6c0cbb93-9ad2-feed-b6fc-f1d28caba8d6.png)
（ちなみに保存データがおもすぎたのか一部データが欠損しています、、)
例えば。警報が発表されたらDiscord に送信されるまで
なんと、最短でも2分15秒かかってしまいます。

へッ、時間を短くするには？
気象業務支援センターからとればいいやん
思った人もいるでしょう、、
お金持ちはいいですね～～
自分はお金がないので無理ですはい、
（ホントはカネがあればそうしたい）
けど金がねぇ。。ってことで気象庁xml を読み込むしかないです、、

ん？なになにそうしさんの？ DM-D.S.Sを使えばいいやん？
ほんとはそうしたい、ほんとはね
けどね、お金がねぇんだ
あと脱線するけど
そうしさんは神だよ
毎回思います
BSC24の中で火山情報が出たときのSEを聞いて
その2分後ぐらい自分は詳細情報を知るので、
やば。。。
って感じです
#最後に
長々の書きましたが、気象庁xml に掲載されるには2～3分かかることがわかりました
また、webhook を使用しdiscord に送っていますが、URLの数が増えるほど
送信時間が増えるので次の処理に進めないので、若干ラグが生じるので
ここが改善のポイントかなと思いました

ここまで読んでくれてありがとうございます！
また再度となりますが、掲載が遅れて申し訳ないです。。
[py2rb] 多重継承

# はじめに
移植やってます
# 多重継承 (Python)
```python
class NoOpBaseReader(object):
    def __init__(self, *args, **kwargs):
        pass

class IndexedReaderMixin(NoOpBaseReader):

class IndexedXML(IndexedReaderMixin, XML):
```
~~この`IndexedReaderMixin`が次に継承される際多重継承となるため、Mixin化を図りたいと思います。
親クラスのインスタンス化で`pass`しているので、弊害は少ないと思いますが。~~
コメント欄にて教えていただきましたが、~~多重継承といいましても、単一継承を何回も繰り返しているだけのようです。~~ダイヤモンド継承になっていてもうまく検索できる仕組みのようです。

**[追記]**
いつも参照させてもらっている、お気楽プログラミングさんに分かりやすい解説がありました。
[お気楽 Python3 プログラミング超入門](http://www.nct9.ne.jp/m_hiroi/light/pythonb03.html)
# module (Ruby)
```ruby
module A
  def __init__(*args)
    puts "module A"
  end
end

class B
  include A
  def __init__(*args)
    puts "class B"
    super
  end
end

p B.ancestors
b = B.new.__init__

# [B, A, Object, Kernel, BasicObject]
# class B 
# module A
```
~~`Ruby`にとって`__init__`メソッドは特殊なメソッドではないので、継承チェーンに気を付ければ、問題ないと思います。~~
ということは、ちょっと格好悪くても、継承を繰り返せば良さそうです。
@shiracamus さん、ありがとうございました。
# メモ
+ Python の 多重継承 を学習した
+ 道のりは遠そう
OpenStackでneutron-calicoを使ってみた

この記事は、[MicroAd Advent Calendar 2021](https://qiita.com/advent-calendar/2021/microad)の14日目の記事です。


# この記事の概要
フルL3ネットワーク環境でOpenStackクラスターを新規構築するにあたり、
最終的にneutron-calicoで構築したという話です

# 構成
ざっくりと以下のような図のNW構成です。__ToR__と__サーバ間__は、__BGPでPeering__しています。
つまり、サーバまでL3で接続しているというNW構成です。

![NWイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20794/d78bb917-4bfa-fde4-ab1f-2a2dbf27f7a8.png)

この構成で問題になるのは、__Compute Node__内に生成されるインスタンスのネットワークです。
通常L2接続環境であれば、OpenStackの[Neutronドキュメント](https://docs.openstack.org/neutron/xena/install/index.html)に手順で問題なく構築できます。

同じテナント（同じ仮想ネットワークに所属する）間のインスタンス同士は、
VxLANでカプセリングすることでアンダーレイNWのセグメントが異なっていても通信できます。
ところが、インスタンスから物理サーバと通信しようとした場合に、
仮想ネットワークから外部ネットワークに接続するネットワークノードの構成方法が
通常の方法では行なえません。

以前から稼働しているOpenStackクラスターは、L2ネットワーク上に構築しており
インスタンス自体に直接接続している物理NWのIPアドレスを割り当てることで
Floating IPが必要ないように設定しています。
そのため、インスタンスから物理サーバへの通信にはCompute Nodeから直接通信するため、
Network Nodeを中継するトラフィックが発生せず、ボトルネックになる心配もありません。
この構成と同じように新しいOpenStackクラスターでも構成したいと思っていました。

# 解決までの流れ
## Calicoを試すまで
Calicoについては以前から知っていましたが、どちらかというとKubernetesで利用されることが多いのではないかと
思っていたので、あまり調べていませんでした。
そのため、OpenStackのNeutronだけでできないか試したり、
neutron-dynamic-routingを試したりしていました。

neutron-dynamic-routingは、仮想ネットワーク上のルーターと外部のToRをPeeringする方法で、
これはPeeringするところまでは確認できましたが
意図した挙動が得られないことや運用する上での課題が多くあったため途中で諦めました。

## Calicoを試し始めたが…
だいぶ遠回りして、ようやくCalicoを試すことになりましたが、
直前まで試していたOpenStack環境で初期化もせず手を加えて
対応しようとしていたことが災いし、なかなかうまく行かず…。
インスタンスすら起動できないエラーに悩まされていました。

結局、どうやっても解決できないことから検証中のOpenStack環境を再構築することに。
（MAASを利用しているので物理サーバの初期化は簡単）
そして1からOpenStackをセットアップして、Calicoのドキュメントのある通りにCalicoをセットアップ。

Compute Node上で__FRRを動かしている__ため__BIRDは使わない__方針で、
セットアップを進めましたが、思っていた以上に簡単にセットアップは完了しました。
悩まされていたエラーもでなくなり、インスタンスも無事に起動できるようになりました。

## インスタンスのIPが外部に広報されない…
ところがセットアップは問題なく完了し、インスタンスも無事に起動…までは良かったものの、
インスタンスに払い出されているIPアドレスが外部に広報されないという現象に。
ただCompute Nodeでneutron-calicoはインスタンスに払い出されているIPをちゃんと処理していること、
インスタンスをホストしているCompute Node内ではインスタンスに通信が可能なことから
FRRの設定が足りていないのではと思い調査。

すると、Calicoが登録しているインスタンスに対するルーティング情報は、
ComputeNode上のルーティングテーブルに__kernel route__として設定されていることがわかり、
FRR側で以下の設定を追加することで対処。

```
redistribute kernel
```

これで、インスタンスの作成、削除時にneutron-calicoがインスタンスの経路情報変更した際も
FRR側で外部に広報できるようになりました。

# 無事に構築完了
実はこの構築が完了したのは、つい先日の話。
なかなか情報が得られない部分だったり、挙動を確認しながらの調査とか
謎のエラーに悩まされたりと、色んな所で時間を取られ最終的な環境ができるまで相当時間をかけてしまいました。

とはいえ、当初予想していたよりも簡単に構築でき、
更にはネットワークノードを使わない構成にできたことで可用性もだいぶ高めることができました。
以前から稼働している環境ではVxLANを使用していますが、
こちらはVxLANも使わずに構築しているので、不要なオーバーヘッドもなくなりました。

# 終わりに
アドベントカレンダー用にサラッと書きましたが、この組み合わせの話ってあまり調べても出てこないので、
詳しい内容はいずれ時間をとって[MicroAd Developpers Blog](https://developers.microad.co.jp/)でブログ記事にしたいと思います。

（こんな中身の薄いQiita記事をアドベントカレンダーの記事としてポストして怒られないかだけが心配です:cold_sweat:）
【Harmoware-VIS】synerex_harmovis 関数書式

#Harmoware-VIS とは

https://qiita.com/ucl_Harmoware_VIS/items/e861e0f651ffde647b6a

#synerexとは
https://www.ucl.nuee.nagoya-u.ac.jp/project

https://github.com/synerex


#synerex_harmovis 関数書式
pipインストールはプロンプトから次のコマンドを実行

```console
pip install synerex_harmovis
```

詳細は [https://pypi.org/project/synerex-harmovis/](https://pypi.org/project/synerex-harmovis/) を参照

ソースコードは [https://github.com/synerex/python_Synerex-HarmoVIS](https://github.com/synerex/python_Synerex-HarmoVIS) を参照

## 関数一覧

| Function name | Arguments format |
| ---- | ---- |
| sendBearingAx | (bearing : number, duration : number=0) |
| sendPitchAx | (pitch : number, duration : number=0) |
| sendViewStateAx | (lat : number, lon : number, zoom : number=-1, pitch : number=-1, duration : number=0) |
| sendBarGraphsAx | (bg : **BGStore**) |
| drawLinesAx | (ln : **LineStore**) |
| drawArcsAx | (ac : **ArcStore**) |
| drawScattersAx | (st : **ScatterStore**) |
| clearArcsAx | () |
| clearScattersAx | () |
| sendTopTextLabelAx | (label : string, style : string="") |
| sendHarmoVISAx | (jsonStr : string) |
| sendMeshAx | (ms : **MeshStore**) |

## 引数作成クラス
**LineStore**

| Function name | Arguments format |
| ---- | ---- |
| setWidth | (width : number) |
| addLine | (srcLat : number, srcLon : number, tgtLat : number, tgtLon : number, color : number=0x708080) |

**ArcStore**

| Function name | Arguments format |
| ---- | ---- |
| addArc | (srcLat : number, srcLon : number, tgtLat : number, tgtLon : number, srcCol : number=0xd0c000, tgtCol : number=0xd0c000, tilt : number=0) |

**ScatterStore**

| Function name | Arguments format |
| ---- | ---- |
| addScatter | (srcLat : number, srcLon : number, tgtLat : number, tgtLon : number, fillCol : number=0xd000f0, lineCol : number=0x200020) |

**MeshStore**

| Function name | Arguments format |
| ---- | ---- |
| setTimestamp | (timestamp : number) |
| setTimestampNow | () |
| setMeshID | (id : number) |
| addMeshItem | (lat : number, lon : number, value : any, color : string="[0,200,0]", itemId : number=-1) |
| updateMeshValue | (itemId : number, value : any, color : string="[0,200,0]") |
| getItemIds | () |
| getJsonStr | () |

**BGStore**

| Function name | Arguments format |
| ---- | ---- |
| addBarData | (timestamp : number, label : string, lat : number, lon : number, barData : any) |
| addBarDataNow | (label : string, lat : number, lon : number, barData : any) |
| updateBarData | (id : number, timestamp : number, lat : number, lon : number, barData : any) |
| updateBarDataNow | (id : number, lat : number, lon : number, barData : any) |
初心者エンジニアがARカメラアプリを作るために3Dモデルについて勉強してみた 

#ARカメラアプリを作りたいんです！

**バイクに乗るのが好きで自分のバイクの写真を撮ることも好きです。**
ただ、行先が同じ場所に偏りがちで、撮影するバイクもずっと同じ。
同じような写真がフォルダー内に増えていくんですよね。

「自分のバイクと一緒に自分が映れば良いか」「ぬいぐるみを持参したら良いか」等々、色々考えたのですが、結局自分が映ってもいつも同じ写真になりそうなんですよね。それに持ち物が増えるのはできれば避けたいところ。

そこで目を付けたのがスマホカメラです。


事前に自分が好きなキャラクターを登録しておいて、Myスマホでバイクと一緒に登録したキャラクターを撮影できるARカメラアプリを作ったらいいんじゃないか！？と、思いました。

ただ、圧倒的に知識も技術も何もかもが足りないため、3Dモデル、ARについて勉強していくことにしました。
そのための3Dモデルを勉強するために参考になりそうな記事をピックアップ＆試していきます。



#ピックアップした記事から勉強
##波・・・波・・・波・・・3D動作

https://qiita.com/pyuruco/items/ceedb3d86976eb3f4b6f

自分のCodePenに貼ってみました。
波がめっちゃ動く！！！ちょっと気持ち悪くなりました・・・
考え方は参考になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/802a2c70-0eb9-d0f9-536a-42b02e9f2bd3.png)

##X・Y・Zの軸での表現方法

https://qiita.com/KazuyoshiGoto/items/72905b62c9a56807d892

X・Y・Z軸でわかりやすく動きも見えて良いと思いました。
自分の好きなキャラクターを表示するにはもっと勉強しないといけなさそうですが、3Dの考え方を視覚的にわかったのは良かったです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/88c5f3c3-d9ba-b24c-6a7f-a451522580d1.png)

##年賀状にARを組み込んでみる！？

https://qiita.com/yushimatenjin/items/03e71c363d6a28ccaa7e

こちらはまだ勉強が足りていません！！
参考にして別で実装してみようと思います！

#さいごに
3Dは奥が深いな・・・と思いました。
これからこんな奥深い世界に入っていくのか・・・
不安はありますがチャレンジしていきたいと思います！
技術的な中身よりも英語が分からないために、何をしたいかが分からない質問

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)


回答した後の返答が思ったこととは違って、何がしたかったのかが分からない質問です。
毎日回答していると、１つくらいはあるんですが、今月は多いなぁ。技術的なことよりも英語が分からない。
何が問題と言っているのが全く理解できないですね。

もし、前職で部下や後輩がこんな質問しきたら、もうその人には仕事頼まなくなる公算が高い。

超ストレスになります。ただでさえ、英語は理解不能なのに....

[数式のヘルプ](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000E9KpY)

Thank you. I'm actually looking for the formula to make the four fields equal to the piece of the Calling Page where the relevant information can be found
何のこと？

[マスターと詳細の関係を作成する-プロパティオプションは使用できません](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Dyclg)
単に指示通りに作ってないだけだろうと思うけど、何を言っても受け付けないですね。こっちも英語が分からんのでずばり言えない。


# 画像だけで質問してきても、トレイルヘッドを探せないんですよねぇ。

自分はやってる最中だからよく分かっているんだろうけど、私にはあんたが何やっているかなんて全く分かりません。
しかし、英語が話せる人はいつもこれでOKみたいなんですよね。日本語とは違って何か秘密の機能があるんだろうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4b8b8b6b-9c57-efa5-eebc-ca7d54d445af.png)


[unable to find the role "support" for non technical department](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HDf7RSAT)

# こういうのも止めて欲しい。英語は分からないしアルファベットを読むのもつらい

読む気すらおきません。
スキップします。朝から気分が悪くなりました 2022/09/08
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0dbe58e5-cc43-c5ae-8b73-9dbbf7e6c45f.png)

# 質問と回答が一致しているのかさえ理解できん。

[Home Page Assignment to Individual Users or custom group of useres](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000J96g2SAB)

この質問の答えがリストビューでOR条件の追加だとはどうしても結びつかない。英語には何か書かれてないことも表現されているのか？
こんな質問を見ているとますます英語を使う気が失せます。

The roles are as followed: 

+ Account Executive would see only their individual information
+ Account Directors would see their own info and their teams (Account Executives)
+ Sales managers would see their own info and their teams (Account Executives and Account Directors)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/046ddbae-bbb6-0ba9-c4b0-5e1cf58f8aff.png)
【AWS】AWS Snow Family

# はじめに
AWS認定試験取得に向けてAWSの知識を整理するためのまとめです。
今回はAWS Snow Familyについてまとめます。

# AWS Snow Familyとは
データ転送用のデバイスを使ってAWSにデータを移行できるサービスです。
ネットワーク経由の転送だと時間がかかってしまう大規模データなどに適しています。

# 特徴

## AWS Snowcone
Snowファミリーで一番小型のデータ転送デバイスです。
8TBのストレージを搭載しています。
データを AWS に移動するには、デバイスをオフラインで送るか、デバイスに
プリインストールされている AWS DataSync を使用してオンラインで移動します。
数日から数週間で転送が完了します。

![スクリーンショット 2021-12-13 11.49.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718108/583660a4-79ff-2425-63f1-88b0b923e041.png)

## AWS Snowball
データ移行およびエッジコンピューティングデバイスで、
コンピューティング最適化とストレージ最適化の 2 つのデバイスオプションがあります。
![スクリーンショット 2021-12-13 11.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718108/7096c104-f34f-fb72-8da7-116c4e90c704.png)

### Snowball Edge Storage Optimized(ストレージ最適化)
80TBのストレージを搭載しています。
大規模なデータ移行に適しています。
数日から数週間で転送が完了します。

### Snowball Edge Compute Optimized(コンピューティング最適化)
42TBのストレージを搭載しています。
機械学習、フルモーション動画分析、分析、ローカルコンピューティングスタックなどの
ユースケースに強力なコンピューティングリソースを提供します。
これらの機能には、52 個の vCPU、208 GiB のメモリが含まれます。
(データに対して何らか処理をしてからAWSに転送したい時など)
数週間〜数年で転送が完了します。

## AWS Snowmobile
AWS Snowmobileは最大 100 PB のデータを輸送コンテナで転送するため、
マルチペタバイトまたはエクサバイト規模のデジタルメディアの移行に最適です。
数ヶ月で転送が完了します。

![スクリーンショット 2021-12-13 11.50.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718108/f2a8be84-2cfa-5acf-b72f-1f7ec662484d.png)


# 参考サイト
https://aws.amazon.com/jp/snow/
Validation failed: 〇〇 must existエラー 解決法

##結論　　 
　　〇〇の部分のアソシエーションに　optional: true　を追記してあげる


```
class Poop < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :user
  belongs_to :humans, optional: true
```

#　optional: trueとは
__外部キーがnillであることを許可してくれるオプションです。__

バリデーションにひっからず保存されるようになります。
詳しくは下記リンクに書いてあります。
https://railsguides.jp/association_basics.html#optional

#なぜこんな事が起こったか

```

  def create
    poop = Poop.create(poop_params)
    if poop.save #ここのsaveでhuman_idがないために起こったエラー
      redirect_to root_path
    end
  end
```
上記の記述ではエラーが表示されずにログでしか確認できないのですが、
save!とすることでValidation failed: 〇〇 must exist
とエラー内容を知る事ができました。
下記save!について詳しく書かれていたページ
https://techacademy.jp/magazine/22082
なぜ Internet Explorerを使い続けるの？

もうサポートが切れそうなInternet Explorer なぜ使い続けるのでしょうか？

いっそのことリサーチをかけてしまいました。

##Windows 8.1 以前の方で Internet Explorerだけ使用される方にお伺いします
なぜデフォルトブラウザのInternet Explorerだけ使用し、他のブラウザには興味がないのでしょうか？

・使い慣れているから
・新しいのを使うのは面倒なので
・なんとなく使い続けている
・あまり使わないから（Webを見ることやPCを使うこと）
・explorerのが慣れているので、他のを取り込んで試したけど、慣れているものにかなわなかった。
・前バージョンから使っているのでその流れで
・新しいものを覚えるのが面倒なので
・インターネットエクスプローラーが一番使い心地が良いから
・お気に入りに登録してあるのを移すのが面倒
・使い方が簡単だから
・Internet Explorerで満足しているから
・PCに詳しくないのでどのように新しいブラウザーをインストールするのかわからないからです

##あまり問題になる行為ではないですが、ついでに聞いてみました
Windows 10 以降で edgeだけを使用している方にお伺いします

なぜデフォルトブラウザのEdgeだけ使用し、他のブラウザには興味がないのでしょうか？

・設定を変えるのがめんどくさい
・edgeで問題ないから
・互換性もあるし読み込みもスムーズだしedgeで間に合ってるから
・互換性がありそうだから
・パソコンではおおむね決まったサイトしか表示しか表示しないので、どれでもよい
・わざわざインストールするのが面倒で、edgeに不満がないから
・使い慣れているから
・Edgeがデフォルトインストールされているから
・システム部のお達しによりインストールが規制されているから
・IEがサポートされなくなって自動的に切り替わることで使い慣れたから
・表示スピードが速いので
・MSの提供だからの安定性です
・慣れが第一だと思うので
・他のブラウザの操作を覚えるのが面倒
・マイクロソフトのブラウザに慣れているからです

等。。。。
Laravelで自作のバリデーションのルール(Rule)を使う際に躓いた事

Laravelのバリデーションで、
独自のルールをrulesで利用する際に躓いた箇所が有ったのでその部分について書いています。

Laravelのバージョンは7です。

#ルールを作成する
作成するところまでは、以下の記事を参考にしました。
[Laravelでバリデーションのルール(Rule)を追加する！](https://codelikes.com/laravel-add-validation-rule/)


#今回躓いたところ
今回バリデーションで追加したruleを使う際に、既に他の作業者が以下の記法でrulesを作成していました。

```php:Requests/SampleRequest.php
    public function rules()
    {
        return [
            'column' => 'required|max:255|exists:table,condition',
        ];
    }
```

記事を愚直に真似てみた感じです。。。
これだと上手く動かなかったです

```php:Requests/SampleRequest.php
    public function rules()
    {
        return [
            'column' => ['required|max:255|exists:table,condition', new CustomMadeRule() ]
        ];
    }
```


下記の様に連想配列に統一したら直りました。

```php:Requests/SampleRequest.php
    public function rules()
    {
        return [
            'column' => ['required','max:255','exists:table,condition', new CustomMadeRule() ],
        ];
    }
```

おしまい、ケル
.NET 5とか.NET 6とか。

[以前の記事](https://qiita.com/sasuke_sss/items/43a2a9c66eaa38453564
)で
.NET Framework と.NET Coreの２つの系列があるんですね
と書いたのですが、

最近、去年の11月(2020/11)に、.NET 5が発表されて、
先月、今年の11月(2021/11)に、.NET 6が発表されたというのを知り、
なにこれ？と、ちょっと調べてみた所、
.NET Framework系列は廃止の方向で、.NET 系列に一本化されるようです。

(.NET 5や.NET 6は.NET Core系列の新バージョンなので、.NET Coreに一本化されて、名前が.NETに変更になったみたいな感じ？）

今後新しく開発する際には、.NET Framework系列ではなく、.NET系列を使うのが望ましいようです。

# 参考URL
https://www.wake-mob.jp/2020/11/net-framework-48-net-50.html
https://www.wake-mob.jp/2021/11/net-60-lts.html
https://blog.inedo.com/jp/dotnet/net5-release-prep
https://blog.inedo.com/jp/dotnet/net5-web-forms
https://devblogs.microsoft.com/dotnet/announcing-net-6/
NCMB Kotlin SDK（デベロッパープレビュー）で各種データを保存してみる

NCMBでは各種プラットフォーム向けにSDKを提供しています。iOSであればObjective-CとSwiftがあります。Android向けにはこれまでJava SDKのみでしたが、現在[Kotlin向けにもSDKを開発中](https://github.com/NIFCLOUD-mbaas/ncmb_kotlin)です。

まだデベロッパープレビューの段階ですが、先日v0.2.0をリリースしましたので、それを使ってデータを保存してみました。

## インストール

Android Studioでプロジェクトを開き、以下の手順でSDKをインストールしてください。

1. app/libsフォルダにNCMB.jarをコピーします
2. app/build.gradleファイルに以下を追加します

```
dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.8.1'
    implementation 'com.google.code.gson:gson:2.3.1'
    api files('libs/NCMB.jar')

    //同期処理を使用する場合はこちらを追加していただく必要があります
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
}
```

## クイックスタート

### AndroidManifest.xmlの編集

&lt;application&gt;タグの直前に以下のpermissionを追加します。

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
```

### 初期化

ActivityのonCreateメソッド内に以下を記載します。

```kotlin
NCMB.initialize(this.getApplicationContext(),"YOUR_APPLICATION_KEY","YOUR_CLIENT_KEY");
```

* 利用する機能に合わせて使用するライブラリのimport

```kotlin
import com.nifcloud.mbaas.core.NCMB //全機能必須
import com.nifcloud.mbaas.core.NCMBCallback //非同期処理を行う場合
import com.nifcloud.mbaas.core.NCMBException //例外処理を行う場合
import com.nifcloud.mbaas.core.NCMBObject //データストアを利用する場合
import com.nifcloud.mbaas.core.NCMBUser //会員管理を利用する場合
import com.nifcloud.mbaas.core.NCMBGeoPoint //位置情報を利用する場合
import com.nifcloud.mbaas.core.NCMBQuery //検索機能を利用する場合
```

## データ保存の基本

一番基本となるデータ保存は次のようになります。これは同期的に保存しています。

```kotlin
val obj = NCMBObject("TestClass")
obj.put("string", "Hello, NCMB!") // 文字列
obj.save()
```

## 数字・真偽値

数字や真偽値であれば、文字列と同じように指定します。

```kotlin
obj.put("number", 100) // 数値
obj.put("boolean", true) // 真偽値
```

## 位置情報

位置情報を保存する際には専用のNCMBGetPointクラスを使います。

```kotlin
val geo = NCMBGeoPoint(35.6666269, 170.765607)
obj.put("geo", geo)
```

## 日時

v0.2.0の時点では日付はJSONObjectで指定する必要があります。将来的にはDate/DateTime/LocalDate/LocalDateTimeなどに対応できるはずです。

```kotlin
val date = JSONObject()
date.put("__type", "Date")
date.put("iso", "2014-06-03T11:28:30.348Z")
obj.put("date", date) // 日付
```

## ACL

アクセス管理を行うACLは専用のクラスNCMBAclを使います。さらにsetAclという専用のメソッドを使って設定します。

```kotlin
val acl = NCMBAcl()
acl.publicReadAccess = true
acl.publicWriteAccess = false
obj.setAcl(acl)
```

## 配列

配列はJSONArrayを使います。

```kotlin
val array = JSONArray()
array.put(1)
array.put(2)
array.put("1")
obj.put("array", array) // 配列
```

## オブジェクト

オブジェクトは日付と同じでJSONObjectを使います。

```kotlin
val o = JSONObject()
o.put("a", "b")
o.put("c", 100)
obj.put("object", o) // オブジェクト
```

## まとめ

データストアではこの他にもポインター（別なNCMBObject）やリレーションなども指定できます。それらのデータも近々対応できるでしょう。Kotlinアプリを開発する際に、ぜひ試してみてください。

[NIFCLOUD-mbaas/ncmb_kotlin: NIFCLOUD mobile backendのKotlin SDK](https://github.com/NIFCLOUD-mbaas/ncmb_kotlin)
GA4のUserId利用でユーザー数が増える件

## 課題

アプリWebviewとブラウザが併用されるサービスにて、GA4のUserId導入後にユーザー数が急増してしまいました。
UserIdを導入したと同時に2倍まではいかないものの、1.5倍近くまで増えています。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/a26e9d7f-c280-474c-d894-5f22e2fcda08.png)


DAUに関してGA4のGUI上では32万と表示されていて、UniversalAnalyticsのUserIdビュー上では14万と表示されています。（この記事の数値は実際の数値を改変しています）

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/4e023cbb-f752-756e-3066-cb32df63777b.png)

![ua.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/0c21cbca-87dc-221b-baff-a429737dcd6e.png)

UAのUserIdビューはUserIdがセットされないユーザー（非ログインユーザー）は計上できないため、GA4とUAの差異は起こり得ますが、それにしても差が大きすぎます。

## BQで抽出してみる



それぞれuser_idとuser_pseudo_idを比較してみることにします。

```SQL
SELECT
  count(distinct user_id) as user_id,
  count(distinct user_pseudo_id) as user_pseudo_id
FROM
  `projectName.analytics_xxxxxxxxx.events_20211211`
```

## 結果

user_idが14万、user_pseudo_idが18万という値が返却されました。
14万という数値はUAのUserIdビューと一致しています。そしてこの2つを足し算すると32万という値になります。

| user_id | user_pseudo_id |
|---------|----------------|
| 142060 | 181193        |

本来、ユーザー数を正しく計測するには「userIdの数」と「user_idが無い、user_pseudo_idの数」を足し算する必要がありますが、現状のGA4では「userIdの数」と「user_pseudo_idの数」を足し算した値を「ユーザー数」として表示しているのかもしれません。

## 関連ページ
https://support.google.com/analytics/answer/9213390

https://developers.google.com/analytics/devguides/collection/ga4/user-id?technology=gtagjs
Dynamics 365 Finance and Opeartions ~ 調査・学習の仕方 ~

おはこんばんちは。
Dynamics 365 Finance & Operations (FO) の調査・学習をする際に役立つサイトを思いつく限りでリスト化します。

# Microsoftで運営しているもの
## 1. [Microsoft Docs](https://docs.microsoft.com/ja-jp/dynamics365/fin-ops-core/fin-ops/)
王道であり、正解が書かれています。まずはここを。
ただ、やはり各機能ごとの説明という作りなので、もう少し長めのユースケース・シナリオでどう使うかを知りたい場合は不十分になりがちです。
また注意点としては、英語版（en-US）が最新で、その後に各言語の翻訳版（e.g. ja-JP）がリリースされるので、念のため英語版を確認した方がいいですね。あとは細かい話はAXシリーズのDocsにも書かれているケースがあるので、そちらも見ておくといいでしょうね（AXとFOで大きな仕様は変わっていないという前提ですが...）。

## 2. [Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/dynamics365/)
こちらは主に 1. Microsoft Docs の内容を組み合わせて、ユースケース・シナリオを意識して作られたMS公式の学習リソースです。
学習の最後には理解度をチェックする小テストもあります。
また、どういった流れでLearnのコンテンツを進めていくかに悩まれている場合は、[こちら](https://partner.microsoft.com/ja-jp/training/mstep-dynamics)のトレーニングジャーニーに従って進めていくのがありかなと思います。

## 3. [Microsoft Virtual Training Day](https://www.microsoft.com/ja-jp/events/top/training-days/)
無料オンライントレーニングです。皆様からのご質問にリアルタイムで回答してくれます。
また、各種Microsoft認定資格受験へ向けての学習コンテンツとしてもご活用いただけます。

## 4. [mstep](https://partner.microsoft.com/ja-jp/training/mstep-online)
MSパートナーネットワークへご登録のパートナーさま向けに無償で受講いただけるLiveトレーニングです。パートナーネットワークへの参加ならびに、mstep への参加は無償です。積極的にご活用ください。
主力製品を中心に、対象ロール、学習レベルごとに随時ご提供しています。

## 5. [Japan Dynamics ERP Support Blog](https://jpdynamicserp.github.io/blog/)
日本マイクロソフトのサポートチームのブログです。日々、様々なお客様からのお問い合わせを対応しているチームからの情報は、貴重かつ共感できるものも多いかと思いますので、ぜひご一読を！

# Microsoft以外で運営しているもの
## 6. [Dynamics Community](https://community.dynamics.com/)
最大規模のWWのユーザコミュニティ。英語のみ。
非常にExpertな方々が数多くいて、質問したらすぐにレスポンスくれます。私もよく使います。
なんでも質問していい場ですが、回答に責任は取れないので、あくまでちゃんとした仕様確認やトラシューはMS公式で。
ただ、ちょっとしたエラーメッセージ・機能の挙動・コーディングの確認なんかには、すごく便利かと思います。

## 7. [D365UG FO](http://www.axug.com/home)
## 8. [Dynamics User Group](https://www.dynamicsuser.net/)
Dynamics Communityに次ぐ？WWのユーザコミュニティ。英語のみ。
VBScript用の日付フォーマット関数

VBScript には、VBA にあるような Format関数がないので、簡易的な日付フォーマット関数をつくってみる。

```vb
Function DateFormat(ByVal date_value, ByVal fmt)

'// 日付を fmt 形式の文字列で返す
'// "yyyy"は西暦4桁、"yy"は西暦下2桁、"y"は和暦、"0y"は和暦0付き、gは元号（明治以前は西暦）
'// "m"、"d"、"h"、"n"、"s" は 月、日、時、分、秒（二文字の場合は0つき2桁）
'// "aaa"は曜日、"a"はその略字

	Dim yyyy, yy, y, g, mm, m, dd, d, hh, h, nn, n, ss, s, aaa, a

	yyyy = Year(date_value)
	m = Month(date_value)
	d = Day(date_value)
	h = Hour(date_value)
	n = Minute(date_value)
	s = Second(date_value)
	aaa = WeekdayName(Weekday(date_value))

	yy = Right(yyyy, 2)
	mm = Right("0" & m, 2)
	dd = Right("0" & d, 2)
	hh = Right("0" & h, 2)
	nn = Right("0" & n, 2)
	ss = Right("0" & s, 2)
	a = Left(aaa, 1)

	fmt = Replace(fmt, "yyyy", yyyy)
	fmt = Replace(fmt, "yy", yy)

	If date_value < #1868/9/4# Then g = "": y = yyyy
	If date_value >= #1868/9/4# Then g = "明治": y = yyyy - 1867
	If date_value >= #1912/7/31# Then g = "大正": y = yyyy - 1911
	If date_value >= #1926/12/27# Then g = "昭和": y = yyyy - 1925
	If date_value >= #1989/1/8# Then g = "平成": y = yyyy - 1988
	If date_value >= #2019/5/1# Then g = "令和": y = yyyy - 2018

	fmt = Replace(fmt, "0y", g & Right("0" & y, 2))
	If y = 1 Then y = "元"
	fmt = Replace(fmt, "y", g & y)

	fmt = Replace(fmt, "mm", mm)
	fmt = Replace(fmt, "dd", dd)
	fmt = Replace(fmt, "hh", hh)
	fmt = Replace(fmt, "nn", nn)
	fmt = Replace(fmt, "ss", ss)
	fmt = Replace(fmt, "aaa", aaa)

	fmt = Replace(fmt, "m", m)
	fmt = Replace(fmt, "d", d)
	fmt = Replace(fmt, "h", h)
	fmt = Replace(fmt, "n", n)
	fmt = Replace(fmt, "s", s)
	fmt = Replace(fmt, "a", a)

	DateFormat = fmt

End Function
```

テスト結果：

```vb
Msgbox DateFormat(Now, "yyyy-mm-dd_hhnnss")
'⇒ 今日の「年-月-日_時分秒」

Msgbox DateFormat(#1989/1/8 9:45:12#, "y年m月d日（a）hh時nn分ss秒")
'⇒ 平成元年1月8日（日）09時45分12秒
```
[SSH]手元のUbuntuからリモートのmysqlサーバーにssh tunnelで接続しようとしたらハマった件について

# 概要
dockerで開発しているときに、リモートにあるサーバーに入っているmysqlの中身を参照したくなりました。
というわけでトンネル接続をしてmysqlコマンドを流そうと思い立ち、実際に実行…するまでにハマったポイントについての解説と実行の記事です。

また、実際に行った事柄について時系列順で述べているので**寄り道が発生しています。**
**同じように引っかかった人は必ず最後のまとめまで見てから実行してください。**

## 環境

ローカルサーバー
Ubuntu 20.04

リモートサーバー
CentOS
Mysql 5.6.34

## やろうとしたこと
```shell
$ ssh -L 9999:localhost:3306 -p xxxx user@remote.server

# 別のシェルにて
$ mysql -P 9999 -u user -p
```

これを行ったときに以下のエラーが出ます。

```shell
Could not create unix socket lock file /var/run/mysqld/mysqld.sock.lock
```

## とりあえず
上記エラーで検索を行ったところ、以下の記事がヒット
https://qiita.com/fukamiiiiinmin/items/a358498b8adb37a7c251
mysqlを入れて、sockファイルがきちんと生成できるように権限を整えてあげればいいらしい。

## というわけで
mysqlをUbuntuにインストールし、`/var/run/mysqld`ディレクトリを生成して権限を`mysql:mysql`に修正。
サービスからmysqlを起動したところ、無事にローカルにmysqlを起動することができました。

というわけで、エラーがなくなったはずのmysqlに再び接続です。

```shell
$ ssh -L 9999:localhost:3306 -p xxxx user@remote.server

# 別のシェルにて
$ mysql -P 9999 -u user -p
> password: 
> ERROR 1045 (28000): Access denied for user 'user'@'localhost' (using password: YES)
```

**やっぱり接続できない……**

## もしかしてMysqlが動いているように見せかけてエラーしてる？
とりあえず、ローカルのMysqlに接続できるか確認してみました。

```shell
$ mysql -u root -p

...

mysql>
```
正常成功しています。
念のためローカルのstatusを見てみましょう。

```shell
mysql> status
--------------
mysql  Ver 8.0.27-0ubuntu0.20.04.1 for Linux on x86_64 ((Ubuntu))

Connection id:          10
Current database:
Current user:           root@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         8.0.27-0ubuntu0.20.04.1 (Ubuntu)
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
UNIX socket:            /var/run/mysqld/mysqld.sock
Binary data as:         Hexadecimal
Uptime:                 8 sec

Threads: 2  Questions: 9  Slow queries: 0  Opens: 117  Flush tables: 3  Open tables: 36  Queries per second avg: 1.125
--------------
```

あれ？**ステータスの中にポート番号が入ってない…？？？？**

## そもそもConnectionがおかしいぞ？
そもそもやろうとしているのは**ソケット通信ではなくTCP/IP接続**のはず……
というわけで、再び検索。
「MySQL ポート番号が効かない」で検索

https://su-kun1899.hatenablog.com/entry/2016/10/27/005410

> Unix では、MySQL プログラムはホスト名 localhost を、ほかのネットワークベースのプログラムと比較して想定されるのとはおそらく異なる、特別な方法で扱います。localhost への接続で、MySQL プログラムは Unix ソケットファイルを使用してローカルサーバーに接続しようとします。これは、ポート番号を指定するために --port または -P オプションが与えられた場合にも生じます。クライアントがローカルサーバーに TCP/IP 接続を行うことを保証するには、--host または -h を使用して、ホスト名の値 127.0.0.1、またはローカルサーバーの IP アドレスまたは名前を指定します。--protocol=TCP オプションを使用して、localhost に対しても、接続プロトコルを明示的に指定することもできます。

つまり、`-h localhost`（つまりデフォルトでホストを指定していない状態）はUnixソケットファイルを使用して強制的にローカルに行ってしまう。と。


# 結論から言うと
IPアドレスの場所にlocalhostを指定すると勝手にsocket通信が展開されてしまうため、そもそもポート指定オプションが効かない＝ローカルのmysqlにがんばって接続しようとしていた。のが問題だったようです。

正しい例は以下

```shell
$ ssh -L 9999:127.0.0.1:3306 -p xxxx user@remote.server

# 別のシェルにて
$ mysql -h 127.0.0.1 -P 9999 -u user -p
password: 
mysql> 
```

当然ですが**ローカル環境にMySQLは必要ありません**。
間違えてインストールしてしまった場合はしっかりアンインストールするか、そっとサービスストップしてあげましょう。

お粗末様でした。
[py2rb] sys.exc_info

# はじめに
移植やってます
# sys.exc_info (Python)
```python
try:
    if self._pass_file:
        self._reader = self._func(
            self._source, *self._args, **self._kwargs)
    else:
        self._reader = self._func(*self._args, **self._kwargs)
except Exception:
    self.__exit__(*sys.exc_info())
    raise
```
`sys.exc_info`はスタックトレースを返すようです。
# inject (Ruby)
```ruby
begin
  if @_pass_file
    @_reader = _func(@_source, @_args, @_kwargs)
  else
    @_reader = _func(@_args, @kwargs)
  end
rescue => exception
  self._source.__exit__(exception.message, exception.backtrace)
  raise
end
```
`message`か`backtrace`を返します（予定）
# メモ
+ Python の sys.exc_info を学習した
+ 道のりは遠そう
Rustの使い方メモ

自分用メモ。

# 開発環境
## インストール
`apt install` とかはできないぽい。

```
curl https://sh.rustup.rs -sSf | sh
```

このスクリプトの出力の通りだが、`~/.rustup` と `~/.cargo` が作られる。`cargo`、`rustc`、`rustup` などのコマンドは `~/.cargo/bin` にあるのでそこにPATHを通す必要があるが、勝手にやってくれる。

`rustup self uninstall` でこれらをアンインストールできるらしい。

## cargo
### プロジェクト作成
```
cargo init
```

`cargo new xxx --bin` とかでもいいらしい。`--bin`はbinaryを作るcrateであることを示すフラグ。`cargo init`でもbinaryを作るように生成されるように見える。

### 実行
```
cargo run
```
で走らせられる。`cargo run -- args`でコマンドライン引数を渡せるぽい。

### ビルド
```
cargo build
```
でバイナリを作れる。`cargo build` では `target/build/xxx` にでき、`cargo build --release` では `target/release/xxx` にできる。

# 言語仕様
## into()
`Into<T>` traitを実装していればinto()が使えるという感じぽい。

```rust
pub trait Into<T> {
    fn into(self) -> T;
}
```

https://doc.rust-lang.org/std/convert/trait.Into.html

ただし、

> One should avoid implementing Into and implement From instead. Implementing From automatically provides one with an implementation of Into thanks to the blanket implementation in the standard library.

実際には `From<T>` を実装することが期待されている模様。

```rust
pub trait From<T> {
    fn from(T) -> Self;
}
```

https://doc.rust-lang.org/std/convert/trait.From.html

## $foo
`$foo` は `macro_rules!` の引数で使われる。

> The arguments of a macro are prefixed by a dollar sign $ and type annotated with a designator:

https://doc.rust-lang.org/rust-by-example/macros/designators.html
Teams アクティビティ レポートを解読する

# はじめに

本記事はこの動画の簡単なまとめです。
興味があれば動画を御覧ください！

https://youtu.be/JHudkNEA9is

## 参考URL
https://qiita.com/ishiayaya/items/d2b19777bb302154ab33

https://docs.microsoft.com/ja-jp/power-bi/collaborate-share/service-teams-analytics

# Teams アクティビティ レポート
Teamsをどのくらい使用しているか可視化されたテンプレートレポートです。
作成の仕方は上記参考URLを御覧ください。

# 各項目を確認する

## My activity
自分の参加ミーティング数や主催ミーティング数、音声ONの時間などを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/fc1d54b1-f34a-7235-db38-a47b76e4979e.png)

## Team activity
イベント用のTeam／チャネルなどで、活動がなくなっているチャネルを発見し削除する・・といった用途が紹介されていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/30388ae2-a1bd-cfe7-c071-dec4681285a1.png)

## Team activity details
Teamごとのアクティブユーザーの数を確認することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/3b5fd3cc-7685-39bb-a934-e71dbfec0c8e.png)


# さて自分のレポートは・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/2c4df62a-5f20-80b9-1ad2-936df8cb6362.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/ed0bbe73-9688-dbf3-6b99-7b6c790b9653.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/00870857-ea24-7957-e721-11682e8435b7.png)

#まとめ
削除あるいは退会、非表示にできそうなTeamがいくつもみつかりました。左側のカラムがスッキリ！
GitHub Actions から App Center にアップロードする

# はじめに

GitHub Actions には便利な[マーケットプレイス](https://github.com/marketplace?type=actions)があり、[App Center](https://github.com/marketplace?type=actions&query=App+Center+) についても色々あります。

ただ、ここで配信されているのが結構どれも Linux でホストされている環境でのみ利用可能ということでしたので、どうしても iOS のビルドの後にパッケージにデプロイしないといけなく、無駄に容量を使ってしまうものばかりでした。

そこで appcenter-cli は自前でもインストールできるので、そのやり方を残しておこうかと思います。

2022/2/22 追記：
いちいち書くのが面倒なのでマーケットプレイスでアクションを公開しました。
[GitHub Marketplace: AppCenter distribute GitHub action](https://github.com/marketplace/actions/appcenter-distribute-github-action)

# App Center CLI のインストールチェック＆インストール

```YAML
- name: Check appcenter
  id: appcenter
  run: |
    appcenter -v
  continue-on-error: true

- name: Install appcenter-cli
  if: ${{ steps.appcenter.outcome == 'failure' }}
  run: |
    npm install -g appcenter-cli
```

まず、ホストする環境に appcenter-cli がインストールされている必要があるので、実行チェックを行いインストールされていない場合のみインストールを行うようにします。

# ipa のアップロード

```YAML
- name: Upload ipa to App Center
  run: |
    appcenter distribute groups publish -n $GITHUB_RUN_NUMBER -f $IPA_PATH -r "$RELEASE_NOTE" -a $APP_NAME -g $DISTRIBUTION
  env:
    APPCENTER_ACCESS_TOKEN: ${{ secrets.APPCENTER_ACCESS_TOKEN }}
    IPA_PATH: ${{ runner.temp }}/Export/ProductName.ipa
    APP_NAME: CLOUD-CREATIVE-STUDIOS/${{ env.PROJECT_NAME }}-${{ env.BUILD_TARGET }}
    RELEASE_NOTE: |
      ${{ env.PROJECT_NAME }}-${{ env.BUILD_TARGET }}
      - GitHub Actions
        - Action : ${{ github.event_name }}
        - Requester : ${{ github.actor }}
        - Build Number : ${{ github.run_number }}
        - Commit Message : ${{ github.event.head_commit.message }}
      - Configurations
        - Configuration : ${{ env.CONFIGURATION }}
        - Team ID : ${{ env.TEAM_ID }}
        - Distribution : ${{ env.DISTRIBUTION }}
```

上記では以下の環境変数を用意しておく必要があります。

- `APPCENTER_ACCESS_TOKEN` : App Center API トークン
- `PROJECT_NAME` : プロジェクト名
- `BUILD_TARGET` : ビルドターゲット (iOS or Android)
- `CONFIGURATION` : Debug or Release
- `DISTRIBUTION` : App Center の配信先グループ名

※API トークンについては以下を参照ください。

https://qiita.com/akiojin/items/dd2f7e21e9904ce926ca

# おわりに

App Center の場合、マーケットプレイスに配信されているものを利用しなくても、上記のようにコマンドさえ分かっていれば簡単に書けます。
Laravelにおいてblade componentあるいはVue componentへ値を渡す方法

"laravel コンポーネント props"と調べると、Vueへの変数の渡し方しか出てこないので、
blade componentへの変数の渡し方とまとめて投稿します！

# 1. blade componentへの渡し方

### 1.文字列
```php:parent.blade.php
<component-name property_name="渡したい文字列" />
```
セミコロンは必要ありません。

### 2.PHPの変数
```php:parent.blade.php
<component-name :property_name="$value" />
```
セミコロンが必要です。

#### その他
値を受け取ったblade component内ではローワーキャメルケースになります。

```php:component-name.blade.php
<div>{{ $propertyName }}</div>
```


# 2. Vue componentへの渡し方

### 1.文字列
```php:parent.blade.php
<VueTemplate v-bind:property='文字列' :shorten_property='文字列'/>
```
v-bindは省略できます。

### 2.PHPの変数
```php:parent.blade.php
<VueTemplate :property='$value'/>
```

### 3.Laravelのヘルパー関数
```php:parent.blade.php
<VueTemplate :route="'{{ route('user.create') }}'" />
```
'{{ }}'で囲ってあげる。

#### その他
値を受け取ったVue component内ではローワーキャメルケースになります。
1のbladeファイルと同じ。

```php:VueComponent.vue
export default {
    props: {
        shortenProperty: String,
    }
```
UnityネイティブプラグインのM1 Mac対応

この記事は [クラスター Advent Calendar 2021](https://qiita.com/advent-calendar/2021/cluster) 16日目の記事です。
昨日は@194_alertさんの「[ワールド紹介動画の撮影について](https://qiita.com/194_alert/items/26e6218207f5b94fcd7b)」でした。

こんにちは。ソフトウェアエンジニアの[izumi](https://twitter.com/rizumi_jp)です。
クラスター社ではiOSとかUnityとか色々やっています。

今回は表題の通りUnityネイティブプラグインのM1 Mac対応についてのお話しです。

# Unityネイティブプラグインとは

[ネイティブプラグイン](https://docs.unity3d.com/ja/2019.4/Manual/NativePlugins.html) とは、C、C++、Objective-C、Javaなどで書かれたWindows、Mac、iOS、AndroidなどのプラットフォームのネイティブコードをライブラリとしてUnity側のC#から呼び出す仕組みです。
この仕組みによって、Unityには提供されていないネイティブの処理やデバイス依存の処理などを実装することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117503/2ff78e56-fbfd-c7a3-5b34-0346be7121f1.png)

[メタバースプラットフォーム cluster](https://cluster.mu/)は、Windows、MacOS、iOS、Android、Oculus Quest2のマルチプラットフォーム対応アプリケーションで、オーディオ処理などでネイティブプラグインを活用しています。
しかしながら、M1 Macでは主にこのネイティブプラグインが原因で正常動作ができず、開発機もIntel MacやWindowsを用いるようにしていました。
※M1 Macユーザー向けにはiOS版の利用を推奨していました[^1]

(これは余談ですが、M1 MacではUnity Editorで実行した瞬間にUnityがクラッシュしてしまっていたため、原因の特定や調査が困難でした。)

# M1 Mac対応

2021年10月のAppleのオンラインイベントでM1 Pro/M1 Max搭載の新型MacBook Pro発表と同時にIntel製のMacBook Proは販売を終了してしまいました。[^2]
このままではMacBook Proでの開発が継続して行えなくなってしまうため、M1 Mac対応を行いました。

MacOS向けのネイティブプラグインはbundle形式で生成し、Xcodeを使ってbuildします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117503/38781c18-997c-6b15-5635-8797f8b984b4.png)

M1 Macに対応するにはBuild Settingsで以下の設定をします。

- ArchitecturesをStandard Architectures (Apple Silicon, Intel)する
- Excluded Architecturesを空にする(x86_64/arm64が入ってなければ大丈夫だとは思います)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117503/2b73bf78-c0c1-82b6-5e51-2ccabf51e42d.png)

また、Build Active Architecture Onlyの設定の通りDebug実行時には対象のアーキテクチャのみしかビルドされないため、ネイティブプラグインとして出力する場合にはConfigurationをReleaseにしてビルドする必要があります。

# Static Libraryの対応

基本的には上記設定でM1 Mac/Intel Mac共に動くBundleができるのですが、厄介なのがXcodeを介さずに書かれたStatic Libraryを参照しているケースで、参照しているライブラリについてもM1 Mac対応をする必要があります。
clusterではC++向けのライブラリなどを手元でbuildして利用しているケースがあるため、この手順が必要でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117503/0ff185d5-43cb-3f6d-4348-b40a25e90545.png)

この場合、M1環境とIntel環境(Rosseta)それぞれでライブラリを作成し、lipoコマンドを用いてUniversal Static Libraryにすることで解決します。

```.sh
lipo -create libintel.a libarm.a -output libuniversal.a
```

正しく生成できた場合は、lipo -infoで下記のようにx86_64とarm64の両方が対応されたことが分かります。

```.sh
lipo -info libuniversal.a
# Architectures in the fat file: libuniversal.a are: x86_64 arm64
```

この対応をした後にもう一度Xcodeでbundleを生成してIntel/M1両対応のネイティブプラグインの完成です🎉

# おわりに

ネイティブプラグインをM1 Macに対応したことで今後も安心してMacBook Proを使って行けるようになりました。
これにより**会社の支給マシンもM1 Max/RAM64GBの特盛マシンになりました！！**

エンジニア絶賛募集中ですので、M1 Max使って仕事したい人は是非来てください！[^3]

https://recruit.cluster.mu/engineer/

以上。

明日は@Hashimoto_Mamiさんの「なんか書きます」です。

[^1]: [一部の環境でMac版が動作しない不具合・M1 Mac対応版のβリリースのお知らせ](https://note.com/cluster_official/n/n987703411e17)
[^2]: [さようなら、Intelチップ搭載MacBook Pro](https://iphone-mania.jp/news-413281/)
[^3]: 詳細なスペックは面談等で聞いてください
react-table + TypeScriptのお作法

プラグイン(useSortBy, usePagenationなど)を使った場合、型が合わなくて泣きそうになった。この解決方法が公式に載っていないので、悩んだ人のためのメモ。

# 前提

@types/react-tableを見るとそれっぽい型が定義されている。ただ、これらは標準では使えず、以下のいずれかの方法で使うことになる。

# 方法1 アンビエントモジュール

以下のファイルのような型定義で、グローバルな型を拡張してしまう。
https://github.com/ggascoigne/react-table-example/blob/master/types/react-table-config.d.ts

このファイルはプラグイン全部入りだけど、このうち必要なものだけを選んで使えば悪くなさそう。

欠点は、プロジェクト内で使うプラグインが統一されていない場合、TypeScriptの型と実行時の型が合わなくなってしまうこと。

# 方法2 キャスト
随時キャストする。

以下のコードは、useSortBy, usePaginationを使った場合のキャストの例。

どの型をどう拡張するべきかは、方法1で示したリンクを見れば分かるはずだけど、それなりに悩む。

```tsx
export type columnOption<D extends object> = Column<D> & UseSortByOptions<D>;

const Table = <D extends object>({
  columns,
  data,
}: {
  columns: columnOption<D>[];
  data: D[];
}) => {
  const table = useTable<D>(
    {
      columns,
      data,
    },
    useSortBy,
    usePagination
  ) as TableInstance<D> &
    UsePaginationInstanceProps<D> & {
      state: TableState<D> & UsePaginationState<D>;
    };
  const { headerGroups } = table;
  return (
    <div>
      <thead>
        {headerGroups.map((headerGroup, headerGroupIndex) => (
          <tr {...headerGroup.getHeaderGroupProps()} key={headerGroupIndex}>
            {(
              headerGroup.headers as (HeaderGroup<D> &
                UseSortByColumnProps<D>)[]
            ).map((column) => (
              <div></div>
            ))}
          </tr>
        ))}
      </thead>
    </div>
  );
};
```
なんでもヴェイパーウェイヴにする２

前回が全然ヴェイパーウェイヴ要素なかったから仕切り直し

https://qiita.com/o________o/items/0bcb7a3695e2610ce6f6

# とりあえずピッチダウンして遅くすりゃよくね

ffmpeg使った


```
ffmpeg -i motoneta.mp3 -vf setpts=PTS/0.5 -af aresample=48000,asetrate=48000*0.8 -ar 48000 vw.mp3
```

おしまい

ffmpeg-pythonってのあるんだけどうまく動かなかった。
誰かffmpeg-pythonで上の設定再現する方法知ってたら教えてほしい。

# 聞いてみた

それっぽいかもしれない

https://soundcloud.com/bjack_mijilme/python-vaporwave2

ここで作った音源を元ネタにした

https://qiita.com/o________o/items/f219242381674b710ebc

試しにもう一つ作った

https://soundcloud.com/bjack_mijilme/python-vaporwave4

元ネタ

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

よくわからん

# 今後の展開
- リズムトラックのマッシュアップとかしたい
- 音質をローファイにしたい
- pyttsx3使ってテキスト読み上げ音源のせてポエムコアとかにしたい