OmniAICreator/Qiita-1.07M huggingface dataset:
cwltool でのCWLのツール定義開発の回し方紹介

# 概要

cwltoolを使ってCWLのツール定義の開発の回し方の紹介

# 結論

1. CWLのツール定義を作る
2. 作ったCWLファイルを検証する
  - `cwltool --validate 作った.cwl`
3. 問題があれば、1
4. ヘルプでオプションを確認する(2の操作の`--validate`と違って、cwlファイルの後ろに `--help`)
  - `cwltool 作った.cwl --help`
5. 設定ファイルのテンプレートを作る。作らない場合は6の後半
  - `cwltool --make-template 作った.cwl > 設定ファイル.yaml`
6. 実行する
  - `cwltool 作った.cwl 設定ファイル.yaml`
　または
  - `cwltool 作った.cwl --作ったオプション1=値 --作ったオプション2=値`
VBAエキスパート合格の記録

# VBAエキスパート試験の分類
4種類あります。
Standard が上位資格です。

- Excel Basic
- Excel Standard
- Access Basic
- Access Standard

# 受験
今回はExcel のBasic と Standard を受けてきました。
2コマ連続で押さえると、連続受験できます。
（Basic が30分ほどで終わり、そのまますぐに Standard を開始できたので、時間の節約になりました）

**※なお、以降の内容はすべて個人の主観に基づいた感想です。
　特に出題の傾向などは、実際には私の感想と異なる場合もあると思いますので、ご注意くださいませ。**

## 勉強方法
- 純粋に Excel VBA の勉強を通じて技術向上することが目的だったので、試験対策本や過去問は一切やりませんでした。

- （業務やソーシャルワーキングでVBAツールは作っているものの）本業プログラマーではなく、VBAを本格的に学んで活用し始めてから日も浅く本格的な開発の経験が無いので、スキルが客観的にどの程度の水準なのか測りたかったのも動機です。

### 勉強量
 - 書籍 ： 4冊 計約2,000ページ。ほぼ往復の通勤電車と昼休みのみの学習、所要期間は2ヶ月ほど。
 - ハンズオン ： 書籍で理解しにくかったサンプルコードを写経。
 - 実践 ： 本業で隙を見てはツールや独自関数を作成して同僚に使ってもらったり。ランサーズ等でも何件か業務遂行（集計ツール作成やスクレイピングの案件）。

ざっくり言うと、上記で **読書50時間 + 実践50時間 = 計100時間くらい** でしたので、目安にはなると思います。
ただし、Excel へ習熟していることが前提です。

また、PCやプログラミング関係の基本的な知識の有無でも差が出ると思います。

（なお**試験合格だけを目的に暗記をこなすなら、最短でもっと短時間の勉強で取れるかもしれませんが**、単なる暗記だけではVBAで成果物を作る役には立ちにくいと思いますので、あまりオススメはしません）

# テストの内容
### 概要
- Basic、Standard ともに50分、40問でCBT方式。
- 1,000点満点中、『最低合格点』が700点（成績表にそう書いてあった）。加えて内訳の全項目、一定以上の点数が必要かも。
- すみません、問題の形式は調べていません。。（受験ごとにランダムで選択される？）

## Excel Basic
- 選択問題が多く、内容も簡単なので難易度は低い。入門書を1冊しっかりやっておけば取れそう。
- 類似のパターンの問題が繰り返し出てきて、少し飽きる。
- IF文の条件式の"<>"を"="と誤認したせいで少し苦しんだ問題があった。（問題はよく読みましょうw）
- 50分あったが、20 ～ 30分くらいで終わった。
- 920点で合格。終わると即、次の試験を開始できる（受験会場の対応によってはできない場合もあるかも）。

## Excel Standard
- 入力問題が非常に多く、入力補完も無いため、暗記力が問われる。
- 問題に非常に偏りがあったように感じた。具体的には、やたらとテーブルの操作の問題が多かった。逆に外部アプリとの連携なんかは、ほぼ無かった。
- 意外なことに WorksheetFunction の問題も執拗に出てきて、使い慣れているのでラッキーな気分だった。（でもこれVBA？）
- Basic と同様、類似の問題が繰り返し出てくるが、あまり詳しくなかったテーブル操作が執拗に出題されて、合格を諦めかけた。。(何通りもの集計列の追加や削除や転記のコードの、穴埋め入力問題など)
- 逆に類似の問題が繰り返される中で、問題文に別の類似問題の回答につながる構文があったり（たとえばテーブルの列の指定で[@列名]の構文が他の問題文から分かったり）して、ラッキーも。
- Basic で選択問題だったのと同じ部分が、入力問題として出てきたりして、連続受験で少し得した、かも。

### Standard の難易度
#### 問題の内容
（リファレンス系の本も一通り読みはしていたが）試験用の暗記学習のようなことをしておらず、利用経験がほぼ無く知識が薄かったテーブル関連のプロパティやメソッドや、その他うろ覚えの関数の挙動やら組込み定数名等々。

そのほとんどが入力問題で、知識が無ければ絶対解けない。

推測による回答は全くできないので、試験対策の暗記勉強無しでは、難易度はかなり高いと感じた。

#### 持ち時間
（前半に分からない問題が偏っていたこともあり）半分経過時点で、問題が半分まで進めておらず時間切れの危機を感じた。

1問あたり約1分しかなく、即答できないものは少し考えているとあっという間に2、3分経ってしまうので、**考えている時間がない。**
後半は納得いくまで考えるのはやめてギアを上げて、どうにか間に合った。

自信もあまり無かったので最後は見直しまでして、時間はほぼ使い切った。

#### 結果
**750点で、ギリギリ合格**
内訳は最低で50％の項目もあり、本当にギリギリで運が良かったかも。

# 役に立つか？
Standard は（実務で役立ちにくい）暗記問題の側面はある。

ただ内容は実務での利用頻度が高いと思われるもので、実際のコーディング経験がけっこう点数に反映されそうだと思った。
（Range なら Resize や CurrentRegion などをソラで書けるかどうか、みたいな感じだったり。その他どう考えても本ではなく実務経験で覚えたような WorksheetFunction の使い方や二次元表に対する多重ループの回し方だったりがかなり出題され、わりと実践的だった）

**（Basic & Standard で）約2.5万円も支払って適度なプレッシャーがかかったおかげで、1,000ページもあるリファレンス系の本なんかを通読するモチベーションになったので、個人的には（勉強面で）とても役に立った。**
問題には出なかったものが大半だが、仕入れた知識で確実にコーディング力の幅が広がってスキルが上がった実感もある。

（個人的には、クラスモジュールを活用して効率的にコーディングできるようになるのが、今の課題）

# これから勉強する人へ
- VBA のスキルを証明できるだけの実績が既にある人 ： おそらく取る意味は無いと思います。
 
- VBA のスキルを証明する必要が無い人 ： VBA が趣味でもなければ、取る意味は無いと思います（それより自分の業務に直結した分野を勉強した方が良いと思います）。

- VBA のスキルアップをしたい初心者 ： 本気でやれば十分取れるし、客観的に見ても一応転職に有利になることもありそうなので、オススメです。（といっても転職については事務職か、さもなくばExcel VBA の開発会社に未経験枠で入ろうとするのでもない限りは、あまり価値は高くないと思いますが...）

- 費用について ： 個人の価値観次第ですが、お金に余裕がない人は無理に払ってまで取る価値は無い気がします。

- 勉強方法について ： **独学一択**だと思います。このレベルなら独学で取れないと、実際にVBAで成果物を作っていくのは難しい気がします。（暗記問題とはいえ、出題されるのは実務でよく使うような知識ばかりでした。誰も知らないようなものはほぼ出ません。...たぶん）

おわり
UMLツール、Amaterasをさくっとセットアップ

# ダウンロード
Eclipse
https://www.eclipse.org/downloads/packages/
Eclipse IDE for Web and JavaScript Developers あたりがコンパクトでよいかと

Amaterasプラグイン
http://amateras.osdn.jp/cgi-bin/fswiki/wiki.cgi?page=AmaterasUML

# セットアップ作業

- Eclipseのインストール
- GEFのインストール
    - Eclipse -> Install New Software...
    - "Graphical Editing Framework"で検索
    - インストール
- Amaterasプラグインのインストール

https://itsakura.com/eclipse-add_manualplugin

- Eclipse再起動

以上
VSCodeでRubyを書く準備

Rubyを書き始めるにあたり、WebStormからVSCodeに完全移行しました。RubyMineまで買えない :money_with_wings:
1年半ほど前に使ったときは、動作がモッタリしてるな〜という印象でしたが（Sublimeが軽快すぎて）
今使ってみると結構さっくさくになってる！快適！
（ちなみにキーバインドはSublimeのバインドがそのまま使えて助かりました。癖ってなかなか変えられないですね...）

## 拡張機能 「Ruby」 をインストール
拡張機能検索で「ruby」と打てば１番上にでてきます。
Ruby言語に関して、デバッガー、Linter、自動補完など大体のことをカバーしてくれる必須拡張機能です。
この拡張機能の設定をしていきます。

## Linter
スタイルガイドに沿わない汚いコードを怒ってほしい！のでlinterをいれます。

こんな感じ
<img width="465" alt="Pasted_Image_2019_07_11_22_29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38634/1b9dc860-b26d-a83c-a874-b012566c081b.png">
linterは [rubocop](https://github.com/rubocop-hq/rubocop) にしました。
まずgemをグローバルインストールします。

```bash
$ gem install rubocop
```
デフォルトではlinterはオフになっているので、 VSCodeの `settings.json` で設定を書き加えます。

```json:settings.json
"ruby.lint": {
  "rubocop": true
},
```
<details>
<summary>`settings.json` の開き方 </summary>
`⌘+,` でGUIの設定画面を開き、右上のカッコ記号をクリックで切り替えられます
<img width="155" alt="Settings_—_cl-bandai-brappers.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38634/eb4f299a-5bee-ddeb-5377-ea7be733d1fc.png">
</details>

以上！

もしエラーがでてたらVSCodeを再起動orリロードするか、それでもだめならパスの問題かもしれないです。
[\[Mac\]VScode で ruby\-rubocop が動かなくなったら executePath を設定してみよう \- Qiita](https://qiita.com/tommy_aka_jps/items/ca7ae36717b69a7e390b)

より詳しい設定をしたい場合は、 `.rubocop.yml` ファイルに書いていきます。
[RuboCopの設定アレコレ \- Qiita](https://qiita.com/necojackarc/items/8bc16092bbc69f17a16d)

## Formatting
手動でインデント揃える鬼畜作業はしたくないので、
ファイルを保存したときに自動一括整形するようにします。
formatterは最初rufoを入れてましたが、[シングルクオート設定ができない](https://github.com/ruby-formatter/rufo/issues/103)みたいだったのでこちらもrubocopを使います。

```json:settings.json
"[ruby]": {
  "editor.formatOnSave": true
},
"ruby.format": "rubocop",
"editor.formatOnSaveTimeout": 5000
```

RubyのREADMEにはタイムアウト時間を1500にしてねと書いてありますが、
1500だと足りないみたいです（ここではまったw）
cf. [visual studio code \- vscode\( vscode\-ruby \+ rubocop \) how to auto correct on save? \- Stack Overflow](https://stackoverflow.com/questions/48030698/vscode-vscode-ruby-rubocop-how-to-auto-correct-on-save)

あとは拡張機能から 「endwise」 も入れておけばひとまず満足しました。
物足りなくなってきたらまた拡張していこうと思います :smiley:
二段階認証が話題になってたので調べた

## 意外と知らない二段階認証（自分も明確には知らなかった）
[7payがやらかした](https://www.itmedia.co.jp/news/articles/1907/08/news055.html)ことを発端に二段階認証が話題になってますが、そもそも二段階認証のことを正確に知らない人って僕含めて多いと思うんですよ。なので調べてみました

## セキュリティの要素
セキュリティの要素は大きく分類して４種類だそうです
・知る要素
・持つ要素
・備える要素
・場所の要素

一つ一つ見ていきましょう

### 知る要素
いわゆる「パスワード」や「暗証番号」です。
自分が「何を知っているか」がキーになります。

### 持つ要素
アナログなものだと「家の鍵」がこれにあたります。
自分が「どんな物を持っているか」がキーになります。
少し意外かもしれませんが、パスワードが書かれた紙なんかもこれにあたるそうです。

### 備える要素
「指紋」や「目の光彩」がこれにあたります。
自分が「どんな特徴を持ってるか」がキーになります（自分はこういう解釈をしてますが、間違ってるかもしれません……）
筆跡やタイピング認証（タイピング時間など個人特有の癖）なんかもこれにあたります。

ツイッターで見かけたアンケート問題（ソースが欲しいけど検索しても出てこないorz）で取り上げていたのは上記３つなのですが、もう一つあるようです。

### 場所の要素
「自分がどこにいるか」がキーになるようです。
登録されているGPS情報や、IPアドレスなどがこれにあたるようですね。

##要素を掛け合わせる
・知る要素
・持つ要素
・備える要素
・場所の要素
これら４つを組み合わせてセキュリティの強度を上げていくことが二要素認証です。

自分なりに例を挙げてみたいと思います。

####知る要素×持つ要素
・自分の好きなものの合言葉（知る要素）を入力した後、持っているカードキー（持つ要素）を使ってロックを解除する

####知る要素×備える要素
・パスワード（知る要素）を入力した後、静脈認証（備える要素）を行ってロックを解除する。

##二段階認証≠二要素認証
ところで自分自身も完全に勘違いしていたのですが、二段階認証と二要素認証は違うものです。

簡単に言うと
二段階認証：同じ要素を使って認証を行う
二要素認証：違う要素を使って認証を行う

具体例を出すと
「パスワードを入力した後、暗証番号４桁を入力する」のが二段階認証で、
「パスワードを入力した後、カードキーを使う」のが二要素認証です。

[こちらのサイト](https://www.segunabe.com/2018/08/31/passclipnews180831/)の方が詳しいかと思いますので、ぜひ見て頂ければと思います。

#まとめ
・セキュリティの要素は４つ（知る、持つ、備える、場所）
・二段階認証と二要素認証は別物

7payに限りませんが、お金絡みや情報絡みのセキュリティって大事ですね……
【Rails】ログイン機能について

sessionを使用したrailsのログイン機能についてのメモです。

##ログイン機能の概要

sessionにユーザの情報があるかどうかを判断します。

sessionにユーザの情報が無い場合
→サインイン(ユーザ登録画面)へ
sessionにユーザの情報がある場合
→ログイン後のページを表示

というのがログイン機能基本的な流れかなと思います。

railsでは、sessionにユーザの情報を自動で暗号化して保持することができるので、こちらで考えることは少なくて済みます。

[ユーザ登録](https://qiita.com/gussan-dayo/items/d4bf9e2e047c020e70d9)について簡単にあとめた記事も公開しているので、参考にしてください。

##コントローラ

ログイン機能で実装するのは、new,create,destroyのアクションです。

下記のコードがログイン機能のコントローラです。

```session.rb
class SessionsController < ApplicationController
  def new
  end

  def create
    email = params[:session][:email].downcase
    password = params[:session][:password]
    if login(email, password)
      flash[:success] = 'ログインにしました'
      redirect_to @user
    else
      flash.now[:danger] = 'ログインに失敗しました'
      render 'new'
    end
  end

  def destroy
    session[:user_id] = nil
    flash[:success] = 'ログアウトしました'
    redirect_to root_url
  end

  private

  def login(email, password)
    @user = User.find_by(email: email)
    if @user && @user.authenticate(password)
      session[:user_id] = @user.id
      return true
    else
      return false
    end
  end
end
```

createアクションでは、ログインに成功すると、ユーザの詳細画面へ、ログインに失敗すればもう一度ログイン画面へとページ移行するようになっています。

login(email, password)では、入力されたemailとpasswordを引数に取り、ユーザが登録しているかどうかの確認を行っています。

##view画面

ログイン画面です。CSSを適用していない最低限の画面です。笑

```index.html
<%= form_for(:session, url: login_path) do |f| %>
    
    <div class="form-group">
        <%= f.label :email, 'Email' %>
        <%= f.email_field :email, class: 'form-control' %>
    </div>

    <div class="form-group">
        <%= f.label :password, 'Password' %>
        <%= f.password_field :password, class: 'form-control' %>
    </div>

    <%= f.submit 'Log in', class: 'btn btn-primary btn-block' %>
<% end %>

<p>New user? <%= link_to 'サインアップ画面', signup_path %></p>
```

超見にくいですが、最低限のログイン画面です。
サインアップ画面は、[ユーザ登録](https://qiita.com/gussan-dayo/items/d4bf9e2e047c020e70d9)に記述してあります。


![スクリーンショット (45).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203857/e3ae6263-08b9-cd67-bbef-07646c0a9259.png)


ログイン後の画面ですが、
下記のコードの中にログイン後に表示したいコードを記述します。

```
<% if logged_in? %>

ログイン後に表示したいコード

<% end %>
```

##ログイン要求画面
ユーザがログインしていない場合に、ログインを要求する機能です。

アプリケーションコントローラに実装し、どのコントローラからでも呼び出せるようにします。

```application_controller.rb
class ApplicationController < ActionController::Base

    def require_user_logged_in
        unless logged_in?
            redirect_to login_url
        end
    end

    def current_user
        @current_user ||= User.find_by(id: session[:user_id])
    end

    def logged_in?
        !!current_user
    end

end
```
require_user_logged_inによって、ユーザがログインしているかどうか判別するコードです。
アプリケーションコントローラに記述しているので、ほかのコントローラでも呼び出すことが出来ます
before_actioの中に記述するのがスマートです。

```
before_action :require_user_logged_in, only: [:index, :show]
```

以上です！これでログイン機能が実装できているはず！
プロデルでネ申Excel作成を自動化したい フォントサイズ編 #0

##その後
　[プロデルでネ申Excel作成を自動化したい #2](https://qiita.com/shukvaal/items/ddaadaa191c5e199712b)をベースにアプリを１本作りました。すでに導入している拙作の日誌アプリのデータベースファイルから、利用者の諸々のデータを読み出して予定表のxlsxファイルに書き出すものです。日誌アプリは過去だけでなく未来の内容についても入力できるようにしてあるので、スケジュールが確定したら日誌アプリでデータ入力（GUIでさくさく行えます）→件のアプリでxlsxファイルを出力という業務の流れにすれば、大幅な労力削減になります。
　早速、依頼者とその部署のスタッフに見せたところ、何か妙な反応でした。Excel上で解決するものと思い込んでいたようで、Excelが一度も画面に現れることなくxlsxファイルがデスクトップに出現する光景が理解不能で、いささか面食らったようです。多分これはお流れになるだろうと思っていたところ、一週間ばかり経ってから依頼者よりあのアプリを導入したいと。ただし、追加の要望があって、多くの利用者が参加する日は予定表の枠に名前が入りきらないので、**自動でフォントサイズを調整できないかと**。今度は私が面食らいました。上長の『調整』もあったのでしょうが、毒を食らわば皿まで、とばかりに自動化の話に大胆に乗って来たのでしょう。正直言うと、書式設定をいじるのは大変ややこしそうなので、自動出力で足らない部分は手作業で修正してほしかったのですが、そうならこちらも毒を食らわば皿まで、やることにしました。
##.xlsxファイルのセルのフォントサイズを書き換えるには？
　実際大変めんどくさかったのです。https://p-space.jp/index.php/development/open-xml-sdk をざっと参考にした限りでは、xl/worksheets/sheet1.xmlが参照しているxl/styles.xmlのフォント定義のサイズ部分だけ書き直すだけ良さそうに思えたのですが、xlsxファイルを何パターンか作ってみて、複数のセルが同じフォント定義やセルの書式定義を参照しているらしいことが分かりました。ということは、参照されているフォント定義とセルの書式定義(それぞれstyles.xmlのstyleSheet/fonts/font要素とstyleSheet/cellXfs/xf要素)のコピーを作ってそのフォントサイズを変え、参照元のインデックス番号も書き換えることになります。
　また、もともとがセルに入っている記号をもとにセルの場所を特定する仕組みのアプリですので、処理の流れとしては、xl/sharedString.xmlの文字列を入れている要素のインデックスからsheet1.xml内の参照元を探し、そこからようやくフォント定義やセル定義に辿り着けるのです。整理しながら進めないと参照関係がごちゃごちゃになりそうです。というか、プロデルで要素のコピーとかどうすんのよ！？いささか途方に暮れました。

[～続く～](https://qiita.com/shukvaal/items/7c84184d995f075a4649)
Unity内のファイルやHierarchyの名前を一括で変更してくれるEz Rename.の紹介

#はじめに
VCI(Virtual Cast Interactive)の作成時に、各GameObjectの名前やMaterial、Audioの名前の付け方を統一したりインクリメント形式で付けると、luaスクリプトで操作する際に取り回しがしやすい事が多いです。
ということで、今回はファイル名やHierarchyの名前を一括で変更することのできるEz Rename.というアセットの使い方を解説していきたいと思います。
こんなアセットです。
![EzReNameRename.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/1b47bcf4-f1ef-a3bf-b563-4608117f57b7.gif)
#1. Ez Rename.のダウンロード・インポート
まず、Ez Rename.をダウンロード・インポートする必要があります。
UnityのAsset Store内でダウンロード・インポートを行ってください。
Unityのアセットストアの使い方については下記サイトを参考にしてください。
[Unityのアセットストア（AssetStore）を使う方法【初心者向け】](https://techacademy.jp/magazine/2222)
下記動画Gifのように検索をかけると出てきますので、それのダウンロード・インポートボタンを押してImportしてください。
![EzReNameInstall.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/459750fa-e919-e412-728e-a38d18f599b1.gif)

#2. Ez Rename.のウィンドウの表示
`Window`メニューから`Ez Rename`を選択して、`Open`から、Ez Rename.のウィンドウを表示することができます。
こちらを使って名前の変更を行います。
![EzReNameOpenWindow.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/609b58cc-06ac-c962-4f53-76282c151902.gif)

#3.　Ez Rename.でできること。 
使い方についてはこちらに載っています。英語ですが。
[Ez Rename Guide](https://solomidgames.com/guides/ez-rename/quick-overview.html)
英語を読みたくない方向けに、ざっくりとした解説を記載します。

##Rename
・複数の名前の変更が一括でできます。
・赤い場所をクリックすると、現在選択している`GameObject`か`Asset`の名前をコピーできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/9c9d8853-e9a5-643a-13a4-8b8d761a5e83.png)
・`Hierarchy`ボタンを押せば、選択している`Hierarchy`の`GameObject`の名前を変更します。
・`Poject Folder`ボタンを押せば、選択している`Project`のファイルの名前を変更します。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。 
![EzReNameRename.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150633/1b47bcf4-f1ef-a3bf-b563-4608117f57b7.gif)
##Replace
・複数の選択している`GameObject`かファイルの名前を置換できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。
##Insert
・複数の選択している`GameObject`かファイルの名前に文字列を追加できます。
・先頭、最後尾、指定文字列目　を指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。
##Remove
・複数の選択している`GameObject`かファイルの名前を指定文字列分削除できます。
・先頭、最後尾、指定文字列目　を指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。
##Case Change
・複数の選択している`GameObject`かファイルの名前の英語の大文字・小文字を整形できます。
・全て大文字・先頭のみ大文字・全て小文字　のいずれかを指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。
##Sort
・複数の選択している`GameObject`かファイルの順番を入れ替える事ができます。
・昇順・降順　のいずれかを指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。
Pythonにおけるクラス定義の仕方まとめ1(クラス定義〜コンストラクタ、デストラクタ)

#概要
メモ代わりにPythonのクラス定義関連についてまとめていきます。

##クラス定義
* 下記は単純なクラス「Car」を定義し、それをローカルで呼び出しているコードです。
* ここでクラス内の関数「run」は**「メソッド」**と呼ばれます。
* ローカル変数myclassは、クラスという定義(概念)を具現化した**「オブジェクト」**を代入した変数です。
* この**「オブジェクト」**はたびたび**「インスタンス」**とも呼ばれます。
* ややこしいのですが、とりあえずPyhtonにおいては、**オブジェクト＝インスタンス**という考えで話を進めていきます。
* クラス定義内の「self」とは上記のインスタンスを指しています。


```Python:classtest1.py
# クラスの定義
class Car(object):
    def run(self):
        print('run')

# インスタンスを生成し、そのオブジェクトをローカル変数へ代入 
mycar = Car()
mycar.run()
```

ここでクラス定義の引数「object」は書かなくてもエラーにはなりません。

```python:classtest1.py
class Car(）:
```
ただ一般的には書いたほうが良いとされるそうです。
ちなみに、**「継承」**という機能を使う際には、ここに継承元となるクラス名を記述します。

##オブジェクトの初期化と破壊
* 下記ではクラスを初期化と破壊時の処理を追加しています。
* メソッド「\_\_init__」はオブジェクトが生成された時,最初に呼び出され初期化処理を行う特殊な関数です。これを**コンストラクタ**といいます。
* メソッド「\_\_del__」はオブジェクトが破壊された時,最初に呼び出され破壊時処理を行う特殊な関数です。これを**デストラクタ**といいます。
* **del [オブジェクト名]** と書くとオブジェクトを破壊できる。


```Python:classtest2.py
# クラスの定義
class Car(object):
    self.color
    # コンストラクタで初期化
    def __init__(self, color):
        self.color = color

    def run(self):
        print('run')

    # デストラクタで破壊時処理を設定
    def __del__(self):
        print("stop");


# インスタンスを生成し、そのオブジェクトをローカル変数へ代入
# コンストラクタが呼ばれオブジェクトが初期化される 
mycar = Car('red')

# 初期化によって設定したデータを表示
print(mycar.color)

# オブジェクトを破壊。デストラクタが呼ばれる
del mycar

```
* オブジェクトが生成された際に**mycar**の「color」に「red」というデータが設定されます。
* オブジェクトが破壊された際に「stop」と表示されます。


###つづく
JavaScriptの基礎～クリックしたとき⇒色を変える など

#JavaScripの基礎
コピペして使ってください。
###クリックしたとき⇒色を変える
```javascript:sample.js
//要素の取得 → クリックされたとき
document.getElementById('target').addEventListener('click',function(){
  //要素の取得 → 背景色を変える
  document.getElementById('target').style.background='pink';
});
```
###その他の処理
```javascript:sample.js
//クリックしたとき⇒クラスを追加する
document.getElementById('target').classList.add('circle');
//クリックしたとき⇒クラスがついていたら外す、外れていたらつける
document.getElementById('target').classList.toggle('circle');
```
HTML で 文字 を 入力する 欄 を表示する ～HTML input text-area～

# 目的
- HTMLの画面に文字を入力する欄の表示を行う方法をまとめる

# 押さえるポイント
- 一行の入力欄を表示させる時はinputタグ使用する
- 複数行の入力欄を表示させる時はtext-areaタグを使用する
- お問い合わせフォームの作成などで送信ボタンを設置するときはinputタグでtype属性にてsubmitを指定する。
送信ボタンは何も設定しないとボタン部分に「送信」と表示される。任意の文字を表示させたい時はvalue属性にて表示させたい文言を与える

# 書き方の例
- 下記にHTMLファイルの内容を記載する。

``` html
<!-- 一行の入力欄を表示する -->
<input>

<!-- 複数行の入力欄を表示する -->
<text-area></text-area>

<!-- 送信ボタンを表示する -->
<input type="submit">
```

# より具体的な例
- 企業webサイトによくある問い合わせ用フォームを作成する。
- 返信用メールアドレスを記入する欄を作成する。
- 問い合わせ主の名前を入力する欄を作成する。
- 問い合わせ内容を入力する欄を作成する。
- 送信ボタンを作成する。
※返信用メールアドレスと問い合わせ主の名前の入力欄は一行の入力欄とする。
※問い合わせ内容の入力欄は複数行の入力が可能な入力欄とする。
※各入力欄の上に入力欄の概要を記載する

- 下記にHTMLファイルの内容を記載する。

``` html
<p>返信用メールアドレス(必須)</p>
<input　class="mail">

<p>お名前(必須)</p>
<input class="name">

<p>お問い合わせ内容</P>
<text-area></text-area>

<input type="submit">
```
Macbookでアンダースキャンが治らないときの対処法

先日MacBookをふとデュアルスクリーンにしたいと思いディスプレイに繋いだのですがなんか黒い枠がずっと出てる...
なんだこれ。という訳で色々調べて解決方法が見つかったのでメモ。

#結論
Terminalで

```
sudo vi /private/var/db/.com.apple.iokit.graphics
```

と入力するとおそらく以下の様な項目が出るはずなので

```
<key> pscn </key> 
<integer> XXXX(10000以下の数字) </integer> 
```
<integer>タグの中の値を10000に変える。

#あとがき
いやーこんなんわからないですね。
地味に小一時間ハマりました。
あとvimはやっぱり慣れません。

参考URLは下記
https://discussions.apple.com/thread/7966665?page=2
HTML の 要素 に 下線 や 枠線 を つける ～CSS border border-bottom～

# 目的
- HTMLファイルの要素に下線や枠線をつける方法をまとめる。

# 押さえるポイント
- 下線や枠線をつけたい要素をCSSで指定してborderプロパティを用いて設定する。
- 線の太さ、種類、色をそれぞれ指定可能。
- 太さはピクセル数で設定する。
- 種類は線の名前で設定する。
- 色はカラーコードで設定する。

# 枠線をつけたい時の書き方の例
- 下記にCSSファイルの内容を記載する

``` css
要素の名前かクラス名 {
    border: 太さ 種類 カラーコード;
}
```

# 下線をつけたい時の書き方の例
- 下記にCSSファイルの内容を記載する

``` css
要素の名前かクラス名 {
    border-bottom: 太さ 種類 色;
}
```

# より具体的な例
h1要素に太さ5px、種類solid、色が赤の枠線をつける
p要素に太さ10px、種類solid、色が黒の下線をつける

〜サンプルコード〜
- 下記にHTMLファイルの内容を記載する。

``` html
<h1>おはようございます</h1>
<p>これは日本の挨拶です。</p>
```

- CSSで上記のHTMLファイルのh1タグとpタグに対して枠線と下線の設定をする。
- 下記にCSSファイルの内容を記載する。

``` css
h1 {
  border: 5px solid red;
}

p {
  border-bottom: 10px solid black;
}
```
HTML の 文章 の 一部だけ 文字の色を 変更する

# 目的
- HTMLファイルの文章の1部のみ文字の色を変更する方法をまとめる

# 押さえるポイント
- 変更したい文字をspanタグで囲みCSSで文字の色を設定する

# 書き方の例
- 下記にHTMLファイルの内容を記載する

``` html
<h1>おはよう<span>ございます</span></h1>
```

- CSSにて色を設定する
- 下記にCSSファイルの内容を記載する

``` css
span {
    color: カラーコード;
}
```

# より具体的な例
h1要素の｢おはようございます。｣の｢。｣を赤色に設定する。

〜サンプルコード〜
- 下記にHTMLファイルの内容を記載する。

``` html
<h1>おはようございます<span>。</span></h1>
```

- CSSで上記のHTMLファイルのspanタグに対して文字を赤色に設定する。
- 下記にCSSファイルの内容を記載する。

``` css
span {
  color: red;
}
```
firebase・vue.jsで作ったWebアプリにGoogle Analyticsを設定してみた。

#やること
先日作ったwebアプリ[reftika](https://testreftika.firebaseapp.com/)にGoogle Analyticsを設定する。

webアプリの詳細はこちらの記事を参照ください。
[<初心者>レファレンス協同データベースの記事をランダムに表示するWEBサービスをvue.jsで作りました。](https://qiita.com/Mmmkk/items/3951e56e737fb653a958)

#やったこと
vue-routerを使っている場合は、やることは2つだけでした。
1.[[Google Analytics]](https://analytics.google.com/analytics/web/)のページでアカウント作成
2.vue-analyticsの導入・設定

参考：
[Vue-SPAでもGoogle Analyticsしたい！](https://qiita.com/hirohero/items/0f29a89cd08b421ccfe1)
[Vue.jsのプロジェクトでGoogleAnalyticsの設置](https://ti-tomo-knowledge.hatenablog.com/entry/2018/06/21/111310)

#1.Google Analyticsのページでアカウント作成
[[Google Analytics]](https://analytics.google.com/analytics/web/)

#2.vue-analyticsのインストール・設定
[vue-analyticsのgithub](https://github.com/MatteoGabriele/vue-analytics)
##インストール

```
npm install vue-analytics -save
```

##設定
main.jsに追記

```main.js
import VueAnalytics from 'vue-analytics'

Vue.use(VueAnalytics, {
  id: 'UA-XXX-X'      ←google analyticsのID
})
```
ES5の書き方の場合はmain.jsは以下のようにする。

```main.js
const VueAnalytics = require('vue-analytics').default

Vue.use(VueAnalytics, {
  id: 'UA-XXX-X'      ←google analyticsのID
})
```

以上でGoogle Analyticsのページに反映されます。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89564/70a3714c-cc0f-7cfe-7d8e-5dca13683ecc.jpeg)

#その他
上記でも使っているVue.use()ってそもそも何なのかという初歩的なことがあいまいだったのでメモ。
・Vur.use()はプラグインを使用するために使用する。
・プラグインとはVueにグローバル・メソッドやグローバル・アセット、コンポーネントアクションなどを追加するもの。

参考：
[Vue.use( )を書く場合と書かない場合](https://qiita.com/fuqda/items/90073e3cd0987c82553d)
[公式ガイド-プラグイン](https://jp.vuejs.org/v2/guide/plugins)
SolidWorks API Part1

SolidworksはAPI(VBA)を書き綴っていく日記。

#SolidWorksAPI　導入編

SolidWorksにはデフォルトで、VBAの統合開発環境が入っています。
そのため、エクセルやプログラミング環境がなくてもAPIを利用してSolidworksを操作できます。

##●IDE環境について
SolidWorksでAPIを利用するには、
ツールバー＞ツール＞マクロ＞新規作成　からSWPファイルを作成し、プログラムを記述していきます。

[初期画面]

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407033/bc9b1efd-36c6-e4bf-4456-70c6a3170e35.png)

初期画面では、
```Set swApp = Application.SldWorks```と記述しています。
こののようにIDEにあるオブジェクトを参照し、APIを利用することができますが、私は、ここを書き換えて、
**Set swApp = CreateObject("Sldworks.Application")**
または、
**Set swApp = GetObject(,"Sldworks.Application")**
としています。

SWPファイルで作成する場合は、必ずSolidWorksを立ち上げていますので、GetObjectでオブジェクト参照を行うのが適切と思います。

##●ModelDoc2(モデル情報の取得)
今回は、立ち上げているモデルをの情報を取得するプログラムを作成します。

``````
Sub main()
Dim swApp As SldWorks.SldWorks
Dim swModel As ModelDoc2
Set swApp = GetObject(, "Sldworks.Application")
Set swModel = swApp.ActiveDoc
End Sub
``````

このように**ActiveDoc**メソッドを使用することで、開いているモデルの情報をセットすることができます。

ここで**GetPathName**メソッドを使用すると、開いているモデルの保存パス名を取得することができます。

``````
MsgBox swModel.GetPathName
``````

↓このように、モデルパスが表示されます。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407033/fcfaf99a-908b-9d8d-edd3-67e608fe1da6.png)


###(ModelDoc2)非常に多様されるメソッド
ModelDoc2は、モデル上の情報を取得するために非常に多様される万能メソッドです。
すべての起点になると言っても過言ではありません。
例えば、Treeアイテムの情報を取得して、Suppressedメソッドで、抑制された部材なのかをチェックできます。

##●DesignTableについて
SolidWorkの肝ともいえば、MSのExcelベースで、モデルのパラメータを制御したり、コンフィギュレーションを制御できる**DesignTable**の機能です。

DesignTableを利用するには以下の記述で、設計テーブルのオブジェクトを取得することができます。

``````
Sub main()
Dim swApp As SldWorks.SldWorks
Dim swModel As ModelDoc2
Dim swDesignTable As DesignTable
Set swApp = GetObject(, "Sldworks.Application")
Set swModel = swApp.ActiveDoc
Set swDesignTable = swModel.GetDesignTable
End Sub
``````

このように、**ModelDoc2からDesignTable**を取得できます。

DesignTableは、モデルにパラメータを反映するには、DesignTableを開き、パラメータをDesignTableのエクセルで編集し、そのあと閉じる必要があります。

その記述を追加すると以下のようにになります。

``````
Sub main()
Dim swApp As SldWorks.SldWorks
Dim swModel As ModelDoc2
Dim swDesignTable As DesignTable

Set swApp = GetObject(, "Sldworks.Application")
Set swModel = swApp.ActiveDoc
Set swDesignTable = swModel.GetDesignTable

’設計テーブルを開く
Call swDesignTable.EditTable2(False)

’***************************************
’ここにエクセルのセルを変更する記述を入れる
’***************************************

’設計テーブルを閉じる
Call swDesignTable.UpdateTable(swUpdateDesignTableAll, True)

End Sub
``````

この**EditTable2**メソッドでは、引数で新しいウィンドウで開くかどうかを指示することができます。

今回はFalseで設定しましたので、モデルビュー内でエクセルが開かれます。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407033/48cc0471-0d49-ea94-2cb8-e30cc7c334ad.png)

**UpdateTable**メソッドは、開いているDesignTableのパラメータをモデルに反映できる記述です。

第1引数では、**swUpdateDesignTableAll**を指定します。
(通常は、**swUpdateDesignTableAll**以外は使うことはないと思います。)

第2引数は、DesignTableを閉じるかどうかを設定できます。
(通常は、閉じるのは通例ですので、True以外は設定しないのが基本です。)

今回はここまで:coffee:
【PHP】公式リファレンスをすんなり読るようになれば、一気に学習が進む説【初心者】


PHP学習を進めるにあたり、よく使う参考資料は何か？と言われたら公式リファレンスが思いつくことだろう。

＞[PHP公式リファレンス](https://www.php.net/manual/ja/index.php)

**とはいえこのサイト、初心者にとっては中々使いにくい。**

#初心者に公式リファレンスが使いにくい理由


何故使いにくいのかと言えば、その専門的な言葉使いが原因だ。
公式リファレンスは容赦なく専門用語が飛び出す。まるで少し難しい用語を調べた時に出て来るwikipediaみたいに…。

初心者相手に書くとなればそれ相応の優しい言い回しをする事になるが、公式リファレンスという立場上砕け過ぎた表現は許されない。

なので、結局初心者は他の解りやすい解説のサイトを使って関数の使い方等を学んで…といった事をしてしまう人も多くいると思うのだが、逆にこう考えてみると学習が一気に進むのでは？と思いついた。

**「公式リファレンスを見て出て来る専門用語を理解できていれば、PHPの学習効率が高まるうえ用語も覚えられて一石二鳥なのでは？」**

##公式リファレンスから知らない単語を抽出して語彙力を伸ばそう(提案)

公式リファレンスでも小難しいwikipediaでも中身が解らない理由はただ１つ。
語彙力が無いからだ。
書いてある言葉をちゃんと理解できているのなら、そもそも理解できるのであれば問題になることはない。

逆にいえば公式リファレンスで触れられた言葉をマスターして説明書をみただけで何をどうすればよいのか解る人は、その時点でPHPに関する知識を十分に蓄えた人に自動的になれるとも言えるのではないだろうか？

#まとめ

・公式リファレンスになじめる努力をしてみよう。
・"知らない"を"お堅い説明書"から抽出して自身の語彙力を伸ばそう。
SSM Session ManagerのSSHをWindowsで使う方法

SSM Session Managerで待望のSSHが使える様になりましたね！　めでたい！
しかし、公式マニュアルにはどうやらLinuxやMacでの設定方法しか書いてないので、Windowsでも簡単に使う方法を検証しました。
[料金も無料][price]だし、[アクセス先制限][deny]もできるしもう使うしか無いですね！！

## 前提条件
* windows 10
* EC2インスタンスはSSMが使える様エージェント、ロール設定済み

## インストール
たったの3ステップ！
1. AWS CLIインストール
    [公式][cli-doc]にあるとおりインストーラーをダウンロードしてきてインストールする。  
    ```https://s3.amazonaws.com/aws-cli/AWSCLISetup.exe```  
2. Session Manager Pluginインストール
    [公式][plugin-doc]にあるとおりインストーラーをダウンロードしてきてインストールする。  
    ```https://s3.amazonaws.com/session-manager-downloads/plugin/latest/windows /SessionManagerPluginSetup.exe```  
3. SSHの設定を追加する。
    Windowsの場合、```C:\Users\【UserName】\.ssh\config```に以下を追加、もしくは追記する。

```text:config
    # SSH over Session Manager
    host i-* mi-*
        ProxyCommand C:\Program Files\Amazon\AWSCLI\bin\aws.exe ssm start-session 【--profile あれば】 --target %h --document-name AWS-StartSSHSession --parameters "portNumber=%p"
```

オリジナルとの違いは```sh -c```が無くなって```aws```がフルパス、```portNumber```のシングルクォーテーションからダブルクォーテーションへ変更  
AWS CLIでプロファイル使っているときはここで入れておく

完了！


## 参考文献
* [AWS Systems Manager セッションマネージャーでSSH・SCPできるようになりました ｜ DevelopersIO](https://dev.classmethod.jp/cloud/aws/session-manager-launches-tunneling-support-for-ssh-and-scp/)
* [Windows に AWS CLI をインストールする - AWS Command Line Interface][cli-doc]
* [(オプション) AWS CLI 用の Session Manager Plugin をインストールする - AWS Systems Manager][plugin-doc]
* [Step 7: (Optional) Enable SSH Session Manager Sessions - AWS Systems Manager ](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html)
* [料金 - AWS Systems Manager | AWS][price]
* [特定 EC2 インスタンスには、SSM セッションログインさせたくないんや ｜ DevelopersIO][deny]
* [Proxy下のWindows10でOpenSSHする - Qiita](https://qiita.com/M11/items/8f3caf19a3911c4449fe)

### 補足
接続に使う秘密鍵は接続先対象EC2に設定しているそのもの
呼び方はSession Manager for SSHとかでよいのだろうか？
#### 端末とAWS間の通信方法
StreamUrlとして以下がAWS CLIのコマンド応答として返却されているためWebSocket（wss）でつながっている。

```
wss://ssmmessages.ap-northeast-1.amazonaws.com/v1/data-channel/【IAMユーザー名を含むランダム列】?role=publish_subscribe
```

#### AWS CLIをその他の場所にインストールしていた場合にAWSコマンドの場所を調べる

```
where aws
```


[deny]:https://dev.classmethod.jp/cloud/aws/deny-session-manager/
[cli-doc]:https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-windows.html
[plugin-doc]:https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html#install-plugin-windows
[price]:https://aws.amazon.com/jp/systems-manager/pricing/#Session_Manager
AWSを使ってみる③

# 作成したインスタンスの確認

![aws_dlna_000018.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391995/75eca2b2-464d-da14-1533-be6d69669dba.jpeg)
**うん、ある！**

画面下部に詳細が色々書かれてるので確認しましょう。（画像ではカットしてます）

# TeraTermでアクセス
早速ユーザと秘密鍵ファイルを指定して接ぞｋ……ん？

```Teraterm.exe
Please login as the user "centos" rather than the user "root".
```

rootでログインすんなって言われました。
そりゃそうだよね。

改めてcentosユーザでログイン

![aws_dlna_000020.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391995/50e9f954-99d4-4ae7-9df1-a124ded1bfa4.jpeg)

無事にログインできましたね。

# 初期設定
ここまでくれば後は簡単ですね。
ささっと初期の設定の確認と修正をしていきましょう。

作業的には下記の通りぐらいですね。
- rootパスワード設定
- 個人ユーザの作成
- sshの設定確認
- 起動プロセスの確認
- プロセスの確認
- cloud-initの設定確認

よーし特に問題ない。apacheいれ……ん？

```
# ip a
 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc pfifo_fast state UP group default qlen 1000
     link/ether 06:7f:b5:4b:44:12 brd ff:ff:ff:ff:ff:ff
     inet 172.31.47.185/20 brd 172.31.47.255 scope global dynamic eth0
        valid_lft 3106sec preferred_lft 3106sec
     inet6 fe80::47f:b5ff:fe4b:4412/64 scope link 
        valid_lft forever preferred_lft forever

```

なんかIPが想定してたのと違う……

# プライベートIPアドレスが想定していたものと違かった
インスタンスの情報を見たところ、作成時に作成したVPCのIDが違いました。
なんでやーと思って作業ログがてら取ってたスクリーンショットを見たところ

![aws_dlna_000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391995/641bf4a0-b1b4-3bc6-07c4-3beb8d5bb107.jpeg)

インスタンス作成時にVPCを正しく指定してませんでした。

**(・ω<) てへぺろ**
みんなはちゃんと指差し確認しようね！

次回環境を作るときは気を付けます。

ElasticIPでグローバルIP取得し、IPを固定化したところで今回はここまで

次回はApacheとPHPとmysql導入
[AWSを使ってみる④](https://qiita.com/tktk0601/items/0e1ce862325c1a7ef9b7)
コンテナからプロセスID（pid）を確認する


`docker inspect [container ID]`で確認できる。


## 検証

1. コンテナを二つ立ち上げる

```sh
$ docker run --name alpine_test -itd alpine
148c39d151fab8861c2527a15b13d1a613f9bfa02b0a8b1284b64e82f9f2dff2
```

```sh
$ docker run --name alpine_test_2 -itd alpine
e7f8a6a77b2a03928b68e3256c75f01a45b058ffadeaa243aef9a70dc12a1381
```

```sh
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
148c39d151fa        alpine              "/bin/sh"           3 seconds ago       Up 1 second                             alpine_test
40e81cafeafd        alpine              "/bin/sh"           About an hour ago   Up About an hour                        alpine_test_2
```

2. 立ち上げたコンテナのプロセスIDを確認する

```sh
ps aux | grep "/bin/sh"
PID   USER     TIME  COMMAND
  216 root      0:00 /bin/sh
  406 root      0:00 /bin/sh
  526 root      0:00 grep bin/sh
```

216, 406のプロセスがどのコンテナに割り当たっているのか、プロセスIDだけ見ても分からない。

3. コンテナの情報を取得する

```sh
$ docker inspect alpine_test | grep Pid
            "Pid": 406,
            "PidMode": "",
            "PidsLimit": 0,
```

`Pid`が、プロセスID。
Singularity を共有計算機環境でつかうときのTIPS

# 概要

Singularity を使える環境で、docker からのイメージ変換でエラーがでた。

# 結論

メモリが足りないことが原因の可能性がある。
共有計算機環境でノードにログインするときに、メモリの量をふやしてみると変換できる。

## 例

- 遺伝研
Firebase信者になった話

# Firebase信者になった話
Cloud Firestoreのオフラインサポートが欲しくてFirebaseについて調べていったところ、
Firebase信者になったので感動したポイントをまとめます。

## TL;DR
* サーバーレス構成で行くならAWSで組むよりはるかに楽
* AWSは非常に汎用的に作ってあるが、プレーンな機能が多いので本来的ではない設定作業が多くなる。
* Firebaseは各サービスがストレスなく連携出来て、設定も最小限

## Firebase系サービスの連携がとても楽
Firebaseでは下に紐づいているAuthentification、Hosting、Firestore、cloudFunctionと言った機能の連携が非常に優秀です。

### AuthentificationとFirestore,CloudStorage for Firebaseの連携
firebase cliから一括して管理が出来ますし、Authの権限情報をFirestoreやCloud Storageに適用するセキュリティルール上でそのまま読み込むことが可能です。
参考:https://firebase.google.com/docs/firestore/security/get-started?hl=ja
同じことをAWS上のサービス(CognitoやS3、DynamoDB)で実装しようとすると、
サーバー上の処理やLambdaによる権限判定ロジックを自前で用意しなければいけません。
細かい権限のグループ分けについてもカスタムクレームでかなりの部分カバーできます。(課金ユーザーとそれ以外の区別や特定のグループ限定など)
参考:https://firebase.google.com/docs/auth/admin/custom-claims?hl=ja)
しかも、Coginitoのカスタム属性に比べて圧倒的に使いやすいです。

### cloud functionとの連携
同様に、cloudFunction上で認証情報を参照するのも簡単にできます。
AwsLambdaとCognitoを連携させる場合自分でtokenを取得してLambdaに送り検証を行う必要がありますが、
cloudFunctionの場合SDK経由呼び出しにするだけでライブラリ内で自動でトークン検証まで内部でやってくれます。
参考:https://firebase.google.com/docs/functions/callable?hl=ja

## UIが全体的に親切
これは私見ですがAWS系の管理UIはサービスごとに統一されていない部分も多い上、
サービス一覧もとにかく大量に並んでいて、事前にしっかりと勉強した上でないとどれを使っていいかもわかりません。
一方で、Firebaseはサーバーレスなシステムを作ることに特化して必要な部分だけダッシュボードに並べてくれていますし、
そのためのドキュメントも綺麗に公式で作られています。

## 基本的にフルマネージド
フルマネージドサービスなので、どのレイヤーもスケーリングについて心配する必要はほぼありません。
(まったく意識しないとさすがにお金の面の心配があるかも知れません)
インフラ側までなかなか手の回らないスタートアップの場合これは非常にありがたいです。

## 銀の弾丸か？
当然ながらそういうわけではありません。
例えば、FirestoreはNoSQLで単なるKeyValueよりはマシにしてもJoinを伴う複雑なクエリが要るようなシステムには不適切です。
また、仕様上クライアントで行うとまずい処理(課金系だったりとか厳密な排他制御が要る場合)が多いシステムの場合あまりメリットは得られません。
あるいは、セキュリティルールだけではカバーできない複雑な権限管理がある場合にも厳しいです。
おそらく、業務系システムには適用しても大体ダメでしょう。

逆に、
* クライアント側で行ってはいけない処理が少ない
* データ構造はあまり複雑ではない
* オフライン状態でもある程度動く必要がある
* 厳密な排他制御や同期は不要

と言ったシステムの場合、非常に刺さります。

## まとめ
使いどころは選ぶけれども、Firebaseはいいぞ。
biocontainers の特定のバージョンの trim_galore --fastqc で処理が止まる問題

# 概要

--fastqc オプションがないと、正しくおわる
--fastqc オプションをとめると、処理が止まる。落ちるわけではない

# 結論

以下の解決策のとり方がある。

[BioContainers の検索はこちらからできます。](https://biocontainers.pro/#/registry)

- biocontainers であれば、新しいバージョンがあるかを調べる。
- 同じバージョンでも、最後の番号が新しいとなおっているかもしれない
- なければ、自分でつくるか、他の人が作ったコンテナを探すという手がある。

なにか変更したら、期待通りに動くことを確認すること。
少ししかバージョンが変わっていなくても、出力がかわることがあるため。

# 参考

似たような問題で、biocontainersの特定バージョンの、picardで似たようなことがあった。
これも、少し新しいバージョンのものを使うことで解決した。

## 他のバージョンに解決済みだが、バージョンによっては、期待通りに動かないことがあったもの。

- fastp
- picard
- trim_galore
CounterFactual Machine Learning勉強会 #1 勉強会メモ

# 概要

[CounterFactual Machine Learning勉強会 #1](https://connpass.com/event/128714/)

> 近年因果推論の知識を機械学習に応用したり、逆に因果推論の為に機械学習を応用するといった方法論が提案されています。 この勉強会はCounterfactual Machine Learningと呼ばれるこれらの手法に関する研究や実例の紹介を行う事を目的としたものです。


# 発表内容

## [CFMLの概要と研究動向](https://speakerdeck.com/kazk1018/cfml-number-1-introduction)

- Counterfactual Machine learning
    - 反事実が生じるデータを用いた機械学習

- Interative LeaningとCasual Inferenceが共変量シフトの部分問題

- 問題設定 intereactive leaning
    - 複数の候補の中から単一のアイテムをユーザに推薦し、ユーザからフィードバックを得る問題を考える
    - ユーザの情報から商品を決定するための方策(Policy)について考える
        - Policyを評価したい
        - 既存のログから新しいPolicyを学習したい

- 評価について
    - オンライン評価(A/Bテスト)
        - 正確な比較を行うことが可能
        - 結果が出るまでに時間がかかる
        - 開発側のコストが高い

    - オフライン評価
        - 既存のログから新しいPolicyを評価する
        - 実際に見せていない商品を選択する際は評価できない(Counterfactua: (反事実)
        - 学習は評価値が最大になる方策を探す


- Interactive Learning
    - 入力：コンテキスト
    - 方策に従ってアクションを決定
    - アクションに基づいて報酬が得られる

    - 関連
        - Recommendation
        - Contextual bandit
        - Reinforcement Learning

- Causal Inference
    - ある薬を患者に投下するか(treatment)で、3日後に病気が治ったかどうかの因果関係を測りたい
    - 実際に観測するのはどちらか一方のみ（因果推論の根本問題）

- 共変量シフト
    - 異なる分布の入力だが(p(x)=p'(x))、予測したい関数・確率が一致する(p(y|x)=p'(y|x))
        - 例: xが画像データ、yが人物、p(x)が室内の画像データの分布、p'(x)が屋外の画像データの分布
    - 共変量シフト下の予測モデルは、入力密度の密度比を用いることで学習可能

- 共変量シフトとの関係
    - Dの生成過程に、観測があるかどうかの違い(pとP')
    - Dの生成過程に、treatmentがあるかどうかの違い(pとP')

- 動向
    - Criteo Ad Placement Challenge
        - Counterfactualを扱った機械学習のコンペティション
        - 世界最大のDSPのCriteoがデータセットを公開
        - 広告配置予測にCounterfactualを考慮した評価指標を導入
    - KDD, NIPS, RecSysなどでワークショップ


## [バンディットと因果推論](https://speakerdeck.com/housecat442/bandeitutotoyin-guo-tui-lun)

※私の事前知識が不足しており、発表の意図をあまり汲み取れてなかったので、最低限の掲載に留める

- Off-Plicy Evaluation
    - Policyの実装は大変 & 微妙なPolicyを投入するリスク & 検証時間の限界
    - なるべくABテストせずに、オフライン検証したい
    - ログ上では評価できないCounterfactualをどうやって評価するか
    - 評価時に傾向スコアの逆数で重みづけ(IPS: Inverce Propensity Score)

    - そのほかDoubly Robust, More Robust Doubly Robust(MRDR)


## [因果推論で推薦システムを問い直す](https://speakerdeck.com/usaito/yin-guo-tui-lun-detui-jian-sisutemuwowen-izhi-su-at-cfmlmian-qiang-hui-number-1)

- Recommendation × Causality 界隈
    - 情報検索・検索のトップカンファレンスで高く評価されている
        - [Offline A/B testing for Recommender Systems](https://arxiv.org/abs/1801.07030)
        - [Causal Embeddings for Recommendation](https://arxiv.org/abs/1706.07639)
    - 推薦周りのトレンドの1つ
        - [Recent Trends in Personalization: A Netflix Perspective](https://www.slideshare.net/justinbasilico/recent-trends-in-personalization-a-netflix-perspective)

- フィードバックループに起因する推薦システムの問題
    - ログデータに対してよく予測できるPolicyを良しとするシステム
    - 観測されるデータは過去の方策に依存する

        - ログ上では、ユーザ×アイテムの観測数に偏りがある
        - 単純なMAEによる評価では、観測数が多い組み合わせを当てられるモデルが高い評価になるバイアスが発生する

    - 新規のユーザ×アイテムの組み合わせは？

- 分布の偏り
    - 推薦されるアイテムの観測数
    - 真のRating分布と観測されるRating分布の乖離

- 因果推論と推薦システム
    - 推薦システムで観測するデータは、過去の推薦方策とrating時のバイアスが発生する
    - 実際の分布との乖離を取り扱うために、因果推論のテクニックを取り扱う


- 分布の乖離の補正方法
    - 観測データを利用して、実際の分布における損失の推定値を使って、評価・学習したい

    - 観測されたデータに対して、シンプルに損失を平均をとったNaive推定量は、傾向スコアによるバイアスがかかる
    - 傾向スコアの逆数IPS(Inverse Propensity Score)で損失を重みづけする
        - 傾向スコアが小さいケースの場合、損失が大きく重みづけられるため、過学習に繋がる
GitHubの草を自動栽培する

Twitter でタイムラインを眺めていると 「[草生やして転職。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30241/c57ca742-fe20-61fb-39cc-ef0d96cb2d65.png)」 なんていう**ふざけた広告**が流れてくるので、なら自動栽培してやろうと思い立った。

## Tools

- GitHub 
- Travis CI

## Overview

とても簡単で毎日 Travis CI を動かして、ファイルいじって、 GitHub にプッシュするだけです。

![travisci-githubのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30241/ad5179d4-ea45-c2d0-fc23-65dfb89acfca.png)

## Config

Travis CI に設定する必要がある項目を紹介する

### Cron Jobs

毎日実行されるように設定するだけ

![スクリーンショット 2019-07-11 19.25.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30241/f9fa2b0c-37fc-ad17-27f0-1c33daaba0a4.png)

### Environment Variables

GitHub の [Personal Access Token](https://github.com/settings/tokens) を使う

`USER_TOKEN` にトークンをセットすると完了

```
travis env set USER_TOKEN the-generated-token --private -r tanjo/saibai
```

または Travis CI のサイトで設定できる

![スクリーンショット 2019-07-11 19.25.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30241/640be53e-069e-b3d4-484c-35d2a1f51aa7.png)

## Code

Travis CI の `TRAVIS_EVENT_TYPE` が `cron` の時にファイルを更新して GitHub へ push する。

イベントタイプによる判断をしているので cron 以外のジョブでは GitHub への push が実行されることはありません。

`tanjo/saibai` はダミーリポジトリ名で存在しません。

```yaml:.travis.yml
language: ruby
rvm: 2.6.2
before_install:
- gem install bundler:2.0.1
script:
  - |
    if [ $TRAVIS_EVENT_TYPE = cron ]; then
      echo -e "machine github.com\n  login $USER_TOKEN" >> ~/.netrc
      git clone --branch develop --depth 1 https://github.com/tanjo/saibai.git
      pushd saibai
      git config user.name "tanjo"
      git config user.email "tanjo@users.noreply.github.com"
      echo `date` > .updated
      git commit -m "Update .updated"
      git push origin develop
      popd
    fi
branches:
  only:
  - develop
```

## Result

約1年くらい栽培した結果がこちらです。

![スクリーンショット 2019-07-11 19.43.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30241/c933ee4f-ddb0-49e4-bff3-a4a0e1541fb7.png)

丹精込めた日ほど色濃く育ちます。

他にどうやらまとめてやる方法があるらしいですが、日々の努力をアピールするため毎日 push しました。

ちなみに、こういった使い方は推奨されないためオススメはしません。

Travis CI で develop ビルドから master へ自動 push がしたい等の参考にしてください。
Flutter(Dart)でユニットテストを書く

# 背景
割と複雑なJSONをAPIから取得する処理を実装していた際、JSONからのシリアライズが正常に出来るか確認したくなりました。
そこで今回は、ユニットテストで確認してみることにしました。
この記事では、ユニットテストの導入とその際にハマったポイントを記載します。

# 参考

* [Testing Flutter apps](https://flutter.dev/docs/testing)
* [An introduction to unit testing](https://flutter.dev/docs/cookbook/testing/unit/introduction)

# 実装
## テストパッケージのインストール
`pubspec.yaml`に依存関係を追加します。
（恐らく、Flutterプロジェクトを生成した際に既に追加されていると思います。）

```yaml:pubspec.yaml
dev_dependencies:
  flutter_test:
    sdk: flutter
```

>The test package provides the core framework for writing unit tests, and the flutter_test package provides additional utilities for testing widgets.
（[An introduction to unit testing](https://flutter.dev/docs/cookbook/testing/unit/introduction)より引用。）

引用文に記載の通り、[testパッケージ](https://pub.dev/packages/test)はユニットテスト用のパッケージ、[flutter_testパッケージ](https://api.flutter.dev/flutter/flutter_test/flutter_test-library.html)はユニットテストに追加してWidgetのテストに関するユーティリティを提供しているので、ひとまず`flutter_test`を入れておけばユニットテストも実装できます。

その後の実装は公式リファレンスを読んでいただければ解説は不要かと思いますので、ここからは私が実装の際にハマったポイントを記載していきます。

# ハマりポイント
## オブジェクト同士の比較が失敗する
試しにシンプルなオブジェクトのユニットテストを書いて見たところ、テストが失敗しました。

```dart:sample.dart
import 'package:json_annotation/json_annotation.dart';

@JsonSerializable(createToJson: false)
class Sample {
  Sample({this.name, this.value});

  final String name;
  final int value;

  static fromJson(Map<String, dynamic> json) => _$SampleFromJson(json);
}
```

```dart:sample_test.dart
import 'package:flutter_test/flutter_test.dart';

const Map<String, dynamic> TEST_DATA = {
  "name": "ほげ",
  "value": 100,
};

void main() {
  test(
    "Sampleクラスのテスト",
    () {
      expect(Sample.fromJson(TEST_DATA), equals(Sample(name: "ほげ", value: 100)));
    },
  );
}
```

```text:失敗時のログ
Expected: <Instance of 'Sample'>
  Actual: <Instance of 'Sample'>
```

どうやら原因は、Sampleクラスの`==`と`hashCode`を実装していなかったことにあったようです。
下記のようにoverrideした結果、無事テストが成功しました。
（`dart:ui`パッケージの`hashValues`は@mkosukeさんに教えていただきました！ありがとうございます！）

```dart:Sample.dart
import 'package:json_annotation/json_annotation.dart';
import 'dart:ui';

@JsonSerializable(createToJson: false)
class Sample {
  Sample({this.name, this.value});

  final String name;
  final int value;

  @override
  bool operator ==(other) =>
      other is Sample && other.name == name && other.value == value;

  @override
  int get hashCode => hashValues(name, value);

  static fromJson(Map<String, dynamic> json) => _$SampleFromJson(json);
}
```
停電検知システム

かなり前に書いた記事ですが、

https://qiita.com/yamori813/items/78030bda4c8949adf6da

このルーターは起動後にDIAGが赤く点灯します。異常系の表示はシステムが起動してオフにすることでクリアされるように作られていることが多いです。

![写真（2019-07-11 19.56）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/70cb0f3a-539e-4201-09d4-610d3fbd5f7e.jpeg)

このLEDはGPIOの0なので、

```
# gpioctl 0 1
```

とすると消えます。

![写真（2019-07-11 19.59）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/9d673b36-df09-e3bf-6511-231350e9d0f4.jpeg)

この状態にしておくと停電があって再起動した時にはまた赤く点灯した状態になるので停電があったことがわかります。自分が留守の時や就寝時に停電があった場合の確認になります。

我が家のNTP st1サーバ4台はRTCが入っていないので、再起動すると1970年になってしまうので、自動起動にはしてません。停電があった時は手動である程度正確な時間をdateコマンドで設定してからntpdを上げる必要があります。

日本の電力供給は非常に安定していて、停電は5年に一度くらいしかない気がします。
＜CSS＞疑似要素にtransitionがかかっているとブラウザバッグでスタイルが崩れる可能性がある

```
発生したブラウザ: chrome
対象: CSS3の疑似要素
```

## 課題
### PC
```style.css
.pageContent.top .secondaryBlock__btnList li:after {
	content: "";
	display: block;
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left: 0;
	transition: all 0.3s ease-out;
	z-index: 1;
}
.elem:hover:after {
	transform: scale(1.15);
}
.elem:nth-child(1):after {
	background: url("img-pc.png") no-repeat center center/contain;
}
```
### SP
```style.css
/* ========================================
            styles for tablet & SP
======================================== */
@media screen and (max-width: 768px) {
.elem:after {
	content: "";
	display: block;
	width: 100px;
	height: 100px;
	z-index: 3;
	top: 50%;
	left: 0;
	transform: translateY(-50%);
	pointer-events: none;
}
.elem:hover:after {
	transform: scale(1) translateY(-50%)
}
.elem:nth-child(1):after {
	background-image: url("img-sp.jpg");
}
}
```
PCのときはhoverのときtransitionでエフェクトを付けていましたが、SP時はhover時の動きはありません。

読み込み時はスタイル崩れはありませんでした。

**しかし!!!**

ブラウザバッグをするとPCの背景画像とスタイルになっているのです。
SPの画像は確かに読み込まれているし、スタイルも認識しているのになぜ?

デベロッパーツールでなにか1つプロパティに変更をかける(チェックを外したり数値を変えたりする)と、SP用スタイルに切り替わる不思議減少。。。


20分くらい悩みました。。


## 解決策
### SP
```style.css
/* ========================================
            styles for tablet & SP
======================================== */
@media screen and (max-width: 768px) {
.elem:after {
	content: "";
	display: block;
	width: 100px;
	height: 100px;
	z-index: 3;
	top: 50%;
	left: 0;
	transition: none; // 追加しました
	transform: translateY(-50%);
	pointer-events: none;
}
.elem:hover:after {
	transform: scale(1) translateY(-50%)
}
.elem:nth-child(1):after {
	background-image: url("img-sp.jpg");
}
}
```
答えは単純`transition: none;`をSPのスタイルに追加するだけです。

**hover用のアニメーションをちゃんと切ってあげるだけ。**



こんなバグもあるんだなあ。と、しみじみしました。
LeetCode / Longest Common Prefix

（[ブログ記事](https://mhiro216.hatenablog.com/entry/2019/07/11/195022)からの転載）

[https://leetcode.com/problems/longest-common-prefix/]

Write a function to find the longest common prefix string amongst an array of strings.
If there is no common prefix, return an empty string "".

Example 1:

Input: ["flower","flow","flight"]
Output: "fl"
Example 2:

Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.

Note:

All given inputs are in lowercase letters a-z.

全文字列共通のprefix（接頭辞）を見つける問題です。様々な解法があって、以下に紹介したもの以外も探してみると面白いと思います。

#### 回答・解説

##### 解法1
リストの1つ目の要素の最も長い文字列から順に確認していき、当てはまらなければ１文字削除してまた確認し・・・というiterationを回します。

```python
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs: return ''
        prefix = strs[0]
        for i in range(1,len(strs)):
            while not strs[i].startswith(prefix):
                prefix = prefix[0:len(prefix)-1]
                if not prefix: return ''
        return prefix
```

"flower"の例で言えば、"flower", "flowe", "flow", "flo", "fl"の順に確認していくことになります。

##### 解法2
解法1は、リストの最初の文字列が最も長く、最後の文字列が最も短いような場合でも、初めの文字列数分のiterationを回してしまうことになります。
そこで、リストを<b>横に見るのではなく、縦に見る</b>ことを考えます。
"flower"の例で言えば、"f", "fl", "flo", "flow", "flowe"の順に確認していくということです。

```python
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs: return ''
        for i in range(len(strs[0])):
            c = strs[0][i]
            for j in range(1, len(strs)):
                if i == len(strs[j]) or strs[j][i] != c:
                    return strs[0][:i]
        return strs[0]
```
pythonのお勉強9日目

### 機械学習の3日目
超初学者の立場からの　[ゼロから作るdeep learning](https://www.oreilly.co.jp/books/9784873117584/)

１〜２章 読書での備忘録です。新しい知見などはありません。

今回は ゼロから作るdeep learning を購入!
この書籍に関してQuiitaの中でも多くの先人の解説
があり参考にさせて頂きました。
### 第1章　Python入門(P1~P20 )
pythonに関しては、少し勉強していたので理解が深まりました。
レナさんのことなどを検索、所要時間20分くらい。

### 第2章　パーセプトロン(P21~P37 )
 andやnand, orを積み重ねていくことで理論上なんでも可能（36p)。ここで量子での並列処理のことが気になり googleを用いてパーセプトロンと量子で検索。すでに何年も前からいろいろとされているようでした。
ここまでで30分以上経過、多重検索を進めていきました。q#によるテレポ...なかなか先に進めません。夕食は済ませ必要なカロリーは摂取できているのだがお腹が空いてレトルトのカリーが食べたくなりました。(食べられるカリー、[食べられないカリー](https://qiita.com/KDKTN/items/6a27c0e8efa66b1f7799))英語のサイトも検索にかかってきます。(お腹が空いていてもbeautifulのあとに続く名詞からは食べ物は連想できない...)英語で基本的な用語は押さえておいた方が良さそうですね。

参考
--
[ゼロから作るDeep-Learningの記事](https://qiita.com/tags/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8Bdeep-learning)
【Rails】Active Storageで拡張子のvalidateを作成する時の注意点

# はじめに
タイトル通りActive Storageで拡張子に関するvalidateを作成したところ、Userがサインアップする時にエラーが出てしまった。

# 事象

Userモデルに以下のような感じで、Active Storageでアップロードするimageに対して拡張子を指定するvalidateを作成した。

```user.rb
class User < ApplicationRecord
  has_one_attached :image

  validate :image_content_type

  def image_content_type
    extension = ['image/png', 'image/jpg', 'image/jpeg']
    errors.add(:image, "の拡張子が間違っています") unless image.content_type.in?(extension)
  end

```

ところがこの後、userを新規アカウント登録させようとすると以下のエラーが出てしまった。

```
content_type delegated to attachment, but attachment is nil
```

<img width="1033" alt="スクリーンショット 2019-07-11 19.40.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/da652a34-e8b6-bddd-f576-59519ffc0554.png">

# 原因
今回の場合はUserをcreateする時にemailとpasswordしかpostしないので、
当然imageはparamsに乗らないため、`image.attached?` は `false`になります。
上記のエラーは**imageがattachedされてないのに`content_type`を呼び出した**ことによるエラーっぽいです。

#解決方法
`image.attached?`が`false`の時はvalidateしないようにすれば解決なので、

```user.rb
class User < ApplicationRecord
  has_one_attached :image

  validate :image_content_type, if: :was_attached?

  def image_content_type
    extension = ['image/png', 'image/jpg', 'image/jpeg']
    errors.add(:image, "の拡張子が間違っています") unless image.content_type.in?(extension)
  end

  def was_attached?
    self.image.attached?
  end
```

これで無事Userがcreate出来るようになりました。
[React Native] iPad端末かどうかを判定する

## はじめに
React Native でiPhone 向けとiPad 向けにアプリを開発しているとする。コンポーネントのレイアウトなど、端末によって特定の処理を分岐させたい。
iPad かどうかを判定する方法は、React Native の公式ドキュメントに載っていない（？）ようなのでメモ。

### 動作確認時のバージョン
- React Native v0.57
- expo SDK v32

## コード
`Platform.isPad` で判定できる。 (`Platform.isIPad` ではない。) 

```javascript
import { Platform } from 'react-native'

console.log(Platform.isPad) // => true | false
```

TypeScript を使っている場合では警告が出るため、 `Platform` を `PlatformIOSStatic` に強制キャストするとよい。
`platformIOS.isPad` でiPad かどうかを判定できる。

```typescript
import { Platform, PlatformIOSStatic } from 'react-native'

if (Platform.OS === 'ios') {
  const platformIOS = Platform as PlatformIOSStatic
  console.log(platformIOS.isPad) // => true | false
}
```

### Platform.ios.js

React Native のコードを読むと、他に `Version() ` `isTVOS()`, `isTV()`, `isTesting()` も用意されているのが分かる。
[react-native/Platform.ios.js at 0.57-stable · facebook/react-native](https://github.com/facebook/react-native/blob/0.57-stable/Libraries/Utilities/Platform.ios.js)

## 参考
- [React Native: How to Determine if Device is iPhone or iPad - Stack Overflow](https://stackoverflow.com/questions/40249604/react-native-how-to-determine-if-device-is-iphone-or-ipad)
- [Platform Specific Code · React Native](https://facebook.github.io/react-native/docs/0.57/platform-specific-code)
Music FMがApp Storeから追放された。Music FM消えた後、代わりになる音楽アプリって？

Music FMがApp Storeから追放された。Music FM消えた後、代わりになる音楽アプリって？

一般社団法人日本レコード協会は7月11日、一般社団法人日本音楽事業者協会、一般社団法人日本音楽出版社協会、一般社団法人日本音楽制作者連盟の4団体に加え、AWA、KKBOX、LINE MUSIC、楽天の4社とともに、アップルに対し、著作権者および著作隣接権者などの管理者が想定しない態様による音楽配信アプリ（無許諾音楽アプリ）の対策強化について、要望書を6月28日付で提出したと発表しました。
それで、音楽ダウンロード無料アプリケーションMusic FMも終わります。Music FM消えた後、どのような音楽保存アプリケーションを使えばいいのかと多くの方々に聞かれています。そこで今回は、Music FM消えた後、代わりになる音楽ダウンロードアプリを厳選してまとめてみます。

Music FM代わりになれる音楽アプリ：Apple Music
![Apple Music.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432052/a733ef53-d819-5d1c-7a33-0bce3082ccae.jpeg)

Apple Musicは、アップルの音楽配信サービスである。2015年6月30日にサービスが開始されました。5000万曲の音楽に自由にアクセスでき、気に入った曲を自分のライブラリやプレイリストに追加したり、オフラインで楽しめるよう端末にダウンロードしたりできます。
創業者： Apple
開局：2015年6月30日
創業国： 米国
ユーザー数：9600万人以上（有料会員数）
本社： 米国
公式サイト：https://support.apple.com/ja-jp/HT204839

Music FM代わりになれる音楽アプリ：Spotify
![spotify.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432052/9d46092b-b17f-2f64-4288-f0b2873c4aab.jpeg)

Spotifyとは、スウェーデンの企業スポティファイ・テクノロジーによって運営されている音楽ストリーミングサービスです。2018年現在、1億7000万人のユーザーを抱えており、音楽配信サービスとしては世界最大手です。
創業者： ダニエル・エク(Daniel Ek), Martin Lorentzon
開局： 2006年4月23日
創業国： スウェーデン
ユーザー数： 1.7億人
本社： スウェーデン; ストックホルム
プログラミング言語： Java、 Python、 C言語、 C++
公式サイト：https://www.spotify.com/jp/

Music FM代わりになれる音楽アプリ：YouTubee Music
![youtube-music.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432052/de67d397-63cc-32d3-87f3-372a4ae4d945.jpeg)

「YouTube Music」は、YouTubeから音楽コンテンツだけを切り出した音楽ストリーミングサービスです。Youtube Musicでユーザーは、お気に入りのアーティストピックアップし、いつでもどこでもYoutubeの音楽動画を楽しむことができます。
創業者： ダニエル・エク(Daniel Ek), Martin Lorentzon
開局：2015年11月12日
創業国： アメリカ
ユーザー数：1500万人（登録者数）
本社：Youtubeを運営するGoogle
公式サイト：https://music.youtube.com/

合わせて読みたい：
https://www.winxdvd.com/apple-iphone-media/powerful-music-fm-music-download-to-pc.htm