OmniAICreator/Qiita-1.07M huggingface dataset:
YouTube Data API (v3) による YouTube 動画のコメント取得（Ruby版）

# はじめに
[YouTube Data API v3](https://developers.google.com/youtube/v3) を使用してYouTube動画のコメントを取得します。

使用言語は`Ruby`で、__Ruby 用 Google API ライブラリ（[google-api-ruby-client](https://github.com/googleapis/google-api-ruby-client)）のバージョンは`0.37.3`__です。

# 事前準備

- API キー
- Ruby 用 Google API ライブラリ

## APIキー取得

下記参照下さい。
[Youtube Data APIを使用して、Youtube Liveのコメントを取得する - Apiキーの有効化](https://qiita.com/MCK9595/items/fdbd543ff938febcd136#api%E3%82%AD%E3%83%BC%E3%81%AE%E6%9C%89%E5%8A%B9%E5%8C%96)

## Ruby用Google APIライブラリインストール

```
$ gem install google-api-client
```

# YouTube動画のコメント取得

## 基礎編

YouTube Video ID を指定して、対象動画のコメントを10件取得する例です。

ちなみにYouTube Video ID とは、`http://www.youtube.com/watch?v=aN46pEO_jX8`の`aN46pEO_jX8`の部分です。

```rb
require 'google/apis/youtube_v3'

class YoutubeApi
	attr_reader :response

	def initialize api_key
		@youtube = Google::Apis::YoutubeV3::YouTubeService.new

		@youtube.key = api_key # APIキー設定
	end

	def comment_threads video_id
		@response = @youtube.list_comment_threads(
			'snippet', # part
			max_results: 10, # コメント取得件数（1 ~ 100で指定可）
			text_format: 'plainText', # 出力フォーマット（html / plainText 形式のいずれかを指定可）
			video_id: video_id)
	end
end

if $0 == __FILE__

	api_key = 'xxx' # APIキー
	youtube_api = YoutubeApi.new(api_key)

	video_id = 'xxx' # Video ID
	youtube_api.comment_threads(video_id)

	comment = youtube_api.response.items.first.snippet.top_level_comment # 最初のコメント

	p comment.snippet.author_display_name # ユーザ名
	p comment.snippet.text_display # コメント

end
```

## 応用編

YouTube Data API v3の制約上、一回のアクセスで取得可能な最大コメント数は100なので
コメントの多い動画（例えば、2000件のコメント投稿のある動画）だと、後ろのコメントが取得できません。

よって、次のステップとして
対象動画のコメントを最新日時順で100件以上取得する例を紹介します。

```rb
require 'google/apis/youtube_v3'

class YoutubeApi
	attr_reader :response

	def initialize api_key
		@youtube = Google::Apis::YoutubeV3::YouTubeService.new

		@youtube.key = api_key # APIキー設定
	end

	def comment_threads video_id, page_token = ''
		@response = @youtube.list_comment_threads(
			'snippet', # part
			max_results: 100, # コメント取得件数（1 ~ 100で指定可）
			order: 'time', # 取得コメントの並び順（time / relevance 形式のいずれかを指定可）
			page_token: page_token, 
			text_format: 'plainText', # 出力フォーマット（html / plainText 形式のいずれかを指定可）
			video_id: video_id)
	end
end

if $0 == __FILE__

	api_key = 'xxx' # APIキー
	youtube_api = YoutubeApi.new(api_key)

	next_page_token = ''

	video_id = 'xxx' # Video ID

	10.times do |i|
		youtube_api.comment_threads(video_id, next_page_token)

		p youtube_api.response

		next_page_token = youtube_api.response.next_page_token
	end

end
```

### 基礎編との差分

- `order`使用：最新日時順で取得
- `page_token`使用：コメント取得ページの指定

# 最後に

本プログラムを使って、コメント分析（言語・感情解析）をしていこうと思います。
次回記事も是非読んで下さい。

# 最後の最後に（更新追記分）

本記事では、APIキーを使った認証方法にてYouTube 動画のコメント取得を行いました。
只、ユーザーのプライベートデータにアクセスするには、Googleは`OAuth 2.0`の使用が必須とのことなので、ご注意下さい。

動画のコメントはプライベートデータになるのでしょうか？
わかる方いればご教授願います。
Goで作った自作ツールをGithubActionsでクロスプラットフォーム向けに自動リリースするテンプレ

# Goのクロスコンパイルばり便利
Goの便利な機能の一つにクロスコンパイルがあります。
同OSでの実行ファイルはもちろんのこと、例えばMac上でWindows用のexeファイルを作ったりできます。
GithubActionsと連携することで、さらに楽にクロスプラットフォーム向けに実行ファイルをリリースできるので
やり方を紹介します。

# 前提
- Go 1.13以降
- Go Modules使用
- [今回の開発環境はVSCode Remote Containerで用意](https://qiita.com/maroKanatani/items/75c38f6ab2f474ef7d37)(ここはまぁ何でも良いと思います)

# 手順
- プロジェクト直下に以下の.goreleaser.ymlを配置。

```yml:.goreleaser.yml
project_name: sample # 任意の名前を設定する
env:
  - GO111MODULE=on
before:
  hooks:
    - go mod tidy
builds:
  - main: .          # mainのディレクトリを指定する
    binary: sample   # 任意の名前を設定する
    goos:
      - windows
      - darwin
      - linux
    goarch:
      - amd64
    env:
      - CGO_ENABLED=0
archives:
  - name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
    replacements:
      darwin: darwin
      linux: linux
      windows: windows
      386: i386
      amd64: x86_64
    format_overrides:
      - goos: windows
        format: zip
    files:       # zipやtarに実行ファイル以外に含ませたいファイルがあれば設定する
      - config.ini
      - README.md
release:
  prerelease: auto
```

- プロジェクト直下に.github/release.ymlを配置する。

```yml:.github/release.yml
name: release # 任意の名前を設定する
on:
  push:
    tags:     # 任意のtag この例ではv0.0.0のような形でtagを切るとReleaseされる
    - "v[0-9]+\\.[0-9]+\\.[0-9]+"
jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v1
        with:
          fetch-depth: 1
      - name: Setup Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.13
      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v1
        with:
          version: latest
          args: release --rm-dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

- （上の2ファイルをPushした後）gitコマンドを実行

```
git tag v0.1.0
git push origin v0.1.0
```

# サンプル
[こちら](https://github.com/Kanatani28/redmine-user-generator)
（release.ymlのパスが.github/workflows/release.ymlになっているけどあまり気にせず）

# 参考
https://tellme.tokyo/post/2020/02/04/release-go-cli-tool/
【Laravel7】There is no existing directory at "storage/logs" and its not buildable: Permission denied

## 環境

- PHP 7.4.4
- Laravel 7.5.1

## エラー

![スクリーンショット 2020-04-12 17.34.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/4ca8898d-143a-703c-ae4d-f158a72b9627.png)

```
There is no existing directory at "/work/backend/storage/logs" and its not buildable: Permission denied
in /work/backend/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php (line 171)
in /work/backend/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php -> createDir (line 99)
in /work/backend/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php -> write (line 42)
in /work/backend/vendor/monolog/monolog/src/Monolog/Logger.php -> handle (line 323)
in /work/backend/vendor/monolog/monolog/src/Monolog/Logger.php -> addRecord (line 541)
in /work/backend/vendor/laravel/framework/src/Illuminate/Log/Logger.php -> error (line 174)
in /work/backend/vendor/laravel/framework/src/Illuminate/Log/Logger.php -> writeLog (line 87)
in /work/backend/vendor/laravel/framework/src/Illuminate/Log/LogManager.php -> error (line 547)
in /work/backend/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php -> error (line 122)
```

## 原因

`storage` ディレクトリに書き込み権限がないため。

## 対策1

```shell-session
$ php artisan config:clear
```

## 対策2

```shell-session
$ chmod -R 775 storage bootstrap/cache
```

[The stream or file "storage/logs/laravel.log" could not be opened: failed to open stream: Permission denied エラーが出たときの対処法](https://qiita.com/ucan-lab/items/54575fd939b9067d1cb6) こちらと同様にパーミッションの場合もあります。

`storage` と `bootstrap/cache` の2つのディレクトリは書き込み権限を付与してあげる。
AWSユーザー向けにAzureの雰囲気を紹介します

#1. はじめに
いきなりですがAWSユーザーのみなさん、Azureのことをどう思ってますでしょうか？
AWSが実案件で当たり前のように使われるようになって飽きていたり、Azureの売上高や成長率が伸びているという情報を小耳に挟んだりして気になっていませんか？
そこで、短期間ではありますが、どちらのクラウドでも構築案件の経験がある私が、AWSユーザーの皆さまにAzureの雰囲気を自分なりに紹介できないかなと思い、本記事を作成しました。

#2. コンソール画面 (Azure portal)
最初に様々な操作を行うAzure portal (AWSでいうところのAWSマネジメントコンソール) について紹介します。

##2.1. ダッシュボート
ダッシュボードは、作成したリソースなどをAzure portal で集中的に整理できるものです。
例えば、リソースのメトリックや時計、すべてのリソース（履歴順）など表示したいものとその配置を好みにカスタマイズできます。
例として、個人の検証用アカウントのダッシュボードをお見せします。
<img width="551" alt="azure001-2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571680/c76d959c-6cb9-ba23-54b8-1f9d611c5494.png">
正直自分はまだ使いこなせてませんが、自由度も高く、とても便利で素晴らしい機能ですので、ぜひ自分が使いやすいようカスタマイズしてください！

##2.2. ポータルの設定
ポータルの背景色を変えるとAzure portalが見やすくなります。テーマの選択の4種類(デフォルト、青、明、暗)とハイコントラストの2種類（白、黒）の計6種類から選ぶことができます。(ハイコントラストを選ぶ場合はテーマの選択を上書きする形になります。)
AWSマネジメントコンソールの公式機能にはないので、意外と知らない人もいるかもしれないですね。この記事で知った方はぜひお好みのカラーに設定してみてください。
個人的には暗の設定が落ち着いていて好きです。自分は検証用アカウントを仕事用アカウントと差別化するために明の設定にしています。

例）テーマ 暗のポータル
<img width="551" alt="azure002-2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571680/cf6c37da-3807-9c45-6074-f1b58c758a7a.png">
また、ポータルの設定からログイン時に最初に開かれるページを"ホーム"にするか"ダッシュボード"にするか選択できます。ログイン時に一目でリソース状況など確認できるのは便利なのでダッシュボードにしておくことをお勧めします。

##2.3. Azureサービスお気に入り機能
Azure portal でサービスをお気に入り設定すると、メニュー画面に並んで表示されます。同様にAzureサービスをダッシュボードにピン留めすることもできます！
これらの設定をしておくと素早くサービスにアクセスできるようになりますので、よく使うサービスを登録しておきましょう。
<img width="551" alt="azure003-2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571680/9b11bf10-36eb-05e5-17b2-e9e79bf09b65.png">
##3. リソースグループ
Azureでは、仮想マシンやデータベース、仮想ネットワークなど、Azure環境上に構築する各サービスのことをリソースといい、リソースを作成する際は、必ず1つリソースグループを指定する必要があります。

つまりAzure環境を構築するには、まずはリソースグループの設計が必要になります。
リソースグループの特徴として、リソースグループを削除すると、関連づいているリソースも全て一緒に削除されます。つまり、ライフサイクルが同じリソースを同一のリソースグループ上にまとめるという考え方がAzureでは1つのポイントになります。

##4. おわりに
ここまでAzureの雰囲気として抑えておくと個人的にいいと思うポイントを紹介しました。NWやVM、RDBなどのサービス機能にはAWSとそこまで違いはないと思いますので、ちょっとした癖に慣れてしまえば問題なくAzureも使いこなせると思いますので、ぜひAzure無料アカウントを作成して触ってみてください！
最後までお付き合いいただきありがとうございました。
JSON Server + ngrok

## 前提 
***Json Server***

- APIモックツール
    - https://github.com/typicode/json-server

***ngrok***

- Public URLs for exposing your local web server.
    - https://ngrok.com


## 使い方
### 1. json-serverとngrokのインストール

`mkdir jsonserver && cd jsonserver
npm init
npm install json-server ngrok`

### 2. db.jsonの作成

```db.json
{
  "posts": [
    {   
      "id": 1,
      "title": "Post title 1"
    }
  ],
  "comments": [
    { "id": 1, "body": "comment 1", "postId": 1 }
  ]
}
```

### 3. package.jsonの中から "scripts"の部分変更
```json
  "scripts": {
    "db": "json-server -w db.json -p 3001",
    "tunnel": "ngrok http 3001"
  },

```

### 4. json-serverとngrokの起動

ターミナルをもう一つ起動し、それぞれのターミナルで下記の2つのコマンドを実行。

`npm run db
npm run tunnel`

### 5. データ確認

```
$ curl http://###.ngrok.io/posts/1
{
  "id": 1,
  "title": "Post title 1"
}
```
商品詳細画面での画像の折り返し表示をする

# 商品詳細画面での商品画面を折り返し表示させる
最終的にこのようなかたちで表示をさせたい
<img width="759" alt="スクリーンショット 2020-04-12 17.35.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531549/93de1b2a-d68b-5562-b782-d9d6a913bbcd.png">

# まずは画像をモデルから取り出す

```ruby:show.html.haml
.photo__box
  %ul.photo__innner
    %li
      = image_tag @item.images.first.src.url, class: "main__image"
      %ul
        - @item.images.each do |image|
          %li
            = image_tag image.src.url, class: "image__list"
```

ulやliの階層については正しいのか自信がありませんが私はこのような形で実装しています。
商品を@itemと設定しましたので、@itemのimagesの一番前の配列をとりだしているのが`class:main__image`になります。

その下の階層に商品画像をすべて取り出すための`- @item.images.each do |image|`にて画像をeachにて取り出しています。
`li`の中で` = image_tag image.src.url, class: "image__list"`で画像を１枚ずつ取り出します。

scssにて整えます

```scss:show.scss
.photo__box{
  float: left;
  margin-right: 15px;
  .photo__innner{
    background-color: #d3d3d3;
    .main__image{
      width: 300px;
      height: 300px;
      object-fit: cover;
    }
    ul{
      display: flex;
      .image__list{
        width: 60px;
        height: 60px;
        object-fit: cover;
      }
    }
  }
}
```

2つめのul（商品画像をすべて抽出してる階層）に`display: flex;`をあてることで横並びになります。

<img width="791" alt="スクリーンショット 2020-04-12 17.51.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531549/ee91359b-efa6-ccc2-2dc2-3c5bd13ec878.png">

横並びにはなるのですがcontentの幅をこえてしまって
右に配置した他の要素が下がってしまいました。
ここで画像を折り返しして綺麗におさまるようにしたいですよね。

# `flex-wrap: wrap;`で折り返し表示させる
要素の幅を超えた場合に折り返し表示させるための記述をします。

```scss:show.scss
.photo__box{
  float: left;
  margin-right: 15px;
  .photo__innner{
    background-color: #d3d3d3;
    .main__image{
      width: 300px;
      height: 300px;
      object-fit: cover;
    }
    ul{
      display: flex;
      flex-wrap: wrap;
      width: 300px;
      .image__list{
        width: 60px;
        height: 60px;
        object-fit: cover;
      }
    }
  }
}
```
`ul`の要素の幅を300pxとして（main__imageと同じ幅）にして右の要素を押し出さないようにした上で
`flex-wrap: wrap;`で要素の折り返し表示をさせます。

<img width="759" alt="スクリーンショット 2020-04-12 17.35.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531549/e14d2868-1643-323b-be41-da40172f3110.png">

こうすることで300pxを超える場合は折り返しするようにしてくれます。

左の要素と右の要素の親要素の幅を超えないようにうまく設定すれば綺麗に収まるようになるはずです。

次回は、`main__image`を下の`image__list`の画像をクリックした場合に切り替わるようにする設定を書きます。

# 追加作成記事
[画像をクリックして画像を切り替える](https://qiita.com/1014Yawara/items/49f41673dd2b76ee12de)
Bootstrap4のテーマ変更のためのサイトメモ

# Bootstrap

公式がやってるテーマのマーケットプレイスという感じ

https://themes.getbootstrap.com/

全て有料かな。npmプロジェクト全体としてパッケージ化されていると思われ。

# Bootswatch

https://bootswatch.com/

フリーで使える21種類のテーマ

SCSSでの導入ができる。またカスタマイズも可能。

```scss
@import "~bootswatch/dist/[theme]/variables";
@import "~bootstrap/scss/bootstrap";
@import "~bootswatch/dist/[theme]/bootswatch";
```

`bootstrap.min.css`も同梱されているので、直接インポートすることもできる。

# Bootstrap 4 by THEMES.GUIDE

http://bootstrap.themes.guide/

フリーで使える14種類のテーマ

`theme.scss`を使えばscssでのインポートも可能。

# Bootstrap Magic

https://pikock.github.io/bootstrap-magic/

カスタマイズをするためのサイト。色だけでなく、各種コンポーネントの細かいパラメータをカスタマイズできる。
バイナリベクタータイルをGeoJSONにデコードする2つの方法

## Abstract
バイナリベクタータイルの実体は、XYZタイルの位置ごとにサーバーに設置されたPBFファイル群です。PBFファイルはプロトコルバッファと呼ばれる規格で（その詳細は把握していませんが）、GeoJSONをシリアライズしたバイナリデータです。つまり元はGeoJSONなので復元（デコード）可能という事です。今回は2つの手法でGeoJSONへのデコードを試みたいと思います。

## tippecanoe-decode
mapbox社謹製のtippecanoeと言えばバイナリベクタータイルの生成で用いられる有名なライブラリですが、付随して、バイナリベクタータイルからGeoJSONへのデコード機能を持っています。

### Install
```shell
brew install tippecanoe
```

### Usage
```shell
tippecanoe-decode <target_pbf> <zoomlevel> <x> <y>
```

これが基本形で、特定のsource-layerのみを抽出する事も出来ます。

```shell:具体例
tippecanoe-decode sample.pbf 13 7121 3260 --layer=road
```
#### 番外編
ベクタータイルをディレクトリで用意出来ている場合、ディレクトリを指定するだけでデコード可能です（この場合、minzoomとmaxzoomを指定してあげた方が安心な挙動をしそう）。しかし出力が少し使いにくいので参考まで（多分PBFファイルを個別に指定するよりこちらの方が速い）。

```shell
tippecanoe-decode bvtiles_dir -z 13 -Z 13 --layer=building
```

## Node.js(vector-tile-js)
こちらもmapbox社製のnpmパッケージです。

### Install
```shell
npm install @mapbox/vector-tile
npm install pbf
npm install fs
```

### Usage
サンプルコードを示します。

```javascript:sample.js
var Pbf = require('pbf')
var VectorTile = require('@mapbox/vector-tile')
var fs = require('fs')

let pbfdata = fs.readFileSync(PBFFILE_PATH)
let pbf = new Pbf(pbfdata)
const layer = new VectorTile.VectorTile(pbf).layers[SOURCE_LAYER_NAME];
if (layer) {
    for (let i = 0; i < layer.length; i++) {
        const feature = layer.feature(i).toGeoJSON(X, Y, ZOOM_LEVEL);
        console.log(feature) //GeoJSON形式のFeature
    }
}
```

## References
- https://cieloazul310.github.io/2018/10/mvt-tile-to-geojson/
AWS Lambda serverless(sls) コマンド入門

## sls command for function

How to deploy, run, stream logs and destroy Lambda functions

```sh:deploy
# deploy
$ sls deploy -v

# deploy only a function  
$ sls deploy function -f <function name>
```

```sh:invoke
# invoke function on local
$ sls invoke -f <function name> -l
```

```sh:log
$ sls log -f <function name> -t
```

```sh:remove
$ sls remove
```
Azure PlayFab の API アクセスポリシーを設定してよりセキュアに運用する

## 前書き
PlayFab の CDN の利用を検討したときにこんな話がありました。

- ユーザーに CDN 上のファイルに自由にアクセスされたくない
- PlayFab の CDN 上にアップロードしたファイルは GetContentDownloadUrl API で取得した署名付き URL からしかアクセスできないので、普通に使っていても意図しないリソースにアクセスされる可能性は低い
- しかし TitleId と LoginId を解析されてしまえばゲームを通さなくても PlayFab SDK から GetContentDownloadUrl を総当り的に叩いて意図しないリソースにアクセスすることも不可能ではないのでこれを禁止したい

PlayFab ではタイトルごとに API のアクセスポリシーを細かく制御することが可能ですので、今回はこれを試してみました。

ちなみに一部の API は GameManager 上でチェックボックスにチェックを入れるだけでポリシーを変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97193/099b74ad-91d0-a35d-2bf3-abf12c6878a7.png)

しかしながら GetContentDownloadUrl は GameManager でポリシーを変更できない API なので、 Admin API を使用してポリシーを変更します。

## Admin API を使って API のアクセスポリシーを変更する
C# のコンソールアプリケーションを作成して以下のコードを実行します。

``` C#
async Task Main()
{
	PlayFabSettings.staticSettings.DeveloperSecretKey = "your title secret";
	PlayFabSettings.staticSettings.TitleId = "your title id";
	
	await PlayFabAdminAPI.UpdatePolicyAsync(new UpdatePolicyRequest
	{
		PolicyName = "ApiPolicy",
		OverwritePolicy = false,
		Statements = new List<PermissionStatement>
		{
			new PermissionStatement
			{
				Action = "*",
				ApiConditions = new ApiCondition
				{
					HasSignatureOrEncryption = Conditionals.False
				},
				Comment = "Do not allow clients to this api",
				Resource = "pfrn:api--/Client/GetContentDownloadUrl",  // ←ポリシーを変更する API 名
				Effect = EffectType.Deny,
				Principal = "*"
			}
		}
	});
}
```

この状態で Client API から GetContentDownloadUrl を実行すると 403 エラーになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97193/efb321da-2511-ed41-0aa5-e0f7d9e8d2da.png)

Client API から実行できなくした GetContentDownloadUrl は、Server API で実行することができます。

クライアント（Unity 等）からは Cloud Script を実行し、Cloud Script 側で Server API を使用して GetContentDownloadUrl を実行してその結果をクライアントに返せば困らないですね。

API アクセスポリシーを設定してよりセキュアにゲームを運用する一例でした。

### 参考ドキュメントなど
[API access policy](https://docs.microsoft.com/ja-jp/gaming/playfab/api-references/api-access-policy)

[Content Delivery Network quickstart](https://docs.microsoft.com/ja-jp/gaming/playfab/features/data/content-delivery-network/quickstart)

[UnityでPlayFabのFileContentをDownloadしてSaveする](https://qiita.com/simplestar/items/47dcfaa213a62a7aa360)
Three.jsで簡単にMeshの移動・回転・拡大

Three.jsを触ってると、UnityやBlenderみたいにマニピュレーターを使いたい時ありますよね。
![Apr-12-2020 17-10-46.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15028/3a4dd651-9fd9-06c7-5e68-fb1553f403bd.gif)
Three.jsには[TransformControls](https://threejs.org/docs/#examples/en/controls/TransformControls)というクラスがあり、`TransformControls`にMeshを`attach`する事で簡単にMeshの移動・回転・拡大縮小ができます。

# 開発環境
Three.js: v0.115.0

# ソースコード
ソースは以下に記載しました。これでマニュピュレーターが表示されて、デバッグが楽になります。
`TransformControls`と`OrbitControls`を組み合わせると、マニュピュレーター以外の領域をDragした場合はカメラ視点も変えられます。
また、ショートカットキーイベントをソースに記述するとW・E・Rで移動・回転・拡大縮小が切り替えられて便利になります。

```typescript
import * as THREE from 'three';
import { TransformControls } from 'three/examples/jsm/controls/TransformControls';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

window.addEventListener('DOMContentLoaded', () => {
  const canvas = document.createElement('canvas');
  const width = window.innerWidth;
  const height = window.innerHeight;
  canvas.width = width;
  canvas.height = height;
  document.body.appendChild(canvas);
  
  const renderer = new THREE.WebGLRenderer({ canvas });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);
  
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
  camera.position.set(0, 0, 5);
  
  const geometry = new THREE.SphereBufferGeometry(1, 30, 30);
  const material = new THREE.MeshBasicMaterial({
    color: 0xff00ff,
    wireframe: true
  });
  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);
  
  const orbitControls = new OrbitControls(camera, renderer.domElement);
  orbitControls.update();
  orbitControls.addEventListener('change', tick);
  
  const transControls = new TransformControls(camera, renderer.domElement);
  transControls.addEventListener('change', tick);
  transControls.attach(mesh);
  
  transControls.addEventListener('dragging-changed', event => {
    orbitControls.enabled = !event.value;
  });
  scene.add(transControls);
  setShotrCutKey();
  tick();

  function setShotrCutKey() {
    window.addEventListener('keydown', event => {
      switch (event.keyCode) {
        case 87: // W = translate
          transControls.setMode('translate');
          break;
        case 69: // E = rotate
          transControls.setMode('rotate');
          break;
        case 82: // R = scale
          transControls.setMode('scale');
          break;
      }
    });
  }

  function tick() {
    renderer.render(scene, camera);
    renderer.setAnimationLoop(tick);
  }
});
```

[参考コード](https://github.com/naotaro0123/three-ts-practice/blob/master/src/Components/HelloTransformControls.ts)
xf86EnableIOPorts: failed to set IOPL for I/O (Operation not permitted)

# Debug
普段どおり自分のアカウントでarch linux OSへログインしようとしたが、正しいusernameとpasswordの入力の末、次のようなエラーメッセージが吐かれた。

```
xf86EnableIOPorts: failed to set IOPL for I/O (Operation not permitted)
(中略)
error: error loading module 'lgi.corelgilua51' from file '/usr/lib/lua/5.3/lgi/corelgilua51.so': waiting for X server to shut down(Ⅱ) Server terminated successfully (0). Closing log file...(中略) E: awesome: main:866 couldn't fin any rc filexinit: connection to X server lostrelgilua51' from file '/usr/lib/lua/5.3/lgi/(以下略)
```

このエラーが吐かれた後、結局ログイン画面へ再び遷移してしまうのだ。

見たところX.Org Server系の問題であり、使用しているウインドウマネージャである[awesome](https://wiki.archlinux.org/index.php/Awesome)のバックグラウンドのluaの何らかのモジュールが読めなくなってしまったらしい(わからない)。

ググってみるといくつか似た状況がみられたが、ウインドウマネージャ系の問題である以上の切り分けが出来ない。

とりあえずこの仮想コンソール(tty1)上ではどうにも出来ないので、別の仮想コンソール(tty2)へ移り(`alt+[F2]`)いくつか確認してみた。`/usr/share/X11/xorg.conf.d/`以下を見たり、`% tail -f .local/share/xorg/Xorg.0.log`等してみても特に問題なさそうであるし、luaのパッケージの問題であると一旦結論した。ので、`pacman`にて更新をかけてみたところ、更新パッケージに悪そうな`lua-lgi`や`wayland`が見つかったので早速更新を実行してみた。その後、ログイン画面へ戻りusernameとpasswordを打ち込んだところ問題なくログインできた！

## まとめ
arch linuxでトラブることって実際普段使いだとあまりないのでコンピュータ初心者のおばあさま方もOSの本とか読みながら使ってみると良いと思う()。

スマホで調べながらデバッグしていたのですが、以下参考に挙げた中国語サイトは[Google 翻訳](https://translate.google.com/)のテキストフォームに直接URLを打ち込むと翻訳していただくことが出来ました(知らなかった)。

### References
- [[SOLVED] xf86EnableIOPorts: failed to set IOPL for I/O](https://bbs.archlinux.org/viewtopic.php?id=232459)
- [请问怎么解决 xf86enableioports: failed to set iopl for i/o](https://bbs.archlinuxcn.org/viewtopic.php?id=3108)
AWSソリューションアーキテクトアソシエイト認定試験学習のまとめ

AWS認定試験のソリューションアーキテクトアソシエイトに合格しました。
受験日が3/25だったので、SAA-C01からSAA-C02に試験の内容が変わってから速攻の受験で合格できて良かった。

<img width="696" alt="AWS000.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6311/e11dee2b-7bc1-2290-f01c-0027d14eb2d0.png">

合格までに取組んだ内容をまとめておきます。

## ソリューションアーキテクトアソシエイトとは

<img width="882" alt="AWS001.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6311/51a47d89-4386-c3db-29fc-c39d9fdaeb47.png">

[AWSクラウドプラクティショナー認定試験学習のまとめ](https://qiita.com/makky_tyuyan/items/47eab62d0a32bf88f073)でも触れましたが、
AWS Well-Architected フレームワークが重要で、このフレームワークに従って「セキュアかつ堅牢なアプリケーションを設計および開発・構築する方法についての理解度を評価する」ものです。

## 背景

AWSの経験(といっても基礎的なサービスだけ)が2年未満であったものの、
実務で必要な範囲を表面的に知っている、使える、という程度でした。

改めて体系的に学んでしっかり身につけたいと考え、その指標としてわかりやすいAWS認定を受けることにしました。
クラウドプラクティショナーも取得しましたが、認定試験に合格することが目的ではなく、必要な人に正しい知識でAWSのアドバイスだったり構築ができるようにしたいと考えています。

## 学習方法

### Udemy

なるべく間を開けずに毎日視聴し、30時間程度です。(模擬試験を含みません)
期間としては3週間くらいで8割のセクションを消化しました。

<img width="878" alt="AWS002.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6311/2b0a2f96-f243-730d-334a-31e74500a4fd.png">

[これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）]
(https://www.udemy.com/course/aws-associate/) を購入しました。
※私の購入時はDiscountされており、1,600円位で購入

すべてをそのまま受講せず、時間の関係でそれなりにスキップしましたが、基本的にはこの講座のアウトラインで学びました。

内容としては「22.5 時間のオンデマンドビデオ」とありますが、教材をそのまま読み上げるところも多い印象でした。
私の場合は、必要な箇所をピックアップしながら、ハンズオンを中心に取り組みました。

後半、セッションに慣れてきたら、1.5倍速で再生し、理解が追いつかないところを重点的に学習するスタンスにしました。

### AWSの無料枠

[AWSの無料枠](https://aws.amazon.com/jp/free/) を活用し、EC2/S3/RDS等の基本的なサービスを触りました。
Udemyと並行しながら、10時間程度です。

<img width="786" alt="AWS005.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6311/5fd2c879-09f0-79c2-7426-6b41470b005b.png">

Udemy教材や書籍だけだと厳しかったと感じてます。

実際にAWSのマネジメントコンソールを使って操作し、EC2等のサービスを実際使って自分の頭を使って設計し、構築しました。
ゼロから構築した経験はなかったので、管理者としての振る舞い(IAM等)は時間かけてキッチリやりました。

**注意点**
無料枠なので油断しがちですが、各種インスタンスやCloudTrail等の設定で放置すると無料枠超えて請求されるので注意です。
無料枠を超えそうなときにアラートが届くように設定しましょう。(Udemyのセッションにある)
私は、S3にDDosいただきまして、たった2日放置しちゃってあっという間に無料枠に達しました。(涙

### AWSソリューションアーキテクトアソシエイト対策本

今回はUdemyに注力したので、補完程度に。

<img width="384" alt="AWS004.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6311/e26d430f-5ff1-5918-1dfd-111039f9032b.png">


### 模擬試験

以下の模擬試験を繰り返し実施、不明点をWEBやUdemyで補完しました。
時間をしっかり記録しなかったんですが、2週間程度の期間でやれるだけ実施。

<img width="604" alt="AWS006.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6311/46038b54-2ccf-8c50-6f10-8d785da6b509.png">
※画像は試験当日の朝に実施。(時間が14分なのは不具合だと思う)

* [最短突破 AWS認定ソリューションアーキテクト アソシエイト合格教本](https://gihyo.jp/book/2019/978-4-297-10382-8) に付属している模擬試験1冊
* Udemyのセッションに含まれている模擬試験2つ

を正答率90%くらいになるまでやりました。
(理想は100%なんですが、タイムアップした)

## まとめ

**模擬試験と同じ問題はでませんでした(重要)**
もはや覚えてないのですが、模擬試験の設問自体が役に立った設問は数問だったような。。。(ちょっと焦った)

クラウドプラクティショナー試験とはちがい、メモ用紙も複数枚もらいます。
求められている(と考えられる)構成書きながら、設問のキーワード探しながら。。。

結果的に130分フルに使いましたｗ

### 感想

AWS Well-Architected フレームワークの、パフォーマンス効率とコスト最適化が多かった気がします。
Aurora、ALB/ELB/CLBの特徴、CDNの理解等は繰り返し復習していて良かった。

セキュリティやネットワークの基礎(特にサブネット)も試されている印象でした。

### ポイント

**設問のキーワードを捉える** という意味で、模擬試験に取り組む。
AWS Well-Architected フレームワークを意識して、模擬試験の正解が「なぜ適しているのか？」を整理する。

個人的見解ですが、振り返った結果、この二点が私としては合格の要因だったかなと思います。
primintrinsic メモ

Wrangleを学習して、ある程度組めるようになるとprimintrinsicを使うケースが増えていきます。
このprimintrinsicは、簡単に説明するとPointsやPrimitives, DetailにHoudiniの都合で値を入れる場所です。
分かりやすい例は、NURBSカーブを作るとします。するとHoudiniは勝手にカーブの長さを求めてprimintrinsicに追加します。
primintrinsicには様々な情報が書き込まれていますので、この値を引っ張ってくると楽ができます。

実際にNURBSカーブの例で確認するとカーブの長さとして85.6765が返ってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615517/2c616507-a5b4-4a1b-ec26-0306b286f6ab.png)


```c#:wrangle
f@curvelength = primintrinsic(0, "arclength", 0);
```

[HIPファイル](https://github.com/DefultVFX/houdini/blob/master/primintrinsic_curve.v1.hipnc)


###primintrinsicリスト
備忘録として追加していきます。

|   primintrinsic     |       説明 |
|:-----------------|------------------:|
| arclength             |              カーブの長さ | 
| measuredperimeter |              カーブの長さ |
PowerShellで環境変数をGUIで一覧表示

`Out-GridView`はPowerShell Core 6に実装されていないのでコマンドから省くとターミナルに表示できます。

## 環境変数をGUIで一覧表示

```powershell
# 長いコマンド
Get-ChildItem env: | Out-GridView

# 短いコマンド
gci env: | ogv
```

## 環境変数PATHをGUIで一覧表示

```powershell
# 長いコマンド
$env:PATH -split ';' | Out-GridView

# 短いコマンド
$env:PATH -split ';' | ogv
```

## 環境変数PATHを重複なし、重複回数を一覧表示

```powershell
# 長いコマンド
$env:PATH -split ';' | Group-Object | Select-Object Name,Count | Out-GridView

# 短いコマンド
$env:PATH -split ';' | group | select Name,Count | ogv
```

## 環境変数PATHから存在しないフォルダを一覧表示

```powershell
# 長いコマンド
$env:PATH -split ';' | Where-Object {-Not (Test-Path -PathType Container $_)} | Out-GridView

# 短いコマンド
$env:PATH -split ';' | ?{!(Test-Path -PathType Container $_)} | ogv
```
railsの複合主キーの警告を非表示にする

## 概要

railsでは複合主キーを持つテーブルはサポート外となっていますが、多対多の中間テーブルにAUTO INCREMENTのIDを振るのはものすごい無駄な気がして嫌なので、その用途に限り私たちの会社では使用を許可しています。

ただ、下記のような大量のWARNINGが出ます。

```
WARNING: Active Record does not support composite primary key.

shop_user has composite primary key. Composite primary key is ignored.
```

テスト実行時などはこのWARNINGが邪魔なのでなんとか非表示に出来ないか調べました。

## コード

強引にモンキーパッチです。読み込まれる場所であればどこでやってもかまいませんが私は`config/initializers/monkey_patches.rb`にまとめてます。

```rb
# config/initializers/monkey_patches.rb
module ActiveRecord
  module AttributeMethods
    module PrimaryKey
      module ClassMethods
        private

          # 元のコード
          # https://github.com/rails/rails/blob/bfbf696ed82df38b68331254f65c25813da83559/activerecord/lib/active_record/attribute_methods/primary_key.rb#L122-L130
          def suppress_composite_primary_key(pk)
            pk unless pk.is_a?(Array)
          end
      end
    end
  end
end
```



## 注意点

この記事は複合主キーの使用やモンキーパッチを推奨する物ではありません。

複合主キーはrailsのサポート外で、上記のウォーニング意外にも色々問題があります。知ってる物だけでも列挙すると・・・

* SomeCompositePrimaryModel.first.destroyなどモデルを直接削除できない。
* 同じく更新できない。
* eager_loadできない。

なんか、使い物にならない感ありますね・・・まあ、回避できなくはないのですがその話はまた別の機会に。というわけで色々大変です。

また、モンキーパッチはrailsのバージョンが変わった時など、動かなくなったり、大きな問題を引き起こす可能性があります。自己責任でご利用ください。
Windows10ProでHyper-Vを導入する方法

#Hyper-Vについて
マイクロソフト社が提供する仮想化システムです。仮想化システムを提供するものは他にもVMwareやVirtuaBox等ありますがWindows10Proの標準機能で手軽に導入できるHyper-Vの導入方法について簡単に解説します。
まったく予備知識のない方にもわかるようにYoutubeに手順を載せてます。こちらも参考にしてください。
https://youtu.be/UHurak9E80Y
※動画にはゆっくり音声（機械音声）が含まれてますので苦手な方はご注意ください。

#用意するもの
Windows10ProがインストールされたPC

以上

#導入方法
+ １． キーボードの[Windowsキー]+[R]を実行し、[ファイル名を指定して実行]タブを表示します。

+ ２．[名前]に[control]と入力しEnterキーを押します。

+ ３．[プログラム]-[プログラムと機能]を選択し、[Windowsの機能の有効化または無効化]を選択します。

+ ４．[□Hyper-V]の左側のチェックボックスにチェックを入れ[OK]を選択します。

+ ５．インストールが始まるので完了するまで待ちます。

+ ６．インストール完了後再起動を実施します。

+ ７．再起動後、[スタートメニュー]-[Windows管理ツール]の下に[Hyper-Vマネージャー]があることを確認します。
　　この[Hyper-Vマネージャー]で仮想マシンの追加等していきます。
　　これでHyper-V機能の導入が完了です。

#最後に
Hyper-Vの導入についてはどうだったでしょうか、Windows10Pro以外でもWindowsServerでもHyper-Vを導入することができます。（むしろこっちが多い？）今後Hyper-Vで仮想マシンを作成する方法や設定も紹介していきます。閲覧していただきありがとうございました。
Chrome拡張機能を作ってみた

## 概要
とりあえずChromeの拡張機能を作って実行してみる。  

難しそうなイメージだったが、実際にやってみると、今の自分のレベルでも思ったよりいろいろできそうだなと感じた。
特に新しい言語が必要なわけでもなく、基本的にはフロント開発と同様`HTML`、`CSS`、`Javascript`で作成することができる。 

## とりあえず作ってみるもの
YouTubeを開くとアラートが出る拡張機能を作ってみる。  
必要なファイルは`manifest.json`と`jsファイル`の2つだけ。

### manifest.json
`manifest.json`はChrome拡張機能での必須ファイル。
拡張機能で使用するスクリプトなどの情報を記載する。

作成したファイルは以下。
細かい説明は省くが、`matches`に当てはまるサイト(今回だとYouTube)を開いたときに、指定したスクリプトが動作するようになっている。

```manifest.json
{
    "manifest_version": 2,
    "name": "Youtube Alert",
    "version": "1.0",
    "description": "YouTubeを開くとアラートが出るだけの機能",
    "icons": {
        "16": "icons/icon16.png",
        "48": "icons/icon48.png",
        "128": "icons/icon128.png"
    },
    "content_scripts": [{
        "matches": ["https://www.youtube.com/*"],
        "js": ["alert.js"]
    }]
}
```

### jsファイル
使用するjsファイルは、manifestで指定した名前で作成する。  

作成したファイルは以下。
単純にアラートを出すだけ。

```alert.js
window.alert('You see Youtube!!');
```

## 実行方法
以下の手順で拡張機能を読み込み、使用できる状態にする。


1. Chromeを開く
2. 3点リーダーをクリックし、「その他のツール」→「拡張機能」を開く
3. デベロッパーモードを有効化する
4. 「パッケージ化されていない拡張機能を読み込む」をクリック
5. 対象のフォルダを開く
6. 対象の拡張機能を有効化する

## 動作確認
実際にYouTubeを開くと、アラートが表示される。
![image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358025/dd80dd49-f120-cc3f-4fc7-1c3432f021ae.png)

## 感想
思ったより簡単。
これからいろいろと作ってみる。
CentOS8になるはやでkuberntesをインストールする手順

CentOS8にkubernetesをインストールするコマンドのメモです。rootで実行してます。
Master✕1, Worker✕2を作りました。

### Dockerインストール（全Node共通）

```
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \
dnf -y install --nobest docker-ce docker-ce-cli && \
dnf -y update https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.10-3.2.el7.x86_64.rpm && \
dnf -y update docker-ce && \
systemctl start docker && systemctl enable docker
```

※podmanがインストール済だったら、uninstallしてからdockerを入れましょう。
↓ありがとうごさいます。
https://qiita.com/cyberblack28/items/0b0ec02bce67a16e2f17

### kubectl, kubeadm, kubeletインストール（全Node共通）

```
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

setenforce 0 && \
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config &&\
swapoff -a && \
dnf install -y kubectl kubelet kubeadm --disableexcludes=kubernetes &&\
systemctl enable --now kubelet
```

### Master setup

firewall設定

```
firewall-cmd --add-port=6443/tcp --zone=public --permanent && \
firewall-cmd --add-port=2379-2380/tcp --zone=public --permanent && \
firewall-cmd --add-port=10250-10252/tcp --zone=public --permanent && \
firewall-cmd --reload
```

```
kubeadm init --pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml
```
### Worker setup

firewall設定

```
firewall-cmd --add-port=10250/tcp --zone=public --permanent && \
firewall-cmd --add-port=30000-32767/tcp --zone=public --permanent && \
firewall-cmd --reload
```

Master setup時に出力されたkubeadm joinのtokenをメモっておいて実行

```
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
```

### おわり

できました。

```
$ kubectl get node
NAME          STATUS   ROLES    AGE     VERSION
k8s-master    Ready    master   3h50m   v1.18.1
k8s-worker1   Ready    worker   3h44m   v1.18.1
k8s-worker2   Ready    worker   4m34s   v1.18.1
```
RxJSのswitchMap mergeMap concatMap


公式の図を見てもいまいち理解しづらいこれらのオペレーターを実際に動かしてみて理解したメモ



### setup

``` sh
echo "{}" > package.json
npm i -D rxjs
```

今回はよくあるユースケースとしてキーワード検索をイメージしています。

``` javascript
const { Subject } = require('rxjs');
const { concatMap, mergeMap, switchMap } = require('rxjs/operators');

const subject = new Subject()

const fetch = ({keyword, delay}) => new Promise(resolve => {
   setTimeout(() => {
     resolve(`response of keyword ${keyword} `)
   }, delay)
 })


subject
  .pipe(
    concatMap(args => fetch(args)) // ここのoperatorを変更して動作確認する。
  )
  .subscribe(next => console.log(next))


setTimeout(() => subject.next({keyword: 'a', delay: 300}), 100)
setTimeout(() => subject.next({keyword: 'ab', delay: 100}), 200)
setTimeout(() => subject.next({keyword: 'abc', delay: 100}), 500)
```


これを実行します。

``` sh
node index.js
```


時間軸を図に表すとこうなります。

|  時間  | 親イベント  | 非同期処理 |  出力|
| ---- | ---- |---- | ---- |
|  100  |  a  |   |   |
|  200  |  ab |   |   |
|  300  |   | abの検索が終了 |  |
|  400  |   | aの検索が終了 |  |
|  500  |  abc |  |   |
|  600  |   | abc の検索が終了 |   |


キーワードaでの検索の結果よりabの検索のほうが早くかえってきてしまったようです。



### mergeMap

非同期処理が終了した順番に流れる。

```
response of keyword ab
response of keyword a
response of keyword abc
```



### switchMap


最新のイベントがながれる。

``` 
response of keyword ab
response of keyword abc
```



キーワードaの検索結果が返ってきたときの最新のイベントはキーワードabであるので流れない。
キーワード(ab|abc)の検索結果が返ってきたときの最新のイベントはキーワード(ab|abc)であるので流れる。



### concatMap

親のイベントが流れた順番にながれる。

```
response of keyword a
response of keyword ab
response of keyword abc
```



時間いじって試してみると理解できると思います。
Windows Server 2019 180日評価版、Windows 10 Enterprise 90日評価版ダウンロード手順

# ダウンロード手順について

本手順では、Hyper-V で稼働させるための OSとして Windows Server 2019 180日評価版 と Windows 10 Enterprise 90日評価版ダウンロードする手順を記載します。

Hyper-V のインストールがまだの場合は、[Windows 10 に Hyper-V をインストールする](https://qiita.com/bitterrich/items/899c751eb7e79ebdbaca) を参照ください。

## 本手順の注意点
画面ショットは chrome を使用してます。
2020年4月の時点の画面になります。


# Windows Server 2019 180日評価版ダウンロード手順

https://www.microsoft.com/ja-jp/evalcenter/

Windows Server をクリック
※画面の一部を削っているため、下にスクロールすると Windows Server が出てきます。

![OSDownload_000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/072eb39c-3a96-6007-8a58-f0759df7b978.png)

## 02. Windows Server 2019 をクリック

![OSDownload_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/c108133c-5ecf-ce98-94a6-9039feeb6584.png)

## 03. 評価ファイルのタイプで「ISO」を選択して次へ

![OSDownload_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/1ef86530-789d-0eae-1dfe-657dcf519eb9.png)

ちなみに、下へスクロールすると、Windows Server 2016 や 2012 R2 もダウンロード可能。

![OSDownload_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/dafc274a-f27f-f58c-f1ac-673eacd451f9.png)

## 04. フォームに必要事項を入力して次へ

![OSDownload_004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/e0ddffe3-cb37-203a-b8c1-64a092b2abd7.png)

## 05. 言語に日本語を選択してダウンロードをクリック

![OSDownload_005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/fc709b85-44d4-221b-786d-aac755e37c04.png)

## 06. 適切な場所に iso ファイルを保存

![OSDownload_006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/770a52e2-59dc-4f79-8ee7-76a5c7b60558.png)


# Windows 10 Enterprise 90日評価版ダウンロード手順

## 01. ブラウザを起動して以下のアドレスを入力してダウンロードサイトに移動

https://www.microsoft.com/ja-jp/evalcenter/

Windows をクリック

![OSDownload_007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/922d5f26-c440-613d-92d4-4e40d8515e7c.png)

## 02. Windows 10 Enterprise をクリック

![OSDownload_008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/339e3b1f-c647-f7d2-c95a-8415a0d3b341.png)

## 03. 評価ファイルのタイプで「ISO - Enterprise」を選択して次へ

![OSDownload_009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/836f3ee5-53f7-7f1b-5802-94e2bcd1fdc9.png)

## 04. フォームに必要事項を入力して次へ

![OSDownload_010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/8c029f33-1777-ddbc-fc52-e5ba5a43f071.png)

## 05. プラットフォームで64ビット、言語で日本語を選択してダウンロードをクリック

![OSDownload_011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/f4210e48-1dff-86a4-eb93-8f516b42f9e8.png)

## 06. 適切な場所に iso ファイルを保存

![OSDownload_012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617437/32f1e0bb-6b1d-4fcd-eaf4-c66165379b85.png)
[Ruby on rails]7つのアクション以外のアクションの設定

# はじめに
フリマアプリのチーム開発をしている時のメンバーからの質問で、『商品購入完了のページを作成しているが、編集（edit）や削除（destroy）は分かるが購入完了はどういうアクションを使ったら良いかわからない』というのがあったので調べたことを備忘録として残しておきます。
# 結論
まずその時にとった選択として、**任意のアクションを作る**ということにしました。
今回の場合には完了（done)とさせていただきました。
（正しくは購入完了ですのでPurchase completedなんですが・・・）
ということで無事解決！！
という訳には行きません。
**今回の論点は基本の７つのアクション以外のアクションを追加した時の対応です。**
# 7つのアクションとは
７つのアクションとは、railsで定義されているメソッドのことで以下のものを言います。

| アクション   | 役割　 　　　　　| 
|:-----------|------------:|
| index      |一覧を表示する　　　　　|
| show       |詳細を表示する　　　　　|
| new        |投稿フォームを表示する　| 
| create     |リソースを追加する　　　| 
| edit   　　|更新フォームを表示する　| 
| update　　　|リソースを更新する　　　|
| destroy　　|リソースを削除する　　　|

これらをroutes.rbに設定するときはresourcesのメソッドを使用するかと思います。

```:routes.rb(例）
Rails.application.routes.draw do
  resources :items
end
```
７つのアクションはそれぞれに与えられた役割があるので機能を追加したときはまずはこの７つのアクションのうちどれにあてはまるかを考えます。
# ７つのアクション以外のアクションの場合
上記のresoucesメソッドで7つのアクションを自動で定義できますが、今回のように７つのアクション以外のアクション（done)を追加する場合はどうしたら良いでしょうか？
## ・collectionとmember
7つの基本アクション以外でルーティングを定義する時には、collectionかmemberを利用します。
collectionはルーティングに:idがつかない、memberは:idがつく。という違いがあります。
今回の購入完了(done)は特にidを指定する必要のない単なる通知のページの作成となりますのでcollectionを使用します。

今回の実装では商品購入に関わるordersコントローラーにアクションを追加しました。

```:orders_controller.rb
class OrdersController < ApplicationController

  def show
      省略
　 end

  def create
      省略
　　　redirect_to action: :done　⬅️　購入が完了したらdoneに移動してもらう
  end
 
  def done　⬅️　今回追加されたアクション

  end

 
end
```
続けてルーティング

```:routes.rb
resources :orders, only: [:show, :create] do
   collection do ⬅️　今回はcollectionを使用（idは不要）
    get 'done'
   end
end
```
あとはdoneのhtmlとcssを作成して購入完了ページを作成する！！

[![Screenshot from Gyazo](https://gyazo.com/9fdf103684ea756e03b107c3bd7abe8f/raw)](https://gyazo.com/9fdf103684ea756e03b107c3bd7abe8f)

これで完成！！

参考にした記事：https://pikawaka.com/rails/resources#member%E3%81%A8collection

# 最後に
スクールでのチーム開発の期間もあと僅かとなりました。
これまで一緒に学んできた仲間たちへの感謝の気持ちを込めて、些細なことでも記録に留めておきたいと思います。
ここまでご覧いただきましてありがとうございました。
CodeBuildで使えるopenJDK13対応のカスタムイメージを作成してECRにPUSHする

# はじめに
現状はCodeBuildの標準イメージではopenJDK13をサポートしていない様子。
そのためopenJDK13対応のカスタムイメージを作成しCodeBuildでビルドに利用出来るようにしてみました。

作成したイメージはCodebuildで参照するためECRにPUSHします。

# 前提条件＆注意点
+ 今回openjdk13が***testingリポジトリ***でしか公開されていないため利用しています。ご注意ください。
+ aws cliのバージョンが古いと`get-login-password`が使えずエラーになる可能性があります。
+ ECRリポジトリの事前に作成しておいてください。
+ 既にdockerイメージがbuild出来る環境がある想定です。
+ 利用する環境はECRへのアクセス権限を持つ必要があります。

参考：[Amazon Elastic Container Registry アイデンティティベースのポリシーの例](https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/security_iam_id-based-policy-examples.html)

# Dockerfile作成
今回は`docker:dind`ベースで作成していきます。`alpine`ベースなのでapkで必要なコマンド等を追加していきます。
少し汎用性も考慮して最終的には以下のようになりました。

`tzdata`はCodeBuildでビルドログを見る際に時刻を合わせるために入れています。
前述のように以下、testingのリポジトリを指定してopenjdk13をaddしています。

```dockerfile
FROM docker:dind

RUN apk update \
    && apk --no-cache add tzdata \
    && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
    && apk del tzdata \
    && apk --no-cache add curl git maven py-pip python\
    && apk --no-cache add openjdk13 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing \
    && pip install awscli \
    && apk del --purge py-pip
```

# ベースのDockerイメージをビルド＆ECRにpush
ECRにイメージをPUSHするので、先にAWSマネジメントコンソールより対象のECRリポジトリを開き「プッシュコマンドの表示」を確認しておきます。

***ECRの認証トークンを取得して、PUSH準備***

```shell
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [AWSアカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/[ECRリポジトリ名]
```

***dockerイメージをbuild***

```shell
docker build -t [AWSアカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/[ECRリポジトリ名]:[イメージタグ] .
```

***ECRにイメージをPUSH***

```shell
docker push [AWSアカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/[ECRリポジトリ名]:[イメージタグ]
```

# 確認＆CodeBuildで動かす際のサンプル
ECRにイメージがPUSHされていることを確認したら完了です。
CodeBuildで使う場合の`buildspec.yml`サンプルを下記を記載します。

alpineベースの場合`timeout`に`-t`オプションを付けるとAWS公式ドキュメントに書いてありますが、
作成したイメージをrunして試したところ`-t`オプションがあるとエラーになるため外しました。

***buildspec.yml***

```yaml
version: 0.2

phases:
  install:
    commands:
    - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&
    - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
  pre_build:
    commands:
　　～以下省略～
```

# ローカルで動かす際の注意点
作成したDockerImageをローカルで動作確認する際は`privileged: true`にしないと動作しないので注意。
自分はdocker-compose.ymlに下記のように書いて`docker-compose up`で確認しています。
（Dockerimageはdocker-dind-testでbuild済み）

```yaml
version: '2'

services:
  docker-dind:
    image: docker-dind-test:latest
    privileged: true
```
Capistranoでのデプロイ時エラーで再確認すべき事

## capistranoでデプロイするときにエラーが出てしまった時の確認事項まとめ

- ローカル側（localhost3000）においてエラーが出ていないか

- サーバー側で、/var/www/<レポジトリ名>/current/log/unicorn.stderr.logをlessまたはcatコマンドで確認しエラーが出ていないか確認する（下に行くほど最新のログです。時刻表記がUTCであることに注意してください）


- ローカルでの編集の`push`や`pull`を忘れていないか
サーバー側の`mysql`や`nginx`の再起動を行ってみる
EC2インスタンスの再起動を行ってみる(※本番環境にてmysqlとnginxの起動も必要です。)

- `unicorn`のプロセスを`kill`しているか

- `github`が起動しているか、連携できているか

- エラー文をググる
非力なサーバーでRailsのasset:precompileがCompiling...でフリーズする

## 概要

表題の通りですが、アセットパイプラインとwebpackを併用したアプリの`bundle exec assets:precompile`を開発用の非力な仮想サーバーですると`Compiling...`で固まってしまいます。

## 解決策

`Compiling...`はwebpackのコンパイルをしているようです。最初時間がかかってSSHがタイムアウトしてるだけかと思ってタイムアウトしないようにしてみてしばらく放置してみたら`Compilation failed!`と悲しいメッセージが。

不思議なのは`bin/webpack`でコンパイルすると1，2分で終わります。そこで、assets:precompile時にwebpackをやらないようにして`bin/webpack`を別途呼んでみるようにしたら失敗しなくなりました。

```
WEBPACKER_PRECOMPILE=false bundle exec rails assets:precompile
bin/webpack
```

`WEBPACKER_PRECOMPILE=false`の環境変数でwebpackをしなくなります。根本的な解決ではないし、なんか気持ち悪いですが困ってる方いらっしゃましたら試してみてください。

想像ですが1プロセス内でアセットパイプラインのプリコンパイルとwebpackが走るとメモリが足りなくなるとかですかね？rails6で作ったアプリはwebpack一本になるのでこう言う心配はなくなるのかな？上記の対象アプリも6にアップグレードはしましたが、歴史的経緯でアセットパイプラインとwebpackが併用になっています。
「子猫」と「自然」の写真がChromeCastに流れてたら最高じゃん

[子猫の写真を見るとGood!](https://www.hiroshima-u.ac.jp/souka/news/21752)で、[自然の写真を見るとGood!](https://wired.jp/2010/08/25/%e3%80%8c%e8%87%aa%e7%84%b6%e3%81%aa%e6%99%af%e8%a6%b3%e3%80%8d%e3%81%8c%e4%ba%ba%e3%81%ab%e4%b8%8e%e3%81%88%e3%82%8b%e5%bd%b1%e9%9f%bf/)だという話を聞きました。

じゃぁ子猫と自然の写真をChromeCastでスライドショーに使おう！
リラックス効果を得て生産性を上げるぜ！ってので思い立ちました。
パブリックドメインの写真のみ。著作権的には問題ないはず。。。

アルバムのリンクはこちら。
https://photos.app.goo.gl/2nAfWDCtyhHuLR1CA

ChromeCastの設定方法はこちら。
https://support.google.com/chromecast/answer/6080931?hl=ja

## 追加歓迎！よろしくお願いします！
テーマに合うパブリックドメインの写真が増えるといいなぁ。
以下みたいな感じで検索するといいのが見つかりそう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447423/f0b6b81a-f6cf-e62b-63ee-20f5f2a5918c.png)
MY SQLでrails db:migrateが反映されない時

## MY SQLでrails db:migrateが反映されない時

スクールでのチーム開発中にブランチ切ってマイグレーションファイルを編集したが、SQL上に変更内容が反映されないという事態が発生。

## rails db:migrateしても。。
DB上にカラムがないので

```:ターミナル
$ rails s
```
でサーバー立ち上げてもエラーが出てしまう。

## 最終的な解決方法

チーム開発であまりおすすめできない強引なやり方ですが

```:ターミナル
$ ./bin/rails db:migrate:reset
```

これで一旦DBの情報をリセットして再び

```:ターミナル
$ rails db:migrate
```

するとマイグレーションファイルからの情報が読み込まれて正常にカラムが認識されました。


結局このあと本番環境にデプロイする際にエラーが出てしまったのでこれから解決していきます。頑張ろう。。。
営業メールを自動化 | JavaScriptでGmailを定期送信 | 無料でスプレッドシートのメアドに対してメールを送ろう！ #StayHomeWithMe #家で一緒にやってみよう 🏠

一件一件メールを送るのが面倒、いや、もはやGmailを開くのすら面倒！
そんな方に必見！　定期配信のメルマガ機能を簡単に作り、スプレッドシートで送信まで全て管理ことができます。コロナで家にいる時が多い方に[ちょうど良い動画](https://youtu.be/8_VPGlJvxnE)にしているので、ぜひご覧ください。

動画：https://youtu.be/8_VPGlJvxnE

[![マイムービー-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216701/56ef5dea-7d10-07b9-e279-12a0e32c4b17.gif)](https://youtu.be/8_VPGlJvxnE)


```コード.js
function email(){
  let opt          = new Object();
  let name         = "";
  let emailAddress = "";
  let times        = "";
  let message      = "";

  const MES_SHEET = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("メール本文");
  const MES_DATA  = MES_SHEET.getRange(1, 1, 2, 2).getValues();
  const mailTitle = MES_DATA[0][0];
  const mailMes   = MES_DATA[1][0];

  // スプレットシートからデータを引き出す
  const SHEET_1   = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("フォームの回答 1");
  const numColumn = SHEET_1.getLastColumn(); // 最後列の列番号を取得
  const numRow    = SHEET_1.getLastRow()-1;  // 最後行の行番号を取得
  const dataRange = SHEET_1.getRange(2, 1, numRow, numColumn);
  let data        = dataRange.getValues();

  // 一人一人、情報を見ていく処理
  for(i in data){
    name         = data[i][0];
    emailAddress = data[i][1];
    times        = data[i][2];
    
    message = `${name}様<br><br>${mailMes}`; // 本文
    message = message.replace(/\n/g, "<br>"); // スプレッドシートから取ってくる改行は\nでメールで使えないので、<br>に変更
    opt.htmlBody = message; // optに本文を格納（改行とかしたいため）
    // メール送信処理（まだ一度もメールを送っていなければ送信）
    if(!times){
      MailApp.sendEmail(emailAddress, mailTitle, "", opt);
      data[i][2] = times + 1;
    }
  }
  dataRange.setValues(data);
}
```

```menu.js
function onOpen() {
  const UI = SpreadsheetApp.getUi();
  let menu = UI.createMenu('メール送信');
  menu.addItem('新規顧客', 'email');
  menu.addToUi();
}
```
VSCode で $もダブルクリックで選択したい（PHPとか）

# 概要

PHPの変数はプレフィックスに `$`が付きます。
VSCodeは標準で単語区切りの認識 `$` が含まれてしまっているため、PHPプログラマがVSCodeで変数名にカーソルを合わせてダブルクリックで選択すると、 `$` が選択範囲に含まれず、コピペの際などに `$` を追加で入力したり、選択範囲を一文字増やしたりなど一手間がかかってしまいます。
そこで、単語区切りのルールを設定変更して、 `$` をダブルクリックで選択できるようにします。

# やりかた

`Cmd + Shift + P` から設定画面を開きます `Preference（UI）` とかです。
開いた設定画面から、 `wordSeparators` を探します。そして `$` を消します。


```
"editor.wordSeparators": "`~!@#%^&*()-=+[{]}\\|;:'\",.<>/?"
```

ただ、上記のやり方だとすべてに適用されてしまって不都合がある人もいるかも知れません。ですので、PHPだけに適用したかったら、jsonで開いて下記のように設定したほうがいいです。

```
"[php]": {
    "editor.wordSeparators": "`~!@#%^&*()-=+[{]}\\|;:'\",.<>/?"
  },
```


# 参考

https://www.igorkromin.net/index.php/2018/04/12/make-visual-studio-code-to-correctly-select-php-variables-on-double-click/
firebaseでexpress-generatorの起動方法

#1
下記のURLで設定
https://qiita.com/yoshikoba/items/ff7beab24863db804f42

この通りに設定してもエラーが出ました。

#2

package.jsonに

```javascript
"engines": {
    "node": "8"
  },
```
を追加。


#3

functionディレクトリ内で

```shell
npm install firebase-admin
npm install firebase-functions
```

#4
firebase serveで localhost:5000を開けば
<img width="704" alt="スクリーンショット 2020-04-12 16.41.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558434/eec6a747-ba78-8d9d-2262-b5035ba8bd5c.png">

表示されます。
【pandas】set_optionとは【使い方】



Python pandasライブラリのset_optionってなんだっけと思って、
調べてもすぐわからなかったので、アウトプットしておきます。

[pandas documentation](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.set_option.html) を参照すると、

>pandas.set_option(pat, value) 
Sets the value of the specified option.

文字通り**値に特定のオプションをつけること**のようです。
さらに、以下のように第一引数が正規表現をとる。

>Parameters: 
**pat : str**
Regexp which should match a single option. Note: partial matches are supported for convenience, but unless you use the full option name (e.g. x.y.z.option_name), your code may break in future versions if new options with similar names are introduced.
**value : object**
New value of option.


出来るオプションはたくさんあるので、
詳しくは公式ドキュメントをご参照ください。

ここではいくつかの使い方を実行したいと思います。

以下、Jupyter notebookでの使用例

**小数点X桁以下を表示させない**
例: データフレームの出力を小数点3以下に抑えたい場合

```python:qiita.py
pd.set_option('display.precision',3)
# 小数点以下3以下を表示させないように設定
# display. は省略しても問題なかった

test = pd.DataFrame({'test':[5,7,9]})
# とりあえず、5,7,9のデータを用意

print(test/3)
#このデータを3で割る

```
出力結果(3桁で以下は表示されない)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266200/399e2225-bb24-3f32-bd7b-e13b0dbcfa89.png)


**表示行数を変更する(自動的に非表示にならないようにする)**
Jupyterなどでは以下のように自動的に行が一部非表示になっていまいます。
※ 10を100個格納したデータを作りました。

```python:qiita.py
test = pd.DataFrame({'test':[10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10,
                             10,10,10,10,10,10,10,10,10,10]})

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266200/4dc865d6-2f23-6ed0-a8d6-54edf0f4eef1.png)

そこで、指定の行数を表示させようと思います。
ここでは、100行のデータを表示させたいです。
したがって、"max_rows"オプションをつけます。
(当然、列オプションもあります。)

```python:qiita.py
pd.set_option("max_rows",100)
```
結果、表示されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266200/fdba4c8d-610b-81cb-34bb-35a7fec00db6.png)

※ 16以降も表示されていますが、全部張り付けると長いので省略します。


以上です。データを表示させたいときに色々試したいですね。



##参照リンク
[pandas documentation](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.set_option.html)



[pandasでよく使う文法まとめ](https://qiita.com/okadate/items/7b9620a5e64b4e906c42)

## P.S ブログとTwitterやってます
2020年4月からqiitaと[Twitter]("https://twitter.com/S3PO3g5UcZKpr7h")と[ブログ]("https://blackswanstat.com/")をはじめました
仲良くしてください
Rubocop、Sider

Rubocopとは
https://gyazo.com/a5b4c9ff6451feace4ee808b0060114c
https://gyazo.com/94e264782d30556dd12f3c1fc6408316
導入方法
https://gyazo.com/092d5475b41d88afcf11fc0ea759b564
参考資料
https://rubocop.readthedocs.io/en/latest/
https://eslint.org/


Siderとは
https://gyazo.com/2eb7328256c7186552f04e03a6005a54
導入方法
https://gyazo.com/b2b1864f50d5cbddee264d7fd6e1c5a9
参考資料
https://blog-ja.sideci.com/archive/category/Ruby%20on%20Rails