OmniAICreator/Qiita-1.07M huggingface dataset:
RailsでiOSアプリのURI スキームに対応する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110571/3a89bb3e-bb83-12f1-415d-c5178bac8563.png)

> 一瞬「あれっ...」ってなったので備忘録

# TL; DR
- `routes.rb`内でダイレクトルーティングで定義すればOK

# バージョン
- Ruby：2.6.1
- Rails：5.2.3

> タイトルにiOSと書いてますがAndroidも対応できます。ただのRoutingの話なので。

# やりたいこと
- RailsがWebとモバイルアプリの両方のサーバサイドの役割を担っている
- モバイルアプリ内で、特定の画面に遷移させるURIスキームを使いたい
    - メニューなどで表示されていないページへの遷移など
- 上記の例としてInstagramに「運営からのコメント」があり、チャットで操作説明を受ける画面に遷移させたいような目的があったとする
    - ヘルパーリンク：`qa_chat`
    - URIスキーム：`instagram://qa_chat`

# 解決策
### routes.rb
`routes.rb`で、以下のようなダイレクトルーティングを設定してあげれば良いです。

```routes.rb
direct :qa_chat do
    "instagram://qa_chat"
end
```

### ヘルパーリンク
Railsと同一のViewでヘルパーリンクを利用する場合は、以下のように記述します。

```sample.erb
<%= link_to qa_chat_url %>
```

ちなみにダイレクトルーティングについて、Railsガイドでは以下の部分に記載があります。
（このURIスキームについての記載はありませんが、あくまで参考までに）
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110571/1395ee2c-e58d-de2f-9a69-455db09c1f22.png)](https://railsguides.jp/routing.html#%E3%83%80%E3%82%A4%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%EF%BC%88direct-routes%EF%BC%89)

# 小ネタ
## 外部URLもroutes.rbで変数として定義できる
ダイレクトルーティングといえば、こちらの使い方のほうが一般的です。

よく使う外部URLを変数定義して、Railsアプリケーション内で使うことができます。
サービスLPのURLを記述する時は、個別にではなく、`routes.rb`にまとめて記述するほうが管理しやすいです。

```example.rb
direct :homepage do
    "http://www.rubyonrails.org"
end
```
(ユーザ定義の) Docker Networkチートシート

何回も調べなおしているのでメモを兼ねて
（特にdocker-composeでのネットワーク指定パターン）

# ネットワークの作成方法

```sh
docker network create -d bridge --gateway=192.168.0.1 --subnet=192.168.0.0/16 <ネットワーク名>
```

# docker run時の指定方法

```sh
docker run --net=<ネットワーク名>
```

# Docker composeからの利用方法

## IPアドレスを指定して使う

```yaml
services:
  my-service:
    ~~~
    networks:
      default:
        ipv4_address: 192.168.0.1

networks:
  default:
    external:
      name: <ネットワーク名>
```

## IPアドレス自動割り当てで使う

```yaml
services:
  my-service:
    ~~~
    networks:
      - <ネットワーク名>

networks:
  <ネットワーク名>:
    external: true
```
Chocolateyをインストールした話

\:information_source: この記事は別サイトで執筆した[Chocolateyをインストールした話 – ひつじぶどう](https://blog.rumraisin.tokyo/?p=126)の内容を加筆・修正した上で転載しています。

# はじめに
Chocolateyとは, Windowsで使用できるコマンドラインのパッケージマネージャーです。
今回はそのChocolateyをインストールした話ですが, 公式サイトに載っているインストール方法にちょっと一工夫というお話です。

# インストール
インストールは基本的にChocolateyの[公式サイトの「Installation」セクション](https://chocolatey.org/docs/installation#install-with-powershellexe)に載っている下記のコマンドを実行すればOKです。

```PowerShell
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
```

ただ, これに従っただけだとインストール後にこんな警告が出てくることがあります。

```PowerShell
WARNING: Not setting tab completion: Profile file does not exist at
'C:\Users\●●●\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1'.
```

PowerShellのプロファイルを用意していない場合, タブ補完が効かなくなるようです(なければ作って欲しいんですが)。
きっと後からでも修正できるんでしょうけどそういうのはめんどくさくて好きじゃないので, 下記のスクリプトを作ってプロファイルがない環境であれば作ってからインストールを実行するようにしましたというお話でした。

```PowerShell:IntasllChocolatey.ps1
# プロファイルがないとTab補完が効かなくなるのでない場合は追加
$PROFILE_PARENT = $(Split-Path $PROFILE -Parent)
If( !(Test-Path $PROFILE_PARENT) ) {
	New-Item -Type Directory $PROFILE_PARENT
}
New-Item -Type File $PROFILE

# 公式ページにあるダウンロードスクリプト
Set-ExecutionPolicy Bypass -Scope Process -Force
Invoke-Expression ( (New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1') )
```
実験系でもPythonで効率化したい(4)try構文を用いてエラーを吐いたときにser.close()するようにする


## 前回までのあらすじ
前回までで測定を自動化できるようになりました。今回は測定装置が機嫌が悪い時に、エラーを吐いてしまうのでそれに対応します。

## Windows COMポート二桁以上許容されない問題
- [マイクロソフトサポートページ](https://support.microsoft.com/ja-jp/help/115831/howto-specify-serial-ports-larger-than-com9)
- 上記サイトでも言及されている通り、Windowsでは**COMポートが、接続デバイスが増えるごとに増殖し続けるにも関わらず、10以上になると不具合が出る**ことがあります。私の環境ではADVANTEST社のR6441が、USBハブなどを用いて接続しているときに、COMポートが10以上だと測定に失敗することがあります。

## try構文を用いて解決する
`except`のあとに例外の名前(エラーのときに出力される)を書いておくと、失敗したときの挙動を決められます。今回は、`ser.close()`するようにします。

```python
try:
    while 1:
        if pulse >= MAX:
            ## 位置がMAXまで来ている場合while文を終了
            break
        ## 現在位置の情報を記録
        pulse_list.append(pulse/2)
        ## 電流を測定する(5回とって平均したものをその位置での値とする)
        for i in range(5):
            ser = serial.Serial(COMampere,bitRate,timeout=0.1)
            ser.write(b"F5, R0,PR2\r\n")
            time.sleep(1)
            ser.write(b"MD?\r\n")
            time.sleep(1)
            tmp = ser.read_all()
            # 電流が取れていない場合はスキップする
            if len(tmp)== 0:
                ser.close()
                continue
            ampere = float(tmp.split()[2])
            ampere_average_list.append(ampere)
            time.sleep(1)
            ser.close()
        ## 電流とpulse(位置)をlistに追加
        ampere_list.append(sum(ampere_average_list)/len(ampere_average_list))
        ampere_average_list = []

        ## 光学台を動かす
        pulse += 1000
        position = "A:2+P"+str(pulse)+"\r\n"
        ser = serial.Serial(COMpulse,bitRate,timeout=0.1)
        ser.write(bytes(position, 'UTF-8'))
        time.sleep(1)
        ser.write(b"G:\r\n")
        ser.close()

    ## リストをdataframeに変える
    print(ampere_list)
    print(pulse_list)
    df = pd.DataFrame({'ampere(A)':ampere_list,'pulse':pulse_list})
    def pulseToMilliMeter(pulse):
        return pulse*0.006
    df["position(mm)"] = df["pulse"].map(pulseToMilliMeter)
    df.to_csv('./csv/result.csv',index=False)
    plt.figure()
    df.plot(x='position(mm)',y='ampere(A)',marker='o')
    plt.savefig('./img/sample.png')
    plt.close('all')
except IndexError:
    ser.close()
```
workbenchのエラー（Error Code: 1175）の対処法

workbenchを使っていて、このエラーにぶち当たったので、対処法を備忘録として記載しておきます。

エラー内容
Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.  To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect.

なんて言っているかというと。。。

「君はセーフモードで起動しているから、prifarence key（主key）以外の絞り込み検索条件（where以降の条件文）ではUPDATEができないぜ！もしもセーフモードを無効にしたかったら、Preferences -> SQL Editor で切り替えてくれ！そして、再接続してね！」

ということを言っているわけです。

macだとどう辿るかを記載します。

1. 左上のMySQLWorkBenchからPreferencesを選択
2. 立ち上がったポップアップにてSQL Editor を選択
3. Others内のSafe Updates のチェックを外す
4. workbenchを再起動

このステップで解決できました！
FizzBuzzの問題を外部入力した数値から数えるアプリケーションを作ってみた

# 通常FizzBuzzの問題は、1~100までを数えるものが多いみたいですが、今回はgets.to_iを使用し、入力した数を（含めて）から30数えるアプリケーションを作ってみる


#目的
　・学習のため
　・入力した数値からFizzBuzzできたら面白そうだと思ったから


#下記条件を満たすように作る
　・外部入力させる
　・入力させた数値を含めて、そこから30数える
　・3の倍数の場合はFizzと表示させる
　・5の倍数の場合はBuzzと表示させる
　・15の倍数の場合はFizzBuzzと表示させる
　・「数値を入力してください」と表示させた後に、入力させる
　・数値を入力させた後は、改行させるか、文字をいれる（ターミナル上で見栄え良くするため）

#擬似コードを書く

```rb

puts "数え始める開始の数値を入力してください"
x = 数字を入力させる
puts "下記に入力した数値を含めて30数えます"
y = 30数えるため、外部入力させた数値に30を足す

  xから(30数える=y)each do|i|
※ここから先はいつものFizzBuzzと一緒
if　○○なら
　puts ○○と表示する

elsif
   ○○なら
 puts ○○と表示する

elsif
   ○○なら 
 puts ○○と表示する
else
  それ以外なら
 puts ○○と表示する

```

#できたアプリケーションがこちら

```rb

puts "数え始める開始の数値を入力してください"

x = gets.to_i
puts "下記に入力した数値を含めて30数えます"
y = x + 30

  (x..y).each do|i|

  if i%15==0
      puts "FizzBuzz"
  elsif
      i%3==0
      puts "Fizz"
  elsif
      i%5==0
      puts "Buzz"
  else
      puts i
  end
end

```

#動作確認しよう。今回は、100から数えてみる。

```
数え始める開始の数値を入力してください
100
下記に入力した数値を含めて30数えます
Buzz
101
Fizz
103
104
FizzBuzz
106
107
Fizz
109
Buzz
Fizz
112
113
Fizz
Buzz
116
Fizz
118
119
FizzBuzz
121
122
Fizz
124
Buzz
Fizz
127
128
Fizz
Buzz
```

あっさり出来た。
感覚的にできるもんすね・・・・・。

たぶん間違っていないかと思われる。
他に良い方法ありそうでしたら、ご指摘いただけますと幸いです。


参考:FizzBuzz基本問題
https://qiita.com/pontarou194/items/6cf17868a8346613fddf
ABEJA「機械学習モデルの負荷がやばすぎて、100倍高速にしつつ精度も上げた話」勉強会メモ

本記事は2019/10/10にABEJAさんの「機械学習モデルの負荷がやばすぎて、100倍高速にしつつ精度も上げた話」に参加したときのメモです。
機械学習を実業務に適用する際に現場で起こった障害・知見について聞ける貴重な機会でした。
うろ覚えの箇所がちょくちょくありますが、間違っていたらコメントにて教えてください！

# 発表スライド
slido.com
`#abejaai_20191010`

# ABEJAのプロダクト：ABEJA Insight for Retail

Insight for Retailまわりのお話がメインでした。
機械学習の技術をビジネスへ適用する際に、以下が難しかったとのこと。

- 現実世界のデータ取得
    - 研究で使うデータセットのように、綺麗なデータを入手できない。
    - 例えば、店の天井にカメラを設置すると大抵斜め上からの顔画像しか取得できない。
- 不安定なIoTデバイス、モデルのハンドリング
    - 業務適用には、システムの安定稼働が必要。

# Retail Face Analysis Inside-Out
店に来た人について、以下の流れで年齢性別推定、リピーター分析を行うシステム。

### 1. Detection, Tracking
顔を検出し、同一人物を集約する。
Detectionはすべてのフレームにやる必要あるので、コンパクトさが求められる。
非生体の顔を除きたい。

### 2. Filtering
学習には顔画像の品質が大事なため、良い画像データを抽出したい。
カメラは天井についているので、例えば来店した人物がうつむいていると良い画像は得られない。また、逆光になると画像品質は落ちる。
品質を評価するために、Error Regression Networks(ERNs)を考案した。

ERNs
ある分布のへりにいる画像ほど品質悪い、と判定する。

- 異なる人物からの大量の顔画像が必要。
- 大きなモデルのほうが精度よいが、当然取り回しが悪いのでバランスが重要。
- 精度のよいデータセットを作るのが困難。

NNはEfficientNetを使う。Googleの出した、ハイパラが少ないモデル。
最初は小さい解像度、チャンネル、層の数の組み合わせで学習を初めて徐々にでスケールさせることで精度が上がった。
→小さい解像度だと、精度が出なかったが解像度を上げるにつれてResNet50以上の精度が出たとのこと。

分布はvon-Mises Fisher分布を使う。muの最尤推定が簡単なため。

分布の中心を算出する方法には、Sphere Embeddingを使った。
顔画像、人物ラベルを球面へ埋め込む。
コサイン内積をとるときに、正解ラベルのみウェイトが高い。
ArcFaceはこれを使っている。ただし、学習はDGX-1 GPU。
AdaCos: ArcFaceのハイパラ自動チューニングを使う。

### その他
- 他のモデルも色々試したが、再現できないものが多かったらしい。
（中国系の論文は再現性低いものがよくある・・・）
- 多クラス分類は、10万人程度のデータがないと論文クラス(State of the arts)の精度は出ない。

## 年齢推定
小売はプラスマイナス5才くらいで当てられないと厳しい。
- 実敵年齢、見た目年齢
- 見た目年齢のアノテーションは困難
- 実敵年齢付きデータの取得は困難
- 顔だけから推定する難しさ
- 研究として最近流行っていない
- Public Datasetは外国人が多い。
- カメラの位置によって、見え方が全然違うので学習が難しい

### 知見
20代半ばを境に、実年齢-見た目何例の入れ替わりが起こる。人間の認知バイアスによる。

## Aggregating Multiple Predictions
集約。難しいらしい。
綺麗な顔と汚い顔の識別、という言い方は笑った

# 研究成果のプロダクション適用

## Retail Task Force
各タスクはDAGとして実装。
マイクロサービスは負荷に合わせたオートスケールが可能。
MLにおけるAWSを用いたマイクロサービスアーキテクチャ

## 障害
（うろ覚えですみません）
2019年のGWに障害発生。Insight for Retailを導入したある小売店で、想定以上の来客数があったため来客画像の特徴量検索がスケール限界を迎えた。
リソースは基本的に無限にオートスケールするよう構築しているが、高負荷に耐えられるよう特徴量検索システムの作りを変える必要がある。

### 対応
ロジックとデータを分離することで、特徴量検索の処理速度改善を行った。

- データロード時間
- ロジック改修の影響減

データが増え続けると、特徴検索時間は増える。選択肢は2つ。

- 厳密探索にすると、9.8倍高速化可能。→採用
- 近似最近傍探索にすると、200倍高速化可能。ただし、updateが多いと、トータルで4倍にまで落ちるため不採用となった。

担当の方は一人で障害対応したとのこと。つらそう。。
自社プロダクトだから許されるのだろうか笑

### 小売業界の話など
小売業界の顧客はシステムにかけられるコストが（他業界と比べ）少ないので、システムの売価を下げることも必要。
今後の課題は原価削減になる。

ABEJAの顧客は全体の20%が全カメラの8割を契約しているらしい。
こうした「大口」顧客のために、ABEJAは個別のキューを用意している。

## 研究と開発のコミュニケーションはどうやっている？

適度な距離を保つ。
    - 週イチ程度の打ち合わせ
    - 開発後半で実装する機能を決める

レポジトリを分ける
- 研究・開発で大量のブランチ運用があったが、思い切ってリポジトリを分けてうまくいっている。

# QA
- API、モデルは自作している。値段が高い、できないため。
- 業務の中で、論文調査に割く時間 人によって違う
- DAGのレイテンシーは翌日までに提供できればよい。
- データ取得環境の影響: 施工、
- ABEJAの人数構成はResearcher1, Engineer2とか

# 本日の格言
「モデルより施工が大事」
良いモデルは良いデータの上にのみ成り立つようだ。
cscの作法 その35 アナログ時計

#概要

cscの作法、調べてみた。
練習問題やってみた。

#練習問題

アナログ時計。


#写真

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3d883776-da73-b5f6-bc02-41a614ae4e5a.png)



#サンプルコード


```
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing.Drawing2D;


class form1: Form {
	form1() {
		Text = "clock";
		Opacity = 0.7;
		ClientSize = new Size(150, 150);
		Timer timer = new Timer();
		timer.Interval = 1000; 
		timer.Tick += new EventHandler(timerTick);
		timer.Start();
	}
	protected override void OnPaint(PaintEventArgs e) {
		Graphics g = e.Graphics;
		g.TranslateTransform(ClientSize.Width / 2, ClientSize.Height / 2, MatrixOrder.Append);
		Pen BPen = new Pen(Color.Blue, 5);
		Pen GPen = new Pen(Color.Green, 5);
		Pen RPen = new Pen(Color.Red, 3);
		Point center = new Point(0, 0);
		DateTime time = DateTime.Now;
		double secAng = 2.0 * Math.PI * time.Second / 60.0;
		double minAng = 2.0 * Math.PI * (time.Minute + time.Second / 60.0) / 60.0;
		double hourAng = 2.0 * Math.PI * (time.Hour + time.Minute / 60.0) / 12.0;
		int r = Math.Min(ClientSize.Width, ClientSize.Height) / 2;
		int secHandLength = (int) (0.9 * r);
		int minHandLength = (int) (0.9 * r);
		int hourHandLength = (int) (0.7 * r);
		Point secHand = new Point((int) (secHandLength * Math.Sin(secAng)), (int) (-secHandLength * Math.Cos(secAng)));
		Point minHand = new Point((int) (minHandLength * Math.Sin(minAng)), (int) (-minHandLength * Math.Cos(minAng)));
		Point hourHand = new Point((int) (hourHandLength * Math.Sin(hourAng)), (int) (-hourHandLength * Math.Cos(hourAng)));
		g.DrawLine(RPen, center, secHand);
		g.DrawLine(GPen, center, minHand);
		g.DrawLine(BPen, center, hourHand);
	}
	void timerTick(object sender, EventArgs e) {
		this.Invalidate();
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}




```


以上。
Uncaught Error: Call to undefined function～が出た時は

#前回のあらすじ
アンケートシステム作ってるなう
・タグでいたずらされないようにしてた。
#今日やったこと（ハイライト）
・XAMPPでMySQLのDBを構築した
・DBにアンケートデータが自動で保存されるよう頑張った
（今回の教科書『いきなりはじめるPHP ワクワク・ドキドキの入門教室』)
#困ったこと
・Uncaught Error: Call to undefined function mb_internal_encording()～～って名前のエラーが出た
#原因
mb_internal_enco「 **r** 」ding　スペルミスってた！！
mb_internal_encoding　　直した！！やったね！！
#感想
自動保存の機能を追加するためのソースを書いてる上で、文字列の連結を理解するのが難しかった。てことで、明日以降の私に丸投げした。

#次回の目標
アンケートシステムをもっと便利にするよう学習していくぞい
WebSocketについて

## WebSocketとは
- サーバとクライアントとの間で効率的な双方向通信を実現する通信規格。
- WebSocket独自のプロトコルで通信を行う為、ヘッダが小さく、通信のオーバーヘッドが少ない。
- セイムオリジン制限は適用されず、WebSocketサーバ側で制限をかける。

## 既存の通信技術との比較
### XMLHttpRequest
- XHRでは通信の度にリクエストヘッダが付与されるため、パファーマンスの差に繋がる。
- サーバ側からクライアント側にプッシュ通知することが難しい。

## WebSocketの動作

```javascript

// WebSocket 接続を作成する
const socket = new WebSocket('ws://localhost:8080');

// 接続を開く
socket.addEventListener('open', function (event) {
   /* do something */
});

// メッセージを待ち受ける
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});
```

## 実装
今度書く。

## 参考
[WebSocket - MDN web docs]
(https://developer.mozilla.org/ja/docs/Web/API/WebSocket)
[日本語版 Modern JavaScript Tutorial - WebSocket]
(https://ja.javascript.info/websocket)
ffmpegで連番画像からフレーム補完をした画像を得る

フレームレート24を想定して作られた連番の`frame_00000.png`,`frame_00001.png`,...という画像からフレーム補完をしたフレームレート60の連番画像を得るffmpegのコマンド。

```
ffmpeg -framerate 24 -i frame_%05d.png -vf minterpolate output/frame_%05d.png
```

※ 出力結果が入力と混ざらないように、出力先フォルダを分けています。

minterpolateにいろいろオプションを設定することでより改善したイメージが得られる可能性がある。

```
ffmpeg -framerate 24 -i frame_%05d.png -vf "minterpolate='mi_mode=mci:mc_mode=aobmc:me_mode=bidir'" output/frame_%05d.png
```

minterpolateに指定可能なオプションは[公式ドキュメント](https://ffmpeg.org/ffmpeg-filters.html#minterpolate)に一覧があります。
Pythonによる AI・機械学習について学んだ内容(1)

#はじめに
この本を使って勉強しています
[Pythonによる AI・機械学習・深層学習アプリのつくり方](https://www.socym.co.jp/book/1164)

#1-1　機械学習で何ができる？
- 分類(classification) ... 与えられたデータを分類
　データの特徴を調べて分類する

- 回帰(regression) ... 過去の実績から未来の値を予測
　過去のデータを学習して将来の数値予測を行う

- クラスタリング(clustering) ... データを似たものの集合に分類
　分類と違うのはあらかじめ決まっている項目に分けるのではなく似たもの区分けする

- 推薦(recommendation) ... データの関連情報を導き出す
　ネットショッピングでユーザの嗜好にあったものを推薦する

- データの次元数を削減(dimensionality reduction) ... データの特徴を残して削減
　大きな次元から特徴的なデータを特定して次元を削減し、効率的にデータを分析する

##何に適用できる？
- 画像解析　画像の物体を判定
- 音声解析　音声からテキストに変換、どんな音なのか判定
- テキスト解析　文章のカテゴリ分け、特定表現の抽出・構文解析

##機械学習の種類
- 教師あり学習(Supervised Learning)
 - データとともに正解が与えられる
 - 未知のデータに対して予測を行う
- 教師なし学習(Unsupervised Learning)
 - 正解は与えられていない
 - 未知のデータから規則性を見出す
- 強化学習(Reinforcement Learning)
 - 行動により部分的に正解が与えられる
 - データから適切な買いを見つける 

#1-2　どのようなシナリオで機械学習を行うのか
1.　ゴールの決定
2.　データの収集
3.　データの整形・加工
4.　データを学習
　1.　機械学習の手法を選択
　2. パラメータの調整
　3. データを学習してモデルを構築
5. モデルを評価
6. 十分な精度がでなければ4.に戻る
7. 業務で活用

#1-3　機械学習で利用するデータの作り方

 機械学習で役に立つ汎用的なデータフォーマット

- カンマ区切りデータ CSV 形式
- ini ファイル形式
- XML
- JSON(JavaScriptのオブジェクト形式を元に考案された構造化データ)
- YAML

その他、Numpy保存形式、Pythonオブジェクトをそのまま書き込むことができる pickleなど
テーブルにカラムの追加と削除をする方法(Laravel)

### はじめに
今回も自分用のメモとしてアウトプットします。

###・カラムの追加
#### 1.migrationファイルの作成

例:postsテーブルにtagというカラムを追加したい場合

```
$ php artisan make:migration add_tag_to_posts_table --table=posts
```

上記の
:small_red_triangle:add_tag_to_posts_tableの部分は任意の命名で大丈夫です。
ですが、マイグレーションファイル名がそのままクラス名として生成されるので、できるだけわかりやすい名前をつけた方が良いです。

:small_red_triangle:--table=postsの部分では、カラムを追加するテーブルの指定を行なっています。

1のコマンドをターミナルで実行するとマイグレーションファイルが作成されます。

#### 2.migrationファイルに記述の追加
upメソッドに追加の処理を記述します。

```

    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
                        $table->string('tag');
        });
    }
```

上記のような感じですね。

#### 3.migrationの実行

```
$ php artisan migrate
```
こちらでテーブルにカラムの追加ができます。

### ・カラムの削除
こちらもカラムの追加と流れは似ています。

#### 1.まずは、composer で “doctrine/dbal” パッケージを追加する必要があります。

```
$ composer require doctrine/dbal
```

#### 2.migrationファイルの作成
例:postsテーブルのtagというカラムを削除したい場合

```
$ php artisan make:migration drop_column_tag_column --table=posts
```
こちらもカラムの追加と同様に、任意のファイル名とカラムを削除したいテーブルの指定をします。

#### 3.migrationファイルに記述の追加
upメソッドに削除の処理を記述します。

```
    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->dropColumn('tag');
        });
    }

    public function down()
    {
        Schema::table('posts', function (Blueprint $table) {
          // カラム作成時のコードを記述
        });
    }
```
カラムを削除するには、スキーマビルダのdropColumnメソッドを使用します。
tagの部分は、削除したいカラム名に変更をお願いします。
また、downメソッドにカラム作成時に書いたコードを記述しておくと、ロールバック時に消したカラムを元に戻すことができます。もしそれが不要の場合は記述は無しでも大丈夫です。

#### 4.migrationの実行

```
$ php artisan migrate
```

これでテーブルからカラムの削除ができます。

### さいごに
初歩的ではありますが、自分の為にもアウトプットしました。
今回の記事で誤字、脱字等ありましたらお手数ですがご指摘をお願い致します。また、最後まで見て頂きありがとうございました！！
Vue component

```vuejs:html
<html>
  <head>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <div id="app">
      <button-counter></button-counter>
      <title1 title="タイトル"></title1>
    </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
      Vue.component('button-counter', {
        data: function () {
          return {
            count: 0
          }
        },
        template: '<button @click="count++">クリック数: {{ count }}</button>'
      });

      Vue.component('title1', {
        props: ['title'],
        template: '<h3>{{ title }}</h3>'
      });
      new Vue(
        { el: '#app' } );
    </script>
  </body>
</html>
```
JavaScript勉強の記録その3: for文

#JavaScriptでfor文

for (初期値; 条件式; 増減値) {ループ毎に行いたい処理;}
と書くことでループ処理ができる。

以下の例では１から10までをコンソールに表示します。

```index.js
for (let i = 1; i <= 10; i++) {
  console.log(i)
}

// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
```
ちなみに``（バッククオート）の中に、${式}と書くことで、文字列の中に式を展開することができます。　これをテンプレートリテラルと言うそうです。

```index.js
for (let i = 1; i <= 10; i++) {
  console.log(`hello ${i}`)
}

// hello 1
// hello 2
// hello 3
// hello 4
// hello 5
// hello 6
// hello 7
// hello 8
// hello 9
// hello 10
```
【JavaScript】hamburgerMenuのコード

```html:filename.html
<body>
  <header>
    <nav class="global-nav">
      <ul class="global-nav__list">
	<li class="global-nav__item">
          <a href="">会社概要</a>
        </li>
	<li class="global-nav__item"><a href="">サービス</a></li>
	<li class="global-nav__item"><a href="">採用情報</a></li>
	<li class="global-nav__item"><a href="">アクセス</a></li>
	<li class="global-nav__item"><a href="">お問い合わせ</a></li>
      </ul>
    </nav>
		
        <div class="hamburger" id="js-hamburger">
          <span class="hamburger__line hamburger__line--1"></span>
          <span class="hamburger__line hamburger__line--2"></span>
          <span class="hamburger__line hamburger__line--3"></span>
        </div>
        <div class="black-bg" id="js-black-bg"></div>
  </header>
  
  <script src="humberger.js"></script>
</body>
```
```css:filename.css

.global-nav {
  position: fixed;
  right: -320px; /* これで隠れる */
  top: 0;
  width: 300px; /* スマホに収まるくらい */
  height: 100vh;
  padding-top: 40px;
  background-color: #fff;
  transition: all .6s;
  z-index: 900;
  overflow-y: auto; /* メニューが多くなったらスクロールできるように */
}
.hamburger {
  position: absolute;
  right: 0;
  top: 0;
  width: 50px; /* クリックしやすいようにちゃんと幅を指定する */
  height: 50px; /* クリックしやすいようにちゃんと高さを指定する */
  cursor: pointer;
  z-index: 600;
}
.global-nav__list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.global-nav__item {
  text-align: center;
  padding: 0 -2px;
  line-height: 500%;
}
.global-nav__item a {
  display: block;
  padding: -2px 0;
  border-bottom: 1px solid #eee;
  text-decoration: none;
  color: #111;
}
.global-nav__item a:hover {
  background-color: #eee;
}
.hamburger__line {
  position: absolute;
  left: 11px;
  width: 18px;
  height: 1px;
  background-color: #111;
  transition: all .6;
}
.hamburger__line--1 {
  top: 14px;
}
.hamburger__line--2 {
  top: 20px;
}
.hamburger__line--3 {
  top: 26px;
}
.black-bg {
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  z-index: 100;
  background-color: #000;
  opacity: 0;
  visibility: hidden;
  transition: all .6s;
  cursor: pointer;
}
/* 表示された時用のCSS */
.nav-open .global-nav {
  right: 0;
}
.nav-open .black-bg {
  opacity: .8;
  visibility: visible;
}
.nav-open .hamburger__line--1 {
  transform: rotate(45deg);
  top: 20px;
}
.nav-open .hamburger__line--2 {
  width: 0;
  left: 50%;
}
.nav-open .hamburger__line--3 {
  transform: rotate(-45deg);
  top: 20px;
}
```

```js:filename.js
function toggleNav() {
  var body = document.body;
  var hamburger = document.getElementById('js-hamburger');
  var blackBg = document.getElementById('js-black-bg');

  hamburger.addEventListener('click', function() {
    body.classList.toggle('nav-open');
  });
  blackBg.addEventListener('click', function() {
    body.classList.remove('nav-open');
  });
}
toggleNav();
```
minikubeをmacOSにインストールする[2020年1月版]

去年の年末あたりからそろそろk8sから逃れられないと感じ始めたので2020年は遂にk8sを始めます。
ということで今年最初の記事はmacOSにminikubeをインストールするところまでです。

macOSにminikubeをインストールする流れは以下の通りです。

1. kubectlのインストール
2. minikubeのインストール

## kubectlのインストール
以下にドキュメントに従うと最新バージョンがインストールされることになるが
最初からkubectlもバージョン管理した方がいいと思うのでkubectlのバージョンを管理するツールを探すところから始めましょう

https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-on-macos

それで見つかった記事がこれ
https://medium.com/faun/using-different-kubectl-versions-with-multiple-kubernetes-clusters-a3ad8707b87b

上記の記事で紹介されてたのが`asdf`

## [asdf](https://github.com/asdf-vm/asdf)



asdfを使って最新の安定バージョン(2020年1月4日現在v1.17.0)のkubectlをインストールします。
※厳密にいうとasdfのkubectlプラグインを使ってになります。

ちなみに最新の安定バージョンの情報はここにあります
https://storage.googleapis.com/kubernetes-release/release/stable.txt

```shell
$ git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.7.6
$ echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc
$ echo -e '\n. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
$ source ~/.bashrc
$ asdf plugin-add kubectl
$ asdf install kubectl 1.17.0
$ asdf list kubectl
  1.17.0
```

とりあえずグローバルでv1.17.0を使うようにします

```shell
$ asdf global kubectl 1.17.0
$ kubectl version --short --client
Client Version: v1.17.0
```

## minikubeのインストール
minikubeは単一のバイナリファイルとして用意されているのでhomebrewを使わずに以下のコマンドでインストールします

ちなみに2020年1月4月現在以下のコマンドだとv1.6.2のminikubeがインストールされます


```shell
$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 && sudo install minikube-darwin-amd64 /usr/local/bin/minikube
$ minikube version
minikube version: v1.6.2
commit: 54f28ac5d3a815d1196cd5d57d707439ee4bb392
```

kubectlのバージョンとk8sのバージョンには以下のようの関係性があるので注意が必要です！！
※だからこそkubectlのバージョン管理が必要になってきます

>You must use a kubectl version that is within one minor version difference of your cluster. For example, a v1.2 client should work with v1.1, v1.2, and v1.3 master. Using the latest version of kubectl helps avoid unforeseen issues.

https://kubernetes.io/docs/tasks/tools/install-kubectl/#before-you-begin


つまり今回kubectlのバージョンがv1.17.0なのでk8sのバージョンはv1.16.x 〜 v1.18.xであるべきということです。

とりあえずminikubeのv1.6.2のk8sのバージョンは確認します

```shell
$ kubectl get nodes
NAME       STATUS   ROLES    AGE     VERSION
minikube   Ready    master   5m45s   v1.17.0
```

単純に`minikube start`したらv1.17.0が入ってくれました。

ただ少し調べてみると`minikube start`時にk8sのバージョンを指定することができるようなので以下のコマンドでminikubeで作られるk8sのバージョンをv1.17.0に指定しました

```shell
$ minikube start --kubernetes-version v1.17.0
$ kubectl get nodes
NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   28m   v1.17.0
```

とりあえずmacOS上にk8sクラスタ環境ができました。
この環境を使って今後色々試していきたいと思います。
Intentのフラグを解析する

AndroidでIntentを受け取ったときにどういうフラグが設定されているかを調べたい時、単純に`intent.flags`を参照するだけだと分かりづらかったので、フラグの名称を出力するために以下のコードを書きました。

```kotlin
Intent::class.java.fields.forEach { field ->
  if (field.name.startsWith("FLAG_")) {
    val flag = field.get(null)
    if (flag is Int) {
      if (flag and intent.flags != 0) {
        Log.d("MyApp", "Intent Flag ${field.name}")
      }
    }
  }
}
```

これで`Intent Flag FLAG_ACTIVITY_NEW_TASK`などがログに出力されます。
JavaScript勉強の記録その2: Switch文

#JavascriptでSwitch文

switchの引数でとった値を判定し、'赤'だった場合は「止まれ」、'黄'だった場合は「注意、'青'だった場合は「渡れ」をコンソールに表示します。

```index.js
const signal = '青'

switch (signal) {
  case '赤':
    console.log('止まれ');
    break;
  case '黄':
    console.log('注意');
    break;
  case '青':
    console.log('渡れ');
    break;
}
```

ちなみにbreakはループ処理を抜ける命令ですので、breakの記述がない場合は下まで処理が続きます。

```index.js
const signal = '青'

switch (signal) {
  case '赤':
    console.log('止まれ');
    break;
  case '青':
    console.log('注意');
  case '青':
    console.log('渡れ');
    break;
}
//コンソールには「注意」と「渡れ」が表示される
```
FizzBuzzの問題で3の時はFizzと表示し、5の時Buzzと表示、15の時FizzBuzzと表示する

#RubyのFizzBuzz練習問題を解く（今回はeach doを使用）

・1から30まで数える
・3の時はFizzと表示する
・5の時はBuzzと表示する
・15の時はFizzBuzzと表示する


まず、擬似コードを考える前に、情報を整理
どのようなコードが必要そうかを並べてみる。

①1から30まで数える
②もし3だったらFizzと表示する
③もし5だったらBuzzと表示する
④もし15だったらFizzBuzzと表示する

以上。

では、擬似コードっぽいやつ書いていく。

```
1から30まで数える（今回は、each do を使って）

if　○○なら
　puts ○○と表示する

elsif
   ○○なら
 puts ○○と表示する

elsif
   ○○なら 
 puts ○○と表示する
else
  それ以外なら
 puts ○○と表示する

```

ここにコードをあてていくと、考えがまとまりやすくなり、コードがすっきりしそう。
もし、仮説と違ったら擬似コードの考え方を実際の答えと比べてみる。

```
(1..30).each do|i|

    if i%15==0
        puts "FizzBuzz"
    elsif
        i%3==0
        puts "Fizz"
    elsif
        i%5==0
        puts "Buzz"
    else
        puts i
    end
end
```

```
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
```

このように表示されていればOKです。

#応用編：数字の横にFizzとBuzzをそれぞれつけてみる。

考え方はほとんど一緒
表示の仕方だけ変えればいいかな？っと仮説を立ててみる。
合ってたら自分を褒める。

```
(1..30).each do|i|

    if i%15==0
        puts "#{i} FizzBuzz"
    elsif
        i%3==0
        puts "#{i} Fizz"
    elsif
        i%5==0
        puts "#{i} Buzz"
    else
        puts i
    end
end
```

見やすくするため、一応数字と文字の間にスペースいれてます。

うまくいくと、以下のようになります。

```
1
2
3 Fizz
4
5 Buzz
6 Fizz
7
8
9 Fizz
10 Buzz
11
12 Fizz
13
14
15 FizzBuzz
16
17
18 Fizz
19
20 Buzz
21 Fizz
22
23
24 Fizz
25 Buzz
26
27 Fizz
28
29
30 FizzBuzz
```

以上となります。
ご参考いただけますと幸いです。
FlutterはデフォルトでReleaseビルドにInternetパーミッションを付けない

はい、タイトルのとおりです。

昔は違ったのですが、今のFlutterで`flutter create`して作られるプロジェクトでは、`android/app/src/main/AndroidManifest.xml`の中に`<uses-permission android:name="android.permission.INTERNET"/>`の指定がありません。そのため、リリースビルドしたアプリではインターネットに接続できず、`Image.network`は何も読み込まないし`HttpClient`などを使ったインターネット接続は全て失敗します。
`android/app/src/debug/AndroidManifest.xml`の中には`<uses-permission android:name="android.permission.INTERNET"/>`が記述されているため、デバッグビルドであればインターネット接続ができます。

私はこのことに気付くまで1日かかりました……
リリースビルドしたときだけアプリが動かない！！

とお悩みの方は、一度これをチェックしてみてはいかがでしょうか。
Vim言語（動詞，名詞，修飾子）を覚える．

[Learn to speak vim — verbs, nouns, and modifiers!](https://yanpritzker.com/learn-to-speak-vim-verbs-nouns-and-modifiers-d7bfed1f6b2d)の記事を参考にVim言語を覚える．
[Mastering the Vim Language](https://www.youtube.com/watch?v=wlR5gYd6um0&t=1317s)の動画も参考．
**動詞** + **修飾子** + **名詞**　の順で命令を作る．

# 動詞
|コマンド    |単語     |意味                 |
|:-------:|:-------:|:------------------:|
|v        |Visual   |Visualモードに切り替える．|
|c        |Change   |変更する．             |
|d        |Delete   |削除する．             |
|y        |Yank/Copy|コピーする．            |

# 名詞
|コマンド    |単語     |意味                  |
|:-------:|:-------:|:-------------------:|
|w        |Word     |1単語（ドットやハイフンで区切られる）|
|W        |Word     |1単語（ドットやハイフンで区切らない）|
|s        |Sentence |1文章（ピリオドまで）       |
|p        |Paragraph|1段落（空白行まで）       |
|b        |Block    |1ブロック（小括弧の中）     |
|t        |tag      |1タグ（html/xmlのタグの中）|

# 修飾子
|コマンド    |単語             |意味                            |
|:-------:|:--------------:|:------------------------------:|
|i        |Inside/Inner    |カーソルが含まれる                   |
|a        |A               |一つの　                          |
|t        |Till            |次の検索文字まで（その文字を含まない）    |
|f        |Find            |次の検索文字まで（その文字を含む）       |
|/        |Search          |次の検索単語まで（その単語を含まない）    |

# 例
`diw`: (Delete Inside Word) そのカーソルが含まれる単語を削除する．aaa-bbbを削除する場合，aaaまたは-またはbbbのみが削除される．
`diW`: (Delete Inside Word) そのカーソルが含まれる単語を削除する．aaa-bbbを削除する場合，aaa-bbbを一単語として削除する．
`cis`: (Change Inside Sentence) そのカーソルが含まれる文章を変更する（削除してInsertモードにする）．
`ci"`: (Change Inside ") そのカーソルが含まれるダブルクオーテーション内を変更する（削除してInsertモードにする）．
`c/foo`: (Change Search foo) 次に見つかるfooの単語直前まですべてを変更する（削除してInsertモードにする）．
`ctX`: (Change Till X) 次に見つかるXの文字直前まですべてを変更する（削除してInsertモードにする）．
`vap`: (Visual A Paragraph) そのカーソルが含まれる1つの段落をVisualモードで選択する．

# その他
`.`: 一つ前の命令を繰り返す．
`u`: 一つ前の変更を元に戻す．
JavaScript勉強の記録その１: If文

#Javascriptでif文
一番シンプルな形としてはif(条件式){Trueだった時の処理}と書くことができる。

```index.js
const score = 90;

if (score >= 80) {
  console.log('Great!');
} 
```

if(条件式){Trueだった時の処理}else{Trueじゃなかった時の処理}という書き方もできる。

```index.js
const score = 60;

if (score >= 80) {
  console.log('Great!');
} else {
  console.log('OK...');
}
```
条件式の中に&&や||を入れることで、ANDやORを表現することができる。

```index.js
const score = 60;
const name = 'okuno'

if (score >= 50 && name === 'okuno') {
  console.log('Good Job!');
}
```
Arch Linux のインストールメモ

#### Arch Linux を再インストールしたので、そのメモ(2020年1月4日)
2018年の夏から使用を継続しているArch Linux が、12月ころから、更新ができなくなっていた。検索すると、サポートが終了したパッケージが何やら邪魔をしていて、更新エラーが起こっているらしい。これかと打ち込んだ削除コマンドが致命的で、Xが起動しなくなったので、データファイルのバックアップを取った後に、ゼロから再インストールした。

#### どのやり方を使うか --> archfi

以前のメモを読み返してみたが、同じ方法を繰り返すのは、まあ楽しくない。ということで最近は、YouTube にも、その類のチュートリアルはたくさんあるので、探していたら、インストール用のスクリプトを紹介している動画があったので、参考にさせていただいた。

https://www.youtube.com/watch?v=GUtpHFI-vjg

この動画で紹介されている方法を試してみたら、うまくインストールできた。　下記の通り
wget で archfi スクリプトをダウンロードし、
その archfi スクリプトを実行する。

```
# wget archfi.sf.net/archfi
# sh archfi
```

スクリプトを実行する環境として、

* 同じPCの違うハードディスクにインストールされているLinux のコマンドラインからarchfiスクリプトを実行して、他のハードディスクあるいは、パーテーションに Arch Linux をインストールする。

* USBスティックのようなインストールメディアから、linux を起動し、そのコマンドコンソールで、archfi をダウンロードし、実行する。

いずれの方法も、ネットワーク環境は必須で、archfiスクリプトを実行すると、必要なファイルをネットからダウンロードしてインストールする。スクリプトは対話式なので、メニューの上から順番に実行すれば良い。Linuxのインストール経験者であれば、なんとかなるでしょう。初心者でも、何回か試してみれば、インストールできます。

3. 日本語の扱いは後回しにして、まずは、英語環境で、Xを起動できるように構築する。なぜかというと日本語フォントがデフォルトでインストールされないので、日本語で立ち上げようとしても、文字化けする。
4. /boot, /home, / として、3つの独立した、パーテーションを前提としている。何に使うかにもよるが、日常のデスクトップ用途であれば、それぞれ　200MB、20GB、25GB程度で良いかと思う。
5. ログイン時のディスプレイマネージャーは、lightdm が最近の流行のようですが、私の場合は、ロケール切り替えができる、lxdm が好み。英語表示環境、日本語表示環境がログイン時に選択できる。
6. 日本語ロケールの生成は、/etc/locale.gen を編集し、ja_JP.UTF-8 UTF-8　の前についている # を削除したのち、コンソールから、#locale-gen とコマンドを打てばOK
6. cinnamon, en_US で Xまで起動できるようにする。日本語環境は、X起動の後で可。cinnamon 以外でもOK、デスクトップ環境も複数インストールして切替可能。
7. 日本語表示のため、noto-fonts-cjk をインストールする。 yay -S noto-fonts-cjk とか。
8. 日本語IMは、fcitx-im, fcitx-configtool, fcitx-mozc の定番をインストールする。
9. ディスプレイマネージャーでログインするので、 ~/.xprofile に以下を記述する。

```
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS="@im=fcitx"
```

Fcitx設定のキーボード設定で、Mozc を追加すると、日本語入力ができるようになる。
後は、好みのアプリケーションをインストールしていけばよろしい。Xが立ち上がっているので、コマンドライン以外、GUIでもインストール可能である。

* NAS接続(Windows共有ディレクトリ)： gvfs-smb
* 音楽再生：audacious
* 壁紙アプリ：variety 

などなど

####更新情報、2020年10月10日
1. archfi スクリプトは、arch linux から起動できる。Linux mint のターミナルから実行しようとしたが動きませんでした。
2. archfi は、以下の方法で取得

```
wget matmoul.github.io/archfi
```

* target にするパーテーションは、前回は3つの独立したパーテーションであったが、今回は、試しに一箇所にしたところ、無事にインストールできた。
* firefox は、デフォルトのweb browser としてインストールしたが、yay をインストールしたあとに、brave browser をインストールして、brave を常用している。
* yay , octopi は、インストールしておくと、のちのち、楽ちんである。
* cinnamon デスクトップは、綺麗にできていると思う。

####更新情報、2020年10月11日
* Arch linux インストーラーとして、zen_installer-2020.05.27-x86_64.iso というイメージが使用可能である。
* 最初に必要な情報を入力して、一挙にインストールするツールであるが、locale を最初に日本語設定にすると、日本語フォントがインストールされないため、X では文字化けしてしまう。ターミナルから日本語フォントをインストールする必要あり。これでなんとか落ち着ける。

```
# pacman -S ipafont
```
fishでの変数扱い方

# はじめに

去年から、fishに切り替えたのですが、変数の扱いがなかなか慣れないので、まとめておきます。

## 変数の定義・使い方

```bash
# 変数の定義
$ set key value
# 変数は$を先頭につける
$ echo $key
# 変数展開その1 変数を{}で括る
$ echo {$key}test
# 変数展開その2 変数以外を""で括る
$ echo $key"test"
# グローバル変数として定義(すべてのfishセッションで共有)
$ set -U global_key globa_val
# eオプション( --erase or -e)で削除
$ set -e global_key
```

## 参考
[fish公式ページ](https://fishshell.com/)
2つのSESAME miniをスマートスピーカーからIFTTT経由で同時に操作する（API不要）

# はじめに
[SESAME mini](https://jp.candyhouse.co/)というスマートロックがあります。
とても便利なのですが上下に鍵があるような扉の場合には
上下で2つ付ける必要があります。
そして解錠も施錠も同時にする必要があるのですが
公式にはアプリのUnlock Allしかない上に
それもイマイチ使い勝手が悪く単体でも反応が遅い上に
ウィジェットやメニューから同時解錠もできないので
2台持ちにはとても使いづらいのが現状です。

ということでIFTTTを利用して2台のSESAME miniを
同時解錠するTIPSです。
といっても単にIFTTTの機能を使うだけです。

# 準備するもの
- IFTTTのアカウント
- SESAME mini
- （必要あれば）IFTTTアプリ

# 手順１　SESAME miniとIFTTTを連携する

CANDYHOUSE公式のブログの準備編を参考にSESAME miniと
IFTTTを連携しましょう。
![o1556131214137229146[1].jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257268/b61b36e0-042f-09c1-357e-9df5735051cc.jpeg)
引用：[IFTTT（イフト）とSESAME（セサミ）スマートロックを連携させてセサミを楽しもう！](https://ameblo.jp/candyhouse-inc/entry-12353322034.html)

# 手順２　IFTTTアプレットの作成準備

IFTTTでさせる一連の操作の設定をアプレットといいます。
ここではそのアプレットを作成します。

Web版ではトップページからEXPLORERを
アプリではGET MOREをクリックしてください。
次のページの「Make your own Applets from scratch」の横の
プラスボタンを押すと

>If
>This
>Then
>That

というページに入ると思います。
ここで「This」と「That」を設定してSESAME miniを
望む条件で操作できるように設定していきます。

# 手順３　開始フレーズの設定

「This」を押すと「Choose a service」というページになります。
ここでそれぞれのスマートスピーカーに合わせて設定をします。

## 手順３－１　Google Assistant（Google Home等）の場合

検索ボックスに「Google」と入力して「Google Assistant」を選択し
「Say a simple phrase」を選んでください。
「What do you want to say?」で操作するときに使う言葉を入れます。
ここでは解錠させるために「開けゴマ」にしましょう。
**（この言葉はセキュリティとして問題があるので
　各自で適切なワードを設定してください）**

「What's another way to say it? (optional)」
「And another way? (optional)」
この２つはさらに他の２つのワードを指定できます。
ここでは必要ないので空欄のままにしておきます。
「What do you want the Assistant to say in response?」
ではスマートスピーカーからの返事を入力します。
これも空欄のままにしますが、適当なものを入力しても構いません。

「Language」は「Japanese」にしておきましょう。

設定が終わったら「Create Trigger」を押せば
「This」の設定は終了です。

## 手順３－２　Amazon Alexa（Amazon Echo等）の場合

検索ボックスに「alexa」と入力して「Amazon Alexa」を選択し
「Say a specific phrase」を選んでください。
「What Phrase?」で操作するときに使う言葉を入れます。
ここでは解錠させるために「開けゴマ」にしましょう。
**（この言葉はセキュリティとして問題があるので
　各自で適切なワードを設定してください）**

設定が終わったら「Create Trigger」を押せば
「This」の設定は終了です。

# 手順４　SESAME miniの操作の設定

次に「That」を押して「Choose action service」から
「SESAME」と入力して「Sesame by CANDYHOUSE」を選択します。
「Open Sesame」と「Close Sesame」があるので
必要な操作を選択しましょう。

今回は解錠をしたいので「Open Sesame」を選択します。
手順１で連携が適切にできていれば
「Which Sesame?」に持っているSESAME miniが表示されるので
まず解錠したい鍵を１つ選択します。

そして「Create Action」を押せば「That」の設定も終了です。

最後にアプレットの名前をつけます。
デフォルトのままでも構いません。

# 手順５　もう１つの鍵のアプレットも作成する

手順３～４を参照してもう一つの鍵のアプレットも作成します。
ここで重要なのは**開始フレーズを同じものにする**ことです。
これによって１つのフレーズで２つを同時解錠できます。

# 手順６　解錠の確認

ここまでで２つの鍵の同時解錠が出来るようになります。

- Google Assistantであれば**「Ok Google, 開けゴマ」**
- Amazon Alexaであれば**「Alexa, 開けゴマをトリガー」**
- 
で２つの鍵が開きます。
施錠のトリガーも同様にして作れば完璧ですね。

ということでこの記事は終了です。
。
。
。
。
。
。
「～をトリガー」って邪魔だしダサいですよね。

# 手順７　（Alexaのみ）定形アクションの作成

Alexaアプリのメニューから「定形アクション」を選択し
右上の＋ボタンから作成画面に入ります。
実行条件を設定で開始フレーズを「開けゴマ」とし、
アクションを追加でIFTTTから手順３～４で作成した
「開けゴマ」アプレットを選択します。

これでGoogle AssistantのようにAmazon Alexaでも

- **「Alexa, 開けゴマ」**

で解錠が出来るようになります。

# おわりに

記事の通りの設定だと誰の声でもテレビの声でも
「Ok Google/Alexa, 開けゴマ」と言われるたびに
玄関の鍵が開いてしまいます。
スマホのアシスタントで設定をしていたなら
外出先でも自宅の鍵が開きかねません。

運用には十分に注意して使用してください。
【簡単】PythonでWikipediaをWebスクレイピングしてみよう【初心者向け】

こんにちは。

せら⇒だいひょー🐯です。

僕のTwitterアカウント
(https://twitter.com/seradaihyo)
では、

未経験からエンジニアを目指す方に向けて日々発信しています。

今回はPythonでWikipediaのスクレイピングを行う方法を記事にしたいと思います。

それでは始めていきましょう。




**Pythonでスクレイピングをする上で必ず使うサードパーティ製ライブラリが二つあります。**

それが

**・Requests**
**・BeautifulSoup**


です。


それぞれ簡単に説明すると、

**Requests
⇒URLを開くためのライブラリ**

**BeautifulSoup
⇒HTMLからデータを抽出する**

といった感じです。

Requestsでページを開いて、BeautifulSoupでデータを取ってくるイメージです。

Pythonコードの先頭に、この二つのライブラリをインポートするためのコードを書いておきます。

```python:wikipedia.py
import requests,bs4
```




#■WikipediaのPython記事をスクレイピング


今回は、wikipediaのPython記事をスクレイピングして目次を表示するアプリを作ります。

アプリと言っても記述するコードはたったの7行なので、安心してください。


まず、wikipediaでPythonの記事を検索します。

![イメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561248/a2b50199-fa91-31cc-4012-43b55495605c.jpeg)


このURLをコピーして、以下のようにURLの変数に入れます。

```python:wikipedia.py
url = 'https://ja.wikipedia.org/wiki/Python'
```

そしてそのURLのページを開く次の呪文を唱えます。

```python:wikipedia.py
res = requests.get(url)
```

resは変数なので名前は自由です。
勿論1と2は次のように一行で書くことも可能です。

```python:wikipedia.py
res = requests.get('https://ja.wikipedia.org/wiki/Python')
```

次にこのURLからHTMLを取ってくる次の呪文を唱えます。

```python:wikipedia.py
soup = bs4.BeautifulSoup(res.text, "html.parser")
```

因みにhtml.parserとは、htmlのタグ情報から情報を解釈するプログラムです。

初めのうちは、htmlを扱いやすくしてくれるという解釈でOKです。


次に、wikipediaの目次の部分にカーソルを持ってきます。

![イメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561248/a499260b-51f8-55bd-fb69-ab6ef9f2e53a.png)


そこで右クリックをし、「検証」をクリックします。

すると、次のようなhtmlのコードが出てきます。

![イメージ 2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561248/24dda508-f957-68af-69c2-c7fbb6e6ad9d.jpeg)


目次を囲っているdivタグのidを確認すると、tocとなっていますね。

![イメージ 3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561248/cfd01056-5b55-cd4a-140a-a187baf997b1.jpeg)


なので、このdivタグ”toc”内の全ての要素を次のように引っ張ってきます。

```python:wikipedia.py
 index = soup.select('#toc')
```

（この場合idなので「#」が付いていますが、classの場合は「.」を付けてください）

これでindexというリストに目次の要素が入れられました。
※なぜリストなの？

後は、for文を使ってindexの中身を表示させます。

```python:wikipedia.py
for i in index:
    print(i.getText())
```

.getText()を付けることで、HTMLのタグを取り除くことができます。


##これまで書いたコード
```python:wikipedia.py
import requests,bs4
 
url = 'https://ja.wikipedia.org/wiki/Python'
 
res = requests.get(url)
soup = bs4.BeautifulSoup(res.text, "html.parser")
 
index = soup.select('#toc')
 
for i in index:
    print(i.getText())
```

 


これを実行すると、

![イメージ 4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561248/e24f1dff-ebbf-0abb-1a44-b599e83e4562.jpeg)



このように、目次を表示する事ができます。


※リストになって返される理由は、select()メソッドがすべての要素を返すメソッドだからです。
一つだけ要素を返したい場合はselect_one()メソッドを使います。


というわけで、今回はPythonでスクレイピングを行う方法を簡単に説明させていただきました。

最後まで読んでいただきありがとうございました！
Markdownの書き方

#きっかけ
転職活動用に職務経歴書が必要となり、
「Markdownで記述し、Githubで管理」
という方法を知り、やってみました。

#Markdownとは
Markdownとはデジタル文書の書き方の一種で、簡単に記述、文書スタイルの変更ができます。WordだとGUI操作が必要な書き方もMarkdownだとキーボード操作のみで可能です。

#書き方
##見出しの書き方

`#`の数を増やすほど小さくなります。HTMLでいうH1 ~ H6のようなイメージでですかね。

~~~
#大見出し
##見出し
###見出し
####見出し
#####見出し
######小見出し
~~~
結果
#大見出し
######小見出し

---

##強調
文章の中で強調したい部分を`**`で囲むと太字になります。
ちなみにVSCodeだと`Command`+ `b`で指定位置から最初にある句読点までをショートカットできます。（私だけでしょうか？）

~~~
私は**Markdown**を勉強しました。
~~~
結果
私は**Markdown**を勉強しました。


##リスト
###箇条書き
文頭に`-`,`+`,`*`のいずれかをつけるとリスト形式になります。また、Tabでさらに階層化することができます。

~~~
- Aerosmith
+ Guns'n'Roses
    * KISS
~~~

結果

- Aerosmith
+ Guns'n'Roses
    * KISS

###数字つき
文頭に`1.`をつけると数字付きリストになります。

~~~
1.The Beatles
1.Led Zeppelin
1.The Rolling Stones
~~~
結果（順番に意図はありません。）

1. The Beatles
1. Led Zeppelin
1. The Rolling Stones

## コード表示
バッククォートや`~~~`で囲むとコードを表示できます。


---

結果

```
コードを表示
```

##リンク
~~~
[リンク名](URL)
[Qiitaマイページ](https://qiita.com/junun)
~~~

結果
[Qiitaマイページ](https://qiita.com/junun)

##区切り線
`-`, `*`, `_`のいずれかを３つ入力すると区切り線を引けます

~~~
***
~~~

結果
***

##疑問点
- VSCcodeのプレビューとGithubで出力結果が異なる

#終わりに
Markdownの書き方については既に多くの記事が出ています。参考にさせていただきながら、アウトプットを習慣づけるために記事を書きました。

職務経歴書はPDF化した状態でGithubにアップした方が良いという記事もありました。
私はVSCodeで.md形式のファイルで編集し、拡張機能**Markdown PDF**でファイルをPDF化してます。
これからGithub.ioなるものを使ってみようと思います。

##参考

[Markdown 書き方の基本をまとめてみた](https://qiita.com/Hase-pro/items/16379a0c83f2725e3a11)

[Markdown記法一覧](https://qiita.com/oreo/items/82183bfbaac69971917f)

[職務経歴書をGitHubで管理しよう](https://qiita.com/okohs/items/abcad0b4aefa585bc50b)

[エンジニアが読みたくなる職務経歴書](https://dwango.github.io/articles/engineers-resume/)
Python3.7でPILがModuleNotFoundErrorになるエラーの解決方法

<h2>実行環境</h2>

```
$ python

Python 3.7.5 (default, Oct 25 2019, 10:52:18) 
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
```

<h2>エラー内容</h2>

Python3.7で `$ pip install pillow` でpillowをインストールしてPILを利用しようとしても、

`from PIL import Image` の箇所でModuleNotFoundErrorエラーになってしまう。

```
$ python test.py

Traceback (most recent call last):
  File "test.py", line 1, in <module>
    from PIL import Image
ModuleNotFoundError: No module named 'PIL'
```

<h2>解決した方法</h2>

Anacondaがインストールされている状態で、 `$ conda install -c anaconda pillow` コマンドでpillowをインストールした。

```
$ conda install -c anaconda pillow

Collecting package metadata (current_repodata.json): done
Solving environment: done
...
Executing transaction: done
```



<h2>参考になった記事</h2>

勉強になりました🙏

https://teratail.com/questions/130649
http://onoz000.hatenablog.com/entry/2018/02/11/142347
Ruby環境構築とRailsについて　エンジニア戦記#3



Ruby開発環境構築

* 「Homebrew」をインストールする
* 「Homebrew」を用いて「rbenv」をインストールする
* 「rbenv」を用いてRubyをインストールする


Ruby　MVCとRouting

Model　データを扱う
View　　表示を扱う
Controller 指令塔
Routing　コントローラーの機能

★ツイでのお勉強★

ファイル名変更

変更したいファイルを選択
→enter

tab+Command　アプリ切り替え
デスクトップ戻る　F11

アプリを終了させるショートカット
tab+Command　ｑ
nox_adb shellでchgrpする

##背景
NoxPlayerのIceCreamSandwich環境でUWSCマクロを書こうとしたとき、nox_adb shell環境では最初からls,grep,cp,chmod等のUNIX系コマンドは通る。
そのため、NoxのAndroid環境ではBusyBoxのコマンド群が予め/system/bin/shに含まれていたのではないかと勘違いしていた。

しかしながら、ファイル・ディレクトリのグループ情報を変更するときにchgrpしようとすると

```
nox_adb shell
#chgrp gip filename
#/system/bin/sh: chgrp: not found
```

と出てしまい、グループ情報が変更できないことがわかった。そのためchgrpを使う方法を2つ考えた。


##解決方法1:BusyBoxを入れる
Nox側でroot取って、[ここ][5]からアプリをインストール、アプリを開いてBusyBoxをインストール。
画面の指示通りにインストールしたなら、nox_adb側で

```
nox_adb shell
#cd /system/xbin
#alias busybox="`pwd`/busybox"
```
と打ち込めば、chgrpを含め,vi,tar等も通るようになる。

なお、adb shellに関して[公式のドキュメント][3]を見てもls以外の記述はなく、何のコマンドが最初から使えるかわからないが[ここ][1]を見る限り、Androidのバージョンによっては、adb shell環境ではgrep,cp,chmodが最初から使えないのもありそう。
ただし、手持ちのOreo機種ではchgrpコマンドも含め、いずれのコマンドも通ったので、Androidバージョンによって通ったり通らなかったりするコマンドがあるみたい。


##解決方法2
chownなら問題なく通るため、以下のようにグループ情報を変更する事ができる。

```sh
chown uid.gid filename
```
chgrpするだけならこっちのほうが簡単。

##教訓
adb shellするならBusyBoxを最初から入れたほうがいい。

##参考
[Androidのターミナルを強化する『BusyBox Non-Root』][1]
[How to change the group id of a file on rooted android device?][2]
[Android Debug Bridge（adb）][3]

[1]:http://atmarksharp.v01.jp/posts/android-busybox-non-root.html
[2]:https://stackoverflow.com/questions/11440770/how-to-change-the-group-id-of-a-file-on-rooted-android-device
[3]:https://developer.android.com/studio/command-line/adb?hl=ja
[5]:https://play.google.com/store/apps/details?id=stericson.busybox&hl=ja
HTML&CSS学習

本日が初投稿です。
学習したことをメモ書き程度に書く場にしようと考えております。
多めに見てやってくださいm(__)m


<h1>HTMLとは

静的なwebサイト作成に使用される「マークアップ言語」の一つです。タグを使いテキストを囲むことで、「見出し」や「リンク」を作成することができます。
<h4>タグの例

<開始タグ>こんにちは</終了タグ>

このように入力すると画面上に「こんにちは」と表示される。
終了タグの前には必ず「/」を入力する。

<h4>主なタグ

h1~h6→見出し
a→リンク
p→段落

<h1>CSSとは
<p>HTMLで作成したファイルをデザインするためのファイルのこと。画面上で反映させるために、「link ren="stylesheet" href="cssファイル名"」をHTMLファイルのheadタグ内に記述している必要がある。

<h4>書き方

例；
h1{
(場所)
 color : #ff0000 
 何を：どうする；
 (色を:赤色にする)
｝
知らないとはまってしまうJavaScriptの配列コピー

# 概要
JavaScriptで配列コピーをする際、
「＝（イコール）」によるコピーでは意図した動作にならない場合があります。
意外にはまりやすい落とし穴だと思ったので、
初心者にもわかりやすいよう、図も載せておきました。

# 配列コピーによる動き
まずは、動きを確認しましょう。

変数aの配列を宣言し、変数bにコピーします。

```javascript:test.js
var a = ['あ','い','う','え','お'];
var b = a;
```
その後、変数b[0]の内容を書き換えます。

```javascript:test.js
b[0] = 'か';
```

この時、書き換えたいのは変数bの値ですが実際は

```javascript:test.js
  console.log('変数a: ' + a); // ['か','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']
```

と、変数aの値も書き換わってしまいます。
書き換えたのは変数bだったのに、なぜ変数aも一緒に書き換わってしまったのでしょうか。

## コピー元の値が書き換わる理由

では、なぜ変数bの値を書き換えたにも関わらず、変数aの値も書き換わってしまったのか
図を交えて説明していきます。

まず、この**変数a**に格納されている値は、配列の情報ではなく、
配列aのインスタンスを参照する**アドレス**が格納されています。

その為、変数bに変数aをコピーした際、
配列ではなくアドレスの情報が渡されているのです。

実際に図にすると、以下の状態です。
![配列コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239956/75c3e547-2998-d894-e191-0eb9e0ecda26.jpeg)

次に、変数b[0]に「か」という文字を代入しましたが、
この時、変数b[0]は変数bの値を書き換えるのではなく、
配列の値を保持したメモリを直接書き換えることになります。

![配列値変更.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239956/d6e2136e-887a-f89c-9aef-889d11a33670.jpeg)

つまり、このb=aという式では、配列は複製されず
同じアドレス先を共有しているだけなのです。

この動作を理解していないと、
まるで両方の変数で値が書き換わったように感じてしまうのです。

# 配列を複製する方法

では、実際に配列を複製するためにはどうすればいいか、いくつか例を挙げておきます。
※上記の説明でコピーという表現が適切ではないと分かったので、ここからは「複製」という表現に変えます

## for文による複製
for文を使って、配列要素文のループにより値を代入します。
この時、変数bは空の配列で宣言します。

```javascript:test.js
  var a = ['あ','い','う','え','お'];
  var b =[];

  for( var i =0; i < a.length; i++){
    b[i] = a[i];
  }

  b[0] = 'か';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']
```
## Array.concat()による複製
Arrayオブジェクトのconcatメソッドは指定された配列を連結して値を返すメソッドですが
引数を指定しない場合は、元の配列の複製を返します。

```javascript:test.js
  var a = ['あ','い','う','え','お'];
  var b = a.concat();

  b[0] = 'か';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']
```

## Array.slice()による複製
Arrayオブジェクトのsliceオブジェクトは配列の一部を取り出して値を返すメソッドですが、
開始を指定し、終了を省略すると元の配列の複製を返します。

```javascript:test.js
  var a = ['あ','い','う','え','お'];
  var b = a.slice(0);

  b[0] = 'か';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']
```
## ...演算子による複製
ES6(ES2015)で追加されたスプレッド構文を使用すると、配列をそのまま複製してくれます。

ただし、ES6をサポートしたブラウザのみ対応です。
 ※ 2020年1月時点では、IE11は非サポートです。

```javascript:test.js
  var a = ['あ','い','う','え','お'];
  var b = [...a]

  b[0] = 'か';
  console.log('変数a: ' + a); // ['あ','い','う','え','お']
  console.log('変数b: ' + b); // ['か','い','う','え','お']
```

# まとめ

「＝（イコール）」を使って変数の値をコピー(代入）する際には
その変数がなんの値を保持しているのか注意しましょう。
Nuxt.jsで簡単のサイトを作ってみた

##Nuxt.jsで簡単のサイトを作ってみた。

Vue.jsとNuxt.jsを学習しているので、簡単なサイトを作って見ました。

```terminal
npx create-nuxt-app <title>
```
上記のコマンドでプロジェクトを作成します。

pagesディレクトリには、各ページのvueファイルを作成します。
![pages.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/742b21fb-8bc8-1157-5ab6-5d3687932385.jpeg)
今回は上記のように作成しました。
Nuxt.jsでは、Vue Routerのルーティングを自動で設定してくれます。pagesディレクトリにvueファイルを作るだけで、各ページを作ることが可能です。

componentsディレクトリには各ページで共通化したい部分を作成します。
![components.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/4aba9683-a472-fc5d-b294-66d2d7e7beb8.jpeg)
今回はヘッダーとフッターを共通化したいので作成しました。

```vuejs:header.vue
<template>
  <header class="header">
    <div class="container">
      <h1>DEAL CAFE</h1>
      <nav>
        <ul class="gnav">
          <li><router-link to="/" active-class="active-list" exact>HOME</router-link></li>
          <li><router-link to="/drink" active-class="active-list" exact>DRINK</router-link></li>
          <li><router-link to="/info" active-class="active-list" exact>INFO</router-link></li>
          <li><router-link to="/contact" active-class="active-list" exact>CONTACT</router-link></li>
        </ul>
      </nav>
    </div>
  </header>
</template>

<style lang="sass" scoped>
    .header
          padding: 20px 0
          box-shadow: 0 0 1px 1px #333
          margin-bottom: 10px
          .container 
                    display: flex
                    justify-content: space-between
                    align-items: baseline
                    .gnav
                        display: flex
                        li
                          margin-left: 10px
                          a
                           &:hover
                                  border-bottom: 2px solid
    .active-list
               border-bottom: 2px solid
</style>
```

```vuejs:footer.vue
<template>
  <div class="footer">
    <div class="container">
      <p><small>DEAL CAFE</small></p>
    </div>
  </div>
</template>

<style lang="sass" scoped>
.footer
      color: #fff
      text-align: center
      background: #333
      padding: 30px
      margin-top: 300px
</style>

```

共通化したcomponentはdefault.vueファイルで読み込みした。

```vuejs:default.vue
<template>
  <div>
    <header-section />
    <nuxt />
    <footer-section />
  </div>
</template>

<script>
import header from '~/components/header.vue'
import footer from '~/components/footer.vue'
export default {
  components: {
    headerSection: header,
    footerSection: footer
  }
}
</script>
```
scriptのcomponentsはキャメルケースで書いて、templateの中はケバブケースでもokです。

最後にビルドして終了です。

```terminal
$ npm run build
```
![demoサイト.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/345f1ef2-1af9-d3b5-6b9d-bc7fdb631f70.jpeg)
簡単ではありますが、SPAサイトの完成です。
今後はもっと複雑なものも作成していきたいです。一応GitHub Pagesにデプロイしているので、良かったご覧ください。
https://to-ko5.github.io/vueDemoHp/

※GitHub Pagesにデプロイする時は、nuxt.config.jsファイルにrouter baseを追記する必要があります。

```javascript:nuxt.config.js
export default {
  router: {
    base: '/<repository-name>/'
  }
}
```