OmniAICreator/Qiita-1.07M huggingface dataset:
Embulkを活用して、MySQLのデータをBigQueryにロードする

# この記事について

Embulkを活用して、MySQLのデータをBigQueryにロードする方法についてまとめた記事です

なぜBigQueryにデータをロードするのかといった部分についても触れています

# Embulkとは？

様々な環境間に対応しているデーターローダーです

>Embulk is a parallel bulk data loader that helps data transfer between various storages, databases, NoSQL and cloud services.

[Embulkのリポジトリ](https://github.com/embulk/embulk)より引用

# embulkのインストール

最新版のv0.9.21ではJava8が必要です

```
curl --create-dirs -o ~/.embulk/bin/embulk -L "https://dl.embulk.org/embulk-latest.jar"
chmod +x ~/.embulk/bin/embulk
echo 'export PATH="$HOME/.embulk/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```

## pluginのインストール

今回使うinputとoutputのpluginもインストールします

```
embulk gem install embulk-input-mysql
embulk gem install embulk-output-bigquery
```

Embulkは前述の通り、様々なインプット/アウトプットに対応しています

実行したいインプット/アウトプットに対応したpluginをインストールしましょう！

他のpluginに関しては公式からご確認ください

https://plugins.embulk.org/

# 設定ファイル

Embulkは設定ファイルをymlで記述します

また変数にも対応しており、その場合はliquidで記述し、ファイル名もconfig.yml.liquidとなります

設定例

```
in:
  type: mysql
  host: {{ env.DB_HOST }}
  user: {{ env.DB_USER }}
  password: {{env.DB_PASS}}
  database: {{env.DB_DATABASE}}
  table: posts
  select: "id,title,body,created_at,updated_at"

out:
  type: bigquery
  location: {{env.BIG_QUERY_LOCATION}}
  mode: replace
  table: posts
  auth_method: json_key
  json_keyfile:  {{env.GOOGLE_APPLICATION_CREDENTIALS}}
  project: {{env.BIG_QUERY_PROJECT}}
  dataset: {{env.BIG_QUERY_DATASET}}
  compression: GZIP
  auto_create_table: true
  allow_quoted_newlines: true
```

## 設定項目の説明
### in:select
どのデータを抽出し、ロードするか選択します

移行する必要のないデータはこのタイミングで除外しておきます

### out:mode
5つのモードがあり、主要なのは `append` と `replace` の2つです

`append` はデータを追記していくモード、

`replace` はデータを書き換えしていくモード となります

### out:auto_create_table

BigQuery側にテーブルが存在しない場合、自動で作成するモードです

スキーマの設定は3種類あります

- schema.json
- テンプレートテーブル
- Embulkからの推測

詳細は[こちら](https://github.com/medjed/embulk-output-bigquery)

### 細かい設定について

その他の設定項目は下記からご確認ください

[embulk-input-mysql](https://github.com/embulk/embulk-input-jdbc/tree/master/embulk-input-mysql)

[embulk-output-bigquery](https://github.com/medjed/embulk-output-bigquery)

## 実行
```
embulk run {$設定ファイルパス}
```

これだけでローディングが完了します！

# なぜやるのか？

## BigQueryに集約することで権限管理の手間を減らす

DBに直接アクセスするような場合は分析用のアカウントをつくるケースが多いかと思いますが、

その場合は共通アカウントになってしまい、実際に誰が使えるのか不透明になってしまい、権限管理に手間が増えます

BigQueryはGCPのIAMで管理できるため、ユーザー単位の細かい権限管理も手間なく行えます

## データポータル, スプレッドシートとの連携で可視化を簡単に

BigQueryはデータポータルとの連携もサポートしており、可視化、ダッシュボードの作成も容易です

データポータルからBigQueryへのアクセスも上記と同じ用にIAMで管理できるため手間がかかりません

G Suite の Business、Enterprise、Education プランであればスプレッドシートとの連携も容易で、利用の幅が広がります

## FirebaseAnalyticsや他のデータとの連携した分析を可能にする

アプリのイベントデータをFirebaseAnalyticsで計測、収集している場合はサービス側のDBと照らし合わせて分析したいケースも多いかと思います

BigQuery上にデータを集めることで、JOINも可能になるので分析がはかどります

※ JOINを可能にするにはデータを同じロケーションに設定する必要があります
COUNTIF文、SUMIF文

#データを条件指定で数える

・B列が0のものを数える場合
=countif(B:B,"=0")


・B列が1以上、2000未満の場合
=countifs(B:B,">=1",B:B,"<2000")

#データを条件指定で合計する

・C列の数値を合計したい、B列が0の場合
=sumif(B:B,"=0",C:C)

・C列の数値を合計したい、B列が1以上、2000未満の場合
=sumifs(C:C,B:B,">=1",B:B,"<2000")



データが追加される可能性がある場合
例）B列　B:B
品質系社員の現場からのビジビリティー、存在感向上＝成果の見える化のアプローチ

何らかの製品、サービス開発をしている会社の中でQA/テストチームを運営している人が、会社のなかでどのように存在感を出していくか、のアプローチをまとめてみました。

# 品質コストから考える
**要するに：ビジネスにばっちり貢献してるんですよ**

まず実際にバグが出せているか？出せているなら、そのバグがもし市場にそのまま出ていたら、どれぐらいの損失（クレームに対して全社が動くコスト＋ブランド失墜の回復コスト）が発生していたかを推定してみる。それはおそらく利益を簡単に食いつぶしていたはず。このとき、絶対に開発チームを責めない。高度なこと、複雑なことをやっているならバグがでるのは当たり前。多様な価値観に基づいてそれに反する事象を探索するのはテスターの仕事。

品質コストには、予防コスト、検出コスト（テスト）、内部失敗コスト（社内で修正できた）、外部失敗コスト（流出した）の4つがあり、テストをする動機は、外部失敗コスト＞予防コスト＋検出コスト＋内部失敗コスト　だから。単に「儲かるから」やる。ただし、外部失敗が許される製品についてはリリース時ではなく、利用時に品質を向上できるような品質方針＝サービスの可用性、データ破損、セキュリティにリソース全振り を取ることが多い（代表的なのはGoogle、Amazon）。

# 技術力から考える・テスト技術編
**要するに：ちゃんとテスト設計しているならその成果物は技術的にも認められる**

ちゃんとテスト設計をしているなら、テストエンジニアがどんなことを考えてテストしているのかを成果物としてチーム全体で共有する。製品や機能、マイルストーンに向けて達成すべき品質と行うべきテストの地図や、機能テストを設計するうえで作った「モデル」（例えばデシジョンテーブルや状態遷移図、テスト観点マトリクスや、CRUDとエフェクトを整理した図、などなどなど）があるはず。モデルを書いてそれをどう効率的に網羅するか？という機能テストの設計はすさまじく創造的で、プログラマからみても芸術的なはず。

```エピソード:エピソード
某JavaScriptエンジンのテストを設計するときに浮動小数点の仕様（IEEE754）
における数の扱いをクラス分けして利用シーンとの影響で整理した図を書いて、
テストの意図を説明したところ、開発側の技術リードから
「ベテランの開発者でもここまで仕様を構造化して整理できる人は少ない」
と称賛のメッセージを頂きました。
```
#技術力から考える・CI/CD編
**要するに：開発チームに親和性の高い部分で貢献する**

CIシステム＋自動テストの開発と運用をテストチーム自身が行う。CIシステムの重要性は開発チームが嫌ってほどわかっているはずだけど、CI/自動テストはある種”サービス”なので、ちゃんと運用するのは難しい。自動テストが伴っていなければ片手落ちなので、いっそテストチームが運用しちゃう。SCMを握れるので、コードメトリクスなんかも絡めて内部品質（保守性）も自動的・PerCommit で診断できるようになるとさらにカッコいい。

#チームの成長から考える
**要するに：プログラマに対するコーチになる**

テストチームが発見したさまざまなバグやそのバグが発生する過程を、バグレポートを通じて開発チームが学ぶことで、次のリリースに向けて少し賢くなっている。この少し賢くなるを繰り返すことで、チームがどんどん成長していく。市場からフィードバックも得られるが、概して市場は「遅い」。きちんと学んだ品質エンジニアであれば、開発プロセスやテストプロセスのどこをどう変えるとチームが成長できるか（例えばシステムテストで数値計算のバグが出ているようなら単体テストを教える、コードレビューに同席して生産性を高めるためのファシリテーションをする、製品の品質ゴールに対してリーダーシップを発揮できる、など）を設計できる。テスターの究極の到達点は「コーチ」。プログラマがプロフェッショナルであるなら、優れたコーチの価値を認める。
任意のコマンド実行が終わったらSlackに通知を送りたい

# 動機
いま在籍している大学の研究室では、設置されているワークステーション（すごく性能のいいPC）に数日かかるようなすごく重い処理を実行させて、ちょくちょく**処理終わってるかな～？**と様子を見に来る、という使い方をしています。

わざわざ様子を見るためだけに来るのも手間なので、**終了したことを通知**してくれるツールがあると便利だな～と思って作りました。

# 環境
Ubuntu 18.04
Python 3.6

# 使用例
これは実行したいコマンド

```shell
python aaa.py
```

以下のように、コマンドの前に```slacknotice```を付けると…

```shell
slacknotice python aaa.py
```

slackに開始と終了が通知されます。
<img width="319" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307646/5765e649-9186-a583-c3b0-1dc87c12ade0.png">

# 方法

1. **Slack Incoming Webhooks**というSlackアプリケーションを用いてPOSTリクエストでメッセージを送信するためのエンドポイントを作成
2. ローカル側で「slacknotice」というスクリプトを作成。ここでは引数に受け取ったコマンドを実行し、その実行前と後にPOSTリクエストを送る。ディレクトリにPATHを通して全体から呼び出せるようにする。

### 1. Slack Incoming Webhooksの設定
[アプリをSlackに追加する](https://slack.com/apps) という画面から「Incoming Webhooks」というアプリケーションを検索して追加します。
投稿するチャンネルや通知するメッセージのアイコンなどの設定を行うと、進めていった先の画面で **Webhook URL** を取得できます。これを次の手順で使用します。
※くわしい設定方法：[SlackのIncoming Webhooksを使い倒す](https://qiita.com/ik-fib/items/b4a502d173a22b3947a0)


### 2. スクリプトの準備

#### 2-1. スクリプト作成

「slacknotice」というスクリプトを作ります。
Pythonで書いています。なのでPythonの入っている（```Python```コマンドでインタープリタが起動する）環境でしか動きません…
（シェルスクリプトでcurlなどを使用して書く方法でもできるとは思います）

以下は一番シンプルなパターン

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

# ここを取得したWebhook URLに変更
webhook_url = "https://hooks.slack.com/services/AAAAA/BBBBBB/CCCCCCCC"

import json, os, requests, sys
from subprocess import run

# 通知を送る関数を定義
def notice(msg):
    post_data = json.dumps({"text": msg})
    requests.post(webhook_url, data=post_data, headers={"Content-Type": "application/json"})


# 引数から実行するコマンドを取得
command = sys.argv[1:]

# 実行前通知
notice("実行開始")

# コマンド実行、ユーザーのカレントディレクトリ（os.getcwd()）で実行するようにしている。
run(commands, cwd="{}/".format(os.getcwd()))

# 実行後通知
notice("実行終了")

```

これを保存します。
今回は```~/scripts/slacknotice```にあるという前提で話を進めます。

#### 2-2. 実行権限の付与

```shell
chmod u+x ~/scripts/slacknotice
```
でスクリプトを実行可能にします。

#### 2-3. PATHを通す

```shell
echo export PATH='$PATH:$HOME/scripts/' >> ~/.bashrc
source ~/.bashrc
```
でスクリプトが保存されているディレクトリ```~/scripts/```にPATHを通します

#### 2-4. 実行

```shell
slacknotice ls -altr
```

など適当なコマンドを実行すると、実行前と後に通知が飛びます。


# まとめ
Slackは手軽にメッセージ送信を行えるので、便利ですね。
pythonでfor文の中で値の代入更新ができない

## 事の発端
タイトルの通りです。自分があまりにも忘れがちで、やってしまいがちな例なので、備忘のためにメモしておきます。(代入ができないというより、エラーになるが正しいのですが、検索したときに引っかかりやすいと思ったので)
あと、エラーの際の内容もはっきりと理解していないので、アドバイスいただけるとありがたいです。

## やりたいことと(追記)
for文の中でdataframeの値の更新。代入というより更新をしたいのです。

## 動作環境
Windows10
PyCharm
Python3

## トラブルの内容
以下のようなfor文をやると変数に値が入らない。
追記）dfの値が更新できない。

```python3
import pandas as pd

data = [["勇者", "桃", 1],
        ["動物", "犬", 1],
        ["動物", "猿", 1],
        ["動物", "雉", 1]]

# データフレームの作成
df = pd.DataFrame(data)
# カラム名をdataframeにつける
df.columns = ["job", "name", "level"]
#print(df)

# 間違った例
for i, row in enumerate(df.itertuples()):
    row.level = 2
print(df)
```
## エラーの内容
row.level = 2
AttributeError: can't set attribute
??調べると、プロパティなので、代入できないということ？みたいな？
(・・・まあ、このfor文の中でiとかrowに代入しようとするのもおかしな話ですが、なんというか引数のように見えて代入したくなってしまうのは自分だけではないはず。)

## 正解のコード
```python3
import pandas as pd

data = [["勇者", "桃", 1],
        ["動物", "犬", 1],
        ["動物", "猿", 1],
        ["動物", "雉", 1]]

# データフレームの作成
df = pd.DataFrame(data)
# カラム名をdataframeにつける
df.columns = ["job", "name", "level"]
# print(df)

for i, row in enumerate(df.itertuples()):
    df.iloc[i, 2] = i
print(df)
```
## 出力結果(dfの値が更新されている)
  job name  level
0  勇者    桃      0
1  動物    犬      1
2  動物    猿      2
3  動物    雉      3

追記）以下の方法のほうが良さそうです。

## iterrows()とat[]を使う方法
```python3
import pandas as pd

data = [["勇者", "桃", 1],
        ["動物", "犬", 1],
        ["動物", "猿", 1],
        ["動物", "雉", 1]]

df = pd.DataFrame(data)                 # データフレームの作成
df.columns = ["job", "name", "level"]   # カラム名をdataFrameにつける

for i, row in df.iterrows():
    df.at[i, 'level'] += i
print(df)
```
## 出力結果(dfの値が更新されている)
  job name  level
0  勇者    桃      1
1  動物    犬      2
2  動物    猿      3
3  動物    雉      4

## 現在の結論
自分的には、このサイトの記事が参考になったので、ピックアップさせるために引用します。
https://note.nkmk.me/python-pandas-dataframe-for-iteration/
**・1行ずつ値を取り出すiterrows()メソッドはビューではなくコピーを返すので、pandas.Seriesを変更しても元データは更新されない。**
・at[]で元のDataFrameからデータを選択して処理すると更新される。

## あとがき
・dataframeはこのような変更をしようとすると、毎回時間がかかりがちなので、もっと練習が必要ですね。
・より良いコードがあったら更新します。
マンガでわかる Adapter

![2F2F6D8B-E064-41D1-8042-C818F7DE6C33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/f318736e-1b06-0cf9-3888-054c87deaaf2.png)

インフラエンジニアそけっとさんはケーブルマニアなので、レガシー端子の変換コネクタもちゃんと持ってきいます。端子形状が違っても安心ですね。

ソフトウェア設計でも、実装ライブラリとフレームワークから求められるインターフェースがかみ合わないことは多々あります。そんな状況では普通、要求されたインターフェースを満たす実装を自分で書いて、内包した実装ライブラリの対応する機能に委譲しますね。これが Adapter パターンです。

なんのことはない普通のお仕事です。いわゆるラッパークラスです。

さてここで大事なのが、 [Decorator](https://qiita.com/tanakahisateru/items/d20be921079496c3aef5) パターンも [Proxy](https://qiita.com/tanakahisateru/items/d26600aba4c9bee9fc54) パターンも、クラス図で書くと同じような形をしたラッパークラスに見えるという点です。いったい何が違うのか。

それは、パターンで取り扱っている解決対象の問題です。

機能は合ってるのに端子がかみ合わないものを形合わせしたいという「意図」に名前が付いているのであって、ぜんぶ新規でコードを書くなら Adapter パターン構造には意味がないよってことです。仕方なくやる手段なんだから、それを目的にしちゃダメですよ。最初から USB-C のキーボードを持ってきておけば、ゲッ○ーロボみたいな端子を作る必要はないでしょ。
Laravel　windowsPCにインストールするにあたって躓いた点

#概要

どうも。初めまして東京へ越してきたばかりのwakakenといいます。

今回はお世話になっているプログラミングスクールさんの教材を基にマイPCにlaravelをインストールし、環境構築を行ったときに躓いたところを紹介します。

・Larabelのインストール

#PCのスペック

プロセッサ：　Core(TM)i3-7100U
メモリ：　8.00G
システムの種類：64ビットOS

PCは5年くらい前に買ったWindowsPCです。

#Larabelのインストール　躓きその１　～composerのPATH設定～

Larabelのインストールをするにあたって参考にしたサイトは以下のサイトです
https://reffect.co.jp/laravel/windows-xampp-laravel-install

手順については特に説明しないので、もし気になった方は上記のサイトを参照してください。

laravelは通常webサイトからのダウンロードなどでインストールを行いません。
「composer」と呼ばれるバージョン管理ソフトを用いてインストールを行うことになります。

composerを用いる際php.exeへのPATHを通す必要があるのですがこの意味が分からずいくつものサイトを調べる羽目になりました。

調べた結果phpはサーバーサイド言語ということでサーバー上でしか起動せず、そのためにはサーバーへのPATHを通しておくことが必須とのことでした。

ただ、新しくLarabelをインストールするためにこのphp.exeへのPATHを通すために自分のPC上にて環境設定とやらを行う必要があるとのこと。

なんやかんや調べたところ以下の手順でPATHを通すことができました！

「スタートメニュー」右クリック
↓
「システム」をクリック
↓
バージョン情報の下の方にある「システム情報」クリック
↓
開いたシステム情報の左側にある「システムの詳細設定」をクリック
↓
開いたシステムのプロパティから「環境変数」をクリック
↓
開いた画面からユーザー環境変数の変数欄に「PATH」があることを確認
↓
ある場合は「編集」、なければ「新規」をクリック
↓
変数名：PATH
変数値：C:\xampp\php（ディレクトリの保存場所はユーザーごとに任意で修正してください。php.exeがあるフォルダの直前までを参照します）
↓
「OK」を押して登録完了

#やっちまったこと（注意点）

自分の場合すでにPATHが通っていたのですが
再度設定しなおそうと一から設定しなおそうとしたら
PATHを誤って削除してしまうという…

PHPだけでなくそのほかのPATHも設定されていたのですが、
まとめて削除してしまいその後の対応にまた追われてしまいました。
PATHを編集する場合はくれぐれも削除はせず追記するのみすることをお勧めします。


#続きは

現在作成途中の為しばらくお待ちください
OracleDB での FUNCTION の作り方

# 概要
OracleDB で 初めて FUNCTION を使ったのでそのときのメモ

# 環境
- Oracle Database 12c

# 詳細
今回実装したのは、以下のような処理を行う FUNCTION です。

- 渡した引数の比率の計算結果を返す
- 分母が ```NULL``` もしくは ```0``` のときは、 ```100``` を返す
- 分子、分母がどちらも ```NULL``` の場合は ```NULL``` を返す

実際のクエリは以下のものになります。

```sql
CREATE OR REPLACE FUNCTION CALCULATION_RATE(
  vNumerator    IN NUMBER -- 分子
  ,vDenominator IN NUMBER -- 分母
) RETURN NUMBER
IS
  result NUMBER
;
BEGIN
  IF (vNumerator IS NULL AND vDenominator IS NULL) THEN
    result := NULL;
  ELSIF (vDenominator IS NULL OR vDenominator = 0) THEN
    result := 100;
  ELSE
    result := TRUNC(NVL(vNumerator, 0) / vDenominator * 100, 1);
  END IF;

  RETURN result;
END;
/
```
ポイントとしては、

- ```CREATE OR REPLACE FUNCTION [関数名](引数)``` で宣言
- ```RETURN [型]``` で戻り値の型を定義
- ```IS``` で関数内で利用する変数を宣言
- ```BEGIN``` ～ ```END``` に処理を記述する

といったところだと思います。

# まとめ
繰り返し呼ばれるような処理だったり、複雑な判定をクエリ上に書きたくない時などは、
FUNCTION にすることを考えたほうがいいと思いました。

単一の値だけでなく、SELECT 結果など複数の値を返すこともできるので、その部分については、
また別途まとめようと思います。
Rails + Carrierwave + fog でS3にアップロードした画像を削除する

RailsアプリからAWS S3へ画像をアップロードしたい際、Carrierwaveとfogを使った方法が様々な記事で紹介されています。

しかしアップロードした画像を削除する方法まで紹介している記事は少なかったので、自分の備忘としてまとめておきます。

画像をアップロードする仕組みは、Carrierwaveとfogを使って既に構築済みであることが前提です。

# なぜ画像を削除したいか
オブジェクトを削除する際に、オブジェクトに紐付いたアップロード済みの画像も削除しなければ、使用しない画像がS3内に溜まっていってしまいます！

# オブジェクト削除時にS3内の画像も削除する
userオブジェクトのimageに画像がマウントされているとします。
`before_destroy` で、オブジェクト削除時にS3からも画像を削除します。 

```app/models/user.rb
class User < ActiveRecord::Base
  mount_uploader :image, ImageUploader
  before_destroy :remove_image

private

  def remove_image
    image.remove!
    image.thumb.remove! # サムネイルを持っていない場合は不要
  rescue Exception => e
    logger.error(e.message)
  end
end
```

意外と簡単ですね！
LaravelやCakePHPでPDOが見つからない場合の対処方法

#エラーの発生内容

AWSのEC2(AmazonLinux)で下記のフレームワークを実行した際に表題のエラーが発生した。
・Laravelのmigrate実行時
・CakePHPのビルドインサーバー実行時

## 環境
PHP7.2
PostgreSQL10系

# 対処方法

下記のコマンドを実行して、自身の環境に合ったモジュールを探す

```
$ yum search php-pdo
```

そうすると、下記のように表示される。

```
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
242 packages excluded due to repository priority protections
=========================================================================================================== N/S matched: php-pdo ============================================================================================================
php-pdo.x86_64 : A database access abstraction module for PHP applications
php-pdo-dblib.x86_64 : PDO driver Microsoft SQL Server and Sybase databases
php54-php-pdo.x86_64 : A database access abstraction module for PHP applications
php55-php-pdo.x86_64 : A database access abstraction module for PHP applications
php56-php-pdo.x86_64 : A database access abstraction module for PHP applications
php70-php-pdo.x86_64 : A database access abstraction module for PHP applications
php70-php-pdo-dblib.x86_64 : PDO driver Microsoft SQL Server and Sybase databases
php71-php-pdo.x86_64 : A database access abstraction module for PHP applications
php71-php-pdo-dblib.x86_64 : PDO driver Microsoft SQL Server and Sybase databases
php72-php-pdo.x86_64 : A database access abstraction module for PHP applications
php72-php-pdo-dblib.x86_64 : PDO driver Microsoft SQL Server and Sybase databases
php73-php-pdo.x86_64 : A database access abstraction module for PHP applications
php73-php-pdo-dblib.x86_64 : PDO driver Microsoft SQL Server and Sybase databases
php74-php-pdo.x86_64 : A database access abstraction module for PHP applications
php74-php-pdo-dblib.x86_64 : PDO driver for Microsoft SQL Server and Sybase databases
php74-php-pdo-firebird.x86_64 : PDO driver for Interbase/Firebird databases

  Name and summary matches only, use "search all" for everything.
```

今回使用しているPHPのバージョンはPHP7.2なので、下記のコマンドを実行してPDOをインストール

```
$ sudo yum install php72-php-pdo
```

これでエラー解消。
間違って他のバージョンをインストールしないこと。
デザインマネージャーとしての半年間の振り返りと、今後の組織デザインについて

この記事は「[株式会社エイチームフィナジーのAdvent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-finergy)」14日目の記事です。

今回はデザイン関係のお話になりますので、noteに寄稿した物をシェアさせていただきます。

記事はこちら↓
[「デザインマネージャーとしての半年間の振り返りと、今後の組織デザインについて」](https://note.com/k_hajime/n/n077d733ed2f5)
PyTorch環境構築 (Windows10, Anaconda3, Pycharm, Python3)

#はじめに

PyTorchの環境構築を試みました。
そのメモを書きます。

PyTorchとは何か。
https://pytorch.org/
>An open source machine learning framework that accelerates the path from research prototyping to production deployment.

#1. 環境構築

OSは、Windows 10です。

##1.1. Anaconda 3のインストール
以下のURLをクリックします。
https://www.anaconda.com/distribution/
![Screenshot_2019-12-05 Anaconda Python R Distribution - Free Download(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400491/7df341a4-239a-cae2-8667-6f7a3a2bf322.png)
Python 3.7 versionの64-Bit Graphical Installer項目をクリックします。
Anaconda3-2019.10-Windows-x86_64.exeをダウンロードして実行します。

Anaconda prompt (Anaconda3)を管理者として実行します。
仮想環境を作成します。

```
conda create -n nn python=3.7
```

仮想環境リストを確認します。

```
conda env list
```

nn仮想環境を開始します。

```
conda activate nn
```

nn仮想環境のpythonバージョンを確認します。

```
python --version
```

##1.2. PyTorchのインストール
PyTorchのインストールコマンドは、以下のURLから入手することができます。
https://pytorch.org/

![Screenshot_2019-12-05 PyTorch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400491/bb68edf3-6a1e-ede2-dc47-b04203b0d1f9.png)

PyTorchをインストールします。

```
conda install pytorch torchvision cpuonly -c pytorch
```

##1.3. PyCharmのインストール
以下のURLをクリックします。
https://www.jetbrains.com/ja-jp/pycharm/download/#section=windows
![Screenshot_2019-12-05 ダウンロード PyCharm：JetBrainsによるプロの開発者向けのPython IDE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400491/3ffc5f3f-a6d2-200a-28f9-813bf7060f83.png)
PyCharmのコミュニティダウンロードをクリックし、
pycharm-community-2019.3.exeをダウンロードして実行します。
##1.4. PyCharmの仮想環境設定
Pycharmを実行して1つのプロジェクトを作成します。
File->Settings->Project nn->Project Interpreterをクリックします。
![New Bitmap Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400491/8818df59-d845-22be-946c-f7cbc09f3ece.png)

Conda EnvironmentのExisting environmentを選択します。
Interpreterに作成したAnaconda仮想環境のパスを入力します。
Conda executableにAnacondaのconda.exeパスを確認します。
OKボタンをクリックします。

ここまで、環境構築は完成でした。

#2. テスト
テスト用のソースコードは以下のURLから取得できます。
https://pytorch.org/get-started/locally/
ソースコードをコピペして、実行します。
以下の結果が得られました。
![New Bitmap Image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400491/6a254499-1d67-c98b-3644-bf129abe4e7d.png)

#3. 今後
PyTorchを使用して、面白い深層学習の実験をしたいですね。

#参考資料
[1] PyTorch: https://pytorch.org/
[2] PyTorch Installing on Windows: https://pytorch.org/get-started/locally/
[3] Anaconda: https://www.anaconda.com/
[4] PyCharm: https://www.jetbrains.com/ja-jp/pycharm/

以上です。
[AWS]AWS CLIからSSH用のキーペアを登録する

CLIからECSを構築するときに、SSH KEYってどうやって登録するんやっけみたいなことがあったので。
覚え書きです。

## 手順
1. ローカル(Mac)でKeyを作成する。
2. CLIで鍵をアップロードする。

そう、これだけ！

## ローカルで鍵を作成

```
$ cd ~/.ssh
$ ssh-keygen
```
Key名をつけたい場合は、1つ目の質問でKey名を入力。
その後パスフレーズの入力が求められます。不要の場合は、そのままEnter。

## AWS CLIからSSH用のキーペアを登録

```
$ aws ec2 create-key-pair --key-name aws_ecs_key_name --query 'KeyMaterial' --output text >~/.ssh/aws_ecs_key_name.pem
```
aws_ecs_key_name、aws_ecs_key_name.pemの箇所は、入力したKey名をいれてください。

これで登録されました。
以上でございます。
Homestead の PHPバージョンを変更する方法

以下のように `Homestead.yml` にphpのバージョンを追記するだけ

```Homestead.yml
sites:
    - map: homestead.test
      to: /home/vagrant/project1/public
      php: "7.3"
```

### 注意
これだけだとバージョンは上がっても、CLIのバージョンはデフォルトのままになってます。
（ `php -v` としても思っていたのと違うPHPのバージョンが表示される）

設定したバージョンに合致する以下のコマンドを実行して、CLIのバージョンも変更しましょう。

```bash
php56
php70
php71
php72
php73
php74
```

## 参考記事
https://laravel.com/docs/6.x/homestead#multiple-php-versions （公式ドキュメント）
https://takuyafujita.hatenablog.com/entry/2019/03/29/234813
https://www.84kure.com/blog/2019/09/03/laravel-homestead%E3%81%A7php%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%8B/
【GAS】1行で「交互の背景色」を実装する【スプレッドシート】【BandingTheme】


##サンプル
```JavaScript
// 1行なら
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A1:C6").applyRowBanding(SpreadsheetApp.BandingTheme.LIGHT_GREEN);

function myBandingTheme() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh = ss.getActiveSheet();

  sh.getRange("A1:C6").applyRowBanding(SpreadsheetApp.BandingTheme.LIGHT_GREEN);

}
```
![便利すぎて泣ける.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280139/a95979e1-e985-a43b-827f-0a88b3ca2314.png)

##ヘッダーとフッターの有無を設定したい場合
```JavaScript
applyRowBanding(bandingTheme, showHeader, showFooter)

// 例：ヘッダー色　なし　フッター色　あり
function myBandingTheme() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh = ss.getActiveSheet();

  sh.getRange("A1:C6").applyRowBanding(SpreadsheetApp.BandingTheme.LIGHT_GREEN, false, true);

}
```
![便利すぎ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280139/598391ba-b655-c336-c6bf-22c6bbccefca.png)

##色の一覧
https://developers.google.com/apps-script/reference/spreadsheet/banding-theme

##参考
サンプル付きで同じ事をやっているページが存在しない（執筆当時）ため書きました

[BandingThemeはSpreadsheetAppクラス](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app)

[applyRowBandingはRangeクラス](https://developers.google.com/apps-script/reference/spreadsheet/range#applyrowbandingbandingtheme)

https://developers.google.com/apps-script/reference/spreadsheet/range#applyrowbandingbandingtheme,-showheader,-showfooter
vue.js body に css つけようぜ

vue.js で body に css をつけたい。

まずはCSSを作ろうぜ。

```app.scss

body {
    background-color: #fff;
}

body.single {
    background: pink;
}


```


んで、hoge.vue に アクセスされたら body に single という Classをつける。
逆に離れたらClassを削除。

```hoge.vue

    export default {

//離れたとき
        beforeDestroy() {
            document.body.className = '';
            this.$root.headerHide = false;
            this.$root.footerHide = false;
        },

//表示されたとき
        mounted() {
            document.body.className = 'single';
            this.$root.headerHide = true;
            this.$root.footerHide = true;
        },


```

これでいけますわ。
MVCでカート機能３ - Controller編 for Laravel

####考え方

[Model](https://qiita.com/Fell/items/1c4c2fe145cad0a6a0d7)は単体データの操作を。
[View](https://qiita.com/Fell/items/2c7cc5927e88536c434f)は表示処理。
ControllerはViewのデータ処理。

####データベース
DBカラム
items : id | name | content | price | quantity | created_at | updated_at | deleted_at
carts : id | user_id | item_id | quantity | created_at | updated_at | deleted_at
####ソース

```php:app/Http/Controller/CartController.php
<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\facades\Auth;
use App\Cart;

class CartController extends Controller
{
    public function __construct(Cart $cart) {
        $this->cart = $cart;
    }
    public function index() {
        $carts = $this->where('user_id', $auth_id)->get();;
        $subtotals = $this->subtotals($carts);
        $totals = $this->totals($carts);
        return view('cart.index', compact('carts', 'totals', 'subtotals'));
    }
    private function subtotals($carts) {
        $result = 0;
        foreach ($carts as $cart) {
            $result += $cart->subtotal();
        }
        return $result;
    }
    private function totals($carts) {
        $result = $this->subtotals($carts) + $this->tax($carts);
        return $result;
    }
    private function tax($carts) {
        $result = floor($this->subtotals($carts) * 0.1);
        return $result;
    }
    public function add(Request $request) {
        $item_id = $request->input('item_id');
        if ($this->cart->insert($item_id, 1)) {
            return redirect(route('cart.index'))->with('true_message', '商品をカートに入れました。');
        } else {
            return redirect(route('cart.index'))->with('false_message', '在庫が足りません。');
        }
    }
    public function delete(Request $request) {
        $cart_id = $request->input('cart_id');
        return redirect(route('cart.index'))->with('true_message', 'カートから商品を削除しました。');
    }
}
```

####解説
set_message(); はオリジナルのヘルパ関数。
sessionに値を挿入して１回だけフラッシュメッセージを出す。
layoutで処理。

####メソッド
**view からのボタン操作。**
・add
・delete
**view への表示用。**
・index
--**private**
・subtotals
・tax
・totals

LGTMよろしくお願いします！
励みになります！
Pythonにおけるlist()と[]の違い

## 追記
2019/12/11追記:
コメントで時間計測の誤りをご指摘いただきました。
現在、正しいコードでの再検証中です。

## TL;DR
- `[]`表記の方が実行時間で有利
- `list()`と`[]`でタプルの扱いが一部異なっているので注意が必要

## 動機
Pythonには`There should be one-- and preferably only one --obvious way to do it.`という哲学があるが、頻繁に使われるデータ構造の一つであるリストについて、二通りの書き方があるのはこの哲学に反しているのでは？
何か違いがあって、異なる定義ができるようになっているのか？と気になった。

### 調べてみた
StackOverflowに2015年に[同様の質問](https://stackoverflow.com/questions/33716401/whats-the-difference-between-list-and)がされていた。

>One's a function call, and one's a literal:

なるほど、`list()`は関数であり、`[]`はリテラルであると。
よくわからん。

>For the sake of completion, another thing to note is that list((a,b,c)) will return [a,b,c], whereas [(a,b,c)] will not unpack the tuple. This can be useful when you want to convert a tuple to a list. The reverse works too, tuple([a,b,c]) returns (a,b,c).

なるほど、タプルに対しての挙動が異なっている。
上記の関数とリテラルであることがこのような挙動の違いに現れているのか？

Quoraでも2016年に[同様の質問](https://www.quora.com/In-Python-any-difference-between-using-and-list-or-between-and-dict)がされていた。

>The end result is the same whether you use [ ] or list() and same for { } vs. dict(). There is a difference in performance, though. [ ] and { } are more performant than the alternatives, list() and dict(), mainly because using list() and dict() involves the overhead of symbol lookup and function invocation.
>
>In my opinion, using [ ] and { } is more pythonic. In addition, this notation allows you to take advantage of list/dictionary comprehension.

そういえば、辞書型においても`dict()`と`{}`で二通りの定義の仕方がある。
リテラル表記の方がよりPythonic(Pythonらしい)である？自分はまだまだPython全然わからんな。

## 検証
それぞれ一部挙動が異なっていることは判ったが、同等の挙動をするような状況ではどちらを使うのが良いのだろう？
関数とリテラルでコールに違いがあるということなので、それぞれ100回づつオブジェクトを生成するようなコードで検証してみた。

### 実行環境
- AWS EC2 t2.micro
- Pyhon 3.6.8

### 実行時間の比較
```Python:list.py
#-*- using:utf-8 -*-
import time

if __name__ == '__main__':
    start = time.time()
    
    for i in range(0,100):
        exec("list_%d = %s" % (i, []))
    elapsed_time1 = time.time() - start
    print ("elapsed_time:{0}".format(elapsed_time1) + "[sec]")

    start = time.time()

    for j in range(100,200):
        exec("list_%d = %s" % (j, list()))
    elapsed_time2 = time.time() - start
    print ("elapsed_time:{0}".format(elapsed_time2) + "[sec]")
```

~~なるほど実行時間に有意差がある！
ちなみにループ数を1000回および10000回にした場合にもリテラル`[]`における実行時間の有意性が認められた。~~

### タプルの扱い
上述したように、生成時にタプルを引数にとるとそれぞれで異なる挙動をするが、
オブジェクトを生成したあとの挙動はどうなるのか？

```Python:
>>> l1 = []
>>> l1.append((1,2,3))
>>> print(l1)
[(1, 2, 3)]

>>> l2 = list()
>>> l2.append((1,2,3))
>>> print(l2)
[(1, 2, 3)]
```

いったんリストオブジェクトとして生成されたあとの挙動には違いがないようだ。
この辺はPythonというかオブジェクト指向の話なんだろう…オブジェクト指向理解してないなー。

### リスト内包表記
Q. 実行できる？できない？
A. どちらの表記でも実行可能。
TypeScript: 配列型からその要素のユニオン型を導出する方法。例えば、Array<A | B | C>からA | B | Cを導き出す。

本稿では、配列型からその要素のunion型を導き出す方法を説明する。

## やりたいこと

例えば、次の`List`型のように、`string`・`number`・`boolean`の要素を持ちうる`Array`型があるとき、

```typescript
type List = (string | number | boolean)[]
```

次のように、配列要素のユニオン型を求めたい。

```typescript
type Elem = string | number | boolean
```

## やりかた

[indexed access operator](https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types)(`T[K]`のようなカギカッコ)使うと、配列要素の型を取り出すことができる:

```typescript
type List = (string | number | boolean)[]
type Elem = List[number] // string | number | boolean になる
```

コンパイルが通ることを確認するコード:

```typescript
const el1: Elem = '' // string
const el2: Elem = 0 // number
const el3: Elem = false // boolean
```

[→このコードをTypeScript Playgroundで試す](http://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=6&pc=35#code/C4TwDgpgBAMglgZ2FAvFAFEgTnAdgcygB8pcBXAWwCMItioqB7RgGwgENcBKAbQF0AUKEhQAomwqpYiYD3LVaggQGNGuJFAgsAjAC4xEqQHIjUAPRmo2PPhVqNWgEz7xESWgAM5y-JpY76shaAMwuhmgAZuwsCNAWDMxsnEA)

## どうして`List[number]`で配列要素のユニオン型が分かるの？

話を単純にするために、要素の型が1つだけの(=ユニオン型ではない)配列型を考えてみよう。次のスニペットの`Booleans`型は`boolean`な値からなる配列型である。

```typescript
type Booleans = boolean[]
```

この`Booleans`型について、いくつか自問自答してみよう。

* `Booleans`型の要素0番目の型は何になるか？ 要素0番目に代入できる値は`ture`もしくは`false`なので、答えは「`boolean`型」である。
* `Booleans`型の要素1番目の型は何になるか？ これも同様に、答えは`boolean`型だ。
* `Booleans`型の要素2番目の型は？ これも当然、`boolean`型だ。

私達がこの自問自答で要素の型を考えられるように、TypeScriptでも要素の型を調べることができる。それが、[indexed access operator](https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types)だ。

```typescript
type Booleans = boolean[]
type TypeOfElement0 = Booleans[0] // 質問「要素0番目の型は何？」をコードで表現したもの
type TypeOfElement1 = Booleans[1] // 質問「要素1番目の型は何？」をコードで表現したもの
type TypeOfElement2 = Booleans[2] // 質問「要素2番目の型は何？」をコードで表現したもの
```

質問「要素0番目の型は何？」は、実はもっと一般化することができる。それが「要素**N番目**の型は何？」という質問だ。「N番目」の「N」に対応する、TypeScriptの表現は`number`になる。

```typescript
type Booleans = boolean[]
type TypeOfElement = Booleans[number] // 質問「要素N番目の型は何？」をコードで表現したもの
```

ここまでは、要素の型が1種類の配列型である`boolean[]`でindexed access operatorを説明してきたが、要素がユニオン型になっている配列にも話を広げてみよう。最初に示した、`List`型で、先程の自問自答を考えてみることにする。

```typescript
type List = (string | number | boolean)[]
```

* `List`型の要素0番目の型は何になるか？ 要素0番目の値は、`string`かもしれないし、`number`かもしれないし、`boolean`かもしれない。だから、答えは「`string | number | boolean`型」である。
* `List`型の要素1番目の型は何になるか？ これも同様に、答えは`string | number | boolean`型だ。
* `List`型の要素2番目の型は？ これも当然、`string | number | boolean`型だ。

つまり、質問を一般化すると、

* `List`型の要素N番目の型は？ → `string | number | boolean`型。

になる。これを先程の`Booleans`の例と同様手順でTypeScriptのコードに起こすと、本稿冒頭の「やりかた」で示したスニペットになるわけだ:

```typescript
type List = (string | number | boolean)[]
type Elem = List[number] // Elem は string | number | boolean になる
```
[小ネタ][Python] 2次元配列の文字列を数値に置換する

Pythonの2次元配列に格納した文字列を数値に置換する方法についてメモ。
たとえば標準入力で以下のように数字が渡される。

```
3
1 2
3 4
5 6
```

1行目は2行目移行の標準入力の繰り返し回数。
で、2行目移行の数値は2次元配列に格納したい。

```python
arr = []
n = int(input())
for i in range(n):
    arr.append(input().split())
print(arr)
>>>[['1', '2'], ['3', '4'], ['5', '6']]
```
このときinput().split()で入力を受け取ると、文字列のリストとして入力される。
これをintに変換したい。

## forで変換する場合
```python
for i in range(len(arr)):
    for j in range(len(arr[i])):
        arr[i][j] = int(arr[i][j])
print(arr)
>>>[[1, 2], [3, 4], [5, 6]]
```

## リスト内包表示で変換する場合
```python
arr = [[int(x) for x in y] for y in arr]
print(arr)
>>>[[1, 2], [3, 4], [5, 6]]
```

## おまけ:1次元配列にしちゃう場合
```python
arr = [int(x) for y in arr for x in y]
print(arr)
>>>[1, 2, 3, 4, 5, 6]
```
JavaScriptのTODOリスト3【備忘録】


```HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>Javascriptの練習</title>

  </style>
</head>
<body>
  <button id="add">ADD</button>
  <li>test</li>
  <ul id = 'ul'></ul>

<script>
class Li {
  constructor(arg_num) {
    this.num = arg_num;
    this.ul = document.getElementById('ul')
    this.li = document.createElement('li');
    this.li.textContent = this.num;
    this.button = document.createElement('button');
    this.button.id = "delete" + this.num;
    this.button.classList.add("delete");
    this.button.textContent = '×';
    this.li.appendChild(this.button);
    this.ul.appendChild(this.li);

    this.button.addEventListener('click', (e) =>{
      console.log('delBtnクリック')
      this.ul.removeChild(this.li);
    });//delBtnClick
  }//constructor

}//Li

const li_el = [];
const addBtn = document.getElementById('add');
let num = 0;
addBtn.addEventListener('click', () => {
  li_el.push(new Li(num));
  num++;
});
</script>
</body>
</html>
```
MVCでカート機能２ - View編 for Laravel

####考え方
[Model](https://qiita.com/Fell/items/1c4c2fe145cad0a6a0d7)は単体データの操作を。
Viewは表示処理。
[Controller](https://qiita.com/Fell/items/bc7d7acec68c682969f0)はViewのデータ処理。

####データベース
DBカラム
items : id | name | content | price | quantity | created_at | updated_at | deleted_at
carts : id | user_id | item_id | quantity | created_at | updated_at | deleted_at

####ソース
````php:resources/view/cart/index.blade.php
@extends('layouts.mini_app')
@section('content')
<body>
@if (0 < $carts->count())
        <table>
                <h1>カート内容</h1>
                <tr style="background-color:#e3f0fb">
                        <th>商品名</th>
                        <th>購入数</th>
                        <th>価格</th>
                        <th>削除</th>
                </tr>
                @foreach ($carts as $cart)
                        <tr style="background-color:#f5f5f5">
                        <td align="right">{{ $cart->item->name }}</td>
                        <td align="right">{{ $cart->quantity }}</td>
                        <td align="right">{{ $cart->subtotal() }}</td>
                        <td><form method="post" action="{{ route('cart.delete') }}">
                                {{ csrf_field() }}
                                <input type="hidden" name="cart_id" value="{{ $cart->id }}">
                                <button type="submit">削除</button>
                        </form></td></tr>
                @endforeach
                <td style="background-color:#f5f5f5">
                        <td>合計</td>
                        <td>{{ $subtotals }}</td>
                        <td>税込: {{ $totals }}</td>
                        <td></td>
                </td>
        </table>
@else
        <h1>カートに商品はありません</h1>
@endif
<br>
<h2><a href="{{ route('item.index') }}">商品一覧へ戻る</a></h2>
</body>
@endsection
```

####解説
```php:コントローラーから受信した変数
$carts //collection-> model->cart
$subtotals //int 税抜合計
$totals //int 税込合計
```
LGTMお願いします！
励みになります！
fishでgit stashできないの？と感じたので調べてみた

#概要
自分は`shell`に`fish`を使っています。

ある対応をしていて、`git stash`を使いたい場面に遭遇して使ってみると

```terminal
git stash list

stash@{0}: On `ブランチ名`: `stash message`

git stash pop stash@{0}

error: stash@0 is not a valid reference
```

なぜ！？

#ブレース展開
答えはブレース展開にありました。

fishでは`{}`の動きが他のshellとは違っています。

- bash

```terminal
echo {1..10}

1 2 3 4 5 6 7 8 9 10
```
このような使い方をしますが、

- fish

```terminal
echo input.{c,h,txt}

input.c input.h input.txt
```

fishではこのような動きになり、`{}展開`という動きになります。

#git stashしたい
ではどうすればいいのかというと、エスケープしてあげます。

```terminal
git stash pop stash@\{0\}
```

バックスラッシュで`{`と`}`をエスケープし、展開させないようにします。

#最後に
このような対応で無事できましたが、タブ補完でもエスケープしてくれました。。。

`fish`賢いですね〜
学園祭当日を楽しめるアプリ開発 始めた理由&開発環境

## はじめに
Qiitaに投稿するのも初めてなので、自己紹介も含め、この記事の概要を説明したいと思います。

私は、理工展連絡会という学園祭実行委員会に所属し、2年目にして、アプリ開発班を一から立ち上げて、理工展当日に楽しめるアプリをなんとか1年で形にしたという経験があります。今回は、その経験をもとに、この記事を執筆しています。

したがって、対象読者としては学園祭のアプリってどうなの？と興味がある実行委員所属の情報系担当者になるのかなと思います。

参考までに、私の立ち上げたアプリ開発班として2年目の第66回理工展のために作成したアプリのURLをこちらに置いておきます。
https://www.rikoten.com/php/pages/app/index.php




## 理工展 アプリ開発にあたって
### アプリ開発を始めたきっかけ
アプリ開発を始めたきっかけとしては、**個人的にAR機能で当日楽しめるものを作ってみたかったからというのが一番の理由です**。まず、早稲田大学西早稲田キャンパスの構造上、中庭ではビル風がどれだけ天気の良い日でも吹いて、中庭にテントを建てられず、閑散としていました。

そこで、私はアプリ開発に興味を以前から持っていたこともあり、中庭にアプリを用いて、ARのデカいオブジェクトを出現させることができれば、その閑散としている状況を少しでも改善することができるのではと思いました。（最終的にAR矢口くんという理工展の「矢口くん」というマスコットキャラクターと一緒に写真を取れる機能をアプリの中に組み込むことができました。）

それが、アプリ開発を始めようと思ったきっかけになります。

### アプリ開発班の組織
上記の理由からアプリ開発を始めると言っても、さすがに一人で開発するのは大変です。そんな中、実行委員会の幹部の先輩方にも助けてもらいながら、自分を含め**3人**をアプリ開発班として、割り振っていただけました。

役割分担としては、私はiOSアプリ開発担当とアプリ開発班のチーフとしての役割を持ちました。そして、残る2人はAndroidアプリ開発とその他細かいアプリ開発に関わる仕事（利用規約作成など）を行ってもらいました。

### 学園祭とアプリの親和性について
**一年間、学園祭アプリを開発し、当日の運用状況として感じたこととしては、学園祭とアプリというものはそこまで親和性が高いかと言われるとそうでもないなという感じです。**

そう考える理由としては、学園祭1日や2日だけのために、わざわざ来場された方々がアプリをダウンロードして下さるかという問題です。ダウンロードするというハードルがやはり高いことから、それに見合う対価を用意しなければ、厳しいのが現状です。

我々は、アプリを入れて頂いた方には、学園祭当日に使用できるクーポン券や謎解きの企画とコラボして、謎解きのヒントをアプリにのみ公開するなど多くの方法を実施してきましたが、爆発的にダウンロード数が伸びるようなメリットを提示は出来ていないように思います。

視点を変えてみると、**コアなファン、すなわち、毎年来て下さるような方であれば、通知による連絡を始めとして、これまで以上にアプローチをすることが可能**になるので、どの層に向けて広報活動をしていくのかというのが、学園祭でアプリ開発をするかどうかの判断材料にもなりうるのではないかと思いました。

## アプリ開発環境
最後に、このアプリ開発にあたり、どのような開発環境で行ったのかというのをご紹介します。学園祭でアプリ開発をしたいという方への参考になれば幸いです。

### iOS
**Xcode&Swiftで開発を行いました。**その理由は非常に簡単で、上記にある通り、AR機能を実装したかったこともあり、Xcode&Swiftでの開発が最適であると判断したからです。
開発は、周りに詳しい人が全くいなかったので、本を読んだ上で、ググって解決することで、ほとんど問題は解決したので、この環境下での開発では、組み方が分からず困ることはないと思います。

### Android
**Android Studio&Javaで開発を行いました。**しかし、この開発環境の欠点としては、AR機能の実装が厳しいことです。
そこで、**AR機能のみはUnityを使用しました。**
結果として、学習コストが半端なく多くなってしまいましたが、一緒に開発を行っていた仲間が持ち前のプログラミングの才能で気づいたらすべて完成しているような状況でした（笑）

ですから、AR機能をAndroidで実装したいと考えているのであれば、気を付けてもらいたいポイントです。

### サーバー
サーバーに関しては、**iOSとAndroid共通でFirebaseを導入しました。**理由としては、簡単に実装できるからです。さらには、利用者がFirebaseの有料版を必要とするくらいに満たない、ようは無料版の中で納まって費用が掛かっていないというのもあります。
また、通知を送信するというようなこともFirebaseであれば、かなり簡単にできるので、学園祭アプリを作るのであれば、当分はFirebaseが良いのかなと思ってます。

### 統合開発環境を使わなかった理由
これは、もうすでに何度も言っているので分かるかと思いますが、**AR機能の実装にこだわったためです。**実際はARKitを使ってみたかったみたいなところが大きいですが、統合開発環境だと、使える機能が制限されるということを敬遠して、選ばなかったということです。

ただし、学園祭のアプリとして、パンフレットの機能の代わりになるくらいのものが作れればと考えているのであれば、統合開発環境でも可能なのではないかと思ったりもします。

##最後に
ざっくりではありますが、学園祭でアプリ開発をした経緯と開発環境について、まとめてみました。
この記事を読んで、学園祭のアプリ開発を始めようと思ってくださる方がいれば幸いです。
最後まで読んで下さりありがとうございました。
ActiveRecord::Type::Boolean#cast の返り値が nil となるケースについて

API などでクライアント側から渡ってきた `"true"`、`"false"`、`1`、`0` などの値を、 Ruby の `true` や `false` として扱いたいときがある。
Ruby では `false` と `nil` 以外の値はすべて `true` として扱われるため、`!!` を先頭につけたとしても実現できない。

```rb
!!nil #=> false
!!0 #=> true
!!'false' #=> true
```

そのようなときには `ActiveRecord::Type::Boolean#cast` を使う。

```rb
ActiveRecord::Type::Boolean.new.cast "true" #=> true
ActiveRecord::Type::Boolean.new.cast 0      #=> false
```

しかしながら、どんな値でも `true` か `false` にしてくれるわけではない。

```rb
ActiveRecord::Type::Boolean.new.cast nil #=> nil
ActiveRecord::Type::Boolean.new.cast ""  #=> nil
```

結論を先に書くと、

- nil になるもの => `nil`, `""`
- false になるもの => `false`, `0`, `"0"`, `:"0"`, `"f"`, `:f`, `"F"`, `:F`, `"false"`, `:false`, `"FALSE"`, `:FALSE`, `"off"`, `:off`, `"OFF"`, `:OFF`
- true になるもの => 上記以外すべて

となる。ロジックの定義箇所は以下を参照。

# 定義箇所

`rails/activerecord/lib/active_record/type.rb` を見てみると、実態は `rails/activemodel/lib/active_model/type/boolean.rb` に定義されていることがわかる。

```rb:rails/activerecord/lib/active_record/type.rb
#...

module ActiveRecord
  module Type
    @registry = AdapterSpecificRegistry.new

    class << self
      attr_accessor :registry # :nodoc:

      #...

      def register(type_name, klass = nil, **options, &block)
        registry.register(type_name, klass, **options, &block)
      end

      #...
    end

    #...    

    Boolean = ActiveModel::Type::Boolean
    
    #...

    register(:boolean, Type::Boolean, override: false)

    #...
  end
end
```

`rails/activemodel/lib/active_model/type/boolean.rb` を見てみると、真偽値の判定ロジックが書いてある。


```rb:rails/activemodel/lib/active_model/type/boolean.rb
module ActiveModel
  module Type
    #...

    class Boolean < Value
      FALSE_VALUES = [
        false, 0,
        "0", :"0",
        "f", :f,
        "F", :F,
        "false", :false,
        "FALSE", :FALSE,
        "off", :off,
        "OFF", :OFF,
      ].to_set.freeze

      #...

      private
        def cast_value(value)
          if value == ""
            nil
          else
            !FALSE_VALUES.include?(value)
          end
        end
    end
  end
end
```



```rb:rails/activemodel/lib/active_model/type/value.rb
module ActiveModel
  module Type
    class Value
      #...

      def cast(value)
        cast_value(value) unless value.nil?
      end

      #...
    end
  end
end
```

# 結論

処理の流れをまとめると以下のようになる。

1. `ActiveRecord::Type::Boolean.new.cast(value)` が呼ばれる
2. `ActiveModel::Type::Boolean.new.cast(value)` が呼ばれる
3. `value` が `nil` でなければ `ActiveModel::Type::Boolean.new.cast_value(value)` が呼ばれる
4. `value` が空文字なら `nil`、`FALSE_VALUES` に含まれている値なら `false`、そうでなければ `true` を返す

よって、冒頭で触れたような結果になる。
XcodeのCommand Line Toolsのせいでbundle install時にerrorになった

## 結論
XcodeのCommand Line Toolsのversionによってbundle installで失敗することがある。

## 過程
環境構築のために`bundle install`を叩いたところ、いきなりのerror…

```
An error occurred while installing json (2.2.0), and Bundler cannot continue.
Make sure that `gem install json -v '2.2.0' --source 'https://rubygems.org/'` succeeds before
bundling.
```

errorに従って`gem install json -v '2.2.0' --source 'https://rubygems.org/' `を叩けばいいんやろと叩くと、またerror…

```
Building native extensions. This could take a while...
ERROR:  Error installing json:
	ERROR: Failed to build gem native extension.
    current directory: /Library/Ruby/Gems/2.6.0/gems/json-2.2.0/ext/json/ext/generator
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby -I /Library/Ruby/Site/2.6.0 -r ./siteconf20191205-18252-quwww1.rb extconf.rb
mkmf.rb can't find header files for ruby at /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/include/ruby.h
You might have to install separate package for the ruby development
environment, ruby-dev or ruby-devel for example.
extconf failed, exit code 1
Gem files will remain installed in /Library/Ruby/Gems/2.6.0/gems/json-2.2.0 for inspection.
Results logged to /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-19/2.6.0/json-2.2.0/gem_make.out
```

errorでググって調べて上位に出てくる内容を試すも悉くうまくいかない。

ふと、この環境で実際に開発している人がいるのだから、自分とその人の差異を埋めれば、解決するのでは？と思ってXcode Command Line Toolsを`10.3`を使用していたことを思い出し、Xcode `11.1`に変更してみた。

## 結果

**$\huge{Ready}$$\huge{Perfectly.}$**

installが進んだ。
なぜ、こんなことが起こったかは調べてないので、詳細は不明。調べるとっかかりもよくわからない。
ひとまず、備忘録として残す。
Docker + Django + Beautifulsoup の環境構築＆実行

# きっかけ
Dockerを使った開発が基本になってきているが、Dockerを使った開発環境の構築をしたことがなかった。
→ **Docker**

Pythonからプログラミングを始めたが、Pythonを使って何かを作ったことがなかったので、何か作ってみたかった。
→ **Django**

スクレイピングを使ったサービスを作ってみたい＆Pythonでスクレイピングがしたい。
→ **Beautifulsoup**

# Docker
まずはDockerfileとdocker-compose.ymlを作成。  

### **Dockerfile**
```
FROM python:3.6
RUN mkdir /app
WORKDIR /app
ADD requirements.txt /app
RUN pip install -r requirements.txt
ADD ./backend /app
```

### **docker-compose.yml**
```
version: '2'
services:
  db:
    image: postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./backend:/app
    ports:
      - "8000:8000"
    depends_on:
      - db

```
ここではデータベースにPostgreSQLを使用する。

### **requirements.txt**
```
Django
psycopg2
beautifulsoup4
```
requirements.txtを使ってDjango、Beautifulsoupをインストールする。

### **コンテナの起動**
① Dockerイメージをビルドする。  

```
docker-compose build
```

② Djangoの慣習に則ってconfigという名前でルートのプロジェクトを作成する。

```
docker-compose run --rm web django-admin startproject config .
```  

③ コンテナを起動する準備が整ったので、下記のコマンドを実行する。

```
docker-compose up
```

[http://localhost:8000/](http://localhost:8000/) にアクセスするとDjangoの初期画面が表示される。


# Django
Djangoでは「myapp」というアプリケーションを作成し、viewからBeautifulsoupを使う。

### **アプリケーションの作成**
```
docker-compose run --rm web python manage.py startapp myapp
```  
これを実行すると、myappアプリケーションのディレクトリが作成される。

### **URLの設定**  
先ほど作成したmyapp/urls.pyにアプリケーションのurlを定義し、それをconfig/urls.pyから呼び出せるように設定する。

**myapp/urls.py**  

```
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
``` 

**config/urls.py**

```
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('myapp/', include('myapp.urls')),
    path('admin/', admin.site.urls)
]
``` 
これで [http://localhost:8000/myapp/](http://localhost:8000/myapp/) にアクセスすると「views」の「index」が呼ばれるが、まだ何も定義していないため「index」を作成する。

### **Viewの作成**  

**myapp/views.py**  

```
from django.shortcuts import render

def index(request):
  return render(request, 'myapp/index.html')
``` 
これで先ほどのURLにアクセスするとこのメソッドが呼ばれるようになったけど、まだ「index.html」がないため作成する。

### **Templateの作成**  
Djangoでテンプレートを作成するときは、アプリケーション以下に「templates」ディレクトリを作り、その中に個々のテンプレートを作成していく。

**myapp/templates/myapp/index.html**  

```
<h1>Hello Django</h1>
``` 
これでやっと「Hello Django」と書かれた画面が表示される。

# Beautifulsoup
Beautifulsoupを使うとHTMLやXMLから特定のデータを抽出することができる。

### **ViewからBeautifulsoupを使用する**
**myapp/views.py**  

```
from django.shortcuts import render
from bs4 import BeautifulSoup
import urllib.request

def index(request):
  # 対象サイトのURL
  url = "http://www.nikkei.com/"

  # スクレイピング
  response = urllib.request.urlopen(url)
  html = response.read()
  soup = BeautifulSoup(html)
  # 全てのaタグを抽出
  links = soup.find_all('a')

  # テンプレートに渡すデータを格納 
  context = {
    'links': links,
  }

  return render(request, 'myapp/index.html', context)

``` 

**myapp/templates/myapp/index.html**  

```
{{ links }}
``` 
これで対象サイトから全てのaタグを抽出し、画面に表示することができているはず。

# 終わりに
とりあえずDockerでDjangoの開発環境を構築し、Beautifulsoupを使うことができた。
まだPostgreSQLは使っていないし、DjangoはAPIとして使いたいし、フロント側はReactで作りたいので、このまま進めていこうと思います。
謎のスペースを殲滅する

# 事の始まり
コピペした内容をテキストボックスに貼り付けて、
送信ボタン押下したら、処理が通らねぇ。

# 何が起こった
見えない文字がある。
コピペ元のHTMLソースを見ると`&#8203;`なるものが。

# `&#8203;`
調べると、ずらずらと記事が出てきます。
**ゼロ幅スペース**
なるものだそうです。

# 対応について
こんなものがたくさんあったら、対応仕切れないよぅ・・。

と思って調べていたら、
まとめてくださっていた方がいらっしゃいました！
[\sが完全には空白文字を網羅できていなかった件](https://www.pandanoir.info/entry/2018/03/11/193000)

神かっ

要点をかいつまむと、
**`\s`で対応していないホワイトスペース文字がたくさんあるよ!**

というわけで、二番煎じ感すごいですが、コードにします。

# コードにする
```js:正規表現のところだけ抜粋
export const unmanagedSpaces =
  '\\u001c-\\u001f\\u11a3-\\u11a7\\u180e\\u200b-\\u200f\\u2060\\u3164\\u034f\\u202a-\\u202e\\u2061-\\u2063';

export const allSpaceRegexp = RegExp(`[\\s${unmanagedSpaces}]+`, 'g');

export default { unmanagedSpaces, allSpaceRegexp };
```

あとは煮るなり、焼くなり、replaceするなり。
csvファイルを分割して読み込んで並列で処理するやつ

磯野〜！数百万件のレコードが入っているcsvファイルがあるから、分割して並列で処理しようぜ！
### 備考
- 分割するのと並列するのを一緒にやってるのが見当たらなかったので備忘録として書きました、なんか素敵な記事があったら教えてください
- python3.7です
- pandas使いません
- [pool](https://docs.python.org/ja/3/library/multiprocessing.html#module-multiprocessing.pool)使います
- [future](https://docs.python.org/ja/3/library/concurrent.futures.html)使いません

### 早速やる
読み込むファイル

```csv:sample.csv
1,あ
2,い
3,う
4,え
5,お
```
`gen_chunks()`は作っている人がいたので拝借しました https://stackoverflow.com/a/4957046
だいたいのことは誰かが既にやってくれています。ありがとうインターネット、ありがとう先人たち
できあがったコードはこちら

```py:pool.py
import csv
import time
from multiprocessing import Pool

def read():
    f = open("sample.csv", "r")
    reader = csv.reader(f)

    pool = Pool()
    results = []
    for data_list in gen_chunks(reader):
        results.append(pool.apply_async(do_something, [data_list]))
    pool.close()
    pool.join()
    _ = [r.get() for r in results]

    f.close()

def do_something(data_list):
    print(f"start {data_list}")
    time.sleep(len(data_list))
    # hoge
    print(f"finish {data_list}")

def gen_chunks(reader, chunksize=2):
    """
    Chunk generator. Take a CSV `reader` and yield
    `chunksize` sized slices.
    """
    chunk = []
    for i, line in enumerate(reader):
        if i % chunksize == 0 and i > 0:
            yield chunk
            chunk = []
        chunk.append(line)
    yield chunk

read()
```

```:結果
start [['1', 'あ'], ['2', 'い']]
start [['3', 'う'], ['4', 'え']]
start [['5', 'お']]
finish [['5', 'お']]
finish [['1', 'あ'], ['2', 'い']]
finish [['3', 'う'], ['4', 'え']]
```
`chunksize=2`なので2レコードずつ`do_something()`に渡されています。でかいcsvだったらここをいい感じにしましょう。
`_ = [r.get() for r in results]`でエラーを拾っています。エラー処理をすべきですが面倒なので省いています
もっと良い書き方がありそうなので知ってる人は教えてください

また、stackoverflowでも指摘されていますが、`gen_chunks()`の配列リセット部分を`del chunk[:]`にすると出力が以下になります

```:結果
start [['5', 'お']]
start [['5', 'お']]
start [['5', 'お']]
finish [['5', 'お']]
finish [['5', 'お']]
finish [['5', 'お']]
```
私はコメントをちゃんと読んでなかったので残念な結果を目の当たりにしました
悲しいね
固定IPを持たないAWS EC2へ毎回同じコマンドでsshする

EC2のパブリックIPは起動するたびに変更されるため、sshする場合は起動するごとに変更が必要になります。

それだと面倒なのでAWS CLIでパブリックIPを取得してsshするようにします。

#### 前提

- AWS CLIがインストールされている

### コマンド

```bash
ssh {ユーザー名}@$(aws ec2 describe-instances --instance-ids {インスタンスID} | grep PublicIpAddress | sed -E 's/[^1234567890.]*//g')
```

#### 別解

`jq`コマンドがあるなら

```bash
ssh {ユーザー名}@$(aws ec2 describe-instances --instance-ids {インスタンスID} | jq -r '.Reservations[].Instances[].PublicIpAddress')
```

とするのも良いでしょう

`$()`記法はbash用のものなのでそれ以外のシェルでは合わせたものを使ってください。
【iOS13】Scheme 起動時にURLが取得できない！

iOS13になってSceneDelegate追加されたこともあり、試行錯誤が続く日々を送っています。
前回に引き続き、仕事中にiOS13でスキーム起動で困ったことをつらつらと書きます。

今までスキーム起動、ブラウザで指定したSchemeを入力した場合、下記のメソッドが呼ばれていました。

```
// AppDelegate.swift
func application(_ app: UIApplication, open url: URL,  options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool
```

SceneDelegateの設定を追加した場合、代わりに下記が呼ばれるようになりました。

```
// SceneDelegate.swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
```

よし、これで安心と思いきや、実はトラップがあって上記メソッドはアプリがバックグラウンドにある場合のみ実行されます。
タスクキルした状態でスキーム起動しても、Xcode上でログやブレークポイントが確認しずらいので解決策を見つけるのに苦労しました。

では、タスクキルした状態でどのようにして判定するかというと、以下のメソッドにヒントがありました。

```
// SceneDelegate.swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
```

このメソッドはアプリ起動時に呼ばれるものですが、第３引数の `connectionOptions` に着目してみるとプロパティに

```
open var urlContexts: Set<UIOpenURLContext> { get }
```

`func scene(_:URLContexts:)` の第２引数と同じものが！
ということで、タスクキルした状態でスキーム起動したら入っていました！

まさか、バックグラウンドとタスクキル状態からで処理が異なるとは・・・
Nuxt.js Axios moduleでCORSエラーの優しい対処法

Nuxt.js の Axios を使って API を叩くと`CORS`とか言うエラーが発生した場合の対処法。

（CORS 説明は省かせてもらいます）

Zennに書き直しバージョンあります

https://zenn.dev/mouse_484/articles/nuxt-axios-cors

# 解決方法

```js:nuxt.config.js
modules: [
      '@nuxtjs/axios',
      '@nuxtjs/proxy'
  ],
proxy: {
  '/api': {
    target: 'http://example.com',
    pathRewrite: {
      '^/api' : '/'
    }
  }
}
```

[クロスオリジンリソースを共有するには？](https://ja.nuxtjs.org/faq/http-proxy/)

**は？意味わからん**って思ったあなた僕も同じでした。

これだけ書かれてもなんにもわかりません 🤔🤔🤔

しかも今プロキシ使う場合ちょっと違う方法を使います。このコードは忘れてください。

# とっても優しい解決方法

### 1. Nuxt.js Axios module をのプロキシ設定をオンにする。

```js:nuxt.config.js
axios: {
  proxy: true
},
```

https://axios.nuxtjs.org/options#proxy

### 2. proxy の設定をする

```js:nuxt.config.js
proxy: {
    '/api/': {
      target: 'http://example.com',
      pathRewrite: {'^/api/': ''},
    }
}
```

これで`http://localhost:3000/api`or`http://your.site/api`にリクエストすると`http://example.com`として処理されます。

`pathRewrite`で`api`を消してあげるってのを書かなかった場合`http://example.com/api`になります。

※Nuxt Axios module には Nuxt proxy module が内蔵されています。

### 3. API を叩く

```js
this.$axios.$get("/api");
```

これでさっき設定した`http://example.com`に get リクエストを送っているという事になっていてしっかりとデータが返ってくると思います。

```js
this.$axios.$get("/api/test");
```

のようなリクエストでも`http://example.com/test`として利用できます。

# 終わりに

自分のサイトにリクエストを送ってるのに別のサイトのデータが返ってくるってのに少し違和感を覚えるかもしれませんが、このように設定してあげる事でしっかりと API を使うことができますし、リクエストする URL が短くなって便利だと思います！

最後まで読んでくださってありがとうございます。