OmniAICreator/Qiita-1.07M huggingface dataset:
Windows環境のEmacsへPygmentsパーサーを導入

# はじめに
以前からwindows版EmacsでGNU GLOBALを使用させてもらっていました。
最近、C#の勉強しているので以前から存在だけは知っていたPygmentsパーサーを利用してC#のタグを作成できるように作業をしました。
その中で少しハマったところがあったのでメモを残しておきます。

# 環境
利用環境は以下です。

- Windows10
- Emacs26.1
　[Emacs for Windows](http://cha.la.coocan.jp/doc/NTEmacs.html)で公開されている「簡易IME対応(2)版(ファイルサイズ削減・tif画像表示対応・TLS対応)」を使用
- GNU GLOBAL 6.6.3 Window用ビルド(Win32版)
　http://adoxa.altervista.org/global/


環境変数には以下が設定されています。

|変数  |値(例)        |
|------|--------------|
|HOME  |D:\emacs      |
|Path  |D:\emacs\bin  |


# Pythonの実行環境をインストール
まずは、Pygmentsを動かすためにPythonの実行環境をインストールします。
Windows向けPythonも色々なバージョンがあるのでどれを導入したらいいのか迷いましたが
[python.org](https://www.python.org/downloads/windows/)の64bitインストーラ版を使用しました。
バージョンは「Python 3.7.4 - July 8, 2019」でした。
(EmacsもGNU GLOBALも32bit版ですが、64bitで動作しました。32bit版でも動作します。途中切り分けで両方試しました…)

注意点は

- 「Add Python 3.7 to PATH」のチェックを入れる
- インストール先を「D:\Python\Python37」に変更しました。※必ず変更する必要はなし
- インストール後にOSを再起動する。
![python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465038/ca6af55b-f99a-0c65-f175-b79d461492db.png)

OS再起動後のeshell又はDOSプロンプトで「pip  --version」と入力して
バージョンが表示さればPythonのインストールはOKです。

```
$ pip --version
pip 19.1.1 from d:\python\python37\lib\site-packages\pip (python 3.7)
```

# Pygmentsパーサーをインストール
以下のコマンドを実行してPygmentsパーサーをインストールします。

```
$ pip install Pygments
```

インストール後にバージョン情報が表示されればOKです。

```
$ pygmentize -V
Pygments version 2.4.2, (c) 2006-2019 by Georg Brandl.
```

# exuberant ctags 日本語対応をインストール
Emacsのbinフォルダには、既にctags.exeが存在していましたが
このファイルを利用すると以下のエラーが発生しました。

```
ctags: unrecognized option '--filter'
	Try 'ctags --help' for a complete list of options.
```

以下のサイトからexuberant ctags 日本語対応Win32版(バイナリのみ)をダウンロードしてbinフォルダにコピーしました。
http://hp.vector.co.jp/authors/VA025040/ctags/

# gtags.confをコピー
GNU GLOBALに付属の「gtags.conf」をコピーします。
環境変数に以下の値を追加します。値は環境に合わせて変更可能です。

|変数       | 値(例)                       |
|-----------|------------------------------|
|GTAGSCONF  | D:\emacs\.emacs.d\gtags.conf |

追加した値と同じパスにgtags.confをコピーしておきます。


# 動作確認
この時点で動作すると思っていたのですが、C#のタグを作りたいディレクトリで
「gtags --gtagslabel=pygments」コマンドを入力すると以下のエラーが発生しました。

```
$ gtags --gtagslabel=pygments
python: can't open file 'd:\emacs\bin\../share/gtags/script/pygments_parser.py': [Errno 2] No such file or directory
```

# pygments_parser.pyをコピー
いきなり身に覚えがないディレクトリが出てきて戸惑いましたが
「pygments_parser.py」はGNU GLOBALに付属していたので指定されたフォルダを作成して、そこにコピー。
今回の場合は「D:\emacs\share\gtags\script\pygments_parser.py」
※このディレクトリは誰が指定しているのは謎のまま…

これでエラーが解消され動くようになりました。


# gtags.confを修正
最後に、gtagsコマンドに毎回オプションを付けるが億劫なのでgtags.confを編集
ファイルの頭の方にある以下の記述を

``` gtags.conf
default:\
	:tc=native:
```

以下のように書き換え、

``` gtags.conf
default:\
  :tc=native:tc=pygments:
```

これで普段はgtags.exeを使用してC#など追加言語はpygmentsを使用する様になります。

# 終わりに
上記の手順でgtagsコマンドでPygmentsパーサーを使用したタグが出力されるようになりました。
C#の場合、gtags.exeだけでも一部のタグは出力してくれます。
だたし、シンボルとリファレンスが別れていないので微妙に使いづらかったのでこれが解消されてとりあえずは満足。


# 参考リンク
https://qiita.com/yoshizow/items/9cc0236ac0249e0638ff
http://cha.la.coocan.jp/doc/gnu_global_with_pygments.html
Bootstrap の グリッドシステム とは ～画像付き解説～

# 目的
Bootstrapのグリッドシステムの考え方についてまとめる
※レスポンシブデザインに対応したグリッドシステムについては別記事でまとめる。

# この記事のターゲット
- Bootstrapを使ってみたけど上手くcolクラスの使い方がわからない方
- ドットインストールのグリッドシステムについての動画を見てもよく分からなかった方
- グリッドシステムについてよく分からずBootstrapを使うのが嫌になってしまった方
- グリッドシステムに苦手意識がある方

# そもそもグリッドシステムって？
- 要素の表示幅に関するワード
- 画面幅に合わせて要素の表示領域をコントロール出来る
- Bootstrapのグリッドシステムという考え方を理解すると簡単にレスポンシブデザイン化が可能となる
※話がややこしくなるので別記事で説明する。
- 「縦方向に12分割された領域」をどのくらい占領するかで表示領域を設定する

# 押さえるポイント
- グリットシステムの最も外の要素はcontainerクラスを持ったdiv、その中にrowクラスを持ったdiv、その中にcolクラスを持ったdivで構成されている。(下記に簡易図を記載する。)
- colはカラムと呼ばれる。
- containerクラスのdivでグリットシステムを使うことを表す。
- rowクラスのdivでcontainerクラスのdivを上下方向に分割する。
- colクラスを持つdivで表示するコンテンツを記載する。
- colクラスを持つdivのクラス名を指定する際にdiv内の要素を12分割された領域をどのくらい使って表示するかを設定
する。
- 使用領域はクラス名のcolに数字をつけて設定する。  
※4領域を使用して表示したいときは次のように記載する  
`<div class="col-4"></div>`
- 一つのcol内で合計12を超える指定をすると自動的に上下に分けて表示する。
- 一つのcol内で合計12を超えない指定をすると左寄りに指定された領域を使用して内容を表示する。  
下記にグリッドシステムの簡易図を載せる。
![グリッドシステム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/028c7958-3fa4-2c25-2239-363055fd9ed3.png)



# グリッドシステムの書き方の例
本項ではグリッドシステムについてのみ解説する。  
レスポンシブデザイン対応のグリッドシステムについては次項で記載する。
- 12分割された内の8領域と4領域を使用してテキストを表示する。
- 下記にHTMLファイルの内容を記載する。

``` html
<div class="container">
　<div class="row">
　　<!-- 12分の8を使用して表示する bg-primaryは背景色を青色にする設定 -->
　　<div class="col-8 bg-primary">
　　　<p>8</p>
　　</div>
　　<!-- 12分の4を使用して表示する bg-warningは背景色を黄色にする設定 -->
　　<div class="col-4 bg-warning">
　　　<p>4</p>
　　</div>
　</div>
</div>
```

下記にコードとプレビュー画面の色関係を表した画像を添付する。

- コードを添付する。
![グリッドシステム1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/e4a415c7-f61f-7455-f10c-2ad394290d00.png)

- プレビューイメージを添付する。

![グリッドシステム_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/b12f25fa-ecae-2dfb-608e-6ddf0e99ac11.png)



- 12分割された内の1領域と1領域と10領域を使用してテキストを表示する。
- 下記にHTMLファイルの内容を記載する

``` html
<div class="container">
  <div class="row">
    <!-- 12分の1を使用して表示する bg-primaryは背景色を青色にする設定 -->
    <div class="col-1 bg-primary">
      <p>①</p>
    </div>
    <!-- 12分の1を使用して表示する bg-warningは背景色を黄色にする設定 -->				
    <div class="col-1 bg-warning">
      <p>①</p>
    </div>
    <!-- 12分の10を使用して表示する bg-successは背景色を緑色にする設定 -->
    <div class="col-10 bg-success">
      <p>⑩</p>
    </div>
  </div>
</div>
```

下記にコードとプレビュー画面の色関係を表した画像を添付する。

- コードを添付する。
![グリッドシステム2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/555ed54c-8cb1-4259-dae4-a35685c724bf.png)


- プレビューイメージを添付する。
 ![グリッドシステム_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/d86bb17b-0dcd-1b7f-9081-3aa88e459158.png)

# まとめ
- グリッドシステムの基本的な考え方をまとめた。
        - 次回はレスポンシブデザイン対応させたグリッドシステムについてまとめる。(本記事にリンクを張る予定)
sudoでPythonファイルを実行したときにImportErrorが起こったときの対処法

# 起こったこと
ラズパイでpythonファイルを自動起動するにはsudoで実行する必要がある。
しかし、普通に`python3 .py`で実行できたファイルがsudoをつけたとたんにImportError: No module named などとエラーを吐いた。
解消に3時間くらいかかったので備忘録。

# 対処法
1. ターミナルで`python3`を実行
2. numpyをインポートして`numpy.__path__`でどこを参照しているのか確かめる
3. 1にsudoをつけて2まで同様に行う。すると先程とは違う参照場所が返ってくるはず
4. そのままsysをインポートして`print(sys.path)`を実行。/dist-packagesと書いてあるものがあることを確認する。ここでは/usr/lib/python3/dist-packagesがあったとする
5. `cd /usr/lib/python3/dist-package`を実行
6. `sudo nano module.pth`で.pthファイルを作る。名前は何でもいい。
7. 2ででてきたpathを''とか""無しに書き込んで保存

以上でImportErrorを起こさずに実行できた。
インタプリタ言語とコンパイラ言語

#まず前提知識として
私たちは様々なプログラミング言語でコードを書いています。
C言語だったりJavaScript、Ruby、PHP色々ありますね。
しかしコンピュータは、これらの言語で書いたままの状態ではプログラムを理解できません。
必ずコンピュータが理解できる"**機械語**"に変換してから読み込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419062/8ad3b24c-5076-766a-3c64-03b70b4126d4.png)

※引用元：https://www.goethekyodai.xyz/entry/compiler-interpreter
※マシン語→機械語のことです
この"変換して実行する過程"が、インタプリタ言語とコンパイラ言語とで異なります。
今回はこのインタプリタ言語とコンパイラ言語の違いについて基本的な特徴をまとめてみました。

#インタプリタ言語とコンパイラ言語の違い


一言でまとめると
**インタプリタ言語は、コードを実行する際に1行ずつ機械語に翻訳していく言語**です。
**コンパイル言語は、まず全てのコードを機械語に翻訳してから一気に実行する言語**です。

以下にそれぞれのメリットとデメリットをまとめておきます。
###インタプリタ言語（JavaScriptやRuby、PHPなど）
***●メリット***
・プログラムをすぐに実行できる
・1行1行読み込むので、実行がうまくいかなかった時点で、すぐにデバックに取りかかれる


***●デメリット***
・実行速度が遅い。
→ プログラムを実行するのに一回一回機械語に翻訳するので、その分実行速度が遅くなります。その為、コンパイラ型言語より実行速度が劣リます。


###コンパイラ言語(C言語、C＋＋など)
***●メリット***
・実行速度が速い

***●デメリット***
・コンパイルするまでエラーを把握できない。
→ 1行1行機械語に翻訳するインタプリタ言語の場合は、機械語に翻訳できないエラーが発生した時点で調査し修正することができます。
しかしコンパイラ言語の場合は、全て翻訳して一気に実行するまでどこでエラーが発生したか把握できません。

#さいごに
私自身、インタプリタ言語しか使ったことがないのですが、色々な場面でインタプリタ言語もコンパイラ言語も普通に言葉として出てくるので把握が必要だと感じました！
インタプリタ言語は、1行ずつ翻訳して実行するんだなー。
コンパイラ言語は、まず全て翻訳してから一気に実行するんだなー。
くらいの把握でも最初は良いかと思います。
【初心者向け】factory_botを利用したダミーデータの作成方法

# factory_botとは
簡単にダミーのインスタンスを作成することができるGemです。他のファイルで予め各クラスのインスタンスに定めるプロパティを設定しておき、specファイルからメソッドを利用してその通りのインスタンスを作成します。

## 導入方法
Gemfileに以下のように記載

```ruby:Gemfile
group :development, :test do
  #省略
  gem 'factory_bot_rails'
end
```
bundle installします。

[![Image from Gyazo](https://i.gyazo.com/6080e2eb0fb81a3df1378c5fc39ecc99.png)](https://gyazo.com/6080e2eb0fb81a3df1378c5fc39ecc99)

specディレクトリ内に’factories’というディレクトリを作成し、（今回はuserのテストをするので）users.rbというファイルを作成します。

## factory_bot を使ってuserを定義する

先ほど作成した`factories/users.rb` 内にダミーのuserを定義します。

```ruby:factories/users.rb
FactoryBot.define do
  factory :user do
    name                  {"tanu"}
    email                 {"test@email.com"}
    password              {"11111111"}
    password_confirmation {"11111111"}
  end
end
```

## 定義したuserをテスト内で使う

先に定義したuserは下記のように使用します。

```ruby:spec/model/user_spec.rb
describe User do
  describe '#create' do
    it 'is invalid without a name' do
      user = FactoryBot.build(:user, name: nil)
      user.valid?
      expect(user.errors[:name]).to include("を入力してください")
    end
  end
end
```
これは、下記の内容と一緒です。（下記は、factory_botを使用しないで、同じ内容を記述した例）

```ruby
describe User do
  describe '#create' do
    it 'is invalid without a name' do
      user = User.new(name: "", email: "test@email.com", password: "11111111", password_confirmation: "11111111")
      user.valid?
      expect(user.errors[:name]).to include("を入力してください")
    end
  end
end
```

なお、

```ruby
user = FactoryBot.build(:user, name: nil)
```

の `FactoryBot`は省略可能で、上記は、

```ruby
user = build(:user, name: nil)
```
と書くこともできます。

## buildメソッドとcreateメソッド

factory_botのメソッドのうち

- `build`　...　インスタンスを生成するメソッド。newと同じ
- `create` ... データのsaveまでを行う。ただし、saveされたデータは、１回のテストが終わったら消えてしまう。

という特徴がそれぞれあるそうです。

## レシーバーの"FactoryBot"という記述を省略する

さらに、rails_helperに下記のような記述をしておくことで、"FactoryBot"という記述は省略できるそうです。

```ruby:spec/rails_helper.rb

RSpec.configure do |config|
  #下記の記述を追加
  config.include FactoryBot::Syntax::Methods
  #省略
end
```

上記の記述によって、テストの記述は下記のように省略できます。

```ruby
user = build(:user, name: nil)
```
テストはしっかり学習しておくように周りから色々なアドバイスを受けるのですが、なかなか奥が深いですね。また折を見て復習したいです。
PHPの定数

定数について、わかっているつもりでも種別や使い方を誤る事が多いので、
勉強しました。

#定数とは
定数とは変数と異なり、途中で中身を変更できない入れ物のことです。
スクリプトの中でなんらかの意味を持つ値にあらかじめ値をつけておく仕組みとも言えます。

```php
const TAX = 1.08;
$price = 1000;
$sum = $price * TAXs;
print $sum;
//結果：1000
```

constは定数を宣言するための命令で、ここでは定数TAXを1.08という値で設定しています。

```php
const 定数名 = 値
```
定数の命名規則は変数とほぼ同じですが、次の点が異なります。

###1.先頭に「＄」のような記号を付ける必要がない
変数のように、1文字目の「＄」は不要です。定数は「＄TAX」ではなく、そのまま「TAX」のように命名します。

###2.PHPで意味を持つ予約語でないこと
PHPで元々定数定義されている予約語は使用しないでください。

###3.すべて大文字で命名する
構文規則ではりませんが、定数は変数と視覚的にも区別しやすいようにすべて大文字で命名します。
命名規則は「TAX_FREE」のようにアンダースコア「_」区切りで表します。

ただし、defineで定義すると以下のように値を変更できません。

```php
<?php
define('TAX', 1.08); // 消費税
define('TAX', 1.10); // 消費税を変更

echo TAX;

<実行結果>
Notice: Constant TAX already defined
1.08
```

#定義済みの定数一覧
PHPには最初から用意

| 定数 | 概要 |
|:-----------|:------------|
|\_\_FILE__|実行中のファイル名(絶対パス)|
|\_\_DIR__|実行中のファイルが存在するフォルダ|
|\_\_LINE__|実行中の行番号|
|\_\_FUNCTION__|実行中の関数名|
|\_\_CLASS__|実行中のクラス名(所属する名前空間含む)|
|\_\_METHOD__|実行中のメソッド名|
|\_\_TRAIT__|実行中のトレイと名(所属する名前区間含む)|
|\_\_NAMESPACE__|現在の名前空間|
|DIRECTORY_SEPARATOR|フォルダ区切り文字 windows「\」linux「/」|
|PATH_SEPARATOR|パス区切り文字|
|PHP_VERSION|使用しているPHPバージョン|
dockerのmysqlが文字化けしていたので色々調べた

## 背景
所属している会社の開発環境がdockerということと、
1. lamp専用の仮想環境と違って、mysqlやPHPなどのミドルウェアのバージョンを気軽にコントロールできる点（mampやxamppより優れている）
2. 動作が軽いのでパソコンに負担をかけなくて、ストレスなく開発ができるという点（vagrantより優れている）
という長所があって、今回初めてdockerで LAMP環境を作って個人的な学習に使おうとした。
今回はその上参考になったサイトなどを記録として残しておく。
特にmysqlの文字化けはちょっと迷ったが、解決できて嬉しい(ﾟ∀ﾟ)

## 参考になったサイト
https://qiita.com/ProjectEuropa/items/5fbb00848cd8d5b57182
最初はとりあえず上の記事通りにすれば動く！

ただここでmysqlの中の日本語をphpでselectすると文字化けしてしまう、、、
原因は下記の記事で探した。
https://qiita.com/luccafort/items/0553c589dcc6459746bc

my.cnfをマウントするだけで直った。
docker.ymlのcommandは特に書かなくても大丈夫ということかな？
とりあえず一件落着(((o(*゜▽゜*)o)))
BitbucketのJavaScriptプロジェクトをビルドしてS3にデプロイする

React.jsなどのSPAアプリケーションをBitbucket Pipelineを使ってS3にデプロイします。割とBitbucketが好きです。

# 用意
## S3へのデプロイIAMユーザーを作成

IAM > ユーザー > 認証情報 > アクセスキー からアクセスキーを作成し、アクセスキーIDとシークレットアクセスキーをメモしておきましょう。ここではs3-deploy-userとしておきます。

## S3のバケットを作成

なんでも良いです。ここではdeploy-bucketとしておきます。
バケットポリシーを設定し、s3-deploy-userでbucketを更新できるようにします。 

```json:policy
    {
        "Version": "2012-10-17",
        "Id": "Policy**********",
        "Statement": [
            {
                "Sid": "Stmt**********",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::*********:user/s3-deploy-user"
                },
                "Action": "s3:*",
                "Resource": "arn:aws:s3:::deploy-bucket/*"
            }
        ]
    }
```

# Bitbucket Pipelineの設定
## bitbucket-pipeline.ymlの作成

masterへのマージを契機にs3へのデプロイを実行します。

```bitbucket-pipeline.yml
    pipelines:
      branches:
        master:
          - step:
              name: Build
              image: node:10.15.3
              script:
                - yarn
                - yarn build
              artifacts:
                - dist/**
          - step:
              name: Deploy
              script:
                - pipe: atlassian/aws-s3-deploy:0.3.2
                  variables:
                    AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
                    AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
                    AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
                    S3_BUCKET: $S3_BUCKET
                    LOCAL_PATH: "dist/"
```
    

最初のステップでビルドを実行し、ビルド結果をartifactsとして次ステップで利用できるようにします。S3へのアップロードにはatlassianで用意されているpipeを利用します。アクセスキーやS3バケットの指定は環境変数で設定します。

Bitbucketのリポジトリ > Deployment の設定にてvariablesの設定を行います。用意しておいたアクセスキー等を設定すればいいです。

![variablesの設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123946/a3f35e8b-7171-b2c5-0554-025a09791f63.png)


後はmasterをpushするか、プルリクエストからマージを行えばS3へのデプロイが実行されます

# 参考
- [bitbucket-pipelines.yml を設定する](https://ja.confluence.atlassian.com/bitbucket/configure-bitbucket-pipelines-yml-792298910.html)
- [キャッシュの依存性](https://ja.confluence.atlassian.com/bitbucket/caching-dependencies-895552876.html)
NULL合体演算子

今日、便利だなと思ったphpの記法をメモ

###NULL合体演算子
基本構文

```
条件式または$変数 ?? 真の式;
```

**<font color="Blue">条件式または$変数</font>**がnullの場合**<font color="Red">真の式</font>**を返し、**<font color="Blue">条件式または$変数</font>**がnullでは無い場合、**<font color="Blue">条件式または$変数</font>**を返します。
(例)

```
$name = null;
$username = $name ?? '名無し';
echo $username; // 名無し
```


（参考
https://www.sejuku.net/blog/23070
https://www.php.net/manual/ja/migration70.new-features.php
【初心者向け】RSpecによるテストの開始方法

Rspecでテストを行うための手順をノートにまとめました。
まず、以下のGemをインストールします。

```ruby
group :development, :test do
  # 省略
  gem 'rspec-rails', '~> 3.5'
  gem 'rails-controller-testing'
  gem 'factory_bot_rails'
  gem 'faker'
end
```

`rspec-rails`・・・RSpecを利用できるようにするGem
`factory_bot_rails`・・・簡単にダミーのインスタンスを作成することができるようにするGem
`faker`・・・ダミーデータを作成するGem
`rails-controller-testing`・・・コントローラのテストに必要なGem

 bundle install　します。
次に、ターミナルで以下のコマンドを入力して、RSpecを使えるようにします。

```
$ rails g rspec:install
```

すると、以下のファイルが生成されます。

```
 create  .rspec
 create  spec
 create  spec/spec_helper.rb
 create  spec/rails_helper.rb
```
この時生成されている、
`rails_helper.rb`
とは、RailsにおいてRSpecを利用する際に、共通の設定を書いておくファイルです。**各テスト用ファイルでこちらのファイルを読み込む**ことで、共通の設定や、メソッドを適用します。

また、
`spec_helper.rb`
rails_helper.rbと同じくRSpec用の共通の設定を書いておくファイルですが、こちらはRSpecをRails無しで利用する際に利用します。

先のコマンドで生成された、.rspecを開き、下記の記述を追加します。

```
--require spec_helper
# 下記の記述を追加
--format documentation
```

これによって、テストの結果が見やすくなります。
「見やすくなる」とはどのようなことかは、こちらの記事をご参照ください。

▼RSpecには表示の出力をキレイにする --format documentation というオプションがある
https://shinkufencer.hateblo.jp/entry/2019/01/21/233000

ここまでで、RSpecを使う準備が整いました。
この時点で、ターミナルから以下のコマンドを入力すると

```
$bundle exec rspec
```
以下のように表示されて、RSpecがきちんと動いていることがわかります。

```
username:appname directory$ bundle exec rspec
No examples found.

Finished in 0.00042 seconds (files took 0.16261 seconds to load)
0 examples, 0 failures
```

まだ、テストを書いていないので、exampleもfailtureもないですが。

次は、userモデルについて、ごくごく簡単なテストを書いていきたいと思います。
LeetCode / Add Binary

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

[https://leetcode.com/problems/add-binary/]

Given two binary strings, return their sum (also a binary string).

The input strings are both non-empty and contains only characters 1 or 0.

Example 1:
Input: a = "11", b = "1"
Output: "100"

Example 2:
Input: a = "1010", b = "1011"
Output: "10101"

Add Binaryのタイトルの通り、Binaryの足し算です。
解けるは解けるんですが、以下にエレガントなアルゴリズムを書けるかが、コーディングインタビューでは見られるんだろうと思います。

#### 解答・解説

##### 解法1
まずは私の超力技のコードを示します。
いやー、見れば見るほど恥ずかしいんですが、あとで振り返ったときにこういう状態から来たんだ、と思えるように。

```python
class Solution:
    def addBinary(self, a: str, b: str) -> str:
        num = BinarytoInteger(a) + BinarytoInteger(b)
        ans = ''
        while num > 1:
            ans += str(num % 2)
            num = num // 2
        ans += str(num)
        ans = ''.join(list(reversed(ans)))
        return ans

def BinarytoInteger(a):
    return sum([int(e)*2**(len(a)-1-i) for i,e in enumerate(a)])
```

##### 解法2
さて、ここからが本番です。。。
recursiveを使った、エレガントな解法が以下の通り。

```python
class Solution:
    def addBinary(self, a: str, b: str) -> str:
        if len(a)==0: return b
        if len(b)==0: return a
        # 下１桁が両方1のときは、その桁は0となり1繰り上がる
        if a[-1] == '1' and b[-1] == '1':
            return self.addBinary(self.addBinary(a[0:-1],b[0:-1]),'1')+'0'
        # 下１桁が両方0のときは、その桁は0となる
        if a[-1] == '0' and b[-1] == '0':
            return self.addBinary(a[0:-1],b[0:-1])+'0'
        # 下１桁が片方0、片方1のときは、その桁は1となる
        else:
            return self.addBinary(a[0:-1],b[0:-1])+'1'
```

加算する2つの数の下１桁に注目し、3つの分岐で処理しています。
一番下の桁を処理したら下から２番目の桁、これを処理した下から３番目の桁、と順に遡っていくrecursiveな処理をしています。
【初心者向け】RSpecによる単体テストの記載方法（モデル編）

#  specファイルの基本

以下のように、specファイルは配置します

```
app
# 省略
spec
 L model
     L モデル名_spec.rb
 L controller
     L コントローラー名_spec.rb
```

ファイル名は、「**対応するクラス名_spec.rb**」になる。
例えば
 `user.rb`(モデル)のテスト　→　user_spec.rb
 `tweets_controlle`（コントローラー）のテスト　→　

## テストの書き方(モデルとアクションの指定)

userモデルのcreateアクションのテストをする場合。
userモデルに、こんなバリデーションがあったとします。

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
end
```

この時、「nameが空欄だったらuserを作れない」ことをテストしようと思います。
まず、外側の書き方はこんな感じです。

```ruby:spec/model/user_spec.rb
require 'rails_helper'

describe User do
  describe '#create' do
    it 'is invalid without a name' do
  　　　#ここにテストの内容を書きます
    end
  end
end
```
userモデルのテストなので、クラス名は「User」
createアクションのテストなので、慣習的に「'#create']と書きます。

`it~do` の間には何のテストなのかを書きます。
ここは日本語でもOKです。

## テストの書き方(テスト内容の指定)

次に、テストの内容を書いていきます。

```ruby:spec/model/user_spec.rb
describe User do
  describe '#create' do
    it 'is invalid without a name' do
      user = User.new(name: "", email: "test@email.com", password: "11111111", password_confirmation: "11111111")
      user.valid?
      expect(user.errors[:name]).to include("を入力してください")
    end
  end
end
```

`user = User.new()`の部分で、今回テストするユーザーのインスタンスを生成しています。

`user.valid?` の「valid?」は、ActiveRecord::Baseを継承しているクラスのインスタンスを保存する際に「バリデーションにより保存ができない状態であるか」を確かめるためのメソッドです。

expect(user.errors[:name]).to ないの `user.errors[:name` で **:name** カラムに対するエラーメッセージを呼び出しています。（エラーメッセージはrails側で定義されています）。

そして、そのエラーメッセージに **"を入力してください"** が含まれているのかをテストしています。

・・・なんだかいろいろ難しいので、もう少し練習して慣れようと思います。
次は、次は、factory botを使って、ダミーデータを用意する手順について書こうと思います。
FlutterでAndroidXへのマイグレーションを行う際の注意点

FlutterでAndroidXへのマイグレーションを行う際、いくつかハマってしまったポイントがあったため、それについてざっとまとめていきたいと思います。

# 基本的にはAndroid StudioのRefactor機能で自動的に行う

基本的には公式サイトにもある通り、Android StudioのRefactor機能を利用して自動的に行うことが推奨されています。
[AndroidX compatibility  - Flutter](https://flutter.dev/docs/development/packages-and-plugins/androidx-compatibility)

Android StudioでFlutterプロジェクトを開き、プロジェクトフォルダを右クリックし、
「Flutter」 -> 「Open Android module in Android Studio」
でAndroid側のプロジェクトを開いたのち、
メニューバーの
「Refactor」 -> 「Migrate to AndroidX」
でマイグレーションを行ってください。

※「Open Android module in Android Studio」が出てこない場合もあるため、その際はプロジェクトフォルダ配下にある「android」フォルダをAndroid Studioで直接開いてください。

# pubspec.yamlに定義されているパッケージのバージョンが古くないか確認

マイグレーション後、ビルドがうまくいかない場合、pubspec.yamlに定義されているパッケージのバージョンが古くないか見直してみてください。
パッケージのバージョンが古いと、そのパッケージがAndroidXに対応していない可能性があります。
パッケージのバージョンを最新にしてからビルドし直してください。

# それでもうまくいかない場合

pubspec.yamlに定義されたパッケージは、

```
flutter/.pub-cache/hosted/pub.dartlang.org
```
にキャッシュされています。
その中にあるパッケージのbuild.gradleを手動で書き換えて修正を試みてください。
（環境依存になってしまうので、あまりやりたくない手段ではあります。。）
Android端末に日本のSIMをさしたらカメラのシャッター音が強制鳴動するロジック

Androidのソースを読んでいたら、なんと**2012年**時点でこんなロジックが存在してたの？？という発見の共有。
https://android.googlesource.com/platform/frameworks/base/+/dd45d01128423a82652a3c9d77fa393631d95229

## 「日本のSIMをさしたら」の判定

```core/res/res/values-mcc440/config.xml
    <!-- Whether camera shutter sound is forced or not  (country specific). -->
    <bool name="config_camera_sound_forced">true</bool>
```

```core/res/res/values/config.xml
    <bool name="config_camera_sound_forced">false</bool>
```

厳密には、日本のSIMをさしているかどうかではなく、
MCC=440のモバイルネットワークに接続したら、読み込むXMLが変わり、config_camera_sound_forced=trueの方を使う。

https://developer.android.com/guide/topics/resources/providing-resources.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/76aa27e9-375a-b507-1191-ac87b30ee638.png)

個人的にはかなり目からウロコだったんだけども、よく見たらリファレンスにもしっかり書かれていたわ・・・。

## 「強制鳴動する」の実装

これはいろんな記事で言及されているのでさらっと。

config_camera_sound_forcedフラグがtrueだったら、音パスを `AudioSystem.STREAM_SYSTEM_ENFORCED` にしているだけ。

## でも...

なお、日本では「シャッター音は何が何でも鳴らせ！」みたいな仕様をどこかの誰かが勝手に決めているので、この話は当てはまらないかもしれない。

だってほら、MCC=440関係ないWifiタブレットでもなぜかシャッター音鳴るじゃん？
自己紹介（2019.7.22更新）

#1.自己紹介
初めまして。関西で高校理科教員と不登校支援事業の管理者をしている「まつし」と申します。
現在27歳で、未経験からエンジニアになるために日々プログラミングを勉強しています。

#2.エンジニアを目指そうと思った理由
**2-1.学生〜社会人（バンドマン×教師）**
私は元々理科教員志望で大学に入学しました。在学中は教職課程と研究を両立させながら、友達と始めた音楽活動や事業の経営に勤しみました。
在学中に音楽活動が軌道に乗ってきたので、大学卒業後は教師一本の道は選ばずに、音楽の夢を追いバンドマンとして全国を周りライブをして、傍らで高校教師やカウンセラーをしながら生きていました。

**2-2.プログラミングとの出会い**
元々「大学を卒業して３年でメジャーデビューできなかったらやめる」とバンドメンバーに伝えていたので、３年が経った頃に音楽活動に区切りを付けました。正直未練もありましたが、これからの自分の人生と真剣に向き合う必要があるなと思い新しい道を模索し始めました。

音楽を始める前までは、元々教員志望だったので、音楽を辞めてからは教育業界で生きていこうと仕事を続けました。しかし、音楽を辞めて教師一本で働いても全く楽しくなく、抜け殻のような日々を過ごしていました。
そこで、音楽のように何か真剣に打ち込めるものを探しました。
動画編集やデザイン、ブログや投資など色んなものを一通り触ってみようと思い、その中で出会ったのがプログラミングでした。

元々理系という事もあり数学的な考え方が好きで、何かを作る事も好きなので、プログラミングの勉強は苦になりませんでした。むしろ楽しみながら勉強できている自分がいました。
また、日頃から「もっとこんなサービスがあればな」と考えていたので「せっかくプログラミングを始めたんだから自分で作ってみよう！」と思い、作ったサービスが教育系サービスの【IEDELAB】です。

[IEDELAB](https://iedelab.com)

当初はこのサービスを作る事を目標に、毎日コツコツ勉強しました。とにかくプログラミングにハマり、楽しみながら勉強している内にサービスが作れるようになりました。リリースした時の高揚感は今でも覚えています。

そして今「もっとこの分野の知見を広めたい」「もっとスキルを身に付けたい」と思うようになりました。
音楽を辞めて抜け殻状態だった私に、再び熱を取り戻させてくれたプログラミングでとことん勝負していきたいと思い、現在エンジニアを目指して勉強をしています。

**2-3.これからどう成長していきたいか**

大学時代には、物販系の事業。
社会人になり、音楽や教育業界に携わり
今、プログラミングに出会い世界の見方が変わりました

物流も音楽も教育も全てネットとの繋がりが強くなり、これからIT産業はもっと伸びると考えています。
その中で、関わってきた業界をリードしていくエンジニアになっていきたいと思っています。

音楽業界なら、不正ダウンロードサービスが横行する中しっかりとアーティストに還元できるシステムを取り入れたサービスを作り、音楽業界を助けたい。

教育業界なら、学校に行けない学生たちにも届くようなオンラインサービス（[IEDELAB](https://iedelab.com)のようなサービス）を作り、学生の夢を応援したい。
プログラミングが必修科する中で、教員の負担を減らせるようなサービスを元教員というキャリアを活かして作りたい。

色んな夢があります。
まだプログラマとしては未熟ですが、将来は作りたいなと思ったサービスを設計から全てできるエンジニアになりたいと思っています。

#ソフトウェア関係
**使用言語**

* HTML
* CSS
* JavaScript
* PHP
* MySQL

**フレームワーク**

* sass
* React
* BACKBORN.JS
* Vue.js
* Laravel

**開発環境**

テキストエディタはPHPStormを使用しています。
MAMPを使用して、ローカル環境で開発しています。

#その他
趣味は楽器演奏で、ベース弾けます。
動画編集とデザイン作れます。（IEDELABのロゴデザインは自分でしました）
Node.jsでLINE BOTの画像送信を試す


画像を送るカンタンなサンプルです。

最近デモで使おうと思うケースが多いけどスニペッドが見つからないことがあるのでメモがてら

ちなみにこの記事は、
`LINE BOT -> ユーザー`へ画像送信です。
`ユーザー -> LINE BOT`に画像送信をするのは[こちらの記事](https://qiita.com/n0bisuke/items/17c795fea4c2b5571ce0)などを参考にして下さい。

> [LINE BOTからNode.jsで画像を受け取って保存する](https://qiita.com/n0bisuke/items/17c795fea4c2b5571ce0)

## 公式ドキュメント

この辺のメッセージオブジェクトの仕様を確認しましょう。

https://developers.line.biz/ja/reference/messaging-api/#image-message

## いつもの記事を元にサンプルを書く

[1時間でLINE BOTを作るハンズオン](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)

いつもの記事です。
初めての人はまずこちらから。

## 画像リプライメッセージ

handleEvent関数をまるっと差し替えましょう。
画像は https://protoout.studio のサイトキャプチャです(笑)

```server.js
省略

function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  return client.replyMessage(event.replyToken,{
      type: 'image',
      originalContentUrl: 'https://i.gyazo.com/e772c3b48a07716226f7184d7f417cda.png',
      previewImageUrl: 'https://i.gyazo.com/e772c3b48a07716226f7184d7f417cda.png'
   });

}

省略
```

## 画像プッシュメッセージ

リプライのように使ってますが、Pushです。
こちらもhandleEvent関数をまるっと差し替えです。

```server.js
省略

function handleEvent(event) {
    if (event.type !== 'message' || event.message.type !== 'text') {
        return Promise.resolve(null);
    }
    
    const userId = `xxxxxxxxxxxxxxxxxxxxxxxx`;
    
    return client.pushMessage(userId,{
        type: 'image',
        originalContentUrl: 'https://i.gyazo.com/e772c3b48a07716226f7184d7f417cda.png',
        previewImageUrl: 'https://i.gyazo.com/e772c3b48a07716226f7184d7f417cda.png'
    });
}

省略
```

## 利用イメージ

何送ってもキャプチャ画像を送ってくれます。

> <img src="https://i.gyazo.com/5c9332544902421187095f63e63c4329.png" width="500px">

こういうときGyazoは便利ですね。
Go + Python + gRPC  技術調査


### Install

```shell

go get -u github.com/golang/protobuf/protoc-gen-go
go get -u google.golang.org/grpc
```


### ProtocolBufferの定義


`/protos`などをディレクトリを作ってそこに格納するのが正解? 


```proto

service {
  rpc GetFeature(Point) returns (Point) {}
  // rpc GetFeature(stream Point) returns (Feature) {} streamでやり取りする場合にはstreamをつける。
}

message Point {
  int32 latitude = 1; // 数字は単に識別のためのもので特に意味はない。
  int32 longitude = 2;
}
```

### GolangでのgRPCコード生成

```shell

protoc -I routeguide/ --go_out=plugins=grpc:routeguide routeguide/route_guide.proto 
```
- `-I ./routeguide` protoファイルが存在するディレクトリ?
- `--go_out=plugins=grpc:routeguide` 出力ディレクトリ
- `routeguide/route_guide.proto` 対象protoファイル


### pythonでのgRPCコード生成

```shell

pip install grpcio-tools
python -m grpc_tools.protoc -I./routeguide --python_out=./routeguide --grpc_python_out=./routeguide ./routeguide/route_guide.proto
```
- `-m grpc_tools.protoc` commandの指定?
- `-I ./routeguide` protoファイルが存在するディレクトリ?
- `--python_out=./routeguide` pythonの出力ディレクトリ1
- `--grpc_python_out=./routeguide` pythonの出力ディレクトリ2
- `./routeguide/route_guide.proto` 対象protoファイル


### GolangでのClient

```golang

import (
  "google.golang.org/grpc"
  pb "google.golang.org/grpc/examples/route_guide/routeguide"
)

func printFeature(client pb.RouteGuideClient, point *pb.Point) {
  log.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude)
  ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  defer cancel()
  feature, err := client.GetFeature(ctx, point)
  if err != nil {
    log.Fatalf("%v.GetFeatures(_) = _, %v: ", client, err)
  }
  log.Println(feature)
}

func main {
  var opts []grpc.DialOption
  opts = append(opts, grpc.WithInsecure()) // Connection uses plain TCP, TLS also exists

  serverAddr := "127.0.0.1:10000"
  conn, err := grpc.Dial(*serverAddr, opts...)

  if err != nil {
    log.Fatalf("fail to dial: %v", err)
  }
  defer conn.Close()

  client := pb.NewRouteGuideClient(conn)
  printFeature(client, &pb.Point{Latitude: 409146138, Longitude: -746188906})
}

```

### PythonでのServer

```python

import grpc

import route_guide_pb2
import route_guide_pb2_grpc
import route_guide_resources


class RouteGuideServicer():
    """Provides methods that implement functionality of route guide server."""

    def GetFeature(self, request, context):
        return route_guide_pb2.Feature(name="", location=request)


def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
        RouteGuideServicer(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    # server.stop(0)

if __name__ == '__main__':
    logging.basicConfig()
    serve()

```
Laravelでマイグレーションしてモデルファイルを作成する

LaravelでDBを扱うためにテーブル作成とモデルファイルの作成方法を紹介します。

# マイグレーションファイルの作成
下記コマンドでマイグレーションファイルを作成します。

```
php artisan make:migration create_shops_table --create=shops
```

__create_shops_table__部分はマイグレーションのファイル名になりますので任意に書き換えてください。
__--create=__の後の__shops__の部分はテーブル名になりますので任意に書き換えてください。
Laravelでは__テーブル名は複数形__で__モデル名称は単数形__というのが標準の命名規則になります。
この記事では
・テーブル名
shops
・モデル名
Shop
という名称で進めます。

すると__プロジェクトルート/database/migrations__にマイグレーションファイルが生成されます。

```php5
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateShopsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('shops', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('shops');
    }
}
```

これを下記のように変更します。

```php5
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateShopsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('shops', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name')->nullable()->comment('店舗名');
            $table->string('sub_name')->nullable()->comment('支店名');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('shops');
    }
}

```

マイグレーションファイルを編集したら下記のコマンドでマイグレーションを実行します。

```
php artisan migrate
```

こうするとDBにshopsテーブルが作成されます。

# モデルファイルの作成

マイグレーションを実行したら下記コマンドでモデルファイルを作成します。

```
php artisan make:model Shop
```

すると__プロジェクトルート/app__に下記のような__Shop.php__というファイルが作成されます。

```php5
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Shop extends Model
{
    //
}
```
Parrot MamboをMac(Mojave)から操作する - 2019版

Parrot manboを飛ばすのにrolling-spiderというライブラリーをベースにした記事がいくつかあるのですが、2019/7の私の環境では動作しなかったため、改めていくつかのライブラリーを試してみました。
nobleというBluetoothライブラリーが最新Mac、最新Xcode、最新Node.jsでの動作で追いついていないようで、このあたりは気が向いたらまた調査します。

# 前提

Node.jsのバージョンによっても動かなくなる可能性があるため、簡単にNode.jsのバージョンが切り替えられるよう、Node.jsのバージョン管理システムnodebrewなどを利用してNode.jsを入れることを推奨します。nodebrew、Node.jsのインストールは割愛します。

筆者は、Node.js v8.16.0にて動作確認できました。

ドローンは、以下のFPVなしのParront manboです。

https://www.parrot.com/jp/doron/parrot-mambo-fly

# minidrone for Node.jsのインストール

以下のコマンドでライブラリーをインストール。

```sh
npm install minidrone
```

ついでに、サンプルで  temporal を利用しているのでそちらもnpmインストール。

```sh

npm install temporal
```

# サンプル・コードで飛ばす

以下のコードをfirstFlight.jsとして作成。

```js
const minidrone = require('minidrone');
const temporal = require('temporal');
const drone = new minidrone.Drone();

drone.connect(function() {
  drone.setup(function() {
    drone.flatTrim();
    drone.startPing();
    drone.flatTrim();
    console.log('Connected to drone', drone.name);

    temporal.queue([
      {
        delay: 2000,
        task: function() {
          drone.takeOff()
          drone.flatTrim()
        },
      },
      {
        delay: 2000,
        task: function() {
          drone.forward({ steps: 30 }, function(){console.log('forward 30', drone.name);})
          drone.flatTrim();
        },
      },
      {
        delay: 2000,
        task: function() {
          drone.backward({ steps: 30 }, function(){console.log('backward 30', drone.name);})
        },
      },
      {
        delay: 2000,
        task: function() {
          drone.land()
        },
      },
      {
        delay: 2000,
        task: function() {
          temporal.clear()
          process.exit(0)
        },
      },
    ]);
  })
});

```

※ `forward`,`backward`という関数は、2つめの引数のcallback関数を省略するとエラーになりました。

以下のコマンドで飛ばす。

```sh
node firstFlight.js
```

離陸、前進、後退、着陸したら成功です。お疲れ様でした。



# もっといろいろな飛行をさせたい

公式のAPIを見てみましょう。https://github.com/jongear/minidrone

# 参考

他に試したmambo制御ライブラリーたち。

| ライブラリー名             | URL                                                  | 2019/7テスト結果                   |
| -------------------------- | ---------------------------------------------------- | ---------------------------------- |
| Mini Drone for Node.js     | https://github.com/jongear/minidrone                 | 本記事参照                         |
| Rolling Spider for Node.js | https://github.com/voodootikigod/node-rolling-spider | インストール(ビルド)エラー。       |
| Minidrone-js               | https://github.com/Mechazawa/minidrone-js            | 応答しない。Bluetooth接続できない? |
| pdrone                     | https://github.com/algolia/pdrone                    | 応答しない。Bluetooth接続できない? |
Rでヘッダの無いcsvを保存しようとwrite.csvを使うと無視されるので、その回避手段

# はじめに
超小ネタですが、表記の件で地味に困ったことがあったので対応策を書きます。

#本題
write.csvで次のようにヘッダが出ないように出力しようと思っても無視されてしまい、ヘッダ付きのcsvが出力されてしまいます。

```R
> write.csv(test.data$X, "test.csv", col.names = F)
 警告メッセージ: 
 write.csv(test.data$X, "test.csv", col.names = F) で: 
   'col.names' への変更の試みは無視されました 
```

これはwrite.csvの意図的な設計で、ヘルプにも書いてありました。

```R
> ?write.table
（略）
CSV files
（略）
These wrappers are deliberately inflexible: they are designed to ensure that the correct conventions are used to write a valid file. Attempts to change append, col.names, sep, dec or qmethod are ignored, with a warning.
```

どうしても、ヘッダを除外したい場合は、代わりにwrite.tableを使うことで対応できます。

```R
> write.table(test.data$X, "test.csv", col.names = F, sep = ",")
```

#検証環境
- R 3.6.1
- RStudio 1.2.1335
- macOS Mojave 10.14.5

#参考文献
- [write.table Rドキュメント](https://www.rdocumentation.org/packages/utils/versions/3.5.1/topics/write.table)
PWAのSprach Screen対応メモ

## まとめ

- Android
    - `manifest.json`に以下のものが記載されていれば自動で認識される
- iOS
    - 各iOSデバイスごとの画像が必要
    - `link`要素で画像を指定する際、画像サイズ、画像解像度、縦向き横向きも指定する
    - オンラインだが[iOS Splash Screen Generator](https://appsco.pe/developer/splash-screens?source=post_page---------------------------)があったりする
        - Sketch用の[iOS Splash screens template](https://www.sketchappsources.com/free-source/855-ios-splash-screens-template.html)とかもあるみたい

## 補足

### Splash Screensとは

PWAに限らずスマホでアプリを最初に起動したとき、最初のコンテンツがレンダリングを開始するまでに少し時間がかかることがある。そこで白い画面が表示される代わりにたちあがるのがSplash Screen（起動画面）。

### Androidはいい感じになるけど

Chromeは`manifest.json`に以下が記載されているといい感じにスプラッシュ画面を表示する。

- `name`プロパティ
- `background_color`
- 512px x 512pxの`.png`アイコン

しかしiOSはAndroidと異なり、いつものようにHTMLで`<link rel ="apple-touch-startup-image">`を指定しかつ各iOSデバイス用に調整されたスプラッシュスクリーンを提供する
必要がある。

### iOSでの対処法

実装方法としては以下：

1. 画像用意
2. HTMLで画像設定

#### 1. 画像用意

面倒なことに、画像1つだけ`<link rel="apple-touch-startup-image">`に指定しても反映されない。各iOSデバイスの大きさの画像を作り、ターゲットとするデバイスの幅、高さ、`orientation`、`device-pixel-ratio`を定義した`media`属性を追加する必要がある
（ちょっと理由が見つけられなかった…誰かわかる方がいらっしゃいましたらご教示ください）

Scketchのテンプレートなどを用いて画像を用意するでもいいし、Appscopeが[Generator](https://appsco.pe/developer/splash-screens?source=post_page---------------------------)を作ってくれていたりするのでそれを利用するでもいいかもしれない。

このGeneratorは`orientation`をサポートしてないので注意（指定しないと、横向きで起動した際に白い画面が表示される。適用されないだけで、縦向きのみ適用される）

#### 2. HTMLで画像設定

前述したように`<link rel="apple-touch-startup-image">`にはターゲットとするデバイスの幅、高さ、`orientation`、`device-pixel-ratio`を定義した`media`属性を追加する必要がある。

たとえばiPhone SEをターゲットにすると以下のような感じになる：

```html
<link rel="apple-touch-startup-image" media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/img/icon_1136x640.png">
```

どのデバイスがどのサイズかは割愛（[Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/launch-screen/)またはこの記事を書いている際に見つけた[iPhone画面サイズ早見表（図付き） - Qiita](https://qiita.com/TD3P/items/b3b754bde584abc98f44)を参照)

これ対象デバイス分書くのつらいorzって思うときは、Generatorをベースに横向き画像分を追記して使ったり[Enabling iOS Splash Screens for Progressive Web Apps](https://blog.expo.io/enabling-ios-splash-screens-for-progressive-web-apps-34f06f096e5c)という記事内で紹介されていた[GistのサンプルHTML](hhttps://gist.github.com/EvanBacon/7fd4dc3be3d00096579bb0b134c56ec7?source=post_page---------------------------)を参考に作ってみると多少なり楽かもしれない。

## 参考リンク

- [PWA Tips and Tricks](https://robferguson.org/blog/2018/09/14/pwa-tips-and-tricks/)
- [Enabling iOS Splash Screens for Progressive Web Apps](https://blog.expo.io/enabling-ios-splash-screens-for-progressive-web-apps-34f06f096e5c)
- [【解決方法】iOS端末でPWAのスプラッシュ画面が真っ白になる - Qiita](https://qiita.com/NaokiIshimura/items/2b18ce82c936399b695c)
- [Progressive Web App Splash Screens - Dave Hudson - Medium](https://medium.com/@applification/progressive-web-app-splash-screens-80340b45d210)
- [Adding Custom iOS Splash Screens To Your Progressive Web App](https://medium.com/appscope/adding-custom-ios-splash-screens-to-your-progressive-web-app-41a9b18bdca3)
シェルスクリプト

Pythonを触り始めて2年。なんとかシェルスクリプトから逃げていましたがついに逃げられなくなりました。

以下奮闘記です。

### 1.現在地を知りたい
```
SCRIPT_DIR=$(cd $(dirname $0); pwd)
```
`$0`は実行ファイルのパスを返してくれます。

### 2.現在地の親ディレクトリのパスを知りたい
```
PAR_DIR=$(cd $(dirname $0); cd ../; pwd)
```

### 3.入力を受け付けたい
```bash:input.sh
input1 = $1
input2 = $2
```
`bash input.sh inp1 inp2`
$NがN番目の引数になります。

### 4.変数を使いたい
```
FILENAME = $1
SCRIPT_DIR = $(cd $(dirname $FILENAME); pwd)
echo 'path for ${FILENAME} is ${SCRIPT_DIR}'
```
やっていることは1.と同じですね。
Leetcode #441: Arranging Coins

```swift
func arrangeCoins(_ n: Int) -> Int {
    var l = 1
    var r = n
    while l<=r {
        let mid = l + (r - l) / 2
        let s = mid * (mid + 1) / 2
        if s == n {
            return mid
        } else if s > n {
            r = mid - 1
        } else {
            l = mid + 1
        }
    }
    return r
}
```
数字当てゲーム（Python）+独自ルール

Pythonで数字当てゲームを作ってみようかという遊びです。
数字当てだけでは、面白くないので、コンピュータと競わせるように
独自ルールを作りました。

- 1〜9の間の数字を入力
- 1度使った数字は、使えない
- コンピュータと同じ数字を使った場合は、スコアーに加算されない
- コンピュータと違う数字を使った場合は、スコアーに加算される

# 技術解説

```python
import random

# 1-9の数字を用意
raw_list = [1, 2, 3, 4, 5, 6, 7, 8 , 9]
score = 0

# ゲームスタート
print('Please enter')

while True:
  print(raw_list)

  # PCの出す手を用意
  pc_card_idx = random.randrange(len(raw_list))
  pc_card = raw_list[pc_card_idx]

  # 入力待ち
  while True:
    s = input('>> ')
    if str.isdecimal(s):
      your_card = int(s)
      if your_card in raw_list:
        your_card_idx = raw_list.index(your_card)
        break

  # 判定
  if your_card == pc_card:
    raw_list.remove(pc_card)
  else:
    raw_list.remove(pc_card)
    raw_list.remove(your_card)
    score += your_card

 # 手札を見せ合う
  print('your card: {0}. pc card: {1}. Now Score: {2}'.format(your_card, pc_card, score))


  if len(raw_list) <= 1:
    break

print('Your Score Is {}'.format(score))

```
# さいごに
次回は、数字を学習するAIを作成してみたいです。
Pythonで動作するルールベースエンジンについて調べた

Python上で動作するルールベースエンジンを調査しました。

## ルールベースエンジンを使う場合
次のページにわかりやすい説明が書かれています。

- [なぜルールエンジンを使うのか(ver3.0.5) 翻訳α版 ](http://www.iluminado.jp/businessruleruleengine/rule-engines/37-rule-engines-business-use.html) （ビジネスルールの館）

## python上のルールエンジン
実際にルールを定義して動作させることができるものをピックアップしました。

- [business-rules](https://pypi.org/project/business-rules/)
    * 参考：[business-rulesを使ってルールエンジンを使った処理を書く](http://ariarijp.hatenablog.com/entry/2017/11/19/134152)
    * 否定条件の書き方がわかりにくい
- [durable_rules](https://pypi.org/project/durable-rules/)
    * 参考：[機械学習全盛だけど、あえてルールエンジンを試す -Pythonのdurable_rulesを試す-](https://qiita.com/ike_dai/items/8ea8b4a1b0b0180d939e)
    * Redisが必要（PurePythonでない）
- [Pyke](https://pypi.org/project/pyke/)
    * ロジックプログラミング、Prologもどき
    * 後ろ向き推論
* PyKnow: Expert Systems for Python
    * [buguroo/pyknow(Github)](https://github.com/buguroo/pyknow)
    * 日本語の情報はなく、英語でも情報は少ない
    * 2019/07/20現在、PyPIから消えている
        * Githubから取得してインストールできる

## そのほかのルールベースエンジン
+ [Toy Open Production System](https://ja.osdn.net/projects/toy-open-ps/) C++
+ [ops5](https://github.com/johanlindberg/ops5) lisp
+ [briangu/OPS5](https://github.com/briangu/OPS5) lisp
+ [CLIPS](https://ja.wikipedia.org/wiki/CLIPS) C++
* その他　→　参考：[オープンソースのルールエンジン ビジネスルールの館](http://www.iluminado.jp/businessruleruleengine/rule-engines/23-oss-rule-engines.html)
NCBIからダウンロードしたdocsumをXML parseする

# NCBIからダウンロードしたdocsum
ダウンロードする
`esearch -db assembly -query "Viruses"[Organism] | efetch -format docsum > viruses.xml`

これをpython3でparseしようとするとできない。


# 解決策
これでparseできる (2019年7月22日現在)。

```python
#!/usr/bin/env python3

import xml.etree.ElementTree as ET

lines=['<?xml version="1.0" encoding="UTF-8" ?>\n',
       '<!DOCTYPE DocumentSummarySet PUBLIC "-//NLM//DTD esummary assembly 20180216//EN" "https://eutils.ncbi.nlm.nih.gov/eutils/dtd/20180216/esummary_assembly.dtd">\n',
       '<DocumentSummarySet status="OK">\n',
       '</DocumentSummarySet>\n']

new_xml='<DocumentSummarySet>\n'
with open('viruses.xml') as f:
    for line in f:
        if not line in lines:
            new_xml += line
new_xml += '</DocumentSummarySet>\n'

root=ET.fromstring(new_xml)

```
Leetcode #438: Find All Anagrams in a String

```swift
func findAnagrams(_ s: String, _ p: String) -> [Int] {
    if p.count > s.count {
        return []
    }
    var pDict = Array(repeating: 0, count: 26)
    for char in p {
        pDict[Int(char.asciiValue!) - 97] += 1
    }
    
    var s = Array(s)
    var answer = [Int]()
    var sDict = Array(repeating: 0, count: 26)
    for i in stride(from: 0, to: p.count, by: 1) {
        sDict[Int(s[i].asciiValue!) - 97] += 1
    }
    if isAnagram(sDict, pDict) {
        answer.append(0)
    }
    for i in stride(from: 0, to: s.count - p.count, by: 1) {
        sDict[Int(s[i].asciiValue!) - 97] -= 1
        sDict[Int(s[i+p.count].asciiValue!) - 97] += 1
        if isAnagram(sDict, pDict) {
            answer.append(i+1)
        }
    }
    return answer
}

private func isAnagram(_ s: [Int], _ p: [Int]) -> Bool {
    for i in stride(from: 0, to: 26, by: 1) {
        if s[i] != p[i] {
            return false
        }
    }
    return true
}
```
Java学習メモ（配列の作成）

忘備録用のメモなので詳細は記載していません。

＜配列の作成＞

・配列の宣言方法

　柔軟性があり、以下のような宣言が可能である。
　[]の数で何次元配列か決めることができる。

　① int[] a;
　② int a[];
　③ int[][] a;　二次元配列
　④ int[] a[];　二次元配列
　⑤ int[][] a[];　三次元配列

・配列インスタンスの生成
　
　1) 要素数を指定する。
　　以下は3つのint型の要素を扱う配列インスタンスを生成し、配列型変数numに代入している。※参照型
　　要素数の指定にはint型であれば式を使うことも可能である。

　　int[] num = new int[3];
　　int[] num = new int[2*3];　※int型の値を戻す計算式

　2) 初期化演算子
　　初期化演算子{}を使用して、インスタンス生成と初期化を同時に行うことができる。
　　以下は３つのString型の要素を持った配列型変数strとなる。

　　String[] str = {“A”,”B”,”C”};

　3) あとから二次元配列の生成を行う。
　　先に一次元目の要素数を指定し、二次元目はあとから、一次元目の配列の要素として代入を行う。

　　int [][] num = new int[2][];
　　num[0] = new int[3];
　　num[1] = new int[2];

　　上記のように異なる要素数を指定することも可能である。
outline（輪郭線）という記憶の外に置かれがちなCSSプロパティのメモ

outline って、なんか影が薄い気がする。<sup>（※個人の感想です）</sup>
#概要
**outline** は、要素の輪郭線を指定する。
輪郭線は **border**（境界線）の外側に描画され、多くは四角の枠線となる。
使い方は **border** とおおむね同じだが、以下の違いがある。

 - 上下左右を個別に設定できない
 - 角丸（**border-radius**）に相当するものがない
 - **outline-offset** なるプロパティで表示位置を調整できる（ただしIEでは全てのバージョンでサポートされない）

（※厳密には、**outline** は **outline-style**、**outline-width**、**outline-color** の3つのプロパティを同時に指定するショートハンド）

**outline-offset** 以外は CSS2.1 で勧告されたプロパティであり、よほど古いブラウザでなければ利用できる。

#特徴と応用例
**outline** は **border** と同程度以下の表現しかできないが、ボックスモデルから独立して設定でき、レイアウトに影響しないという特徴がある。**border** と同時使用すれば1つのボックス要素に2種類の枠線を描ける。

用途としては、ブラウザのフォーカス枠（キーボードで操作する場合などに現れる）の表示、入力フォームにおける必要項目や重要な段落のハイライトなど、一時的に使われるケースが多いように思われる。

しかし、**もっぱら視覚デザインのためにのみ使われる要素**ならば、恒常的に **outline** を表示させてもよいだろう。

##border と outline で枠線を２つ引く
下の例は、赤いドットの border の外側に、黄色いドットの outline を表示している。
![s20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87385/c81f4a2a-bcaf-6ea2-dd87-aec4ddd171f4.png)

```css:
/* 枠線を２つ引く */
div{
  border:  0.6em #f00000 dotted;
  outline: 0.8em #ffdd00 dotted;
}
```

##outline-offset で表示位置を変える
下の例は、赤色の border の少し内側に、黄色の outline を重ねて表示している。黄色は半透明なので、重なった部分がオレンジ色になっている。
![s20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87385/dab9e0df-549d-6489-6e8a-0f673d8ab673.png)
outline-offset は、outlineの表示位置を border外側からの相対距離で指定する。IEでは全てのバージョンでサポートされない。
マイナス値にすれば borderの線上や内側に outlineを表示できる。


```css:
div{
  padding: 1em;
  border:  1em #ff0000 solid;
  outline: 1em #ffff0080 solid;
  outline-offset: -1.5em;
}
```

border の場合、太さ（border-width）を変えるとコンテンツ領域のサイズに影響するが、outline は干渉しない。また外側にある他の要素に重なってもレイアウトには影響しない。
ガチガチに組まれた職人的デザインでも安心か。
Leetcode #434: Number of Segments in a String

```swift
func countSegments(_ s: String) -> Int {
    var count = 0
    var index = 0
    let str = Array(s)
    var hasChar = false
    while index < str.count {
        if str[index] != " " {
            if !hasChar {
                hasChar = true
                count += 1
            }
        } else {
            hasChar = false
        }
        index += 1
    }
    return count
}
```
無料で使える！効率化！マーケティング＆業務＆アプリ開発で使える便利ツールまとめ

# はじめに
先日、会員制のカフェで開かれるセミナーに参加してきました。
[「スイーツを食べながらテクノロジーを学ぶ会～超便利！明日使える無料ツールを大紹介～」](https://eventinfo.benkyo-cafe.net/event/53642)

その中で紹介されたツールを箇条書きで紹介します。
概要のみで使用方法などの詳細は紹介致しませんのでご留意いただければと思います。
基本無料ですが、中には従量課金のサービスもありますのでご注意下さい。

# セミナーの講師の方
普段は企業でWeb系のコンサルティングやマーケティングを行なっており
自分が業務等で使用しているツールをご紹介いただきました。
Udemyで講師もされているようです。
講師の方のツイッター:point_down:
https://twitter.com/shufu_gaishi

# 紹介されたツール
それぞれ以下の点をご紹介します。
 - ツールの提供元URL
 - 概要
 - ツールについて詳しい記述があるサイト(ブログ等)があった場合はそのURL

## Mentimeter
https://www.menti.com/
 - プレゼンツール
 - リアルタイムでアンケート、投票(いいね、ハート等)が行える（スマホからでも可能）
 - アカウント登録の必要がない為、インターネット環境があれば気軽に使用できる
 - 今回のセミナーは実際にこちらを使用して実施

## GoogleAnalytics
https://analytics.google.com/analytics
 - 言わずも知れた自社サイト分析ツール
 - サイトの流入元、訪問時間、色々な情報が解析される

## juicer
https://juicer.cc
 - 同じく自社サイト分析ツール
 - GoogleAnalyticsより解析範囲は狭いが、深い情報が知れる(訪問者の性別、年代、場所、企業名等)
 - GoogleAnalyticsでの解析結果と情報を合わせることでより詳細な解析が可能に
 - アクセスにくる人のペルソナ(大体の人物像)も生成される

## Similarweb
https://www.similarweb.com/ja
 - 他サイトのアクセス状況をリサーチする
 - 解析したいサイトのURLを入力するだけで「アクセス解析」や「検索キーワード」などを解析
*詳しい記述があるサイト*
https://ferret-plus.com/489

## Power BI
https://powerbi.microsoft.com/ja-jp/
 - レポート作成ツール
 - データをチャートやグラフで可視化してくれる
 - クライアントソフトもあるのでデータがクラウドに上がる事はないので重要なデータも安心して使える
*詳しい記述があるサイト*
https://www.cloudtimes.jp/dynamics365/blog/what-is-powerbi.html

## tableau
https://www.tableau.com/ja-jp/products/what-is-tableau
 - こちらもレポート作成ツール
 - データをチャートやグラフで可視化してくれる
 - Google Analyticsとの連携機能もある

## GoogleTrends
https://trends.google.co.jp/trends/
 - 最近の検索されたホットなキーワードがわかる
 - キーワードがどの地域でバズっているかもわかる
 - 期間、国、地域を選択してキーワードごとに比較する事も可能
*詳しい記述があるサイト*
https://keywordfinder.jp/blog/seo/googletrend/

## IBMWatson
https://www.ibm.com/watson/
 - IBMクラウドに登録することで使用可能
 - 画像解析、音声解析、文章解析などがRestAPIでコールできるようになっている為、簡単に使用可能
*詳しい記述があるサイト*
https://www.ibm.com/blogs/solutions/jp-ja/watson-api-matome/

## flowxo
https://flowxo.com/
 - チャットボット作成ツール
 - ノンプログラミング、全てUIで設定が可能

## Dialogflow
https://dialogflow.com/
 - チャットボット作成ツール
 - ノンプログラミング、全てUIで設定が可能
*詳しい記述があるサイト*
http://www.nct-inc.jp/engineer_blog/3064/

## Hubspot
https://www.hubspot.jp
- CRMツール
- Webサイト、チャットボット作成も可能
- 機能の少ない◯ales◯orceみたいな感じ
*詳しい記述があるサイト*
https://goworkship.com/magazine/hubspot-howtouse/

## STUDIO
https://studio.design/ja
- Webサイト作成ツール
- ノンプログラミングで可能
- 全てUI（ドラッグ&ドロップ、クリック等）で作成できる
*詳しい記述があるサイト*
https://webkikaku.co.jp/blog/webservices/studio-design-tool/

## Nibbler
http://nibbler.silktide.com
 - Webサイトテストツール
 - URLを入力するだけでWebサイトのアクセシビリティ、SEOなどを解析
 - スコア(10点満点)も出してくれる
*詳しい記述があるサイト*
https://nelog.jp/nibbler

## ちえのわ
https://tienowa.herokuapp.com/ajax
 - SEO対策ツール
 - 単語を入力するだけで関連するキーワードを探してくれる
*詳しい記述があるサイト*
https://trend-tracer.com/post-1248/

## GoogleDocument
https://www.google.com/intl/ja_jp/docs/about/
 - 文書（ワープロソフト）
 - 音声入力の精度が非常に高い（そのまま議事録にできるレベル）
*詳しい記述があるサイト*
http://pasokatu.com/14226

# 所感
無料で使えるという事が、驚愕のツールばかりでした:open_mouth:

中でも「STUDIO」は隣のWebデザイナーさんが「これは仕事なくなる...」と苦笑いしていました:sweat_smile:

既知のツールもありましたが、組み合わせ使う事でより威力を発揮するものもありました。

今後もこういったツールもウォッチ、活用していく事で業務の効率化、及び質の向上に務めたいと思います。
そして何よりも新しいツールを使っているときって楽しいですよね:relaxed:
Leetcode #415: Add Strings

```swift
func addStrings(_ num1: String, _ num2: String) -> String {
    let s1 = Array(num1.reversed())
    let s2 = Array(num2.reversed())
    var i = 0
    var carry = 0
    var answer = [Int]()
    while i < s1.count || i < s2.count {
        let tmp1 = i < s1.count ? Int(s1[i].asciiValue!) - 48 : 0
        let tmp2 = i < s2.count ? Int(s2[i].asciiValue!) - 48 : 0
        let sum = tmp1 + tmp2 + carry
        answer.append(sum % 10)
        carry = sum / 10
        i += 1
    }
    if carry != 0 {
        answer.append(1)
    }
    var result = ""
    for num in answer.reversed() {
        result += "\(num)"
    }
    return result
}
```