OmniAICreator/Qiita-1.07M huggingface dataset:
PythonでDataFrameをGoogle Spreadsheet に上げる3つのパッケージを比較してみた

## 悩み
pandas DataFrameのデータをGoogle Spreadsheetに上げたいけど、アップできるパッケージがいろいろある・・・

ということで、今回は下記の３つを比較

- [gspread-dataframe](https://pypi.org/project/gspread-dataframe/)
  - Stars: 137
  - Qiitaで日本語の記事も出てるので、ほとんどの人はこれを使うのでは・・・
- [gspread-pandas](https://pypi.org/project/gspread-pandas/)
  - Stars: **273**
  - スターが一番多い！！
- [df2gspread](https://pypi.org/project/df2gspread/)
  - Stars: 119
  - 昔からあるみたいです

## 環境と検証方法
+ m1 mac / miniforge 環境
+ Google Spreadsheetへのアクセスには service_account をクレデンシャルファイルとして利用
+ df2gspreadとgspread-pandasはcondaでインストール、gspread-dataframeはpipでインストール

```sh
$ conda list | grep gspread
df2gspread                1.0.4           pyhd3deb0d_1002    conda-forge
gspread                   4.0.1              pyh6c4a22f_0    conda-forge
gspread-dataframe         3.2.1                    pypi_0    pypi
gspread-pandas            2.2.3                      py_2    conda-forge
```

+ サンプルデータは[国勢調査の都道府県人口のCSVデータ](https://www.e-stat.go.jp/stat-search/files?page=1&layout=datalist&toukei=00200521&tstat=000001011777&cycle=0&tclass1=000001094741&tclass2val=0)を利用、ちょうど1,000行弱で都合が良い！


## 結論

<font color="red">**gspread-dataframe がダントツで速い**</font>

| Package | speed |
| -- | -- |
| gspread-dataframe | 1.98 sec |
| gspread-pandas | 3.51 sec |
| df2gspread | 7.01 sec |

なるべくフェアにテストしたつもりなのですが・・・結構、パフォーマンス違うんですね。思った以上に違ったのでビックリ。

参考までに、[テストしたコード](https://gist.github.com/tokkchan/4a37bcbf4ad2511d6141bfa7ca26b29c)
卒業制作「One Message」

# 作品名「One Massage」

# 製作目標
1. 内定先の技術取得し、研修を免除する
2. 第5回専門学校HTML5作品アワードで、入賞を目指す
3. 複数のメッセンジャープラットフォームのDM送信管理を簡単にさせるサービスを作る
    - 個人でやっている知り合いのアニメショップが、一人一人にTwitterとLINE両方に新商品やイベント情報のお知らせを送信している姿が大変だったため、その課題を解決したかったため
    
# 作品内容
## 概要
下記画像のように、本サービスを通して、一つのメッセージを送るだけで、DMを一斉送信することができる
![One Message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500157/f56155ca-2f4e-a45e-a17b-f5c74e611ba3.png)
## 仕様
- 本サービスのアカウント一つで、複数のプラットフォームにメッセージを送信できるようにする
- 送信できる相手を検索できるようにする
- スパムメッセージなどの不正利用が出来ないようにする

## 実装予定機能
### 利用ユーザー情報の登録・更新
### 認証・認可
JWTを利用
### 利用プラットフォームのアカウント連携登録機能
ユーザーがOne Messageで利用できるプラットフォームの連携をするために、各プラットフォームのアカウントの認証やAPIキーを登録するための機能
### 利用プラットフォームのフレンドアカウント検索機能
各プラットフォームごとに、登録したアカウントのフレンドの検索を行う（Twitterで言うフォロー・フォロワー、LINEで言う友達）
### DM送信機能
ユーザーが指定したメッセージを各プラットフォームにDM送信する
送信に関するオプションは、以下の内容を参照
##### 送信プラットフォームを選択
利用登録済みのプラットフォームを選択できるようにさせる
一つも利用登録ができない場合は、DM送信機能を利用できないようにさせる
##### 送信相手の選択
送信相手をプラットフォームごとに選択できるようにさせる
送信相手は、[利用プラットフォームのフレンドアカウント検索機能で検索した結果から選択できるようにする](#利用プラットフォームのアカウント連携登録機能)
また、フレンドアカウント検索機能で検索した結果全て選択させる機能を実装させる
### スパム・迷惑DM対策
もし、悪意のあるユーザーに本サービスを利用された場合の対策のため、ユーザーが送信したメッセージの他に通報用リンクを記載したDMを送信する
通報された回数をカウントし、10回通報されたら、アカウントを利用停止させる。

## 画面遷移図・画面説明
![One Message-画面遷移図 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500157/528a63e1-cee8-ae17-63df-687d91f00333.png)


### ログイン画面
登録済みのユーザーのログイン画面
ユーザー登録とホーム画面に遷移可能
### ユーザー登録画面
ユーザー登録を行う画面
以下の内容を登録させる
- 名前
- メールアドレス
- パスワード
各プラットフォームのアカウントは、[各プラットフォームアカウント情報画面で登録させる]()
ユーザー登録とホーム画面に遷移可能
### ホーム画面
各プラットフォームのアカウントの登録状況や最近送信したメッセージ履歴を表示させる
### ユーザー情報画面
登録したユーザー情報の確認や更新を行えるようにする
### 各プラットフォームアカウント情報画面
各プラットフォームのアカウントの情報や更新を行う
### フレンド検索画面
各プラットフォームのアカウントのフレンドを検索する
### DM送信設定画面
DMの送信やその設定を行う
### DM送信完了画面
DMの送信の完了やエラーを表示させる

# 技術選定
## フロントエンド
- 言語 TypeScript
- フレームワーク Angular
- UIライブラリ Angular Material
- テストフレームワーク Jest

## バックエンド
- 言語 Java
- フレームワーク SpringBoot
- ORM SpringJPA
- 認証方式 JWT
- テストフレームワーク JUnit

## インフラ
- デプロイ先 Amazon Lightsail
- データベース Amazon LightsailのMySQL
- フロントエンド用Webサーバー Nginx(Docker-Composeを利用)

## CI
- GitHubActions

## その他
- API設計ツール OpenAPI
- デザインツール　Figma
- ソーシャルアカウント認証ライブラリ Firebase Authentication
- 利用した外部API 
  - TwitterAPI
  - LINE Messaging API
Windowsコマンドプロンプト上でのインストール時のプロキシ突破

#トラブル内容
Windowsコマンドプロンプト上でライブラリのインストール等で外部サーバからファイルを入手する際、正しいコマンドを入力しても失敗する。
今回の場合はPythonのpipをアップグレードしようとした際に失敗した。

```powershell:cmd.exe
> pip install --upgrade pip
ERROR: Could not find a version that satisfies the requirement
```

#原因
プロキシ突破ができていなかったため、外部サーバにアクセスできなかった。
今回の場合は、社内→社外におけるプロキシが突破できていなかった。

#対策内容
プロキシ突破するために、--proxyを追加する。(プロキシを指定する)
※http://{ユーザ名}:{パスワード}@{ホスト名}:{ポート番号}の部分は、各環境において変更してください。

```powershell:cmd.exe
> pip install --upgrade pip --proxy http://admin:password@192.168.0.1:8080
Successfully installed pip-21.2.1
```
Web サービスのサーバー構築で躓いたところ

#サーバーの構築
・さくらのサーバーで構築

pythonをcgiで動かすには、下記のように書く必要あり
下記の#!も書く必要あり。


```hehho.cgi
#!/usr/local/bin/python

print("Content-Type: text/html; charset=UTF-8")
print("")

print("Hello, World!")
```

最初は教本のコードをそのまま使ったらエラーに。。。

＃のコメントを削除したら動くようになりました。
【個人開発】自分のPC上で実行できるDiscord読み上げbotを作りました

# 自分のPC上で実行できるDiscord読み上げbotを作りました

## はじめに

皆さんのDiscordサーバーに読み上げbotはいますか？日本国内で有名なものといえば喋太郎やshovelなどでしょうか。しかしながら、彼らは頻繁に**読み上げを停止したり、レスポンスが悪くなったり**してしまいます。日本でこれほどまでに有名であれば無理もありません。そこで、外部のサーバーに依存せずに動く、読み上げbotを開発することにしました。

## 概要

https://github.com/Garden-Tree/yomi-KAI

yomi-KAIはDiscordのテキストチャンネルに送られた文章をボイスチャンネルで読み上げるbotです。
自分のPC上で実行できるため、他の公開されている読み上げbotと比べて**負荷が集中しにくく、安定して動作**します。
もちろん無料で使えます。

## デモ

準備中

## 環境

- Python 3.9以上
- FFmpeg 4.4以上

## 依存ライブラリ

- discord.py **2.0以上**
- python-voicetext

## 導入方法

### Windows

1. [Discord Developer Portal](https://discord.com/developers/applications)からbotを作成し、 `Privileged Gateway Intents` の権限をすべて付与。
1. [VoiceText Web API](https://cloud.voicetext.jp/webapi)に登録し、APIキーを受け取る。
1. [Google Cloud Platform](https://console.cloud.google.com/)(GCP)でプロジェクトを作成し、[Cloud Text-to-Speech API](https://cloud.google.com/text-to-speech?hl=ja)を有効化してサービスアカウントのキー(JSONファイル)を受け取る。
1. [Releases](https://github.com/Garden-Tree/yomi-KAI/releases/latest)から `yomi-KAI-v***.zip` をダウンロードして解凍。
1. `config.ini.example` を開き、DiscordのトークンVoiceTextのAPIキー、GCPのキーのディレクトリ(ファイル名も含む)を入力。
1. `config.ini` で名前をつけて保存。
1. `windows_setup.bat`を実行

### Linux

1. Windowsの6. まで同じ
1. Python, FFmpegをインストール
1. `pip install git+https://github.com/Rapptz/discord.py`
1. `pip install python-voicetext`
1. `pip install google-cloud-texttospeech`

## 起動方法

### Windows

`yomi-KAI.exe` を実行。

### Linux

`yomi-KAI.py` を実行。

## コマンド

### y.c

発言者と同じボイスチャンネルに接続します。

### y.dc

ボイスチャンネルから切断します。

### y.dict

辞書に関する操作です。詳しくは`y.dict help`を参照してください。

### y.help

このヘルプを表示します。

## 機能

- 辞書
- プレフィックスの変更
- 自動切断

## 設定

`config.ini` から設定を変更できます。現在設定可能な項目は以下の通りです。

- プレフィックス
- 話者（声質）
- ピッチ
- スピード

## 補足

- 本プログラムをアップデートする際には、辞書データを手動で引き継いでください。辞書データの場所は `./dict/` です。
- **discord.py v1.7.3では動作しません。**
- exeで起動した場合、pythonでの起動と比較して、若干の遅延が発生します。

## サポート

サポートサーバーはこちら。要望や質問はこのDiscordサーバーで受け付けています。**試用もできます。**

https://discord.gg/DWEQ2cP3KZ

## 支援

サーバー運営費等が毎月発生しています。皆様のご支援をお待ちしております。開発のモチベーションにも繋がります！  

https://fantia.jp/fanclubs/254049

## 作者

GardenTree [[Twitter]](https://twitter.com/Garden__Tree)

## 更新
2022/11/17 最新の内容に更新
PostgreSQLのコマンド

#PostgreSQLの起動・停止

PostgreSQLのバージョン確認
```$ postgres --version```

初期化
```$ initdb /usr/local/var/postgres -E utf8```

データベース・サーバーを起動
```$ pg_ctl start -D /usr/local/var/postgres```

データベース・サーバーを停止
```$ pg_ctl stop -D /usr/local/var/postgres```

#PostgreSQLに接続

デフォルトのテーブルに接続
```psql -d postgres```

テーブルとユーザを指定して接続
```psql -d テーブル名 -U ユーザ名```

接続解除
```\q```

#データベース

データベース一覧
```\l```

データベース選択
```\c データベース名;```

#テーブル

テーブル一覧の表示（シーケンスも含む）
```\d```

テーブル一覧の表示（テーブルのみ）
```\dt```

テーブル構造の表示
```\d テーブル名```

テーブルのオーナーの変更
```alter table テーブル名 owner to オーナー名;```

#ユーザー

ユーザー一覧
```\du```

#スキーマ

スキーマ一覧
```\dn```
railsアプリ作成の忘却録

##webアプリケーションの新規作成

```
$rails new アプリ名(その後にオプションの指定)
```

```
$rails new アプリ名 --datebase=postgrep --api 
```

PostgreSQL
データベース(SQL)の１つ
オープンソース、データベースと関連付けた
丈夫さ、パフォーマンス性に特徴がある
インストール方法とか使い方の記述が豊富

##データベーステーブルを作成した際のエラー

```
$ bundle exec rails db:create
$ bundle exec rails db:migrate
```
を記述したら


```
could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
Couldn't create 'scaffold_app_development' database. Please check your configuration.
rails aborted!
ActiveRecord::ConnectionNotEstablished: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
/Users/▲▲/dev/rails/scaffold_app/bin/rails:5:in `<top (required)>'
/Users/▲▲/dev/rails/scaffold_app/bin/spring:10:in `block in <top (required)>'
/Users/▲▲/dev/rails/scaffold_app/bin/spring:7:in `tap'
/Users/▲▲/dev/rails/scaffold_app/bin/spring:7:in `<top (required)>'

Caused by:
PG::ConnectionBad: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
/Users/▲▲/dev/rails/scaffold_app/bin/rails:5:in `<top (required)>'
/Users/▲▲/dev/rails/scaffold_app/bin/spring:10:in `block in <top (required)>'
/Users/▲▲/dev/rails/scaffold_app/bin/spring:7:in `tap'
/Users/▲▲/dev/rails/scaffold_app/bin/spring:7:in `<top (required)>'
Tasks: TOP => db:create
(See full trace by running task with --trace)
```
のようにエラーが発生

postgreSQLを再起動したら解決しました。

```
$brew services restart postgresql
```

```
Created database '●●_development'
Created database '●●_test'
```

rakeタスクファイルの作成

```
$bundle exec rails g task scheduler
```
成功

```
create  lib/tasks/scheduler.rake
```

##herokuへのデプロイ時のエラー

```
remote:  !     Could not detect rake tasks
remote:  !     ensure you can run `$ bundle exec rake -P` against your app
remote:  !     and using the production group of your Gemfile.
remote:  !     rake aborted!
remote:  !     SyntaxError: scheduler.rake:2: syntax error, unexpected tIDENTIFIER, expecting end-of-input
remote:  !     task :update_ feed => :environment do
```

このようなエラーが発生した
解読したところscheduler.rakeの２行目
task :update_ feed => :environment doに問題があると表示された

２行目を確認したところ

```
task :update_ feed => :environment do
```
update_ feedの間に空白があったので埋めたら
無事うまくいった

エラー文がどれだけ優秀か悟った
Azure Database for MySQLでテーブルを作成した時につまらないエラーで悩んだ話

<h2>初めに</h2>
これは自分用のメモであるため簡潔に書いてあります。
SQL初めての人がとても簡単なエラーに悩んだ話です。

<h2>エラー内容</h2>
テーブルを作成した時に以下のようなエラーが出た

```
mysql.connector.errors.ProgrammingError: 1044 (42000): Access denied for user 'USER'@'%' to database 'mysql'
```

アクセスできないらしい。

<h2>原因</h2>
mysqlの管理用のテーブルみたいなのに書き込もうとしたのが原因です。
とても初歩的なミスだけど、初めてだったからしょうがないよね...。

<h2>解決方法</2>
ちゃんとアプリケーションで使用するためのデータベースを作る。

```
create database <ここに作成したいデータベース名>
```

そしてここにテーブルを作るだけ。
終わり！
Hyper-VのVMを多重階層化(Nested VM)する

# 概要
VM上でHyper-Vを有効化しようとした際に「必要な仮想化機能がプロセッサにありません」というエラーが出た場合の対処法です。

# 結論、の前に
Intel製プロセッサでない場合、Nested VMはサポートされていないとのことです。
(機能が有効化できてもVMの起動に失敗したりする模様)
パブリッククラウドのIaaSで利用する場合はハードウェアについても確認しましょう。

# 結論
デフォルトでは無効化されている「[ExposeVirtualizationExtensions](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization)」を有効化する必要があります。
このパラメータはNested VMの有効/無効を示します。

# 手順
ホストPCのPowerShellから下記コマンドを実行します(おそらく要管理者権限、未確認)。
*\<VMName>*には対象となるVM名を指定します（下記の参考画像では"Host_Training"がマシン名)。
なお、対象のVMは停止している必要があります。

```
Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true
```

下記コマンドでVMの一覧が表示されますので、上記実行後に結果を確認します。

```
Get-VMProcessor -VMName * |ft VMName,ExposeVirtualizationExtensions
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/d98f4bda-e0ab-117b-7786-ad7e82309346.png)

対象の"ExposeVirtualizationExtensions"がTrueになっていればOKです。
再度VMを立ち上げれば、Hyper-Vを有効化できるはずです。
【Laravel】Artisan よく使うコマンド集

Laravelでプログラムを書いているときに、比較的よく使うコマンドの備忘録です。

##Artisan
###route:list
ルーティング定義の一覧を表示

```vim
$ php artisan route:list
```
###make:migration
マイグレーションファイルを作成

```vim
$ php artisan make:migration create_sample_table --create=samples
```
###migrate
マイグレーションの実行

```vim
$ php artisan migrate
```
###migrate:rollback
直前に実行したマイグレーションの取り消し

```vim
$ php artisan migrate:rollback
```
###migrate:reset
全てのマイグレーションを取り消し

```vim
$ php artisan migrate:reset
```
###make:model
モデルの作成
テーブル名の単数形を名前に付けることで、テーブルとオブジェクトがマッピングされ、
クラス経由でDB操作が可能になります。

```vim
$ php artisan make:model Sample
```
###make:seeder
シーダーファイルの作成

```vim
$ php artisan make:seeder SamplesTableSeeder
```
###db:seed
シーディングを実行

```vim
$ php artisan db:seed
```
###make:controller
コントローラの作成

```vim
$ php artisan make:controller SampleController
```
###make:request
バリデーションの作成

```vim
$ php artisan make:request SampleRequest
```
###make:component
コンポーネントの作成

```vim
$ php artisan make:component Sample
```
Railsを使ったクイズアプリで問題を1問ずつ表示する方法

#前提
quizがquestionとアソシエーションの関係である。

```ruby
class Quiz < ApplicationRecord
  has_many :questions, dependent: :destroy
end
```
```ruby
class Question < ApplicationRecord
  belongs_to :quiz
end
```

以下のように問題を1問ずつ回答したのちに結果を表示させるような実装をしたい方は、ぜひ参考にしてみてください。

<img src="https://i.gyazo.com/68fec03421093ae16b50f0f2838f50db.gif" alt="Image from Gyazo" width="300" height="200">

#実装方法
####nextメソッドを定義する

```ruby
class Question < ApplicationRecord
  belongs_to :quiz

  def next(quiz)
    quiz.questions.where("id > ?", self.id).order("id ASC").first
  end
end
```

- `"id > ?", self.id`の部分で現在表示されているレコードよりもidが大きいレコードを取得
- `order("id ASC").first`でidが一番若いレコードを取得


####引数にnextメソッドを使う
```ruby
if @question.next(@quiz).present?
  redirect_to quiz_challenger_question_path(@quiz.id, challenger.id, @question.next(@quiz))
  # 引数にnextメソッドを使うことで、次のレコードへのpathを実装できる
else
  redirect_to quiz_challenger_path(@quiz.id, challenger.id)
end
```

- もし次のレコードがある時、次のレコードへ遷移する
- 次のレコードがなければ、回答結果画面に遷移する
AWS S3 静的ウェブサイトをHTTPS化

～2021年9月27日でのAWSのコンソールで確認～

#大まかな手順
* S3に静的Webサイトをデプロイする
* 独自ドメインを取得し、Route53に登録する
* AWS Certificate Managerで証明書発行
* CloudFrontからS3にアクセスできるようにする
* S3への直アクセスを制限する
* Route53にCloudFrontのドメインを登録



#S3に静的Webサイトをデプロイする
[チュートリアル: Amazon S3 での静的ウェブサイトの設定](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html)がわかりやすい

#独自ドメインを取得し、Route53に登録する
[独自ドメインをRoute 53でホストする](https://qiita.com/ebtiag/items/cd954a1e036d523e6f4d)

#ACMで証明書発行
:::note warn
ACMを発行する際、リージョンはバージニア北部にする
:::
* AWS Certificate Managerのコンソール画面＞証明書のリクエスト
* パブリック証明書のリクエストを選択＞証明書のリクエストをクリック
* ```*.取得したドメイン```を入力
* DNSの検証を選択
* 任意のタグをして
* 確定とリクエスト
* 検証状態のステータスが「検証保留中」になっていることを確認する
* Route53でのレコードの作成　をクリック
* レコード作成のポップアップが表示＞作成　をクリック

しばらく待つ。今回は30秒ほどでした
#CloudFront経由でS3のバケットを公開する
* CloudFront＞ディストリビューション＞ディストリビューションを作成
* オリジンの設定
>オリジンドメイン：クリックして今回作成したS3バケット名を選択
オリジンパス：空白でOK
S3バケットアクセス：はい、OAI を使用します を選択
新しいOAIを作成をクリック
バケットポリシー：はい、バケットポリシーを更新します を選択

* デフォルトのキャッシュビヘイビア
>ビューワープロトコルポリシー：Redirect HTTP to HTTPS

* 設定
>代替ドメイン名 (CNAME) ：```www.取得したドメイン``` を入力
カスタム SSL 証明書：今回ACMで作成した証明書を選択
デフォルトルートオブジェクト：index.html
* 作成したディストリビューションのドメイン名にブラウザでアクセス

#S3への直接アクセスを制限する
* S3＞該当のバケット＞アクセス許可タブ
* ブロックパブリックアクセス (バケット設定)を編集
パブリックアクセスをすべて ブロックにチェックを入れる
* バケットポリシーを編集する
```"Sid": "PublicReadGetObject"```の{}で囲まれた範囲を削除する
```"Sid": "2",```の2を1にする
* S3バケットウェブサイトエンドポイントのURLにアクセスすると、403エラーになることを確認する

#Route53にCloudFrontのドメインを登録
* Route53＞ホストゾーン＞該当のホストゾーン＞レコードを作成＞
クイック作成へ切り替える　をクリック
>レコード名：CloudFrontで設定した代替ドメイン名
レコードタイプ：A
値の右にある「エイリアス」をオンにする
エンドポイントを選択：CloudFrontディストリビューションへのエイリアス
ディストリビューションを選択：CloudFrontのディストリビューションドメイン名を選択

#ブラウザで確認する
作成したドメインをブラウザでアクセスする
ムームードメインで取得したドメインをAWS Route53に登録

#ムームードメインでドメインを取得
###ムームードメインの操作

* 取得したいドメインを検索＞カートに追加

* ドメイン設定
>WHOIS公開情報：チェックネームサーバー(DNS)：ムームーDNS
ドメインの利用方法：選択しない
ムームーメール：チェックしない


#取得した独自ドメインをRoute53に登録する
###AWSの操作
* Route53＞ホストゾーン＞ホストゾーン作成
> ドメイン名：取得したドメイン
説明：任意
タイプ：パブリックホストゾーン
* 作成したホストゾーンをクリック
* NSレコードにチェックを入れる
* レコードの詳細の4つの値をコピー

###ムームードメインの操作
* ネームサーバ設定変更＞取得したドメインで使用する　を選択
* ネームサーバー１～４にコピーしたRoute53のNSレコードの値を順に入力
※　末尾の「.」は入力しない
RifidiEdge3.8.1 に内蔵されたEnterprise Rifidi Management Dashboardが動作しない問題

#Rifidiとは？
オープンソースのRFID/センサーミドルウェアプラットフォーム。
このシステムを利用したサーバーが販売されている(2021/9/27現在)。

---

 ・内蔵サーバ版(Ubuntu or windows)
　https://argowireless.com/collections/software/products/rifidi-edge-server
 ・ラズベリーパイ版
　https://argowireless.com/collections/software/products/rifidi-pi

---

#目的
ミドルウェアはOSSとして公開されている為、利用出来ないか検討。

#問題
インストールはサクッと完了した。
rifidiserver.bat
を叩いてサーバーログは何となく動いてそうな雰囲気。

しかし、チュートリアル
http://wiki.rifidi.net/index.php?title=Web_Administration_Dashboard
がうまくいかない。管理が出来るダッシュボードを開いても変数名が丸見えでボタンは動作していない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345260/9a21813f-5c76-071a-c7d7-a4ee727ddcad.png)



似たような症状がフォーラムに投稿されているが質問者が放置している。
http://forums.rifidi.net/viewtopic.php?f=34&t=4618


ChromeやIEで見る限りangular-sanitaize.jsでエラーが発生している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345260/08e255cf-e668-bcfd-dcb1-addd63f34cd8.png)

チュートリアルにはリモートRifidiサーバーを管理するための前提条件として
・署名付き証明書を使ったhttps化 or ブラウザのセキュリティをオフ
せよと記載があるのでブラウザセキュリティオフを実行したが結果は変わらなかった。
>"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="c:/someFolderName"


#暫定処置
C:\RifidiEdge\RifidiEdge-3.8.1\admin\app\bower_components\angular-sanitize
にインストールされたangular-sanitize.jsの629~632行目をangular 1.8.2の記述に差し替えた

```javascript:angular-sanitize.js 
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
  var LINKY_URL_REGEXP =
        /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/,
      MAILTO_REGEXP = /^mailto:/;
```
↓

```javascript:angular-sanitize.js暫定
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
  var LINKY_URL_REGEXP =
        /((s?ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
      MAILTO_REGEXP = /^mailto:/i;
```

#結果
とりあえずチュートリアルが続けられそう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345260/ade3becd-015b-8a2f-761f-86e9c37f5983.png)
超解像SRCNNモデルのまとめ

# はじめに
超解像タスクにおける最初のCNNモデルであるSRCNNモデルの論文の重要なところだけまとめます。
モデル構造とかパラメータの数値がメインです。
初めて超解像やってみる方の参考になれば。

[自分で実装して学習させた記事](https://qiita.com/okateru/items/a5d3cc9f34eae38d8466)も書いてるのでコチラも是非。

# 簡単な用語まとめ

## SISR

Single Image Super-Resolutionの頭文字を取ったもの。
日本語訳では「単一画像超解像」と訳される。

要は一枚の画像を入力として受け取り、それに対応した高画質の画像を出力とするもの。
超解像といったら、このことを指すことが多い。

## LR, HR

それぞれLow Resolution, High Resolutionの略。
低解像度、高解像度と訳すのがいいかも。要は低解像度画像と、高解像度画像のこと。

超解像タスクにおける入力と出力ですね。

これらの単語は超解像分野のどの論文にも出てきます。

じゃ本題に入っていきます。

# モデル構造
![20190213151109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890361/345f846d-c8fb-63cb-db90-d8485a8cb451.png)

高解像度の画像と同じサイズの低解像度画像を入力として受け取り、高解像度画像を出力する。
シンプルで畳み込み層3層で構成されている。第一層と第二層の畳み込みの後の活性化関数はReluを使う。

またそれぞれの層の重みは平均0,標準偏差0.001のガウス分布で初期化する。

tensorflow(keras)で実装するなら以下。

```python
initializer = tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.001)
    
    
model = Sequential()
model.add(Conv2D(64, kernel_size=9, padding='same', kernel_initializer=initializer, input_shape=(None, None, 3)))
model.add(Activation('relu'))
model.add(Conv2D(32, kernel_size=1, padding='same', kernel_initializer=initializer))
model.add(Activation('relu'))
model.add(Conv2D(1, kernel_size=5, padding='same', kernel_initializer=initializer))
```

最後の畳み込み層のフィルター数はグレー画像なら1,カラー画像なら3にする。

# 損失関数
損失関数はMSE(Mean Squared Error)を使う。MSEの値を小さくすることで評価指標であるPSNRの値を大きくすることにつながる。

# 最適化アルゴリズム
モーメンタム付き確率的勾配降下法(SGD)を使う。

学習率は最初の2層が0.0001, 最後の層が0.00001と学習率を層ごとに変更する。

tensorflow(keras)で実装するなら以下のようになると思う。(tensorflow_addonsをpipでインストールしておく必要あり）

```python
import tensorflow_addons as tfa

optimizers = [
              tf.keras.optimizers.SGD(learning_rate=0.0001, momentum=0.9),
              tf.keras.optimizers.SGD(learning_rate=0.00001, momentum=0.9)
              ]

optimizers_and_layers = [(optimizers[0], model.layers[:-1]), (optimizers[1], model.layers[-1])]
optimizer = tfa.optimizers.MultiOptimizer(optimizers_and_layers)
```

# 評価指標
PSNRとSSIMを使う。それぞれの指標がどういう意味合いかは[コチラ](https://qiita.com/toshi_machine/items/3ff0a09279a8e71c4e82)の記事が詳しい。

端的にいうと、画質が良いか悪いかを表す。

tensorflow(keras)で実装するのは簡単。

```python
def psnr(low, high):
    return tf.image.psnr(low, high, max_val=1.0)

def ssim(low, high):
    return tf.image.ssim(low, high, max_val=1.0)
```

max_valは輝度の最大値を示すので、255で割って正規化している場合は1、してないなら255を設定する。

# データ前処理
論文中では高画質画像だけを用意し、それを縮小→元のサイズに拡大とすることで画質を落として低画質画像を生成している。この時の補完方法はbicubic法を用いている。

またRGB画像をYCbCr変換して、Y成分のみを学習させていたり、RGB画像のまま学習させていたりするが、RGB画像のまま学習させた方が精度は高めかも。（状況による）

入力画像サイズは任意のものでok。


# まとめ
論文中のパラメータをメインでまとめてみました。一番最初の超解像CNNモデルで実装もしやすいので、自前のデータセットなどで実験してみると良いと思います。
【Golang】プログラム内から import している外部パッケージのバージョンを確認する【外部モジュール情報の取得】

> Go 言語（以下 Golang）のソースコードの `main` パッケージで、アプリが利用しているモジュール／外部パッケージのバージョンを取得したい。

[「"golang" import パッケージ モジュール バージョン 確認」でググって](https://www.google.com/search?q=%22golang%22+import+%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8+%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB+%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3+%E7%A2%BA%E8%AA%8D)も、`go get` するモジュールのバージョン指定しか出てこなかったので、自分のググラビリティとして。

## TS; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. [runtime/debug](https://pkg.go.dev/runtime/debug) パッケージの `debug.ReadBuildInfo()` を使い `buildInfo.Deps` で依存パッケージ（モジュール）情報から `Version` フィールドを参照する。<sub><sup>（Go 1.12 以降）</sup></sub>
1. 具体的なコード

    ```go
    package main
    
    import (
    	"fmt"
    
    	"log"
    
    	"golang.org/x/xerrors"
    	"runtime/debug"
    )
    
    func main() {
    	buildInfo, ok := debug.ReadBuildInfo()
    	if !ok {
    		err := xerrors.New("failed to get build info")
    
    		log.Fatal(err)
    	}
    
    	for _, modDep := range buildInfo.Deps {
    		fmt.Println("module name:", modDep.Path)
    		fmt.Println("module version:", modDep.Version)
    	}
    }
    // Output:
    // module name: golang.org/x/xerrors
    // module version: v0.0.0-20200804184101-5ec99f83aff1
    ```
1. [オンラインで動作をみる](https://play.golang.org/p/KWJKvaUDh0l) @ Go Playground

## 参考文献

- ["go install" でもアプリのバージョン情報に自動対応させる](https://qiita.com/KEINOS/items/cbc410ce3ee809cb9a20) @ Qiita
Program　Filesって意味知ってますか！？

OBSのソフトをいじる機会がありまして
ふと『すんごい発見』をしちゃいました✨✨✨✨🐾🐾


##Windows内にあるファイルの違い
みなさんふと、このファイルの違いってなんだろう…？
って思ったことありませんか？


>『Program Files』と『Program Files（x86）』

なんとこれ
<b>32bitか64bit<b/>かを表しているそうです！
（私は知らなかった…。）

>つまり「Program Files」にも64bit用と32bit用があって、
「Program Files（x86）」が32bitです！！！！
永続的に変数を保存する(Python)

#永続的な変数作る
変数を永続的に保存したいことはよくあることだと思います
例えば、ウインドウプログラムの座標やサイズ、設定項目などです

Serializeとかで検索すれば、色々な言語でこのようなことをするものが出てくるのですが、Pythonではpickleを使うのが多分普通なんじゃ無いかと思います。楽です。
#それでももっと楽したい
ので、つくってみたのがこれです。

~~~python:persistentvals.py
from typing import Any
import os.path, pickle

class _Old:
    def __init__(self, filename: str) -> None:
        if os.path.exists(filename):
            with open(filename, "rb") as f:
                tmp = pickle.load(f)
            self.__dict__.update(tmp)

class PersistentVals:
    def __init__(self, filename: str) -> None:
        object.__setattr__(self, "_PersistentVals__filename", filename)
        object.__setattr__(self, "_old", _Old(filename))

    def print(self) -> None:
        for i,v in self.__dict__.items():
            if i != '_PersistentVals__filename':
                print(i, '=', v)
    
    def __setattr__(self, name: str, value: Any) -> None:
        if name in self.__dict__.keys():
            object.__setattr__(self, name, value)
        else:
            if name in self._old.__dict__.keys():
                if type(value) is type(self._old.__dict__[name]):
                    object.__setattr__(self, name, self._old.__dict__[name])
                else:
                    object.__setattr__(self, name, value)
            else:
                object.__setattr__(self, name, value)

    def __del__(self) -> None:
        if hasattr(self, '_old'):
            del self._old
        with open(self.__filename, "wb") as f:
            del self.__filename
            pickle.dump(self.__dict__,f)

class NotPersistentVals:
    def __init__(self, filename: str) -> None:
        pass

    def print(self):
        for i,v in self.__dict__.items():
            print(i,'=',v)
~~~
#どういうものなの？
変数を勝手に保存するクラスです。クラス自体はほぼ空っぽなので
`p = persistentvals.PersistentVals('savedata')`
のようにインスタンスを作ったら
`p.hoge = 'こんにちは'`
のように普通にプロパティを追加していって下さい。
このとき、過去に`p.hoge`に何らかの値が代入されていて、`savedata`に保存されている場合、
__p.hogeには"こんにちは"は代入されずに、savedataに保存されている物が代入されます。__
#どういう作り？
インスタンスを作成したときに、保存された変数データを読み込み、変数が初めて代入されたときに保存されたデータと比較して、同じ型、同じ名前のものがあれば保存されたデータを代わりに代入します。
#どう使うの？
普通に、保存したい変数はこのクラスのプロパティに入れる形で初期化してください。
普通の形で初期化していても、保存した値になるので、便利かもしれません。

```Python:example.py
import persistentvals

p = persistentvals.PersistentVals("./test.dat")
p.foo = "Hello World" #二度目以降の実行ではこれは代入されない
print(p.foo)

#p.foo = 10
#print(p.foo) # 10
#例外として、最初の代入でも保存されている物と型が違う場合は代入される

p.foo = "こんにちは、世界" # 最後に代入された物が保存される

p.lists = [1,2,3,4,5,6,7,8,9,10]
print(p.lists)
p.lists = [10,9,8,7,6,5,4,3,2,1,0]
print(p.lists)
# リストの場合

p.print() #定義されている変数の一覧が出ます
```
#注意事項
このクラスは(多分)便利ですが、変数に値を代入したら変数にはその値が入ると言うプログラムの常識を覆すクラスです。デバッグに支障が出ること間違いありません、使用には十分注意してください。

`persistentvals.NotPersistentVals`と言う本当に何もしないクラスが付属しています。使い方は同じですが、何もしないので少なくともデバッグ時にはこれを使用することを推奨します

このクラスはメモリ内に前回に保存した変数の内容を全て保存します。なので、あまり大きな配列などを入れるとメモリを無駄に使用するので、あまり大きな配列は入れない方が良いと思われます。
#追記
あと、Singletonなクラスにした方が、便利かもしれないなあとか思った。
#修正
_oldの削除に失敗するのを修正(2022/01/25)
SAMBAを使った簡単ファイルサーバを作ってみた

## 目的
ノートパソコンからもアクセス・ファイル保管を行えるファイルサーバを自宅デスクトップ内に作りたい！

## 環境
* デスクトップ
    * OS: ubuntu 20.04
* ノートパソコン
    * OS: Wndows10


## 手順
### Sambaのインストール

Sambaとは
> Sambaは、Linux上でWindowsのネットワーク機能を実現するソフトウェアです。Sambaを導入すると、Windowsのファイルサーバーと同じ役割を果たせる他、実際のWindowsファイルサーバーをLinuxから利用することもできます。
参照:[Sambaの基本を知っておこう](https://atmarkit.itmedia.co.jp/ait/articles/1612/01/news183.html)

つまり、普段、Linux上の開発用Webサーバー等にアクセスするときFTP経由（ソフト：FileZilla、WinSCP、etc...）でアクセスし、ファイル操作を行うが、これをWindowsクライアントからのアクセス時ファイルエクスプローラーでファイル操作を行えるようにするものがSambaに当たる。
SambaをLinuxサーバ側に入れることでWindwsクライアント側からもファイルエクスプローラーを使って簡単にファイルサーバにアクセスできる！

Sambaのインストール
あらかじめ、ubuntuを最新状態にし（`sudo apt update`）、パッケージを最新にしておく（`sudo apt upgrade`)。
その後、下記コマンドを実行しSambaのインストールを行う。

```
sudo apt install samba smbfs 
```

### Sambaの設定
Sambaでは、共有を行うディレクトリ箇所の詳細設定や、Windowsの[ワークグループ](https://atmarkit.itmedia.co.jp/ait/articles/1612/01/news183.html#body_insert_ad)に合わせたアクセス許可設定が行える。
今回は、一番簡単で基本的な設定のみ行う。（ワークグループ、セキュリティー等はまた別の機会で・・・）

Samba設定ファイルオープン

```
sudo nano /etc/samba/smb.conf
```

Samba経由共有フォルダーの設定
Samba設定ファイル内をスクロールし、下記のような共有ディレクトリ設定箇所を探し出し、設定を行う。
![Screenshot from 2021-09-27 11-13-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/3d91b11b-ab43-682d-1ae4-02ae45700fb1.png)

共有ディレクトリの作成・設定

```
sudo mkdir /k-share
sudo chmod 0777 /k-share
```


Sambaの再起動

```
/etc/init.d/smbd restart
```

ファイルサーバ構築完了！

### ファイルサーバへのリモートアクセス

:::note info
Windowsクライアントよりアクセスを試みるには、まずubnntuサーバーのIPを調べる必要があります。
IPを調べ出すコマンド： 

```
ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
```
:::

あらかじめ確認ように、適当なファイルを共有ディレクトリ上に保管

` ls -l /k-share `

![Screenshot from 2021-09-27 11-44-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/6f1f0b68-fd58-86f0-f587-12d8320d9c95.png)

Windowsクライアントよりアクセス
ファイルエクスプローラーのディレクトリバーに下記ディレクトリパスを入力
` \\ubnntuサーバーIP\共有ディレクトリ名`
例：![スクリーンショット 2021-09-27 115212.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/14220fbd-242a-e340-e45c-db2b983d10f9.png)

アクセス成功！（初めてのアクセス時は、ubuntuサーバー側のユーザーログインが求められる。）


## まとめ
ファイルサーバーの作成自体はかなり簡単だが、詳細設定方法によってはできることの幅が多そうだ。
また、この状態では同じLAN内でのアクセスのみが可能で、実のところ会社や学校からの自宅サーバへのアクセスが不可。
そのため、**VPN接続を使ったリモートアクセス設定が必要**

Sambaの良さを更に理解する上で、改めて[FTPサーバの構築](https://atmarkit.itmedia.co.jp/ait/articles/1612/01/news181.html)を行ってみる必要もありそうだ。

#### 参考サイト
* [How to set up Samba in Ubuntu/Linux, and access it in Mac OS and Windows](https://adrianmejia.com/how-to-set-up-samba-in-ubuntu-linux-and-access-it-in-mac-os-and-windows/)
* [How to get the primary IP address of the local machine on Linux and OS X?](https://stackoverflow.com/questions/13322485/how-to-get-the-primary-ip-address-of-the-local-machine-on-linux-and-os-x#answer-13322549)
* [Sambaの基本を知っておこう](https://atmarkit.itmedia.co.jp/ait/articles/1612/01/news183.html)
GitHub：Markdown (rst, md) の行へのリンクを取得する方法

GitHubである行（Line）へのリンクを取得したいことがある（Issueとか解説BLOGとか）が、これまで Markdown（rst, md 等） 形式のファイルはレンダリングされてしまい行へのリンクが取得できなかった。

これが2021年6月にできるようになった：
https://github.blog/changelog/2021-06-30-parameter-to-disable-markdown-rendering/

やり方は簡単で "URLの最後に `?plain=1` を加えて表示" するだけ。
行番号をクリックすると表示される `・・・` から

・Copy line
・Copy permalink
・View git blame
・Reference in new issue

を選択できるようになった。

例：[https://github.com/ebiken/p4srv6/blob/master/README.md?plain=1#L3](https://github.com/ebiken/p4srv6/blob/master/README.md?plain=1#L3)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93467/7d625331-3633-1d07-369c-6fd8a5089c59.png)
Railsで作るクイズアプリのテーブル設計

# 前提
- 問題の作成、回答ができる
- 回答の選択肢を増やせる

上記のようなアプリを作りたい方は、ぜひ参考にしてみてください。

# 完成系
<img src="https://i.gyazo.com/8b1d12bfd0e3504083f3f990d4ca0dc7.png" alt="Image from Gyazo" width="500" height="500">

# テーブルの役割
####quizzesテーブル
作成者の情報と問題の大枠を管理する。

####questionsテーブル
問題の内容を格納する。

####choicesテーブル
選択肢の情報を格納する。
また、`correct_answer`を`boolean`で設定し、回答正誤を判定する。

####challengersテーブル
回答者の情報を管理しています。
また、ランキング機能を作るために`score`カラムを追加。

#解説
####NGパターン
クイズアプリのテーブル設計をする際パッと思いつくのは、こんな感じではないでしょうか？

| question                 | choice_1     | choice_2     | correct_answer | 
| ------------------------ | ------------ | ------------ | -------------- | 
| 休みの日は何して過ごす？ | 家でゴロゴロ | 外へおでかけ | 1              | 
| どっが好き？             | レストラン   | 大衆居酒屋   | 2              | 

しかしこれだと、選択肢を追加したいときにはカラムを増やすしかなくなってしまいます。

####OKパターン
それぞれにテーブルを設け、questions < choices の関係でアソシエーションを組む。

| id | question                 | 
| -- |------------------------ | 
| 1 |休みの日は何して過ごす？ | 
| 2 |どっが好き？             | 

| id |choice         | correct_answer | question_id |
| -- |-------------- | -------------- | ----------- |  
| 1  |お家でゴロゴロ | true           | 1 |
| 2  |外へおでかけ   | false          | 1 |
| 3  |レストラン | false          | 2 |
| 4  |大衆居酒屋 | true           | 2 |
Windowsのソートを実装する(Python,Windows)

#ファイル操作をするとき
順番に操作したいときがあるときがあります。当然ソートするわけですが、このソート順は必ずしも一致しません。
#natsortとか
0.txt
1.txt
2.txt
10.txt
15.txt

このようなファイルをソートすると、通常のソートでは文字コード基準になり

0.txt
1.txt
10.txt
15.txt
2.txt

こうなります。最初のように数字順に並べるのが[natsort](https://pypi.org/project/natsort/ "")です。Pypiにあります。
#それでも困ることがある
Windowsのエクスプローラは、Windows7からこのような自然なソートをします。するのですが、これが困ったことに数字以外の記号や漢字はnatsortと微妙に違うソート順でソートされます。たまに困ります。
#なので
Windowsのエクスプローラと全く同じ結果を出すソートが必要です。多分
もちろん、Windowsでしか動く必要がないので、Windows専用です。

```Python:winsort.py
def winsort(lst):
    import ctypes
    from functools import cmp_to_key

    SHLWAPI = ctypes.windll.LoadLibrary("SHLWAPI.dll")
    def cmpstr(a, b):
        return SHLWAPI.StrCmpLogicalW(a, b)

    return sorted(lst, key=cmp_to_key(cmpstr))
```
なんか普通に5ちゃんねるの超初心者スレにあったよこれ
スリープを抑止する、画面を消す(Python,Windows)

とりあえず
#スリープ抑止
```Python:
import ctypes
ES_CONTINUOUS = 0x80000000
ES_AWAYMODE_REQUIRED = 0x00000040
ES_SYSTEM_REQUIRED = 0x00000001
ES_DISPLAY_REQUIRED = 0x00000002

def denysleep(): #スリープを抑止する
    ctypes.windll.kernel32.SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_CONTINUOUS)

def allowsleep(): #スリープを再開させる
    ctypes.windll.kernel32.SetThreadExecutionState(ES_CONTINUOUS)
```
とりあえず作ってみたけどちゃんと動くか調べてない。

#画面を消す
```Python:
import win32api
WM_SYSCOMMAND = 0x0112
SC_MONITORPOWER = 0xF170

def displaysuspend(): #モニタを強制的にオフにする
    win32api.PostMessage(-1, WM_SYSCOMMAND, SC_MONITORPOWER, 2)
```
Pywin32が必要
オフには簡単にできるが、オンにするのは非常に手間がかかる、メッセージキューに単にモニターオンにしろと流しても動作しないらしい
pyautoguiを使うのが多分ベスト
VMware Fusion for Apple SiliconでWindows 11を使う

# 更新履歴

- 2021/09/27 初期投稿

# VMware Fusion TP21H1

9/22にVMware Fusion Public Tech Preview 21H1 がリリースされました。このリリースの大きな特徴はApple Siliconをサポートしていることです。現時点で対応しているOSは以下の通り。

- Linux (Debian, Ubuntu, VMwareの出してるやつなど） 
- FreeBSD

つまり，Windows on ARMはサポートされていません。しかし，いくつかの制限はあるもののインストールして動かすことはできますので，その手順を手っ取り早く書いてみます。

# 準備

#### 1. VMware Fusionのインストール

以下からVMware Fusionをダウンロード，インストールします。

- [Download Fusion for Apple Silicon Now](https://vmware.com/go/get-fusion-m1)

ダウンロードする際にVMware Customer Connectに登録する必要があると思いますので，登録します。

#### 2. QEMUのインストール

ディスクイメージを変換するためにQEMUのツールを使うのでQEMUをインストールします。

# Windows 11 on ARMを動かす手順

#### 1. Windows 11 on ARMのダウンロード

以下のサイトから Windows 11 on ARM Insider Preview をダウンロードします。

- [Windows Insider Preview Downloads](https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64)

ダウンロードされるのはVHDXというWindows Hyper-V用の仮想ディスクイメージです。

#### 2. ディスクイメージの変換

QEMUのツールである `qemu-img` を利用してVHDXディスクイメージをVMwareの仮想ディスクイメージのフォーマットであるVMDK形式に変換します。

```:shell
  $ qemu-img convert -f vhdx -O vmdk Windows11_InsiderPreview_Client_ARM64_en-us_XXXX.VHDX Win11_ARM64.vmdk
```

#### 3. 仮想マシンの新規作成

VMware Fusionを起動し，「その他のOS」の仮想マシンを新規作成します。その際，ディスクイメージを新規作成するのではなく，「既存のディスクイメージを利用」するようにします。

既存のディスクイメージとして，先ほど変換したVMDK形式のディスクイメージを指定します。この際，コピーするように指定しておくと良いと思います。

#### 4. 構成の設定

初期構成だとメモリ容量が 256MB ととんでもなく少なくなっているので，これを4GBとか6GBくらいに変更します。

以上でWindows 11 on ARMの仮想マシンが作成されます。起動するとWindows 11が起動します。

# 制限

現状，VMware Fusion上でWindows 11 on ARMを利用するにはいくつかの制限があります。

### VMware Toolsがない

正式にサポートされていないので当然かもしれません。もしかしたらあるのでは...という淡い期待を抱きながら動かしてみましたが，やっぱりVMware Toolsがありません。そのため，以下のような直接的な制限があります。

#### 1. ネットワークが利用できない

結構致命的なんですが，VMware Fusionの仮想マシン上のネットワークインターフェイスがWindows11 on ARMからは認識できません。というか，認識できていてもドライバがないので利用できません。

もしかするとWindows 11 on ARM on QEMU用のドライバが利用できるかもしれませんが試していません。

正式にはVMware Toolsの対応を待つしかないように思います。

#### 2. 解像度の制限

以上，簡単ですが。
Flutter webでfirebase storageから画像を取得するImageProvider

NetworkImageの用な感じで、Firebase storageから画像を読み込んで表示するためのImageProviderを作りました。

# 経緯
downloadUrlを使えば画像表示するだけなら事足りますが、セキュリティルールとか厳密にしたくなるとfirebaseのライブラリから通常の認証を経由して画像を取得するのがいいと思いました。
ios/android は [firebase_image](https://pub.dev/packages/firebase_image)というライブラリがありましたが、webには対応していなかったので技術検証がてら作ってみました。

# 実際のコード
キャッシュは考慮してないですが、以下のようなコードで機能は実現できました。
NetworkImageのweb版の実装とfirebase_imageを参考にしています。

```
class StorageImage extends ImageProvider<StorageImage> {
  final double scale = 1.0;
  final String path ;

  StorageImage(this.path);

  @override
  Future<StorageImage> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<StorageImage>(this);
  }

  @override
  ImageStreamCompleter load(StorageImage key, DecoderCallback decode) {
    return MultiFrameImageStreamCompleter(
      codec: _loadAsync(key as StorageImage, decode),
      scale: key.scale,
      debugLabel: "debuglabel",
    );
  }

  Future<ui.Codec> _loadAsync(
    StorageImage key,
    DecoderCallback decode,
  ) async {
    assert(key == this);
    print("_loadAsync");

    return await PaintingBinding.instance!
        .instantiateImageCodec(await _fetchImage());
  }

  Future<Uint8List> _fetchImage() async {
    print("_fetchImage");
    final bytes = await FirebaseStorage.instance.ref(path).getData();
    print("fetched:${bytes!.length}");
    return bytes;
  }
}

```
【メモ】LaTeXのプリアンブルを書き出してみる

　そういえばプリアンブルを追加しっぱなしで忘れかけているので、勉強も兼ねて現在のプリアンブルを書き出してみます。

# documentclass, graphicx.sty

```tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{graphicx}
```

　`\documentclass`は原稿全体の体裁を決める命令。和文の短いメモ書きだったり論文だったりであれば`jsarticle`で十分。英語で書く場合は`article`にしないといけませんね。
　`graphicx`は図の取り込みに必要なパッケージ。正直おまじない程度にしか理解していない。

# AMSパッケージ
```tex 
\usepackage{amsmath}
\usepackage{amssymb}
```

　種々の特殊記号や高度な数式を書けるようにするパッケージ。**入れないと人権がなくなる**ので、人権が欲しい人は入れましょう。
　`amsthm.sty`については後述。
　
# enumerate.sty

```tex
\usepackage{enumerate}
```

　箇条書きで用いる`enumerate`環境のカスタマイズができるパッケージ。デフォルトの番号付き箇条書きでは、番号が「1., 2., 3., ...」と振られますが、これを「(a), (b), (c), ...」とか「i), ii), iii), ...」などのように変えられます。詳しくはこちら: 

http://www.yamamo10.jp/yamamoto/comp/latex/make_doc/item/item.php#ENUMERATE_STY

　最近では新たに`enumitem.sty`なるパッケージが出てきた。こちらのほうがカスタマイズが豊富らしい[^1]。
　`enumerate.sty`にしても`enumitem.sty`にしてもかなり便利なので、**入れたほうがいいです。**

# proof.sty

```tex
\usepackage{proof}
```

　証明図を書くときに必要なパッケージ。数理論理学をやる人ならまあ必須。
　これは日本語による説明書きがないので、今度しっかり解説記事を書きたいですね。

# qtree.sty 

```tex
\usepackage{qtree}
```

　木構造を書くときに必要なパッケージ。一回入れたけどあんまり使ってない。

# subcaption.sty

```tex 
\usepackage{subcaption}
```

　図を並列して配列するためのパッケージ。長らく使ってないので使い方を忘れました。

# siunitx.sty

```tex 
\usepackage{siunitx}
```

　SI単位系はじめ、単位をきれいに書けるパッケージ。数式内でも、たとえば`\SI{30}{kW}`と入力するだけで $30 \ \textrm{kW}$ と出力されます[^2]。数字と単位の間を半角スペース分あける、単位は立体にするといった規則に自動で合うように出力できます。
　現在の分野(数理論理学)ではほとんど使いませんが、物理・化学などを先行する人にとっては必須のパッケージ。私も学部の授業で実験レポートを書いたときに入れたのを思い出しました。

# xcolor.sty

```tex
\usepackage{xcolor}
```

　文字色とか背景色を変えられるパッケージ。`HTML`オプションを使えばカラーコードが使えるので超便利。
　まあ文書の作成だけならほとんど使わない。私は後述する`listing`で使っています。

# tikz

```tex
\usepackage{tikz}
\usetikzlibrary{automata}
```

　みんなだいすきTikz　tex内部で図を書けるというスグレモノなので**これは入れておくといいです。**
　拡張機能を使ってさまざまな図を書くことができます。私はオートマトンを楽に書ける`automata`を使っています。

# amsthm.sty

```tex
\usepackage{amsthm}
\theoremstyle{definition}
\newtheorem{dfn}{Definition}[section]
\newtheorem{prop}[dfn]{Proposition}
\newtheorem{lem}[dfn]{Lemma}
\newtheorem{thm}[dfn]{Theorem}
\newtheorem{cor}[dfn]{Corollary}
\newtheorem{rem}[dfn]{Remark}
\newtheorem{fact}[dfn]{Fact}
\renewcommand{\qedsymbol}{$\blacksquare$}
```

　過去の記事で紹介した定理・証明環境です。数学はじめ理論系分野ではほぼ人権パッケージ。

https://qiita.com/hungry_and_fool/items/b28f9bb32ce738889523

# listings.sty

```tex
\usepackage{listings}
\lstset{
    basicstyle={\small\ttfamily},
    columns={fullflexible},
    frame=tlrb,
    rulecolor=\color{black},
    backgroundcolor=\color{black!10}
}
```

　プログラムのソースコードを直接貼り付けるためのパッケージ。`lstlisting`環境を使えば、プログラムのコードを直接テキストファイルとして貼り付けることができます。
　これも学部時代に課題で使ったっきりで今は有効活用できていません。

# 本質情報まとめ

- `amssymb`, `amsmath`**は人権パッケージなので必ず入れよう**
- `enumitem`は便利なので分野を問わず入れよう
- 自然科学系なら`siunitx`を入れて単位入力をしよう
- 数学系なら`amsthm`の環境を作ろう

おしまい

[^1]: 例えば、場合分けのカウンターを太字にすることができる(「(**a**), (**b**), (**c**), ...」)。
[^2]: ちなみにQiitaでは`\SI`が使えなかったので`$30 \ \textrm{kW}$`と記述しています。`siunitx.sty`を使わない場合はこのように入力することになりますが、面倒ですね。
kubectlでNodeGroupごとにNodeの数をカウントする(AWS EKS, Kubernetes)

jsonpathの練習として。どのNodeGroupにいくつNodeがあるか見たいときに。

```bash
kubectl get nodes -o jsonpath='{range .items[*]}{@.metadata.labels.nodegroup-name}{"\n"}{end}' | sort | uniq -c
```

```bash
  22 nodegroup-foo
   5 nodegroup-bar
```

参考: [kubectlチートシート](https://kubernetes.io/ja/docs/reference/kubectl/cheatsheet/)

関連: [kubectlでNodeGroupにあるPodを一覧表示する(AWS EKS, Kubernetes)](https://qiita.com/tippy/items/2d22d0e322ddedea06c5)
[Ruby] AtCoder過去問 B - Foods Loved by Everyone

##はじめに
AtCoder過去問のB問題をRubyで解いてみました。
よろしくお願いします。

問題はこちらから確認してください。↓

https://atcoder.jp/contests/abc118/tasks/abc118_b

##B - Foods Loved by Everyone
はじめに入力を受け取ります。

```ruby
n, m = gets.split.map(&:to_i)
a = readlines(chomp: true).map{|line| line.split(' ').map(&:to_i)}
```

2行目は二次元配列で受け取っています。入力例1を例にすると
```[[2, 1, 3], [3, 1, 2, 3], [2, 3, 2]]```
といったように受け取ります。

配列aの中のそれぞれの配列の先頭（インデックスで0番目)の数字は好きな食べ物の数を表しているだけです。好きな食べ物を表しているわけではないので、邪魔になります。消しましょう。

```ruby
n, m = gets.split.map(&:to_i)
a = readlines(chomp: true).map{|line| line.split(' ').map(&:to_i)}
 
a.each do |i|
  i.delete_at(0)
end
```

これでそれぞれの先頭の数を消せました。入力例1では現在aは下記のようになっているでしょう。

```[[1, 3], [1, 2, 3], [3, 2]]```

続いて、この配列aの中身を一つに結合したいです。
flattenメソッドを使って一次元配列にします。

```ruby
n, m = gets.split.map(&:to_i)
a = readlines(chomp: true).map{|line| line.split(' ').map(&:to_i)}

a.each do |i|
  i.delete_at(0)
end

flat_a = a.flatten
```

これで一次元にできました。
入力例1でいえばflat_aは下記のようになっているでしょう。

```[1, 3, 1, 2, 3, 3, 2]```

あとは1~mの数字がそれぞれがこの配列の中に何個あるかを調べます。そしてその個数と人数が同じだったら全ての人が好きであるということなのでその場合、変数ansに＋１します。
最後にansを出力して完成です。

```ruby
n, m = gets.split.map(&:to_i)
a = readlines(chomp: true).map{|line| line.split(' ').map(&:to_i)}
 
a.each do |i|
  i.delete_at(0)
end
 
flat_a = a.flatten
 
cnt = 0
 
(1..m).each do|j|
  if flat_a.count(j) == n
    cnt +=1
  end
end
 
puts cnt
```
M5stackでアバターを動かしてみた

#本記事の内容
- M5Stack Grayにアバターを表示させてみました！かわいいー。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5Stackでアバターを動かしてみた！かわいい～ <a href="https://t.co/Q2pN0uYhOd">pic.twitter.com/Q2pN0uYhOd</a></p>&mdash; kaname kun (@kanamekunkun) <a href="https://twitter.com/kanamekunkun/status/1441308458305736708?ref_src=twsrc%5Etfw">September 24, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


#実施環境
- Windows 10
- Arduino 1.8.16
- M5Stack Gray

#手順の流れ 
1. アバター用のライブラリーのダウンロード
2. Arudino IDEでのライブラリの取り込み
3. ライブラリーのサンプルプログラムの実行

## 1. アバター用のライブラリーのダウンロード

アバター用のライブラリーを公開してくださっている[こちらのページ](https://github.com/meganetaaan/m5stack-avatar)にアクセス。
”Code”をクリックし、"Download ZIP"からライブラリーをダウンロードする。

![00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/bd484f88-199e-2e0d-bdc1-15a7ef103828.png)



## 2. Arudino IDEでのライブラリの取り込み

Arduinoツールを起動し、`スケッチ > ライブラリーをインクルード > .zip形式のライブラリーをインストール ...`のメニューを開く。

![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/e190048b-321f-2ba3-f06f-e2e3867d3b57.png)

ダウンロードしたライブラリーのzipファイルを指定する。

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/1c977454-485d-4ac0-463c-225582ef7bb5.png)

ライブラリー追加完了のメッセージが画面の下部に表示された。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/70970297-5b6d-a8ab-e247-83bab936c14f.png)


## 3. ライブラリーのサンプルプログラムの実行

メニューから`ファイル > スケッチ例 > M5Stack_Avatar > basics`をクリックする。

![06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/f28c2185-bd14-70a1-4a27-dbb12713c52c.png)

以下のようにサンプルプログラムが開かれる。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/6da85c14-1a76-174c-16c3-85c4e6fb6121.png)


マイコンボードに書き込むアイコンをクリックし、M5Stackにプログラムを書き込む。
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/f81282d5-fba3-47fa-601f-418893ededa8.png)

「ボードへの書き込みが完了しました。」のメッセージが表示され、M5Stackにアバターが表示された。

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/ad9c17f5-ad43-075c-83c0-1e5040fefbad.png)


![IMG20210927112106.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/ff5ff1e4-cd21-14be-58a3-b7cf5196ab6c.jpeg)

実施して気づいたのですが、スピーカーからノイズ？が聞こえます。
M5.Speaker.begin()とM5.Speaker.mute()をsetup時に実行するようにすることで、防げるようなので、コードに付け足したところ、ノイズが収まりました。

	void setup()
	{
	  M5.begin();
	  avatar.init(); 
	  M5.Speaker.begin(); // この行を追加
	  M5.Speaker.mute();  // この行を追加
	}

手順は以上。

# 参考文献
本記事の作成に当たり、以下の情報を参考にさせて頂きました。
- [M5Stack のアバターを試してみる](https://blog.akanumahiroaki.com/entry/2018/08/18/220000)
- [M5Stackのスピーカーを無効にして雑音（ノイズ）を消す方法](https://asukiaaa.blogspot.com/2020/03/m5stack-disable-speaker.html)
scikit-learnによる問題解決のためのアプローチ


Pythonで利用可能な機械学習のライブラリであるscikit-learnがあります。分析を行なった人なら使ったことがあると思います。

scikit-learnのドキュメントにはアルゴリズムの仕様説明だけでなく、機械学習におけるアプローチ方法についても記載があります。

機械学習の問題解決のために試行錯誤する際に、道標となるような基本的なアプローチ方法がまとまっているので紹介します。

## ドキュメント

scikit-learnのドキュメントは安定版の1.0をベースに紹介します。
開発版の1.1も公開されているので興味がある方は覗いてみてください。

安定版1.0

https://scikit-learn.org/stable/

開発版1.1などの別バージョン

https://scikit-learn.org/dev/versions.html

GitHub ソースなど

https://github.com/scikit-learn/scikit-learn

## 検出器の選び方

機械学習の問題を解決する上で最も難しいのは、その作業に適した推定器を見つけることであることがよくあります。
機械学習の手法ありきではなく、データありきで問題を解決する必要があるので、データの特徴をよく理解した上で最適な手法を選択する必要があります。

データの種類や問題によって、適した推定器は異なります。

以下のフローチャートは、データに対してどの推定器を試すべきか、どのように問題に取り組むべきか、大まかなガイドとなるようにデザインされています。

下のフローチャートの各推定量をクリックすると、そのドキュメントが表示されます。

![ml_map_sl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/a6abd3f8-4a2c-bb4e-015b-8e886efcb7ae.png)

https://scikit-learn.org/stable/tutorial/machine_learning_map/

オレンジ色のSTARTから見ていくと、アルゴリズムを選択する分岐点には、データ数が10Kや100K以上あるかが判断材料になっていることがあります。

自分の使ったことがあるアプローチだけでなく、データの特徴に基づいて判断してアプローチ方法を変えてみるというのも大切です。

緑色の検出器までたどり着くと、４つの大きなカテゴリ(classification,regression,clustering,dimensionality reduction)に分かれています。以下に４つのカテゴリの特徴をまとめます。

## 分類 classification

ある物体がどのカテゴリーに属するかを識別すること。

応用例はスパム検出、画像認識。
アルゴリズムはSVM, nearest neighbors, random forest, など。

## リグレッション regression

物体に関連する連続値の属性を予測する。

応用例は医薬品の反応、株価の推移。
アルゴリズムはSVR, nearest neighbors, random forest など。

## クラスタリング clustering

類似したオブジェクトをセットに自動的にグループ化すること。

応用例は顧客のセグメンテーション, 実験結果のグループ化。
アルゴリズムはk-Means、スペクトルクラスタリング、Mean-Shiftなど。

## 次元削減 dimensionality reduction

考慮すべき確率変数の数を減らすこと。

応用例は可視化、効率化。
アルゴリズムはk-Means、特徴選択、非負行列因子分解など。
CentOS7とiptablesで簡単にポートフォワーディングする


CentOS7でポートフォワーディングをしたい場合、本来あるべき姿としてはfirewalldを使って対応する方法かと思いますが、firewalldで設定するのが手間だったり（設定に手間を掛けたくない）、VirtuozzoやOpenVZ上のコンテナのような、環境によってfirewalldが利用できない（firewalldするとコンテナがハングアップする等）というケースもあると思います。そのような場合は、iptablesを使うことになります。

iptablesによるポートフォワーディングについて検索してみると、SNATで対応する方法、IPマスカレードで対応する方法が出てきますが、ここではIPマスカレードで対応することにします。なお、IPマスカレードの場合、転送先のホストからは転送元のホストから接続されたように見えます（転送先のホストでは、本来の接続元が何かを確認することはできませんので、その点について理解したうえで利用する必要があります）。

## 手順

```
# yum erase -y firewalld
# yum install -y iptables-service
# iptables -t nat -A POSTROUTING -d <転送先FQDN or IPアドレス> -j MASQUERADE
# iptables -t nat -A PREROUTING --dport <転送元ポート番号> --to <転送先FQDN or IPアドレス>:<転送先TCPポート>
```


なお、IPマスカレードの定義に関しては、各ポートフォワーディングの転送先となるホストが同一セグメント（例えば、10.0.0.1, 10.0.0.2, 10.0.0.3など）であれば、次のように設定することで、転送先を1件ずつ追加する必要がなく、この設定1つのみで済みます。

```
# iptables -t nat -A POSTROUTING -d 10.0.0.0/24 -j MASQUERADE
```


設定が問題なければ以下を実行します。

```
# service iptables save
```
眼鏡ユーザーでもVRがしたい！　前説編

# 前書き
こんにちは、回路設計エンジニアの樋口です。最近は他社製の製品に組み込まれている基板にマイクロスコープあてて部品の型番を調べるといったお仕事が増えてきました。そろそろ基板設計のお仕事来ませんかね？

突然ですが皆様はVRというものを体験したことがありますか？
![DSC_0026.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600123/18787669-4209-ae83-e147-299a3eacf93b.jpeg)

日本語にすると『仮想現実』というんでしたっけ？目の前に映像を投影することで利用者が映像内に入っているような感覚でゲームや会話等を楽しめるシステムですね。最近だいぶ手に入りやすくなりましたがなかなかすごい物です。

数年前にまともに動くVR機器を導入しようと考えたら、選べるのは台湾HTC社のVIVEや米国Oculus社のRiftといった値段が10万円近くする高級な機種ぐらいしかありませんでしたし、それに加えてそこそこ値の張るGPUを搭載したPCも必要になって
『総額が20万円超えたぞ、うわ～貯金消えたわ～』という話をよく聞きましたが、

今はすごいですね～。
2017年の後半ぐらいでしたかね、米国MicrosoftのWindows MRというVR機器が5万円前後で買えるようになったのが始まりだと思いますが急速にVR機器の低廉化が進み、
執筆時点(2021年後半)では、もはや高額なPCを使わなくてもそれなりに楽しめてしまうHTC Focusや、PC無しでそれなりに使える一方で無線接続でPCに接続すると本格的なVRを楽しめるというまさに一石二鳥なVR機器なのにお値段なんと3万円台というOculus Quest2なんてのも出てきました。
びっくりですよ。数年前は20万円以上出さないと楽しめなかったVRが今ではたったの3万円台ですよ。
一体どこまで安くなるんでしょうかね。この市場。<br><br><br><br>
さて、そんな値下げ合戦と性能向上が続くVR業界ですが、いくら時間がたってもたびたび問題に上がるものがあります。


![fashion_glasses_megane.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600123/7d84b2b6-e938-b0ad-ee06-c1f37c927f93.png)
<br><br>眼鏡です。
目の屈折異常の補正や、目を保護、あるいは着飾ったりするための、目の周辺に装着する器具(Wikipediaより引用)としてとてもポピュラーな物ですが、VR機器を使用するときにはよく問題が発生します。<br><br><br><br>
$\huge{鼻}$が痛いんです。<br><br>
なんとも説明しにくいんですが、VR機器を装着するときに眼鏡を付けたまま装着すると、VR機器によって眼鏡が鼻に押し付けられる状態になる機種が多いんですよ。
で、遊んでいるうちにVR機器がずれないようにキツめに装着すると眼鏡の鼻あて部分が鼻背に食い込む感じになってしまいましてね...痛いんですよ。<br>
だからと言って眼鏡をはずして装着しようものならせっかくのVRの世界がぼやけて何が見えているのかわからないと。
ということで鼻の痛みを我慢しながらVR機器を使用していたのですが、そうですね、購入してから3ヶ月ぐらい経過したぐらいでしょうか、
眼鏡とVR機器によって負荷をかけられ続けた鼻背のあたりがついに<FONT COLOR=red>出血</FONT>しまして。
当時学生でしたので研究室に通っていましたが、なぜか鼻背という怪我しにくい部位にカサブタがついているというなかなか奇妙な姿の筆者が誕生していましたよ。<br>
で、対策を考えました。
**VR機器に取り付ける視力補正用レンズを作れば出血しなくて済むのでは？**<br>
ということで、これまで試してきた内容を数回に分けながら少しずつ解説していきます。なんせ学生時代からちまちまと実験している内容ですからねぇ。それなりにボリュームも多いわけですよ。ご了承ください。

# 準備
今回の記事は前説編ということで先程の前書きがこの記事の大部分を占めるのですが、それだけではさすがに記事らしくないので、行ってきた実験でほぼ毎回共通して使用した機材を紹介します。実験開始した当時、これらをそろえて実験を行いました。<br>
・PC
　CAD等が快適に動作するそれなりに恵まれたPCです。
・VR機器
　しっかりレンズが装着できるか確認するために必要です。実験開始時点では、Windows MRの一種であるAcer AH101を用意していました。(注：過去形)
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600123/ef228c74-5420-d22d-4f73-48de4dcd4c1e.png)
　(画像はAcer公式サイトから引用しました)
・3Dプリンタ
　3DCADでモデリングしたレンズのフレームの出力用として用意しました。機種はANYCUBIC社のI3 Mega、それなりに安くてそれなりに快適に動作してくれるFDM式の3Dプリンターです。とてもおすすめ。

# 今回のまとめ
今回の記事では、私が数年前からゆっくり進めているVRレンズの説明と準備した機材の説明をしました。次回の記事から実際に設計したものと結果等を順番に解説していきます。
次の記事はこちら　https://qiita.com/Guppy_T_Higuchi/items/baf53e4ff3b75bb1e077

<DIV ALIGN=CENTER><HR COLOR=BLUE WIDTH=50%></DIV>
執筆日　2021/09/27

執筆者　樋口(Qiitaアカウント名 ＠Guppy_T_Higuchi)
DockerでWordpressを立ち上げ、ローカルのディレクトリでファイルを編集できるようにする

# 概要

[Dockerのドキュメント](https://docs.docker.jp/compose/wordpress.html)を見るとcomposeを使ったwordpressの立ち上げ方がわかります。
しかし、そのままではwordpressのソースコードを編集したいときにコンテナ内に入らないといけないため編集がしづらいです。
ボリュームをマウントすることで、ローカルのディレクトリでphpやcsvを編集できるようにする方法を紹介します。

# やり方
docker-compose.ymlのwordpressのところで`volumes`に`./wp:/var/www/html`を指定。
これで、ローカルのディレクトリをコンテナにマウントできる。

```
$ docker-compose up -d
```

```docker-compose.yml
version: '3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     volumes:
       - ./wp:/var/www/html
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
volumes:
    db_data:

```