OmniAICreator/Qiita-1.07M huggingface dataset:
【Flutter/Dart】Youtube再生のライブラリを調査してみた

Youtube動画をFlutterアプリ内で表示させたいケースがあり、ライブラリから調査したので、簡単にまとめたいと思います！

## 結論

今回は、[youtube_player_iframe](https://pub.dev/packages/youtube_player_iframe)を採用しました。
このライブラリであれば、動画再生に関する基本的な機能は提供してくれていると思います。

## 前提として
今回のケースでは以下の仕様を満たす必要がありました。

- Youtube上にアップロードされている動画が表示される
- 動画はWidgetに埋め込む形で表示できる(さらにいうとモーダル上に表示できる)
- 動画再生、一時停止、音声オンオフの切り替え、全画面表示、Youtubeへの遷移、を行うことができる

## 候補ライブラリたち

大きく分けて、
- ローカルファイル含め動画再生できるライブラリ
- Youtube再生に特化したライブラリ
の2つの方向性から調査し、いくつかのライブラリが候補にあがりました。


## 候補1:[video_player](https://pub.dev/packages/video_player)
ローカルファイル含め動画再生できるライブラリ。
Flutter 公式が出しており、パッケージ内ではスター数から、動画再生系では一番メジャーなライブラリなのではないかと考え、
このライブラリを使用することを最初に検討しました。

## 候補2:[chewie](https://pub.dev/packages/chewie) 
ローカルファイル含め動画再生できるライブラリ。
video_player よりよしなにUIを実装してくれそうだが、その分カスタマイズ性は低めに感じました。
調査時点で、ライブラリの最終更新が8ヶ月前なので将来的にサポートされるか不安がありました。

## 候補3:[better_player](https://pub.dev/packages/better_player)
ローカルファイル含め動画再生できるライブラリ。
video_player とchewie をもとに作られている？よう。
バージョンアップデートも活発な印象を受けました。スター数を比較した場合、それほど多くない。

## 候補4:[youtube_player_flutter](https://pub.dev/packages/youtube_player_flutter)
Youtube再生に特化したライブラリで、特化系のなかではスター数が一番多い。

## 候補5:[youtube_player_iframe](https://pub.dev/packages/youtube_player_iframe)

Youtube再生に特化したライブラリ。
youtube_player_flutterとの違いとしては以下記載されていた。
```
Note: This package only provides default youtube web player's skin. If you need Youtube Android player like player with gesture support, use youtube_player_flutter instead. youtube_player_flutter also uses this package as dependency. (Migration Pending)
```

## video_player の使用を試みる!

スター数も一番多く、デファクトスタンダード感があったのでまずはこのライブラリを使用できないか調査しましたが、
Youtube上の動画表示は正式にサポートしていないようでした・・
mp4など、動画の拡張子であればインターネット上の動画は表示できるみたいです。
別途APIを組み合わせればYoutube表示は可能だったのですが、ライブラリのみで手軽に表示できる手段がないか、
調査を継続することにしました。

※今回のケースではYoutube上の動画を表示するという目的があったため、こちらのライブラリは使用しないようにしたのですが、
動画ファイルの再生、ということであればこのライブラリで実現できると考えます。

参考: 
https://stackoverflow.com/questions/65038430/youtube-video-in-video-player-package

## youtube_player_flutterの使用を試みる!

次に調査したのは、Youtube表示に特化したライブラリでスターが多かった、youtube_player_flutterです。
こちらを使用してYoutubeの表示は成功したのですが、調査時点でiOSで動画のフルスクリーン表示ができない仕様でした....

参考: 
https://stackoverflow.com/questions/70750656/video-is-not-showing-in-fullscreen-in-ios-device-in-youtube-player-flutter-packa

最終的に上述したyoutube_player_iframe を採用することで動画表示を行うようにしました。

## 最後に

ライブラリを使用することでシンプルに動画再生機能を実装できたので、今後も色々と使っていきたいと思います！
Flutterで現在時刻を含むテストを安定して実行させるためにClockを使う

# 概要
現在開発中のプロダクトにはVisual Regression Testを入れているのですが、現在時刻が表示されるようなコンポーネントだとテストに失敗してしまいます。

自分でダミーの値を渡すようにしてもいいのですが、ユースケースによっては改修が手間な部分も出てきうるのでdart-langに含まれている[Clock](https://github.com/dart-lang/clock)を調べました。

下記がClockの説明です。
> This package provides a Clock class which encapsulates the notion of the "current time" and provides easy access to points relative to the current time. Different Clocks can have a different notion of the current time, and the default top-level clock's notion can be swapped out to reliably test timing-dependent code.

# 使い方

例として生年月日を選択するコンポーネントがあり、デフォルト値は現在時刻という仕様の場合をイメージしてください。

これをCIなどで実行すると、ダミーデータを時刻に表示できるようにしておかないとテストが実行される度にこけてしまいます。

テストコードの例
※Visual Regression Testには[Golden Toolkit](https://github.com/eBay/flutter_glove_box/tree/master/packages/golden_toolkit)を利用しています。
※サンプルがVisual Regression Testである必要はありませんが、コードをリライトするのが手間だったのでご容赦ください。

```
  testGoldens('Visual Regression Test', (tester) async {

    const targetWidget = xxx;

    final builder = DeviceBuilder()
      ..overrideDevicesForAllScenarios(devices: [
        Device.phone,
      ])
      ..addScenario(
        widget: targetWidget,
        name: 'default',
      );
      
    await tester.pumpDeviceBuilder(builder);
    await screenMatchesGolden(tester, 'xxx_widget_test_default');
  });
```

次にClockを利用したテストコードを記載します。

Clockを利用してテスト書くには、まず既存の `DateTime.now()` などの実装部分を `clock.now()` にリプレイスします。
そして、下記のように`withClock`のcallback内にテストしたい対象の処理を移動します。

以上の処理を加えることで、現在時刻を `Clock` で指定したものに固定することができます。　

```
  testGoldens('Visual Regression Test', (tester) async {

    const targetWidget = xxx;

    final builder = DeviceBuilder()
      ..overrideDevicesForAllScenarios(devices: [
        Device.phone,
      ])
      ..addScenario(
        widget: targetWidget,
        name: 'default',
      );

    withClock(
      Clock.fixed(DateTime(2000)),
      () async {
        await tester.pumpDeviceBuilder(builder);
      },
    );

    await screenMatchesGolden(tester, 'xxx_widget_test_default');
  });
```

![スクリーンショット 2022-05-04 19.05.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57963/a4a39980-3c8d-561f-87c8-63ef1e2d5412.png)

以上のような感じでClockを利用することにより、テストの現在時刻を固定することができました。

# 補足
コードも楽に終える規模なので、具体の実装が気になる方はコードも確認しておくと良いかもしれません。
https://github.com/dart-lang/clock/tree/master/lib/src
スプレッドシートに紐付くスクリプトが実行できない原因について


とあるアカウント(Aアカウント)でスプレッドシートを開いてGAS(Google App Script)で書いたマクロを実行したいのだができなくてずっっと悩んでいました。
なぜ他のアカウントで実行できてAアカウントでできないのか、とても不思議かつ謎でした。

### ~通常アカウントの場合~
普通にログインした場合は下記の図のようにスプレッドシートのhogehogeにあくせすすると、右上にgoogleアカウントでログインした時のアイコンが出ます。
![スクリーンショット 2022-05-04 19.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/55b666d4-4582-e114-3933-b2cd59bc68da.png)
加えて、自分で作成していたマクロがメニューに追加されていて「課題」が表示されます。


### ~Aアカウントの場合~
ただ、Aアカウントでログインした時にはhogehogeを開いても下記の図のようにログインしていない状態となるのです。
![スクリーンショット 2022-05-04 19.29.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/b579c070-ce3b-076c-320a-0d7ad755447b.png)

ここからログインしたとしても下記の図のようにアクセス権がないですよ、と言われてしまいます。
![スクリーンショット 2022-05-04 19.44.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/4c4c0f8e-4293-5af3-bab9-5b0a1b7e04da.png)

なぜなのでしょうか？？

結論、これは
Aアカウントの初期設定の問題と推察されます。

Aアカウントにはgoogleドライブの割り当てはなく、使用できない設定になっています。おそらくそれが原因かと思います。
他の特定の機能は使用できるのですが、スプレッドシートやフォームは作成できません。おそらく自身のアカウントで作成できないため、他者が作成したスプレッドシートは閲覧のみになっています。閲覧のみのため、ログインしないと使用できないマクロも使えないのかと考えました。
みんなもそんな時に出会した時はお気をつけて！
AWS IAMについて

# AWS IAMについて学んだ事

AWSのIAMを改めて勉強していたらよくわかっていなかったことがたくさん出てきたので復習も兼ねて学んだ事のアウトプットする。
間違いなどのご指摘は大歓迎です。

# 私のスペック
大学卒からアパレル関係の営業を6年経験後現在のSESに転職して1年ほど。
気づいたらAWSの勉強をしており、資格11冠目指したいとも思ってます。
その前にAWSエンジニアとして仕事をしたい為、更なる知識の深める際にIAMに詰まった。
SAAは合格済み

# なぜ書こうと思ったか
アウトプットするまでが勉強だと思い記事を書く事にした。
また、IAMに苦手意識もあり、AWSに知見がある方がIAMが詳しい人はAWSの知識も豊富とのことを聞き納得した自分がいたため。

# そもそもIAMとは
正式な名前はAWS Identity and Access Management
・AWSリソースをセキュアに操作するために、認証・認可の仕組みを提供する
マネージドサービス
・「誰が」「どのような条件で」「どんなアクセスができるか」を細かく制御可能
・IAMポリシーで、最小権限の付与が可能
・料金は無料
・ルートユーザー・　IAMユーザー・グループ・ポリシー・ロールとある
# ルートユーザーについて
最初にAWSアカウントを作成したときにメールアドレス・パスワードでログインできる
・全てのAWSサービス・リソースに対して完全なアクセス権を持つユーザー
・全ての権限を持つので悪用されると大変なのでアクセスキーを削除し極力使用しない
ただ、サポートプランの変更などルートユーザーでの認証が必要なタスクが存在する

# IAMユーザーについて
AWSで作成するエンティティ(ユーザー・アプリケーション)
・AWSのリソースなどを使用酢rためのユーザー
・名前と認証情報(パスワード・アクセスキー)で構築される
・ルートユーザーではなくIAMユーザーを利用する

# IAMポリシーについて
IAMアイデンティティやAWSリソースに関連づける事によってアクセス許可を定義することができる
・JSON形式でのアクセス条件を記述
・アイデンティティベースは管理ポリシー（AWS管理ポリシー・カスタマー管理ポリシー）とインラインポリシー
・リソースベースはIAMロールの信頼ポリシー、S3のバケットポリシー、SNSトピックのアクセス許可、SQSキューのアクセス許可
・パーミッションバウンダリー（IAMアクセス許可の境界、SCP)
・アクセスコントロールポリシー(ACL)

# まとめ
IAMはとても奥が深い、特にポリシー・ロール。
今後はポリシー・ロールの勉強をしてポリシー・ロールのみの記事を書く予定
WSLでFedoraを起動する

WSLにFedoraを入れてみた。
Windows上でシェルスクリプトやlinux系コマンドを使うときに便利である。

Ubuntuは以前に使用したことがあったが、RedHat系とパッケージマネージャーやパスが違い使いずらいのでなるべくFedoraに統一したいところ。

## インストール

インストーラ(Fedora-Remix-for-WSL-SL_35.12.3.0_x64_arm64.msixbundle)は以下からダウンロードできる。

https://github.com/WhitewaterFoundry/Fedora-Remix-for-WSL/releases

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372771/be067ab7-d090-8b13-5abe-a208542f3383.png)


`.msixbundle`という拡張子はMSI形式のインストーラーをまとめたものなので、普通にダブルクリックでインストールできる。
※以前は`wsl --import`が必要だったようだがインストーラー形式になったらしい。

インストールしたら即起動、といきたいところだが、その前に少々設定が必要になる。

WSLというのは仮想マシンホストのようなもので（厳密には違うが）ディストリビューション（仮想マシンのインスタンスのようなもの）を複数管理・起動できる。
インストール済みのディストリビューションは``wsl -l -v``コマンドで確認できる。


```
c:\>wsl -l -v
  NAME                   STATE           VERSION
* docker-desktop         Stopped         2
  docker-desktop-data    Stopped         2
  fedoraremix            Stopped         1
```

`fedoraremix`というのが追加したfedoraのディストリビューションである。

Docker for Windowsをインストールした環境で確認してみると、…見覚えのない`docker-desktop`というディストリビューションが追加されてたりする。
この環境だとデフォルトではfedoraでなくdocker-desktopのほうが起動してしまう(><

## 設定

インストールした直後はWSL1を使用する設定になっており使用できない機能があるので、WSL2に切り替える。

```
wsl --set-version fedoraremix 2
```

また、fedoraがデフォルトになってない場合は、以下のコマンドでデフォルトに切り替える。
※エクスプローラーでShift+右クリックを押し『Linuxシェルをここに開く』で起動するのもデフォルトのディストリビューションになる。

```
wsl --set-default fedoraremix
```

## 確認

設定を変更した後に再度確認すると以下のようになる。
```
c:\>wsl -l -v
  NAME                   STATE           VERSION
* fedoraremix            Stopped         2
  docker-desktop-data    Stopped         2
  docker-desktop         Stopped         2
```

あとは``wsl``コマンドを実行すればデフォルトのディストリビューションが起動する。
ちゃんと``rpm``も使える。

```
c:\>wsl
[root@PC c]# rpm
RPM version 4.17.0
Copyright (C) 1998-2002 - Red Hat, Inc.
```

起動時に`wsl -d <ディストリビューション名>`でディストリビューションを指定して起動することもできる。
```
c:\>wsl -d docker-desktop
PC:/mnt/host/c# rpm
-sh: rpm: not found
```

----
WSL の基本的なコマンド
https://docs.microsoft.com/ja-jp/windows/wsl/basic-commands
Splunk内部ログを用いたスケジュールサーチ実行状況確認

## はじめに
Splunk利用方法の一つとして、スケジュールサーチ(アラート)機能を利用して定期的にログを確認し、条件に合致した場合はアクション実行…といった使い方があります。
このスケジュールサーチですが、同時実行サーチ数の上限に到達する等の様々な要因により、サーチ実行に失敗したり、スキップされる場合があります。
スケジュールサーチの実行状況はMonitoring Console上で確認出来ますが、Splunk内部ログに対して任意のサーチを実行することでも確認することが出来ます。

## 注意事項
Splunk内部ログにおける詳細な出力条件や各フィールドの情報等に関する仕様等は、Splunk Documentation上では公開されておりません。
あくまで、筆者の経験値的なナレッジとしてのご紹介となります。

## 構成
* Splunk Enterpriseバージョン
  * v8.2.2
* Splunk構成
  * Standalone構成
  * 分散構成(Distributed Environment)
  * Search Head Cluster構成

## Splunk内部ログを用いたスケジュールサーチ実行状況確認サーチ文
各サーチは、Splunk内部ログをサーチ可能なSplunkコンポーネント上にて実施します。
### 各スケジュールサーチにおけるスキップ発生確認
```
index=_internal sourcetype=scheduler app=(確認対象のスケジュールサーチ/アラートを設定したApp) status=skipped
| eval scheduled_time = strftime(scheduled_time,"%Y/%m/%d %H:%M:%S")
| table _time savedsearch_name scheduled_time status reason
```
上記サーチにより、実行がスキップされたスケジュールサーチ/アラートの名称(savedsearch_name)、実行予定時刻(scheduled_time)、実行ステータス(status)、スキップ理由(reason)を結果として得ることが出来ます。

### 各スケジュールサーチにおける失敗発生確認
```
index=_internal sourcetype=scheduler app=(確認対象のスケジュールサーチ/アラートを設定したApp) success=0
| eval scheduled_time = strftime(scheduled_time,"%Y/%m/%d %H:%M:%S")
| table _time savedsearch_name scheduled_time errmsg
```
上記サーチにより、実行が失敗したスケジュールサーチ/アラートの名称(savedsearch_name)、実行予定時刻(scheduled_time)、エラーメッセージ(errmsg)を結果として得ることが出来ます。

### 各スケジュールサーチ実行時における発生待ち時間確認
```
index=_internal sourcetype=scheduler app=(スケジュールサーチ/アラートを設定したApp) status=success
| eval wait_time=dispatch_time-scheduled_time
| search wait_time>=60
| eval scheduled_time = strftime(scheduled_time,"%Y-%m-%d %H:%M:%S")
| eval dispatch_time = strftime(dispatch_time,"%Y-%m-%d %H:%M:%S")
| table _time savedsearch_name scheduled_time dispatch_time wait_time
```
上記サーチにより、60秒以上の待ち時間が発生したスケジュールサーチ/アラートの名称(savedsearch_name)、実行予定時刻(scheduled_time)、実際に実行された時刻(dispatch_time)、発生した待ち時間(wait_time)を結果として得ることが出来ます。待ち時間の検索条件を変更したい場合は、3行目の条件式を変更します。

### 同時実行サーチ数上限到達事象の発生確認
```
index=_internal (sourcetype=splunkd OR sourcetype=scheduler) "The maximum number of concurrent"
```
上記サーチを実行して1件以上の結果が得られた場合、同時実行サーチ数の上限に抵触した状況が発生していたことになります。

### 各スケジュールサーチ実行におけるサーチ所要時間
```
index=_audit source=audittrail savedsearch_name=(調査対象のスケジュールサーチ名)
| stats values(user) as user max(total_run_time) as total_run_time by savedsearch_name exec_time
| eval exec_time = strftime(exec_time,"%Y/%m/%d %H:%M:%S")
| sort - total_run_time
```
上記サーチにより、スキップされたスケジュールサーチ/アラートの名称(savedsearch_name)、実行された時刻(exec_time)、サーチ所要時間(total_run_time)を、所要時間が長い順に結果として得ることが出来ます。

## 参考
* [What Splunk software logs about itself - Splunk Documentation](https://docs.splunk.com/Documentation/Splunk/8.2.2/Troubleshooting/WhatSplunklogsaboutitself)
【GAS】スプレッドシートをcsvに変換してS3にアップロードするサンプルコード


S3ライブラリの追加
-

https://qiita.com/GoeMon564/items/851b76a5c78b22a64fe2


プロパティストアに、以下を追加
-

- awsAccessKeyId
- awsSecretKey
- SpreadsheetId

メイン関数の実装
-
```javascript
// ssToS3.gs

function ssToS3() {
  var awsAccessKeyId = PropertiesService.getScriptProperties().getProperty("awsAccessKeyId");
  var awsSecretKey = PropertiesService.getScriptProperties().getProperty("awsSecretKey");

  // スプレッドシートを取得
  var SpreadsheetId = PropertiesService.getScriptProperties().getProperty("SpreadsheetId");
  var ss = SpreadsheetApp.openById(SpreadsheetId);
  // シートのオブジェクトを取得
  var sheet = ss.getSheetByName(Setting.targetSheetName);
  const lastRow = sheet.getLastRow();
  // データを取得
  var data = sheet.getRange(Setting.tableRange).getValues();

  // 送信データ用の配列
  var csvString = '';
  for ( var i = 1; i < lastRow; i++ ) {
    if (data[i][Setting.amazonUrl] != '') {
      csvString += '"' 
                    + data[i][Setting.foo] + '","'
                    + data[i][Setting.bar] + '","'
                    + data[i][Setting.baz] + '","'
                    + data[i][Setting.hoge] + '","'
                    + data[i][Setting.piyo] + '","'
                    + "\n";
    }
  }

  csv = Utilities.newBlob(csvString, "text/csv", "UTF-8");
  
  var s3 = S3.getInstance(awsAccessKeyId, awsSecretKey);
  s3.putObject( 'バケット名', 'ファイルパス', csv, {logRequests:true} );
}
```


定数管理のために設定クラスを用意
-

```javascript
// setting.gs

class Setting {}

// 対象シート名
Setting.targetSheetName = 'シート1'

// テーブルの範囲
Setting.tableRange = 'A:E'

// 列設定(0オリジン)
Setting.foo   = 0
Setting.bar   = 1
Setting.baz   = 2
Setting.hoge  = 3
Setting.piyo  = 4
```

ついでにメニューから実行できるようにしよう
-
```javascript
// onOpen.gs

function onOpen() { 
 var ui = SpreadsheetApp.getUi(); 
 var menu = ui.createMenu("スクリプト"); //メニュー名 
 menu.addItem('ssToS3','ssToS3'); //表示名、スクリプト名 
 menu.addToUi(); 
}
```
Xcode13でUser-Difined Settingを使用して、debugとreleaseで値を切り替える

# 目次
- [はじめに](#はじめに)
- [環境](#環境)
- [実装方法](#実装方法)
- [さいごに](#さいごに)

# はじめに
個人開発したiOSアプリに「Google AdMob」を導入した際に、テスト環境と本番環境で値を切り替えたい場面がありました。
その際にXcodeで用意されている「User-Difined Setting」という機能が便利に活用できたので、今回記事にしてみました。

# 環境
- Xcode13.2.1
- Swift5

# 実装方法
実装方法は非常にシンプルです。

- XcodeのPROJECTを選択した状態で、「Build Settings」タブを選択し、「＋」ボタンから「Add User-Defined Setting」を選択します。
![スクリーンショット 2022-05-04 18.58.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/62b11a42-6052-b919-144f-f3971931a58c.png)

- 「User-Defined」の項目に新規キーが追加されるので、適切な名前をつけてDebug、releaseそれぞれに使用したい値を設定します。
![スクリーンショット 2022-05-04 19.03.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/987bbb18-cb05-2064-86b9-bda64e5dc01c.png)

- info.plistにキーを追加し、先ほど追加した「User-Defined」のキーを参照します。
![スクリーンショット 2022-05-04 19.08.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/6211165e-4b16-dafd-56db-424df1e40bc5.png)

- 値を使用したい場所で、下記の様にinfo.plistのキーから値を取得する。
![スクリーンショット 2022-05-04 19.12.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/79e6c1ef-2a4f-be53-2454-259feb7fbde2.png)

# さいごに
非常にシンプルな方法でテスト環境と本番環境の値の切り替えが出来るので、「Google AdMob」を導入する場合などにぜひ活用してみてください。
AtCoder B - Good Distance

## 問題
https://atcoder.jp/contests/abc133/tasks/abc133_b




```Python
N, D = map(int,input().split()) 
#リスト内包表記
#上から順にlistを読み込んでlistに格納していく。
x = [list(map(int, input().split())) for l in range(N)]

ans = 0

for i in range(N-1): # i番目の点
  for j in range(i+1, N): # j番目の点
        dist = 0
        for k in range(D): #i点とj点を計算
            dist += (x[i][k] - x[j][k]) ** 2
        if dist ** 0.5 == int(dist ** 0.5):
            ans += 1
            
print(ans)
```



## ポイント

i点とj点を比較するので、全検索forの2重ループを使用する。
距離を測る際には別にfor文を用意する必要がある。
Windows11 WSL2で行うダウンロードが高頻度でタイムアウトするのを直す

## これは
- Windows11
- WSL2
- Ubuntu20.04LTS

## それは
- ネットからのダウンロードが高頻度でタイムアウト
  - npmを使えば `ETIMEDOUT`みたいに言われ、brewを使えばDownloading (curlを使ってそうな表示)で延々と待たされてtimeoutし、Spacemacsがelpaからダウンロードする時も無言で固まっている
  - たまに成功する (意味がわからない)
  - たとえば `brew upgrade`で10パッケージ近くをダウンロードしてしまっている時、Ctrl+Cで遮断して再実行すると、1~3個ずつダウンロードが完了することがあるし、Spacemacsのパッケージダウンロードが `(1/3)`で固まった時もSpacemacs自体を再起動すると `(2/3)`へ進捗することがある
  - 低確率で成功するから「あっ待ち始めたな」と思ったら遮断・再実行……を10回くらい繰り返していればそのうち最後まで行ける
  - 不思議なことにcurlを直接使ってタイムアウトした経験はない
- 色んなアプリが遭遇するのだからWSLのネットワークで何か起きてそうだけど途中の通信をどう引き抜けば良いのか全然わからない
- WiresharkでvEthernet (WSL)をキャプチャすると `TCP Port numbers refused`がドカドカ出てくるのでWindows側で何か弾いてるんじゃないかとは思うけど何もわからない
- 443ポートがやたら嫌われている感じはした
- 何も考えずファイアウォールを無効化するなどしてみたけど特に効果を感じなかった

## あれは
WSLの `resolv.conf`自動生成機能を止めた上で、WSLのDNSサーバ指定を `8.8.8.8` (Googleに限らず外部のDNSサーバなら何でも良いのかもしれない)へ変える

```conf:/etc/wsl.conf
[network]
generateResolvConf = false
```

```conf:/etc/resolv.conf
nameserver 8.8.8.8
```

cf. https://github.com/microsoft/WSL/issues/7254#issuecomment-905767204


---

そんなんでええんか？

自動生成されるのがWindowsホスト機IPだったなら、知らんドメインをホストに聞きに行ってホストがデフォルトルートなり何なりでルータへ繋いでくれそうだから自然な流れだと思って手を付けていなかったけど

(自動生成されるのが何のIPかも覚えていないし　いいや……)
Power BI workout - Personalize visuals

組織やグループに展開しているレポートが "すべてのひとに最適で必要" だったということは奇跡かも、展開が広ければ広いほどね。BI を活用する企業文化が成熟していれば、奇跡ではなく当然になるのでしょう。

使っている BI ソリューション のなかで最も使っている機能はなんですか？Excel へのエクスポート機能です。というジョークがあるのだけど、まじめに考えてもよいのではと思うのです。提供されている BI レポート や ビジュアルに満足できていないと考えてもよいわけで、じゃぁどうするかってところかと。単にイヤイヤしてるだけのコドモおとなをあやしてる場合ではないから、建設的な使い方ができればよいなぁと。

https://docs.microsoft.com/en-us/power-bi/create-reports/power-bi-personalize-visuals

Personalize visuals は、レポートを利用するユーザの操作によってキャンバスに配置されたビジュアルをカスタマイズできる。
# 機能を試すだけなら
ささっと自動生成できる Power BI のレポートに使われているから概要はすぐにわかるよね。

https://docs.microsoft.com/en-us/power-bi/create-reports/service-quick-create-report

https://docs.microsoft.com/en-us/power-bi/create-reports/service-quick-create-sharepoint-list

https://docs.microsoft.com/en-us/power-bi/create-reports/dynamics-quick-create-report

# 本格的に使うなら
本格的に使ってもよいけれども戦略的にね。

こういう機能はないのかと言われたら、こんなこともあろうかとささっと用意する。用意されたビジュアルが気に入らないと言われたら、集計対象が増減した時とかどうしますか？軸や凡例も増減した時とかどうしますか？じゃぁ、この機能を用意したので確認しながら最適と考えられるビジュアルを具体的に教えてねと。

## やらなければならないことは必ずやる
以下項目を並べていて思うのだけど、ほとんどモデリングの基本タスクでしょ。

**レポート上で直接利用されないフィールドやメジャーは必ず非表示にする**
モデリングのタスクでうち最も達成できていないことだと思う。単にレポートビューで表示されないということだけではないのです。Personalize visuals を使うためにということではない。

**暗黙のメジャーを使用しない**
メジャーはどのような集計をするのかを明示的に定義するもの。
Personalize visuals を使うためにということではない。

**Format / 書式設定**
レポートユーザが設定できないのだから当然。
Personalize visuals を使うためにということではない。

**Sort by column / 列で並び替え**
Personalize visuals を使うためにということではない。

**Column hierarchy / 列の階層**
Personalize visuals を使うためにということではない。

**Perspective / パースペクティブ**
Perspective は 追加された定義ではなくもともとあるんだよね。Power BI ではなかなか使う機会がなかっただけ。
Analyze in Excel でも使えますし。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/aac2f8ca-7a9c-4c1a-cf8a-9f827ec07124.png)
[Command text] に "Model" ってなってるでしょ。これ、既定の パースペクティブ名。だから、新たに定義した Perspective を使って、Excel ピボットテーブルで利用される 見出しやメジャーの表示を調整できる。

パースペクティブ を準備するには Power BI Desktop では解決できない。なので Tabular Editor など外部ツールを使うとよい。

Perspective の適用範囲はレポートのページごとだから、レポートの構成など含めて考慮する必要がある。


**レポートのカスタムテーマ** 
ユーザが様々なビジュアルを使用できるのだから、各ビジュアルの既定の書式を設定しておいた方がよい。だって、ユーザはビジュアルをカスタマイズできるけどフォーマットの変更ができないから。

https://qiita.com/PowerBIxyz/items/9c05aca7ddf2e7391a21#header--%E3%83%98%E3%83%83%E3%83%80%E3%83%BC

Header icon の `showPersonalizeVisualButton` で既定を`false`にして必要なビジュアルだけ`true`にするとか工夫もできるよね。

# 思ったこと🙄
Power BI に限らずなのだけど、サービスや製品にはたくさんの機能がある。じゃぁ、それらすべてを使いこなす必要があるのかというとそうではないよね。ただ、💡これが使えそうだなって機会はいつ来るかわからないからね。


# その他
https://powerbi.connpass.com/

- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
電子カルテとは何か？

## はじめに
　以下の記事は、

https://clius.jp/mag/2020/06/05/whats-electronic-karte/

に書かれていることを引用させていただいております。その上で私たちがよくわからなかったこと、もっと理解を深める必要があると感じた箇所について学習した内容を別の記事としてリンクを埋め込んでいる形となりますのでご了承ください。私たちが”さらに詳しく学習した箇所”はいわば初学者がよくわからない箇所、躓きやすい箇所だと認識しています。私たちが学習した轍を皆さんも辿っていただければ最終的な理解（ここでは”電子カルテとは何か”）に最短でたどり着けると思い、記事にさせていただきました。
## 電子カルテって何？
　みなさん、カルテってご存知ですか？そうです、病院で診察を受けたらお医者さんがパソコンに何やら打ち込んだり、紙に書いたりしていますよね。このように患者さんの状態や診察内容、経過等を記録したものをカルテと言います。
　特に電子カルテとは、診療内容を紙カルテに記入する代わりに、コンピュータ上で編集・管理し、診療録として保管・参照できるシステムを指します。多くの場合、医療に伴う色々な作業、たとえば紹介状・処方箋・検査データ管理・その他諸々をサポートします。近年ではクリニック開業に際して、電子カルテを導入するケースが増えてきており、その普及率は年々伸びています。
## 電子カルテの普及
　平成29年（2017年）に厚労省が発表したデータでは、400床以上の一般病院の電子カルテ普及率は85.4%にまで及んでいます。同データでは、一般診療所における電子カルテの普及率は41.6%と右肩上がりで、今後も普及率の伸びが期待されています。

↓↓以下、厚生労働省が公開している資料です↓↓</font>
[電子カルテ等の普及状況の推移](https://www.mhlw.go.jp/content/10800000/000482158.pdf )


## 電子カルテのメリット
　特にこれから新規開業する場合、ほとんどの診療所が電子カルテを導入しています。なぜなら、紙カルテと比較した時に、電子カルテならではのメリットが多く存在するからです。紙カルテでは長く診療を続けていくとその分、カルテの保管・収納スペースが必要となってきますが、電子カルテはコンピュータやクラウド上にデータを保存するため、大量の患者情報も省スペースで保管・管理することができます。また、膨大なカルテデータの中から必要な情報を検索して、患者情報をすぐに呼び出せたり、キーボード操作での素早いカルテ記入、誰にでも読める文字の入力、受付事務とのスムーズな情報のやり取りなどが可能で、時間効率を上げられます。レセコンと連携することで保険請求手続きなど、診察以外の業務の手間が削減され、診察に集中することができます。
<font color="DeepPink">**↓↓レセコンについてよくわからない方、確認したい方はこちら！↓↓**</font>

https://qiita.com/medit_project/items/b7396c9abdd469bfcd1b

## 電子カルテの種類
　電子カルテにはその形態の違いから２つに大別することができます。それぞれの特徴を押さえておきましょう。
### オンプレミス型
　まず初めに紹介するのはオンプレミス型の電子カルテになります。オンプレミス（On-premise）のpremiseは建物、構内という意味があり、名前の通りオンプレミス型電子カルテはサーバーコンピュータを自院内に設置し、データの保存・管理を行います。自院内のコンピュータ同士はローカルネットワークで接続されるため院内で完結するシステムとなっています。メリットとして

:::note info
メリット
- 大病院をはじめ、これまで医療機関で広く使われていたため、一般的にベンダーによるサポートが手厚いとされている。
- 専門的な機能や高度な医療機器との連携といった機能を多く備えてる場合がある。 
:::

などが挙げられます。一方でデメリットとしては、

:::note alert
デメリット
- 院内にサーバーコンピュータや専用端末を設置するスペースが必要。
- 故障やトラブルがあった場合には、自院にサポートが来るのを待たなくてはならない。
- データが自院のサーバーコンピュータに保存されているため、バックアップといったDR（災害復旧）対策を施す必要がある。
- 初期費用及びランニングコストが高い
  - 院内にサーバーコンピュータや専用端末を設置する初期費用として約300〜500万円程度かかる。（一般的なクリニックにおいて）
  - システムアップデートにかかる更新費や保守費用といったランニングコストがかかる。
:::

などが挙げられます。

<font color="DeepPink">**↓↓サーバーについてよくわからない方、確認したい方はこちら！↓↓**</font>

https://qiita.com/medit_project/items/f3b658d1a1595a13fa3a

### クラウド型
　続いてはクラウド型電子カルテの紹介です。クラウド型電子カルテは、自院内にデータの処理や保存をするサーバーを設置するオンプレミス型と違い、インターネットを通じてクラウド事業者が持つサーバーに分散してカルテデータが保存・管理され、そのサーバーからデータを呼び出して利用します。そのためその特徴はクラウドの特徴をそのまま受け継いでいると言えます。メリットとしては

:::note info
メリット
- コンピュータとインターネット、Webブラウザがあれば場所や端末を選ばずに利用可能
- 初期費用や稼働費はオンプレミス型と比べて安価です。
- 一般的なクラウドサービスではデータを保存するサーバーを分散させるなどして、DR対策を講じています。そのため、もしクリニックが災害などに遭ってしまったとしても、データ自体は別の場所に保存されているため、カルテデータは守られています。
:::

::: note alert
デメリット
- 事業者が提供する設定やオプション以外のカスタマイズはできません。そのため、規定の範囲内で電子カルテを運用していく必要があります。
- インターネットを介したシステムなので、インターネット環境がなければクラウド型電子カルテは利用できません。
  - 万が一、インターネットが使えない状況に陥っても対処できるような仕組み作りが求められます。
:::

<font color="DeepPink">**↓↓クラウドについてよくわからない方、確認したい方はこちら！↓↓**</font>

https://qiita.com/medit_project/items/714992e9c46bd97f1bfc
SharePoint作るときに参考にしているサイト

#### UIで参考にさせてもらっているサイト

https://developer.microsoft.com/en-us/fluentui#/

#### 色選びで参考にさせてもらっているサイト

https://developer.microsoft.com/en-us/fluentui#/styles/web/colors



#### jsonで書式設定するときに参考にさせてもらっているサイト

https://docs.microsoft.com/ja-jp/sharepoint/dev/

https://jpdebug.com/p/1201982
サーバーとは

## サーバーの定義
**ネットワーク上でデータを提供している側のことです。**
対義語にはクライアントが来ます。（クライアント：データを利用〈要求〉している側のこと）
コンピュータのネットワークを介してサーバーとクライアントがつながっているイメージです。
![サーバーとクライアントの関係](https://www.colorfulbox.jp/media/wp-content/uploads/2020/11/server-img01-1.jpg)
## サーバーの種類
サーバーにも様々な種類があります。大きくは物理サーバーと仮想サーバーに分けられ、そこからさらに用途によって細かく種類が分けられます。
**物理サーバー**：一台の物理的なサーバー
**仮想サーバー**：一台のハードウェアに、分割して複数のOSを動作させ、複数のサーバーが動作しているように見せかけて稼働するサーバー


サーバーも用途によって使い分けられます。イメージしやすいもので言いますと…

- **Webサーバー**：Webブラウザからのリクエストに応じて静的画面や画像などのホームページのデータをWebブラウザに送ってくれるサーバーのことです。ホームページを表示させるためにはこのWebサーバーが必要になってきます。

- **メールサーバー**：メールの送受信の役割を担っているサーバーです。このメールサーバーにおいてさらにサーバーが使い分けられています。

  - SMTPサーバー：メールを送信する役割
  - POPサーバー：メールを受信する役割（ダウンロードして閲覧）
  - IMAPサーバー：メールを受信する役割（オンライン上で閲覧）
  - DNSサーバー：IPアドレスを取得する（送信先を獲得）
![メール送受信の仕組み](https://business.ntt-east.co.jp/content/cloudsolution/images/column/img_column220_05.png)

- **データーベース（DB）サーバー**：複数のサーバーが必要な階層型システム上で、データベース管理システムが稼働するサーバーです。（システム上のデータを管理し、データの保存や更新、バックアップなどを行います。

- **クラウドサーバー**：クラウド上にある仮想サーバーのことです。

こういったものだと聞きなじみがあるかもしれません。

## 参考サイト

https://www.internetacademy.co.jp/trends/it-strategy/what-is-server-introductory.html

https://business.ntt-east.co.jp/content/cloudsolution/column-220.html
レセコンとは？

## レセコンって何？
　レセコンとはレセプトコンピューターの略で、一言で言うと”診療情報明細書（レセプト）を計算・作成するコンピューター”です。レセコンの目的は、診療報酬の請求業務を行うことであり、医療機関の会計情報を管理し、正しく関係機関へ請求するためのものです。医療機関の大半の収入が、レセプトの作成で得られるものであるため、医療機関の経営にとって非常に大切なプロセスでもあります。

## そもそも保険報酬の仕組みとは...
　日本では公的医療保険制度に全国民が加入しており、病気や怪我などの際に保険証を提示すれば、誰でも必要な医療行為を受けることができます。その対価として医療機関に対して支払われる費用は診療報酬と呼ばれ、厚生労働大臣が定めた医療行為1つ1つの点数を足し合わせて算出した金額となります。本来ならば医療行為を受けた患者さんが全て負担するところですが公的医療保険制度に加入している人は原則として診療報酬の3割を自らが負担し残りの７割は税金や社会保険料によって支払われます。これらを担っているのがレセコンの仕組みになります。

![保険診療の仕組み](https://www.its-kenpo.or.jp/images/hoken/situation/case_09/shikumi/b-041_illust.png)

https://www.its-kenpo.or.jp/hoken/situation/case_09/shikumi.html

https://www.med.or.jp/people/what/sh/

## レセコンと電子カルテの違い
**電子カルテ**：医師が使うもので医療情報を電子データで管理する。
**レセコン**：医師ではなく会計士や事務員が使うもので、会計情報を管理・使用するためのコンピューターのこと。

## 電子カルテとレセコンの連携
　レセプト作成のためには改めてカルテ情報を入力することがあるのですが、二つを連携することで医療事務の手間を減らすことができます。また、データをそれぞれ別に管理していた場合、修正や変更・追加などがあると両者のデータを変更する必要があるため、手間が2倍になる上に、ミスが発生する可能性も高くなります。
　この連携には二通りあり、「電子カルテ・レセコン連動型」と「電子カルテ・レセコン一体型」があります。連動型は、電子カルテとレセコンのシステムが別々になっており、一体型は、電子カルテとレセコンのシステムがひとつになっています。そのため一体型のほうが、別々に入力する手間をはぶくことができ、受付・診察・会計までが一元で管理できるので便利です。（しかしコストは高い）

## 現在の日本の医療経済について
![我が国の医療制度の概要](https://www.mhlw.go.jp/content/12400000/000768283.jpg)

https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/kenkou_iryou/iryouhoken/iryouhoken01/index.html
UndoManagerで簡単に元に戻す メモ

### UndoManagerとは
UndoManagerとはUndo機能を実装するためのクラス

https://developer.apple.com/documentation/foundation/undomanager

第一引数でUndoの対象となるオブジェクトを設定し、第二引数でUndoをした際の挙動をクロージャー内で実行できる。
```swift
func registerUndo<TargetType>(withTarget target: TargetType, handler: @escaping (TargetType) -> Void) where TargetType : AnyObject
```

実際のコード

```swift
func register() {
   
    // Undo操作をhandlerに登録
    undoManager.registerUndo(withTarget: 対象のオブジェクト) {
        // クロージャの第一引数 $0 は、Targetで指定したオブジェクトが入ってくる。


    }
}
```

実際にUndoする。先ほどクロージャー内で設定したundo処理を行う。

```swift
undoManager.undo()
```

その他
registerUndoの引数には循環参照を防ぐために参照型しかいれてはいけない。
クラウドとは？

## クラウドの定義
　クラウドとは、ユーザーが大規模なインフラ（サーバーやストレージ）やソフトウェアを持たなくてもインターネットなどのネットワーク経由でコンピューティング、データベース、ストレージ、アプリケーションをはじめとした様々なITリソースを必要な時に必要な分だけ利用するという考え方あるいはサービスの総称を指します。
- **インフラ**：インフラストラクチャー。パソコンやサーバーなどのハードウェア、ネットワークを構築するインターネット・LAN、データベース・OSなどのソフトウェアのことを指す。ITサービスの土台となるもの。
- **ストレージ**：大容量のデータを保存できる装置のこと。サーバーもデータの保存は可能だがストレージはデータの格納に特化しているためより大容量のデータを保存できる。物理的な機器としてのストレージだけでなく、インターネット上のスペースを利用するオンラインストレージと呼ばれるサービスもある。ex.)外付けHDDやUSBメモリ

## 具体例
- outlookやExcelやWord→そのアプリ自体をPCへインストールし、インストールしたPCのみで利用可能です。→これはクラウドではありません。
- Gmailはアカウントがありネット環境があればパソコンにソフトをインストールせずとも利用できます。→こちらはクラウドです。

## クラウドとサーバー
　クラウドを語る上で、クライアントとサーバーという言葉は切っても切れない関係にあります。コンピュータを使ったサービスでは、サービスを提供する側を「サーバー」と呼び、サーバーが提供したサービスを受け取るコンピューターを「クライアント」と呼びます。より具体的には、プログラムやファイルなどを保管し、複数の端末から共有できるスペースを有するコンピュータ（サーバ）と、利用者の操作するコンピュータ（クライアント）に役割を分け、これらが相互にネットワークで接続されています。このモデルをクライアントサーバモデルといいます。このモデルでは、クライアントがサーバに「要求」を送信し、サーバがそれに「応答」を返す形で処理が行われます。
![クライアントサーバーシステムの仕組み](https://d1gt4pceznpvut.cloudfront.net/files/user/sys_imgs/article/1418_018a.jpg?v=1490872602)

　上記の通り、サーバーは特定の役割を集中的に担当するコンピュータ(主に高度な演算やデータ管理)で1ケ所で管理すべき資源やサービスが保存されています。光ファイバーやweb技術が発達する1990年代以前は、各企業は自前のサーバーを用意し、社内のPCをサーバーに物理的につないで処理を行っていました。

## Webサーバー
　Webサーバーとは、パソコンやスマートフォンなどの端末からHTTP/HTTPSで送られたリクエストに対してHTML、CSS、JavaScriptなどの情報を返す役割を持ったソフトウェアのことを指します。一般的に、Webサーバーへ接続するためにはブラウザを使用します。私たちがWebサイトを閲覧しようとするとき、ブラウザはどのWebサーバーが目的のページを提供しているのか検索を行ないます。合致するWebサーバーを見つけると、そのWebサーバーに対してWebページを表示するために必要な情報をリクエストします。Webサーバーはリクエストを受けた情報をサーバー内から検索して、ブラウザに対して検索結果を送信します。そこでようやくブラウザが受け取った情報を再構成して、Webページを表示できるのです。
　通常、通信のポート番号は決まったものを使用します。ポート番号を簡単に説明すると、扉（Webページ）の番号をイメージすると良いでしょう。Web上でアクションをする際は、扉の番号が必要になり、それがポート番号になります。メールを送る場合のポート番号、Webページを見るためのポート番号などそれぞれに割り振られており、HTTPは80番、HTTPSは443番が一般的です。そして、Webサーバーにはさまざまな種類があり、メジャーなものとしてはApache、Nginx、IISなどがあります。
　このWebサーバーの普及により、webブラウザにより遠隔サーバーからデータやサービスを受け取ることが可能になりました。しかし、サーバーは自前で用意しなければならない点は変わりません。そこで用いられるようになったのがクラウドです。

## クラウド
　それでは、クラウドです。クラウドでは、物理サーバーの中に数台の仮想サーバーを立てています。そして、このサービスは大手のIT会社が提供しているプラットフォームを利用するので自前でサーバーを用意する必要がありません。
![仮想サーバーについて](https://pfs.nifcloud.com/navi/beginner/images/virtualization.png)
### (補足）クラウドの種類
クラウドにはいくつか種類があります。
**SaaS（Software as a Service）**･･･　ソフトウェアを提供するクラウドサービス
**PaaS（Platform as a Service）**･･･　開発環境を提供するクラウドサービス
**IaaS （Infrastructure as a Service）**･･･　サーバー（インフラ）を提供するクラウドサービス
のようなものですが、特に意識する必要はないかと思います。

 つまりクラウドは、仮想Webサーバーによって提供されるwebサービスということになります。クラウドの特徴について以下にまとめておきます。

:::note info
クラウドサービスのメリット
- アカウントがあれば様々な端末からサービスを利用できる。
- 初期費用が安いこと。サービスによっては無料で利用できるものもある。
- 導入の手間もかからず、障害対応も提供者側が行うため安心して使える。
- クラウドサービスを用いてソフトウェアやサービスの開発を行う際には、サーバーの拡張が容易にできる。
:::

:::note alert
クラウドサービスのデメリット
- カスタマイズが自由にできないこと。
  - 全てを自社で調達し、開発するオンプレミス型のサービスに比べると、どうしても自由度は下がる。
- インターネット上でサービスを提供している仕組みのため、オンライン環境でないとサービスが受けられない。
- サービスが停止されるリスクも考えられる。
:::




## 参考サイト

https://www.itscom.co.jp/forbiz/column/office-environment/1087/

https://securesamba.com/media/8279/

https://www.internetacademy.co.jp/trends/it-strategy/merit-and-demerit-of-cloud.html
Listへの新規アイテム登録画面の書式設定をjsonでいじってみたのでメモ


## とりあえずこんな感じにしてみた。

![List_Add.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2652090/ba238406-70c3-3f23-4d2b-afe541b4c047.png)

## コードはこんなかんじ。

```json:ヘッダー
{
  "elmType": "div",
  "attributes": {
    "class": "ms-borderColor-teal"
  },
  "style": {
    "width": "100%",
    "border-top-width": "0px",
    "border-bottom-width": "5px",
    "border-left-width": "0px",
    "border-right-width": "0px",
    "border-style": "solid",
    "margin-bottom": "16px"
  },
  "children": [
    {
      "elmType": "div",
      "style": {
        "display": "flex",
        "box-sizing": "border-box",
        "align-items": "center"
      },
      "children": [
        {
          "elmType": "div",
          "attributes": {
            "iconName": "TextDocument",
            "class": "ms-fontSize-42 ms-fontWeight-regular ms-fontColor-teal",
            "title": "Details"
          },
          "style": {
            "flex": "none",
            "padding": "0px",
            "padding-left": "0px",
            "height": "36px"
          }
        }
      ]
    },
    {
      "elmType": "div",
      "attributes": {
        "class": "ms-fontColor-neutralSecondary ms-fontWeight-bold ms-fontSize-24"
      },
      "style": {
        "box-sizing": "border-box",
        "width": "100%",
        "text-align": "left",
        "padding": "21px 12px",
        "overflow": "hidden"
      },
      "children": [
        {
          "elmType": "div",
          "txtContent": "Document submission form"
        }
      ]
    }
  ]
}
```


```json:本文
{
  "sections": [
    {
      "displayname": "Document",
      "fields": [
        "Applicant",
        "Title"
      ]
    },
    {
      "displayname": "Schedule",
      "fields": [
        "Applicant date",
        "Deadline"
      ]
    },
    {
      "displayname": "Progress",
      "fields": [
        "Authorizer",
        "Progress"
      ]
    }
  ]
}
```

```json:フッダー
{
    "elmType": "div",
    "attributes": {
        "class": "ms-borderColor-teal"
    },
    "style": {
        "width": "100%",
        "border-top-width": "0px",
        "border-bottom-width": "3px",
        "border-left-width": "0px",
        "border-right-width": "0px",
        "border-style": "solid",
        "margin-bottom": "16px"
    }
}
```
コミュニティースペースの自動仮予約システムをMakeで作成

## 課題：貸しスペースの予約や日程管理を自動化し、電話対応の時間や、連絡の抜け漏れを無くしたい

私は、業務でコミュニティースペースの管理をしているのですが、ボランティア同好会の大学生、子ども食堂で利用するお母さんたち、イベントスペースとして利用したい学生など、様々な関係者から、コミュニティースペースの予約連絡が来ます。これをなるべく自動化し、最小限の労力で動かせるようにできればと思っています。

## 解法：Googleフォームで希望日を回答すると、自動でGoogleカレンダーに仮予約を記載し、LINE通知をしてくれるシステムを作る。また、その共有カレンダーをウェブ上に公開しておく。


Notion上に置いた、今回作成した自動仮予約システムのスクリーンショット
<img width="auto" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2562329/4d6255a4-3dda-4f8d-90fd-6ea5f885797f.png">

## 実装環境
[Google form](https://www.google.com/intl/ja/forms/about/)
[Google calender](https://www.g-workspace.jp/googleworkspace-reference/calendar/)
[LINE](https://line.me/ja/)
[Make](https://www.integromat.com/en)
[Notion](https://www.notion.so/ja-jp/product)

今回は、こちらの5つのサービスを使いました。

「Googleフォーム」で回答したコミュニティースペースの使用希望を、「Make」を使って、「Google calender」に自動で書き込むようにして、同時に「LINE」に仮予約が入ったことを通知します。連携した「Google　calendar」は、「Notion」で簡易的なWEBサイトとして表示し利用者も閲覧できるようにします。

<img width="600" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2562329/89ca0535-25f4-74ac-7cbf-b65ba5cba50f.png">

**①GoogleFormsの作成**
この辺りは、通常のGoogleフォームの使い方と一緒です。使用日と使用時間の質問だけ、日付と時刻専用の回答フォームを使っています。
<img width="500" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2562329/e76e13d2-578e-463f-2adf-c04c25eecb52.png">

**②Makeでの連携（Googleフォーム）**
Googleフォームの回答が記載されている、Spreadsheetのリンクを指定します。
<img width="500" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2562329/d05e9d22-4380-636f-ea82-4d487e4a5475.png">

**③Makeでの連携（Googleカレンダー）**
Googleカレンダーの新規予定作成に必要な項目を、上記で紐付けた、Googleフォームの回答項目から選んでいきます。
<img width="500" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2562329/31e98e8b-26dc-4dc2-4108-41e70327be96.png">
これで、自動でフォームの回答が、カレンダーに記載されるようになります。

**④Makeでの連携（LINE）**
最後に、スペース利用の予約が入ったことの通知がLINEで来るように設定します。

<img width="500" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2562329/ceec12bd-f280-b14e-d3b1-4661e61023ae.png">

フォームに申し込みがあると、このような形で、LINEからも通知が来るようになります。
<img width="500" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2562329/ba2df60e-5b31-ad29-6c01-d14172a1dd77.jpeg">
管理しているメンバーでLINEグループを作って、そこに届くようにしておけば、いちいちメンバーに報告する必要もなくなると思います。

iPaaSである、Makeの特徴や細かい使い方は、こちらのサイトなどをご参照ください。
（旧名　「integromat」　→　　現在は「Make」になりました。検索は旧名のほうが引っかかります。）

https://nocodedb.world/archives/5489

## フィードバック
プロジェクトを共同で進めることの多い、同僚Cさんにフィードバックをもらいました。

**C氏「管理が楽になりそうでとてもいい。気になるのは、Googleフォームに連絡先を入れてもらうと、メアドを入れ間違える人が一定数出てくるので、予約が取れなかった時に、そういう人と連絡が取れなくなるパターンが心配。」**

コミュニティースペース利用希望者が加入必須なLINEBotを作るなど、相手と連絡が取れる手段を、一個かましてから、Googleフォームに案内するなど導線に工夫の余地がありそう。システム側の工夫と、運用での工夫を組み合わせて、穴を潰していきたい。

## まとめ
比較的簡単に、ノーコードで業務効率化のシステムができてしまうのは、やはり感動的ですらあります。まだまだ、Makeの細かい仕様もわからないので、もっとポテンシャルと引き出しは、あると思います。長崎近郊に住む、非エンジニアの周りの人たちと分かち合って、iPaaS勉強会は、やっていこうと思います。
Syslog ログレベル

# 【Syslog】

## Syslogとは
- ネットワーク上でログメッセージを転送する標準規格
    - 主にサーバーやネットワーク機器で利用される
    - Syslogサーバーに保存されたログはセキュリティや監査、障害発生時の調査等に活用

## ログレベル
- 最も一般的なレベルは、DEBUG, INFO, WARN, ERROR, FATAL

- **レベル定義に従うことは強制ではなく、適切なレベルでログを出すかはエンジニア次第**
    - 適切なログレベルが設定されていないと何かの情報をログから探すことが困難に、、 

### DEBUG
- プログラム内で起こっていることに関連するあらゆる情報
    - プログラマーがデバッグのために書いたメッセージであることが多い

### INFO
- ユーザーが開始したアクションや、スケジュールされたタスクの実行
- システムのスタートアップやシャットダウンなどのシステム操作

### WARN
- 将来的にエラーになる可能性のある状態
- ライブラリの廃止に関する警告、 使用可能なリソースの不足、パフォーマンスの低下など

### ERROR
- すべてのエラー状態

### FATAL
- システムをシャットダウンさせるすべてのエラー状態
    - システムの起動に32GBのメモリが必要だが16GBしか利用できない場合、
      プログラムはFATALエラーメッセージを記録し、 ただちに終了することになる

## 参考
- システム運用アンチパターン
RVMをシェルスクリプト内で利用する場合の注意

# シェルスクリプト上ではRVMはそのままでは実行できない

```sh
#!/usr/bin/env bash

set -eu

rvm use 2.7.2
```

デプロイを自動化しようとして例えばこのようなことをすると、次のようなエラーが起こり、実際にrubyのバージョンが指定できない。

```
RVM is not a function, selecting rubies with 'rvm use ...' will not work.

You need to change your terminal emulator preferences to allow login shell.
Sometimes it is required to use `/bin/bash --login` as the command.
Please visit https://rvm.io/integration/gnome-terminal/ for an example.
```

コンパイルエラーのような感覚でこのエラーを読むと「RVMは関数ではありません」と読めてしまい混乱する ("RVMは関数でないから決して関数みたいな呼び出し方はするな" という類のエラーに見える)が、このエラーはむしろ「RVM**が**関数ではありません」と読まれるべきものである。つまり、RVMは`bin`フォルダに入っているもの(`/usr/local/rvm/bin/rvm`など)を直接使うのではなく、同名のBash関数として定義されたものでなければ正しく機能しないらしい。

## 追記: 調べてみた

`bin` というフォルダに入っているからといって、その中にある実行ファイルが `binary` であるとは限らないようだ！(実質的な動作の違いはさほどないからだろうか？) `/usr/local/rvm/bin/rvm` は[テキストとして読めるBashスクリプト](https://github.com/rvm/rvm/blob/master/bin/rvm)だった。ログインシェルの中でのみ、自動的に必要なファイルが読まれ、`rvm`がshの関数に置き変わる。

```
# シェルスクリプトで type rvm を実行すると
$ cat ./test.sh
#!/usr/bin/env bash
type rvm
$ ./test.sh
rvm is /usr/local/rvm/bin/rvm

# しかしシェルプロンプトから直接実行すると
$ type rvm
rvm is a function
(関数が吐かれる)
```

# 一旦特定のファイルをsourceする必要がある

[シェルスクリプトで使う場合にのみ、次のパスのどちらかにあるファイルを `source` しないと動作しない](https://stackoverflow.com/questions/19954043/how-to-use-rvm-in-shell-scripting)。

```sh
source "$HOME/.rvm/scripts/rvm" # $HOMEにあるなら
source "/usr/local/rvm/scripts/rvm" # システムレベルであるなら
```

これを実行すると、 `rvm` が関数に置き換えられて `use` などのサブコマンドが使えるようになる。

# それでも落ちる場合

`set -eu` をしているとこの `source` および `rvm` コマンドは失敗する。

```sh
#!/usr/bin/env bash

set -eu

source "/usr/local/rvm/scripts/rvm"

rvm use 2.7.2
```

```
/usr/local/rvm/scripts/functions/support: 行 182: _system_name: 未割り当ての変数です (英語の場合"Unbound variable")
```

どうやら `rvm` は未割り当て変数が存在する前提で動作するようになっているらしい。
そのため、 `rvm` コマンドの操作が終わるまでは、 `set +u` を明示的に指定した上でコマンドの実行が妨げられないようにしなければならない。 
`rvm` を実行し終わった後は `set -eu` しても構わない。

# 期待通り動作するスクリプトの例

```sh
#!/usr/bin/env bash

set +u # WTF: rvmコマンド群の未定義変数エラーを回避

source "/usr/local/rvm/scripts/rvm"
rvm use 2.7.2

set -eu # エラー処理を元に戻す

bundle install
bundle exec something
```
ユニコード拡張とゲーデル数化

# はじめに
自作のEasy-ISLispにユニコードの機能を拡張しています。これのテストにユニコードで記述された論理式の文字列をゲーデル数化するもの、そしてその数を論理式を表す文字列に復号するコードを書きました。

# ゲーデル数
数学者ゲーデルはその不完全性定理の証明にあたり論理式を自然数に変換する手法を用いました。ゲーデル数と呼ばれています。数学が自己言及するための仕組みです。素因数分解の一意性を利用しています。

論理式に用いられる記号に対応する自然数を定義しておきます。そして素数のべき乗の積を計算します。


2^3 * 3^4 * 5^2 　のようにです。　　　　

復号の計算ではmathライブラリの素因数分解を利用しています。　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　

# 動作例

```lisp
Easy-ISLisp Ver2.40
> (load "tests/godel.lsp")
T
> dt
"∃xy〜(x)∧(y)"
> (encode dt)
395017145154031183566599905857292182568201440502240006394147044479902343750000
> (decode 395017145154031183566599905857292182568201440502240006394147044479902343750000)
"∃xy〜(x)∧(y)"

```

# ソースコード

```lisp
#|
godel number (test unicode)

|#
(import "math")
(import "cxr")

(defglobal dt "∃xy〜(x)∧(y)")

(defglobal code-list
    '((1 #\〜)
      (2 #\∧)
      (3 #\))
      (4 #\∃)
      (5 #\=)
      (6 #\0)
      (7 #\s)
      (8 #\()
      (9 #\))
      (10 #\")
      (11 #\x)
      (13 #\y)))


(defun rev-assoc (key list)
    (if (equal (cadar list) key)
        (caar list)
        (rev-assoc key (cdr list))))

(defun char->integer (ls)
    (mapcar (lambda (x) (rev-assoc x code-list)) ls))

(defun string->integer (str)
    (char->integer (convert str <list>)))

(defun integer->godel (ls)
    (integer->godel1 ls 1))

(defun integer->godel1 (ls n)
    (if (null ls)
        1
        (* (expt (prime n) (car ls)) (integer->godel1 (cdr ls) (+ n 1)))))

(defun encode (str)
    (integer->godel (string->integer str)))

(defun decode (n)
    (decode1 (factorize n)))

(defun decode1 (ls)
    (if (null ls)
        ""
        (string-append (convert (cadr (assoc (cadar ls) code-list))  <string>)
                       (decode1 (cdr ls)))))
         

```

# ISLisp規格との関連
ISLisp規格ではユニコードについて規定されていません。Easy-ISLisp用に独自に拡張しました。文字列とキャラクタにのみユニコードが使えます。

```
> dt
"∃xy〜(x)∧(y)"
> (elt dt 0)
#\∃
> (aref dt 7)
#\∧
> (convert dt <list>)
(#\∃ #\x #\y #\〜 #\( #\x #\) #\∧ #\( #\y #\))
> (length "こんにちは")
5
> 

```


現在、ISLispの規格を満たしつつユニコードの拡張ができているか検証テストコードで確認中です。確認作業が終わりましたら正式にver2.40としてリリース予定です。

https://github.com/sasagawa888/eisl
[ARKit] Occulustion

## Occulustionとは
手前にある物体が後ろの物体を隠すことをいう。普通のことに思えるが、ARではこれをしっかり考えていないと手前にある物体が後ろの物体を隠さずに不自然にレンダリングされることになってしまう。

## Occulustionにするには
下記のOcuulusionMaterialをmodelEntityのMaterialとして設定する。

![スクリーンショット 2022-05-04 17.47.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474285/b8c9ab85-0953-14e4-5cfa-47d0d8ae6100.png)

下記コード
```swift
let model = ModelEntity(mesh: .generateBox(size: 1.0))
let material = OcculusionMaterial()
model.material = material 
```

これでOcculusionMaterialを設定したモデルはOcculusionが有効になる。
Laravel sail の文字化け問題を解消する




Laravel sailを普通にビルドすると、データベースの文字化けが発生します。
ここでは解消方法を共有したいと思いますが、その前にDockerの仕組みについて簡単に説明します。

Dockerは、素になるイメージファイルを使ってコンテナイメージを生成します。Dockerのライフサイクルでは一度、イメージが生成されると変更差分をキャッシュするので、一度ビルドすれば何度でもイメージを使いまわすことが可能ですが、基本的に個々のファイルの依存関係をスナップとして保存しているため、**アプリケーションのソースコードやデータベースのデータはローカルのディレクトリにマウント（同期）して保管しておく必要があります。**

その意味ではGitに似ています。

![docker_lifecycle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654367/791f0e2c-5504-fb22-6d17-fa97e1551b0f.png)

また通常、アプリを稼働・運営する場合は複数のコンテナを生成する必要がありますが、それらの依存関係を定義するファイルが**docker-compose.yml**になります。

まずMySQLのコンテナ内部に入り、データベースの設定ファイルである my.cnf がどこにあるのか、ディレクトリを特定します。Macでは通常、etc/の配下にあるケースが多いです。

![スクリーンショット 2022-05-04 17.10.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654367/f28c03a8-bebc-8e43-4cc3-6fdc579e778a.png)

編集を加えるファイルの場所が分かったので、次にdocker-compose.ymlのファイルにマウントを指示する記述を加え、さらにmy.cnfの中身も編集します。

```php:docker-compose.yml
    mysql:
        image: 'mysql/mysql-server:8.0'
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ROOT_HOST: "%"
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 1
        volumes:
            - 'sail-mysql:/var/lib/mysql'
            - './my.cnf:/etc/my.cnf'
```

```my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
explicit-defaults-for-timestamp=1
general-log=1
general-log-file=/var/log/mysql/mysqld.log

[client]
default-character-set=utf8mb4
```
これでコンテナを再起動すれば、諸々の変更内容がデータベースに反映されるはずです。
ロリポップ！　WordPressのフォルダを完全消去する方法

ロリポップ！でアップロードした、WordPressのフォルダを完全消去する方法をアウトプットしておきます。
まず、
https://lolipop.jp/manual/blog/wordpress-del/
を見て手順通りに進めますが、
「ロリポップ！ＦＴＰで、フォルダが消去できない」場合にこの記事をよんでください。

それは、
https://support.lolipop.jp/hc/ja/articles/360049133353-web%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E4%B8%8A%E3%81%AE%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB-%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%81%8C%E5%89%8A%E9%99%A4%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93

としてロリポップ側で解答されています。

![755.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2101809/567d6a55-f54e-994a-0c8e-b2782a3a9cef.png)
これは自分のロリポップＦＴＰの画像です。
中央右上の「現在の属性値」が755となっているのが見えますか？

これをどうやって705に変えればいいのか、が今回の本題です。

Ａ.以下のように変更してください。
![705.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2101809/527b26e7-3bdc-ceac-35bd-46ffcb8ae5f3.png)

項目のチェックを変更すると、「705」になりました！！

やったー！ということで、終わりです。ありがとうございました。
TweepyとTwitter API V2を利用して100件以上のツイートを一度に取る方法

わたくし、最近Tweetを収集してセンチメント分析をすることを楽しんでいる（https://twitter.com/tweet_mood_ai
）のですが、先日までに書いたコードがAPI v1.1を利用したものになっていたことに気づきました。
遠からず使えなくなるAPIを使ったままにするのは忍びないので書き直しました。

TweepyからAPI V2を利用してたくさんのTweetを取得するサンプルコードはあまり見かけなかったので、お役に立てば幸いです。

```
tweepy.Paginator
```
を利用すると、ページネーションの処理を書かなくていいのでらくちんです。
22/5/19:取得したい時間幅の指定（通常のAPIでは過去7日まで）ができるようにしました。

## TweepyからTwitter API V2を利用してTweetを取得するコード
```
import tweepy
import pandas as pd
from datetime import datetime,timedelta

BAERER = '*************'   # Twitter Developerで取得したBearer Token
query = '吉野家 lang:ja -is:retweet'       # 検索するキーワード 検索条件指定してOK
limit = 500                # 取得したいツイート数

# 取得対象のツイートの時間幅を指定する この例では実行前の２４時間としています。
# iso形式のUTC時間で指定しないと正しく時間指定ができない模様。
# 指定した時間幅に、limitで指定した件数以上のツイートがあってもlimit以上は取得しません。

now = datetime.now()
now = now.replace(minute=0, second=0, microsecond=0)
end_time_tweepy = str(now.isoformat())+'+09:00'
start_time = now - timedelta(days=1) 
start_time_tweepy = str(start_time.isoformat())+'+09:00'

client = tweepy.Client(BAERER)

df_tweet = pd.DataFrame()
for tweet in tweepy.Paginator(client.search_recent_tweets, query=query, start_time=start_time_twint, end_time=end_time_tweepy,
                              tweet_fields=['id','created_at','text','author_id','lang',], 
                              max_results=100).flatten(limit=limit):
    #print(tweet.text)
    df_tweet = pd.concat([df_tweet, pd.DataFrame([tweet.data])], ignore_index=True)

print(df_tweet)
```
DigisparkでOLED SSD1306

u8x8を使って，無事動きました。

```main.cpp
#include <Arduino.h>
#include <U8x8lib.h>

U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ 2, /* data=*/ 0, /* reset=*/ U8X8_PIN_NONE); // Digispark ATTiny85

void setup(void)
{
  u8x8.begin();  
}

void loop(void)
{
  u8x8.setCursor(0, 0);
  // u8x8.setFont(u8x8_font_8x13_1x2_f); // too big size
  // u8x8.setFont(u8x8_font_7x14_1x2_f); // too big size
  // u8x8.setFont(u8x8_font_5x7_f); // good
  u8x8.setFont(u8x8_font_torussansbold8_r); // good
  u8x8.print("Hello World!\r\n");

  delay(2000);
  u8x8.clear();
}
```
指定するフォントにより，ATTinyの容量に収まりませんでした。


```platformio.ini
[env:digispark-tiny]
platform = atmelavr
board = digispark-tiny
framework = arduino
lib_deps = olikraus/U8g2@^2.33.2
```

自分でドライバーらしきものを書こうと数年前奮闘していたけど，実はあっさり動くなんて... 感謝です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/f263e38a-3286-26bd-e43f-a5f902720f4a.png)
レコメンドシステム：アイテムベース協調フィルタリング

# 背景：レコメンドシステムも本格的に理解したい
最近、Kaggleで「H&M Personalized Fashion Recommendations」というのが始まりました。と言っても、もう1週間もしないうちに終わります。ファッションが楽しくなってきた私にとって、H&Mのデータを使うというのと、前から気になっているレコメンドシステムのコンペという事もあり参加だけさせてもらっていました。いろいろ分かってきた事もあるので、コンペの規約に引っかからない程度に共有させて頂きます。
# 目的：簡単なRecommendation Systemsを作って、最新のGLocal_Kを理解します。
まずは「[Browse State-of-the-Art](https://paperswithcode.com/sota)」でRecommendationSystemuについて調べます。最新の手法に「GLocal_K」があるのが分かりました。更に、GitHubから「[GLocal_Kの原著論文](https://arxiv.org/pdf/2108.12184.pdf)」をあたり、これまでの手法とスコアの比較も知ることが出来ました。そもそもRecommendationSystemをまともに作った事も精査した事もなかったので、協調フィルタリングあたりから実装してみようと思いました。
# 方法：「[我妻先生の動画](https://youtu.be/8tIYpybe0Tg)」をなぞります。
今回はアイテムベース協調フィルタリングです。簡単に流れを追います。
1. データを読み込む。
1. 相関行列（類似度）を求める。
1. ユーザー0について、各映画のお勧め度を求める。

# 結果：実装の結果を方法の流れに沿って見て行きます。
1. データを読み込む。
データは[MovieLens](https://grouplens.org/datasets/movielens/)から引っ張ってきました。我妻先生の動画に従ってユーザー0を加えてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/0a69704d-9f16-adf1-1643-6a438e415b92.png)

1. 相関行列（類似度）を求める。
先程のデータを使って相関行列を求めます。これはあくまで、映画を評価した人たちの範囲で求めた類似度になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/130dcd16-4357-062e-f4b3-664e431eb5da.png)

1. ユーザー0について、各映画のお勧め度を求める。
相関行列を元に、ユーザーが評価した物に対してウエイトを掛けます。下に表示したのはユーザー0が評価した物以外のトップ10です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/e33b0c77-86e6-d5c5-54d8-ba9d915dca85.png)

# 感想：シンプルなのにそれっぽい
今回は非常にシンプルなレコメンドシステムを実装しました。手順的には「1. 相関行列を出す, 2. ウエイトを掛ける」の2つだけで非常にシンプルです。シンプルなのにそれっぽいのには感動を覚えました。

# 課題：RecommendationSystemをいろいろ試したい。
GLocal_Kを使える様にするのが、ここでの最終目標です。論文を見ると「LLORMA」「I-AutoRec」「CF-NADE」など、何のことか分からない手法も試されている様です。全部を試さなくても良いと思いますが、なんにしろレコメンデーションに対する理解は深めていきたいと思います。

# 参考
1. [我妻(2022.5)、実践データサイエンス&機械学習 with Python 映画のレコメンドを行う、YouTube](https://youtu.be/8tIYpybe0Tg)
1. [Soyeonら(2021.8.27),GLocal-K: Global and Local Kernels
for Recommender Systems, arXiv](https://arxiv.org/pdf/2108.12184.pdf)
1. [MetaAI(2022.5), Recommendation Systems, Browse State-of-the-Art](https://paperswithcode.com/task/recommendation-systems)
Laravel API 例外発生時のHTTP ResponseをJson Responseにする

Laravelで正常時にJsonレスポンスを返していても、例外時はHTTPレスポンスを返す場合があります。
HTTPヘッダーに`Accept: application/json` が指定されてないとHTTPレスポンスが返ってきます。

フロント側でHTTPヘッダーを追加して送ってもらうのも正しいですが、指定がないとHTTPレスポンスが返るのもAPIサーバーとしては謎な挙動なので常にJsonレスポンスを返すためにミドルウェアを作ります。

## 環境

- PHP: 8.1.5
- Laravel: 9.9.0

## 手順

```shell-session
$ php artisan make:middleware ForceJsonResponse
```

```php:app/Http/Middleware/ForceJsonResponse.php
<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

final class ForceJsonResponse
{
    /**
     * @param Request $request
     * @param Closure $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next): mixed
    {
        $request->headers->set('Accept', 'application/json');

        return $next($request);
    }
}
```

`app/Http/Kernel.php` に`ForceJsonResponse`ミドルウェアを追加します。

```php:app/Http/Kernel.php
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\ForceJsonResponse::class, // 追加
    ];
```