OmniAICreator/Qiita-1.07M huggingface dataset:
LinodeでCode Serverを構築して低コストのVisual Studio Codeの開発環境を手に入れよう

# Linodeとは

Linodeについてはこちらを参照。

https://qiita.com/isss802/items/5313c7a6da1d9ed50a38

# Code Serverとは

Code Serverは、VS Codeのバックエンドの部分をサーバー上で稼働し、WebベースのアクセスでVS Codeを操作できるようにしたものです。
Web経由でのアクセスをセキュアに行え、どこからでも開発を行うことができ、VS CodeをインストールできないChromebookやiPadなどでも快適に開発を行えます。

https://github.com/coder/code-server

# Linode構築する Code Server

LinodeでCode Serverを構築するメリットとしては以下が挙げられます。

- 個人専用のサーバーを用意でき、ローカルでの重い処理も快適になる
- マーケットプレイスを利用することで簡単に構築が可能
- 低コストで予測しやすい費用で構築が可能
- インスタンスの費用は月額5ドルから利用が可能
- 一定の転送量がインスタンス費用に含まれいる

## Linodeの構築

今回は最小のLinodeインスタンスで構築するため、月額の費用は5ドルからとなります。

コンソールにログインし、LinodesからCreateを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/76000a9b-b7c9-b982-cc45-8ea01023eefe.png)

Marketplaceの検索項目に「vs code」と入力し、「VS Code Server」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/19eab40b-757d-32b7-2050-381edec75c5c.png)

VS Code Serverのセットアップを行います。

最小のLinodeインスタンスの場合、入力項目は2つです。
- Web UIにアクセスするパスワード
- SSL認証に必要なメールアドレス

今回はAdvanced Optionの設定は省略します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/563d0373-c030-cea5-b94b-ec0c496980f6.png)

リージョンとインスタンスタイプを選択します。

インスタンスタイプの選択については以下を参照ください。

https://qiita.com/isss802/items/c53315615a7e087cc41a

今回はリージョンは日本で最小のインスタンスタイプを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/4b16f191-5fcb-4b61-9981-cf0ad30adb7b.png)

インスタンスの設定を行います。

Linode Label：インスタンス名
Root Password：Rootパスワード
SSH Keys：RootのSSH公開鍵

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/5f2d00de-010f-bcc7-3ce7-2fada0851b0f.png)

Marketplaceで対応しているOSはDebianとなります。
問題なければCreate Linodeを選択し、起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/b3243d16-ac4e-5d05-e470-98de6faf476c.png)

## Visual Studio Code Serverにアクセス

サーバーが起動したら、接続に利用するDNSをコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/03542a8d-e971-3016-bd76-d0ca92b7f4e8.png)

xxx-xxx-xxx-xxx.ip.linodeusercontent.com へブラウザでアクセスします。
ログインするためにパスワードが表示されるため、先程設定した内容を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/5ee1d7a8-0a26-0199-9179-72d95de0b00f.png)

WebブラウザからVisual Studio Codeの操作が可能となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/8b5b7ed8-fd94-a16a-b62a-743e06e3005f.png)

Visual Studio Code ServerはPWA に対応している為、Chromeなどの対応したブラウザで開くとアプリ化することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/6a134317-d5eb-9ab6-07ec-b63539a57b5a.png)

これで以下のように、アプリのように利用することが可能となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/5e3ca833-f1a9-36f9-0a7c-a338a7cbb8cf.png)


## さいごに

今回はマーケットプレイスを利用した簡単な構築方法の紹介となりましたが、好きなOSを選択したい場合にはLinodeのサーバーを構築した後に以下を参考にインストールすることが可能です。

https://code.visualstudio.com/docs/remote/vscode-server

Linodeは今回のような低コストで維持したい個人の開発環境など、様々な用途で利用することができます。

## 関連記事

アカマイ・テクノロジーズ合同会社のQiitaではLinode関連など開発者向けの記事を記載しております。

https://qiita.com/organizations/Akamai
Rails enumを設定したカラムの値が取得できない時に確認したい場所

# 何が起きた？
例えばUserモデルにstatusというカラムがあるとする
usersテーブルの中身はこう！
|id|status|
|:--|:--|
|1|1|
|2|2|
## enumを定義したカラムの値を取得してもnilとなってしまう
例えばUserモデルにstatusというカラムがあるとする

```ruby
class User < ApplicationRecord
    enum status: { economy: 1, vip: 2 }
end
```

rails cでstatusを表示すると以下のようになる

```shell
$ rails c
$ [1] pry(main)> User.find(1).status
$ => nil

```

え？
それどころかデータを見てもnilなのだ

```shell
$ rails c
$ [1] pry(main)> User.find(1)
$ => User
$    id: 1
$    status: nil

```

それはもうおかしいじゃん。ダメじゃんそんなの！
聞いてないって！！！


## enumの定義を消すと値は取得できる。

```ruby
class User < ApplicationRecord
    # enum status: { economy: 1, vip: 2 }
end
```

rails cでstatusを表示すると以下のようになる

```shell
$ rails c
$ [1] pry(main)> User.find(1).status
$ => "1"

```

んなんでだ？

## 想定していた動き

```ruby
class User < ApplicationRecord
    enum status: { economy: 1, vip: 2 }
end
```

rails cでstatusを表示すると以下のようになる

```shell
$ rails c
$ [1] pry(main)> User.find(1).status
$ => "economy"

```

こうなると思っている。何もおかしくない。俺は間違っていない。うわああああああああああ

# 原因はカラムの型の定義だった
これは気付くのに時間がかかりました。
マイグレーションを使っていないのですが簡単に書くと

```ruby
# 数値で定義すべきところが
integer :status

# 文字列になっていた
string :status
```

:neutral_face::neutral_face::neutral_face::neutral_face::neutral_face:
お...俺じゃ無いんだ...これを書いたのは...

# 結論
enumを使えるのは整数型のカラムだけ！
別のカラムを追加して確認してみたりすると気付けるぞー。
ESP32で時刻同期出来ない時は、IP V6応答になってないか確認

### 概要
ESP32＋nuro光でconfigTimeで時刻同期しようとしたら失敗。
NTPサーバにpingしたら、IP V6応答になっていたので、V4応答するものだけを残せばOKだった

### 環境
- nuro光 - HG8045D(純正ルータ) - TP-Link Archer AX20
- ESP32 

https://amzn.to/3ymvszr

- Arduino IDE 1.8.19


### いきさつ
ESP32で時刻同期するため、configuTimeを以下HPのソースで実行した結果

https://www.autumn-color.com/archives/839

時刻同期が成功しない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436645/a10d7f15-f4f0-1908-bead-27580d214de5.png)


#### 切り分け
- ocn mobile one テザリング/android　⇒　問題なし
- au テザリング/iphone ⇒問題なし

nuro光接続PCでping ⇒　ntp.nict.jpはIP V6応答
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436645/f001b2fe-404e-fab9-5278-eedf0d764fc8.png)

ntp.jst.mfeed.ad.jp V4応答
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436645/7910266b-c9d3-afd1-46ff-3978014d4b0c.png)

### 対応
ntp.nict.jp　を消して、ntp.jst.mfeed.ad.jpだけにした⇒〇
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436645/a7bd7d74-ca7b-1acf-47ab-808f5bf5cda5.png)


今回はルータの設定変更などの対応は行ってません。ご参考まで
nvm useでバージョンが切り替わらない（windows環境）

# nvm useでバージョンが切り替わらない（windows環境）

## 経緯
- 元々nodeバージョン16.16をインストール済み
- nodeバージョン12.22.3を使用する必要ことになった。
- nodeバージョン管理ツール**nvm-windows**をインストール。インストール方法の参考サイト（[nvm-windows の導入と簡単な操作をやってみた](https://qiita.com/akipon0821/items/eaeffe79221cfcd4d258)
- **nvm-windows**インストール後、再起動が必要ヨ！
- `nvm install 12.22.3`でnodeバージョン12.22.3をインストール。
- しかし、`nvm use 12.22.3`でバージョンの切り替えができない。

#### 具体的なエラーメッセージ

```cmd
C:\Users\atom>nvm use 12.22.3
exit status 5: ・A・N・Z・B・・・・・・・・・B
exit status 1: ・・・a・・・・・・・t・B・・・・・・低・・・B
```

### 環境変数

調べると`NVM_HOME`や`NVM_SYMLINK`の環境変数がシステムプロパティに設定されているか確認せよ、とのアドバイスが多い。しかし最近のnvm-setup.exe（ここではバージョン1.1.9を入れた）でインストールし再起動もしたならば、ほとんどの場合ここは問題ない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/ec91fb43-d2ee-4bc3-78d1-77be63829aee.png)

## 解決方法

簡単です。コマンドプロンプトを管理者モードで立ち上げ、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/b727af55-4430-222b-5d3b-5f1f695193eb.png)

管理者モードコマンドプロンプトであれば、nvm useが可能となる。

```cmd
C:\WINDOWS\system32>nvm use 12.22.3
Now using node v12.22.3 (64-bit)

C:\WINDOWS\system32>nvm list

    16.16.0
  * 12.22.3 (Currently using 64-bit executable)
```

以上です。



<br />




<br /><br />
git-credential-manager 影響下で git-remote-codecommit を使うと「配列の範囲が無効です」エラーが出る

# 症状

WSL2 の Ubuntu 環境で陽気な開発作業をしていて、GitHub と AWS CodeCommit を両方使っています。認証情報をいちいち入力したくないので、GitHub では (Git for Windows 同梱の) git-credential-manager ~~-core~~ [^2]を、CodeCommit では [git-remote-codecommit](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-git-remote-codecommit.html) を使うことにします。


git-remote-codecommit は基本的に pip でインストールするだけで設定は要らない[^1]ので、 git-credential-manager ~~-core~~ だけ [Linux 用 Windows サブシステムで Git の使用を開始する - Microsoft Ignite](https://learn.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-git) などの記事を参考に

```bash
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe"
```

と設定しました。

GitHub の pull/push はこれで全然問題ないのですが、CodeCommit (GRC 形式の URL) の pull/push しようとすると、できることはできるものの毎回心臓にわるいエラーメッセージが表示されます。

```text
fatal: Failed to write item to store. [0x6c6]
fatal: 配列の範囲が無効です。
```

# 解決

git-credential-manager ~~-core~~ 影響下で git-remote-codecommit を使うのがよくないようです。ので、 git-credential-manager ~~-core~~ は GitHub にアクセスするときだけ効くように

```bash
# さっき追加したすべての URL に効く credential.helper は削除
git config --global --unset credential.helper
# git-credential-manager は GitHub だけに限定する
git config --global credential.https://github.com.helper "/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe"
```

とすることで、エラーメッセージから解放されました。

`~/.gitconfig` の内容はこんな感じです(user 部分は例です)。

```text
$ cat ~/.gitconfig
[user]
        name = Taro Qiita
        email = taro-qiita@example.com
[credential "https://github.com"]
        helper = /mnt/c/Program\\ Files/Git/mingw64/bin/git-credential-manager.exe
```

[^1]: AWS のアクセスキーなどの認証情報の設定はもちろん必要です。
[^2]: [git-credential-manager-core は git-credential-manager に改名された](https://opcdiary.net/git-credential-manager-core-%E6%94%B9%E3%82%81-git-credential-manager%E3%81%B8/) そうなので、こちらの記事にも反映しました。Git for Windows の今日現在の最新版 2.39.0.2 では -core 付き/ -core なしの両方が入っていますが、-core 付きのほうを使うと `warning: git-credential-manager-core was renamed to git-credential-manager` と警告が出ます。
【TypeScript】 const var letの3つの宣言方法について調べてみた

# 変数宣言とは？？
`変数宣言とは、コンピュータプログラムのソースコード中で、これから使用する変数の名前を宣言し、値を格納するための記憶領域を確保させること。プログラミング言語によって要不要や方法は異なる。`
参考：https://onl.bz/vri1Ygt
だそうです。

## なぜ調べようと思ったか？？
私は今までほとんどの変数宣言を`const`で書いていた。
なぜかというと、どこかのサイトで`大体の変数宣言はconstでいけるよ～`的な記事を見たからである。

そして、数字をカウントするために以下のコードを実行したときにエラーが出た。
```typescript
const count1:number = 0;
count1++;//Cannot assign to 'count1' because it is a constant.
console.log(count1);
```

他の二つの宣言方法だと普通に+1される
```typescript
let count2:number = 0;
count2++;
console.log(count2);//1

var count3:number = 0;
count3++;
console.log(count3);//1
```

## エラー文を見てみる
エラー文は`Cannot assign to 'count1' because it is a constant.d`
日本語に直すと`count1' は定数なので代入できません`である

* じゃあ定数ってなに？？
① 一定の数。きまっているかず。規則などできめられた人数。
② 定まった運命。命数。
参考：https://kotobank.jp/word/%E5%AE%9A%E6%95%B0-6056
字の通り`定まった数`という意味を持っているようです
(constantも同じ意味)

## つまり？？
**const**で宣言した値は更新することができない（再代入できない）
→count++しても値を更新することはできない

* string型でも同じエラーが出力される
```typescript
const text:string = 'abc';
text = 'def';//Cannot assign to 'text' because it is a constant.
```

# 本題：const,var,letの違い
本題のconst,var,letの違いを簡単に確認すると
1. **const**→ほとんどの変数宣言はこれでOK!
1. **var**→古いからあんまり使わない
1. **let**→数え上げなど再代入する際に使う
ほかにも、再宣言やスコープなどの違いがあるそう
↓の記事が分かりやすかったので載せておく
【JavaScript】var / let / const を本気で使い分けてみた：https://qiita.com/cheez921/items/7b57835cb76e70dd0fc4
Flutterのバージョン比較をするメソッド


##　背景

Flutterで、アップデートを判定したり、OS判定をしたりするのに最初は`double.parse()`でやっていたが、
アプリバージョンなどは`1.0.1`とかなのでパースもうまくいかない。

せっかくなら、OSもアプリバージョンも一緒に比較できるようにと思い実装してみました。

## 実装イメージ
1. 比較対象の数字をそれぞれ、0埋め６桁の数字（文字列）にする
2. `int.parse()`をして整数化する
3. 比較をしてバージョン判定を行う

## 使ったメソッド
0埋めしたり、特定の文字で埋めたいときは[padLeft](https://api.dart.dev/stable/2.18.1/dart-core/String/padLeft.html), [padRight](https://api.dart.dev/stable/2.18.1/dart-core/String/padRight.html)という便利な関数がdartにはありました。


### 使い方

padLeft, padRightメソッドは、`String.padLeft(何文字にするか, '埋めたい文字');`のように指定します。

```dart
final String text = 'AAA';
debugPrint(text.padLeft(5, 'X'));
// XXAAA : ５文字になるように左がXで埋められます。
```

## 実装
### バージョンを整数６桁に変換するメソッド
```dart
int formatVersionNumber(String version) {
  // 集計用変数
  String tempValue = '';
  // ピリオドで分割する
  final List<String> versionNumbers = version.split('.');
  // 配列の個数で識別
  // ex.) version 15 => '150000' => 150000
  if (versionNumbers.length == 1) {
    tempValue = versionNumbers.first.padRight(6, '0');
  }

  // ex.) version 8.5 => '080500' => 800500
  if (versionNumbers.length == 2) {
    versionNumbers.asMap().forEach((int index, String value) {
      tempValue += value.padLeft(2, '0');
    });
    tempValue = tempValue.padRight(6, '0');
  }

  // ex.) version 1.0.1 => '010001' => 10001
  if (versionNumbers.length == 3) {
    versionNumbers.asMap().forEach((int index, String value) {
      tempValue += value.padLeft(2, '0');
    });
  }

  return int.parse(tempValue);
}
```
### 上記フォーマットを用いて、比較するメソッド
```dart
bool compareVersionNumber({
  required String baseVersion,
  required String targetVersion,
}) {
  return formatVersionNumber(targetVersion) >=
      formatVersionNumber(baseVersion);
}
```

### 使い方
```dart
void main() {
  
  String version = '8.1';
  String version2 = '12.20.11';
  
  int appVersion = formatVersionNumber(version);
  int deviceVersion = formatVersionNumber(version2);
  
  print('appVersion $appVersion'); // appVersion 80100
  print('deviceVersion $deviceVersion'); // deviceVersion 122011
  
  final result = compareVersionNumber(baseVersion: '8.0', targetVersion:'8.1');
  print(result);
}

```

以上です！小ネタでした。

#### Github
https://github.com/kurogoma-flutter/dart_version_format/blob/main/README.md
MacにJDKをインストールする

## はじめに
こんにちは、今年（2022年）の11月からSES企業に勤めることになりました。
入社予定の会社では主にJavaを使用するということで、言語習得や資格取得に向けて頑張っています。
本記事では、MacでJavaの勉強するためにJDKをインストールするため少し手間取ったので忘備録として残しておきます。

## JDKをインストールする
インストールは下のOracle公式ページから行えます。
https://www.oracle.com/java/technologies/downloads/#java17
開くと、こんなページに飛びます。
![スクリーンショット 2022-10-06 16.14.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759696/65d67593-5497-9ff4-9bdc-334526a54b3b.png)

### 1. バージョンを指定してダウンロードする
上で開いたページでスクロールすると、少し下の方に↓のような画面が出てきます。
![スクリーンショット 2022-10-06 16.16.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759696/29a2bd55-5610-22b2-39ca-5c94aecb44b9.png)
任意のバージョンでクリックし、Arm 64 DMG Installerのダウンロードリンクをクリックすると、ダウンロードが始まります。（３０秒くらいでダウンロードが完了します。）

### 2. 解凍してダウンロードを完了させる
ダウンロードが完了したことを確認したら、クリックして開くと以下のようなファイルが開きます。
![スクリーンショット 2022-10-06 16.26.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759696/cd9d02df-2d1e-912b-97f8-81800ed9f17f.png)
赤枠のファイルをダブルクリックすると、以下のようなウインドウが開きます。
![スクリーンショット 2022-10-06 16.28.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759696/ac9a8131-eceb-0d3a-919f-4e1d88e916fe.png)
そのまま続けるボタンを押し続けると、あっさりインストールが完了します。
![スクリーンショット 2022-10-06 16.30.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759696/0c44aa64-77c0-48bb-1b93-ebc78d45e4cc.png)
このまま閉じるボタンを押すと、「インストーラーをゴミ箱に入れますか？」と聞かれます。「はい」で大丈夫です🙆‍♀️
### 3.インストールできたか確かめる
Macのターミナルを開き、以下のコマンドを実行してください。
```
~ % javac -version 
~ % java -version
```
１行目のコマンドでは、１行の結果が、２行目のコマンドでは３行くらいの結果が出てきると思います。
自分がインストールしたバージョンの数字とあっていればインストールできています。

## 終わり
これでJavaを勉強する土台を作れました！！
【kotlin】サブディレクトリのリストを作成日時昇順・降順で並び替える


```kotlin
/**
 * サブディレクトリを作成日時で昇順に並び替える
 */
fun Path.sortDirectoriesByCreationDateInAscendingOrder() =
    listDirectoryEntries().filter { it.isDirectory() }
                          .toList()
                          .sortedBy {
        Files.readAttributes(it, BasicFileAttributes::class.java).creationTime()
    }

/**
 * サブディレクトリを作成日時で降順に並び替える
 */
fun Path.sortDirectoriesByCreationDateInDescendingOrder() =
    listDirectoryEntries().filter { it.isDirectory() }
                          .toList()
                          .sortedByDescending {
        Files.readAttributes(it, BasicFileAttributes::class.java).creationTime()
    }
```

## example

```kotlin
fun main() {
   Paths.get("parent").sortDirectoriesByCreationDateInAscendingOrder().forEach {
        println(it)
   }
}
```
ローカルからEC2にファイルをアップロードしたい

#  ローカルからEC2にファイルをアップロードしたい
(windows環境)
丁寧に解説。
<br>
<br>

●EC2インスタンス起動しTeratermでリモートSSH接続しておく。
●デスクトップ等に任意の転送テストファイルを用意。

ローカルのコマンドプロンプト画面等で以下入力し実行するだけ：
```
scp -i <pemファイルのパス> <送信するファイルのパス> <送信先ホスト>:<送信先パス>　
```
やってみる

●ローカルPCのpemファイルのパスを確認：
例：今いるディレクトリ(仮にデスクトップにいるとして)にpemファイルと送信するファイルの両方を用意した場合↓
```
keyPairName_My.pem
```
<br>
<br>

●送信するローカルファイルのパスを確認：
今いるディレクトリ(仮にデスクトップにいるとして)にpemファイルと送信するファイルの両方を用意した場合↓
```
My.txt
```
<br>
<br>


●送信先ホストと送信先パスを確認：
今回の様にリモート側のpublic IP アドレス確認方法はTeraTerm画面で
```$ ec2-metadata```でIPv4の欄に表示される。
送信先のパスは任意のディレクトリに用意。
```
ec2-user@01.23.456.789:/home/ec2-user/test
```


<br>
<br>


コマンド組み立て↓

コマンド例：
```
scp -i keyPairName_My.pem My.txt ec2-user@01.23.456.789:/home/ec2-user/test
```

<br>
<br>

Teraterm画面を見て転送されたかを確認する。成功。

考え方としてEC2にTeratermでリモートssh接続している状態(SSHがアクティブ)を前提として
ローカルのWindowsPCのコマンドプロンプトやパワーシェルではEC2へアップロードできるのであれば
逆にEC2にssh接続しているTeratermのリモート画面ではダウンロードができる？
ASUSノートPCで0x8007003bが発生しましたが、解消しました

# はじめに
先日、ASUSのノートPCを購入しましたが、Wi-Fiの通信が遅く、また、NASへの書き込みにおいて0x8007003bのエラーが発生しました。
解消しましたので、解消までの経緯を残したいと思います。

# 環境
Windows
　ASUS ROG Flow X13 GV301QH
　OS           Windows 10 Pro 21H1
　　osビルド 19043.2006
　CPU         AMD Ryzen 9 5900HS with Radeon Graphics  3.30 GHz
　MEM       32.0 GB
　HDD        WDC SN530 SDBPTPZ-1T00-1002
　　フォーマット NTFS
　無線LAN  Intel(R) Wi-Fi 6 AX200 160MHz

NAS
　I-O DATA HDL-AA3
　システムのバージョン 1.11

# 発生事象詳細
・NASからの読み込みはできる。書き込みにて通信速度が非常に遅く、しばらくすると通信速度が0になる。
・当該PCからNASへの書き込みは前述の通りであるが、他のPCからWi-Fiでの書き込みは高速に行われ、成功する。
　⇛NASが壊れたわけではないことが確認できた。
・当該PCの通信内容をWireSharkで通信内容を調べたところ、大量のエラーが出力される。
・デバイスマネージャにエラー表示は出ていない
・NAS側にユーザは1人しか登録しておらず、他のPCと当該PCはNASのユーザを共有しているそのため、当該PCでNASから読み込めるということはアクセス権限で失敗しているわけではない。
・有線LANアダプタを当該PCに接続して、NASへ書き込み、成功することを確認。
　⇛一部の記事で、NAS側のフォーマットとPCのフォーマットが相違していると当該事象が発生するとの記載があり、これに該当するのであれば有線LANでもエラーがは出るはずという事の確認。
・当該PCから他PCの共有されたフォルダに書き込みしたところ当該事象が発生することを確認。

# 参考記事
  参考にさせていただきました。ありがとうございました。
  https://qiita.com/snkimu/items/18352a9e5f3dcdb2d67b

# 対応内容（その１）
  ①参考記事のページに有るようにレジストリを修正し、タイムアウトを300秒に変更
　⇛エラーになるまでの時間は長くなるものの、通信速度は改善せず。
  ②Wi-Fiのドライバを最新にアップデート。
  ③MTUが当該PCとNAS側で同じであることを確認。

# 原因の考察
発生事象を基に検討したところ、原因は当該PCであると判断しました。
またおそらくWi-Fi周りの不具合ではないかと予想しました。
とはいえドライバは最新にしており、Windows側からは有線LAN,無線LANとも同じNWカードとして認識されているはずです。
残るはWi-FiカードのAX200自体の不具合となりそうです。
「ハズレ引いたかなー」と考えていたのですが、ふと、そういえば昔、PCを省電力モードで動かすと不具合が起きる機器があったということを思い出しました。
ASUSのノートPCについてきたツールに「Armoury Crate」というものがあり、それを起動し、状態を確認しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630870/f1a132c2-490d-7e8b-5a86-b40b450a4cd0.png)
現状「サイレント」になっていたので、「パフォーマンス」に変更し、再試験しました。
予想通り、通信速度は改善し、0x8007003bも発生しませんでした。
・
・
・
が、うるさい。

# 対応内容（その２）
一応解決しましたが、うるさいですし、電池の持ちも悪そうです。
他の方法を探していたら、解決手段を見つけました。

同じくASUSのツール「GameFirst VI」を入れたところ解決し、「サイレント」に戻しても通信速度が改善したことを確認しました。

# GameFirst VI 導入手順
①「Armmoury Crate」を起動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630870/62dbbdf8-47ba-8e52-04f1-432e22a14c65.png)

②左側のメニューから「シナリオプロファイル」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630870/445ea0bd-a59c-0e1e-d351-bf5d76b6b516.png)

③「アプリ設定」の「GameFirst VI」よりインストールを行う。
　※当方のPCは導入後ですので記載がないですが、導入前であれば「インストール」の表記になります。

# 最後に
ASUSのノートPCの不具合がASUSのツールを導入したことにより解消したということが腑に落ちませんが、一応解消しました。
購入した直後から当該PCのWi-Fiが遅いような気がしていたのですが、それも解消しました。
解決はしたのですが、やっぱり納得いかんなぁ。
vscodeでrubocopを使ってrubyをフォーマット（mac編）

vscodeでrubocopを使って
rubyを「適当」にフォーマットしたい！
だけなのに困ったのでメモメモ。

## rubocopをインストール

rubocopは単なるフォーマッターではなく、
コードの問題点を多角的に分析してくれます！
・・・でも今はとりあえずフォーマットしたい！
余計なことはいらないんだ！

- vscodeの拡張機能`ruby-rubocop`を
インストールしましょう。

- 以下のコマンドを実行して`rubocop`の
gemパッケージもインストールしましょう。

```shell
gem install rubocop
```

## vscodeの設定

rubyファイルは`option + shift + f`で
rubocopにフォーマットしてもらいますよ、
とvscodeに教えましょう。

- 設定画面右上のアイコンから`settings.json`を
開いて、以下を追記しましょう。

```json
    "[ruby]": {
        "editor.defaultFormatter": "misogi.ruby-rubocop"
    }
```

この状態で`option + shift + f`すると、
フォーマットされるけど大量の警告表示が！！

## .rubocop.ymlを書く

rubocopは`.rubocop.yml`という設定ファイルで
その挙動を制御できます。

- `vi ~/.rubocop.yml`で
ユーザーフォルダ直下にファイルを作成し、
`i`キーを押して編集モードにして、以下をコピペしましょう。

```yaml
AllCops:
  DisabledByDefault: true
  NewCops: enable
  DefaultFormatter: progress

Layout:
  Enabled: true
```

- そのまま`esc`キーで編集モードを終了して、
以下のコマンドで保存して終了しましょう。

```shell
:wq
```

- フォーマットしたいファイルを変更（インデントを崩すなど）して、
再度`option + shift + f`すると、警告は表示されず、
フォーマットのみが実現できるはずです。

## 終わりに

`DisabledByDefault: true`によって一旦すべての
機能を抑止して、`Layout`のみできるようにしました。

ここから段々と設定ファイルを育てていくことをお勧めします。

設定内容は公式を読んでみましょう！

https://docs.rubocop.org/rubocop/configuration.html
【BigQuery】WindowFrame句省略時の挙動まとめ

# はじめに
ウィンドウ関数における `Window Frame` 句は省略時の挙動が場面によって変わります。
場面に合わせて最も適していそうなものになっているようですが、ちゃんと理解せずにいたら少し混乱したのでまとめました。
BigQuery以外のDBMSでも同じかもしれませんが、検証していないのでBigQueryについてのみ書きます。

`Window Frame` が何かという部分については当記事では扱いません。
「ウィンドウ関数（分析関数）を何となく使っているけど、 `ROWS BETWEEN〜` の部分の動作がイマイチわかってない」という方向けです。

# 定義
定義自体はシンプルで、以下の2パターンです。

## ウィンドウ指定内に `ORDER BY` 句が存在しない場合
下記の指定を行ったのと同じ動作となります。
```sql
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
```

つまり
```sql
COUNT(*) OVER()
```

は、以下と同じです。
```sql
COUNT(*) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
```

## ウィンドウ指定内に `ORDER BY` 句が存在する場合
下記の指定を行ったのと同じ動作となります。
```sql
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
```

```sql
COUNT(*) OVER(ORDER BY foo)
```

は、以下と同じです。
```sql
COUNT(*) OVER(ORDER BY foo RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
```

:::note inro
ソート順を指定すると集計範囲が現在行までになる
:::

# 検証
## `ORDER BY` 指定なし
下記SQLで動作検証を行います。
```sql
WITH values AS (
  SELECT 
    val
  FROM
    UNNEST(GENERATE_ARRAY(1, 5, 1)) AS val
)

SELECT 
  *,
  COUNT(*) OVER w AS cnt
FROM
  values
WINDOW w AS ()
```

### 実行結果
|val|cnt|
|--:|--:|
|1|5|
|2|5|
|3|5|
|4|5|
|5|5|

全てのレコードが集計対象となるので、`COUNT()` の結果は全行 `5` になります。

## `ORDER BY` 指定あり
上記SQLに `ORDER BY` を追加しました。
```sql
WITH values AS (
  SELECT 
    val
  FROM
    UNNEST(GENERATE_ARRAY(1, 5, 1)) AS val
)

SELECT 
  *,
  COUNT(*) OVER w AS cnt
FROM
  values
WINDOW w AS (ORDER BY val)
```

### 実行結果
|val|cnt|
|--:|--:|
|1|1|
|2|2|
|3|3|
|4|4|
|5|5|

以下の動作となっています。
- `val = 1` のレコードを処理時は、同レコードのみが集計対象となるので、 `COUNT()` の結果は `1` になる
- `val = 2` のレコードを処理時は、 `val = 1` と `val = 2` のレコードが集計対象となるので、 `COUNT()` の結果は `2` になる

ソート順を追加したのみですが、集計対象まで変わってしまうので要注意です。 

## 関数呼び出し箇所で `ORDER BY` 指定
名前付きウィンドウの方では `ORDER BY` を記載せず、関数呼び出しの方に記載すると、ソート順を指定した関数のみ集計対象が変わります。

```sql
WITH values AS (
  SELECT 
    val
  FROM
    UNNEST(GENERATE_ARRAY(1, 5, 1)) AS val
)

SELECT 
  *,
  COUNT(*) OVER (w) AS cnt1,
  COUNT(*) OVER (w ORDER BY val) AS cnt2
FROM
  values
WINDOW w AS ()
```

### 実行結果
|val|cnt1|cnt2|
|--:|---:|---:|
|1|5|1|
|2|5|2|
|3|5|3|
|4|5|4|
|5|5|5|


# 混乱を招く要因
最初に書いた通り、定義自体は2パターンで特にややこしいということはないです。
それなのに、初学者が集計関数、ナビゲーション関数について都度調べていると混乱することも多そうです。

その理由は、「主なナビゲーション関数は `ORDER BY` 指定が必須である」ということにあると思います。
例えば、 `LAST_VALUE()` について解説した記事には下記のように書いてあったりします。

> `LAST_VALUE()` の定義は下記です。
> ```sql
> LAST_VALUE(foo) OVER (ORDER BY bar)
> ```
> 集計範囲を省略すると `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW` となり、現在行までが対象となります。
> 全ての行を対象にする場合は `ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING` と書く必要があります。

大元の定義を知らずにこれを読むと、「集計範囲を省略すると現在行までになるのか」と誤解する可能性があります。
`LAST_VALUE()` は必ずソート順を指定するので、 **結果的に** 現在行までが初期値にはなるのですが。

一番の要因は [BigQueryのマニュアル](https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls#def_window_spec) が分かり辛すぎることですけどね。
LINE × GAS｜Googleカレンダーの予定をLINEに通知

:::note warn
本記事に記載のコードの中身については、全てを1から私が記載したわけではありません。あくまでも参照元に倣って自分でも作ってみて、一部改造を記録した記事です。
詳細は参照記事をご覧ください。
:::

# ゴール・完成形

▼構成イメージ
![Untitled__Online_Whiteboard_for_Visual_Collaboration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/7acc9966-316d-b306-d50c-c471796a7bc0.png)


<details><summary>コード</summary>

```js:notify_Today_Schedule.gs
// スクリプトプロパティのオブジェクトを取得
  const prop = PropertiesService.getScriptProperties().getProperties();
  var LINE_NOTIFY_TOKEN = prop.LINE_TOKEN;
  var LINE_NOTIFY_API = "https://notify-api.line.me/api/notify";


function calendarToLine() {
  var calendars = CalendarApp.getAllCalendars();
  var text = Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + "\n";

  for(i in calendars) {
     var calendar = calendars[i];
    var events = calendar.getEventsForDay(new Date());
 
    //カレンダー名を取得する
    if( events.length > 0 ) {
      text += "■ " + calendar.getName() + "\n";
    }
    
    //カレンダーの内容を取得する
    for(j in events) {
      var event = events[j];
      var title = event.getTitle();
      var start = toTime(event.getStartTime());
      var end = toTime(event.getEndTime());
      text += start + ' - ' + end + " " + title + '\n';
    }
 
    if( events.length > 0 ) {
      text += "\n";
    }
  }
 
  sendToLine(text);//LINEにデータを送信する
}
 
//LINEにデータを送信する
//text:送信するデータ
function sendToLine(text){
  var token = LINE_NOTIFY_TOKEN;
  var options =
   {
     "method"  : "post",
     "payload" : "message=" + text,
     "headers" : {"Authorization" : "Bearer "+ token}
 
   };
   UrlFetchApp.fetch(LINE_NOTIFY_API, options);
}
 
//'HH:mm'に変換する
function toTime(str){
  return Utilities.formatDate(str, 'JST', 'HH:mm');
}
```

</details>

<details><summary>スクリプトプロパティ</summary>

![Gカレの内容をLINE通知_-_プロジェクトの設定_-_Apps_Script.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/314f9fac-5fd0-eeee-db71-b8589f38b217.png)

</details>


# 感想・今後の展望
- 改造してオリジナリティを出したかったけど、参照先の内容が完成されすぎて、改造ができなかった。
- あ〜、予定の取得だけでなく、予定変更があったときに変更内容をLINEに通知できたらもっと便利かも。


# 参照

https://technical.verybestcbp.com/calendertoline/#toc8
個別のオブジェクトのまとめ

こちらにはあんまり使わないオブジェクト固有の情報を整理しておきます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/054b2dfa-6b01-deff-bc77-14e4462c76ad.png)


# A

+ [AuraDefinitionBundleとAuraDefinitionとの子リレーション名](https://qiita.com/Keiji_otsubo/items/42820a157f0385efc14e)

### Account Plan objects

:::note
質問自体を消されている

By default, only Salesforce admins can access the sales account plan objects. 

Select Who Can Use Sales Account Plans
https://help.salesforce.com/s/articleView?id=sales.account_plans_setup_assign_users.htm&type=5

Turn on Sales Account Plans
https://help.salesforce.com/s/articleView?id=sales.account_plans_setup.htm&type=5
 :::

# C

+ [create object from spreadsheet でアップロードできない](https://qiita.com/Keiji_otsubo/items/97b018c63fc8a310d4c9)

# E

+ [資格(Entitlement)オブジェクトをレコード リストとして選択できません](https://qiita.com/Keiji_otsubo/items/522f2ade9d2d9219abf4)
+ [エンタイトルメント管理の制限事項](https://help.salesforce.com/s/articleView?id=sf.entitlements_best_practices.htm&type=5)

# F

+ [FeedItem のまとめ](https://qiita.com/Keiji_otsubo/items/cc8e2a0ec812112292e8)

# N

+ [Pin Notes to Top of Notes List View アイデア](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000OrrXr)
+ [transfer note](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A8hF1)


# T

+ [Anyone who has dealt with "Territory2" Object](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000O5ntt)

# V

+ [Virtual Remote Assistant/ Scheduler　というオブジェクトのレポートを作る](https://qiita.com/Keiji_otsubo/items/2863399bd4a071a986c6)


# W

**Work Order**

+ [作業指示品目オブジェクトのクイックアクションとして Lightning Web コンポーネントを追加する](https://qiita.com/Keiji_otsubo/items/e6002bdf76bad92674b9)
+ [作業指示のカスタムアクションが強調表示パネルに表示されない](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ifhXaSAI)

ページレイアウトではできない。動的アクションにアップグレードし手動で追加


# 削除されたカスタム オブジェクト レコードは引き続きストレージ制限にカウントされます

+ [Deleted custom object records still counted against storage limit](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000GzlAy)

カスタムオブジェクトが削除され、ごみ箱からも削除された場合、オブジェクトは組織内のどこにも表示されませんが、それでもストレージ使用量はオブジェクトがメモリを消費していることを示しています。

すでに削除されたオブジェクトのレコードの一意の ID が必要になるため、データローダーからでもそのオブジェクトに関連付けられたデータを削除することはできないと思います。
MacのiMessageでSMSを受信する方法

今回はMacのiMessageでMacのiMessageでSMSやMMSの受信する方法を説明します。

# Step1

MacのiMessageにiPhoneと同じApple IDでログインする。

# Step2

iPhoneの設定で「メッセージ」を開き、SMS/MMSの転送という部分を開きます。
ここで転送したい端末にチェックを入れる。

### はい終わり！
今回は非常に簡単でしたね。

今は2段階認証などによりSMSの需要が上がっているので、今回の方法を抑えてワンタイムパスワードなどをわざわざiPhoneを使ってなんてしないようにしよう！
mds_stores暴走のお話

先日Mac（2020 MBA）を使っていてmds_storesというプロセスが暴走したので対策法？を紹介します。

備忘録的な形なので、詳しい方がいれば教えてください。

# 対処法1

1. ゴミ箱を空にする。
2. 再起動する。

以上です。

# 対処法2

索引を一度オフにする。
※OFFにしたままだと、アプリケーションの起動がSpotlightからできなくなる。

```
# off
sudo mdutil -a -i off
# on
sudo mdutil -a -i off
```
ffmpegとSpeech-to-Textで動画の文字起こしをしてみる

# やりたいこと
「動画データ⇒音声データ抽出⇒自動で文字起こし」をやってみたい。

※細かい設定とか背景とかは置いておいて、
　とりあえず試してみたい！というモチベーションでやってます。
　色々説明不足な点があるのは悪しからず。

## きっかけ

* 社内の有志による活動でAIを使った何かをやりたい
* Teams会議の文字起こしツールを作ってみるかという話に（Teamsにも文字起こし機能はありますが、、、）
* 調べるとGCPの機能だけでできそうな感じだった
　
⇒やってみよう！


## 環境
* OS: Ubuntu 20.04.4 LTS
* Python: 3.8.8


## やりかた

1. **Speech-To-Textを使用する方法**
⇒まず最初に思いついた方法。
2. Cloud Video Intelligence APIを使用する方法
⇒調べたら動画から直接文字起こしする方法があった、、

今回は「**Speech-To-Textを使用する方法**」について紹介します。
~~「Cloud Video Intelligence APIを使用する方法」の記事は[こちら]()~~ 現在記事作成中。

## 準備
　1. GCPのコンソールにログインしてプロジェクトを作成
　2. GCSのバケットを作成しておく

※ググったらやり方出てくるので詳細は割愛。

# 動画の文字起こしをする

## 手順

1. 動画データ(mp4)を音声データ(wav)に変換する
2. 音声データをSpeech-To-Textでテキストに変換する

## 動画データ(mp4)を音声データ(wav)に変換する

ffmpegのインストール

```
$ sudo apt-get update
$ sudo apt-get -y install ffmpeg
```

## ffmpeg-pythonのインストール

```
$ pip install ffmpeg-python
```

## 動画データ(mp4)を音声データ(wav)に変換

```
$ python
>>> import ffmpeg 
>>> stream = ffmpeg.input("myVideo.mp4")
>>> stream = ffmpeg.output(stream, "myAudio.wav") 
>>> ffmpeg.run(stream)
```

## 音声データをGCSにアップロード

GCPのコンソール上から簡単にアップロードできる
※もちろんコマンドラインからでも可

↓アップロード成功すると、こんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204121/419bafe8-2c61-ea22-c549-6a01c54bb540.png)

## いざ、Speech-to-Text

手順

1. Speesh-to-Textの「New Transcription」から新しいTranscriptionを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204121/53a59126-35d6-30f6-1e02-fc6efd060faa.png)

2. Audio ConfgurationでCloudStorageから音声ファイルを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204121/cd1532c2-ceb1-fbea-0636-84824c37726c.png)

※残りの設定はアップロードしたファイルに合わせて自動で設定される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204121/3e1050c7-8b74-210d-c57c-100d0504bd1e.png)

3. Transcription optionsで言語を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204121/8200b0b2-91bd-3a2f-bf71-f78b4ce09c60.png)

4. 送信
※Model adaptationは試してないので詳細は割愛
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204121/117d93da-c00f-a1f4-571c-5e1d05f2249f.png)

## 結果

翻訳が終わるとテキストが出力される。CSV形式でDLも可能。

## 所感

* 機械学習に関する知識はほぼ使わずにできた。
* ちゃんとパイプラインを組めば、動画をアップロードから
テキスト取得までのワークフローも自動化できそう。
* 取得したテキストは正確ではないが何について話しているか何となく把握できるレベル。
※議事禄にするにはまだ精度が足りなそう、、、

# 参考記事
* [ジコログさんの記事](https://self-development.info/%E3%80%90%E7%B0%A1%E5%8D%98%E3%80%91python%E3%81%A7%E5%8B%95%E7%94%BB%E3%81%8B%E3%82%89%E9%9F%B3%E5%A3%B0%EF%BC%88mp3%E3%83%BBwav%EF%BC%89%E3%82%92%E6%8A%BD%E5%87%BA%E3%81%99%E3%82%8B%E6%96%B9/)
ffmpegインストールと実行の部分のコードを参考にさせて頂きました。
ER図やREADMEを用いたテーブル設計

# はじめに
これらは、テーブル設計を行う際に、自分が忘れがちな内容を忘れないように記録する記事です。

## テーブル設計の流れ
### ①テーブルのエンティティ(保存するデータ)を洗い出す。
### ②ER図を書き出す。
VSCodeの拡張機能「Draw.io Integration」や「Lucidchart」などがあるので、自由にツールは導入して良い
今回は、VSCodeの拡張機能で「Draw.io Integration」と検索してインストールした。

アプリケーションファイル内に<strong>拡張子[.dio]</strong>で新規ファイルを作成する。
作成したファイル内にER図は書き込める。

### ③作成したER図をもとにREADMEにテーブル設計を正書する。
マークダウン記法を用いて書く。
学習リモコンを購入してみた

Amazonで500円くらいの学習リモコン(L336)を購入してみました。

とりあえず、三菱のディスプレーとONKYOのCDプレーヤー、FPGA FMチューナのON/OFFに使っているSONYのタイマーと自作の選局モジュール用のSONYのTVの信号を収納してみました。

![L336(1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d98ff60f-c281-fe6f-59da-284de73c70bf.jpeg)

設定は３セット（ページ）持つことができ、上部の青いボタンで選択します。

登録は、上部の青いボタンのどれかを長押し->インジケーターが明るく点灯->設定するボタンを押す->インジケーター点滅->信号送受信->学習できると点滅から点灯に変わる->登録を続ける場合は設定するボタンを押して繰り返し、終る場合は上部の青いボタンを押す

学習リモコンのメリットは一つでいろいろ制御できるということと、電池が節約できます。またリモコンは使ってないと、ボタンの反応が悪くなったり、電池が液漏れしたりすることがあるので、この点でもよいです。

リモコンは電池が切れた状態で長期間放置すると液漏れして、壊れてしまうことが良くあります。使わないのであれば電池を抜いておくのが賢明です。

リモコンの信号も強く4mくらい離れてもちゃんと制御できています。

スマホのアプリで赤外線リモコンを制御するような製品もありますが、すぐつかえる棒の方が便利な気がします。

我が家はインターネットが消滅しても自立して機能するようにしているのでAlexaなどは論外です。

SONYのタイマーがコンデンサーの液漏れで壊れて直したのですが、またおかしくなったので、あきらめて購入しました。学習は自作のMacアプリのアルマジロのお使いで信号を出してしました。

そもそもタイマーとしては使ってなくて、たまに使うON/OFFのためだけに単三３本は無駄でした。

昔はクロッサムというHAL研究所が出していた学習リモコンをつかっていたのですが、これも壊れて使えなくなりました。

L336はボタンを押して信号送信時にインジケーターが点灯するので、分かりやすいと思います。

はめ込みで作られているので、分解を躊躇したのですが、すでにいろいろ調べている人がいました。

https://goughlui.com/2020/10/11/review-teardown-l336-learning-infrared-remote-control-reviving-a-dead-remote/

学習データはEEPROM(128Kbit)に入れているようです。なので、電池をぬいても学習データはなくなりません。また学習時の受光は受光モジュールは使わず発光用のダイオードでおこなっているようです。ページの選択はSRAMに入っているようで、電池を抜くとTVになります。

以前だと学習データをSRAMに入れておいて、電池交換時のバックアップにコンデンサーが付いているケースが多かったです。コンデンサーの劣化で十分にバックアップされなくなったり、液漏れでパターンが切れて壊れたりする事もあるのでEEPROMを使うのは非常に賢明です。

使われているマイコンの待機時の消費電流は0.7uAなので電池の持ちも良さそうです。

リモコンは省電力モードであってもキースキャンは定期的に実行する必要があり、汎用のマイコンではここまでの省電力は実現できないと思います。

数年購入を検討していたのですが、よい買い物な気がします。

AmazonにはL336はたくさん出品されてて、中国発送のものと、国内(Amazon)発送のものがありますので、注意してください。

偽物があるって書いてあったページもあったので、不自然に安い商品には注意したほうが良いかもしれません。

L336にはL336間でページの全データーを送受信する機能があるのですが、どうもハンドシェークしているようなので二台ないと解析できないです。

EEPROMの中身を解析している人もいました。

このリモコンはオリジナルがないと学習できませんが、アルマジロのお使いのようなパソコンのアプリで信号を出して学習することはできます。

学習リモコンはどう設定したか忘れないようにすることが大切かもしれません。

リモコンは電池の液漏れやスイッチの接触不良の故障が考えられます。電池の状態をときどき確認するのがよいです。またあまり強い力でおなさない事や、ときどき押してると良いような気がします。
Raspberry Pi起動時にChromiumを自動起動させる方法

# 1.Chromium 起動スクリプトを作成

```
$ nano ~/launch.sh
```


```launch.sh
/usr/bin/chromium-browser --noerrdialogs --disable-infobars --kiosk ____URL____
```

____URL____ここに自動で開きたいURLを書く

## 1.1テキストエディタnanoの終わらせ方

```
Ctrl + O
Enter
Ctrl + X
```

# 2.スクリプトを実行して確認


```
$ bash ~/launch.sh
```

# 3.autostart ファイル作成

```
$ mkdir -p ~/.config/lxsession/LXDE-pi
$ cp /etc/xdg/lxsession/LXDE-pi/autostart ~/.config/lxsession/LXDE-pi/autostart
$ nano ~/.config/lxsession/LXDE-pi/autostart
```


※``~/.config/lxsession/LXDE-pi/autostart`` が ``/etc/xdg/lxsession/LXDE-pi/autostart`` の代わりに実行されます。

## 4.``autostart``一番下の行を追加する

※5.スクリーンの自動スリープを防ぐも同時に行うことを推奨。

```ruby:autostart
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
bash /home/pi/launch.sh
```

# 5.スクリーンの自動スリープを防ぐ
```
$ nano ~/.config/lxsession/LXDE-pi/autostart
```


```ruby:autostart
@xset s 0 0
@xset s noblank
@xset s noexpose
@xset dpms 0 0 0
```

# 6.Raspberry Piのマウスカーソルを非表示

Terminal で unclutter というアプリ（一定時間マウスが動かないと、カーソルが非表示され、再びマウスを動かせば、カーソルが表示されるアプリ）をインストールする。

```
$ sudo apt-get install unclutter
```

インストール後、


```
$ sudo nano /etc/xdg/lxsession/LXDE/autostart
```

下記を追記して、リブートを行う。

```
@unclutter -idle 0.1 -root
```

# 7.KIOSKモードのブラウザを強制終了

「Alt + F4」キーでブラウザを終了

# 8.今回の環境

– Raspberry pi 4 8G
– Raspberry Pi OS(2021-05-07-raspios-buster-armhf.img)
http://downloads.raspberrypi.org

※2021.8.11実装
SQLによるデータ定義

# SQLの種類
### SQL-DDL
データ定義を行う。

### SQL-DML
データ操作を行う。

#### 気づき
いつも使っているSQL文のことなのかな?

# スキーマの定義
```
CREATE SCHEMA AUTHORIZATION スキーマ名
```

# テーブル（表）の定義
正規化されたデータに基づいて、あらかじめ次のような項目を決めておく必要がある。

* テーブル（表）名
* 列名
* 列に格納されているデータ型とその最大長
* 主キーとなる列(または列の組み合わせ）
* 外部キーである列

# 権限の設定
```テーブル（表）またはスキーマ```などに対する```処理の権限を設定```する。
```
GRANT 権限１,権限２,...ON 表名　TO 許可識別子
```
権限１、権限２は```権限の種類（挿入、更新、削除、読み取り、定義など）```を定義する。
許可識別子は、```権限を付与するものを識別子```として指定する。

# 権限の取り消し
付与した権限を取り出す場合は、REVOKE文を用いて次のように指定する。
```
REVOKE 権限1, 権限2, ... ON 表名　TO　許可識別子
```

# ビュー表の定義
```実在の表の一部```または```複数の表を組み合わせて作成```した仮想の表で、```読み取りのみが可能```.
ビューにより、```実表の安全性を確保```することができる。

p２０３を見る
### ビュー表の表名の定義
### 項目表
問屋名、発注日、商品名、数量を列名で表示させる。

### データ導出元
発注表、商品表、問屋表

### 導出条件
商品コードが発注表と商品表の両方に存在し、かつ問屋コードが商品表と問屋表の両方に存在する行を選択する。

# 親言語方式でもSQLの利用
## 親言語方式とは？
アプリケーションを作成した```プログラム言語（親言語）中にデータベース操作命令（SQL文）を埋め込む```方法。

## カーソルとは？
表から```1行ずつデータを読み込む```機能

## カーソルを使った読み出し方法
ファイル処理と同様の操作手順がある。
### カーソルを定義
```DECLARE```文を使う。

### 処理を始めるために読み出す
```OPEN```文を使う。

### 1行ずつ読み込む
```FETCH```文を使う。

### 条件文として記述
```WHERE CURRENT OF カーソル名```

### 全ての処理が終わるとカーソルを閉じる
```CLOSE```

http://www.dataondemand.co.jp/documents/data_integrator814/rifl_language/Calling_External_DLL_Examples.html

# 関連記事
https://qiita.com/masatom86650860/items/94d2dcf5093acd84f489

# 出典　
https://gihyo.jp/book/2022/978-4-297-12375-8
AI Programmerの作法 その12

# 概要
AI Programmerの作法、調べてみた。
zundokoやってみた。

# 投入したソースコード
- C++
- ランダムにズンとドコを表示し、ズンが4回続いたら、「ドコ、キヨシ」を表示する。
 
# 実行結果

```
ランダムにズンとドコを表示し、ズンが4回続いたら、「ドコ、キヨシ」を表示する。

#include <iostream>
#include <random>
#include <string>

int main() {
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<int> dist(0, 1);

    int count = 0;
    while (count < 4)
    {
        if (dist(mt) == 0)
        {
            std::cout << "ズン" << std::endl;
            count++;
        }
        else
        {
            std::cout << "ドコ" << std::endl;
            count = 0;
        }
    }

    std::cout << "ドコ、キヨシ" << std::endl;

    return 0;
}




```

# paiza.io 実行結果

```
ズン
ズン
ドコ
ズン
ズン
ドコ
ドコ
ズン
ドコ
ドコ
ズン
ドコ
ズン
ズン
ドコ
ドコ
ドコ
ドコ
ドコ
ズン
ズン
ドコ
ドコ
ドコ
ドコ
ズン
ドコ
ドコ
ドコ
ドコ
ズン
ズン
ズン
ドコ
ズン
ズン
ドコ
ズン
ズン
ズン
ズン
ドコ、キヨシ
```

# 成果物

https://paiza.io/projects/nKShfo3OeU0kuGnxdq4Tqg

以上。
PhraseExpressで定型文（スニペット）の貼り付けがおかしい場合の対策

# 現象

* PhraseExpressで定型文を貼り付けると、時々カタカナがひらがなになったり、改行が反映されない。
* FireFoxのtextareaで起きる頻度が高い。

# 対策

ファイル ⇒ Settings 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3c74a976-4c99-4f99-bd00-c3a00252824e.png)

Text Insertion 。
もし
『Paste text via keystroke…』
の設定になっていたら
『Paste text using the Windows Clipboard』
に変更。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/5c338ff8-9edf-3925-3e23-0ee547f377dc.png)

要は **『1文字1文字キー入力するモード』** ではなく **『クリップボードに入れて一括で貼り付けモード』** にする。

# バージョン

Windows 10 Pro 21H2 OSビルド 19044.2075
PhraseExpress Free v15.0.95f
Azure Fundamentals(AZ-900)：Azure のアーキテクチャとサービスについて説明する「Azure物理インフラストラクチャ」

Microsoft Learnを用いたMicrosoft Azure Fundamentals(AZ-900)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始める方の参考になれば幸いです。

## 今回の学習内容
**◆「Azure物理インフラストラクチャ」**
◇対応するMicrosoft Learn ラーニングパス
[Azure の基礎: Azure のアーキテクチャとサービスについて説明する](https://learn.microsoft.com/ja-jp/training/paths/azure-fundamentals-describe-azure-architecture-services/)
◇対応するモジュール
[Azure 物理インフラストラクチャについて説明する](https://learn.microsoft.com/ja-jp/training/modules/describe-core-architectural-components-of-azure/5-describe-azure-physical-infrastructure)

※前回の投稿は下記から確認できます。
[Azure Fundamentals(AZ-900)：クラウドの概念について説明する「信頼性と予測可能性」「セキュリティとガバナンス」](https://qiita.com/fsd-jume/items/592be27a2e3c3f9ee4c9)

## リージョンと可用性ゾーン
下記の投稿で今回のMicrosoft Learnの内容を含めて記載しております。

https://qiita.com/fsd-jume/items/592be27a2e3c3f9ee4c9

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/90a93adf-32c3-f6f1-7c48-a493d1ca6141.png)


**◆アプリで可用性ゾーンを使用
アプリの可用性を高めることができる**
・例)コンピューティングやストレージ、ネットワーク、データリソースを1つの可用性ゾーンに併置し、他の可用性ゾーンにレプリケート(複製)する
→1つの可用性ゾーンで障害が発生した場合も、レプリケートした可用性ゾーンで継続した動作が可能
※サービスを複製し、可用性ゾーン間でデータを転送するためのコストがかかる場合がある

**◆可用性ゾーンに対応しているサービスの分類**
**◇ゾーンサービス
自分で選んだ特定の可用性ゾーンにリソースを配置する方式**
・アプリケーションとデータをリージョン内の1つ以上のゾーンにレプリケートすることで、回復性を各自が設計できる
・例)仮想マシン、マネージドディスク、標準IPアドレスなどを特定のゾーンに固定し、リソースの1つ以上の仮想サーバを複数のゾーンに分散

**◇ゾーン冗長型サービス
リソースがゾーン間で自動的にレプリケートまたは分散される方式**
・ゾーン冗長ストレージやSQL Database、ロードバランサーなどに用いられる
・例)1つのゾーン内の障害がデータの高可用性に影響しないように、3つのゾーンにデータがレプリケートされる

**◇非リージョンサービス
常にすべてのAzure地域から利用可能で、ゾーンやリージョン全体の停止に対しても、回復性があるサービス**
・例)Azure Virtual DesktopやAzure Active Directoryなど

ただし、リージョン障害ではリージョン内の複数またはすべての可用性ゾーンに影響を与える可能性がある→さらに回復性を高めるために、Azureには**リージョンペア**がある

**◆リージョンペア
リージョン全体で障害が発生した際に、ペアとなるリージョンに自動的に切り替えることができる**
→サービス停止時間を短くすることができる
→信頼性の高いサービスとデータの冗長性を提供可能
・同じ地域(米国、ヨーロッパ、アジアなど)内の少なくとも300マイル(483km)離れている別のリージョンとペアになっている
・一部のAzureサービスではリージョンペア間の自動切り替えをサポートしていない
・一部のリージョンペアでは互いにバックアップせず、一方向のペアリングになっている
( =プライマリリージョンがセカンダリリージョンのバックアップにならない)

**◆ソブリンリージョン(Sovereign Region)
コンプライアンスまたは法的な目的に合致したアプリケーションを構築する場合に使用できる特別なリージョン**
・例)Azure Government：米国政府向けのリージョン、Azure China：中国向けのリージョン　など

## 次の学習内容
**◆Azure管理インフラストラクチャ**

https://qiita.com/fsd-jume/items/cbbfe233a868901cf1e7

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8
GoogleのAI作曲 Magentaで旧バージョンのレポジトリをダウンロードする方法

GoogleのAI作曲 Magentaは、開発者向けにレポジトリをローカルにダウンロードをして、そのレポジトリのファイルを使用しての開発が行える様になっています。

通常レポジトリのダウンロードはgit cloneで行うのですが、この場合最新版のレポジトリ(現在は2.1.4）がクローンされます。
しかしMagentaはバージョン違いのエラーが頻発する問題（泣）がありバージョンダウンなどで実行する必要が度々あるのですが、この場合旧バージョンのクローンはどう行えば良いのでしょうか？

git checkoutで過去バージョンを指定、、、、という方法もあるのですが、初心者様には難しいので今回別の（手動での）方法を解説します。

## １・magentaのgithubレポジトリにアクセス
https://github.com/magenta/magenta
右側にReleasesがあるので+47releasesをクリック

![スクリーンショット 2022-10-06 14.02.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61803/8d3446bc-57ca-c979-f3bb-4e308a28bbc8.png)

## ２・任意のバージョンを選んでダウンロード
遷移先ページに過去のレポジトリ一覧があります。
![スクリーンショット 2022-10-06 14.03.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61803/0ecb5cee-efe5-ee5e-8a87-f6e5bb7c7d30.png)

現在2.1.3は無くなっておりますので2.1.4以下は2.1.2となります。
assetsをクリックするとzipファイルがダウンロードできるリンクが出てきます。
任意のディレクトリ（作業ディレクトリ推奨）に保存してください。


なおMagentaの開発をこの方法で行う場合、実行用の仮想環境もmagenta==2.1.2などバージョンを合わせてください。
自立航法測位やってみた（Flask）

# はじめに
こんにちは。今回初投稿です。

大学の戦略的教育プログラムの一環で行われたIoT Dojo前期の活動が終了したのでそこで扱った技術について少しまとめてみたいなーと思います。
こうゆう記事書くの初めてなんであんまりうまい説明できないかもですがご了承ください。

# プロジェクトの概要
今回私たちは、今話題の（？）「自立航法測位」について5,6人のグループで活動を行いました。最初は知識も全くない状態だったのでこのプロジェクトを行ってくれている大学院生のメンターさんに色々聞きながらプロジェクトを進めていきました。正直テーマを決めるのにも相当大変で、ここから開発から何からどうなるんだろうと当時は不安でした。:sweat:

自立航法測位をするときに「esp32」というデバイスに加速度センサと角度センサの6軸を用いて自立航法測位を行いました。センサから取得した値をもとに座標を計算して、その値をもとにあらかじめ作成しておいたマップ（7m×7m）に描画していきます。

今回私はサーバー側のデータ受け取りと、それをhtml側にデータを送って描画するところを担当したのでそれについてメモを残そうと思います。（概要長くね？）

1歩判定をどうしたかとかは他のチームメンバーが書いてくれたのでこちらをご覧ください🙏
https://qiita.com/nk_gfp/items/e22ac9ac31f354c8c7eb

# 使用した機器
先ほども少し触れましたが今回使用した機器はこちらです
- esp32
- ジャイロセンサー
- 加速度センサー
- ブレッドボード（大きめのやつ）
- PC（サーバー)
大体こんな感じです。

# Flaskとは？
今回、小規模なWebアプリケーション開発だったので、「Flask」というpythonのWebアプリケーションフレームワークを使用しました。

#Flaskのインストール
ubntsu上で
```python
pip install flask
```
これでインストールが終了です。（めちゃ簡単！）

# Flask実行方法
### HTMLデータ送信、受け取り 
次に、サーバー側からデータが送られてきたときの処理とリクエストが送られてきたときの処理を書きます。
```python
@app.route("/test")
def web_view():#関数名は何でもいいです
 ......
# htmlにデータを送る 
  return render_template("map_create.html", data=[x_data,y_data,x_re_data,y_re_data])
```
このリターン文で指定したデータをHTMLに送ることができます。

```html
...
<body>
  ...
  let list_data = {{ data | tojeson }}
  ...
</body>
```
これでlist_dataという変数に先ほどFlaskで送ったデータを受け取ることができます。
HTMLにデータを送る、受け取りはこれで終了です。

### esp（センサー）からデータ送信、受け取り

次に、espからデータの送信、受け取りについてです。espは言語にmicropythonを使います。（ほとんどpythonと同じです）
```python
url = 'http://192.168.2.101:5000/' #サーバのIP
payload = {"degree": degree_list} #データ部分(key:distance, value:test)
#JSON形式にする
header = {'Content-Type' : 'application/json'}
#おまじない
response = urequests.post(url, data = ujson.dumps(payload).encode("utf-8"), headers = header)
print(response)
response.close() 
```
これがesp側での送信する処理です。espからはjson形式でデータを送っています。urlにFlaskサーバーに送るためのIPアドレスを指定します。それでデータを指定してresponseを送ります。これで、データの送信は終了です。
次にデータをサーバー側で受信します。
```python
@app.route("/",methods=["POST"])
def main(): #関数名はなんでもOK
...
# アプリケーションを動かすためのおまじない
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True) #ポート5000番
...
```
このapp.runのところはFlaskを動かすためのおまじない（？）です。後は、Ubuntuなどのコマンドプロンプトで
```
export FLASK_APP=flask_server.py
flask run --host=0.0.0.0
```
これを入力し実行することで、Flaskを起動することができます。
これで、Flaskの実行方法は終了です！

# おわりに
記事を書いてみて、技術について説明するのも結構難しいなと思いました。課外活動では、チーム開発とかいろいろ大変な部分もありましたが、とても勉強になったと思いました。Webアプリケーション開発は面白いなーと思いました。後期も参加する予定なので新チームで頑張りたいと思います！
PythonでMDことはじめ Vol. 1

# 0. はじめに
分子動力学法(Molecular Dynamics, MD)への止まない興味の記録を残します。
ぶっちゃけると、PythonでMDシミュレーションプログラムを作るのは非合理的です。計算量が膨大になるため、いかに計算を効率化するか、並列化するかが重要です。そのような分野で実行速度の遅いPythonなどの言語を勧めることはできません。
当方完全に素人ですので、間違い、アドバイスがあればご教示いただけると大変助かります。

# 1. MDとは
簡単に言うと、原子（分子）間の力を計算し、ニュートンの運動方程式に基づいて速度・位置を計算することでミクロな挙動をシミュレートする、というイメージです。
MDシミュレーションにおいて理解する必要があるのは
1. 原子間の力を決定する**ポテンシャル**
1. 速度・位置の計算をするための**数値積分**

の二つだと考えています。

# 2. 主なポテンシャル
MDの有名なポテンシャルとしては[レナードジョーンズポテンシャル](https://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%8A%E3%83%BC%E3%83%89-%E3%82%B8%E3%83%A7%E3%83%BC%E3%83%B3%E3%82%BA%E3%83%BB%E3%83%9D%E3%83%86%E3%83%B3%E3%82%B7%E3%83%A3%E3%83%AB)(Lennerd-Jones Potential, LJ Potential)が挙げられます。二つの原子間の距離$r$のみの関数としてポテンシャルエネルギー・力を計算するモデルです。
三体間ポテンシャルで有名なTersoffポテンシャルや、量子力学からポテンシャルを算出するab initio分子動力学(AIMD)というものもあります。

# 3. 主な数値積分法
オイラー法、ルンゲクッタ法、Leap-frog法、速度Verlet法などがあります。

# -1. 次回予告
次回はLJポテンシャルの実装と可視化をやっていきます。
リンクはこちら:point_right:https://qiita.com/PlusF/items/e356ce5ebcbad530c0d5
hygenのテンプレートファイルレンダリング方法を確認する

社内のコーディングの生産性向上のために、[hygen](https://www.hygen.io/)でファイルを追加するスクリプトを作っていたのですが、[hygenのTemplateドキュメント](https://www.hygen.io/docs/templates)を見てもどういう風にテンプレートファイルがレンダリングされているのかよくわからなかったので調べてみました。

# 前提

- yarnでhygenを実行して、複数のテンプレートファイルから数種類のファイルを生成したかった。
- オプションの値によってテンプレートファイルの処理方法を変えたかった。
- 条件分岐の書き方などでわからないところがあった。
- hygenのバージョンはv6.2.11

# hygenのコードを読む

ドキュメントは使い方がざっくり書いてあるだけなので、コードを読みました。
[render.tsのrender関数](https://github.com/jondot/hygen/blob/v6.2.11/src/render.ts#L38)

## front-matterでパース

実際にファイルを読み込んだあと、[front-matter](https://github.com/jxson/front-matter)でヘッダ部分とボディ部分を読み込んでいます
[該当コード](https://github.com/jondot/hygen/blob/v6.2.11/src/render.ts#L59-L64)

hygenのテンプレートファイルは↓のようになっています。
```yml
---
// frontmatterの定義部分（ヘッダ部分）
---
// テンプレート部分（ボディ部分）
```

これをヘッダ部分とボディ部分に分けて次の処理に渡しています。

## ejsでテンプレートをレンダリング

その後、ヘッダ部分とボディ部分を用いてファイルをレンダリングしています。
[該当コード](https://github.com/jondot/hygen/blob/v6.2.11/src/render.ts#L65-L87)

### ヘッダ部分の属性をパース

front-matterでパースされたヘッダ部分の属性の値を`renderTemplate`に渡してパースしています。
[該当コード](https://github.com/jondot/hygen/blob/v6.2.11/src/render.ts#L67-L75)
`renderTemplate`関数では受け取った値を[ejs](https://github.com/mde/ejs)でパースします。
[該当コード](https://github.com/jondot/hygen/blob/v6.2.11/src/render.ts#L28-L29)

パースされた値がこの後テンプレートのレンダリングに使用されます。

### ボディ部分を属性値を使ってレンダリング

パースされた属性値と、render関数が受け取ったargs、ボディ部分のテンプレートを`renderTemplate`に渡してパースします。
[該当コード](https://github.com/jondot/hygen/blob/v6.2.11/src/render.ts#L77-L85)
`renderTemplate`はejsを使用しているので、テンプレートのパースもejsが行っていることになります。

# まとめ

以上をまとめると、テンプレートファイルは下記のようにレンダリングされるようです。

- front-matterによって、frontmatterの定義部分（ヘッダ部分）とテンプレート部分（ボディ部分）に分離される。
- ヘッダ部分に定義されている属性値がrender関数に渡されたargsを使ってejsでパースされる。
- ボディ部分が、render関数に渡されたargsと上記でパースされた属性値を条件にレンダリングされる。

front-matterとejsが使用されるのと、この順序を念頭においてテンプレートファイルを作成すればいいことになります。
基本的にはejsの記法が肝になると思うので、困ったらejsのドキュメントを参考にすればいいと思います。
ヘッダ部分の挙動（レンダリング・injectするか否かなど）についてはhygenのドキュメントを漁るしか無いですが、そこに渡す値はejsの記法範囲で自由にできるので自由度は高いと思いました。
Dockerからメールが送れない　原因：eximが消えていた・・

```
Swift_TransportException Connection could not be established with host localhost 
:stream_socket_client()
: unable to connect to localhost:25 (Cannot assign requested address)
```

Dockerでmailを送るためにeximを入れていたが
なぜかDockerfileでインストールしてたはずのeximが消えていた・・

急遽
yum install -y exim
を行った



備忘録
Dockerからメールを送るためのeximの導入方法

```
yum install -y exim
mkdir /etc/exim4
vi /etc/exim4/update-exim4.conf
----
dc_eximconfig_configtype='internet'
dc_other_hostnames=''
dc_local_interfaces='127.0.0.1;::1'
dc_readhost='exim4'
dc_relay_domains=''
dc_minimaldns='true'
dc_relay_nets=''
dc_smarthost=''
CFILEMODE='644'
dc_use_split_config='true'
dc_hide_mailname='true'
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'
----
```
【firestore  + Jest】Jest did not exit one second after the test run has completed の対処法

# 自分の環境
jest: 28.1.3
firebase: 9.8.4

# 原因
非同期処理が正しく終了していない
(自分の場合、非同期処理には全てawaitを付けているのでこれが原因ではありませんでした..)

## とはいうものの非同期処理はawaitちゃんとつけているのに...
これ本当に悩みました。非同期処理は全てawaitを付けているのに何故エラーメッセージが消えないのかと。

答えありました。
[GitHub Actions と Firebase を使用すると、テストの実行が完了してから 1 秒後に Jest が終了しませんでした。](https://www-anycodings-com.translate.goog/1questions/2499752/jest-did-not-exit-one-second-after-the-test-run-has-completed-when-using-github-actions-and-firebase?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=sc)

## テスト終了後にfirebaseとのリソースを切断する必要がある
下記のコードでfirebaseのリソースを解放しましょう!
【firebase v9　の場合】
```javascript
describe("firestore test v9", ()=>{
    afterAll(() => {
        //リソース解放
        deleteApp(app);
    });
    test("何かしらのテスト", ()=>{
        //中身
    });
})
```

【firebase v8　の場合】
```javascript
describe("firestore test v8", ()=>{
    afterAll(() => {
      //リソース解放
      firebase.app().delete();
    });
    test("何かしらのテスト", ()=>{
        //中身
    });
})
```
GoogleのAI作曲 Magenta colab notebookでの実行

# GoogleのAI作曲 Magenta colab notebookでの実行

MagentaをGoogle Colab Notebookで実行する方法の動画とファイルを公開しました。

**動画リンク**
[magenta colab notebookでの実行](https://youtu.be/eVXqFivGmzY)
この動画を参考にしながら後述の流れで実行してください。

**配布ファイル**
[magenta_notebook.ipynb](https://canplay-music.com/download/30410)
です。
zipファイルになっているので解凍して使用してください。

**学習済みデータ**
[basic_rnn.mag](http://download.magenta.tensorflow.org/models/basic_rnn.mag)
よりダウンロードしてください。


# 実行の流れ
**１・Google Colaboratoryを開いてください**
（googleアカウントが必要です）

https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja


**２・配布したmagenta_notebook.ipynbを開いてください**
ファイルからノートブックをアップロードをクリックしファイルを選択。


**３・最初のセルを実行（左のプレーボタンをクリック）**
```
pip install magenta
```

**４・終了したら RESTART RUNTIME をクリック**
右上に初期化中と表示されます。
終わるとRAMとディスクが表示されます。

**５・ダウンロードしたbasic.rnnファイルをアップロード**
右のフォルダアイコンからcontentを選択。
アップロードをクリックしてbasic.rnnファイルを選択の上、アップロード。
（アップロードファイルのcolaboratoryへの保存はできないため、毎回アップロードの作業が必要です、、、）

**６・melody_rnn_generateコマンドを実行してください**
```
melody_rnn_generate \
--config=basic_rnn \
--bundle_file=/content/basic_rnn.mag \
--output_dir=/content \
--num_outputs=1 \
--num_steps=128 \
--primer_melody="[60]"
```
生成が完了するとcontent内にmidiファイルが生成されますのでダウンロードして音楽再生できます。
DAWやMIDIプレーヤーで再生してください。