OmniAICreator/Qiita-1.07M huggingface dataset:
オンラインミーティングをメタバース内で出来るのか(cluster)

![acyber-g6e3747fe3_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/26c7ee85-b1bd-9636-8b5e-659ffd1da43d.jpeg)
最近、話題の”メタバース”。結局どういう事なのか実態が掴めない人も多いのではないだろうか。そんな中、私の会社でも「何かしてみたい」という話になったので、手探りでメタバースを実験してみた、その結果をサラッとレポートしていく。メタバースの解釈は細かく分けると様々ですが、今回は試しにオンラインミーティングを3D空間で出来るかチャレンジしてみた。

# "cluster" をＤＬしてみた
今回使用するのは東京に本社を置く、メタバース企業"cluster"というアプリ。昨今では様々プラットフォームが台頭しているが、自作したアバターを自由に持ち込めるのが何だか楽しそうという、フワッとした独断で選んだ。
始める時はアプリのダウンロードが必要で少し面倒ではあったがアプリ使用時の動き自体は良く、動き自体も比較的滑らかだった。VRゴーグルは無いのでＰＣ版で操作したが、マウスでカメラ操作、十字キーで移動という動きには慣れが必要かもしれない。因みに新規登録時、私はGoogleと紐づけてアカウントを作成した為、アバターの頭の上には自分の名前とGoogleアカウントのアイコンが表示されていた。(下の写真参照)
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/53b6e6a0-88dc-6331-8c39-b79d93673850.png)

# メタバースに入ってみた
利用を開始すると自分のアバターが現れ、広くて綺麗な空港のロビーの様な所についた。(下の写真)
”バーチャルＳＮＳ”というだけあり、早速沢山の人(知らない人)で溢れかえっていた。この近未来的な状況を堪能しようと私は暫くソファーに座ってアバター観察をしてみた。それぞれが思い思いのアバターで、中には動物の形をしたものや何やら判らないものまで多種多様で、それらが集まってコミュニケーションを取っている光景は、近未来的でワクワクするものがある。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/fb9c064b-51d1-3367-2501-c860d42e6bc6.jpeg)

# ミーティング(イベント)をつくる
遊びもそこそこに早速ミーティングの準備をしていく訳だが、アプリでのミーティング設定の動きが悪く、思うように進まない。調べた所、ブラウザで公式HPから設定出来る様なので、そちらでやってみる事に。下の画像の「＋」ボタンから設定が出来るみたいで、ミーティングの設定が何かと選べる項目があったので、紹介していく。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/6d254b70-5049-9709-9dc8-dad277a00bfe.png)

# ミーティングの設定
ミーティングには誰でも参加出来るもの(500人まで)、URLを知っている人しか入れないもの(最大50人で40分まで)があった。
それを選んだらミーティングの名前や概要、画像(サムネみたいなもの)を決めていく。今回は使用しなかったがYouTubeやTwitterとの連携も出来る様で、イベントをバズらせる為のツールの用意はある様だった。その他にも参加者の”権限”などもコントロール出来るみたいで、これにより参加者の出来る事を増やしたり減らしたり出来る。
個人的にいいなと思ったところはミーティングの場所がいくつも選べるので、和室や南国とかもあって少しテンションが上がりました。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/86df24dd-f675-21e7-375e-36498ed20725.png)

# 実践
それでは実践パート。数人に協力してもらいミーティングツールという観点からレヴューしてみた。
快適にミーティングするにあたり、求める要素は幾つかあるが今回は４つにまとめた。

①プライベートな場であるか (他人に話が漏れない)
結果→　URLを知っている人しか入れないのでOK

②会話が出来、テキストでもコミュニケーション出来る
結果→　権限でスピーカーもコントロール出来、テキストもアバター上部と壇上の画面に表示されるという使いやすい仕様
　　　　ただグループワークをしたい時にはそれそれで設定が出来ないから不便かも

③画面や動画等、情報共有の使いやすさ 
結果→　画面共有は壇上に表示され、没入感はあるが少し見づらく、対応ファイルもExcelやWordが表示出来なかった。

④俊敏なリアクション機能 (挙手、拍手等) 
結果→　良い感じ！　立体的で分かりやすいアイコンと音が出ていて種類も豊富。聞く側も非常に参加しやすい機能。(下の写真は拍手中)

・・・と、こんな感じだろうか。無料で行えるのは素晴らしいがプライベート空間は40分が上限なので、利用する場合は圧倒的な"ファシリ力"が要求される事だろう。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/4f60ce6e-d61b-2d97-111f-4f2c542729d1.png)

# まとめ
アプリをダウンロードしてログインすると無料で使用出来る為、ITリテラシーが無くても参入しやすい。参加者の殆どが日本人だったりウォレットやNFTなどがガッツリ絡んでこないのは逆に安心して遊べる要素かも。
社内のコミュニケーションやミーティングツールとしては、やや使い辛いが、一方でしっかりと準備して"講義"を行うにはとても良いプラットフォームだと感じた。

以上「オンラインミーティングをメタバース内で出来るのか」でした。調べ漏れや間違いがありましたら優しく教えてください。
こんな感じで手探りで今後もメタバース関連の記事を投稿していくので時間があればまた見てください！

cluster公式HP
https://cluster.mu/
100日でSQLの達人になる@LeetCode! Day10 <比較する式にもselectが使用可>

## 626. Exchange Seats （問題レベル: Medium）
今日の問題はこれ。この問題は問題ミスがありname -> studentにして解く必要あり。
偶数idと奇数idを前後で入れ替えるが、奇数人しかいない場合は最後はそのままという問題。

最初はテーブルを一つずらして自己結合をするのかと考えたが、単純にidの計算のみで良かった。

```
select 
　　　　case when (id % 2)=1 then id+1 
　　　　　　　else id-1 　　　　end as id, student
from seat
order by id asc
```
基本はこれでOKただし、これでは、奇数人の場合最後の人のidまで変わってしまう。

最終的な回答は下記とした。
```
select 
　　　　case when (id % 2)=1 then 
　　　　　　　(case when id!=(select max(id) from seat) then id+1 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　else 　id 　end) else id-1 end as id, student
from seat
order by id asc
```

今回のポイントは、```case when```を入れ子にした（入れ子にしない方法もできるが入れ子にした方が速度はだいぶ早い）のと、
比較する論理演算の式に```select文```を用いたことだ。

さすがMediumレベルの問題には色々な解法がある。Discussionをざっと見ただけでも、`if文`を多用する例、`union文`を使う例、行番号を使う例など様々な解法があった。
勉強になる！

* [LeetCode](https://leetcode.com/)の問題は、MS SQL Serverで解いています。
【Vue.js】$emitの使い方

# $emitとは

**$emit**は、子コンポーネントでボタンが押されたり、テキストボックスの変更などが発生したときに親コンポーネントに伝えることができる。
また、子コンポーネントから親コンポーネントにデータを渡したいときにも使われる。
子コンポーネントがカスタムイベントを作成して、親コンポーネントに対してイベントを発生させる。その後、親コンポーネントがイベントを検知して処理を実行する。
**$emit**の基本的な書き方は以下となる。

```Vue
this.$emit(<イベント名>,<データ>):
```

## サンプル
**$emit**を使って子コンポーネントから親コンポーネントにデータを渡す簡単なサンプルをメモしておく。

###子コンポーネント

```Vue:Sample.vue
<template>
	<button @click="onClickButton">ボタン</button>
</template>

<script>
export default {
	name: "sample",
	data() {
		return {
			message: "Hello!!",
		};
	},
	methods: {
		onClickButton() {
			this.$emit("onClick", this.message);
		},
	},
};
</script>
```

###親コンポーネント
子コンポーネントのイベントを監視する場合は、```v-on:<イベント名>```または```@<イベント名>```で指定する。
そして、子コンポーネントの**$emit**で指定された値は、イベントで紐づけたメソッドに引数として渡される。

```Vue:App.vue
<template>
	<div>
		<sample @onClick="getMessage" />
		{{ message }}
	</div>
</template>

<script>
import Sample from "./components/Sample.vue";

export default {
	name: "App",
	components: {
		Sample,
	},
	data() {
		return {
			message: "",
		};
	},
	methods: {
		getMessage(value) {
			this.message = value;
		},
	},
};
</script>
```
Qiitaでアスタリスクやアンダーバーを含む数式を書くときの注意

既出かもしれませんが、まとめておきます。

# アスタリスクが認識されない場合の対処
`*`を複数含むコードは上手くレンダリングされないことがあります。

> ##### 【失敗例】
> $\psi_{ij}^{*}$
>
> $\psi_{ij}^{*} \psi_{kl}^{*}$
>
> $\psi_{ij}^{*} \psi_{kl}^{*} \psi_{mn}^{*}$

```:失敗している例のコード
$\psi_{ij}^{*}$

$\psi_{ij}^{*} \psi_{kl}^{*}$

$\psi_{ij}^{*} \psi_{kl}^{*} \psi_{mn}^{*}$
```

これは、Qiita内ではアスタリスクが *Italic* や **Bold** への書式変更に利用されており、2個以上のアスタリスクを含む数式が正しく認識されないことが原因です（実際、上の例では斜体になってしまっています）。

このような場合は `*` の代わりに `\ast` を使うか、 `*` をバックスラッシュでエスケープします。

> ##### 【成功例】
> $\psi_{ij}^{\ast}$
>
> $\psi_{ij}^{\ast} \psi_{kl}^{\ast}$
>
> $\psi_{ij}^{\ast} \psi_{kl}^{\ast} \psi_{mn}^{\ast}$

```:\ast を使う
$\psi_{ij}^{\ast}$

$\psi_{ij}^{\ast} \psi_{kl}^{\ast}$

$\psi_{ij}^{\ast} \psi_{kl}^{\ast} \psi_{mn}^{\ast}$
```

```:バックスラッシュを使う
$\psi_{ij}^{\*}$

$\psi_{ij}^{\*} \psi_{kl}^{\*}$

$\psi_{ij}^{\*} \psi_{kl}^{\*} \psi_{mn}^{\*}$
```

　

# アンダーバーが認識されない場合の対処

Qiitaではアンダーバー `_` もアスタリスクと同様に書式変更に用いられています。

> ##### 【失敗例】（これも部分的に斜体になってしまっています）
>$$\begin{equation}
\begin{aligned}
E_{\mathrm{x}}^{\mathrm{HF}}=-\frac{1}{2} \sum_{i, j} \iint \psi_{i}^{\ast}\left(\mathbf{r}_{1}\right) \psi_{j}^{\ast}\left(\mathbf{r}_{2}\right) \frac{1}{r_{12}} \psi_{j}\left(\mathbf{r}_{1}\right) \psi_{i}\left(\mathbf{r}_{2}\right) d \mathbf{r}_{1} d \mathbf{r}_{2}
\end{aligned}
\end{equation}$$
```:失敗している例のコード
$$\begin{equation}
\begin{aligned}
E_{\mathrm{x}}^{\mathrm{HF}}=-\frac{1}{2} \sum_{i, j} \iint \psi_{i}^{\ast}\left(\mathbf{r}_{1}\right) \psi_{j}^{\ast}\left(\mathbf{r}_{2}\right) \frac{1}{r_{12}} \psi_{j}\left(\mathbf{r}_{1}\right) \psi_{i}\left(\mathbf{r}_{2}\right) d \mathbf{r}_{1} d \mathbf{r}_{2}
\end{aligned}
\end{equation}$$
```

コマンドが多く長い数式の場合は、アスタリスクと同様に、アンダーバーもバックスラッシュでエスケープしておくと良いでしょう。

> ##### 【成功例】
> $$\begin{equation}
\begin{aligned}
E\_{\mathrm{x}}^{\mathrm{HF}}=-\frac{1}{2} \sum\_{i, j} \iint \psi\_{i}^{\ast}\left(\mathbf{r}\_{1}\right) \psi\_{j}^{\ast}\left(\mathbf{r}\_{2}\right) \frac{1}{r\_{12}} \psi\_{j}\left(\mathbf{r}\_{1}\right) \psi\_{i}\left(\mathbf{r}\_{2}\right) d \mathbf{r}\_{1} d \mathbf{r}\_{2}
\end{aligned}
\end{equation}$$

```:エスケープした場合のコード
$$\begin{equation}
\begin{aligned}
E\_{\mathrm{x}}^{\mathrm{HF}}=-\frac{1}{2} \sum\_{i, j} \iint \psi\_{i}^{\ast}\left(\mathbf{r}\_{1}\right) \psi\_{j}^{\ast}\left(\mathbf{r}\_{2}\right) \frac{1}{r\_{12}} \psi\_{j}\left(\mathbf{r}\_{1}\right) \psi\_{i}\left(\mathbf{r}\_{2}\right) d \mathbf{r}\_{1} d \mathbf{r}\_{2}
\end{aligned}
\end{equation}$$
```

　

## その他、Qiita内での数式記法に関する参考記事

Qiitaで数式を記述する上で参考になると思われる記事を挙げておきます。

https://qiita.com/yyu/items/633ae6af08aff4e5805c

https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada
[py2rb] tempfile

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# tempfile (Python)
```python
import tempfile

    def test_tmpfile_text(self):
        with tempfile.TemporaryFile(mode='r') as f:
            self._check_file_object(f, False)
```
おおぅ

https://docs.python.org/ja/3.7/library/tempfile.html
# どうすRuby
```ruby
require 'tempfile'

  def test_tmpfile_text
    Tempfile.open("temp"){ |f|
      _check_file_object(f, false)
    }
  end
```
https://docs.ruby-lang.org/ja/latest/class/Tempfile.html

気になるのは、`temp`の場所とライフサイクルでしょうか。
# メモ
+ Python の tempfile を学習した
+ 百里を行く者は九十里を半ばとす
FTDI Virtual COM Port Driversをアンインストールする方法（Big Sur以降）

IoT関連の開発で、FTDIのVirtual COM Port Driverをインストールしたのですが、その後、アンインストールしたくなったときに手間取ったので、記録として残しておきます。

# 経緯
私がインストールしていたのは、macOS用のドライバー 1.4.7で、2021年5月18日に公開されたものになります。

まず、私の場合、ドライバー（.dext）は下記の中にインストールされていました。
/Library/SystemExtensions
また、シンボリックリンクが下記の中にもありました。
/Library/DriverExtensions

ところが削除するために、Finderから[delete]キーで削除しようとしても、ターミナルから rm -Rf しても、sudoをつけても削除できません。Operation not permitted的なエラーが表示されます。

FTDIのサイトを見ても削除する方法が書かれているものの、内容が古い。
困ったなー、となっていました。

# 解決策
結論をいうと、アンチウィルスソフトベンダーのSophosのサイトに参考となる手順が載っていました。
https://community.sophos.com/intercept-x-endpoint/big-sur-eap/f/recommended-reads/124391/how-to-remove-system-extensions

FTDIのドライバーの場合は、下記の手順となります。

#### 1) System Integrity Protection(SIP) を無効化する

SIPが有効だと2)の手順でエラーになるため、まずSIPを無効にします。SIPを無効にするにはリカバリー（復旧）モードに入って、そこでターミナルを開く必要があります。

リカバリーモードへの入り方はこちらにあります。
https://support.apple.com/ja-jp/HT201255

M1 Macの場合、その後ターミナルまでたどり着く方法はこちらにあります。
https://support.apple.com/ja-jp/guide/mac-help/mchl82829c17/mac

無事にターミナルが開けたら下記のコマンドでSIPを無効化します。

```
csrutil disable
```

#### 2) ドライバーをアンインストール
ターミナルを開いて次のコマンドでアンインストールします。

```
# インストールされているドライバーと、teamIDとbundleIDを確認
systemextensionsctl list

# teamIDとbundleIDを引数にして、uninstallコマンドを実行
systemextensionsctl uninstall 658CPPCMJJ com.ftdi.vcp.dext
```

一度再起動して、ドライバーがアンインストールされていることを確認します。（デバイスを認識しなくなっていることで確認する、など。）

#### 3) SIPを再度有効化する
1)と同じようにしてリカバリーモードでターミナルを開き、下記のコマンドを入力して、SIPを再度有効化します。

```
csrutil enable
```

再起動したら、作業完了です。

以上です。
CentOS 7に新しめのバージョンのSQLite3を導入する

# はじめに
CentOS 7にはデフォルトでsqlite3が実装されるが（2022/2/10時点でyumでアップグレードできる最新バージョンは3.7.17-8）、Django2以降ではバージョン3.9以降が必要になるなど、CentOS 7標準実装のsqlite3では対応できない場合がある。
標準実装のバージョンを削除して新しいバージョンを導入できれば簡単だが、yumはじめCentOS 7内で使用されている機能でsqlite3を利用しているものがいくつかあるため、yum erase sqlite でアンインストールすることができない。
pgdg-commonリポジトリで新しめのsqlite3が提供されているので、これを利用することにする。

# インストールと設定手順
 ```
# pgdg-commonリポジトリの有効化
# yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# リポジトリから利用可能なsqlite関連パッケージの確認
# yum list | grep '^sqlite' | sort
　　：
sqlite33-analyzer.x86_64                   3.30.1-1.rhel7         pgdg-common
sqlite33-debuginfo.x86_64                  3.30.1-6.rhel7         pgdg-common
sqlite33-devel.x86_64                      3.30.1-6.rhel7         pgdg-common
sqlite33-doc.noarch                        3.30.1-6.rhel7         pgdg-common
sqlite33-lemon.x86_64                      3.30.1-6.rhel7         pgdg-common
sqlite33-libs.x86_64                       3.30.1-6.rhel7         pgdg-common
sqlite33-tcl.x86_64                        3.30.1-1.rhel7         pgdg-common
　　：

# SQLite 3.30のインストール
# P=sqlite33; yum -y install $P $P-devel $P-lemon $P-libs

# この状態ではSQLite3が正常に起動しないことの確認
# sqlite3
SQLite header and source version mismatch
2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3dfalt1
2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668

# インストールしたSQLite 3.30の場所の確認
# find / | grep 'sqlite3$'
　　：
/usr/sqlite330/bin/sqlite3
　　：

# CentOS 7のalternative機能を使用して、/usr/local/bin/sqlite3 を登録し、インストールしたバージョンを使用するように設定
# alternative --install /usr/local/bin/sqlite3 sqlite3 /usr/sqlite330/bin/sqlite3 1

# sqlite3で実行できるバージョンの確認
# sqlite3 --version
3.30.1 2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3dfalt1
```
Django 3.2をインストール＆プロジェクト作成し、./manage.py コマンド実行時にSQLite3関連エラーが出ないことを確認した。

【追記】
CentOS Software collections(SCL)リポジトリからインストールしたPython3.8（rh-python38）を使用してDjango3.2を実行したときにはsqlite3エラーが出ることを確認。
epelリポジトリからインストールしたPython3.6の場合はDjango3.2が正常に動作した。
Amazon Comprehendの使い方メモ


Amazon Comprehendの使い方メモ

◆AWSのIAMでcomprehendへのアクセス権限を付与しておく
↓検索窓で「IAM」を検索＆押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718245/f0c9c9c1-0f31-7a4b-008a-e7119da6d994.png)

↓左ペインの「ユーザ」
　「アクセス権限の追加」押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718245/434e663f-5ed1-daa4-c69a-9398badcebc0.png)


「既存のポリシーに・・・」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718245/1e1daef5-5a8f-a58b-3013-06112ec699d4.png)

「ComprehendFullAccess」を検索
「次のステップ：確認」押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718245/3e85700a-1869-cc02-80f1-8565c33f8e20.png)

「アクセス権限の追加」押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718245/fde74e7d-3a09-e8cc-b833-773f969a0598.png)

◆pythonでamazon comprehend実行
anaconda起動
anacondaのjupyter notebook起動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718245/ff8fba19-18c7-4d3c-fa20-a9fc087d5321.png)

以下を入力して実行（RUN押下）

```
import boto3
import json

client = boto3.client('comprehend', region_name='us-east-1')

text = '空気階段の踊り場が大好きです'

response = client.detect_dominant_language(Text=text)
print(json.dumps(response, indent=2))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718245/4952da37-a166-afa5-2611-cfe0ebd0ae41.png)

以上😊っす！
【pluckの使い方】複数のデータがあり絞り込みが出来ない場合


●状況
DBに大量にデータのあるテーブルA、テーブルB、テーブルCが存在する

①テーブルBはテーブルAのカラム１と一致するデータを検索
②テーブルCは、上記で絞り込んだテーブルBのカラム２と一致するデータを検索

```ruby:model
  テーブルA.each do |sample|
   hoge = テーブルB.where(カラム1: sample.カラム1)
   hoge2 = テーブルC.where(カラム2: hoge.カラム2)

  〜省略〜

  end
```

上記を実行すると、「underfind method カラム2 for 〜」とエラーが発生する。

●解決策
テーブルCが複数のデータが必要な場合、
一度hogeの時点でカラム2の配列情報にして渡す必要がある。

現状の内容は、
hogeの内容を見ると下記のように「ActiveRecord::Relation」型となっている。

```
#=><ActiveRecord::Relation [
#<User id: nil, カラム1: "aaa", カラム2: 111>, 
#<User id: nil, カラム1: "bbb", カラム2: 222>, 
#<User id: nil, カラム1: "ccc", カラム2: 333>
#], >
```

これを配列にして渡すことで、テーブルCも必要な絞り込みが出来るようになる。
そのため、下記のように記載するとエラーが出ずに渡せる。

```ruby:model
  テーブルA.each do |sample|
   hoge = テーブルB.where(カラム1: sample.カラム1).pluck(:カラム2)
   hoge2 = テーブルC.where(カラム2: hoge.カラム2)

  〜省略〜

  end
```


参考記事：
【Rails】カラムの値を配列の形で取得したい場合に使えるpluckメソッドを徹底解説
https://coffee-engineer4.com/2021/06/12/%E3%80%90rails%E3%80%91%E3%82%AB%E3%83%A9%E3%83%A0%E3%81%AE%E5%80%A4%E3%82%92%E9%85%8D%E5%88%97%E3%81%AE%E5%BD%A2%E3%81%A7%E5%8F%96%E5%BE%97%E3%81%97%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AB/
[py2rb] warnings.catch_warnings(record=True)

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# warnings (Python)
```python
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter('always')
            result = aux._check_use_index(fo, None, None)
            self.assertEqual(len(w), 0)
```
やっていることは、警告を発生させてその回数を確認している様子。

https://docs.python.org/ja/3.7/library/warnings.html
# どうすRuby
```ruby
module Warning
  def self.warn(message, category: nil)
    @count += 1
  end

  def count
    @count
  end

  def reset_count
    @count = 0
  end
end

Warning.reset_count
10.times do |i|
  warn i
end
puts Warning.count

# 10
```
オープンクラスでやっちゃいました。
# メモ
+ Python の warnings を学習した
+ 百里を行く者は九十里を半ばとす
IIS web アプリケーションからOracle Autonomous database接続の設定

# 概要

.net Web application からOracle.ManagedDataAccessを使ってOracle Autonomous databaseへ接続の設定メモです。


# 準備
クライアントの資格証明(ウォレット)をダウンロード、任意のフォルダーに解凍します。

例：C:\cwallet

# 設定方法

## 方法１：　
### Step1: web.config のconfigSections　にoracle.manageddataaccess.client設定追加、 
Version=4.122.19.1の部分を実際使っているOracle.ManagedDataAccess.dllのバージョンに合わせます。

```
  <configSections>
    <section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.122.19.1, Culture=neutral, PublicKeyToken=89b483f429c47342" />
    ...
  </configSections>
```

### Step2: oracle.manageddataaccess.clientのTNS_ADMIN、WALLET_LOCATIONを設定。
ウォレットをC:\cwalletに解凍した場合の例：

```
<configuration>
...
<oracle.manageddataaccess.client>
    <version number="*">
      <settings>
        <setting name="TNS_ADMIN" value="C:\cwallet" />
        <setting name="WALLET_LOCATION" value="C:\cwallet" />
      </settings>
    </version>
  </oracle.manageddataaccess.client>
</configuration>
```

### Step3: <connectionStrings>に接続用connectionStringを追加：

例：

```
<connectionStrings>
<add name="atptest" connectionString="Data Source=******;User ID=*****;Password=****;" />
</connectionStrings>
```
Data Source - tnsnames.ora の中で記述したtnsname。


## 方法2：　
### Step1: ウォレット解凍したファイルの中のtnsnames.ora、sqlnet.oraをweb.config と同じフォルダーにコピーする

### Step2: sqlnet.oraの中のDIRECTORY=の部分を環境に合わせて記述

ウォレットをC:\cwalletに解凍した場合の例：
```
WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="C:\cwallet")))
SSL_SERVER_DN_MATCH=yes
```

### Step3: <connectionStrings>に接続用connectionStringを追加　（方法１のStep3と同じ手順）

例：

```
<connectionStrings>
<add name="atptest" connectionString="Data Source=******;User ID=*****;Password=****;" />
</connectionStrings>
```
Data Source - tnsnames.ora の中で記述したtnsname。


# Appendix
request timed outとORA-00542エラー発生の場合、下記の記事を参照してください。
 [IIS web アプリケーションからOracle Autonomous database接続時のrequest timed outとORA-00542エラー対応](https://qiita.com/fish_on_cloud/items/5091939aea7b26f9052d)
【Javaの基本②】パッケージとインポート

## はじめに
オラクル認定資格教科書 Javaプログラマ Silver SE８
第一章　Javaの基本　←　ｲﾏｺｺ！！
第二章　Javaのデータ型の操作
第三章　演算子と判定構造の使用
第四章　配列の作成と使用
第五章　ループ構造の使用
第六章　メソッドとカプセル化の操作
第七章　継承の操作
第八章　例外の処理
第九章　Java APIの主要なクラスの操作

## パッケージの目的
・名前空間を提供し、名前の衝突を避ける
　→パッケージが違えば、同じクラス名が使えるってこと

・アクセス修飾子と組み合わせてアクセス制御機能を提供する
　→publicなクラスはほかのパッケージに属するクラスからも使えるが、
　　publicではないクラスは同じパッケージからしか使えない。

・クラスの分類を可能にする
　→パッケージは、ディレクトリ構造とマッピングされる。

##パッケージ宣言
パッケージ宣言の前には何も記述できない

```java
package sample;

public class クラス名{
  //~~
}
```
## インポート宣言

```java
package sample;

import aaa.*;

public class クラス名{
  //~~
}
```
## staticインポート宣言
通常staticなフィールドやメソッドは「クラス名.フィールド名」、「クラス名.メソッド名」という形でどのクラスかを明示して使用するが、staticインポートをすることで、クラス名を省略できる。

↓　staticメソッドを持つSampleクラス

```java
package test;

public class Sample {
  public static void print() {
    System.out.println("staticインポート");
  }
}
```
↓　staticインポート

```java
package test
import static test.Sample.print;

public class aaa {
  public static void main() {
    print();
　　 }
}
```
※クラス内にimportしたフィールド・メソッドと同名のフィールド・メソッドがある場合、importされたものは無視される。

## リンク集
[【Javaの基本①】クラスの構造](https://qiita.com/vitamin_b12/items/3f920cd223fd3cc1ceae)
[【Javaの基本②】パッケージとインポート](https://qiita.com/vitamin_b12/items/be766c8c3ef2366d9fea)
[【継承の操作②】インターフェース](https://qiita.com/vitamin_b12/items/cdc76298d7f6a494dff2)
[【Javaのデータ型の操作①】プリミティブ型のデータ・参照型](https://qiita.com/vitamin_b12/items/f922ab56e4d8b6580f49)
[【演算子と判定構造の使用①】論理演算子(&&、||)、同一性（==）、同値性(equals)](https://qiita.com/vitamin_b12/items/9feb89e8fb1bc67a8d6d)
[【演算子と判定構造の使用②】分岐処理(if、swich)](https://qiita.com/vitamin_b12/items/523467908e683474eac7)
[【配列の作成と使用】](https://qiita.com/vitamin_b12/items/2fc45588640c479e1f4d)
[【ループ構造の使用】while文、do-while文、for文、拡張for文](https://qiita.com/vitamin_b12/items/23d853dda9baf727e4ac)
[【メソッドとカプセル化の操作①】メソッドの概要](https://qiita.com/vitamin_b12/items/215ad731221c2691c441)
[【メソッドとカプセル化の操作②】オーバーロード、コンストラクタ](https://qiita.com/vitamin_b12/items/e4fd3d51a35bb6a5566c)
[【継承の操作①】クラスの継承](https://qiita.com/vitamin_b12/items/19f8ad6f9801ac8f6a8f)
[【例外の処理】](https://qiita.com/vitamin_b12/items/f7ebf2c1106a7dcbdb41)
[【Java APIの主要なクラスの操作】](https://qiita.com/vitamin_b12/items/dcd3edfe2273e5a09231)
docker上でdjangoの環境を構築

# 目的

docker を用いて Django の環境を構築する。
接続先の DB (PostgreSQL) も docker コンテナを利用する。

# Django の環境を用意

手順としては下記です。

1. Dockerfile, docker-compose.yml を作成
1. イメージを作成
1. イメージから Django のプロジェクトフォルダを抽出
1. migrate

いったんイメージからプロジェクトフォルダの抽出作業を行っている理由としては、プロジェクトフォルダが無い状態で `docker-compose up -d` をするとプロジェクトフォルダ内が空の状態になってしまったためです。

#### 1. Dockerfile, docker-compose.yml 作成

database ディレクトリも作成し、以下のディレクトリ構成とします。

```
.
├── Dockerfile
├── database # 空ディレクトリ
└── docker-compose.yml
```

```file:Dockerfile
FROM python:3

ENV PYTHONUNBUFFERED 1

RUN python -m pip install --upgrade pip \
# PostgreSQL 以外を使用する場合は psycopg2 ではなく、対応するデータベースバインディングに変更
    && pip install Django psycopg2 \
    && pip cache purge \
    && django-admin startproject sample \
# DB の設定を修正
    && sed -i sample/sample/settings.py \
        -e "s/'ENGINE': 'django.db.backends.sqlite3',/'ENGINE': 'django.db.backends.postgresql',/" \
        -e "s/'NAME': BASE_DIR \/ 'db.sqlite3',/'NAME': 'mydb',/" \
        -e "/'NAME': 'mydb',/a<SPACE>'USER': 'user'," \
    && sed -i sample/sample/settings.py \
        -e "/'USER': 'user',/a<SPACE>'PASSWORD': 'pass'," \
    && sed -i sample/sample/settings.py \
        -e "/'PASSWORD': 'pass',/a<SPACE>'HOST': 'postgres',"  \
    && sed -i sample/sample/settings.py \
        -e "s/<SPACE>/        /"
```

```yml:docker-compose.yml
version: "3"
services:
    wait:
        image: dadarek/wait-for-dependencies
        container_name: "wait"
        depends_on:
            - postgres
    postgres:
        image: postgres:10
        container_name: "postgres"
        environment:
            POSTGRES_USER: user
            POSTGRES_PASSWORD: pass
            POSTGRES_DB: mydb
        ports:
            - "15432:5432"
        volumes:
            - ./database:/var/lib/postgresql/data
        networks:
            - db-net
    django:
        build: .
        image: "django"
        container_name: "django"
        working_dir: /sample
        command: python manage.py runserver 0.0.0.0:8000
        volumes:
            - ./sample:/sample
        ports:
            - "8000:8000"
        networks:
            - db-net
        depends_on:
            - postgres
            - wait

volumes:
    database:
        driver: local

networks:
    db-net:
        driver: bridge
```

#### 2. イメージを作成

`docker-compose build` を実行

#### 3. イメージから Django のプロジェクトフォルダを抽出

作成したイメージには `django-admin startproject sample` を実行した直後のプロジェクトフォルダが入っている。
イメージから直接ファイルを取得はできないらしいので、一度コンテナを生成してからホストマシン側に取得する。

```
> CONTAINER_ID=`docker create django`
> docker cp $CONTAINER_ID:/sample/ .
> docker rm $CONTAINER_ID
```

#### 4. migrate

いったんコンテナを起動し、migrate を実施して起動しなおす。

```
> docker-compose up -d
> docker-compose run django python manage.py migrate
> docker-compose restart
```
[localhost:8000](localhost:8000) に接続できれば OK

# おわり

上記設定ができれば sample 配下で開発を実施し、`docker-compose up -d` でサーバを起動・動作確認ができる。
テスト等、各種コマンドの実行は下記のように `docker-compose exec django [実行コマンド]` とすればよい。

```
docker-compose exec django  python manage.py test sample
```
Jupyter Notebook上でCythonを使用して高速化を行う

本記事は
https://qiita.com/pashango2/items/45cb85390193d97523ca
を参考にしています。
#環境
環境は以下の通りです。
windows10
jupyter core     : 4.5.0
jupyter-notebook : 6.0.0
qtconsole        : 4.5.1
ipython          : 7.6.1
ipykernel        : 5.1.1
jupyter client   : 5.3.1
jupyter lab      : 1.0.2
nbconvert        : 5.5.0
ipywidgets       : 7.5.0
nbformat         : 4.4.0
traitlets        : 4.3.2
cython                    0.29.12
Python 3.7.3
適宜ご自身の環境に合わせて下さい。
#手順
1. Visual Studio 2019 バージョン16.3 Communityをダウンロードします。

https://visualstudio.microsoft.com/ja/downloads/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1840215/1ce698d8-f3c6-e450-0118-21be0b1dd8d5.png)
2. インストールします。以下のようにPython開発を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1840215/5cad16d2-4b74-6ee2-5f26-0b58bf640c7f.png) (再起動を促すアイコンが出れば)コンピュータを再起動します。
3. bulid tools ダウンロードしインストールする。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1840215/b07dec9f-fda0-8111-c687-6e0f9d19f8c2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1840215/8b481400-664d-388f-b621-835c82f73fbd.png)
上記c++ builder toolsを使用する。
(再起動を促すアイコンが出れば)コンピュータを再起動します。
4. 実行テスト

```Python:
%load_ext Cython
%%cython
def cyfib(int n):
    a, b = 0.0, 1.0
    for i in range(n):
        a, b = a + b, a
    return a
import time

start = time.time()
cyfib(1000000)
t = time.time() - start
print (f"{t:0} [sec]")
 

def fib(n):
    a, b = 0.0 , 1.0
    for i in range(n):
        a, b = a + b, a
    return

start = time.time()
fib(1000000)
t = time.time() - start
print (f"{t:0} [sec]")
```

実行すると、通常の場合とCythonで高速化された場合の違いが分かると思います。
ModuleNotFoundError: No module named 'apt_pkg'

Google先生に聞いて見つけた解決法がどれもだめだったので、1つのケースとしてメモ的に残しておこうかと。

Ubuntuなどで、デフォルトのPythonとは違うPythonをインストールし、update-alternatives でデフォルトを変更した場合、apt updateを実行すると、標題のような
``` ModuleNotFoundError: No module named 'apt_pkg' ```
が表示されてうまくいかないことがあります。
例えば、Python3.6 が標準のときにpython3.8を入れて切り替えたようなときですね。

検索でよくみつかるのは/usr/lib/python3 の apt_pkg関係の .so をシンボリックリンクで、という解決法ですが、これでうまくいかなかったので、(たぶん相当怪しい)力技で解決しました。
例に挙げたように、システム標準はpython3.6 で、python3.8 を追加インストール、update-alternatives でpython3 がpython3.8 になっているような状況とします。

```
sudo vi /usr/lib/python3/dist-packages/CommandNotFound/db/creator.py
sudo vi /usr/lib/cnf-update-db
```
上記の2つをファイルをお好みのエディタで開き、1行目の
``` /usr/bin/python3 ``` を ```/usr/bin/python3.6```に書き換えて保存する。
私の環境ではこれであっさりapt updateが通るようになりました。

OSはUbuntu 18.04LTSで、別のサーバのほうは素直に20.04LTSに上げたら標準が3.8になったわけですが、この問題が発生した方はちょっとクリティカルな運用があるのでぎりぎりまで引っ張ろうかと粘って思わぬ罠に…
サーバに配置したWebViewのコンテンツからスマホのネイティブアプリのURLスキームの呼び出し方法

筆者は普段サーバサイドのエンジニアとしてWebシステムの開発をしているが、
担当している案件でスマホのネイティブアプリ内のWebView内にコンテンツを組み込む案件がありました。

その際に、URLスキームを使ってネイティブアプリとWebViewのコンテンツ間の連携でハマったので、備忘録として残しておきます。
本記事はあくまでサーバサイドの立場からの対処方法になります。

## URLスキームの書き方
筆者ははじめ、下記のコード用にfetch関数での読み込みを想定していました。
しかしURLスキームはネイティブアプリのWebViewのURLローダーの部分で実行する仕組みのため、
fetch関数のようなJavaScriptの非同期処理では実行が出来ませんでした。
そこで以下のように `location.href` にURLスキームを設定し、
ネイティブアプリのWebViewに読み込ませることで問題を解消しました。

```
// 間違い
fetch("【URLスキーム】");
// 正解
location.href = "【URLスキーム】";
// 参考例
location.href = "appli://test";
```

## 最後に
ちなみに以前、スマホアプリのエンジニアとして案件を担当した際に、上記のようなケースの経験がありました。
今回はサーバサイドの案件の担当者として参画したので、アプリの開発にノータッチの状況は初でした。
久々に対応すると忘れていることも多いので、注意が必要ですね。。。
(Power BI) DAX Studioをはじめてみる #1

　DAXの理解を深めるには、DAX Studioを使いこなすのが必須だと思いますが、DAX Studio - DAX Tools Video Courseのビデオを見終わっても、「さて？」という感じになってしまうので、簡単な始め方を書いてみます。

　探してみると @ishiayaya さんの記事と被ってますが、ご容赦ください。

https://qiita.com/ishiayaya/items/785a8dd6f07f6f285bd5

　こちらも参照して勉強しましょう。

https://qiita.com/PowerBIxyz/items/ddcb3044fdbe4272dbd3

　ともかく、以下のビデオも見ておいてください。

https://www.youtube.com/playlist?list=PLU6II7MW-aiJ3Z-wbUQ0tkqSbAkyiB3uy

# DAX Studioのインストール
　DAX Studioは、sqlbiからダウンロードします。メールアドレスを入力する項目がありますが、必須ではありません。(see https://www.sqlbi.com/tools/dax-studio/ )
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/64c146a4-8a5c-bc08-94d2-70c39435b8a8.png)
　ダウンロードしたファイルを実行して、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/883e1c2d-6d59-bbc1-0d73-2083befc7c7b.png)
　インストールが終了した後にPower BIを立ち上げると、外部ツールの項目の中にDAX Studioのアイコンが表示されます。
![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/2ea84a39-0742-2120-27a6-b39a380edd74.png)

# 起動してみる
　テーブルを読み込んでからDAX Studioを起動すると、以下のような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/d34c76f8-87f6-5f67-d40b-44017e639f31.png)

# データを表示させてみる
　Query Builderを選択すると、真ん中に枠が表示されます。
![img4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/2d2ba232-ec66-04fc-a699-cfbd89e65265.png)

　Columns/Measuresの枠に表示させたい項目を左側から持ってきて、Run Queryを押すと、Resultの枠に結果が表示されます。
![img5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/6f316686-648b-6a6e-5f07-a8ac7a8aa291.png)

# DAX Queryを表示させる
　Query Builderで作成したDAX Queryを表示させるには、Edit Queryを押します。
![img6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/579bd7e3-39ae-6dc0-7410-c28f018e0de5.png)
　EVALUATE文ででーたの表示を行います。並び順はORDER BYで行っています。
　DAX Queryについては、以下を参照してください。

https://docs.microsoft.com/ja-jp/dax/dax-queries

# DAXを編集する
　先ほど使用したSales Amountのメジャーを編集する場合は、左側の項目名を右クリックしてDefine Measure （関連するメジャーも表示させたい場合はDefine Dependent Measure)を選択します。
![img7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/d708d5f1-963b-2715-483c-f45d96f3e973.png)
　この中で、DAXを変更して試してみることができます。実行は、左上のRunで行います。

# DAXを新たに書く
　新しくDAXを書いてみることができます。
　今までのDAX Queryを消すか、左上のOpen a new query window using the current connectionのアイコンを押します。
![img8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/9ca60a0f-c855-b705-5746-3e5d5a5dc15a.png)

　DEFINE MEASUREでメジャーを記述し、EVALUATE SUMMARIZECOLUMNSで表示する項目を並べます。ORDER BYは必須ではありませんが、表示する項目の昇順、降順を指定できます。出力される書式の指定ができないみたいですが、慣れてくるとPower BIの数式バーで記述するよりも書きやすいかもしれません。ただし、**ここで作成、修正したDAX式は、元のPower BIのデータには反映しません**。また、計算列の記述もできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/ae2631d5-40e0-1bae-de27-c725563b0c5d.png)

# DAX式を整形する
　思いつくままDAX式を書いても、最後はきれいなインデントで揃えて、カッコがきちんと対応してるかとか、引数が正しく並んでいるかを確認したいものです。
　Format Queryで、Long Line、Short Lineの整形ができます。個人的にはShort Lineを使ってます。
![img9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/93d3dece-d2b7-2984-a9d1-556fd38f2b19.png)
【2022最新】Androidスマホのシステム音声とマイク音声をパソコンにミラーリングする方法

#Androidスマホのシステム音声とマイク音声をパソコンに出力！
皆さんこんにちは！
この前、LetsViewというミラーリングアプリを例としてアンドロイドデバイスの音声をパソコンにミラーリングする方法を紹介しました。

残念なことにLetsViewはアンドロイドのマイク音声のみをミラーリングできます。従って、Androidの音声をミラーリングする時、システムの音声だけでなく、マイクの音声も同時に流れます。

今回はApowerMirrorを使ってAndroidスマホのシステム音声とマイク音声をパソコンにミラーリングする方法について詳しく説明させていただきます。ご自分のニーズに応じて、システム音声またはマイク音声を自由に選択してミラーリングできます。

##事前準備
[ApowerMirror](https://www.apowersoft.jp/phone-mirror?apptype=qiita210)
Android側は最新のバージョンをインストールする必要があります。
最新バージョン1.7.5.0 [Google Play](https://play.google.com/store/apps/details?id=com.apowersoft.mirror&hl=ja&gl=jp)
![apowermirror-version.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/4ae32812-89f2-41cc-a454-1917a3b661e7.jpeg)


##使う手順
1.アンドロイドのデバイスとパソコンからApowerMirrorを起動します。
2.スマホとパソコンを同じネットワークに接続して、スマホ側からパソコンの名前を選択します。
![apowermiror-device.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/4354ae23-dcbd-ea4a-6909-f3011094ab23.jpeg)

すると、スマホの画面と音声はパソコンにミラーリングします。

**音声をオン・オフにする方法**
Androidの音声をパソコンにミラーリングしたい場合、下記の音声ボタンをオンにしてください。
![apowermirror-audio-on.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/4a767209-4f7b-980e-a3b4-0a30e7c6a5b3.jpeg)

音声ボタンをオフにすると、アンドロイドの音声はミラーリングされません。
![apowermirror-audio-off.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/865ca6ac-2469-a7bf-45a4-841d9a6efed9.jpeg)


##システム音声とマイク音声を切り替える
スマホ側からアプリの設定に入り、音声入力から「システム音声」と「マイク音声」を自由に設定できます。
![apowermirror-audio.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/51bf5eaa-ca89-8c2a-2ceb-bad86bbaf337.jpeg)
PowerAutomateじゃできないSlack botを作りたい

## はじめに

サクッとSlack botを作っていきます。
メール受信をトリガーにメッセージ投稿！とかならPowerAutomateでできてしまうので、そことの差別化のため、今回はSlackの過去メッセージ読み込みと投稿をしていきます。
※PowerAutomateでできるSlack操作は限定されています。[こちらの記事](https://qiita.com/k_ued/items/738193f204cfdb7c7e64#slack%E3%81%A7%E5%8F%AF%E8%83%BD%E3%81%AA%E6%93%8D%E4%BD%9C)を参考にしてください。

## 手順

### 1. SlackAppを作る

https://api.slack.com/apps?new_app=1
↑からSlackAppを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429691/d0d95b3b-f780-c775-e4b4-596e03788fb5.png)

適当な名前とワークスペースを選択してください。

### 2. SlackAppに権限を与える

[OAuth & Permissions]から権限を追加します。
今回必要な権限は
- メッセージの読み込み
- メッセージの投稿
なので、↓のように権限を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429691/da02dda1-f8f8-7da9-5408-23397669add2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429691/4f3fc2c6-fce0-53c8-de1a-b063a69fb8c3.png)
必要な権限は、SlackAPIのリファレンスから確認できます。
https://api.slack.com/methods

### 3. SlackAppのインストール
[Install App]からインストールします。
インストールするとOAuth Access Tokenが発行されます。このTokenはあとで使います。

### 4. APIを叩く

後はAPIを叩けばOKです。
使用可能なAPIはSlackAPIのリファレンスにまとまっています。

#### 例：メッセージ投稿
以下のように指定すると、generalチャンネルに「hello!」というメッセージを送ることができます。

```
URL: https://slack.com/api/chat.postMessage
Method: POST
QueryString: {
  token: xoxp-xxxxxxxxx,
  channel: C0XXXXX,  // チャンネルIDを指定する必要があります。
  text: hello!
}
BodyType: Application/x-www-from-urlencoded
```

#### 例：メッセージ取得
以下のように指定すると、generalチャンネルの過去の1メッセージを取得できます。

```
URL: https://slack.com/api/conversations.history
Method: GET
QueryString: {
  token: xoxp-xxxxxxxxx,
  channel: C0XXXXX,  // チャンネルIDを指定する必要があります。
  limit: 1,
  inclusive: true
}
BodyType: Application/x-www-from-urlencoded
```

### (おまけ)SlackでチャンネルIDを取得する方法

チャンネルを右クリック > [リンクをコピー]して、リンクの貼り付けをすることで、チャンネルIDを確認できます。
`https://testspace-mqv1800.slack.com/archives/XXXXXXXX`のようになっているので、最後の`XXXXXXX`がチャンネルIDです。

## 実際に何か作ってみる

以下の記事で紹介しています。
https://qiita.com/k_ued/items/499b25c0bd56094c7cfd
MAMPでPHPのバージョンを切り替えようとすると落ちる

## 概要
windowsでMAMP使っていて、
PHPのバージョン切り替えようとした際に、MAMPが落ちてしまう現象があったので対処方法を記載します。

## 前提

無料版のMAMPは内部的いくつかPHPのバージョンを持っておりますが、アプリ上では2つまでしか選択できません。
その場合は、以下のファイルパスにある使っていないphpのフォルダ名を一時的に変更すると使えるようになります。
`C:\MAMP\bin\php`

私の場合は、アンダーバーでフォルダ名に入れて以下のような形にしています。（MAMPは最新のPHPから最大2つまで読み込みます）
<img width="200" alt="qiita" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/8a1592b0-d28c-5503-309c-b39e8443c3a5.png">
上記の場合だと、PHP7.4.1と7.2.14がMAMPのアプリ上で切り替えられます。

## 現象

php7.3を使おうとフォルダ名を以下のようにしました。
しかし、MAMPを起動するとサーバーやDBのランプが点灯せず、アプリが落ちるような現象になっていました。

<img width="120" alt="qiita" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/22b65296-3c03-9efd-549b-d34ea2a90716.png">

## 対処法
MAMPのアプリを一度落としてから
confにある`C:\MAMP\conf\apache\httpd.conf`内にある`Additional libraries`部分を修正することで起動するようになります。



実際に`httpd.conf`の60行目あたりを見ますと、
おそらく今利用しているPHPのバージョンが読み込まれて、以下のような感じになっていると思います。

```
# Example:
# LoadModule foo_module modules/mod_foo.so
#
#
# Additional libraries
#
LoadFile "C:/MAMP/bin/php/php7.2.14/libssh2.dll"
LoadFile "C:/MAMP/bin/php/php7.2.14/libcrypto-1_1.dll"
LoadFile "C:/MAMP/bin/php/php7.2.14/libssl-1_1.dll"
LoadFile "C:/MAMP/bin/php/php7.2.14/nghttp2.dll"
# End Additional libraries
#
#
# Additional libraries
#
LoadFile "C:/MAMP/bin/php/php7.4.1/libssh2.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/libcrypto-1_1.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/libssl-1_1.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/nghttp2.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/libsqlite3.dll"
# End Additional libraries
#

LoadModule actions_module modules/mod_actions.so
LoadModule alias_module modules/mod_alias.so
・
・
```

この`Additional libraries`で使わないバージョン部分は消します。

```
# Example:
# LoadModule foo_module modules/mod_foo.so
#
#
# Additional libraries
#
LoadFile "C:/MAMP/bin/php/php7.4.1/libssh2.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/libcrypto-1_1.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/libssl-1_1.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/nghttp2.dll"
LoadFile "C:/MAMP/bin/php/php7.4.1/libsqlite3.dll"
# End Additional libraries
#

LoadModule actions_module modules/mod_actions.so
LoadModule alias_module modules/mod_alias.so
・
・
```

このようにして上書き保存してMAMPを再起動します。
そうすると私の場合は無事起動するようになりました。


どうも無料版は設定ファイルに２種類以上のバージョンのモジュールが読み込まれるとダメみたいです。
redis withscores バグ、動かない

laravel と redis を使っているのだが、
withscoresが動かない。


# 結論

```hoge.php

$request->home_user_id = 44212;
$request->user_id = 44167;

Redis::zadd('ashiato:'.$request->home_user_id, time(),$request->user_id);//どのユーザーのページに、いつ訪問したか、来訪したユーザー
$tmp = Redis::zrange('ashiato:'.$request->home_user_id,0,-1,['withscores' => true]);

```

これで動く。
以下は古いバージョン

```hoge.php

$tmp = Redis::zrange('ashiato:'.$request->home_user_id,0,-1,'withscores');//全員分取得

```
別画面からのリロード処理トリガーを実装したい

#初めに
今回は、単一Activity複数Fragmentでの実装の際に、遷移先の画面でデータの更新があったときに遷移元に更新があったことを伝えたい場面が多くあると思います。
そんなときに一番簡単で一番実装しやすい方法を記事として残しておきます。
###やること
では、実際にどの様なコードを書くのかと言いますと`setFragmentResult`を使います。
`setFragmentResult`とは、`setFragmentResultListener`と対になっており`setFragmentResult`には`requestKey`に鍵として`String`を渡し`result`に値として`Bundle`を入れることができます。
`setFragmentResultListener`では`requestKey`に鍵として`String`を渡し、その鍵に格納された値を取り出すことができます
そのため、コードで書く場合以下の様になります

```kotlin:FirstFragment
setFragmentResultListener(requestKey = REQUEST_KEY) { key, bundle ->
            if (bundle.getBoolean(REQUEST_KEY, false)) {
                // TODO
            }
        }
```

```kotlin:SecondFragment
setFragmentResult(
                requestKey = REQUEST_KEY,
                result = bundleOf(RESULT_KEY to true)
            )
```
こうすることで、別画面での更新状態を取得することができます。

###最後に
あくまで一例として、一番実装しやすい物を今回記事として書かせていただきました
補足等がございましたらぜひコメントを残していってください
Web3Modalなどのウォレットログイン機構

# はじめに

もともとブラウザにログインする形でのdAppsでの通貨の管理について、Web3.jsなどでログイン機構と残高の管理を実装していましたが、Ethereumに加えてMaticやFLOWなど様々なものを管理する必要がでてきたので、いくつか方法を書いておきたいと思います。


# Web3Modal(ETH/MATIC)を利用する


Webからモーダルを開く。ChromeなどにインストールしたMetamaskと連動できるので既存のMetamaskユーザーには新たに何かする必要がないので便利。

![スクリーンショット 2022-02-10 14.28.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/3bdef1c0-1512-6df2-1526-5c0ae091fd71.png)

## install
```
npm install --save web3modal
```

## example

```
import Web3Modal from 'web3modal'

let web3Modal
if (typeof window !== 'undefined') {
  web3Modal = new Web3Modal({
    network: 'mainnet', // optional
    cacheProvider: true,
    providerOptions, // required
  })
}
```

customのwalletリンクも貼れるので便利に使えます。
Walletごとにネットワークを選ぶことも可能

```
  'custom-walletlink': {
    display: {
      logo: '',
      name: '',
      description: 'Connect to demo Wallet',
    },
    options: {
      appName: '',
      networkUrl: `https://mainnet.infura.io/v3/${INFURA_ID}`,
      chainId: 1,
    },
```

## doc
https://github.com/Web3Modal/web3modal

# BLOCTO(FLOW)

FLOWの場合は、BLOCTOを利用する。
必要最低限の実装でモーダルログインを実装できる。


![スクリーンショット 2022-02-10 14.28.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/3a02133a-beec-fa65-7481-853b0cae6e58.png)


![スクリーンショット 2022-02-10 14.28.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/de5b3ef9-9237-a9e1-e433-8a61ed88310a.png)


## instrall

```
npm install @onflow/fcl --save
```

## example

```
  import * as fcl from "@onflow/fcl";

  const [user, setUser] = useState({loggedIn: null,addr:null})
  useEffect(() => fcl.currentUser.subscribe(setUser), [])
```

## doc
https://docs.blocto.app/blocto-sdk/flow


# BLOCTO(ETH/MATIC)


## install

```
npm install @web3-react/core
npm install @blocto/blocto-connector
```

## example

```
import { useWeb3React } from '@web3-react/core'
import { BloctoConnector } from '@blocto/blocto-connector'

export const Wallet = () => {
  const { chainId, account, activate, active } = useWeb3React<Web3Provider>()

  const onClick = () => {
    activate(connector)
  }

  return (
    <div>
      {active ? (
        <button type="button" onClick={onClick}>
          Connect
        </button>
      )}
    </div>
  )
}

```

## doc
https://docs.blocto.app/blocto-sdk/evm-sdk

## BLOCT　CLIENT側

EthereumなどFlow以外のトークンは、BloctoWallet側であらかじめ追加しておく必要があるが、

![スクリーンショット 2022-02-10 11.23.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/81d42b7d-a17d-103a-8834-25b16cb20bc8.png)

Ethereumの場合は、BloctoWalletの連動にはコントラクトの制御がひつようなようでGasPriceがかかるようで、かなりお高め。

![Image from iOS (34).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/97c22241-82e9-7c69-a502-81aa72ad348b.png)
Swiperでカルーセルを実装して矢印連打するとSafariで範囲選択される事象

# 発生したこと

Swiperを用いて以下のようなカルーセルを実装しました。

<p class="codepen" data-height="389" data-theme-id="dark" data-default-tab="result" data-slug-hash="VwrpxWY" data-preview="true" data-user="heeroo-ymsw" style="height: 389px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/heeroo-ymsw/pen/VwrpxWY">
  SwiperTest</a> by heeroo-ymsw (<a href="https://codepen.io/heeroo-ymsw">@heeroo-ymsw</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

公式のDemoの[Slides per view](https://swiperjs.com/demos#slides-per-view)に、矢印を足して、ページネーションを除いたものになります。

これをSafariで開き、右矢印をクリックしスライドアニメーション中にもう一度右矢印をクリックする（ダブルクリックする）と以下のようにSwiperのコンテナが範囲選択状態になることが分かると思います。

発動条件が一応あり、下に要素が続く場合のみ発生するようです。

![スクリーンショット 2022-02-10 13.47.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924363/af532c39-7f93-898a-b02b-4fcdb26be7a4.png)


## この事象が発生した環境

- Safari 14.1.1 (16611.2.7.1.4)
- Swiper v8.0.3

# 対策

範囲選択されなければいいので、CSSで範囲選択されるコンテナに対して**`user-select`を`none`に設定**します。
ただし、Safariで`user-select`を有効にするには、ベンダープレフィックスを付与する必要があります。
その他IEや古いバージョンのFirefoxなどベンダープレフィックスが必要ですので、以下のように記載します。

```css
.swiper {
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
```

また、`.swiper`内にテキストなどの範囲選択できるようにしたい部分があれば、その部分に対して`user-select`の設定を上書きすればその範囲のみ選択できるように設定できます。

:::note warn
allはIE非対応、Safariは挙動が異なるため、textと明示します。
:::

```css
.swiper-slide-text {
  -moz-user-select: text;
  -webkit-user-select: text;
  -ms-user-select: text;
  user-select: text;
}
```

## `user-select`について

ユーザがテキストを範囲選択できるかどうかを制御します。

### `none`
対象の要素とその子孫要素のテキストは範囲選択できなくなります。

### `text`

テキストを選択できます。

### `contain`

要素の内部で選択を始めることができます。

### `auto`

下記のように決められます。

- 擬似要素`::before`と`::after`では、値は`none`
- 編集可能な要素の場合、値は`contain`
- 上記以外で、親要素の`user-select`の値が`all`の場合、対象要素の使用値も`all`
- 上記以外で、親要素の`user-select`の値が`none`の場合、対象要素の使用値も`none`
- 上記以外の場合、使用値は`text`

### `all`

1回クリックすると範囲選択されるようになります。
選択範囲が要素の一部を含んだ場合、選択範囲はすべての子孫要素を含む要素全体が含まれます。
子孫要素でダブルクリックや右クリックを行うと、この値が設定されている要素の先祖要素の最上位要素が範囲選択されます。

https://developer.mozilla.org/ja/docs/Web/CSS/user-select
Gatsby.jsでsitemapを作成しGoogle Search Consoleに提出する

##方法
①プラグインgatsby-plugin-sitemapを使用し、サイトマップを作成する。
②{サイト名}.com/sitemap/sitemap-0.xmlにアクセスし、作成されていることを確認する。
③Google Search Consoleへ{サイト名}.com/sitemap/sitemap-0.xmlを提出する。

##環境
Gatsby.jsバージョン4.6.0

##①サイトマップの作成
プラグインのインストール

```
npm install gatsby-plugin-sitemap
```

gatsby-config.jsへの追加

```gatsby-config.js
plugins: [
        {
            resolve: `gatsby-plugin-sitemap`,
            options: {
                excludes: [`/除外するページ/`,]
            }
        },
],
```

注意点として、Gatsby2以前は「exclude」だったoptionsの記述が現在「excludes」と記述するよう変更になっている。
※横着してググった記事を見て以前の記述の方法が載っているためうまくいかずにハマりました。公式のドキュメントを読むべきという自戒の意味を込めて書いておきます。


何かがおかしいことに気づかせて頂いた記事
>https://qiita.com/ebifry_w_t/items/84fb29790c8357ca2819

公式のドキュメント
>https://www.gatsbyjs.com/plugins/gatsby-plugin-sitemap/

##②サイトマップの作成と確認

ビルドしてローカル環境のpublic/sitemap/sitemap-0.xmlが作成されていることを確認する。

```
gatsby build
```
ローカル環境から確認するためサーバーを立ち上げる

```
gatsby serve　もしくは　gatsby develop
```

{サイト名}.com/sitemap/sitemap-0.xmlにアクセス。
作成されていることと除外するページの指定などがうまくいっているかを確認する。

##③提出

[Google Search Console](https://search.google.com/search-console/about)のサイトマップ欄から②で確認したサイトマップのURLを貼り付けて提出。
例：　{サイト名}.com/sitemap/sitemap-0.xml

ステータスの更新に若干時間がかかった覚えがあります。
古いNpgsql.dllで新しいPostgreSQLに接続したいときのエラーと対策

# はじめに
本当は新しいNpgsql.dllを使ったほうが良いことは分かってるんだけど、上司やコストという大いなる意思のためどうしても古いやつで接続しなきゃいけない…という時のメモです。
セキュリティ的にあまり良くない対策なので実行する際は注意です。
また、記事の内容に間違いや勘違いがあった場合はご指摘いただけると助かります。

# エラーが出ていた状況
- PostgreSQL 9.1.9で動いていたシステムを最新のPostgreSQL（現時点で14.1）に変更しないといけない
- DBは14.1に変更済
- ソースコードやdllは変更できない

単純に当時のdllを使ってアクセスすると以下のエラーが出てしまいます。

```
Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now. Received: 10
```

AuthenticationClearTextPasswordかAuthenticationMD5Passwordじゃないと受け付けませんよという内容がPostgreSQL 14.1から出ているわけです。
なのでこれを他のも行けるように変更します。

# 対策：confファイルの書き換え
> pg_hba.conf

PostgreSQLをインストールした際、データディレクトリとして指定したフォルダにこういう名前のファイルが作られます。これを任意のテキストエディタで開いてください。
>METHOD

この列があると思います。
これの設定が「md5」とかそういう値になっているかと思います。これを全部「trust」に書き換えてください。
これはサーバに接続してくる人全員を信じて許可するという心の広い認証です。なのでこれで接続ができるようになります。
参考→[PostgreSQL 認証方式](https://www.postgresql.jp/document/13/html/auth-methods.html)

# おわりに
新しいやつを使ったほうが良いどころか使うべきなのは分かってはいるんですけど、どうしてもやらなきゃいけない時というのがあるということでご勘弁ください。
FontAwesome6(Pro)をimportmapなRails7に組み込む

FontAwesome6がリリースされました。これをRails7 with importmap に組み込もうとしたところ、いくつかの知識が必要だったので共有します。それぞれを知っていれば特に難しい話ではないのですが、どなたかの役に立てばと思います。

Rails7ではwebpackerがなくなり、importmapで管理する必要があります。

webpackerにFontawesome Proを組み込むには、.npmrcに認証情報を書くなどして対応をする必要がありましたが、importmapではこのやり方が使えません。

ちょっとググっても方法が見つからなかったのですが、下記のようにすれば使えました。

# FontAwesome Pro Kit URLの取得

FontAwesomeのサイトに行き、Kitと呼ばれるツールを使い、FontAwesomeをサーブするURLを作る。 
https://fontawesome.com/docs/web/setup/use-kit 
FontAwesome 5以降はCDNではなく、このKitを使ってサーブするのを推奨しているようです。

# config/importmap.rb に設定を追加

```ruby
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
# この1行を足す。
pin "fontawesome", to: "https://kit.fontawesome.com/YOUR-KIT-PATH.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
```
`https://kit.fontawesome.com/YOUR-KIT-PATH.js` のところは実際のKit URLで置き換えてください。
何となく pin_all_from の前に書いた方がいいのかなと思ってそうしています。

# app/javascript/application.js に設定を追加

```javascript
import "@hotwired/turbo-rails"
import "controllers"
import "fontawesome" // この1行を追加
```

importで使う名前は、config/importmap.rb の pin に書いた名前と同じであれば、 fontawesome でなくても問題ありません。


# 使ってみる。

```html
<p>
  Hello, FontAwesome 6! <i class="fas fa-thumbs-up"></i>
</p>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1034/4c1bd112-d8af-e685-cae7-167938c89952.png)
Setup Karate API testing in windows

# Outline

Karate はAPIのテストを行うためのフレームワークである。
APIのscenario testを組む時便利なツールである。




# Java
JDKをインストールする
https://www.oracle.com/java/technologies/downloads/#jdk17-windows
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/c5d5914a-07db-0045-5356-92833f2ab6c1.png)

# Maven
Apache Mavenをインストールする
https://maven.apache.org/download.cgi

zipをダウンロードして、適当なフォルダに解凍する
今回は、<B>C:\</B>に配置する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/175ea496-4adf-99d7-8d6f-b6b4d8db2a3f.png)

command lineで実行できるように、PATHに今回追加したapache-mavenのbinのパスを追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/b425887f-e8f0-800d-ca09-1361fc33ce97.png)

Pathが通っているかを、command promptを起動し、mvnコマンドを実行する

```
mvn -v
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/9f84d72e-3024-22b2-410b-83b0a58848bc.png)


# Create Karate Project

```
mvn archetype:generate  -DarchetypeGroupId=com.intuit.karate  -DarchetypeArtifactId=karate-archetype  -DarchetypeVersion=1.1.0  -DgroupId=com.example  -DartifactId=example-karate
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/854fa7c7-62b1-bf07-fb4d-8211adeedd5a.png)



※archetypeVersionは、ここから確認する　https://mvnrepository.com/artifact/com.intuit.karate/karate-archetype




# run Karate

exmapleでusers.featureがある。
これをまずは実行してみる。（DEMO用のAPIが使える）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/3389c198-3ffb-89a3-e126-e418a254343e.png)

```
mvn clean test
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/ca64e75a-1328-e470-8a8a-980b7ab25806.png)
【JavaScript】西暦の年だけを用いて和暦の年を表示する方法

こうする

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="YzEVqBY" data-user="qwe001" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/qwe001/pen/YzEVqBY">
  Untitled</a> by qwe001 (<a href="https://codepen.io/qwe001">@qwe001</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```javascript
function convertYearToJapaneseEra(year)
{
  var m = new Date(year, 0, 1); // e.g. "2022-01-01"
  var dt = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {era: 'short'});
  var [{ value: era }, { value: year }] = dt.formatToParts(m); // e.g. {type: 'era', value: '令和'},{type: 'year', value: '4'},{type: 'literal', value: '年'}
  var str = era + year;
  return str; // e.g. "令和4"
}
```

普通に西暦から「2018」を引けば令和年は算出できますが、私の場合は平成年のデータも入るので将来的なメンテナンス性を考えて`Intl.DateTimeFormat`を使ってみることにしました

令和元年(2019年)は平成31年として表示されます。
令和元年を令和元年として表示したいなら、`new Date(year, 0, 1);`を`new Date(year, 4, 1);`にしたらええんちゃう。知らんけど

### 追記

「令和4年」みたいなオーソドックスな取得をする場合は、以下の方法でも可能です(@lhankor_mhy様 コメントありがとうございます。)

```javascript
function convertYearToJapaneseEra(year)
{
  var m = new Date(year, 0, 1); // e.g. "2022-01-01"
  var dt = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {era: 'short', year: 'numeric'});  
  var str = dt.format(m);
  return str; // e.g. "令和4年"
}
```

eraの値を`narrow`にすれば、「R4」みたいな感じでアルファベット表記で取得できます。ただし、明治以前の年(1868年 慶応など)は、アルファベット表記に対応しておらず、「慶応」のまま表示されます。

```javascript
function convertYearToJapaneseEra(year)
{
  var m = new Date(year, 0, 1); // e.g. "2022-01-01"
  var dt = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {era: 'narrow'});
  var [{ value: era }, { value: year }] = dt.formatToParts(m); // e.g. {type: 'era', value: 'R'},{type: 'year', value: '4'},{type: 'literal', value: '年'}
  var str = era + year;
  return str; // e.g. "R4"
}
```

eraの値が`long`の場合、スマホのMobile Chromeなどで見た時に正しく和暦が表示されないようです(2022.02時点)

```javascript
  var dt = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {era: 'long'});
```

<img width="320" alt="Screenshot_2022-02-10-19-40-22-94_a87fd7db6caa850b517aa6fa9d2fcd0e.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130352/cdc11f72-7586-ffff-2aa1-6f488ee21280.jpeg">

```javascript
  var dt = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {era: 'short'});
```

<img width="320" alt="Screenshot_2022-02-10-19-40-51-71_a87fd7db6caa850b517aa6fa9d2fcd0e.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130352/b045587e-cfbf-363e-c2fa-76efcf248483.jpeg">