OmniAICreator/Qiita-1.07M huggingface dataset:
GitHub Actions で Android アプリのリリース署名をする


リリース用の証明書やそれらのパスワード類は、Git リポジトリにコミットすべきではないので、 GitHub Actions のワークフロー上でこれらを用意して署名するようにします。

まずは、アプリのビルド時に自動的に署名がされるような設定を `app/build.gradle` に記述します。

```gradle:app/build.gradle
// ...

signingConfigs {
    debug {
        // デバッグ用の証明書はリポジトリににコミットしてしまってもよいと思います。
        // 今回はプロジェクトのルートに debug.keystore が配置されているものとします。
        // 尚、Android Studio でデフォルトで用意される証明書であれば、パスワード類の記載は必要ありません。
        storeFile rootProject.file('debug.keystore')
    }
    release {
        // GitHub Actions のワークフローで、プロジェクトのルートに release.keystore が配置され、
        // パスワード類は環境変数へ設定される想定です。
        storeFile rootProject.file('release.keystore')
        storePassword System.getenv('KEYSTORE_PASSWORD')
        keyAlias System.getenv('KEY_ALIAS')
        keyPassword System.getenv('KEY_PASSWORD')
    }
}
buildTypes {
    debug {
        signingConfig signingConfigs.debug
        // ...
    }
    release {
        // 今回は、署名なしの release ビルドも可能とする為に判定処理をいれています。
        if (rootProject.file('release.keystore').exists()) {
            signingConfig signingConfigs.release
        }
        // ...
    }
}

// ...
```

証明書やパスワード類は、リポジトリの Secrets に設定しておきます。

<img width="600" alt="スクリーンショット 2020-06-19 21.16.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35733/f0499954-915b-545e-e4f9-8ece3fbd0abc.png">

証明書は上図の `KEYSTORE_BASE64` です。次のように実際の証明書を Base64 エンコードした文字列を設定します。他の項目はそのまま文字列として設定できると思います。

```shell
$ cat release.keystore | base64
```

ここまでで事前の準備は完了です。GitHub Actions のワークフローで次のようにビルドすれば、リリース署名することが出来ます。

```yaml
build:
  name: Build
  runs-on: ubuntu-18.04
  steps:
    - name: Check out
      uses: actions/checkout@v2
    - name: Set up JDK
      uses: actions/setup-java@v1
      with:
        java-version: 1.8
    - name: Build with Gradle
      run: |
        # 今回は、Secrets が設定されいなければ署名なしのapkファイルが作成されるよう判定処理をいれています。
        # 確実に署名させたいのであれば、判定処理を外すことで署名エラーとしてしまってもよいと思います。
        if [[ -n "${{ secrets.KEYSTORE_BASE64 }}" ]]; then
          echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore
          export KEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}"
          export KEY_ALIAS="${{ secrets.KEY_ALIAS }}"
          export KEY_PASSWORD="${{ secrets.KEY_PASSWORD }}"
        fi
        ./gradlew assembleRelease
    - name: Get apk path
      id: apk-path
      run: |
        path=$(find **/build/outputs/apk -name '*.apk' -type f | head -1)
        echo "::set-output name=path::$path"
    # 今回は artifact へ apk ファイルをアップロードし、ワークフローの結果画面がらダウンロードできるようにします。
    - name: Upload apk file
      uses: actions/upload-artifact@v1
      with:
        name: apk
        path: ${{ steps.apk-path.outputs.path }}
```

注意： secrets を bash で扱う場合、シングルクォートだと文字によってはエラー（例えば `<`など）になってしまうので、ダブルクォートを利用しています。
【AWS RDS】Unable to create a snapshot as the database instance is not in available stateの意味

#エラー発生
RDSの作成中に「Unable to create a snapshot as the database instance is not in available state」のエラーが出た。

#エラーの意味
調べてみると下記の英語のサイトに意味が載っていた。
https://docs.druva.com/Knowledge_Base/Druva_CloudRanger/Troubleshooting/Unable_to_create_a_snapshot_as_the_database_instance_is_not_in_available_state
サイトの内容は以下の通り。

<h2>エラーの説明</h2>
エラーによりRDSのバックアップに失敗した。

"Unable to create a snapshot as the database instance is not in available state."
「DBインスタンスが利用可能状況ではないため、スナップショットを作ることができなかった。」ということだ。

<h2>原因</h2>
AWSの制限

<h2>解決方法</h2>
RDSインスタンスを起動して、バックアップを起こしなさい。

#今回の原因
RDSを作成したばかりで、まだ準備が整っておらずエラーが発生した。RDSの状態をチェックすると実行中になっていた。その後時間をおいて、もう一度スナップショットを作成したら無事作られた。
DX化を行う上でキーパーソンとなるエンプロイーサクセスマネージャーについて

#はじめに

　製造業非ＩＴ部門で働いている私ですが、日常的にDX（デジタルトランスフォーメーション）に関する話題に触れることが多くなりました。
　
　企業をDX化していくことについて下記で学んでおりますので、備忘でまとめていきます。マイクロソフト社の方の講義となっています。

　LinkedInに登録されている方は無料で閲覧できるかと思います。

+ [チェンジマネジメントで働き方のデジタルトランスフォーメーションを推進する](https://www.linkedin.com/learning/leading-digital-transformation-for-work-style-reform-with-change-management/2292211)

項目は下記です。

+ DX化とは
+ エンプロイーサクセスマネジャーとは


##DX化とは

　この記事を御覧頂いている方に説明する必要はないかもしれませんが、私なりの理解が下記です。

　DX(デジタルトランスフォーメーション)とは、**事業への影響力が大きいテクノロジーを活用して企業を変革することで利益を上げていくこと、**と理解しています。

 よく外資系のコンサルティングファームの資料では、「破壊的な影響をもたらす」技術等強い言葉を使っていますが、どうもしっくりこないと思っています。
　DX化を推進したいコンサル業界のポジショントークと感じてしまう面があるためです。前向きにとらえると、私自身がAIやデジタル技術のすばらしさに全て気づけていないだけなのかもしれませんが。。





##エンプロイーサクセスマネジャーとは

　DX化をしたい企業において、DX化を推進する役割の社員をエンプロイーサクセスマネジャー(ESM)と位置づけています。

　基本的には情報システム部門の方が任命される（＝業務としてアサインされる）のでしょう。

　このESMに求められる役割は下記です。

1. 働き方改革のDXのゴールとなるビジョンを定める
2. 現状を把握し、理想とギャップを埋めるための現実的なプランを作成する
3. チーム・スポンサー・組織を巻き込みながら「理想の働き方」（1.で定めたもの）の実現に向けて実行

具体的な図にすると下記になります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567823/b38c558c-cde4-45c3-bb98-15c001597e1b.png)

BIツールを活用していきたいというニーズで例を書きました。
　
基本的にはESMが実際に使用していく部門の社員へ働きかけていく必要があります。この時のポイントとしては、後述にもなりますが、組織をより良くして生きたいという思いが大事だと感じます。

　結局、導入はできたものの業務改善というフェーズに達するまでが一番苦労するところと思います。そこは、ESMというよりも各部門の方が知恵を出して活用方法を模索するフェーズであるからです。
　いかに各部門で活用しようとする人々へ働きかけ続けているかがESMの役割になります。

次に、ESMが役割を果たすために必要な要素が下記です。

1. チェンジマネジメントのフレームワークとノウハウを活用
2. クラウドツールの使い方と事例の把握
3. 組織をより良くしたいという情熱


チェンジマネジメントについては、先ほどの１～３．の役割を進めることを意味します。

最後の３つ目のより良くしたいという情熱についてですが、結局は気合論が挙げられています。

　これは、ESMが情報システム部門で営業、製造、経理部門へ働きかけることをイメージすると分かりやすいのですが、DX化による業務プロセスを変えたい部門が変わらないといけないため、そう働きかける思いが重要であることを示しています。


#終わりに

　DX化のためには素晴らしいＢＩツールやＩＣＴ技術だけでなく、使いこなして業務改善したいというマインドセットがまずは大事であることを確認できました。
【Rails】ancestryを用いた多階層カテゴリー機能の実装『seed編』

# 開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

# 前提

下記実装済み。

・[投稿機能実装](https://qiita.com/matsubishi5/items/1a5aeab651b5822d1f2c)
・[多対多のカテゴリー機能実装](https://qiita.com/matsubishi5/items/a805fbcfd96f768dd622)
・[多階層カテゴリー機能実装(準備編)](https://qiita.com/matsubishi5/items/77aadc97a2e63c98cd91)

# 実装

|id|name|ancestry|
|---|---|---|
|1|**ビジネス**|nil|
|2|**金融**|1|
|3|株|1/2|
|4|為替|1/2|
|5|税金|1/2|
|6|**経済**|2|
|7|日本経済|1/6|
|8|国際経済|1/6|
|9|**経営**|3|
|10|経営学|1/9|
|11|戦略・攻略|1/9|
|12|企業・開業|1/9|
|13|**マーケティング**|4|
|14|経営学|1/13|
|15|戦略・攻略|1/13|
|16|企業・開業|1/13|

本のカテゴリーに上記の様な親子関係を持たせたい場合は、以下の様にデータを作成します。

```ruby:seed.rb
business = Category.create(name: 'ビジネス')
business_children_array = ['金融', '経済', '経営', 'マーケティング']
business_grandchildren_array = [
  ['株', '為替', '税金'], # 金融の子
  ['日本経済', '国際経済'], # 経済の子
  ['経営学', '戦略・管理', '起業・開業'], # 経営の子
  ['広告', '営業', '開発'] # マーケティングの子
]

business_children_array.each_with_index do |children, index|
  children = business.children.create(name: children)
  business_grandchildren_array[index].each do |grandchildren|
    children.children.create(name: grandchildren)
  end
end
```

# 続編

[多階層カテゴリー機能実装(作成フォーム編)](https://qiita.com/matsubishi5/items/4afb4a4f307023126c66)
Leaflet.EditableでgeoJSONを扱う場合の注意

`Leaflet.Editable`を使用して描画した図形を、`geoJson`として保存したが、保存した`geoJson`を`Leaflet.Editable`に取り込む時に引っかかった点があるためまとめる。

保存した`geoJson`は以下のようなものとする。

```json
{
    "type": "Feature",
    "properties": {},
    "geometry": {
        "type": "Polygon",
        "coordinates": [
            [
                [
                    139.761372,
                    35.694623
                ],
                [
                    139.743776,
                    35.694623
                ],
                [
                    139.743776,
                    35.677239
                ],
                [
                    139.761372,
                    35.677239
                ],
                [
                    139.761372,
                    35.694623
                ]
            ]
        ]
    }
}
```
## 失敗例

`geoJson`のgeometry typeが`polygon`のため、leaflet側では`L.polygon`として扱おうと思ったが、`geoJson`のフォーマットと、leafletの各種図形の型は緯度・経度のペアの順序が違うため、単純に読み込めない。

```javascript
// オブジェクトの作成はできるが、座標がおかしくなる
var polygon = L.polygon(geoJsonData.geometry.coordinates);
```
これを解決するには、自前で全ての座標に対して緯度・経度の順序を反転させる必要がある。

参考 : https://gis.stackexchange.com/questions/234460/how-to-convert-geojson-to-polygon-in-leaflet

## 成功例
leafletは`geoJson`フォーマット自体の入出力には対応しているため、`geoJson`オブジェクトとして読み込めば正しく扱うことはできる。

```javascript
// 正常
var geoJsonLayer = L.geoJSON(geoJsonData);
```

調べた所、`Leaflet.Editable`は`geoJson`レイヤーの編集には対応しており、各レイヤーに対して`enableEdit`メソッドを呼び出せば編集可能に設定ができる。

leafletの地図を描画し、`geoJson`データを読み込んで編集可能とするサンプルは以下の通り。

```javascript
// 地図を表示
var map = L.map("map", {editable: true}).setView([38.258595, 137.6850225], 5);
var tileLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution: "&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors"
});
map.addLayer(tileLayer);

// geoJsonレイヤーを作成
var geoJsonLayer = L.geoJSON(geoJsonData, {
    onEachFeature: function(feature, layer){
        layer
        .on("dblclick", L.DomEvent.stop)
        .on("dblclick", layer.toggleEdit);
    }
});
// 先に地図へ追加する
geoJsonLayer.addTo(map);
// レイヤーを編集可能に設定
geoJsonLayer.getLayers().forEach(l => l.enableEdit());
```

`leaflet 1.6.0`と`Leaflet.Editable 1.2.0`の組み合わせでは、`enableEdit`メソッドを呼び出す前にレイヤーが地図に追加されていないとエラーが発生するため、`geoJsonLayer.addTo(map);`を先に実行している。

参考 : https://github.com/Leaflet/Leaflet.Editable/issues/163
Linuxのプロンプトの色を変える

 
#~/.bashrcに以下の記述を加える。

```~/.bashrc
PS1='\[\e[1;32m\][\u@\h \w]\\\$ \[\e[m\]'
```

プロンプトの表示は次のようになる。
![as.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552559/5989c005-e104-6512-339c-fdf5b16fbd35.png)
既読・未読判定機能の実装

# 既読・未読機能の実装方法
まず、簡単なブログ機能のあるrailsアプリがあるとします。
このアプリのブログ詳細画面に遷移した際に、既読となるような仕様で実装していきたいと思います。
※既読/未読機能を実装するために必要なコードのみ載せています。

## ER図
![9E62416E-211A-4FC1-B849-AE2B019E9D50_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613801/b738bbc2-69ef-ec4f-12d2-31915bf49232.jpeg)

### テーブル

- user
- blog
- read

既読機能を実装するにあたって、userテーブルとblogテーブルの中間テーブルが必要になります。
そこで、readテーブルを作成しました。

### readテーブルのカラム

- user_id
- blog_id
- complete(boolean型)

completeカラムをboolean型とし、既読/未読を真偽値で取得するようにしました。

## モデル

```ruby:user.rb
class User < ApplicationRecord
  has_many :blogs
  has_many :reads, dependent: :destroy
end
```

```ruby:blog.rb
class Blog < ApplicationRecord
  belongs_to :user
  has_many :reads, dependent: :destroy
end

```

```ruby:read.rb
class Read < ApplicationRecord
  belongs_to :user
  belongs_to :blog
end
```

## コントローラーの設定

```ruby:blogs_controller
class BlogsController < ApplicationController

  def show
    if Read.create(blog_id: @blog.id, user_id: current_user.id) 
      @read = Read.update(complete: true)
    end
  end
```

showメソッドに、「ブログ詳細画面に飛んだら、現在ログインしているユーザーidとブログidが取得された、readメソッドが作成される。readメソッドが作成されたら、ブログが既読の状態にアップデートされる。」という記述をし、@readに格納します。
complete: true = '既読'

## ビューの設定

```ruby:show.html.erb
<%= @read ? '既読' : '未読' %>
```

「@read ? '既読' : '未読'」 は、`三項演算子`という記法で、「?」の前の記述（@read）が、
true(真)であれば:の左側の処理を実行('既読'という文字列の出力を実行)し、
false（偽）であれば:の右側の処理を実行('未読'という文字列の出力を実行)します。

以上のようにコードを記述してくと、ブログ詳細画面に遷移した際に
![4FE0EDBE-6683-41E2-AE32-FB10EF2D5D40_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613801/7adfe1b3-6222-4921-e5b8-002ecb3f42ea.jpeg)

このように「既読」という文字列を出力できるようになります。
型 'EventToReactiveCommand' の値は、型 'TriggerActionCollection' のコレクションまたは辞書に追加できません。

エラーメッセージ

```
型 'EventToReactiveCommand' の値は、型 'TriggerActionCollection' のコレクションまたは辞書に追加できません。
```

への対処。
```System.Windows.Window.Interactivity```ではなく```Microsoft.Xaml.Behaviors.Wpf```を使いましょう。

理由はこの辺みたいです。

[WPF のビヘイビアーが入ってる Blend SDK for Visual Studio が Visual Studio 2019 で消えた件について](https://blog.okazuki.jp/entry/2019/03/02/221827)


##EventToReactiveCommandを使おうとしたけど例外！！


[MVVM でイベント引数の値を ViewModel のコマンドに渡す方法](https://blog.okazuki.jp/entry/2019/04/19/172010)を参考にやってみたらタイトルの例外で落ちてしまいました。

検索してみたら冒頭の情報とTwitterに辿り着きossの方のInteractivityを使うようにしたらすっと動きました。
地味に時間かかって悔しい。


具体的にはこんな感じです。

```XML
<Window x:Class="TestEventToReactiveCommand.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"

        xmlns:behaviours="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"
        
        xmlns:local="clr-namespace:TestEventToReactiveCommand"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">

    <behaviours:Interaction.Triggers>
        <behaviours:EventTrigger EventName="MouseMove">
            <interactivity:EventToReactiveCommand Command="{Binding MouseMoveCommand}">
                <local:MouseMoveToMousePositionConverter />
            </interactivity:EventToReactiveCommand>
        </behaviours:EventTrigger>
    </behaviours:Interaction.Triggers>

    <Grid>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        <TextBlock
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Text="{Binding Message.Value}" />
    </Grid>
</Window>

```

なんか私の場合はNugetで Microsoft.Xaml.Behaviors.Wpf を追加しないでも動いてますが、
[ここ](https://github.com/microsoft/XamlBehaviorsWpf)によれば追加しろと書いてある？？

ざっと動かしただけですが確認したソース
[TestEventToReactiveCommand](https://github.com/satorimon/TestEventToReactiveCommand)
【JQuery】This request has been blocked; the content must be served over HTTPS.と表示される。

##事象について
グラフを描画するために、以下JQueryを読み込む処理を記載した。

```application.html.erb
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
<script type="text/javascript" src="http://techanjs.org/techan.min.js"></script>
```

すると・・・「techan.min.js」が読み込まれない。エラーを確認してみると

```
The page at 'https://74f8d60….vfs.cloud9.us-east-2.amazonaws.com/' was loaded over HTTPS, 
but requested an insecure script 'http://techanjs.org/techan.min.js'. 
This request has been blocked; the content must be served over HTTPS.
```
「このコンテンツはhttpのため、ブロックします。httpsにしてください」とのこと。

##実施したこと

httpsに変更してみると・・・表示されない。元々httpsには対応してないみたいだ。
検索すると、httpsを省略しても読み込むことができるとのことなので、試してみる・・・。

```
<script type="text/javascript" src="//techanjs.org/techan.min.js"></script>
```

がっ・・・だめ・・・！コンテンツがhttpしかない場合、どうやってもブロックされるみたいだ。

##対処法

普通にJQueryをダウンロードして、ファイルを「app/assets/javascripts」にぶち込んだら動いた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594264/b480f62b-550c-4d5d-ee3c-64c1b7f1dc6f.png)
Elasticsearch(5.4.2)でシャードがunassignedのまま修正されない場合


何かの理由でunassignedがでて原因を除いにもかかわらずunassignedが出続ける場合

```
# curl -XPOST 'http://xxx.xxx.xxx.xxx:9200/_cluster/reroute' -d '{
  "commands": [{
    "allocate_replica": {
      "index": "xxxxxxxxxxxxxxx",
      "shard": 3,
      "node": "IP123.456.789.012"
    }
  }]
}'
```

たくさんでても一つやれば再配置される。
Oculus VRとは

今回は自分が使っている機材を紹介します。
（広告ではないです:sweat_smile:）

# Oculus VRとは
まず、Oculusは仮想現実のハードウェアおよびソフトウェア製品に特化した企業の事です。
企業自体が気になったら調べれば色々情報が出るので、ここでは詳しく説明しません。

肝心なのは、Oculusの製品ですね。
最初に開発したバーチャルリアリティ、ヘッドマウントディスプレイは「Oculus Rift」です。
それから「Oculus Go」、「Oculus Rift S」、「Oculus Quest」を開発しました。
ちなみに、「Oculus Go」は、中国のスマートフォンメーカー「Xiaomi」との提携により開発したものです。
中国市場では「Oculus GO」をリブランドした「Xiaomi Mi VR」と呼ばれるヘッドセットを発売しています。
# Oculus の区別
今発売されているのは、
「Oculus Go」、「Oculus Rift S」、「Oculus Quest」のみらしいので、
「Oculus Rift」抜きで説明します。

三機共通点は、
メガネの上から着用可とスピーカー内蔵二点のみです。

自分はメガネをかけていないので、メガネ着用時の着け心地はちょっとわからないですが、
設計の時、ちゃんとメガネ着用者の事も考えたのは、いいと思います。
スピーカーは、音声が聞こえる方向を立体的に再現しできるタイプです、音声の質は普通です。
イヤホン接続可ですので、質を追求したいなら、着用すれば解決できると思います。
![picturemessage_53yz20j5.tpp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541380/68938b65-ce90-bed5-0db0-bc10e7421e82.png)
[VRヘッドセット・デバイス - Oculus](https://www.oculus.com/?locale=ja_JP)
以下の内容は「Oculus」公式サイトの製品内容を参考し、作成しております。
## Oculus Go

PCとの継続は必要ありません。

LCDディスプレイで解像度は1280x1440です。

リフレッシュレートは60Hzです。三機の中一番古いタイプなので、Hzは一番低いですね。

コントローラーは1本のみ、精度はそれ程高くないので、ゲーム体験は他のタイプより低い感じです。
トラッキングは頭の動きを検出できます。
ゲーム内キャラを移動したい場合はコントローラーが必要です。

重さが一番軽くて、長時間使用の場合は頭にかかるストレスが、他のタイプより低いと思います。

古いタイプなので、値段は勿論一番安いです。

（ちなみに、Goのデザインは私が一番好きです。）

## Oculus Rift S

「Oculus Rift S」は残念ながら、実機を使った事ないため基礎知識のみ話します。
「Oculus Rift S」をプレイするにはPCが必要です、
なので高いパフォーマンスが要求されるゲームにも対応できます。
PC接続タイプなので、PCの配置にも要求されます。
（とはいえ要求はそれほ厳しくないです。）
処理速度も勿論PC次第です。

ディスプレイと解像度は「Oculus Go」と同じです。

リフレッシュレートは80Hzです。
三機の中では一番高いですね。

コントローラーは2本があって、両手の位置や動きをVR内に再現できます。

## Oculus Quest
一応独立タイプなんですが、最近はPC接続可になりました。
（PC接続の際は「Oculus Link」必要です。）
自由度は高いと思います。

OLEDディスプレイを使用しています。
ディスプレイ変化しましたね。

解像度は1440x1600で、リフレッシュレートは72Hzです。

コントローラーは「Oculus Rift S」と同じ2本ですが、
現在はハンドトラッキング技術がある為、未来でコントローラー使わずにゲームをプレイする事ができるようになると思います。

ちなみに、「Oculus Quest」はBluetoothを使えます。

重さは三機の中で一番重いタイプです。
# 購入なら
機能としては、勿論「Quest」です。
バランスが良くで、最新タイプなので、間違いないです。迷ったら「Quest」です。
（ゲームを遊ぶ為にも「Quest」勧めです。）

主に視聴用でしたら、
「GO」です、コントローラー1本で操作がしやすいし、準備も手間がかからないです。
軽いので、長時間の使用はいいと思います。

「Oculus Rift S」に関しては、使った事ない為、ここは保留します。

では…
psql のためだけに Docker を使う

DB をホストするわけじゃないので PostgreSQL をインストールしたくないパーソンです。

すぐ忘れるのでメモ。

## 使い捨て

```
# docker image を pull
$ docker pull postgres

# コンテナ起動して bash へ（--rm で終了即コンテナ削除）
$ docker run --rm -it postgres /bin/bash

# psql を使うよ
root@xxxx:/# psql -h <host> -d <database> -U <user>
```

```bash
# いきなり psql で良かったわ
$ docker run --rm -it postgres psql -h <host> -d <database> -U <user>
```

## コンテナ使いまわし（bash のコマンド履歴使いたい場合）

```
# docker image を pull
$ docker pull postgres

# コンテナ起動して bash へ（--name でコンテナに名前付けて消さない）
$ docker run --name psql -it postgres /bin/bash

# psql を使うよ
root@xxxx:/# psql -h <host> -d <database> -U <user>

# 抜け
root@xxxx:/# exit

# もう一度コンテナへ
$ docker start -ai psql

# 履歴使える
root@xxxx:/# psql -h <host> -d <database> -U <user>
```

コンテナを消すのは ``docker rm psql``。

## 応用: pg_dump を使う

```bash
 docker run --rm -it postgres pg_dump -h <host> -U <user> <datbase> > hostdir/backup.sql
```

(今まで、-v してコンテナ内部から pg_dump してたのがムダだと気づくのに、結構な日数を使ってしまったよ…。)
(あれ、でもなんかダンプした backup.sql の日本語が文字化けしてるな。。。）

## restore も一発でやろうとしたんだけど…

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">cmd /c &#39;docker run --rm -it postgres psql -h host db &lt; ./bk/bk.sql&#39;<br>でイケた（ﾀﾞｻ…<br>→winpty を付けろとか怒られる<br>→cmd /c &#39;winpty docker run --rm -it postgres psql -h host db &lt; ./bk/bk.sql&#39;<br>→stdin is not a tty と怒られるヽ(｀Д´#)ﾉ</p>&mdash; WFHあめいにおまかせろ! (@amay077) <a href="https://twitter.com/amay077/status/1281120247966121984?ref_src=twsrc%5Etfw">July 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Active Directoryドメインに参加させたCentOS8で、Domain Admins所属ユーザーにsudoを許可する

#はじめに
ローカルユーザーにsudoを許可させるにはwheelグループへ所属させる方法が王道ですが、ドメイングループ・ユーザーについて visudo で指定してsudoを許可する方法をご案内します。
（ドメインユーザーをwheelグループへ所属させる方法が不明なため...ちなみにsssdでドメインに参加させています）

#手順
"domain.tld"ドメインのdomain adminsグループ所属者とdomain user ユーザーにsudoを許可させる方法です。
visudoコマンドから、sudoersファイルへ次のように追記します。

```
%domain.tld\\domain\ admins ALL=(ALL) ALL
domain.tld\\domain\ user ALL=(ALL) ALL
```

- 先頭を%にするとグループでの指定になります。
- 空白は円マークでエスケープします。円マーク2連続でひとつの円マークを意味します。

以上です。
（4B）raycast

# 何かにぶつかったらゆっくり消えるスクリプト作らなければってなった時のraycast


![本を消す.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232643/011eee46-d781-b858-8f13-4f508732e7ed.gif)

```csharp 
public class Contact : MonoBehaviour
{
    //RaycastHitの「入れ物」
    RaycastHit hit;
    Vector3 iremono;
    //public float speed = 350.0f;
    int counta;

    void Start()
    {
    }
    void Update()
    {

        //最大のポイント
        //クリックしたら、クリック位置にRayを飛ばして色々物色
        if (Input.GetMouseButtonDown(0))
        {
            //elseの何もぶつかっていない時のマウス位置を取得用
            Vector3 pos = Input.mousePosition;

            //posにやや奥行を設定
            pos.z = 10.0f;

            //クリック位置にRayを発射!!
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            //rayの可視化（Sceneで見ないと出ない）
            float distance = 100; // 飛ばす&表示するRayの長さ
            float duration = 3;   // 表示期間（秒）
            Debug.DrawRay(ray.origin, ray.direction * distance, Color.red, duration, false);

            //Rayが当たったオブジェクトの情報を入れる箱
            RaycastHit hit = new RaycastHit();

            //rayにぶつかったら
            if (Physics.Raycast(ray, out hit))
            {
                counta++;
                // 複数クリック対策
                if (counta == 1)
                {
                    iTween.FadeTo(gameObject, iTween.Hash(
                    "alpha", 0,
                    "time", 2f,
                    "oncomplete", "Destroy",
                    "oncompletetarget", this.gameObject
                     ));

                    // Rayの衝突地点に、このスクリプトがアタッチされているオブジェクトを移動させる
                    this.transform.position = hit.point;

                    // コルーチンで一時停止
                    // StartCoroutine("ChangeTime");
                }
            }
            //rayに何もぶつかっていない場合はキューブを移動
            else
            {
                Vector3 newpos = Camera.main.ScreenToWorldPoint(pos);
                transform.position = newpos;
            }
        }
    }

  
private void Destroy()
{
    Destroy(gameObject);
}

    IEnumerator ChangeTime()
    {
        //赤色にする
        //gameObject.GetComponent<Renderer>().material.color = Color.red;

        //2秒停止
        yield return new WaitForSeconds(2);

        //自分を消す
        Destroy(this.gameObject);
    }
}
```
##解決事項
[iTween.Fade問題](http://takahirohirata.com/home/unity-javascript-itween-fadeto-%E9%80%8F%E9%81%8E)

##pointと不明点

・Raycastの使用（検証）
　これの違い
　・ScreenPointToRay
　・ScreenToWorldPoint

・iTweenアセットの利用（検証）
　もしや、ゆっくり移動可能？出来る事をもっと知りたい

・移動させる部分（復元検証）
　```// Rayの衝突地点に、このスクリプトがアタッチされているオブジェクトを移動させる
this.transform.position = hit.point;　```
　この部分がtransrateだとうまく動かなかった。
　当たった位置をVector3で格納してその位置にtransrateしたと思う。。

![本の移動.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232643/f87b82e0-3379-d66a-b17e-37ad3ca19b57.gif)


・初めてのコルーチン処理
　IEnumerator

・OnTriger（復元検証）
　その前段で、衝突をOnTrigerで取得してVector3に格納して使おうと思ったけどだめだった。
　Vector3で保管、もしくは値のセーブ方法
【Rails】ancestryを用いた多階層カテゴリー機能の実装『準備編』

# 開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

# 前提

下記実装済み。

・[投稿機能実装](https://qiita.com/matsubishi5/items/1a5aeab651b5822d1f2c)
・[多対多のカテゴリー機能実装](https://qiita.com/matsubishi5/items/a805fbcfd96f768dd622)

# 実装

### 1.Gemを導入

```ruby:Gemfile
# 追記
gem 'ancestry'
```

```terminal:ターミナル
$ bundle
```

### 2.カラムを追加

データ量がかなり多くなるので`index`を張ります。

```terminal:ターミナル
$ rails g migration AddAncestryToCategory ancestry:string:index
```

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

```ruby:schema.rb
create_table "categories", force: :cascade do |t|
  t.string "name"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "ancestry"
  t.index ["ancestry"], name: "index_categories_on_ancestry"
end
```

### 3.モデルを編集

```ruby:category.rb
# 追記
has_ancestry
```

`has_ancestry`
➡︎ ancestryを使える様になる。

# メソッド一覧

|メソッド名|返り値|
|---|---|
|parent|親レコードを取得|
|parent_id|親レコードのIDを取得|
|root|レコードのルートを取得|
|root_id|レコードのルートIDを取得|
|root?is_root?|レコードがルートであれば、trueを返す|
|ancestors|ルートで始まり、親で終わる、レコードの祖先を返す|
|ancestors?|レコードに祖先（ルートノードではない）がある場合はtrueを返す|
|ancestor_ids|レコードの祖先のIDを返す|
|path|ルートで始まり、自己で終わる、レコードのパスを返す|
|path_ids|ルートIDで始まり、 自己のIDで終わるパスのIDをリストで返す|
|children|子レコードを取得|
|child_ids|子レコードのIDを取得|
|has_parent?ancestors?|レコードが親を持っていれば、trueを返す|
|has_children?children?|レコードが子を持っていれば、trueを返す|
|is_childless?childless?|レコードが子を持っていなければ、trueを返す|
|siblings|兄弟レコード（同じ階層のレコード）を返す|
|sibling_ids|兄弟レコード（同じ階層のレコード）のIDを返す|
|has_siblings?siblings?|レコードの親に複数の子がある場合はtrueを返す|
|is_only_child?only_child?|レコードが親の唯一の子である場合はtrueを返す|
|descendants|子レコード、孫レコード、曽孫レコード... を返す|
|descendant_ids|子レコード、孫レコード、曽孫レコード... のIDを返す|
|indirects|孫レコード以下を返す|
|indirect_ids|孫レコード以下のIDを返す|
|subtree|子孫と自己のモデルを返す|
|subtree_ids|レコードのサブツリーのIDをリストで返す|
|depth|ノードの深さを返す|
|parent_of?(node)|このレコードを(node)の親にする|
|root_of?(node)|このレコードを(node)のルートにする|
|ancestor_of?(node)|(node)の祖先にはこのレコードが含まれる|
|child_of?(node)|(node)はレコードの親|
|descendant_of?(node)|(node)はこのレコードの祖先の1つ|
|indirect_of?(node)|(node)はこのレコードの祖先の1つですが、親ではない|

# 階層構造

**親：ビジネス**
**子：経済**
**孫：日本経済、国際経済**

本のカテゴリーに上記の様な親子関係を持たせたい場合は、以下の様にデータを作成します。

```ruby:
business = Category.create(name: 'ビジネス')

business_economy = business.children.create(name: '経済')

business_economy.children.create([{ name: '日本経済' }, { name: '国際経済' }])
```

### カラム構造
|id|name|ancestry|
|---|---|---|
|1|ビジネス|nil|
|2|経済|1(親のid)|
|3|日本経済|1/2(親のid/子のid)|
|4|国際経済|1/2(親のid/子のid)|

# 続編

[多階層カテゴリー機能実装(seed編)](https://qiita.com/matsubishi5/items/91248fce37b4b0d2e0f1)
深層学習Day1_学習レポート

<h1>深層学習day1</h1>
本レポートでは講義のまとめと問題の解答を記載する。
問題とその解答については下記のように示す。
(問：問題、答：筆者の答案、解：教材の模範解答)


<h2>0.全体像</h2>
■ニューラルネットワーク

問：ディープラーニングは結局何をやろうとしているのか
答：人間の脳であるニューロンを真似ることで、機械にも画像や音声のデータを判別すること
解：誤差を最小化するパラメータを発見すること

問：どの値の最適化が最終目的か
答：バイアス
解：重み、バイアス

問：次のネットワークを紙にかけ
答、解：
<img width="795" alt="ネットワーク.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632017/94bf3fcc-2f8f-5b70-95fd-49235d966828.png">


■ニューラルネットワーク(NN)でできること
回帰
　連続する実数値をとる関数の近似
　例：結果予想、ランキング

　回帰分析の種類
　・線形回帰
　・回帰木　など

分類
　性別(男あるいは女)や動物の種類など離散的な結果を予想するための分析
　例：写真の判別、文字認識

　分類分析の種類
　・ベイズ分類
　・ロジスティック回帰
　・決定木　など

深層学習の実用例
　自動売買(トレード)
　チャットボット
　翻訳　など

<h2>1.入力層〜中間層</h2>
入力：$x_i$
重み：$w_i$
バイアス：b
総入力：u
出力：z
活性化関数：f
入力層のインデックス：i
数式：$u = w_1x_1 + w_2x_2 + ... + w_ix_i + b$
　　　　$= Wx + b$
⇨(Pythonで記載する場合)
 u1 = np.dot(x, W1) + b1

問：1-1のファイルから
中間層の出力を定義しているソースを抜き出せ
答、解：z = functions.relu(u)


<h2>2.活性化関数</h2>
■活性化関数
　ニューラルネットワークにおいて次の層の出力の大きさを決める非線形の関数

■中間層用の活性化関数
　・ReLU関数
　→現在最も使われている関数。勾配消失問題が回避できる。
　・シグモイド（ロジスティック）関数
　→0~1を緩やかに変化する関数。人間的。勾配消失問題がある。
　・ステップ関数
　→出力は常に1か0。機械的

■出力層用の活性化関数
　ソフトマックス関数
　恒等写像
　シグモイド関数（ロジスティック関数）

入力：$x_i$
重み：$w_i$
バイアス：b
総入力：u
出力：z
活性化関数：f
入力層のインデックス：i
第二層のインデックス：j

u = Wx
z = f(u)

問：配布されているソースより z = f(u) に該当するソースを抜き出せ
答、解：z1 = functions.sigmoid(u)

<h2>3.勾配降下法</h2>
■深層学習の目的
　学習を通して誤差を最小にするネットワークを作成すること
　→誤差E(x)を最小化するパラメータwwp発見すること
　→勾配降下法を利用してパラメータを最適化

　 $w^{(t+1)} = w^{t} - ε$▽$E$(ε：学習率)
　　・学習率が大きすぎた場合→発散してしまい、最初値が見つからない
　　・学習率画小さすぎた場合→発散することはないが、計算に時間がかかる
　　　　　　　　　　or 限られた範囲での最小値を算出してしまう可能性がある

勾配降下法の学習率の決定、収束性向上のためのアルゴリズムについては
複数の論文が公開されている。(詳しくはDay2)

■確率的勾配降下法(SGD)
　式は勾配降下法と変わらないが、アプローチが異なる。
　確率勾配降下法：ランダムに抽出したサンプルの誤差
　勾配降下法：全サンプルの平均誤差

　メリット
　・データが冗長な場合の計算コストが軽減できる
　・望まない局所極小会に収束するリスクの軽減
　・オンライン学習ができる

問：オンライン学習とは何か
答、解：学習データが追加されるたび、追加分のデータを用いて学習を行うこと。

■ミニバッチ勾配降下法
　式は勾配降下法と変わらないが、アプローチが異なる。
　ミニバッチ勾配降下法：ランダムに分割したデータの集合に属するサンプルの平均誤差
　勾配降下法：全サンプルの平均誤差

　確率勾配降下法のメリットを損なわずに、計算機の計算資源を有効利用できる
　→CPUを利用したスレッド並列化やGPUを利用したSIMD並列化

■誤差勾配の計算 - 数値微分
　プログラムで微小な数値を生成し擬似的に微分を計算する一般的な手法

　デメリット
　・各パラメータ$W_m$それぞれについて$E(W_m+h)$と$E(W_m-h)$を
　計算するために準伝播の計算を繰り返し行う必要があり負荷が大きい。
　→誤差逆伝搬法を使用する。
CentOS8 のリモートデスクトップサービス (XRDP) 設定

#はじめに
CentOS8 へリモートデスクトップ接続 (RDP) をするため xrdp をふつうにインストールしようとしても「xrdp が見つからない」とのエラーで失敗してしまいます。

#対策
"epel-release" をさきにインストールします。

```
dnf install epel-release
dnf install xrdp tigervnc-server

systemctl enable xrdp --now

firewall-cmd --add-port=3389/tcp --zone=public --permanent
firewall-cmd --reload
```

以上です。
ウォークスルー後の通知許可とフォアグラウンド 通知を両立しようとしたら，うまくいかなかった件について

# TL;DR
- よくあるチュートリアルの後に通知許可の処理をしたらアプリ内通知が動かなかった
- これをするときは`appDelegate`にフォアグラウンド処理を書いてもダメ
- 通知許可の`viewController`にフォアグラウンド処理を書こう

# 何があったのか（前提条件）
- appDelegateの`application(_ application: UIApplication, didFinishLaunchingWithOptions)`に通知許可の処理を書かない -> アプリ立ち上げでは通知許可は出さない
- ウォークスルー終了後のメイン画面で通知許可を記述．
- フォアグラウンド通知のための`func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification:〜以下略)`はappDelegateに書いていた．

## 実行環境
|機材|バージョン|
|:--|:--|
|Xcode|11.5|
|iOS|13.5.1|
|Swift|5.2.4|

---

# 解決方法
上に書いてあるとおり，appDelegateには通知系の処理を書かず，通知許可を取りたい画面のコードに，

```swift:MainViewController.swift
import UIKit
import UserNotifications

class MainViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //通知許可
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound, .badge]) { [weak self] (granted, _) in
            if granted {
                let center = UNUserNotificationCenter.current()
                center.delegate = self
            }
        }
    //~~~~~~
    (中略)
    //~~~~~~
}

extension MainViewController: UNUserNotificationCenterDelegate {
    //フォアグラウンド通知処理
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    willPresent notification: UNNotification,
                                    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        //通知とサウンドのみ
        completionHandler([.alert, .sound])
    }
}
```
と記述する．

# 最後に
なんでこんな仕様なんだろう・・・
原理や「お前の勘違いや」，「もっとこうすべき」などのご指摘がございましたらコメントにてよろしくお願いいたします．
Javascriptの復習（5）

# この記事について
　Javascript初学者がアウトプットの場として書いている記事なので、スルーしてもらっても大丈夫です。Rubyを学習した後なのでRubyと絡めて記事を書くこともあります。

#ファイルの分割
　コードの量が増えてくるとコードの修正が大変になります。1つのファイルに書くのではなく、複数のファイルに分割することで管理しやすくなります。今回は分割する時のコードの書き方を説明します。
　ファイルを分割する時は、それぞれのファイルを関連付け必要な値を渡さなければなりません。
「export default クラス名や定数等」とクラスや定数の下に書く事で他のファイルへとエクスポートできます。
※因みにexportは英語で「輸出」を意味します。

```animal.js

class Animal {

}

//クラス定義後に書く事で他のファイルで使うように準備できます。
export default Animal;

```
次に、上記のAnimalクラスを使いたいファイルで「import クラス名や定数 from "./ファイル名"と書きます。
これにより、そのファイル内でAnimalクラスを使用できます。ファイル名の拡張子である".js"は省略できます。
※因みにimportは英語で「輸入」を意味します。

```cat.js
//この記述でcat.js内でanimal.jsで定義したAnimalクラスを使用できる。
import Animal from "./animal"

```

#デフォルトエクスポート
これまで書いていたexport defaultですが、この書き方は「デフォルトエクスポート」と言います。importする時にfrom"./ファイル名"とファイルを指定すると思いますが、この記述を書くと自動的にexportに書かれているクラスや定数が読み込まれます。先程「import クラス名や定数 from "./ファイル名"」と書くと説明しましたが、ここにあるクラス名や定数名はexportに書いてあるものと一致しなくても実は大丈夫です。importでファイル名を指定した時点で、自動的にexport defaultに書かれているクラス名や値がインポートされます。

```animal.js

class Animal {

}

export default Animal;

```

```cat.js
//クラス名がAnimalじゃなくても問題ない。このCat.jsファイル内では、AnimalクラスはBeastクラスとして扱われる。
import Beast from "./animal"

```

**ただし**、エクスポートできるのは１つの値で、複数のクラスや定数をエクスポートしようとするとエラーが出ます。

#名前付きエクスポート
名前付きエクスポートとはdefaultと書かずに名前を指定してエクスポートする方法で、名前は{}で囲います。

```dog.js
const dog1 = "チワワ"

//定数名を指定してエクスポート
export {dog1};

```
インポートする時も名前を書きます（importとfromの間）

```script.js
//インポートも定数名を書く。
import {dog1} from"./dog"

console.log(dog1);

```
名前付きエクスポートはデフォルトエクスポートと違い複数のクラス及び定数をエクスポートすることができます。

```dog.js
const dog1 = "チワワ"
const dog2 = "チャウチャウ"

//{}の中にエクスポートしたい物を全て書く
export {dog1, dog2};

```


```script.js
//インポートも同様に全て書く
import {dog1, dog2} from"./dog"

console.log(dog1);
console.log(dog2);

```
#パッケージ
Javascriptには「パッケージ」と呼ばれる誰かが既に作ってそのまま支える物があります。自分のプログラムでも引用して使用できます。フレームワークと同じ物だと思います。今回は以下のパッケージを使用しました。

chalk : コンソールに出力する文字に色を付けられる。
redline-sync : コンソールに値を手入力できる(Rubyのgetsのような機能)

パッケージを使用する時は、importでパッケージをインポートします（exportはいらない）。

```script.js
//定数はなんでも良いが、同じ名前の方がわかりやすい。
import chalk from "chalk";

```

インポートしたファイルではパッケージの機能を使えるようになります。

```script.js
//文字列をchalk.yellow等で囲むと色が変化する。
import chalk from "chalk";
//文字がイエローになる
console.log(chalk.yellow("Hello World"));
//背景色がシアンになる(bgはback groundの略)
console.log(chalk.bgCyan("Hello World"));

```
redline-syncというパッケージを使用すると、コンソール上に値（文字）を入力することができ、その値をプログラム上で使用できるようになります。今回はredlineSyncという定数としてredline-syncを使用できるようにしていますが、readlineSync.question("質問文")というコードを書くことで、質問文が表示され、文字が入力できるようになります。
整数を入力したい時はquestionではなくquestionIntと書きます(integerのintだと思う。)

```script.js
//redline-syncをredlineSyncとしてインポートする。
import redlineSync from "redline-sync";

//質問文が表示されて、文字を入力できるようになる。入力された文字は定数wordに代入される。
const word = readlineSync.question("文字を入力してください : ");
console.log(`${word}と入力されました。`)

```
OBSの画面をMeet, Zoomでスマートに共有する

##ここだけ読めばOK
- カメラとスライドを合成するにはOBSを使うのが早い。
- OBSの画面を右クリックするとディスプレイにプレビューできる。
- プレビューされた画面をMeetやZoomで画面共有することで余計な物を映さずに共有できる。

##なんで書いたの？
せっかく誰かがスライドを使っていい話をしているのに、その画面にOBSのメニューが映ってしまっていて勿体ないと思ったので。

##どうしたいのか
ZoomやMeetで画面を共有する際に、映したい画面と自分の顔を同時に表示させたい。できたらスマートに。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556386/b482865b-a1f8-f30e-9e32-04d8c5f2baf9.png" width=50%>

ものすごいざっくりしたイメージはこう

##必要な物
- webカメラ
- それなりのスペックのPC
- ディスプレイ（3画面あると良い。）

##実際に写すには
MeetやZoomは、webカメラを取り込んで映像を写すことと、画面共有をすることの二つの方法で映像を取り込むことができる。

どちらの方法でもOBSの映像を使うことは出来るが、個人のカメラとして認識させる都合上、サイズは他の人と同じ。
全員に画面を拡大させるように指示してもいいけど、あまりスマートではなさそう。

**今回は画面共有で写す方向でやってみよう。**

まずOBSを起動する。
![コメント 2020-06-19 193153.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556386/83d22b69-4e4b-b4a7-7b31-995a430a5bab.png)
カメラとスライドはOBS側のソースからよしなに取り込む。
今回は都合でカメラじゃなくて猫で代用。
これをそのまま画面共有で取り込んでもいいけど、ミキサーとかソースとか映っててあんまりきれいじゃない。

そこで、どこでもいいのでプレビュー画面上を右クリックする。

![コメント 2020-06-19 193342.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556386/31b80268-d8c8-03e5-f4c8-d9dfec53d3c1.png)

すると赤線を引いたところに**全画面プロジェクター(プレビュー)**というものが存在する。
コイツにカーソルを合わせると全画面表示するディスプレイを選択できるので、任意のものを選択。
すると一画面全て使ってプレビュー画面だけがドンと表示される。
画像で言うと猫とソファと高輪ゲートウェイ！！だけが表示されるハズ。
なお、ウィンドウで表示もできるがそうすると上の方にウィンドウのバーが映るので注意が必要。

###後はMeetおよびZoomで画面共有→全画面表示されているディスプレイを選択すれば
![slide_image_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556386/12db9673-a8d3-3f33-ef6f-f859e67ca4f4.png)
このように、無駄なスペース無く表示させることが出来る。
非常に美しいですね。
Dispatchers.Main.immediateとは？


Qiita初投稿です。何か間違い等ありましたらコメントで指摘いただけると助かります。

coroutineを使う際にDispatcherとして指定できるDispatchers.Main.immediateについて調べたことをまとめてみました。

# 要点
先に要点を述べておきます。

Dispatchers.Main.immediateとは？
* メインスレッドで実行される。
* UI更新を即時行いたい際に使用。

名前から予想できますがメインスレッドで実行されます。本記事では２つ目の「UI更新を即時行いたい際に使用」に焦点を当てて解説していきます。

# 調べた経緯


viewModelScopeを使う際に、デフォルトのDispatcherは何だろうと思い、ソースコードを見てみると以下のようになっていました。

```kotlin
val ViewModel.viewModelScope: CoroutineScope
        get() {
            val scope: CoroutineScope? = this.getTag(JOB_KEY)
            if (scope != null) {
                return scope
            }
            return setTagIfAbsent(JOB_KEY,
                CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate))
        }

```

DispatcherとしてDispatchers.Main.immediateが指定されています。

私はDispatcherとして指定できるものは以下の4種類だけだと思っていたので、Dispatchers.Main.immediateについて調べてみました。

* Dispatchers.Main
* Dispatchers.Default
* Dispatchers.IO
* Dispatchers.Unconfined

Qiita内でDispatchers.Main.immediateで検索すると以下の2つの記事がヒットします。

[Coroutines私的メモ2~Dispatchers, withContext, async/await~](https://qiita.com/sudo5in5k/items/319a7c45923aebc04571)
[Kotlin coroutine入門 ② ~ coroutine scope & jobについて~](https://qiita.com/ymkit/items/71dc7ddcbc6c24c26e83)

両記事ともDispatchers.Main.immediateの説明として以下のような記述がありました。
> UI更新を即時行いたい際に使用

UI更新を即時行いたい際に使用とはつまりどういうことでしょうか？
Dispatchers.Mainではダメなのでしょうか？

# UI更新を即時行いたい際に使用とはどういうことか

同様の処理をDispatchers.Mainを指定した場合とDispatchers.Main.immediateを指定した場合で比較して見ていきます。

### Dispatchers.Mainの場合

メインスレッド上で以下の処理をした場合の出力を考えていきます。

```kotlin
Log.i("tag", "a")
launch(Dispatchers.Main){
    Log.i("tag", "b")
}
Log.i("tag", "c")
```

出力

```
I/tag: a
I/tag: c
I/tag: b
```

a→c→bと出力されました。これはメインディスパッチャーが処理をMessage Queueにpostするだけでその場で実行されないからだそうです。


### Dispatchers.Main.immediateの場合

```kotlin
Log.i("tag", "a")
launch(Dispatchers.Main.immediate){
    Log.i("tag", "b")
}
Log.i("tag", "c")
```

出力

```
I/tag: a
I/tag: b
I/tag: c
```

a→b→cと出力されました。launch内の処理がその場で実行されていることがわかります。

つまり、Dispatchers.Main.immediateを指定したものをメインスレッド上で呼び出すと後続の処理を待たずしてコルーチン内の処理を実行できるということです。

そのため、コルーチン内にUI更新の処理がある場合は即座に画面に反映することができるという点から「UI更新を即時行いたい際に使用」ということなんだと考えられます。

# 参考にしたページ


[Coroutines私的メモ2~Dispatchers, withContext, async/await~](https://qiita.com/sudo5in5k/items/319a7c45923aebc04571)
[Kotlin coroutine入門 ② ~ coroutine scope & jobについて~](https://qiita.com/ymkit/items/71dc7ddcbc6c24c26e83)
[MainCoroutineDispatcher.immediate - kotlinx-coroutines-core](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-coroutine-dispatcher/immediate.html)
[Launching a Kotlin Coroutine for immediate execution on the Main thread](https://medium.com/@trionkidnapper/launching-a-kotlin-coroutine-for-immediate-execution-on-the-main-thread-8555e701163b)
あるだけで一寸嬉しいちょっとした簡易ブックマークレット(たち)

# 概要
最近自分で作ったブックマークレットの内、
利用頻度が高く、作って良かったと感じたものをいくつか記載。

※『作った』とかいう表現は大げさだけど

# ブックマークレットたち

## 上へ
所謂『1つ上の階層』に移動する。

```javascript:☝
javascript:(function(){
  window.location.href = window.location.href.replace(/[^\/]+\/?$/g, '');
})();
```
```javascript:☝&#32;(ブックマーク登録用)
javascript:(function(){window.location.href = window.location.href.replace(/[^\/]+\/?$/g, '');})();
```

## title
ページ タイトルを入力ダイアログで表示し、コピーを補助する。

```javascript:title
javascript:(
  function(){window.prompt('page title', document.title);
})();
```
```javascript:title&#32;(ブックマーク登録用)
javascript:(function(){window.prompt('page title', document.title);})();
```
### (補足)
調べ物などをしていてWEBページをメモる時に
URLと一緒にタイトルも一緒に欲しくなることが多い。
firefoxなどではページのプロパティ画面があったのでchromeだと同様のものがなく、また元々手数も多かった。
ページを非破壊でコピーまですることは出来ないので、
入力ダイアログを代用している形。


## picture size
画像の解像度を表示。

```javascript:picture&#32;size
javascript:(function(){
  var img = new Image();
  img.onload = function () {
    Promise.resolve().then(function() {
      window.prompt('width x height', '' + img.width + 'x' + img.height + '');
    });
  };
  img.src = location.href;
})();
```
```javascript:picture&#32;size&#32;(ブックマーク登録用)
javascript:(function(){var img = new Image(); img.onload = function () {Promise.resolve().then(function() { window.prompt('width x height', '' + img.width + 'x' + img.height + '');});}; img.src = location.href;})();
```
### (補足)
一応chromeでもファイル名の末尾に解像度は出ているものの、
ファイル名が長くなる + 沢山タブを開いてると、すぐに見えなくなる。
結果的には再ダウンロードがかかってしまうので、トラフィックにはあまり優しくない。


## user agent
そのまま。
javascriptで取得出来るUserAgentを表示。

```javascript:useragent
javascript:(function(){
  window.prompt('user agent', window.navigator.userAgent);
})();
```
```javascript:useragent&#32;(ブックマーク登録用)
javascript:(function(){window.prompt('user agent', window.navigator.userAgent);})();
```

## amazondp
amazonの商品へのリンク
　\*\*\*\*/dp/****/
を抜き出して遷移。

```javascript:amazondp
javascript:(function() {
  var p = window.location.pathname.match(/\/dp\/[^\/?#=&]+/g);
  if(p) {
    window.location.href = window.location.origin + p[0];
  };
})();
```
```javascript:amazondp&#32;(ブックマーク登録用)
javascript:(function(){var p = window.location.pathname.match(/\/dp\/[^\/?#=&]+/g); if(p) {window.location.href = window.location.origin + p[0];};})();
```

### (補足)
AmazonのURLは共有しようとすると○したくなるくらい長い。
~~~商品名とかURLに埋め込む必要あんの？？？~~

## openpopup
今開いているページをポップアップで表示。

```javascript:openpopup
javascript:(function() {
    window.open(window.location.href, undefined, 'menubar=no, toolbar=no');
})();
```
```javascript:openpopup&#32;(ブックマーク登録用)
javascript:(function() { window.open(window.location.href, undefined, 'menubar=no, toolbar=no');})();
```
※スクリプトが誤っていたので修正しました。
❌ window.location.pathname
⭕ window.location.href

### (補足)
漫画は縦長が多いので、どうしてもアドレスバーやタブバーなどの分の解像度がもったいなくなる。
ポップアップで開くことで高さを稼いだりできる。
ただし、ポップアップ ブロッカーなどで起動の確実性は保証できない。
また、あくまでURLで開き直しているだけなので、POST系などのページでは遷移出来ない。



# 余談
ブラウザ拡張のツールバー文化は完全廃れたけど。
ブックマークバーとブックマークレットの併用でも、
ブラウザを便利にできることは多いので、もっと活用していけたらなぁと思う、
AWS CLI on IBMi

AIX上にawscliをインストールする[記事](http://techadminblog.com/aix-install-awscli-exclusively-to-current-user/)を見つけ、もしやpase環境にもインストールできるのは？と思い実施してみました。

## 検証した環境

||  バージョン  |備考|
| ---- | ---- | ---- |
|OS|7.3||
|Python|2.7.13||
|pip|20.1.1||
|groff|1.22.2|helpが見たい時に必要です。|

SSH接続で作業をしています。なお、環境についてアップグレードが必要になる場合がありますが自己責任でお願いします。

## pipのアップグレード
もともとのバージョンが9.0.1で、yum infoで確認しても9.0.1です。（2020年6月現在）
このバージョンのままで作業するとcliのインストールに失敗したため、アップグレードをしました。

```
> pip install --upgrade pip
```

```
> pip -V
pip 20.1.1 from /QOpenSys/QIBM/ProdData/OPS/Python2.7/lib/python2.7/site-packages/pip (python 2.7)
```

## 指定のフォルダにaws cliをインストールする
ここでは /home/ymurata/awscli にインストールしてみます。

```
> pwd
/home/ymurata
> mkdir awscli
> export PYTHONUSERBASE=/home/ymurata/awscli
> pip install --user awscli

```
![awscli01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146069/adb00476-ecc9-ead4-d07a-bf57b4ec38d9.png)
pip showで確認した、Locationを控えておいてください。

```
> pip show awscli
Name: awscli
Version: 1.18.81
Summary: Universal Command Line Environment for AWS.
Home-page: http://aws.amazon.com/cli/
Author: Amazon Web Services
Author-email: UNKNOWN
License: Apache License 2.0
Location: /home/ymurata/awscli/lib/python2.7/site-packages
Requires: botocore, PyYAML, docutils, rsa, colorama, s3transfer
Required-by:
```

## 動かす

環境変数PYTHONPATHが必要です。

```
> export PYTHONPATH="/home/ymurata/awscli/lib/python2.7/site-packages"
> awscli/bin/aws --version
aws-cli/1.18.81 Python/2.7.13 OS400/3 botocore/1.17.4
>awscli/bin/aws help

Could not find executable named "groff"
```

s3にアップロードをしてみましたが、上手く動きました！

## groffをインストールする

/opt/freeware/bin/に存在しているかもしれません。無ければ、以下の手順で。RPMでインストールしました。

[このページ](https://www.perzl.org/aix/index.php?n=Main.Groff)から groff-1.22.2-1.aix5.1.ppc.rpm をダウンロードし、適当なifsのフォルダにアップロードします。（ここでは/home/ymurata/download)

環境変数のセットは、各環境に合わせてください。LIBPATHは必要かどうか微妙ですが念のためセットしました。

```
> export PATH=$PATH:/QOpenSys/usr/bin:/QOpenSys/usr/sbin:/opt/freeware/bin
> export LIBPATH=/QOpenSys/usr/lib:/opt/freeware/lib
> cd download
> rpm --ignoreos --ignorearch --nodeps --replacepkgs -hUv groff-1.22.2-1.aix5.1.ppc.rpm
> groff -version
GNU groff version 1.22.2
Copyright (C) 2013 Free Software Foundation, Inc.
GNU groff comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of groff and its subprograms
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.

called subprograms:

GNU eqn (groff) version 1.22.2
GNU troff (groff) version 1.22.2
> cd ..
> awscli/bin/aws help
AWS()                                                                    AWS()



NAME
       aws -

DESCRIPTION
       The  AWS  Command  Line  Interface is a unified tool to manage your AWS
       services.
:
:
```

## 遭遇したエラー

```
> aws help
Traceback (most recent call last):
  File "./aws", line 19, in <module>
    import awscli.clidriver
ImportError: No module named awscli.clidriver
```
このエラーが出ましたが、PYTHONPATHを設定することで解決しました。

実行についてまとめると

- 実行するのに必要な環境変数は、PYTHONPATH・PYTHONUSERBASEが必要
- helpが見たい場合はgroffが存在しているフォルダのPATHを通す
Excel 起動時テーブルオブジェクト作成・連動ドロップリスト


|a  |b  |c  |a  |b  |c  |
|---|---|---|---|---|---|
|  |  |  |  |  |  |
|  |  |  |  |  |  |
|  |  |  |  |  |  |
|  |  |  |  |  |  |
|  |  |  |  | 　|  |
|  |  |  |  |  |  |
|  |  |  |  |  |  |

#ワークシート上変更
```VB
'セル変更時対応
Private Sub Worksheet_Change(ByVal Target As Range)

    ' 一つ目のドロップダウンリストの変化を検知
    If Not Intersect(Target, RngA) Is Nothing Then
        
        'リストに存在すれば
        If ListA.Exists(Target.Value) Then
                
            '二つ目のドロップダウンリスト設定
            With Target.Offset(0, 1).Validation
        
                .Delete
                .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Formula1:=ListA.item(Target.Value)
            
            End With
    
            '二つ目のドロップリスト用値を作成
            tmp = Split(ListA.item(Target.Value), ",")
            
            '二つ目のドロップリスト初期化、3つ目のセルにも値を入れる。
            Target.Offset(0, 1).Value = tmp(0)
            Target.Offset(0, 2).Value = ListB.item(Target.Value & tmp(0))
    
        Else
        
            'リストに該当しない場合は記入済み値を消去
            Target.Offset(0, 1).Value = ""
            Target.Offset(0, 2).Value = ""
            Target.Offset(0, 1).Validation.Delete
    
        End If

    '二つ目のドロップダウンリストの変化を検知
    ElseIf Not Intersect(Target, RngA.Offset(0, 1)) Is Nothing Then
    
        'リストに存在すれば
        If ListB.Exists(Target.Offset(0, -1).Value & Target.Value) Then
    
            '三つ目以降の値を記述
            Target.Offset(0, 1).Value = ListB.item(Target.Offset(0, -1).Value & Target.Value)

        Else
            'リストになければ三つ目の以降の値を消去
            Target.Offset(0, 1).Value = ""

        End If
        
    End If

End Sub
```

#ブック起動時初期化プロシジャー呼び出し
```VB
Private Sub Workbook_Open()

    Call Table_Init

End Sub
```

#標準モジュール（テーブルオブジェクト作成）
```VB
Public RngA As Range
Public ListA As Object
Public ListB As Object
Public Wsi1 As Worksheet
Public Wsi2 As Worksheet

Public Sub Table_Init()
    
    Dim RngS As Range
    
    'シート宣言
    Set Wsi1 = ThisWorkbook.Worksheets("Master")
    Set Wsi2 = ThisWorkbook.Worksheets("Check")
    
    'テーブルA（入力レンジ）
    With Wsi1
    
        Set RngS = .Range(.Cells(2, 2), .Cells(16, 2))
    
    End With
    
    '出力先レンジ
    With Wsi2
    
        Set RngA = .Range("C3:C27")
    
    End With
    
    'テーブル設定
    Set ListA = CreateObject("scripting.dictionary")
    Set ListB = CreateObject("scripting.dictionary")
    
    
    'テーブル値反映
    For Each Rng In RngS
    
        '未登録ならキーと値を登録
        If Not ListA.Exists(Rng.Value) Then
        
            ListA.Add Rng.Value, Rng.Offset(0, 1).Value
            
        Else '登録済みなら値にカンマ区切りで値追加
        
            ListA.item(Rng.Value) = ListA.item(Rng.Value) & "," & Rng.Offset(0, 1).Value
                        
        End If
        
        '1列目と2列目の組み合わせでキー登録
        ListB.Add (Rng.Value & Rng.Offset(0, 1).Value), Rng.Offset(0, 2).Value
        
    Next Rng

    'Rangeにドロップリスト配列指定
    RngA.Validation.Delete '既存の入力規則を削除
    RngA.Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Formula1:=Join(ListA.Keys, ",")
    
End Sub
```
【enum】 rails enumを利用してデータの可読性をあげよう

##【ゴール】
rails においてenumの使用 

![画面収録 2020-06-19 19.28.08.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620689/60c48f87-cc70-8c9e-1088-200d92cbcaf5.gif)


##【メリット】
■　dbの可読性向上、管理しやすい
■　日本語化にも応用が効く


##【開発環境】
■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7

##【実装】
####と言ってもとても簡単!!!!対象のモデルに追記するのみ

※①が一番簡単な書き方
※②だと日本語も可能

```model/hoge.rb
① enum カラム名:[:任意の単語, :任意の単語, :任意の単語, :任意の単語]
② enum カラム名:{"任意の単語": 1,"任意の単語": 2.......}
```

※number_field をselectに変更する
※enumで設定した値を取得して、選択できるようになります。

```hoge/_form.html.erb
<%= form.select :カラム名, モデル名.カラム名s.keys, :selected=>モデル名.カラム名s[カラム名] %>
```
以上

##【合わせて読みたい】
■enumについて
https://web-camp.io/magazine/archives/16862

■form_withについて
https://qiita.com/tanaka-yu3/items/50f54f5d4f4b8dfe19f3
VSCodeで「The .NET Core SDK cannot be located.」メッセージを抑止

# 概要

Visual Studio Code起動時に表示される以下のエラーを抑止する方法

> The .NET Core SDK cannot be located. .NET Core debugging will not be enabled. Make sure the .NET Core SDK is installed and is on the path.

# やり方

`Disable this message in user settings`ボタンを選択します。
![vscd1-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/b382a2d5-f30c-8c89-88b3-509290ea6ab9.png)

設定画面の検索ボックスに`suppress`を入力して設定項目を絞り込みます。
`Csharp:Suppress Dotnet Install Warning`にチェックを入れます。
![vscd1-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/0704e5b5-e1f2-4637-c457-172bdae3c50a.png)
CakePHP4で自作Templateを含んだヘルパーを作成してみる

#この記事について
CakePHPは、デフォルトで`Cake\View\Helper\FormHelper`, `Cake\View\Helper\HtmlHelper`などを含んでいます。これらを使用すると、自分でHTMLを直接コーディングしないでほぼPHP内でHTMLタグを自動作成してくれます。例えば、以下のようなコーディングができます。

```php5

echo $this->Html->image('cake_logo.png', ['alt' => 'CakePHP']);

```
これは、以下のHTMLを生成します。

```php5
<img src="/img/cake_logo.png" alt="CakePHP" />
```

でもどうやってこのようにHTMLヘルパークラスはHTMLタグを返却するのでしょう？自分も同じようなヘルパークラスを作れないのか？ということで、今回はHTMLヘルパークラスを紐解きながら、このようなヘルパークラスの作成方法を考えていきます。

###実際にHTMLヘルパークラスを見てみよう

以下のリンクから、公式のHTMLヘルパーのコードを参考にできます。
https://github.com/cakephp/cakephp/blob/4.0.8/src/View/Helper/HtmlHelper.php

ここで特に気づいてほしいのは、`Cake\View\StringTemplateTrait`の使用です。
他のヘルパークラスを見ても同じように使われています。これさえうまく使いこなせれば、ヘルパークラスをかなりカスタマイズできそうです。

[公式の説明](https://api.cakephp.org/3.8/class-Cake.View.StringTemplateTrait.html#)を読んでもいまいち理解できないので、実際にStringTemplateTraitを使っているHTMLヘルパーをパクって自作ヘルパーを作っていきます。

#設計、プラン
以下のようなヘルパーを作りたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464595/c47c05ed-ffd9-d788-475b-10f39d2ade80.png)

##1. StringTemplateTraitを呼び出す

```php5:FruitsHelper

<?php
declare(strict_types=1);

namespace App\View\Helper;

use Cake\View\Helper;
//StringTemplateTraitを呼び出す
use Cake\View\StringTemplateTrait;

class FruitsHelper extends Helper
{
    //StringTemplateTraitの使用を宣言
    use StringTemplateTrait;
    
    //ヘルパー内で他のヘルパークラスを使う場合、以下のように書く
    protected $helpers = ['Url'];

```
ここは、ベーシックなヘルパーを作成するのと同じです。今回、URLヘルパーをFruitsヘルパーの中で使いたいので`$helpers`に設定しています。

##2. $_defaultConfigにtemplatesを設定
編集中

##3. renderメゾットの定義
編集中

##4. フロント側でrenderメゾットを呼び出す
編集中
[メモ]summarise(across())を使ったsummarise_each()の代替表現の例

データフレームの中で特定の列に限定して、ある処理を行いたいとします。
その場合は`dplyr`の`summarise_each`関数が便利です。

たとえば

```R
(データフレーム) %>% summarise_each(mean, matches("(正規表現)", ignore.case=FALSE))
```

とすれば正規表現を満たす列にのみ`mean`関数が適用されます。

しかしこのようなsummarise_each関数ですが、いずれ非推奨となるようです。

なので`summarise(across())`を使って代替表現を書いてみます。

```R
(データフレーム) %>% summarise(across(matches("(正規表現)", ignore.case=FALSE), mean))
```


これら出力結果を`all_equal`関数で比較すると`TRUE`が返ってくるので、無事代替表現を実装できました。