OmniAICreator/Qiita-1.07M huggingface dataset:
[Fancontrol] Fancontrolの設定 完全版！ これで駄目なら諦めなさい！

# はじめに
こちらの記事に興味を持っていただいたということは、ファンの騒音に悩まされている、もしくは、うるさくはないけど無音に違い状態で作業を行いたいといった望みがあるのではないでしょうか。

当の私はLinuxの自作PC初挑戦でRyzenで躓いて、今回i7-3770の中古を購入して上手くいったようなので記事に残すこのにしました。

同じような問題で悩まれている方の助けに少しでもなれたら書いた甲斐があります。


# 解決方法

`/etc/fancontol`の設定をフルパスとWildcardで指定することでデバイスが見つからない問題を回避できます。


## 当方環境について

- デバイス名: nct6667
- CPUファン: 1つ
- ケースファン: 1つ

- pwm1=ケースファン
- pwm2=CPUファン


## 当方の設定内容について

- 当方のファンともに停止しないものだったので、`MINSTOP`を0にしてあります。
- ケースファン : `CPU温度`が`45度`以上になるまで`50%rmp`で回転を開始
- CPUファン : `CPU温度`が`35度`以上になるまで最低速度で回転、越えたら`150rpm`で回転を開始
- `両ファン`とも完全停止しないため`MINSTOP`を`0`

**注意**
rpm値の設定はファンによって冷却性と騒音レベルが違うので、バランスをよく調整しながら決める。

- 当方のケースファンはなかなかの轟音を放つためrpm値を小さ目(50rpm)に設定した。

**小技**
デバイス名がどこにあるかわからない場合は、`find ディレクトリ名　-name デバイス名`で簡単に調べられるのでお試しください。

```:デバイスのlocationの探し方
find ディレクトリ名 -name デバイス名
```


## 設定

```:/etc/fancontol
# Configuration file generated by pwmconfig, changes will be lost

INTERVAL=10

FCTEMPS=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm1=/sys/devices/platform/coretemp.0/hwmon/hwmon[[:print:]]*/temp1_input /sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm2=/sys/devices/platform/coretemp.0/hwmon/hwmon[[:print:]]*/temp1_input

FCFANS=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/devices/pwm1=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/fan1_input /sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/devices/pwm2=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/fan2_input

MINTEMP=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm1=35 /sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm2=35

MAXTEMP=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm1=60 /sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm2=60

MINSTART=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm1=50 /sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm2=150

MINSTOP=/sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm1=0 /sys/devices/platform/nct6775.656/hwmon/hwmon[[:print:]]*/pwm2=0

```
オンラインリアルシステムまとめ

コンピューターシステムの処理方式の一種

Why　処理の即座性を要求されるから 
When　
Who　端末が
What　
Where　座席予約システム　ATMによる入出金
How　通信回線を通じてホストコンピューターなどに接続して処理要求を即座に送信して実行、完了すると結果を返す方式

（参考文献）
http://e-words.jp/w/%E3%82%AA%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%83%AA%E3%82%A2%E3%83%AB%E3%82%BF%E3%82%A4%E3%83%A0%E5%87%A6%E7%90%86.html
Discord.jsでグローバルチャットを作る

<hr>Discord.pyのグローバルチャットについては@coolwind0202さんが[Discord.pyでグローバルチャット](https://qiita.com/coolwind0202/items/061a08b0608d94fcb552)という記事を書いていたので、そちらをご覧ください。<hr>Discord.jsのインストールなどは省略するので、自分で調べてください。<hr>

#追記
220/04/30 画像が表示されないバグを直しました。

# グローバルチャットとは
グローバルチャットとは、あるサーバーAでメッセージを送信すると、他のサーバーBやCでもメッセージを受信できるというものです。また、Bでメッセージを送信するとAやCでもメッセージを受信できます。

説明が下手なので[こちら](https://qiita.com/coolwind0202/items/061a08b0608d94fcb552#%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%81%A8%E3%81%AF)を見てもらった方が早いと思います。

#コード
グローバルチャットのコードです。コードについての解説は下を見てください。

```js:discordbot.js
client.on('message', message => {
	if(message.author.bot){
		return;
	}
	if (message.channel.name == ("グローバルチャット")){
		message.delete();
		const ch_name = "グローバルチャット";
		client.channels.forEach(channel => {
			if (channel.name === ch_name) {
				channel.send({embed: {
					title: message.content,
					color: 0x800080,
					timestamp: new Date(),
					footer: {
						text: "TestBotのグローバルチャット"
					},
					thumbnail: {
						url: "https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png"
					},
					fields: [
						{
							name: "サーバー",
							value: `${message.guild.name} (${(message.guild.id)})`,
							inline: true
						},
						{
							name: "チャンネル",
							value: `${message.channel.name} (${message.channel.id})`,
							inline: true
						},
						{
							name: "ユーザー",
							value: `${message.author.username} (${message.author.id})`,
							inline: true
						}
					]
				}});
			}
		})
	}
});

```

#コード解説
ここではコードの解説をしていきます。

```js:Discord.js
client.on('message', message => { // メッセージが送信されたとき
	if(message.author.bot){ // もし相手がBOTなら無視する
		return;
	}
	if (message.channel.name == ("グローバルチャット")){ // もし送信された場所が「グローバルチャット」なら
		message.delete(); // メッセージを削除する(二重になるのを防ぐため)
		const ch_name = "グローバルチャット"; // 「グローバルチャット」という名前のチャンネルに一斉配信
		client.channels.forEach(channel => {
			if (channel.name === ch_name) {
				channel.send({embed: {
					title: message.content, // メッセージ内容
					color: 0x800080, // 色
					timestamp: new Date(),
					footer: {
						text: "TestBotのグローバルチャット" //フッターの内容
					},
					thumbnail: {
						url: "https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png" // ユーザーのアイコン
					},
					fields: [
						{
							name: "サーバー",
							value: `${message.guild.name} (${(message.guild.id)})`, // 送信されたサーバーの名前とID
							inline: true
						},
						{
							name: "チャンネル",
							value: `${message.channel.name} (${message.channel.id})`, // 送信されたチャンネルの名前とID
							inline: true
						},
						{
							name: "ユーザー",
							value: `${message.author.username} (${message.author.id})`, // 送信したユーザーの名前とID
							inline: true
						}
					]
				}});
			}
		})
	}
});

```
embedについては[こちら](https://qiita.com/nedew/items/4e0c20c1a89e983a6992)の記事をご覧ください。

#完成!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628982/dbe68bab-57bc-5c33-bb3b-5e9d79d918b5.png)
メッセージを送信すると、このような感じになります。
カスタムNavigationViewStyle例

```swift
import SwiftUI

public struct AllVisibleNavigationViewStyle: NavigationViewStyle {
    struct ControllerModifier: ViewModifier {
        struct ControllerView: UIViewControllerRepresentable {
            class ViewController: UIViewController {
                var perform: (UIViewController) -> Void = { _ in }
                override func viewDidAppear(_ animated: Bool) {
                    super.viewDidAppear(animated)
                    perform(self)
                }
            }
            var perform: (UIViewController) -> Void
            func makeUIViewController(context: Self.Context) -> UIViewController {
                let vc = ViewController()
                vc.perform = perform
                return vc
            }
            func updateUIViewController(_ uiViewController: UIViewController, context: Self.Context) {}
        }
        var perform: (UIViewController) -> Void
        func body(content: Content) -> some View {
            content.overlay (
                ControllerView(perform: perform).frame(width: 0, height: 0)
            )
        }
    }
    public func _body(configuration: _NavigationViewStyleConfiguration) -> some View {
        NavigationView { configuration.content }
            .modifier(ControllerModifier(perform: { vc in
                guard let svc = vc.parent?.children.first as? UISplitViewController else { return }
                svc.preferredDisplayMode = .allVisible
            }))
    }
    public init(){}
}

struct ContentView: View {
    struct Greet: View {
        var text: String
        var body: some View {
            Text(text).navigationBarTitle("Secondary")
        }
    }
    var body: some View {
        NavigationView {
            List(0..<100) { i in
                NavigationLink(destination: Greet(text: "hello \(i)")) {
                    Text("greeting \(i)")
                }
            }.navigationBarTitle("Primary")
        }.navigationViewStyle(AllVisibleNavigationViewStyle())
    }
}

import PlaygroundSupport

PlaygroundPage.current.wantsFullScreenLiveView = false
PlaygroundPage.current.setLiveView(ContentView())
```

<img width="768" alt="38C7D426-3E71-4C7F-9247-427CDD1ED65A.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91569/98450be1-a3ca-c55f-391d-bf343cec6286.jpeg">
kubernetesキホンのキ

# 1. はじめに

前回の投稿から、ご無沙汰してしまいました。前回、[Dockerの導入編](https://qiita.com/takuya_tsurumi/items/182d2de3f3ce7bb63edb)ということで、Dockerのインストール方法や、簡易的な使い方をまとめました。

今回は、その上位互換として知られる kubernetes の概念や用語について勉強したことをアウトプットしていきます。


# 2.kubernetesとは

kubernetesを一言でいうと、「コンテナを管理するためのシステム」です。
ざっくり言うと、「Docker 拡張バージョン」です。

Docker は単一マシンの上でコンテナを動作させるシステムでしたが、kubernetes は複数マシン上でコンテナを管理・統合させるためのシステムです。コンテナオーケストレーションといいます。

図2.1 は視覚的にDockerとkubernetesの差分を理解するために図示しました。
Dockerのみだと単一ホスト上で動作するコンテナの管理のみしかできませんが、kubernetesを利用することによって、複数のDockerホストをkubernetesのシステム上で管理することができるようになります。

![kubernetesとDocker位置付け.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329544/70d94a54-a1ae-6c57-5de4-e60e5ce5d3cd.png)
図 2.1. Dockerとkubernetes


Docker でも Docker Swarm を利用することで複数マシン上でコンテナを管理することができますが、kubernetesの方が機能が充実していて実践に使用されているため、今回は kubernetesを取り扱っています。


# 3. kubernetes の用語

以下 kubernetes で使われている用語をまとめました。

| No | リソース名             | 意味・用途 |
|----|-----------------------|------------------------------|
|  1 | Node                  | ・コンテナを乗せる元のサーバ(物理マシン、VMどちらも) |
|  2 | Namespace             | ・仮想的なクラスタ<br>・開発者(チーム)それぞれのNamespaceを作ることでメインのNamaspaceを綺麗に保つことができる |
|  3 | Pod                   | ・コンテナの集合体単位<br>・デプロイするコンテナの集合体になるので、密結合となるwebサーバ用コンテナとアプリケーションサーバ用コンテナをまとめると有効活用できる |
|  4 | ReplicaSet            | ・同じ仕様のPodを複数生成・管理<br>・Podのみでは単一のPodのデプロイしかできないため、複数のPodをデプロイする際に利用する |
|  5 | Deployment            | ・ReplicaSetの世代管理<br>・実運用では、ほとんどDeploymentの単位でデプロイを管理すること |
|  6 | Service               | ・Podにアクセスするための経路定義<br>・アクセスするPodを制御するために利用する<br>・L4層レベルでのアクセス制御が可能 |
|  7 | Ingress               | ・Service公開の口<br>・L7層レベルでのアクセス制御が可能<br>・HTTP/HTTPSでのサービス公開をする際はServiceよりIngressをメインに使用する |
|  8 | ConfigMap             | ・構成ファイル、コマンドライン引数、環境変数、ポート番号などの設定情報を定義し、Podへ供給する<br>・うまく活用すると構成の変更や管理が容易にできる |
|  9 | PersistentVolume      | ・Podが利用するストレージを定義<br>・ストレージの実体である |
| 10 | PersistentVolumeClaim | ・ストレージを論理的に抽象化したリソース<br>・PersistentVolumeを動的に確保する(必要な要領のみ) |
| 11 | StorageClass          | ・PersistentVolumeが確保するストレージの種類を定義(HDDやSSD等) |
| 12 | StatefulSet           | ・同じ仕様で一意性のあるPodを複数生成・管理<br>・継続的にデータを永続化するステートフルアプリケーション管理用リソース |
| 13 | job                   | ・常駐目的ではない複数(もしくは単一)Podを生成し、正常終了するまで管理するリソース<br>・大規模計算やバッチ処理などで利用 |
| 14 | Cronjob               | ・cron記法でスケジュール実行されるjob |
| 15 | Secret                | ・認証情報等の機密データを定義するリソース<br>・証明書や秘密鍵、パスワードなどの機密情報を管理する |
| 16 | Role                  | ・Namespace内で操作可能なkubernetesリソースのルールを定義するリソース<br>・権限の管理に利用する |
| 17 | RoleBinding           | ・Roleとkubernetesリソースを利用するユーザーを紐付ける |
| 18 | ClusterRole           | ・クラスタ全体で操作可能なkubernetesリソースをルール定義する |
| 19 | ClusterRoleBinding    | ・ClusterRole と kubernetesリソースを利用するユーザーを紐付ける |
| 20 | ServiceAccount        | ・Pod に　kubernetes リソースを操作させる際に利用するユーザー |

# 3.まとめ

今回は、kubernetes の概念と用語についてまとめました。

時間があるときにこの用語を参考に実際に手を動かしながら、kubernetesの使い方を見ていきたいと思います。

その中でkubernetesのどういう部分が人気が高いのか考えていければと思います。うまくまとめられればqiitaにも投稿してみます。

また、最近マイクロサービスアーキテクチャを採用したシステムとkubernetesの相性がいいと言われますが、その意味も気にしながら手を動かしていこうと思います。

# 参考資料

- [Docker/Kubernetes 実践コンテナ開発入門](https://www.amazon.co.jp/dp/4297100339/)
- [kubernetes公式ドキュメント](https://kubernetes.io/ja/docs/concepts/overview/what-is-kubernetes/)
Rails MVC構造について

#Rails 処理の流れ

1. リクエストが送信されます。リクエストはURL+HTTPメソッドの組み合わせで成り立っている
2. ルータは、コントローラのアクションを呼び出します。どのコントローラで、どのようなアクションであるかは、リクエストの内容によって変わります。
3. コントローラのアクションが実行され、モデルにデータ操作の命令を出します（命令がない場合、そのままビューのフェーズに移ります）。
4. モデルはコントローラからの命令をSQLに翻訳し、DBに命令を出します。
5. DBがデータを返却します。
6. データはコントローラに渡されます。
7. コントローラはデータをビューに渡します。
8. 渡されたデータを元にビューは、HTMLを生成します。
9. HTMLがレスポンスとして返却されます。

---

ルータ　：HTTPサーバからきたリクエストを元にコントローラーのアクションを選択する。
コントローラー　：モデルに命令を出しデータの操作を行う、ビューにデータを渡す。
モデル　：コントローラーの命令を元にSQL発行し、レコード操作を行う
DB　：レコードが保存されている場所
ビュー　：見た目の部分を生成する

*アクション役割（アクション内には主に以下を記述）
・モデルにDB操作の命令を出す
・ビューにデータを渡す（インスタンス変数を定義する）
・リダイレクトを行う、どのビューを呼び出すか記述する
###HTTPメソッド
*HTTPメソッドは、クライアントが行いたい処理をサーバーに伝えるという役割があります。
主だったものを以下に紹介します。

|     GET          |    リソースの取得     |    
|:-----------------|-------------------|
| POST             |   リソースの作成など   |        
| PUT（PATCH）       |         リソースの更新など |      
|        DELETE	  |       リソースの削除 |       

GET:ブラウザからのリクエストの際に使用する。（例）「このページを開く（取得）」
POST:データベースにデータを登録してほしいリクエストの時に使用する。
PUT(PATCH):情報の更新等、データを新しく書き換える時等に使用。
DELETE:情報を削除してほしいというリクエスト時に使用。

---
主なアクション名と対応するHTTPメソッド、URLを紹介します。

| アクション名       |      意味 |    HTTPメソッド   |         URL          |
|:-----------------|------------------:|:------------------:|:------------------:
| index            |           一覧 |        GET      |              /properties      |
| show|            詳細|       GET       |                      /properties/:id|   
| new            |             新規|       GET     |/properties/new|
| edit              |               編集|         GET        |/properties/:id/edit|
| create            |            作成 |      POST      |/properties|
| update        |        更新|      PATCH      |/properties/:id|
|destroy	|削除|DELETE|	/properties/:id	|
【Python】二次元リストを一次元リストに変換する方法

Pythonで二次元リストを一次元リストに変換したい場合がある。
`sum`関数を使えば一行で変換可能。

知らないと一見何をしている処理なのか分からないけど、使ってみると意外と便利。
三次元リストを一次元リストに変換したい場合は`sum`関数を二回使えばよい。

``` python
x = [[1, 2], [3, 4]]
x = sum(x, [])
print(x) # [1, 2, 3, 4]

y = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
y = sum(sum(y, []), [])
print(y) # [1, 2, 3, 4, 5, 6, 7, 8]
```

速度重視の場合は[itertools.chain.from_iterable()](https://docs.python.org/ja/3/library/itertools.html#itertools.chain)を使う。
こちらの方が`sum`関数を使う場合よりも高速。

``` python
import itertools
x = [[1, 2], [3, 4]]
x = itertools.chain.from_iterable(x)
print(list(x)) # [1, 2, 3, 4]

y = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
y = itertools.chain.from_iterable(list(itertools.chain.from_iterable(y)))
print(list(y)) # [1, 2, 3, 4, 5, 6, 7, 8]
```

上記の他にも自作関数を作るという方法もある。
リストの次元数に依らないので、様々な次元数のデータを扱うときはオススメ。

https://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists
Node.jsを使ってサーバにアクセスログを出力してみた

#はじめに
この記事はなんとなくJSなどを勉強している学生がメモ代わりに書いている記事です。内容は期待しないでください。

#1.仮想環境を構築する。
今回はUbuntuで行うのでiTerm2で仮想環境を起動する。

起動したところで
1.Virtual Box(バーチャルボックス)
2.Vagrant（ベイグラント）
という2つのソフトウェアを使った仮想環境でUbuntuを使用します。
cd ~/vagrant/ubuntu
vagrant up
vagrant ssh

Ubuntuがインストールされたディレクトリに移動。vagrant upは仮想的なPCにインストールされたUbuntuを起動するコマンドで,vagrant sshはVagrantの仮想マシンがセットされている状態でSSHに接続します。

#2.作成したサーバにログを表示する
以下の内容をhttp.createServerのアロー関数内に記述します。
```console.info(
  '[' + new Date() + '] Requested by ' + reqest.connection.remoteAddress
);
```
今回はreqestという変数にサーバへのリクエストを代入しています。今回はリクエストが送られたIP情報を出力します。console.infoというものを使用していますがinfoは以下のように分類されます。

|関数名|内容|出力|
|:---:|:---:|:---:|
|info,log|普段から残す情報|標準出力|
|warn,error|警告|エラー標準出力|

#3.作成したサーバにエラーを出力する
```on('error', (e) => {
  console.error('[' + new Date() + '] Server Error', e);
```
以上のon関数をアロー関数後に記述します。

#4.実際にサーバを起動してみる
```node ファイル名
```
実際にサーバを起動してエラー等のコンソールが表示されれば成功です。
Pythonでファイル名が悪くてimportでハマった

ライブラリをちょっと試そうとして、import したいモジュールと同じ名前を付けてハマりました。常識なのかもしれませんが、知らなかったのでメモしておきます。

# エラー

math モジュールを試したくて、math.py というファイルを書いたとします。

```python:math.py
import math
print(math.pi)
```

これを実行するとエラーになります。

```text:実行結果
$ python math.py
Traceback (most recent call last):
  File "math.py", line 1, in <module>
    import math
  File "/home/xxxx/math.py", line 2, in <module>
    print(math.pi)
AttributeError: partially initialized module 'math' has no attribute 'pi' (most likely due to a circular import)
```

# 自分自身を循環参照

原因はエラーに書いてあるように自分自身を import して循環してしまったことです。

> (most likely due to a circular import)

すぐには分からなかったので、適当に print を入れたりしてみました。

```python:math.py
print("math")
import math
print(math.pi)
```
```text:実行結果
$ python math.py
math
math
Traceback (most recent call last):
  File "math.py", line 2, in <module>
    import math
  File "/home/xxxx/math.py", line 3, in <module>
    print(math.pi)
AttributeError: partially initialized module 'math' has no attribute 'pi' (most likely due to a circular import)
```

`math` が2回表示されています。これでようやく、自分自身を参照していることが分かりました。

同じファイルの2回目の import は無視されるので先に進んで、`math.pi` がないことからエラーになります。

# 結論

ファイル名を変えれば動きます。import の対象と同じファイル名は避けましょう。
dockerのコマンドメモ

# 記事の趣旨
dockerコマンドの覚え書き．

## 1. dockerのコマンド

### `docker search 検索キーワード`

Docker Hubに登録されているイメージを，検索キーワードで検索する．

### `docker pull イメージ名`

Docker Hubからイメージを取得する．

### `docker images`

保有しているイメージの一覧を表示する．

### `docker run オプション イメージ名 コマンド`

イメージを用いてコンテナを起動し，コマンドを実行する．かなりオプションが多いので代表的なものだけ以下に書いていく．全量は[こちら](http://docs.docker.jp/engine/reference/commandline/run.html)を参照すること．

- `-d`：コンテナをバックグラウンドで実行する
- `-i`：ホストの標準入力をコンテナの標準入力にアタッチする
- `-t`：コンテナに疑似TTYを割り当てる
- `-p xxx:yyy`：ホストのxxx番ポートにコンテナのyyyポートを割り当てる
- `--name`：コンテナに名前を割り当てる
- `--rm`：コンテナ終了時に自動的に

`-i`とか`-t`とか入れないとどうなるの？という疑問は，[こちら](https://ohbarye.hatenablog.jp/entry/2019/05/05/learn-tty-with-docker)を読めば大体解消すると思う．

### `docker ps`

コンテナの一覧を表示する．

### `docker attach コンテナ名`

コンテナ内のPID-1のプロセスに接続する．離脱する場合は`Ctrl-p + q`で．

### `docker exec オプション コンテナ名 コマンド`

コンテナ内で新たなプロセスを立ち上げてコマンドを実行する．

### `docker build オプション パス`

パスに置いてある`Dockerfile`という名称のファイルを用いてイメージをビルドする，オプションは以下．

- `-f`：ビルドファイル名を明示する．
- `-t 名称:タグ`：イメージにタグをつける

### `docker cp ホストパス コンテナ名:パス`

ホストパスに存在するファイルをコンテナの指定パスにコピーする．

### `docker cp コンテナ名:パス ホストパス`

先述とは逆に，コンテナの指定パスに存在するファイルをホストの指定パスにコピーする．
Windows10からのRDP接続（ubuntu20.04 LTS）

# はじめに

**前回のあらすじ**

[Windows10からのRDP接続（ubuntu16.04 LTS）]
https://qiita.com/hitobb/items/e97b38723304589f4f1d

上記経験から、RDP環境コワイコワイ病に掛かっておりましたが、昨今のリモートワーク/テレワークの波には逆らえず、漂流しかけておりました（※主にやる気が）

そんな中、2020年4月23日にLTSバージョンとなる、ubuntu20.04 LTSがリリース！

これはトラウマを克服するためのちょうど良い機会！
メモらねば。。。

# 前提条件

ubuntu 20.04 Server にデスクトップ環境をインストールするところから開始。

**ワタクシはLTSが使いたいのです！**

ubuntu 18.04LTS → 20.04LTSアップグレード手順については、こちらをご参考ください。

[ubuntu 18.04(LTS)→20.04(LTS)アップグレード方法]
https://qiita.com/hitobb/items/2ee9b1c2c49760976e0f

**ワタクシはLTSが使いたいのです！！**

# 手順

## desktop環境をインストール

CLIでubuntu desktop環境をインストールします。
時代に合わせて、今回は`apt-get`ではなく`apt`を使います。

最初のお約束。

```
sudo apt update
```
```
sudo apt upgrade
```

desktop環境をインストール

```
sudo apt -y install ubuntu-desktop
```

10分程度かかるインストールが完了したのち、再起動

```
sudo reboot
```

コンソールにGUIが表示されればOK
<img width="1017" alt="001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211189/ebe0d4fe-5b2a-8e96-26f0-04afaaa23cb5.png">


## XRDPインストール

apt使って最新のxrdpをインストールします。

**ワタクシはLTSが使いたいのです！**


まずは下準備。
SSHで接続しなおしてから、下記コマンドを実行。

```
sudo apt -y install xrdp
```

xrdp 再起動

```
service xrdp restart
```

これでRDP出来るはず。

<img width="1436" alt="002.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211189/88553fab-5a3a-5569-ffd8-db29dd13164a.png">

かっこいい！

<img width="1434" alt="003.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211189/763e8442-6448-26d2-5b56-f73333ae8dfb.png">

## XRDP接続ポート変更

さて、もうひと作業。

RDPのデフォルトポート「3389」は、インターネット上に公開すると攻撃を受けやすい為、ポートの変更を強く推奨します。

```
sudo vi /etc/xrdp/xrdp.ini
```
ポート部分を3389から別のポートに変更

```
; ports to listen on, number alone means listen on all interfaces
; 0.0.0.0 or :: if ipv6 is configured
; space between multiple occurrences
;
; Examples:
;   port=3389
;   port=unix://./tmp/xrdp.socket
;   port=tcp://.:3389                           127.0.0.1:3389
;   port=tcp://:3389                            *:3389
;   port=tcp://<any ipv4 format addr>:3389      192.168.1.1:3389
;   port=tcp6://.:3389                          ::1:3389
;   port=tcp6://:3389                           *:3389
;   port=tcp6://{<any ipv6 format addr>}:3389   {FC00:0:0:0:0:0:0:1}:3389
;   port=vsock://<cid>:<port>
port=3389 ←ここの数値を任意のポートに変更

; 'port' above should be connected to with vsock instead of tcp
; use this only with number alone in port above
; prefer use vsock://<cid>:<port> above
use_vsock=false

; regulate if the listening socket use socket option tcp_nodelay
; no buffering will be performed in the TCP stack
```
xrdp 再起動

```
service xrdp restart
```
リモートディスクトップ接続する場合は、以下のルールに従ってIPアドレスを指定してください。

```
IPアドレス:変更後のポート番号
```
例えば、`192.168.2.1`に対するRDPの接続ポートを`13389`に変更した場合は、以下を指定します。

```
192.168.2.1:13389
```
ユーザ名/パスワードは、変更なしです。

以上、お疲れさまでした！

# 総括

ubuntu 20.04LTSでのRDP接続環境構築は、とっても簡単！
未来に感謝！
参照がいつまでたってもわからない

わかったことだけメモ。

＜そもそもなんの話か＞
・メモリ管理に関する話。
・変数とかを使っている間、それをメモリに取っておかねばならない。
・使い終わったら解放しないと、メモリがいっぱいになってしまう。

＜前提＞
・swiftの値型では、スコープから抜けると自動でメモリが解放される。参照型の場合はそうではない。
・参照型は複数の箇所から参照されうるので、メモリを解放してよいかを簡単に判断できない。そこで、ARCという方式を使う。
・ARCでは、参照カウントというのを使ってメモリを管理する。（参照カウント＝参照されている数。０になったら解放）

＜参照の種類＞
・強参照(strong)：デフォルト。参照カウントが１増える。
・弱参照(weak)：参照カウント増えない。メモリ解放後はnilが入るようになる。
・非所有参照(unowned)：参照カウント増えない。メモリ解放後に参照しようとするとエラーを投げる。

＜循環参照とは？＞
・こんな感じでお互いに参照しているといつまでたってもメモリが解放されない。→困る。

```swift:
a.hoge = b // bの参照メモリが１増える
b.hogehoge = a // aの参照メモリが１増える
```
→強参照じゃないのを使えば解決！（片方の参照メモリを増やさないことでうまいこと参照メモリが減ってくれるようになる。）


＜参考ページ＞
詳細で正確な説明が載っています……。
<a href="https://medium.com/@shiba1014/swiftのメモリ管理を知る-5fc4f4ade999">Swiftのメモリ管理を知る - Satsuki Hashiba - Medium</a>
Python ファイルに日本語書込みエラーUnicodeEncodeError を解決する

Pythonの鬼門として文字コードの扱いは必ず挙げられると思います。
Pythonを使い始めた初期はこの文字コードの扱いに辟易して二度と使うか！と思ってた時期もありました。
今はもう慣れましたが。。。


さて何をしようとしていたか

1. Pythonスクリプトで、DBのAPIでクエリログを取得する。
2. ファイルに書き込む。

もうこんだけです。

そのクエリログに日本語コメントが入っていると、書き込んだ時に冒頭のUnicodeEncodeErrorが起きることがありました。

その状況と解決を書きてみます。
Python は2.7です。今時ごめんなさい。。。。

## 確認したときは大丈夫だったのに...

DB APIで取得したときは問題なくクエリログを取得できて不要な文字列なども削除できていました。
お試しのログを書き込むこともできた！
そこで、「あーじゃあもうファイルに書き込むだけじゃん！」っと思ってたんですね。

ではそのようにをファイルに書き込んでみましょう。

```python
# -*- coding: utf-8 -*-

# 実際はAPIでログを取得しますが、ここでは動作確認のために文字列のログにします。
log = "aaa 日本語"

with open("test.txt", "a") as f:
    f.write(log + "\r\n")
```

ファイルのtest.txtをみると

```
aaa 日本語
```

ちゃんと書かれてる。じゃあもうAPIからクエリログを取得して動かすだけだ。
っと思っていたんですね。そこでAPIからログを取得して書き込んでみたら下記のようなエラーが。。
（すみませんがAPIの部分は省略させてもらいます）

```python

Traceback (most recent call last):
  File "writetest.py", line 11, in <module>
    f.write(log + "\r\n")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 4-6: ordinal not in range(128)
```

__結論から言うと、APIで取得した文字列がUnicode型で扱われていました。
どうもpython2ではwriteで書き込むときはデフォルトのasciiで書き込もうとするから起きるエラーのようです。__
あまり詳しく調べられてませんが、そういうものみたいです。

どうやって解決したかというと

```
log = log.encode("utf_8")
```

というように一度utf-8に変換して書き込みました。

```python

# -*- coding: utf-8 -*-

# APIでログを取得
log = (APIでログを取得)

log = log.encode("utf_8")

with open("test.txt", "a") as f:
    f.write(log + "\r\n")
```


ちなみにですが、

```
f.write(log.encode("utf_8") + "\r\n")
```

でも同様のエラーでした。

## その他解決方法

上記の解決も含て

+ 一度utf-8に変換する ex. log = log.encode("utf_8")
+ codecモジュールを使ってファイルオープンするときに"utf_8"で開いて書き込む
+ python3だとopenの時に文字コードを指定できるので、"utf_8"で開いて書き込む

といった方法があるようです。

## Unicode型の動作
ちなみにUnicode型の簡単な動作を確認してみましょう。

```python
# coding: utf-8

str_1 = "日本語"
str_2 = u"日本語"

print str_1
print str_2

print type(str_1)
print type(str_2)

print len(str_1)
print len(str_2)

print ("本" in str_1)
print (u"本" in str_2)

print str_1.find("本")
print str_2.find(u"本")
```

これを実行すると

```python
日本語              # print str_1
日本語              # print str_2
<type 'str'>       # print type(str_1)
<type 'unicode'>   # print type(str_2)
9                  # print len(str_1)
3                  # print len(str_2)
True               # print ("本" in str_1)
True               # print (u"本" in str_2)
3                  # print str_1.find("本")
1                  # print str_2.find(u"本")
```

ざっと見た感じ、
str型は文字列がバイト形式で扱われていて
unicode型は(人が直感的に判断できる)文字として扱われている
とわかりますね。

このことからも文字列を扱うのであればunicodeの方が扱いやすいかと思います。

そのためであれば冒頭のpythonによるAPIでログを取得したときのログはunicode型で取得されていたことが理解できます。

ちなみにですが、このへんの動きはまったく知りませんでしたw
IBMの「Liberty」について整理する

IBMから提供されているJava EE対応のアプリケーションサーバー「WebSphere Application Server」には，2012年からLibertyという新しいランタイムが提供されています。このLibertyという言葉はいろいろな意味で使われることがあり，混乱しているケースが（IBM社員でも）しばしばみられますので，整理してみたいと思います。

# ランタイム

- Libertyプロファイル / WebSphere Liberty

前者はWAS V8.5の時の名称で，後者はV9.0での名称です。2012年に出荷されたV8.5から新しく追加されたランタイムです。クラウド時代に対応するために新たに開発されたランタイムで，完全モジュール化された軽量・高速なランタイムで，DevOpsやコンテナなどのモダンな環境にも適しています。

現在も活発に新機能の開発や新仕様への対応などが続けられています。

- Fullプロファイル / WebSphere traditional

前者はWAS V8.5の時の名称で，後者はV9.0での名称です。tWASとよばれることもあります。

1998年の登場以来バージョンアップが続けられている，従来型のランタイムです。過去との互換性に優れており，古いJava EEの仕様や，従来提供されていたIBM独自APIなどもほとんどそのまま利用できます。管理概念やツールなどもWAS V5.0のころからのものをほとんどそのまま継承しています。

ただ，モノリシックな実装が限界に達しており，現在提供されているものが最終バージョンで，今後は新機能の実装などはおこなわれません。

# ライセンス

IBMから[購入するライセンス](https://www.ibm.com/jp-ja/cloud/websphere-application-server)としては，三種類のエディションがあります。

- WebSphere Application Server Network Deployment（通称WAS ND）
- WebSphere Application Server（通称WAS Base）
- WebSphere Application Server Liberty Core（通称Liberty Core）

じつは，WAS BaseエディションやWAS NDエディションでも，WebSphere Libertyランタイムは使用できます。これらのエディションのライセンスは，購入いただいたCPU数の範囲で，WebSphere LibertyランタイムとWebSphere traditionalランタイムを自由に選択してご利用いただけます。

Liberty Coreエディションは，安価なWebSphere Libertyランタイム専用のライセンスです。このライセンスでは，WebSphere traditionalランタイムは使用できません。またWebSphere Libertyランタイムも，利用できるAPIがJava EEのサブセット，Web Profileに限定されています。

また，2021年1月からは[WebSphere Hybrid Edition](https://www.ibm.com/jp-ja/cloud/websphere-hybrid-edition)というライセンスも購入できるようになっています。このライセンス1コアあたり，WAS NDライセンス 1コア，またはWAS Baseライセンス4コア，またはLiberty Core 8ライセンスとして使用することができます。また変換する組み合わせは，再購入することなく自由に変更することができます。

# まとめ

表にまとめるとこのようになります。
<img width="640" alt="WebSpherのエディションとランタイム" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60041/9e0c25be-a1c6-c971-bafa-3a1a2db76971.png">

Libertyという名前が，Liberty Coreというエディション名とWebSphere Libertyというランタイム名で混同されて使われることがありますので気をつけましょう。

# Libertyを無償で使うには

おおきくは二つの方法があります。

- 製品版を開発者ライセンスで使用する
- OSS版のOpen Libertyを使用する

製品版のWAS BaseのLibertyは，[開発者版が無償でダウンロード](https://www.ibm.com/support/pages/websphere-liberty-developers)できます。こちらは，開発者が専有して利用する機器上での実行で使用できます。ローカルのPCで[Eclipseと組み合わせ](https://marketplace.eclipse.org/content/ibm-liberty-developer-tools)てテスト実行するなどの用途が想定されています（複数の開発者で共有したり，他からネットワーク経由で接続して利用する開発機などの場合は，有償のライセンスが必要になります）。開発者版は，購入後に提供される[ライセンスファイルを適用する](https://www.ibm.com/docs/ja/was-liberty/base?topic=archives-applying-license-liberty-installations)ことで正式版に変更できます。

[Open Liberty](https://www.openliberty.io/)は，OSS版のLibertyです。Libertyは，現在はOpen Libertyとして開発され，それを取り込む形で製品版が作られています。Open Libertyと製品版のWebSphere Libertyでは，[提供されている機能（フィーチャー）が異なっています](https://www.ibm.com/docs/ja/was-liberty/base?topic=management-liberty-features)が，両方で提供されているフィーチャーは全く同じ機能が提供されていますし，構成ファイルなども共有できます。
application.propertiesの設定を環境変数を用いてlocal起動とDocker起動で切り替える

# はじめに
下記の記事からの補足になる
【IntelliJ + Docker (APP+DB) + SpringBoot (Maven) 環境構築】
https://qiita.com/SSM3G/items/bd61970648d94ccb691a

# docker-compose.ymlに環境変数を記載

**environment**でDockerコンテナを起動する際に渡す環境変数を記述できる

```yml:docker-compose.yml
version: '3'
services:
  app:
    image: openjdk:14-jdk-alpine
    ports:
      - "80:8080"
    volumes:
      - .:/app
    working_dir: /app
    command: ./mvnw spring-boot:run
    environment:
      DATASOURCE: jdbc:mysql://db:3306/sample
  db:
# 省略
```

# application.propertiesに環境変数を記載
下記部分
**spring.datasource.url=${DATASOURCE:jdbc:mysql://localhost:3306/sample}**

```properties:application.properties
spring.datasource.url=${DATASOURCE:jdbc:mysql://localhost:3306/sample}
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
```

`${環境変数:デフォルト値}`と記載
環境変数が設定されている場合は環境変数を読み込む
設定されていない場合はデフォルト値を読み込む

# SpringBoot起動
## ローカル起動
環境変数は何も設定していないため
デフォルト値の`jdbc:mysql://localhost:3306/sample`を読み込む

## Docker起動
docker-compose.ymlで**DATASOURCE**という名で環境変数を設定しているため
appのコンテナ内ではこの環境変数が適応される

1.コンテナ内でSpringBootを起動
2.コンテナ内のapplication.propertiesを読み込む
3.環境変数の`jdbc:mysql://db:3306/sample`を読み込む

![screenshot.73.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619433/a02b854e-71df-9b48-710d-7a3661ddbf2c.jpeg)
`set`で環境変数を確認したところ、ちゃんと設定されていました

# おわり
`${環境変数:デフォルト値}`の書き方が全然わからなくてハゲそうだった
SprinBoot application.properties 環境変数 切り替え 変数 リテラル ${} シェル変数 とかで色々調べちまった
UdonSharp日記～メニューを自作する～

#やったこと
今回はキーボードのESCを押した際にオリジナルのメニューを表示する機能を作成しました。
今手元にviveコンがないのでデスクトップモードのみを対象としています。
(発火させるボタン登録を変更すればVRモードでも実行可能)
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">UdonSharpをこねこねしてESCキーでオリジナルのメニューがでるようにしてみた。<br>消すにはもう一度ESCキーをプッシュ。<a href="https://twitter.com/hashtag/UdonSharp?src=hash&amp;ref_src=twsrc%5Etfw">#UdonSharp</a> <a href="https://t.co/rxmWsufWeh">pic.twitter.com/rxmWsufWeh</a></p>&mdash; はんちょ (@sadimensions) <a href="https://twitter.com/sadimensions/status/1255761841612980224?ref_src=twsrc%5Etfw">April 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#参考文献
uGUIからUdonSharp関数を呼び出す方法について
[ハツェさんのUdon#入門③](https://hatuxes.hatenablog.jp/entry/2020/04/05/013336)

#やり方
Canvasを作成します。
メニューを出すのに直接は関係ないですが、同時にuGUIからmanagerのUdonSharp関数呼び出しと、値の取得を試したかったため、Button, Slider, Textを追加しています。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627563/dfe75c7c-78ea-ab50-ae9f-5420383ea1ca.png)

![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627563/e5d47e0f-b6b2-abb7-ee92-37f7c7963f12.png)

実装の方針は
1.ESCキーが押されたら
　2.メニューがアクティブならば非アクティブにして消す
　3.メニューが非アクティブならば　ユーザーの座標近くにメニューを移動して　アクティブにする。

という考えです。

```c#:
    private void UM_Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape)) 
        {
            if (UM_userMenue.activeSelf)
            {
                //メニューがアクティブならば、非アクティブ化
                UM_userMenue.SetActive(false);
            }
            else
            {
                //非アクティブならば、プレイヤーの前に移動しアクティブ化

                //座標設定
                Vector3 pos = GEN_localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).position;
                Quaternion rot = GEN_localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).rotation;
                //オイラー角に変換後、メニューが垂直になるようにx軸を0にする。
                Vector3 rotEuler = rot.eulerAngles;
                rotEuler.x = 0;
                //オイラー角をクォータニオンに戻し、プレイヤー座標とずらす距離を計算する
                rot = Quaternion.Euler(rotEuler);
                Vector3 bias = rot * new Vector3(0f, 0f, 0.5f);//0.5mだけ前に出す
                //座標設定
                UM_userMenue.transform.position = pos + bias;

                //角度設定
                UM_userMenue.transform.rotation = rot;

                //アクティブ化
                UM_userMenue.SetActive(true);
            }
        }
        //プレイヤーとの距離が遠い場合は非アクティブ化
        float seqDist = Vector3.SqrMagnitude(GEN_localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).position - UM_userMenue.transform.position);
        if(seqDist > 4.0f)
        {
            UM_userMenue.SetActive(false);
        }
    }
```

クォータニオンはよくわかりませんが、Vector3に掛け合わせると、クォータニオンの軸に従って回転してくれること。
直接操作できなくてもオイラー角に直せばなんとなく加工できることがわかりました。


メインとなるUodate関数は次の通り

```c#:
    void Update()
    {
        GEN_Update(); //前回の記事参照
        UM_Update();  //今回追加したもの
        FM_Update();  //前回の記事参照
    }
```

uBUIのボタンからUdonSharp関数を呼び出す方法については参考文献にそのまま乗っているので、今回は記載しません。

他のオブジェクトから引数渡しでUdonSharpを呼び出すことはできませんが、uGUIのTextにデータを書き込んでから呼び出せば、実質データを渡しての外部からの実行ができそうですね。
ボタンを押すと、Textへ渡すデータを書き込む関数と、動かしたい関数を呼び出せば、うまくいきそう・・・

でももし二つが非同期で同時に走ったらそれもそれで面倒な予感はあります。
さくらVPSにmaria db + nginx + headlessCMSのstrapiを入れる

# さくらインターネットでVPSを契約
# 基本環境はCentOS7を選択
# nginx インストール
```
yum -y install nginx
```
# marina dbをインストール
```
yum install mariadb-server
systemctl enable mariadb
systemctl start mariadb
```
# Node.js インストール
```
curl -L git.io/nodebrew | perl - setup
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
source ~/.bash_profile
nodebrew install-binary stable
nodebrew use stable
```
# strapiのインストール
```
npm install strapi@alpha -g
cd /usr/share/nginx/html
strapi new blog
```

# nginxの設定の追加
```/etc/nginx/nginx.conf
location / {
     proxy_pass http://localhost:1337;
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection 'upgrade';
     proxy_set_header Host $host;
     proxy_cache_bypass $http_upgrade;
}
```

# pm2による自動起動の設定
https://qiita.com/kuryus/items/fbdc373f23d3236ebb04

# nuxtのプロジェクト作成
```
$ yarn create nuxt-app my_blog
yarn create v1.15.2
[1/4] 🔍  Resolving packages...
warning create-nuxt-app > sao > download-git-repo > download > mkdirp@0.5.4: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
warning create-nuxt-app > sao > micromatch > snapdragon > source-map-resolve > resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
warning create-nuxt-app > sao > micromatch > snapdragon > source-map-resolve > urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
warning Your current version of Yarn is out of date. The latest version is "1.22.4", while you're on "1.15.2".
info To upgrade, run the following command:
$ brew upgrade yarn
success Installed "create-nuxt-app@2.15.0" with binaries:
      - create-nuxt-app

create-nuxt-app v2.15.0
✨  Generating Nuxt.js project in my_blog
? Project name my_blog
? Project description My world-class Nuxt.js project
? Author name Rickey
? Choose programming language JavaScript
? Choose the package manager Yarn
? Choose UI framework Vuetify.js
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules Axios
? Choose linting tools ESLint
? Choose test framework None
? Choose rendering mode Universal (SSR)
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
```
# Netlifyの登録
https://qiita.com/isihigameKoudai/items/e3b136e9964f1d30d73d
https://ja.unflf.com/tech/netlify/route53/
【Rails】Kaminariで同一ページにもっと見るを複数実装する


# 通常の場合
```home_controller.rb
def index
  @cats = Cat.page(params[:page]).per(1)
end
```

```app/views/home/index.html.erb
<%= paginate @cats %>
```
# 複数の場合
```home_controller.rb
def index
  @cats = Cat.page(params[:cats_page]).per(1)
  @dogs = Dog.page(params[:dogs_page]).per(1)
end
```

```app/views/home/index.html.erb
<%= paginate @cats, param_name: 'cats_page' %>
<%= paginate @dogs, param_name: 'dogs_page' %>
```
# ajaxを利用したもっと見るの場合
```home_controller.rb
def index
  @cats = Cat.page(params[:page]).per(1)
  @dogs = Dog.page(params[:page]).per(1)
  return unless request.xhr?
  case params[:type]
  when 'dog', 'cat'
    render "#{params[:type]}"
  end
end
```

```app/views/home/index.html.erb
<%= link_to_next_page @cats, 'もっと見る', remote: true, params: { type: :cat }, id: 'more-cat' %>
<%= link_to_next_page @dogs, 'もっと見る', remote: true, params: { type: :dog }, id: 'more-dog' %>
```
```app/views/home/cat.js.erb
$('.cat-wrap').append('<%= escape_javascript(render 'cat', object: @cats) %>');
$('#more-cat').replaceWith('<%= escape_javascript(link_to_next_page(@cats, 'もっと見る', params: { type: :cat }, remote: true, id: 'more-cat')) %>');

```
```app/views/home/dog.js.erb
$('.dog-wrap').append('<%= escape_javascript(render 'dog', object: @dogs) %>');
$('#more-dog').replaceWith('<%= escape_javascript(link_to_next_page(@dogs, 'もっと見る', params: { type: :dog }, remote: true, id: 'more-dog')) %>');
```

## 参考
https://qiita.com/Coolucky/items/bde74b020b8d37ccf426
https://www.rubydoc.info/github/amatsuda/kaminari/Kaminari/ActionViewExtension
LaTeX メモ 自分用

# 行列

```
\[
  A = \left(
    \begin{array}{ccc}
      a & b & c \\
      d & e & f \\
      g & h & i
    \end{array}
  \right)
\]
```

```math
  A = \left(
    \begin{array}{ccc}
      a & b & c \\
      d & e & f \\
      g & h & i
    \end{array}
  \right)
```

# 場合分け

```
\begin{eqnarray}
c_{k,l}=\left\{ \begin{array}{ll}
1 & (l=k) \\
\alpha & (|l-k|=1) \\
0 & (\text{上記以外}) \\
\end{array} \right.
\end{eqnarray}
```

```math
\begin{eqnarray}
c_{k,l}=\left\{ \begin{array}{ll}
1 & (l=k) \\
\alpha & (|l-k|=1) \\
0 & (\text{上記以外}) \\
\end{array} \right.
\end{eqnarray}
```

# ベクトル表記

```
\mathbf{V}
```

```math
\mathbf{V}
```

# 参照URL

* [行列 - LaTeXコマンド集](http://www.latex-cmd.com/equation/matrix.html)
【Python】複数グラフを描くときはravel()が便利

複数のグラフを描画する際、ravel()を使うと制御が楽。

`plt.subplots()`すると`axes`に二次元配列ができるため、`for loop`でグラフを描くときネストしなければならないが、`ravel()`で一次元配列にしてやれば、ネスト不要。

```python:
import pandas_datareader.data as web
import datetime
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()

dic = {'Unemployment rate':'UNRATE',
       'USHY spread': 'BAMLH0A0HYM2',
       'CPI':'CPIAUCSL',
       '10 year treasury': 'DGS10',
      'Federal Funds Rate': 'FEDFUNDS',
      'Industrial Production Index':'INDPRO',
      'Household Debt to GDP': 'HDTGPDUSQ163N',
      'Real GDP': 'A191RL1Q225SBEA',
      'WTI oil price': 'WTISPLC',
      'VIX': 'VIXCLS',
      'S&P500': 'SP500'}

source = 'fred'

start = datetime.datetime(2015, 1, 1)
end = datetime.datetime(2020, 5, 1)

h = ((len(dic)+1)//2)*4

fig, axes = plt.subplots(6,2, figsize = (15,h))

for ax, (ttl, symbol) in zip(axes.ravel(),dic.items()):
    dt = web.DataReader(symbol,source, start, end)
    ax.plot(dt)
    ax.set_title(ttl) 
    ax.grid(True)

plt.tight_layout()
plt.savefig('FRED',bbox_inches="tight")   
```

![FRED.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341224/3b5101de-32fd-29c2-ad5b-94e7931a3879.png)
Pythonで自作C++ライブラリを呼び出そう(環境設定編)

#Pythonで自作C++ライブラリを呼び出そう(環境設定編)

##概要
表題の件、暇なので大好きな言語1推しのC++ と、急浮上で2推しになったPythonと
連携させてみたいということで、調べたら、Microsoftの公式ページでチュートリアルがったので
それに従って実行した記録である。

特に詰まったポイントなどを、ハードコピーつきで記録しておきたい。

##参考ページ
マイクロソフトの公式ページ
[Python 用 C++ 拡張機能の作成](https://docs.microsoft.com/ja-jp/visualstudio/python/working-with-c-cpp-python-in-visual-studio?view=vs-2019)
を参考に

##Python環境のインストール
自分のPCには、既に最新(2020/4/30時点)の64bit版Pythonがインストールされていた。
よくチュートリアル読まずに進めていたのだが、これが逆にハマるポイントだった。
VisualStudioのインストーラを使って32bit版をインストールすれば安心だ。


ところが、それはどこにインストールされたのか、レジストリエディタで確認するらしい
コンピューター\HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\3.7\PythonPath

私の場合、C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64
だった。
これを、環境変数
PYTHONPATH
に通す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480709/73724947-9f57-a2f2-fe25-c4131e0d95e4.png)

上記でもだめだった、python3.6である必要があるらしい。

https://www.python.org/downloads/release/python-361/
からインストールして、上記の環境パスを設定

##結果
圧倒的な速度向上が分かる。
とはいえ、こんなレベルで速度求める処理を組む機会はないだろうし
Pythonライブラリは豊富なので、実務的に使うことはまずないかな（個人的には）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480709/6e66af36-2518-d38d-e1fb-cbc16134c679.png)
Zoom (>= v4.6.10) で Snap Camera 等の仮想カメラを使う

**Zoom** (>= v4.6.10) **で** Snap Camera 等の**仮想カメラを使うには**、
**zoom.up.appの署名を取り除け**ば（or 自分で署名し直せば）良い。

<img width="787" alt="スクリーンショット 2020-04-30 16.08.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627793/c3fc7165-e7ff-bad0-abee-de7cf1d847d1.png">

# 方法
*Xcode is required!* : 以下のコマンドの**どちらか一方**をターミナルで実行

■**署名の除去**

```
$ codesign --remove-signature /Applications/zoom.us.app/
```
■オレオレ再署名

```
$ codesign --force --deep-verify --sign {your cert name} /Applications/zoom.us.app/
```

# 参考
▼Xcodeのダウンロード（数GBと重いので注意）
https://apps.apple.com/jp/app/xcode/id497799835?mt=12

▼再署名の方法
https://qiita.com/zeriyoshi/items/78b4c7227217e2eac536

▼zoomと仮想カメラの関係（redditのリンクがqiitaではじかれたので検索して下さい)
「FYI Zoom v4.6.10 breaks Blackmagic capture devices as a source」で検索
[ネタ]iPhone Xに物理ホームボタンを追加する[ネタ]

最近のiPhoneって、ホームボタンないんですってね。
ホームボタンあったら、嬉しいですよね？
Android使いなのでよくしらないですが。

ESP32を使って物理ボタンを追加しましょう。

# 仕組み

ArduionoのライブラリーでBluetoothキーボードにできるものがあったので、これを使います。

ESP32-BLE-Keyboard
https://github.com/T-vK/ESP32-BLE-Keyboard


# 準備するもの

ESP32-DevKitC V4
ブレッドボード
タクトスイッチ

こんな感じです。

![IMG_20200430_161245.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/c22f04d2-0667-978a-432b-64b113514bb1.jpeg)


# ソース

タクトスイッチが押されたら`command + H`を送ります。それだけです。

```c++
#include <Arduino.h>
#include <BleKeyboard.h>

BleKeyboard bleKeyboard;

const int switchPin = 32;

int currentState = 0;
int beforeState = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(switchPin, INPUT);

  bleKeyboard.begin();
}

boolean isChange(int current, int before)
{
  return (current != before) && (current == 1);
}

void loop()
{
  currentState = digitalRead(switchPin);

  if (isChange(currentState, beforeState))
  {
    Serial.println("Change!!!");

    if(bleKeyboard.isConnected()) {
      bleKeyboard.press(KEY_LEFT_GUI);  // Windows key
      bleKeyboard.press(0x68);  // H key
      delay(100);
      bleKeyboard.releaseAll();
    }
  }

  beforeState = currentState;

  delay(100);
}
```

# 使ってみた

手元にあるiPadで試してみました。
Bluetoothの設定にて`ESP32 BLE Keyboard`とペアリングをすれば準備完了。

タクトスイッを押せばホーム画面に戻ります！期待通り！

**ただし！物理キーボードが接続されていると判定されるので、テキスト入力が必要なところでソフトウェアキーボードが出ません！！！**

どうしても使いたい場合は、下向き三角（下図）を長押しするとソフトウェアキーボードが出てくれます。一度ソフトウェアキーボードが出る状態になると、次からもソフトウェアキーボードが出ます！

![コメント 2020-04-30 160915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/ad502a06-14d5-0617-4989-917c34fac381.png)

やった！ **これで、物理ホームボタンの完成です！**
仮想マシンにCentOSをインストールしてみた

##はじめに
前回の記事の続きです。
https://qiita.com/ysda/items/fbfc90ba0161f2e65257

前回の記事と今回の記事で、仮想環境を1から作れるようになります。
OSやメモリなどを自分で設定するため、ユーザーから報告を受けたバグを再現する時などに役立ちます！

##早速インストール
まずEsxiにログインして、datastore→データストアブラウザを選択します。
![スクリーンショット 2020-04-30 14.31.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/cd7634c8-adbb-8c78-050e-a0a824e37da7.png)
![スクリーンショット 2020-04-30 14.34.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/648671e2-ee62-41a3-5795-9ddcddfe9b9e.png)

アップロードボタンを押下すると、ファイル選択のダイアログが表示されるので、
あらかじめダウンロードしておいたCentOSのisoファイルをアップロードします。
数GBのファイルなので、気長に待ちましょう。
![スクリーンショット 2020-04-30 14.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/6d09542e-1917-0489-7fa2-e89eb749b85c.png)

それでは仮想マシンの作成を行いましょう。
![スクリーンショット 2020-04-30 15.04.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/7697e383-1a88-9f3c-423a-c38c5d367af3.png)

マシンの名前は任意のものを入力。
今回はCentOS８をインストールするので、ゲストOSファミリはLinux、ゲストOSのバージョンはCentOS8を選択します。
![スクリーンショット 2020-04-30 15.06.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/10f10289-a569-3e16-c84d-21692646a24e.png)

リソースの割り当て。
各々で必要な分を割り当ててください。
![スクリーンショット 2020-04-30 15.09.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/8ee8c94f-fef7-47ea-92a9-c2f369618364.png)

仮想マシンができました！
![スクリーンショット 2020-04-30 15.15.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/d635b3c9-53ff-48a5-d224-c8b3575e8569.png)

仮想マシンを起動させると黒い画面になります。「Install CentOS Linux8」を選択しましょう！
![スクリーンショット 2020-04-30 15.20.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/70e9c9fc-4305-b446-d41b-8d7fb28f14e5.png)

言語は日本語を選択。
![スクリーンショット 2020-04-30 15.21.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/2c3445e7-944b-f49d-51e0-d6cf9e6b9597.png)

こんな感じの画面になります。インストールの開始を押したいところですが、一旦ネットワークの設定を行います。
LAN内のPCでサーバーを遠隔操作できるようにするためです。
![スクリーンショット 2020-04-30 15.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/999ddc26-2d39-7874-7422-a8834d614697.png)

まずはEthernetをオンにします。その後設定画面で静的なIPを割り当てます。
![スクリーンショット 2020-04-30 15.38.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/b3f4d0e5-bde9-a2d9-75b8-3eada2fb71cb.png)
![スクリーンショット 2020-04-30 15.47.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/2ba26afd-42d2-3085-f02f-0db8dedc1ec7.png)

IPの設定が終わったら元の画面に戻ってインストールを開始します。
インストール中にルートユーザーのパスワードを設定できるので、ついでに設定しておきましょう。
![スクリーンショット 2020-04-30 15.50.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/00933a01-dfaf-6c76-2316-a8ad1596702b.png)

##ターミナルからSSHでログインしてみる
sshコマンドを実行した後に先ほど設定したパスワードが求められるため、入力しましょう。

```
% ssh root@192.168.1.8
root@192.168.1.8's password: 
Activate the web console with: systemctl enable --now cockpit.socket
[root@localhost ~]# 
```
念のためバージョンがCentOS8になっているか確認

```
[root@localhost ~]# cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core) 
```
無事CentOSをインストールできました！
仮想環境に作っているので、リソースの範囲内でUbuntu入れたりRHEL入れたりも出来ます！
興味を持った方はぜひやってみてください！
PHPでのMySQL (データベース)接続　PDO

##PDOとは
PHP Data Objectsrの略称
PHPからデータベースのアクセスを抽象的にしてくれるもの

###PHPからMySQLに接続するコード例（SELECT文）
```php

<?php

$mysql    = 'mysql:host=localhost;dbname=xxxxxx,charet=utf8';
//xxxxxx === 自分のmysql中の接続したいデータベース名
$user     = 'xxxxxx'; 
//xxxxxx === 自分のmysqlユーザー名
$passwoad = 'xxxxxx'; 
//xxxxxx === 自分のmysqlパスワード

try {
	$db     = new PDO($mysql, $user, $passwoad);
	$select = "SELECT　* FROM" ;
	$res    = $db->query($select);

} catch (PDOException $e) {
	echo '接続エラー: ' . $e->getMessage();
}

?>
```
Geant4をUbuntu18.04.4 LTSにインストールする

#導入

新しく購入したLinux PCにGeant4(以下、G4)をインストールした際の環境メモである。
詳細についてはここよりも優良なサイトがある。

【Geant4 インストール】
https://qiita.com/aximov/items/3387e4cba7040f2acfe2
Qiitaの記事で最も簡潔にG4インストールなどについてまとまっているサイト

【Geant4初心者講習会・研究会】
https://wiki.kek.jp/display/geant4/Geant4+Japanese+Tutorial+for+Detector+Simulation+2019
KEKのスタッフらによる初心者講習会。ここの資料があれば自分でもできる。

#環境

- Ubuntu 18.04.4 LTS
- gcc 7.5.0
- GNU Make 4.1
- CMake3.17.2
- expat 2.2.5
- libexpat1-dev 2.2.5
- xorg-dev 1:7.7+10ubuntu7.1
- freeglut3-dev 2.8.1

今回インストールしたG4バージョン
- Geant4.10.04.p01

#Genat4 Visuallization

Geant4 の visuallization には色々とある。

#Qt5のインストール

一般的に使用されるものの中で一番使いやすいのはQtである。
GUIの画面で粒子走らせたりができるので、便利。
ただ、結構重いのでそれなりにハイスペックなPC(GPUを積んでいるもの）や、軽いgeometryを動かす際に利用した方が良いかと思います。
（Qtが重いけれどもグリグリと3DモデルをGUIで操作したいならば、VRMLを利用することをオススメする）




#CMakeのオプション

CMakeをする際のoptionは次のようにする。

```
cmake \
-DCMAKE_INSTALL_PREFIX=/path/to/geant4.10.06.p01-install \
-DGEANT4_INSTALL_DATA=ON \
-DGEANT4_USE_QT=ON \
/path/to/geant4.10.06.p01
```


オプション一覧[under construction]

```
hogehoge
```

## おまけ（ccmake）

デバッグなどをする際に一番厄介なのは正常動作している環境との違いだと思います。その際に重要なのが、cmakeをしたときのオプションの確認です。geant4-config --helpでも確かめることは可能ですが、ccmakeを使うことでよりわかりやすく見ることができます。
以下を参照
https://alt-native.hatenadiary.org/entry/20121224/1356319986


# 可視化(Visualization)

（メモ）
VRML2FILEで見るときは、以下の二行が必要であることに注意

```
/vis/open VRML2FILE
/vis/viewer flush
```

# まとめ

随時更新予定ではありますが、上記資料と環境だけで問題なくできたのでここではなく別のところを参照しましょう。

# 参考

http://be.nucl.ap.titech.ac.jp/~ryuki/iroiro/geant4/
いつまで誤差で消耗しているの？

# 「誤差はあるもの」という強烈な違和感

[AtCoder](https://atcoder.jp/)というプログラミングコンテストサイトで出された、「[Sqrt Inequality](https://atcoder.jp/contests/panasonic2020/tasks/panasonic2020_c)」(平方根の不等式)という問題。

```
「a, b, c という正数の変数が与えられるので、 "√a + √b < √c" という不等式が成り立つか判定せよ」
```

という内容。

```PHP
<?php
fscanf(STDIN, "%d %d %d", $a, $b, $c);
echo sqrt($a) + sqrt($b) < sqrt($c) ? "Yes" : "No";
```

という2行のコードを書きつつ、

（´-`）.｡oO（100点問題ならまだしも、300点問題だし、このままじゃ正解にならんだろうな……）

と思いながら、コードを提出。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90217/c6c8d627-6e19-f3c3-507a-1d4a09f1a99f.png)

**はい、不正解 WA（Wrong Answer)。**

不正解になったテストケースの一つ、テストケース6では、 a = `249999999`、 b = `250000000`、 c = `999999998` 。
計算してみると、 √a + √b が `31622.77657006101667…` 、 √c が `31622.77657006101670…` となり、小数点第14位で違いが出て、 √c の方が大きいため、正解は「Yes」なんですが、プログラム言語によっては同じ数値になってしまい、「No」と出力されるので不正解となります。

PHP 7.4.2で計算してみると、 √a + √b も √c も `31622.77657006101799…` と同じ数になってしまうので、これが原因です。

この問題も、だいたいの言語ではいまだに `精度` や `誤差` の関係でストレートな回答では正解できない、という前提となっています。（そうでないならこの問題は100点のはずです）

いや待て、コンピュータ黎明期ならまだしも、それから何十年と経って高性能化も著しい中で、 **いまだに計算に誤差があるとか、精度ガー、とか、ダサくない？、と感じないでもありません。**

# 真っ向勝負で解く

この問題の[解説](https://img.atcoder.jp/panasonic2020/editorial.pdf)を見ると、不等式を工夫して平方根記号を排除し、整数の計算で判定してね、という流れになっています。（整数計算だと基本的に精度の問題がなく、誤差とか、丸め誤差などがないため）
一方で、時代の進化によってそういう回り道をしないでも、正面突破で計算する手段が用意されていたりします。
PHPで言うと「[BCMath 任意精度数学関数](https://www.php.net/manual/ja/book.bc.php)」というライブラリで、任意の精度の計算結果を得ることができます。

BCMathライブラリ自体は昔からありますが、AtCoderでは非対応でした。でも最近、バージョンアップにより対応になったんです。そんな訳で、レッツチャレンジ。

```PHP
<?php
bcscale(14);

fscanf(STDIN, "%d %d %d", $a, $b, $c);
$aa = bcsqrt($a);
$bb = bcsqrt($b);
$cc = bcsqrt($c);
$dd = bcadd($aa, $bb);

echo gt($dd, $cc) ? "Yes" : "No";

function gt($a, $b) {
	$len_a = strlen($a);
	$len_b = strlen($b);
	$len = max($len_a, $len_b);
	$aa = str_repeat("0", $len - $len_a) . $a;
	$bb = str_repeat("0", $len - $len_b) . $b;
	$cc = bcsub($aa, $bb);

	if (preg_match("/\.0+1$/", $cc)) {
		return false;
	}

	$ret = strcmp($aa, $bb);
	return $ret < 0;
}
```

BCMath関数では計算結果が文字列で返されるので、文字列として大小を比較しなければなりません。
さっそく提出……と思いましたが、この問題のコンテストは、まだ非対象でした（2020年4月から対象）。仕方ないので、ローカルで実行。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90217/f1728941-050b-0517-e40d-a96ff3f4e4db.png)

とりあえず正解なようです。

# おまけ
テストケース6〜10が `√a + √b < √c` 、
テストケース11〜20が `√a + √b = √c` 、
テストケース21〜22が `√a + √b > √c` の微小差のケースとなっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90217/ac51c581-7559-5f7b-f9b9-3d02e3c9434a.png)
Eclipseのm2eプラグインとMavenの関係

タイトル通りですが、初心者すぎて私がわからなかったのでメモっておきます。

## m2eプラグイン
これは、Eclipse上からMavenを実行するためのプラグインです。
今回、JavaEE開発用のEclipseを使いましたが、その場合はデフォルトで入っています。

## わからなかったポイント
Eclipse上で右クリックしてMavenの実行を行うと、ポップアップが表示され、ゴールを指定する画面が出てきます。

一方で、世に出回っているMavenの記事を参照すると

```
mvn compile
```

のようなコマンドが良く出てきます。
私はこの関連性がよくわからず、mvnコマンドを実行したいんだけど、コマンド引数はどこに設定すればいいんだろう？と思ってました。

## Eclipse上でMavenを実行するには

m2eプラグインで表示されるポップアップのゴールに設定するのは、上記で言えば「compile」の部分です。
mavenではmvnコマンドの後にゴールを指定するという書式になっており、ものすごく大雑把に言うとmvnコマンドの引数＝ゴールというイメージになります。

また、2つ以上ゴールがある場合、例えば

```
mvn package deploy
```

のような場合もポップアップのゴール欄に「package deploy」と入力すればOKです。

つまり、m2eプラグインのポップアップの画面でゴールにmvnの引数部分を指定することで、mvnコマンドが実行できるのです！（※ハイフンで始まる引数は別枠）