OmniAICreator/Qiita-1.07M huggingface dataset:
rubyのブロック処理における配列関連のメソッドメモ


[チェリー本](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AERuby%E5%85%A5%E9%96%80-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%83%BB%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%8A%80%E6%B3%95%E3%81%BE%E3%81%A7-Software-Design-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/4774193976)を参考にした。このあたりよく忘れるのでメモっておく
##each
普通のfor文と同じ役割

```
num = [1,2,3,4]
sum = 0
num.each do |n|
  sum += n
end
print sum #=> 10
```

## each_with_index
eachについて配列のインデックスも扱うことができる

```
num = [1,2,3,4]
num.each_with_index do |i,n|
  p "#{i}:#{n}"
end
#出力は以下の通り
#0:1
#1:2
#2:3
#3:4
```

##map
ある配列の要素に対する処理結果を別配列に返す

```
num = [1,2,3,4]
new_num = []
new_num = num.map do |n|
  n * 10
end
print new_num #=> [10,20,30,40]
```

エイリアスメソッドであるcollectも同様の使い方が可能

## select/find_all
ある配列の要素について、条件に一致しているものを返す

```
num = [1,2,3,4]
new_num = num.select do |n|
  n.odd? #nが奇数のものをnew_numへ格納
end
print new_num  #=> [1,3]
```

エイリアスメソッドであるfind_allも同様の使い方が可能

## reject
ある配列の要素について、条件に一致していないものを返す
要するにselect/find_allの反対

```
num = [1,2,3,4]
new_num = num.select do |n|
  n.odd? #nが奇数でないものをnew_numへ格納
end
print new_num  #=> [2,4]
```

## find/detect
ある配列について、戻り値が真かつ最初の要素を返す

```
num = [1,2,3,4]
new_num = num.find do |n|
  n.odd?
end
print new_num #=> 3
```

エイリアスメソッドであるdetectも同様の使い方が可能

## inject/reduce
ある値を初期値として配列各要素を足しこむ。eachの拡張か。

```
num = [1,2,3,4]
sum = num.inject(0) do |result,n|
  result += n #初期値0に各要素をすべて足しこむ。初期値が異なれば結果も異なる。
end
print sum #=> 10
```

当然ながら文字列の結合処理にも利用可能
エイリアスメソッドであるreduceも同様の使い方が可能

## その他
map/collectとinject/reduceの思想の違いらしい。エイリアスというくらいなので多分map処理を名前変えてcollectとかしてんだろうな。要するに実装上の違いはないと思うがどうなのか。。。
https://magazine.rubyist.net/articles/0038/0038-MapAndCollect.html#map-%E3%81%A8-collect-%E3%81%AE%E7%99%BA%E6%83%B3%E3%81%AE%E9%81%95%E3%81%84
GitHubとVSCODEの連携方法

#はじめに

初めまして！何度やっても時間が開くとついつい忘れてしまいがちな
GitHubとVSCODEの連携方法を自分用の備忘録として投稿。

〜未来の私へ〜
コマンドの前に記載されている`$`は抜いてからコマンドを動かすこと
いつも余分に`$`が入っているから怒られているよ・・・

#開発環境
 
| ツール名 | バージョン |
|:-----------|:------------|
| OS | macOS Mojava 10.14.5 | 
| Git |  2.20.1 |

#GitHub 初期設定

以下のコマンドを打ち込む。
`--global`と打ち込むことで、ユーザー情報を設定するから
一度打ち込めば再度設定する必要はない（らしい）

```
$ git config --global user.name "GitHubに登録しているユーザー名"
$ git config --global user.email GitHubに登録しているメールアドレス
```
#リポジトリ作成

1. GitHubにログインしてプロフィール写真横の「+」をクリック
2. 「New repository」を選択

![スクリーンショット 2019-07-06 22.07.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413382/986f6fe7-ccde-3b5c-f668-055334702552.png)


3.「Reposiltory name」にリポジトリ名を入力
　
4. 自分で作るのはめんどくさいので READMEにチェックを入れる
　　これにチェック入れるだけで、勝手にMarkdownのファイル作ってくれるからめちゃくちゃ助かる:raised_hands:
5. 最後に「Create repository」をクリックして作成

![スクリーンショット 2019-07-06 22.55.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413382/26c98376-3413-5c87-5cde-b07f9224e447.png)


これでリポジトリの作成完了！
そして、次の作業のために「Clone or download」をクリックしてリポジトリのURLをコピーしておく。
![スクリーンショット 2019-07-06 22.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413382/041d153e-a557-256b-000b-f131d330a3c5.png)

#リポジトリをローカルにクローン

（訳）ローカル（自分のパソコン）にリポジトリの中身をダウンロードすること
　　一度自分のローカルにソースを落としてから作業をする
　　※この時、ターミナル上ではダウンロードしておきたいフォルダに移動しておくと◎:ok_woman:

```
$ git clone 先ほどコピーしたURL
```

# 開発してGitHubに追加

VSCODEを用いて開発💻

ソース管理画面を開くと変更箇所に色がついてる〜〜〜！！！
という感じに自分の変更した場所に色がつきます:ok_woman:

1. ソース管理画面を開く
2. 変更箇所を確認
![change.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413382/78054786-2c2a-d6f2-bd95-10e27905e912.png)
3. 変更したファイルの「＋」をクリックしてステージングする
4. コメントを入力して、「✔︎」をクリックしてコミットする  
![commit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413382/40e87881-d837-8f95-7f18-7a5137610e39.png)
5. 「・・・」をクリックしてメニューを開き、「プッシュ」を選択
![スクリーンショット 2019-07-07 17.09.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413382/6b6a7f7b-63b1-0bb9-0534-63bd2ccee3ac.png)  
以上の方法でGitHubに追加されます！
次は、既に作成済みのファイルをGitHubに追加する方法もアウトプットしたい:thinking:

#参考サイト
先輩に教えてもらった後に、この記事書くのにお世話になりました！

[最初のGitの構成](https://git-scm.com/book/ja/v1/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-%E6%9C%80%E5%88%9D%E3%81%AEGit%E3%81%AE%E6%A7%8B%E6%88%90)
[Markdownの記法](https://qiita.com/tbpgr/items/989c6badefff69377da7)
Rubyのゲッター、セッター、initializeについて

```ruby:car.rb
class Car

  def initialize(color)
    @color = color
  end

  # ゲッター
  def color
    @color
  end

  # セッター
  def color=(color)
    @color = color
  end
end

# インスタンス化する際にinitializeメソッドに値を渡す
car1 = Car.new("red")
car2 = Car.new("green")
car3 = Car.new("blue")
# car1.color = "gray"

# colorを呼び出すと代入された値が表示される
puts car1.color
puts car2.color
puts car3.color
```
↑こういうrbファイルがあったとする。

これをターミナル上で実行`ruby car.rb`すると下記のような結果になる

```
red
green
blue
```

#疑問に思ったこと

`initialize(color)` は引数`(color)`で
car1 = Car.new("red")の`("red")`を受け取ることができている。

「えっ・・・これセッターを書く意味ある？」と疑問に思ったのだ。
試しにセッターをコメントアウトして、再度ターミナルの結果を見てみる

```ruby:car.rb
class Car

  def initialize(color)
    @color = color
  end

  # ゲッター
  def color
    @color
  end

  # セッター
  # def color=(color)
  #   @color = color
  # end
end

# インスタンス化する際にinitializeメソッドに値を渡す
car1 = Car.new("red")
car2 = Car.new("green")
car3 = Car.new("blue")
# car1.color = "gray"

# colorを呼び出すと代入された値が表示される
puts car1.color
puts car2.color
puts car3.color
````

結果↓

```
red
green
blue
```

「えっ・・・これホンマにセッター書く意味ないやん、、、
試しに`car1.color = "gray"` でcar1.colorの値もちゃんと返ってくるか確かめてみよ」

```ruby:car.rb
class Car

  def initialize(color)
    @color = color
  end

  # ゲッター
  def color
    @color
  end

  # セッター
  # def color=(color)
  #   @color = color
  # end
end

# インスタンス化する際にinitializeメソッドに値を渡す
car1 = Car.new("red")
car2 = Car.new("green")
car3 = Car.new("blue")
car1.color = "gray" #ここのコメントアウト外した

# colorを呼び出すと代入された値が表示される
puts car1.color
puts car2.color
puts car3.color
````

結果↓

```
Traceback (most recent call last):
class.rb:22:in `<main>': undefined method `color=' for #<Car:0x00007ffe6b172520 @color="red"> (NoMethodError)
Did you mean?  color
```

「おっ！エラーはいた。（良かった〜）」
#わかったこと
initializeメソッドは初期値を受けとれるだけ。
なので今回の`car1.color = "gray"`のように後から代入する可能性も考えると
セッターの記述は必要。

ちなみにセッターのコメントアウトも外して、再度実行すると`car1.color`の出力値を更新することができた。

```ruby:car.rb
class Car

  def initialize(color)
    @color = color
  end

  # ゲッター
  def color
    @color
  end

  # セッターのコメントアウトを外した
  def color=(color)
    @color = color
  end
end

# インスタンス化する際にinitializeメソッドに値を渡す
car1 = Car.new("red")
car2 = Car.new("green")
car3 = Car.new("blue")
car1.color = "gray"

# colorを呼び出すと代入された値が表示される
puts car1.color
puts car2.color
puts car3.color
```

結果↓

```
gray
green
blue
```

オブジェクト指向って難しいね〜（大満足）
RHEL7 DockerRegistryレジストリ構築 Enterprise Edition ～運用編～

RHEL7 DockerRegistryレジストリ構築 Enterprise Edition ～構築編～
https://qiita.com/guttikunn/items/2f0bd6e745f182c93c45

でDockerレジストリの構築は無事終了しました。
それではDockerレジストリを使い倒しましょう。

#やること
リポジトリの作成/適切な権限付与
pull/pushを行う

#リポジトリ構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174900/a8f07946-b302-ac8b-f363-173c1759d549.png)

・制限事項
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174900/7872f59c-b3dd-b18e-e47d-9a66b1d1f91c.png)

#構築手順
1.ユーザの作成
2.組織の作成
3.チームの作成
4.リポジトリの作成
5.リポジトリの割り当て
6.pull/push操作

#1.ユーザの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174900/6df4adb9-a3cf-6fde-8d01-7b599d504e5f.png)

#6.pull/push操作

作ったレジストリにpull/pushしましょう。

```
$ docker tag registry.access.redhat.com/rhel7 172.17.0.1:443/giants/giants_repo1:RHEL7_1.0
$ docker push 172.17.0.1:443/giants/giants_repo1:RHEL7_1.0
```
Raspbian Busterのインストール

# Raspberry Pi 3 ModelBを買ってみた
Raspberry pi1 ModelBしかもっていなかったのでRaspberry pi3 ModelBを秋葉原で購入しました。
Raspberry pi4の日本販売まで待ちきれなかった…

# Rasbianのインストール

Deabin Busterがリリースされる前なのに、Rasbianでは実装されているようです。

## Macでの作業

- imgのダウンロード
- ddコマンドで、SDカードへコピー
- SSHの有効化
- IPアドレスの確認
- piユーザーのパスワード変更

## imgのダウンロード
https://www.raspberrypi.org/downloads/raspbian/
リンク先より、Lite版をダウンロードする。

## ddコマンドで、SDカードへコピー

事前にSDカードのマウントポジションを調べておきます。
`diskutil list`
今回は、disk2で作業します。

### SDカードのアンマウント
```Terminalで実行
$ sudo diskutil unmountDisk /dev/disk2
```
### DDコマンドでimg書き込み
```
$ sudo dd bs=1m if=/Users/xxxxxxx/Download/raspbian.img of=/dev/disk2
```
コマンドのフォーマットは以下の通り
``dd bs=[blockサイズ] if=[書き込むimgファイルのパス] of=[書き込み先のパス] ``

## SSHの有効化
ディスプレイ接続が、面倒なので事前にSSHを有効化して、作業をします。
現在のRasbianでは、デフォルトでSSHが無効化されているようなので、以下のコマンドで有効化する必要があります。

```
sudo touch /Volumes/boot/ssh
```

### IPアドレスの確認
デフォルトでは、Ethernet Cableを接続すると、DHCPでIPアドレスを取得します。
IPアドレスをルータの管理画面やNmapで確認します。

### piユーザーのパスワード変更
デフォルトでは、ユーザー名:pi,パスワード:raspberryになっているため、変更しておくことを推奨します。

```
passwd pi
```

## 所感
初代ModelBと比べて、格段に早くなっていることがすぐにわかりました。
Raspberry Pi4は、3の数倍早くなっているとのことで、また購入したいと思います…
Golangのポインタ・アドレスについての学習メモ

# 「アドレス」は変数が配置された場所を示す
```go
var n int = 100

fmt.Println(n)  // 100
fmt.Println(&n) // 0xc0000167b0
```

`&`は**アンパサンド**といい、変数がメモリ上のどこのアドレスに格納されているかを知るために利用します

コンピュータは変数を以下のようなイメージで保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231086/4638f11f-a247-f85a-ec02-8e3c42434e0c.png)

メモリの各領域にアドレス(16進数)が割り振られています。

なので、アドレスと値は紐づいている状態ですね。

アンパサンド`&`を用いることで、「その変数がメモリ上のどこにあるのか」を知ることができるのです。

# ポインタはアドレスを格納するためのオブジェクトである
```go
var n int = 100
var p *int = &n
fmt.Println(p) //0xc00007c770
```

[C言語のポインタ構文のつまづきどころ
](https://qiita.com/tatachiy/items/7856931f4cacf2c5b743#%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E5%9E%8B%E5%A4%89%E6%95%B0)を参照すると、孫引きとなってしまいますが、このような記述がなされていました。

>ポインタ (pointer)とは、あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、それを参照するものである。有名な例としてはC/C++でのメモリアドレスを表すポインタが挙げられる。(ja.wikipedia.org)


>In computer science, a pointer is a programming language object, whose value refers to (or "points to") another value stored elsewhere in the computer memory using its address.(en.wikipedia.org)

なので、「ポインタ = アドレス」と捉えても、差し支えはないです。(**厳密には違いますが....**)

上記のコードの`var p *int = &n`の部分で、変数pはintのポインタ型を宣言して、変数nのアドレスを格納しています。
この時点で`p`は「ポインタ」と呼ぶことが可能です。

`*int`はint用のアドレスを格納する「ポインタ型」です。

# `&`と`*`を利用すれば何となくわかる
```go
var n int = 100

fmt.Println(n)  // 100
fmt.Println(&n) // 0xc0000167b0
fmt.Println(*&n) // 100
fmt.Println(&*&n) // 0xc0000167b0
```

ややこしいのですが、`*`を型の前ではなく、変数の前に置くと「アドレスの実体」を参照することができます。
インバス　自分用メモ

♯リーダーとして 
* 何が必要なのか自発的に動く
　例)与えられた情報が必要なものか、それらがすべて揃っているか。

♯ 組織の活用力
着任後に確認すべきこと
1. 自分の部署がどの位置づけにあるか
2. サポート、支援を受けられる組織はどの位置にあるのか
3. 報告・連絡のルートはどのようになっているか

♯ 顧客志向(誰に向かって仕事をしているのか)
例)　ルールが現実的でなければ、管轄部門に相談
顧客志向になっていない風土に問題がある

♯ 問題発見能力
リスクをはらんだ問題は常に変化している。与えられた情報からリスクがどれくらいあるのか常に検討する。

♯定量的な数値を常に出す
Django Girls Tutorialを復習する　〜目次〜

Django Girls Tutorialを一通り終えたので、復習のため記事を書きました。

＊この記事は単体ではなく、本編のDjangoGirlTutorialのサブとしてご活用ください。
なお、本編URL（https://tutorial.djangogirls.org/ja/ )
Pythonを一通りやってみて、Djangoに挑戦したい！という初心者向けの記事です。


　本編の各章にそって記事を書きます。実務でプログラミングをやったことのない私にとっては、Django Girls Tutorialけっこうハードルが高く、説明を読んでもよくわからず、でもなんとか終わらせた感じがあります。
　きちんと本文を順番通りに読めればいいのですが、ところどころ理解できないところがあり、思いもしないエラーに見舞われ、解決策もわからずということがおきました。それでも先にはすすめたい！終わらせて全体像をつかみたい！とりあえずコピペでいいから完成はさせたい！そんな初心者ための記事にしていきたいと思います。

　記事の構成は、何を入力すればいいのか、というコードのみです。写経のように、何も考えなくてもただ打ち込めばいいようにコピペできるコードを書く。コマンドラインは何を入力すればいいかを書く。どのような出力がされるかは書いておりません（なぜその操作をするのか、考え方をまとめるということは、随時更新していきたいとは思いますが・・）。

＊省略している章もあります。それは下記の通り
・序盤（”はじめに〜インストール〜Chromebookのセットアップ〜インターネットのしくみ〜コマンドラインを使ってみよう〜Pythonのインストール〜コードエディタ〜Python入門〜Djangoってなに？”）
・”デプロイ！”
・”次のステップは？”


目次とURLをはりつけます。

1.Djangoのインストール　＋　プロジェクトを作成しよう！
https://qiita.com/K-Kazutaka/items/af1fe47f08653087b90f
2.Djangoモデル
https://qiita.com/K-Kazutaka/items/7b39142de12891dcc637
3.ログインページを作ろう（Django admin）
https://qiita.com/K-Kazutaka/items/15d3dde4d282e1cae8e5
4.Django URL　＋　Djangoビュー
https://qiita.com/K-Kazutaka/items/20dd734ae471e4e6163a
5.HTML 入門
https://qiita.com/K-Kazutaka/items/7f58137e8033e5310f17
6.Django ORM（クエリセット）
https://qiita.com/K-Kazutaka/items/cbbbba866f0e3b526a24
7.テンプレート内の動的データ　＋　Djangoテンプレート
https://qiita.com/K-Kazutaka/items/76bb8c46e613499d89b4
8.CSSでカワイくしよう
https://qiita.com/K-Kazutaka/items/ce0eb19e8c93fd40fb1b
9.テンプレートを拡張しよう
https://qiita.com/K-Kazutaka/items/d005a9d49386fa507f69
10.アプリケーションを拡張しよう
https://qiita.com/K-Kazutaka/items/7e05ed89fd6418ddb55c
11.Djangoフォーム
https://qiita.com/K-Kazutaka/items/149d5d421be69275f102


なお、本編はこちらのURLからどうぞ。
https://tutorial.djangogirls.org/ja/
ansible-playbook でコマンド実行結果から条件分岐する方法

# 概要
ansible-plyabookの条件分岐の方法がわからず調べていて、実際に実行して成功したのでアウトプットしました。

ansible-playbookを使用して、対象のコマンドの実行結果が成功であれば「成功」のメッセージを出すようにしています。


## インベントリファイル
今回はテスト用で自端末を対象にします。

```
[localhost]
127.0.0.1 ansible_connection=local
```

## playbook
記載内容は`uptime`コマンドを実行する項目と、レジスタ内に入っている値の表示、そして実行結果が成功だったら「成功」を実行する項目の3つで構成しています。

```
- hosts: localhost
    tasks:
    - shell: uptime
      register: result

    - debug:
        msg: "{{ result }}"

    - debug:
        msg: "成功"
      when: result.rc == 0
```

## 実行結果
「inventory」にインベントリファイル、「conditionsTest.yml」にplaybookの内容を記述しています。

```
$ ansible-playbook -i inventory conditionsTest.yml

PLAY [localhost] *******************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [127.0.0.1]

TASK [shell] ***********************************************************************************************************************************************************************************************
changed: [127.0.0.1]

TASK [debug] ***********************************************************************************************************************************************************************************************
ok: [127.0.0.1] => {
    "msg": {
        "changed": true,
        "cmd": "uptime",
        "delta": "0:00:00.009835",
        "end": "2019-07-07 16:39:13.762565",
        "failed": false,
        "rc": 0,
        "start": "2019-07-07 16:39:13.752730",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "16:39  up 9 days, 17:47, 7 users, load averages: 1.62 2.08 2.11",
        "stdout_lines": [
            "16:39  up 9 days, 17:47, 7 users, load averages: 1.62 2.08 2.11"
        ]
    }
}

TASK [debug] ***********************************************************************************************************************************************************************************************
ok: [127.0.0.1] => {
    "msg": "成功"
}

PLAY RECAP *************************************************************************************************************************************************************************************************
127.0.0.1                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

コマンドの実行が成功しているので「"msg": "成功"」が出力されています。

## 補足
`shell`の実行結果をregisterで取得し、変数resultに格納しています。
「rc」に実行結果が格納されており、成功であれば0が格納されています。

そこでwhenを使用し、「`uptime`の実行結果をregisterを使用してresult変数に格納、rcに0が格納されていれば成功を出力する」という条件にしています。
1分で始めるtoioプログラミング

# はじめに

[toio](https://toio.io/)の**プログラミングを1分ではじめる**ための方法を紹介します。

プログラムはJavascriptで書いてブラウザ上で動かします。

# 用意するもの

- [toio](https://toio.io/)のコアキューブ
- PC
 - Bluetooth 4.0 アダプタが搭載されていること
 - [Google Chrome](https://www.google.com/intl/ja/chrome/) がインストールされていること

# 手順

適当なテキストエディタで以下をコピペし、`hoge.html`というファイル名[^1]でPC上に保存してからChromeで開くだけです。

[^1]: 拡張子を`.html` とすれば名前はなんでもかまいません。

```html
<!DOCTYPE html>
<html>
<head>
<script src="https://snoguchi.github.io/toio-browser/toio-browser-1.0.0.js"></script>
</head>
<body>

<button id="connect">connect to cube</button>

<script>
document.getElementById("connect").addEventListener("click", async ev => {
  const cube = await new toio.scanner.NearestScanner().start();
  await cube.connect();

  // ここからがプログラムの本体（キューブが前進します）
  cube.move(100, 100, 1000);
});
</script>

</body>
</html>
```

# 動かし方
Chrome上に表示される `connect to cube` というボタンを押すとペア設定のダイアログが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323684/a27a8bba-0123-640f-6da8-4b147159546e.png)
ここで`toio Core Cube`を選択すれば、プログラムどおりにキューブが動くはずです。

あとはHTMLファイル中にある `cube.move(100, 100, 1000)` の部分を[APIドキュメント](https://toio.github.io/toio.js/modules/_toio_cube.html)を見ながら色々といじってみましょう。

おしまい。

# 以下余談

今回プログラムを始めるまでの手順をできるだけ簡単にしたかった[^2]ので、[前回の記事](https://qiita.com/shinsuke-noguchi/items/037d729327232b6c0d33)で解説した設定やパッチをUMDにして `<script>` タグで読み込ませるようにしました。

[^2]: gitとかNode.jsとかwebpackとか知らなくても誰でもプログラムを楽しめるようにしたかった

ソース：https://github.com/snoguchi/toio-browser

あとは面白いものが出来たときに、お手軽にホスティングできる方法があればいいのですが、まだ見つけられていません...[^3]

[^3]: GitHub Pagesは敷居が高いし、CodePenやjsFiddleはcross-origin iframeのせいでWeb Bluetoothが動かない
プログラミング初学者が独学でポートフォリオを完成させるまでの話〜挫折しない方法〜

# 自己紹介
2019年3月初旬にエンジニアYouTuberの動画を見てHTML/CSSから[Progate](https://prog-8.com)でプログラミングの勉強を始め、2019年6月末にRuby on Railsのポートフォリオを完成させてデプロイしました。2019年4月からは大学院の修士課程（農学）にいて、21卒でエンジニアを目指しています。プログラミングの勉強を始めた2019年3月時点ではプログラミングは完全未経験でした。
本記事がこれから独学でプログラミングの勉強を始める人の参考になれば嬉しいです。

# 挫折しないためのポイント
結論から言うと、独学でプログラミングを勉強する際には以下の３点を守るようにすると挫折しにくくなります。
1. お手本のコードを自分専用のライブラリとして保存する
2. 勉強時間は余裕をもって設定する
3. ググっても分からないバグを無理に解決しようとしない

それでは、１つずつ解説していきます。

# 1. お手本のコードを自分専用のライブラリとして保存する
これは挫折しない方法というよりは勉強法になります。Progateで書いたコードのような正しいコードを解説付きでコンピューターに保存しておきましょう。ポートフォリオを制作する際は、そのコードを一旦コピペしてから必要部分を書き換えるようにすると文法ミス（syntax error）が減ってコードを書く速度が格段に上がります。

#2. 勉強時間は余裕をもって設定する
時間に余裕がないことによる焦りは挫折の大きな原因になります。初学者の場合、エンジニアとしての最低限の技術とやる気の証明になるようなポートフォリオを制作するまでの作業時間はProgate等の基礎学習の時間を含めると最低500時間は確保しておいた方が無難です。当然のことながら個人差があるので、もっと時間がかかる人も多くいると思いますので、500時間以上かかったとしてもとにかく焦らないように気をつけましょう。

# 3. ググっても分からないバグを無理に解決しようとしない
ググっても分からないバグは分からないのですから、解決しようとするだけ無駄です。無理に解決しようとしても消耗するだけです。とはいってもバグは解決しなければいけません。
一通りググってもバグを解決できない場合は以下のような順番で対処することをおすすめします。

##3-1. 一晩寝かせて翌朝もう１回そのバグを見てみる
昨晩どれだけググっても解決できなかったバグが、翌朝もう１度見てみると驚くほどあっさり解決することがよくあります。そういう時は基礎的なことが抜けていた場合が本当に多いんですよね…。

この方法で解決できなかった場合、3-2に進んでください。3-2はA,B,Cと分岐します。バグの状況や自分の精神状態（笑）に応じて適切なものを選んでください。

##3-2A. プログラミングスクールやプログラミングができる友人などに質問する
解決しなければ全く進めないバグに遭遇したときや挫折しそうな精神状態のときの対処法として推奨する方法です。一番確実に素早く答えを得られる方法ですが、この方法を使うことで失われるものがあることを知っておいた方がよいでしょう。

###1. お金
プログラミングスクールは（無料期間のあるスクールがあるものの）基本的に10万円単位のお金がかかります。痛い出費ですが、挫折するよりもはるかにマシなので、選択肢の１つとして頭の片隅に入れておきましょう。友人に聞く場合も、ごはんを奢ってあげた方がいいですよね。

###2. 自走能力の証明
初学者が独学で作ったポートフォリオにはエンジニアとしての「自走能力」（バグを自力でググって解決して次に進む能力）の証明という大きな要素があるのですが、プログラミングスクールや友人に質問するとポートフォリオからこの要素がなくなります。実はこちらがかなり大きいそうです。しかし、繰り返しますが挫折するよりもはるかにマシなので、精神的にやばいときはプログラミングスクールに行きましょう。誤解がないように言っておくと、筆者はこの方法は使っておりません。

##3-2B. 質問サイトで質問する
[teratail](https://teratail.com/)や[Stack Overflow](https://ja.stackoverflow.com/)などのプログラミング専用の質問サイトがあるので、そこで質問してみましょう。ただし、質問してもなかなか答えが返ってこないことも多く、答えが得られる保証はありません。ただ、困っている内容を人にわかりやすく伝えるいい機会なので、解決できないバグが出てきたときにはこの方法を一度使ってみることをおすすめします。

##3-2C. あきらめる
筆者が多く使った方法（？）です（笑）。ポートフォリオを制作するうえで必須ではない機能の部分で一通りググっても分からないことがあった場合、制作時間の短縮のためにその機能実装をあきらめました。初学者がポートフォリオを取りあえず完成させて形にするうえでは必要なことだと割り切ってこれをするのもありだと思います。筆者は独学にこだわって自走能力の証明をしたかったので、この方法を多く使いました。当然のことながら、「現場で実力がついたら、必ずこの機能を実装する」と誓ってポートフォリオでは実装できなかった機能をコメントアウトして残しています。実装をあきらめた機能があっても、とりあえず独学でポートフォリオを完成させたという事実は大きな自信につながるので、可能なら最後まで独学でポートフォリオを作りましょう。

# 最後に
最近では技術の発展によってプログラミング独学のハードルがどんどん下がっています。最後まで独学でポートフォリオを完成させられるかどうかに関しては個人の適性もありますが、できれば独学でがんばりましょう。
この記事に書ききれなかったポートフォリオ制作の流れを時系列で書いたものを別記事として作ります。プログラミングを独学する際の大まかな流れや心構えの参考になればと思って書きますので、そちらも読んでいただけると幸いです。
それでは、これからプログラミングの勉強を始めるみなさん、幸運を祈ります！
atcoder ABC119 C問題

解法までわかったが実装できなかった。
https://atcoder.jp/contests/abc096/tasks
#C問題

#方針
見た瞬間に、貪欲法が思いついたが、合成するとわけがわからなくなるので、dfsで全探索を考えた。しかしながら、最終的に延長魔法と短縮魔法の実装をどうするかわからなくなり、回答を見た。

#解法
合成魔法を使うとよくわからなくなるため、各木についてどの材料に使うか(A,B,Cまたは使わない)について4通りの全探索をする。最終的に、できた各合成木(A',B',C')について、A,B,Cとの絶対値の差を取ることで、実質延長魔法、短縮魔法の処理を行った事になる。この時のdfs処理で、初めの各木は合成してないが合成している定でcost+10しているので、最後の処理ではcost-30する。
Djan Gogirls Tutorialを復習する（６）　〜DjangoのORMとクエリセット〜

注意事項はこちら。
https://qiita.com/K-Kazutaka/items/1a432bda4f723e6757d6
写経用の記事です。


Django shellを起動する
`$ python manage.py shell`

次のように表示がかわる
(InteractiveConsole)
">>>"


```command.line
>>> from blog.models import Post
>>> Post.objects.all()
<QuerySet [<Post: my post title>, <Post: another post title>]>
>>> from django.contrib.auth.models import User
```
```
>>> User.objects.all()
```
さっき登録したユーザー名を確認。

```
>>> me = User.objects.get(username='ユーザー名')
>>> Post.objects.create(author=me, title='Sample title', text='Test')
>>> Post.objects.all()
```


さらに投稿を追加

```command-line
>>> Post.objects.filter(author=me)
>>> Post.objects.filter(title__contains='title')
>>> from django.utils import timezone
>>> post = Post.objects.get(title="Sample title")
>>> post.publish()
>>> Post.objects.filter(published_date__lte=timezone.now())
```

オブジェクトの並び替え

```command-line
>>> Post.objects.order_by('created_date')
>>> Post.objects.order_by('-created_date')
```

クエリセットをつなげる

```command-line
>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
>>> exit()
```
Dockerの仕組みを超初心者向けに超初心者がまとめてみた

# はじめに
先日超初心者にもわかるようにDockerの仕組みを説明してもらえる機会があったので、そこで教えてもらった内容を自分のアウトプット用としてまとめておきます。なお、超初心者用にかなり言葉を噛み砕いてとても簡単に説明してもらったものなので、Dockerの仕組みを熟知している人が見ると厳密には違う部分もあるかもしれませんが、「大雑把に言うとこんな感じだよね～」くらいで捉えてもらえると幸いです。

# Dockerってなに？
A. 簡単に言うと、**自分のパソコンの中にもうひとつパソコンを搭載できるサービス**のこと

ちなみに、超初心者の私はDockerの仕組みを部屋とテントに例えて説明してもらうと理解しやすかったです。自分の部屋(＝自分のパソコン)にテント(＝もうひとつのパソコン)を張っているところを想像してみてください。このとき自分の部屋(＝自分のパソコン)はテント(＝もうひとつのパソコン)にスペースを貸している状態になります。このスペースを貸している状態のことを**仮想化**と言います。この仮想化こそがDockerの真骨頂のサービスです。

# どうして仮想化を使ったほうがいいの？
A. 仮想化には以下のメリットがあります。

・ネット環境がなくてもサービスの開発ができる
・テント(＝もうひとつのパソコン)は何回でもつくったり壊したりできる
・テント(＝もうひとつのパソコン)は何個でもつくれるので開発しようとしている技術を比較しながら開発できる 

このように、アプリケーションを効率的に開発することができるので、仮想化を利用することが勧められています。ちなみに、仮想化サービスはDocker以外にもいくつかあるみたいなので気になる人はぜひググってみてください。

# Dockerではどんなサービスを提供しているの？
A. Dockerでは2つのサービスを提供しています。

1. Docker Engine：もうひとつのパソコン(テント)をつくることが出来る技術のこと
2. DockerHub：(他の)Dockerユーザーが作成したコンテナをアップロード・共有できるサービス

DockerユーザーはDockerHubから使いたいテント(もうひとつのパソコン)ををつくるための材料をダウンロードすることができます。この材料のことを**イメージ**と言い、これを元にしてDockerユーザーはテント(もうひとつのパソコン)を自分のパソコンにつくることができます。

また、ダウンロードしたイメージは自分たちが使いやすいようにイメージをカスタマイズすることで使うことができます。そしてこのイメージをカスタマイズしたもの＝テント(もうひとつのパソコン)であり、これをDocker用語で**コンテナ**と言います。コンテナの中にはWebサーバーパッケージなどを含むライブラリ機能とアプリケーションを作ることが出来る機能が搭載されています。

なお、このイメージをカスタマイズしたコンテナはDockerHubにアップロード・共有することができ、それをまたほかのユーザーがダウンロードして使うこともできます。

# おわりに
ここまでDockerの仕組みを簡単にまとめてきました。多分文字だけで理解するのは難しい部分も多くあると思います。私自身も実際に絵や図にまとめて理解した部分も多くあるので、もしこれで理解しにくいな～と思う部分があれば絵や図にまとめてみると少し理解しやすくなるかもしれません。
Herokuへデプロイした時に「The page you were looking for doesn't exist. 」エラーが出る

#事象
Railsでアプリを作って、動作確認も問題なし！
「さぁHerokuにデプロイ！」と思い、「git push heroku master」を実施。

デプロイされたアプリをherokuのURLを開くと下記のエラーが出た・・・

![スクリーンショット 2019-07-07 16.37.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407853/39facf53-2711-0cb3-e25d-92220679ea4b.png)

```
The page you were looking for doesn't exist.
You may have mistyped the address or the page may have moved.

If you are the application owner check the logs for more information.
```

ターミナル上でもデプロイ時にエラーが出ておらず原因が不明。

#原因
ググってみると、どうやら`routes.rb`にroot（URLのトップ）にアクセスした際に表示するページが設定されていないのが問題っぽい。

参考記事
http://mozuzaru.hatenablog.com/entry/2018/03/10/204643

#解決方法
```ruby:routes.rb
Rails.application.routes.draw do
	# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

	root  'users#index'  #この1行を追加

	#ユーザー一覧を表示
	get '/users', to: 'users#index'
	#新規投稿（登録画面）に遷移
	get '/users/new', to: 'users#new'
	#投稿されたデータを受け取る
	post '/users', to: 'users#create'

	#投稿されてデータを編集する画面に行く
	get '/users/:id/edit', to: 'users#edit'

	#編集完了画面に遷移
	patch 'users/:id', to: 'users#update'

	# 投稿の削除を実施する
	delete '/users/:id', to:'users#destroy'
end
```

`root  'users#index'`を追加して、再度デプロイしたらHeroku上でも見れるようになったー！
やったね！！
![スクリーンショット 2019-07-07 16.45.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407853/124041f7-d72f-e1de-db3e-30357cf0a151.png)
Ruby on RailsでHelloWorld

###はじめに
RailsでHelloWorldする。

###環境
MacOS : Mojave
Ruby  : 2.3.7
Rails : 5.2.3

###アプリ作成
```
rails new helloworld
cd helloworld
```
<img width="1112" alt="スクリーンショット 2019-07-07 16.30.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402891/3a6b9ec1-0fd1-b9eb-4f06-c1ec8940b926.png">
<img width="867" alt="スクリーンショット 2019-07-07 16.30.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402891/ccfc487c-c3ea-bfe2-a66c-80e1d05060e4.png">

###サーバ起動
```
rails server
```
<img width="839" alt="スクリーンショット 2019-07-07 16.30.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402891/55450829-ba7c-9f76-81c9-fe04d44c45ee.png">

###起動確認
ブラウザから以下にアクセス。
 http://localhost:3000/

HelloWorld的な画面が表示された。
<img width="1440" alt="スクリーンショット 2019-07-07 16.31.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402891/cd2ca5e8-0d98-15f0-5182-61e0df93bcbc.png">


###hello world表示
controlerを以下に書き換える。

```:helloworld/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def hello
    render html: "hello, world!"
  end
end
```

ルーティングファイルも書き換える。

```:helloworld/config/routes.rb
Rails.application.routes.draw do
  root 'application#hello'
end
```

ブラウザから以下にアクセス。
 http://localhost:3000/

これでRailsできますと言えるようになった。(?)
<img width="808" alt="スクリーンショット 2019-07-14 17.54.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402891/e4d8974a-4e94-34f0-1bf8-63b3b17183dc.png">
Python+OCRでデジタル温度計（計測器）の数値を読み込んでみた

## 背景
職場の温度が暑くて、担当部署に改善要望を出したい！！（切実）
では、主観じゃなくデータを出せと言われたので、（←管理部門の仕事な気もするが）
デジタル温度計の表示をOCRで読み取って温度履歴を取ります。
（温度計の他にPCに接続されていない計測器にも応用できるかも！と企んでみたり）

## 環境
MacOS Mojave ver10.14.4
Anaconda Navigator 1.9.7
　※Anacondaのインストールは、[こちら](https://qiita.com/satoshi-iwaki/items/e431b4182e50a2918a17)を参考にいたしました
JupiterNotebook 5.4.0
OpenCV 3.4.2

## 事前準備
### 画像の取得
Webカメラで取得する方法を一定時間ごとに撮影する時間を考えましたが、
手元にwebカメラがすぐ用意できず断念。。。
デジカメがあったので、タイムラプス撮影で一定時間ごとに静止画を撮影して、
１日の温度計の静止画を取得しました。
https://smartparty.jp/powershot-g1-x-mark-iii-timelapse

### OCR環境の構築
まずは、OCRできる環境を用意します。
「Anacondaだけで環境を構築して、Python+OCRをやってみる」
https://qiita.com/anzanshi/items/9ee94affecd74be33159
今回は、温度計のデジタル数字（７セグメント）を読み取るので、学習データを追加します。
「Python+OCR(tesseract)の新しい学習データ（言語データ）を追加してみた」
https://qiita.com/anzanshi/items/c7d554a6cc8aa4c39b5c

## 実践
### 画像のトリミング
まずは、撮影した画像をトリミングして、下記コードで数字情報だけにします。
※お使いの画像に合わせて、トリミング範囲を指定してください。

```python

import cv2
img_or = cv2.imread('ORIGINAL_PHOTO.JPG')
img_tr = img_or[1900:2400, 1200:1900 ] #トリミング範囲を指定
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288322/55564995-62e9-20ea-d0ab-83e1e09d7caa.png" width=50%>

### 画像処理
このままの画像だと、読み取り精度が落ちるので、
グレースケール化→２値化→ノイズ処理します。

```python

import cv2
import numpy as np

#グレースケール化
img_gray = cv2.cvtColor(img_tr, cv2.COLOR_RGB2GRAY)
#2値化（100:２値化の閾値／画像を見て調整する）
ret,thresh1 = cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
#ノイズ処理（モルフォロジー変換）
kernel = np.ones((5,5),np.uint8)
img_opening = cv2.morphologyEx(thresh1, cv2.MORPH_OPEN, kernel)
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288322/6c165f48-0326-7406-99f6-7fc0db85d85b.jpeg" width=50%>

### OCR（文字認識）の実行！！
さて、いよいよOCRの実行です！

```python
from PIL import Image
import sys
import pyocr
import pyocr.builders
import cv2

#OpenCV型→PIL型に変換
def cv2pil(image):
    ''' OpenCV型 -> PIL型 '''
    new_image = image.copy()
    if new_image.ndim == 2:  # モノクロ
        pass
    elif new_image.shape[2] == 3:  # カラー
        new_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    elif new_image.shape[2] == 4:  # 透過
        new_image = cv2.cvtColor(image, cv2.COLOR_BGRA2RGBA)
    new_image = Image.fromarray(new_image)
    return new_image

#OCRの準備
tools = pyocr.get_available_tools()
if len(tools) == 0:
    print("No OCR tool found")
    sys.exit(1)
# The tools are returned in the recommended order of usage
tool = tools[0]
print("Will use tool '%s'" % (tool.get_name()))
# Ex: Will use tool 'libtesseract'

langs = tool.get_available_languages()
print("Available languages: %s" % ", ".join(langs))
lang = langs[0]
print("Will use lang '%s'" % (lang))

#OCR実行
temp_pil_im = cv2pil(img_opening) #上述の画像処理後の画像データ
txt = tool.image_to_string(
    temp_pil_im,
    lang="letsgodigital",
    builder=pyocr.builders.TextBuilder(tesseract_layout=6)
)
print( txt )

```
```python:実行結果

26.0
```

## 終わりに
無事に温度情報を取得することができました！
これを管理部門に叩きつけて、快適な職場環境を手に入れたいです！（切実）
本当はWebカメラでリアルタイムに情報が取得できると望ましいので、次回はwebカメラを用意して記事を書きたいと思います！

## 参考
「tesseract-OCRで遊んでみる」
http://blog.nomulabo.com/article/422712502.html
「Real-time image preprocess and OCR」
https://github.com/arturaugusto/display_ocr
promiseとsetTimeout、どっちが先に実行される？

# 例
```js
![console2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255229/16525369-8ace-464b-46dc-76b4435e7db0.png)
var r = new Promise(function(resolve, reject){
    console.log("a");
    resolve();
});
setTimeout(()=>console.log("d"), 0)
r.then(() => console.log("c"));
console.log("b");
```

実行したら、こうなります
![console2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255229/06f41a64-2a08-4ee1-35a2-d3554587a97a.png)
console.log("d")より、console.log("c")が先に実行された？なぜでしょうか？

# event-loop
前提として、JavaScriptはシングルスレッドで動いてるため、並行処理はできないということです。だから、ブロッキングさせないように、イベントループによってタスクキューに登録されている関数がコールスタック上に追加され、実行されます。インメージは以下のとなります。![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3235353232392f63333138653435322d653831632d633834372d353961342d3439633565613539616163312e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255229/0ea5cf26-d519-19c0-44c6-5038e5cb4668.png)
（event-loopのインメージ from [「Help, I’m stuck in an event-loop」](https://vimeo.com/96425312)）
（このブログ [JS基礎ー非同期とコールバック](https://qiita.com/haoyu_ma/items/bbb96193733419a07bd2) は軽くまとめましたが、ごさんこうまで）


# MacroタスクとMicroタスク
promiseとsetTimeoutともコールバック関数をイベントループに登録しますが、promiseみたいなnode.js環境提供する関数は**Microタスク**としてイベントループに登録します。（恐らくブラウザ環境提供される）setTimeoutは**Macroタスク**としてイベントループに登録します。

![16f70a9a51a65d5302166b0d78414d65.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255229/0ccb2073-790a-153f-a395-971d5675d651.jpeg)
- Macroタスク:イベントループに登録できる粒度（上記の黄色のやつ）
- Microタスク：Macroタスク内格納され、より粒度が小さいタスク

promiseはMicroタスクを生成し、イベントループ内の実行待ちのMacroタスクの中にインサートしますが、setTimeoutは新たなMacroタスクを新規作成し、イベントループに登録するようなインメージです。

# 用途
```js
function sleep(duration) {
    return new Promise(function(resolve, reject) {
        console.log("b");
        setTimeout(resolve,duration);
    })
}
console.log("a");
sleep(3000).then(()=>console.log("c"));
```
よく使われるケース：PromiseでsetTimeoutを非同期させます。
実行順番は以下となります：
➀Macroタスク１が実行
②console.log("a")が実行;
③console.log("b")が実行;
④setTimeoutでMacroタスクが登録されます
⑤resolveが実行
⑥then内のconsole.log("c")処理が実行
だから、a->b->cが出力されます。
※ sleep(0)にしても、a->b->cって順番で出力されます。

# 参考
1.winter.2019.relearning front-end
【React Nativeでのスマホアプリ開発 #1】Firebaseを使ってスマホアプリ開発の準備をしよう

# Firebaseとは

Firebase とは Google が提供するウェブ開発・スマホアプリ開発向けのバックエンドサービスです。
通常ウェブサービスには、ユーザが実際に操作をするフロントエンド、ユーザの操作に応じてサーバ側でデータ処理をするバックエンド、という２つの開発領域があるのですが、Firebaseはこのバックエンドの機能を設定画面からの簡単な設定によって簡略化してくれる、というサービスになります。

今回は、そんなFirebaseの初期設定の方法を簡単にご紹介できればと思います。


# 前提条件

- ご自身のGmailアカウントをお持ちであること
- ブラウザで上記GmailアカウントでGoogleにログインしていること


# Firebaseにプロジェクトを作成する

### 1. まず下記のURLよりFirebaseにアクセスしましょう。
https://firebase.google.com/?hl=ja

### 2. 右上の「コンソールへ移動」をクリックしましょう。
<img width="1679" alt="Firebase-TopPage.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447508/32a5c1d1-e8ff-394e-ae03-9da5b6615712.png">
※ 噂によると、真ん中の「使ってみる」をクリックしても良いとのことです。



### 3. 画面中央の「プロジェクトを作成」をクリックしましょう。

<img width="1680" alt="Firebase002.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447508/50feb043-c1d3-7583-e408-92673f2099d0.png">



### 4. プロジェクトの情報を入力し、右下の「プロジェクトを作成」を押してプロジェクトを作成しましょう。

<img width="1677" alt="Firebase003.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447508/5595af39-3be4-abca-8120-10df90adc2db.png">

上記画像の赤枠４箇所の部分をいじり、右下の「プロジェクトを作成」ボタンをクリックします。

a. プロジェクト名: お好みのプロジェクト名を入力します
b. アナリティクスの地域: デフォルトはアメリカになっているので、ひとまず日本などへ変更
c. 測定管理者のデータ保護条約: チェックを入れます
d. 利用規約への同意: チェックを入れます


### 5. 「次へ」を押してプロジェクトダッシュボードへ移動します。

<img width="1676" alt="Firebase004.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447508/e62b1142-1c32-0bb1-7da2-6fc853f75b20.png">


### 6. 下記画像のようなプロジェクトダッシュボードへ遷移したら下準備は完了です。

<img width="1678" alt="Firebase005.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447508/90bb0230-4a0f-13e7-c0b1-f45c717476aa.png">

ひとまずこれで、Firebaseを利用した開発の準備は完了です。


# Firebaseのダッシュボードでできること

<img width="1680" alt="Firebase006.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447508/0da47ec2-f297-954c-2247-f6e118f8b9e0.png">

上記ダッシュボードの左側のメニューを見て頂ければわかるのですが、
今後実際にFirebaseを利用した開発をしていく際には、このダッシュボード画面から、

- ユーザ認証機能に関わる設定
- データベースの設計
- ファイルストレージ（画像のアップロードなど）の設定
- その他クラッシュ情報やアクセス解析などの設定

などをFirebase上で一元的に設定・管理することができます。

小さめの個人開発や、スタートアッププロダクトの小規模MVPの開発などにおいては、
バックエンドの開発をこのような設定画面から設定・管理できるのは非常に大きな強みとなります。
特にスマフォファーストで何かを作りたい、というプロジェクトでは、非常に便利なツールですね。
技術系資格試験は受ける意味があるのか？〜Ruby Silver編〜

## 前書き
世の中には様々な資格試験があります。
そして技術分野にも資格試験があります。
受ける理由は人それぞれだと思いますが、今回は資格試験は意味がある=業務に役立つのかをポイントに、個人的に感じたことをまとめてみます。


## 前提と先に結果
私の経歴はこんな感じです。

* Java歴 1.5年 (新卒時です)
* Ruby/Rails歴 1年ちょっと (厳密には学生時代にも数ヶ月やったことがありました)

ただし仕事ではサービス開発/運用/セキュリティ全般を担当しているので、毎日フルでRubyを書いてるという訳でなく、AWSを触っていたりというよな時間も多いです。(ハードル下げ)

・受けた試験
[Ruby技術者認定試験のSilver](https://www.ruby.or.jp/ja/certification/examination/)です。
Goldを取るつもりなのですが、それには下位であるSilverがまず必要だったので受けました。

・受けたきっかけ
自分がどれだけRubyを理解できているか知りたかった、
Rubyの組み込みクラスを再実装する勉強会に行った際に理解が足りていないと感じた、
CTOが良い試験だと言っていたからです。


・勉強時間と結果
勉強期間は２週間弱です。平日0.5~1時間、休日3時間程度です。
業務後に予定があったり、週末旅行に行ったりしたので毎日はできませんでしたが、前日の詰め込みなどを平均したらそれくらいです。
100点中75点が合格点で、90点でした。

## Ruby技術者認定試験は受ける意味があったか？
先に結論から言いますと、個人的にはあったと思います。

まずそう思った要因は、
1. この試験は業務に役立つ試験になるように作られている気がした
2. 実務を1年やってから受けているので、単なる暗記にならなかった
3. 達成感を得られる
です。

以下で詳しく説明します。

## １.業務に役立つ試験になるように作られている気がした
まず、「こういう記憶色の強い試験だと、重箱を隅を突くような出題があって、無駄な勉強が生まれるのでは」と私は危惧していました。
が、結果的には勉強に無駄が生まれないように工夫されていると感じました。
網羅的にメソッドが紹介されている参考書を読んでいる時、「これそんなに使うシーンあるかな・・」というメソッドがあったりするのですが、肌感ですがそれらは出題されなかったので、テスト作成者も使用頻度が高いメソッドを選んでいるんじゃないかな〜と個人的には感じました。

※そもそもOSSであるRubyにメソッドが用意されているということは、一定以上の需要があるはずです。
なので、「これそんなに使うシーンあるかな・・」と感じるのは私の経験が浅いという理由もあると思っています。

ただ全くなかったわけでなく、１つありました。それはいろんなパターンのHashの生成。
でもこれくらいでした。

## 2. 実務を1年やってから受けているので、単なる暗記にならなかった
私はもともとJavaをやっており、間髪入れずにRubyの会社に転職をしたので業務をしながら覚えていきました。
入門はたのしいRubyとチェリー本だったので、網羅的に学ぶということはしていませんでした。

合格教本で完全ではありませんが割と網羅的に学べたので、知らなかったメソッドを知れました。その際、「あそこの処理、このメソッドで置き換えた方がcoolかも」と考えながら勉強ができ、実際書き換えもしたのでとても有益でした。

また他によかった点として、毎回出くわす度に調べていた名前や挙動の紛らわしいメソッドをちゃんと覚えられたので、仕事も早くなるかなと思います。
あとはオブジェクト指向についての出題も多いので勉強し直したのですが、改めてJavaと比べてRubyの挙動は柔軟で面白いな〜とRubyをさらに好きになりました笑


## 3. 達成感を得られる
Silverは踏み台として受けただけなのですが、それでも達成感はありました。

余談ですが、受講料について。
1万6千円は高すぎでしょ!?と思っていたのですが、試験2日ほど前には「１万６千円を無駄にできない」という猛烈なpressureで勉強が捗ったので、大人を本気にさせるとてもいい価格設定だったと思いました。


## 勉強方法とかかった時間
先人達が色々とまとめられているので簡単に。

私がやったのは、
0. 勉強方法や気をつけるべきポイントを調べる
1. まず１回模擬試験を解いて、自分のできなさ具合に焦る&雰囲気を掴む
2. [Ruby公式資格教科書](https://www.amazon.co.jp/dp/B0756VF9Y3/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1) の該当箇所を読む。私はGoldも受ける気だったので、Silverの範囲はあまり気にせず読んでいました。
3. https://www.ruby.or.jp/ja/certification/examination/rex で模擬試験を４回くらいやる
です。

あとRuby試験に限ったことではないのですが、中学/大学受験時の経験として、
紛らわしいポイントは抽出してまとめておき、1日数回、突如自分クイズを始めてなんども思い出して定着させることがかなり有効なのでやっていました。

## まとめ
Ruby技術者認定試験は、業務に活かせるか？というポイントにおいて、個人的には良い試験だと思います。
特に業務を始めて半年くらいたった人には良いと思います。
これからRubyをはじめるきっかけとしてこの試験に取り掛かるのは、個人的には暗記ゲーになってしまい、楽しくできるかは微妙なんじゃないかなと思っています。先にアプリを作ったりしてからやった方がいいかなと思います。もちろん自分がそうだった訳ではないのであくまで一意見ですが。

## あとがき
プロメトリックの回し者ではありません。
試験勉強は大好きです。
駆け出しRubyistのヒントになればいいな。
Nuxtでaxiosのエラーハンドリングをグローバルに行う

Nuxtを書いていて、401、500エラーのような対応処理が同じエラーに対しては、プラグインファイルの中で一括で行いたかったので、その方法を調べました。

## onErrorヘルパーを使う

例えば認証にJWTを使ってajax通信を行う際、プラグインファイルを作って、interceptor的にresponseヘッダにjwtトークンを埋め込む処理を書くと思います。こんな感じ。

```javascript:plugins/axios.js
export default ({ $axios }) => {
  $axios.onRequest(config => {
    const accountToken = localStorage.getItem('accountToken')
    if (accountToken) {
      config.headers.common['x-access-token'] = accountToken
    }
  })
}
```

エラーハンドリングをグローバルに行いたい場合、onErrorヘルパーを使います。

```javascript
// $axios.onRequest(){...}

$axios.onError(error => {
  if (error.response.status === 401) {
    // 401エラーの場合の処理を書く
  }
})
```

他にもヘルパーはいくつかあるので、気になる人はaxios公式ドキュメントを読みましょう。
[Axios Modules](https://axios.nuxtjs.org/helpers)

## 404エラーのハンドリング

404エラーのハンドリングはaxios側ではできません。（ajax通信が関係ないので当たり前ですが...）

404エラーに関してはrouterに任せましょう。Nuxtの場合は404エラーのハンドリングはnuxt.config.jsに記述できます。

```javascript

router: {
  extendRoutes(routes, resolve) {
    routes.push({
      path: '*',
      component: resolve(__dirname, 'pages/404.vue')
    })
  }
}
```

こちらの記述は、「[Nuxt.jsで存在しないURLにアクセスされた時に404ページ(任意のページ）を表示する方法](https://qiita.com/yoshinbo/items/d149560c409503b07758)」を参考にさせてもらいました。

これにより、ルーティングに存在しないURLにアクセスされた場合に/404に遷移させることができます。あとは404.vueをpages/配下に置けばOKです。

## まとめ

Nuxtはこういった処理が簡単にできるので便利ですね。
Dockerの使い方

## Dockerマウントの罠
dockerを使っていると、マウントしたくなります。pycharmの設定でDockerを使うこともできるらしいですが、よくわからないので使っていません。そうすると、pycharmで編集したファイルがそのままコンテナ内でも編集されていてほしいわけです。そんなわけでフォルダのマウントは非常に使えるわけですが、注意点が一つ。

　　　　　　　　　　　　　　　　　***/rootにマウントするな***

`docker run -v /Users/Name/Project:/root`
としてしまいますと、大半の場合バグります。
理由としては、Dockerfileでいろいろとした設定が大抵/rootに入っているからです。
上のコマンドを打ってしまうと、Docker imageでセットアップされた/rootが全て吹き飛びます。

デバッグ時にコードを書き換えて反映したいときは、/Users/Name/Project:/root/source

などとしましょう。そうするとローカルでの変更が全てsource以下のファイルに反映されます。
社内勉強会 機械学習入門（1.開発環境の準備）

# 公式サイトからPythonをダウンロードする
[公式サイト](https://www.python.org/downloads/)
![2019-07-07_14h13_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/82cc473b-6786-0671-cb63-906eb74086a8.png)
※2019年7月時点の最新バージョンである「3.7.3」をダウンロードします。

# インストールする
ダウンロードした「python-3.7.3.exe」を実行してください。
![2019-07-07_14h16_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/2d78af29-d573-06c2-6b04-5fe2cc25a0ee.png)

# 正しくインストールされたことを確認する
コマンドプロンプトから以下のコマンドを実行しましょう。
```python --version
```
「Python 3.7.3」と表示されたらOKです。

※勉強会用にコマンドプロンプトもみんな同じもの（ConEmu）にそろえましょう。

# Pythonの仮想環境を導入する
Pythonの仮想環境 ＝ Pythonのバージョンとライブラリをプロジェクトごとに管理できるようにする仕組み です。
この仕組みにより、プロジェクトに必要なライブラリだけを仮想環境にインストールできます。

1. 勉強会用のフォルダーを作る
今回は、Cドライブ（空きがなければ別ドライブでもOK）直下に「ml-intro」というフォルダを作成しましょう。

2. 仮想環境を作る 
以下のコマンドで作成
```cd C:\ml-intro
python -m venv env
```
以下のコマンドで仮想環境を有効化　
```env\Scripts\activate.bat```

↓のように先頭に(env)が表示されていればOKです。
![2019-07-07_14h58_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/63352c7c-619e-d9ce-638e-621c74ec24b1.png)

# 「Jupyter Notebook」をインストールする
Jupyter Notebookは、対話型でPythonを実行できるツールです。しかも、ブラウザで実行できます。
この勉強会では、Jupyter Notebookを使います。
※対応ブラウザは、「Google Chrome」「Firefox」「Safari」

1. Pythonの標準パッケージ管理ツール（＝ pip）を最新化する
仮想環境が有効である状態（以降、この状態であること）で、以下のコマンドを実行します。
```python -m pip install --upgrade pip```
![2019-07-07_15h16_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/d4402aeb-4687-90d2-d779-879c2feca8f4.png)

2. Jupyter Notebook をインストールする 
以下のコマンドを実行します。
```pip install jupyter```
![2019-07-07_15h27_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/98c789fb-08a4-16d4-1dcd-f0fc61d9eb89.png)
途中省略
![2019-07-07_15h28_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/80528eb1-e1ae-500d-4887-f37989454d6c.png)

3. Jupyter Notebook を起動する
以下のコマンドを実行します。
```jupyter notebook```

このURLにアクセスし、
http://localhost:8888/tree

以下のダッシュボード画面が表示されたらOKです。
![2019-07-10_13h40_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/1f2fcec6-2ada-bc96-725a-4c2393be7a8c.png)

「1.開発環境の準備」は、これで終了です。
次回は、「2.「Jupyter Notebook」を使ってみよう」です。
[社内勉強会 機械学習入門（2.「Jupyter Notebook」を使ってみよう）](https://qiita.com/masami310/items/792d71e109d7d6d402f9)
M5StickCで文字列をスクロール表示する

# 概要
M5StickCの表示領域が小さくて辛いので、横スクロール表示させてみました。
Arduino IDEを使いました。

以下の図のように「Hellooo Wooorld!」という文字列を右端から左端に横スクロールさせました。

図：スクロールの様子
![スクロールの様子.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/9c32a86c-ed3f-9a2a-8fd4-adf7525abcc6.png)






# 環境構築
[こちらのQiita記事](https://qiita.com/itiB_S144/items/7a232c1a31151fcb5e5b)の通りに行いました。（カンタン！）

# Arduinoのスケッチ

Arduinoのスケッチは下に載せた「M5StickMoveText.ino」の通りです。

スケッチの中では、下の「図：スクロール領域の指定」のようにスクロールする領域(Spriteの領域)のパラメータをdefine定義しています。

その他のスクロールに関するパラメータもdefine定義しているので、お試しになりたい方はそこを変更していただけると良いかと思います。
　

図：スクロール領域の指定![スクロール用テキストの指定値.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/a073906e-b181-2999-2da7-01c5cfd0e6c4.png)




```c:M5StickMoveText.ino
#include <M5StickC.h>

TFT_eSprite scrollText = TFT_eSprite(&M5.Lcd); // Sprite object

int tcount;
int dispLength;
int scrollWidth;
int startOffset;

#define M5STICK_TFT_W 160
#define M5STICK_TFT_H 80

#define TFT_BG_COLOR TFT_BLACK
#define TEXT_SPRITE_H M5STICK_TFT_H
#define TEXT_SPRITE_W M5STICK_TFT_W*4
#define TEXT_SCROLL_H M5STICK_TFT_H
#define TEXT_SCROLL_W M5STICK_TFT_W
#define TEXT_SCROLL_PIXEL 2
#define TFT_TEXT_POSI_X 30 // vertical position
#define TFT_TEXT_POSI_Y 0 // horizontal position
#define TEXT_SPRITE_POSI_X 0 // vertical position
#define TEXT_SPRITE_POSI_Y 0 // horizontal position
#define TEXT_FONT_SIZE 4
#define TEXT_SPRITE_COLOR TFT_BLACK
#define SCROLL_INTERVAL_MS 50

void setup() {
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(TFT_BG_COLOR);

  // Create a sprite for Hello World
  scrollText.setColorDepth(8);
  scrollText.createSprite(TEXT_SPRITE_W, TEXT_SPRITE_H);
  scrollText.fillSprite(TEXT_SPRITE_COLOR);
  scrollText.setTextColor(TFT_WHITE); // White text, no background

  tcount = 0;
  dispLength = 0;
  scrollWidth = 0;
  startOffset = 0;
}

void loop() {
  // Push the sprites onto the TFT at specied coordinates
  scrollText.pushSprite(TFT_TEXT_POSI_Y, TFT_TEXT_POSI_X);

  if (tcount > 0) {
    scrollText.scroll(-TEXT_SCROLL_PIXEL); // scroll text left
    tcount--;
  }
  else {
    startOffset = M5STICK_TFT_W; //start position is edge of tft
    if (dispLength > 0) {
      scrollWidth = dispLength + startOffset;
    }
    else {
      scrollWidth = 0;
    }
    tcount = scrollWidth / TEXT_SCROLL_PIXEL;
    String drawStr = "Hellooo Wooorld!";
    dispLength = scrollText.drawString(drawStr, TEXT_SPRITE_POSI_Y + startOffset, TEXT_SPRITE_POSI_X, TEXT_FONT_SIZE);
    if (TEXT_SPRITE_W <= dispLength) {
      dispLength = TEXT_SPRITE_W; // disp length is too long -> TEXT_SPRITE_W
    }
    scrollText.setScrollRect(0, 0, dispLength + startOffset, TEXT_SCROLL_H, TEXT_SPRITE_COLOR); // Update ScrollRect
  }

  delay(SCROLL_INTERVAL_MS); // wait so things do not scroll too fast

}


```

			
# 参考記事

 + M5StickCを動かしてみる
  + https://qiita.com/itiB_S144/items/7a232c1a31151fcb5e5b

 + M5Stackのサンプルスケッチ (文字スクロール)
  + https://github.com/m5stack/M5Stack/blob/master/examples/Advanced/Display/Sprite/Sprite_scroll/Sprite_scroll.ino
 + M5StickCの小ネタ (144Labグループ開発者ブログ)
  + https://tech.144lab.com/entry/M5StickC_Tips

			
# 更新履歴
* 2019-07-07：新規作成 
* 2019-07-07：概要の図を追加＆スケッチを修正
ライフサイクル　優良記事

制約の更新のタイミングなどの参考になるかも

**・[基礎からやりなおしメモ 【ライフサイクルと記述ルール】 - Qiita](https://qiita.com/yuri_RN/items/8ff47aac98dbf6c9dc7a)**
**・[UIViewにおけるレイアウトのライフサイクル - Qiita](https://qiita.com/shoheiyokoyama/items/2f76938dffa845130acc)**
**・[ios – 向きの変更後にUIViewフレームが更新されない - コードログ](https://codeday.me/jp/qa/20190407/574428.html)**
Python+OCR(tesseract)で新しい学習データ（言語データ）を追加してみた

## 背景
Anaconda + python + tesseract でOCR環境を構築したのですが、
対応していない言語をOCRする必要が出てきました。
ということで、新たな言語の学習データを追加してみました。

## 環境
MacOS Mojave ver10.14.4
Anaconda Navigator 1.9.7
　※Anacondaのインストールは、[こちら](https://qiita.com/satoshi-iwaki/items/e431b4182e50a2918a17)を参考にいたしました
JupiterNotebook 5.4.0

## 実践
tesseract用の学習データ（「xxxx.traindeddata」）を入手して、指定のフォルダに格納します。

### 学習データの入手
各種言語データ
https://github.com/tesseract-ocr/tessdata
使用したい言語データ（xxx.traineddata）を入手します。

7セグメント用（温度計等のデジタル数字）
https://github.com/arturaugusto/display_ocr
「letsgoditital」→「letsgodigital.traineddata」を入手


### 学習データの格納場所
ダウンロードしてきた学習データを下記のフォルダに格納します。今回は、「letsgoditital」を格納しました。


```python

/Users/xxx/anaconda3/share/tessdata/
```
もし、格納場所がわからない場合は、下記のコードを一度実行してみましょう。
実行結果の一番下に
「TesseractError: (1, b'Error opening data file 〜〜」
という部分があるかと思います。これは、指定した学習データがないよというエラーです。
なので、こちらに学習データを格納してあげましょう。

```python

txt = tool.image_to_string(
    Image.open('./imagesFolder/num/567.png'),
    lang="letsgodigital",
    builder=pyocr.builders.TextBuilder(tesseract_layout=6)
)
print( txt )
```
```python:実行結果

TesseractError                            Traceback (most recent call last)
<ipython-input-7-294dc4179e9d> in <module>()
      2     Image.open('./imagesFolder/num/567.png'),
      3     lang="letsgodigital",
----> 4     builder=pyocr.builders.TextBuilder(tesseract_layout=6)
      5 )
      6 print( txt )

~/anaconda3/lib/python3.6/site-packages/pyocr/tesseract.py in image_to_string(image, lang, builder)
    378                                          configs=builder.tesseract_configs)
    379         if status:
--> 380             raise TesseractError(status, errors)
    381 
    382         tested_files = []

TesseractError: (1, b'Error opening data file 
/Users/xxxx/anaconda3/share/tessdata/letsgodigital.traineddata\n
Please make sure the TESSDATA_PREFIX environment variable is set to your "tessdata" directory.\nFailed loading language \'letsgodigital\'\nTesseract couldn\'t load any languages!\nCould not initialize tesseract.\n')
```



### 学習データの確認
下記コードを使って、学習データが使えるようになっているか確認します！

```python
from PIL import Image
import sys
import pyocr
import pyocr.builders

tools = pyocr.get_available_tools()
if len(tools) == 0:
    print("No OCR tool found")
    sys.exit(1)
# The tools are returned in the recommended order of usage
tool = tools[0]
print("Will use tool '%s'" % (tool.get_name()))
# Ex: Will use tool 'libtesseract'

langs = tool.get_available_languages()
print("Available languages: %s" % ", ".join(langs))
lang = langs[0]
print("Will use lang '%s'" % (lang))
```
結果はこちら。
無事7セグメント用デジタル数字（「letsgodigital」）が使用可能なのが確認できます。

```python:実行結果

Will use tool 'Tesseract (sh)'
Available languages: eng, jpn, letsgodigital,
Will use lang 'afr'
```

## 終わりに
以上、tesseractの初期セットにない学習データを追加してみました！これで、いろんな言語のOCRが可能になります！
静的コンテンツの配信(GAE/Go/Gin)

#はじめに
GAEをGinを利用して構築していきます。
[プロジェクトとアプリケーションの設定 (GAE/Go/Gin)](https://qiita.com/koshi_an/items/472659f89ef3e472b896)の続きです。

流れは、公式サイトの[静的コンテンツの配信](https://cloud.google.com/appengine/docs/standard/go/building-app/serving-static-files?hl=ja)と同じです。


#ソース

今回のフォルダ構成は、以下の通りです。
svgファイルは、[公式サイト](https://cloud.google.com/appengine/docs/standard/go/building-app/serving-static-files?hl=ja)からダウンロードしてください。

```
├──  template
│    └── index.html
├──  static
│    ├── style.css
│    └── gcp-gopher.svg
├──  app.yaml
└──  main.go
```

```yaml:app.yaml
runtime: go111

handlers:
- url: /static
  static_dir: static
  
- url: /.*
  script: auto
```

```css:style.css
body {
    font-family: Arial, sans-serif;
    color: blue;
  }
```

```go:main.go
package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"google.golang.org/appengine"
)

func main() {
	router := gin.Default()

	router.LoadHTMLGlob("template/*") // 事前にテンプレートをロード(相対パス)

	router.GET("/", HelloWorld)

	http.Handle("/", router) // router.Run(":8080")の代わり
	appengine.Main()         // これがないと動かない
}

func HelloWorld(c *gin.Context) {
	c.HTML(http.StatusOK, "top/hello", gin.H{
		"hello": "hello, World!!",
	})
}
```


```html:template/index.html
{{ define "top/hello" }}
<!DOCTYPE html>
<html>
  <head>
      <link rel="stylesheet" type="text/css" href="/static/style.css">
  </head>

  <body>
    test
    <img id="logo" src="/static/gcp-gopher.svg" width="100">
    <h1>{{ .hello }}</h1>
  </body>
</html>
{{ end }}
```


#ローカルで実行
`dev_appserver.py app.yaml`

`localhost:8080`  にアクセスすると以下の画面が表示されます。

![スクリーンショット 2019-07-07 14.48.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125499/48163e0a-b56e-f1fb-eeaa-5781062c3224.png)


#アプリケーションをデプロイする

`gcloud app deploy`


#アプリケーションを表示する

`gcloud app browse`


その後、`http://[YOUR_PROJECT_ID].appspot.com`で、画面が表示されるかを確認します。



#参考
[静的コンテンツの配信](https://cloud.google.com/appengine/docs/standard/go/building-app/serving-static-files?hl=ja)