OmniAICreator/Qiita-1.07M huggingface dataset:
Anaconda3 + Selenium +ChromeDriver + BeautifulSoupでスクレイピング

RubyでCapybaraを用いたスクレイピングしようとしたところ環境設定がうまくできなくて断念したのでPythonで試すことに

##参考書籍
[Pythonによるスクレイピング＆機械学習 開発テクニック](http://www.socym.co.jp/book/1079)
![alt](http://www.socym.co.jp/wp-content/uploads/2016/ac15a1df2c2dca10a4c215f6096d8892.jpg)
こちらの内容を参考にしながら進めていきました。
ただ2018年9月現在、モジュールなどが最新の場合は一部のサポートが期限切れだったりして（Selenium + PhantomJS　など）、参考書の一部のコードがそのままでは動作しないということがわかったので、そちらをふまえて今回はSelenium + Chromeを用いました。

##動作環境
- MacOS X(筆者はversion 10.13.6)
- Python 3.6.5 :: Anaconda custom (64-bit)
- chromedriver-binary       2.38
- beautifulsoup4            4.6.3
- selenium                  3.14.0


インストール方法は下記
（はじめのころAnaconda3でPython3系を入れていたためpip3などは今回は利用しないで進めました。）

Anacondaのインストールはこちらを参考:
[Anaconda で Python 環境をインストールする](https://qiita.com/t2y/items/2a3eb58103e85d8064b6)

参考書籍では環境設定を主にDockerにイメージを作成してそこでpythonとpipを利用してSeleniumやBeautifulSoupをインストールしていくという流れだったのですが思わぬアクシデントがあったので断念、、、
#####※アクシデントの内容
参考書に沿って進めていき、「pip3のバージョンが古いのでアップデートしてください」というエラーが発生したので、指示に沿って下記のコードを実行したところ
`$pip3 install --upgrade pip`
さらにエラーが続き、調べたところこちらのサイトに書かれた内容と同じ事案のようでした。
[「KOKENSHAの技術ブログ」
 Python pip3 – pip upgradeした後 「cannot import name ‘main’ 」error](https://kokensha.xyz/python/python-pip3-cannot-import-name-main-error-after-upgrading-pip/)
ここにある通りに復旧した後、Anacondaにパッケージを追加していく方向となりました。
####パッケージのインストール
`$conda install selenium`
`$conda install beautifulsoup4`
`$conda install python-chromedriver-binary`

PhantomJSを利用する場合は
`$conda install phantomjs`
でインストールできます。
**※はじめにも書きましたが、書籍のサンプルなどではヘッドレスブラウザとしてPhantomJSを使っていましたがSelenium v3.8.1以降のバージョンではPhantomJSはサポートされていないので今回はChromeを利用しました**

インストールの確認は
`$conda list` で確認できます。


##実践
以下のコードが問題なく動けばOKです！

```python:test.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary
from bs4 import BeautifulSoup
import re #正規表現モジュール

# ブラウザーを起動
options = Options()
options.add_argument('--headless')
# Chromeのドライバを得る
browser = webdriver.Chrome(chrome_options=options)

url = "https://www.carsensor.net/usedcar/search.php?SKIND=1"

# 暗黙的な待機を最大3秒行う(サーバーの負担軽減)
browser.implicitly_wait(3)
# URLを読み込む
browser.get(url)
# htmlを取得
html = browser.page_source
# 「メーカー 車種」選択ボタンをクリック
browser.find_element_by_id('shashuAnc').click()
# HTMLを解析する
soup = BeautifulSoup(html, "html.parser")
# メーカー名/車種名を取得
makers = soup.find_all("a", "js_makerMenu", href="#")
# 項目のなかの不必要なもののリスト
skip_list = ["こだわらない","国産車その他","輸入車その他"] 

for maker in makers:
  # テキスト部分の抽出
  maker = maker.text
  # 正規表現で余分なものを取る
  maker = re.sub(r'\(\d*\)', "", maker) #(数字)
  maker = re.sub(r'\s', "", maker) #空白

  #除外項目をスキップ
  if not maker in skip_list:
    print(maker)

# ブラウザを終了
browser.quit()
```
mysql-connector-python でcommit()が失敗するケース

# 前提
### 使用バージョン
 - python: 3.6.6 (Anaconda)
 - mysql-connector: 8.0.12 ([Anaconda公式](https://anaconda.org/anaconda/mysql-connector-python))

### テーブル構成
 - IDと名前の2つだけのカラム.
 - 既存で1レコードだけデータがある状態とする.

```
MariaDB [mydb]> desc tbl;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

MariaDB [mydb]> select * from tbl;
+------+------+
| id   | name |
+------+------+
|    1 | shio |
+------+------+
```

### DBへの接続方法
 - 接続情報を辞書型変数で宣言して利用する.
 - 変数```conn```でデータベースへの接続を確立する.

```python
import mysql.connector

# DB接続情報
config = {
    'host': 'myserver',
    'user': 'myusername',
    'password': 'mypassword',
    'database': 'mydb'
}
conn = mysql.connector.connect(**config) # DBへのコネクション確立
print(conn.is_connected()) # -> True
```

# 本題
DB書き込みが失敗する場合をケース別に．

### ケース1: コネクション切断後にクエリ実行する場合
(当たり前)

```python
print(conn.is_connected()) # -> True
cursor = conn.cursor() # カーソルを定義

# 実行クエリ1
query = '''INSERT INTO tbl(id, name) VALUES(2, 'koro') ; '''
cursor.execute(query) # クエリ実行
conn.commit() # コミット. (2, koro) のデータは問題なく書き込める．
conn.close() # ここでDBへのコネクション切断
print(conn.is_connected()) # -> False

# 実行クエリ2
query = '''INSERT INTO tbl(id, name) VALUES(3, 'haku') ; '''
cursor.execute(query) # -> Traceback: Lost connection to MySQL server at 'my_server:3306', system error: Connection not available.
# conn.commit()
```
同じようにカーソルを閉じた後にもクエリ実行できない

```python
print(conn.is_connected()) # -> True
cursor = conn.cursor() # カーソルを定義

# 実行クエリ1
query = '''INSERT INTO tbl(id, name) VALUES(2, 'koro') ; '''
cursor.execute(query) # クエリ実行
conn.commit() # コミット. この場合も(2, koro) のデータは問題なく書き込める．
cursor.close() # カーソルのclose
print(conn.is_connected()) # -> True

# 実行クエリ2
query = '''INSERT INTO tbl(id, name) VALUES(3, 'haku') ; '''
cursor.execute(query) # Traceback: Cursor is not connected
#conn.commit()
```

コネクションやカーソルのclose()は最後に行えば良いだけの話．
疑問なのは```cursor.close()```の使い所． 
```conn.close()```ではなくあえてじゃなくて```cursor.close()```を使うメリットがあるケースって？？

### ケース2: SET句で変数を使う場合
こっちが本題

```python
print(conn.is_connected()) # -> True
cursor = conn.cursor() # カーソルを定義

# 実行クエリ
query = '''
    SET @name = 'lemo';
    INSERT INTO tbl(id, name) VALUES(2, @name) ;
    '''
cursor.execute(query) # クエリ実行
conn.commit() # Traceback: Commands out of sync; you can't run this command now
```
> **Commands out of sync; you can't run this command now**
> (= コマンドは同期されていません。このコマンドは現在実行できません)

なんじゃこりゃ．
普通にGUIツールやコマンドラインで実行したら上手くいくクエリ文なのに．
[公式チュートリアル](https://dev.mysql.com/doc/connector-python/en/connector-python-tutorial-cursorbuffered.html)でも特に触れられてない気がする． Issue行き?
select結果を後の代入に使いたい場合， python側の変数に持たせないといけなくてなんだかな〜と．

# おわり
ケース別と言いつつ大してネタは無いという．
他のケースや指摘あればコメントください．
フォルダ共有

# フォルダ共有

## ファイアウォールの設定
Windows ファイアウォールを有効にしたまま、ファイルやプリンターを共有したい
http://faq.epsondirect.co.jp/faq/edc/app/servlet/qadoc?029082

## フォルダの共有設定


# Jenkins
# 共有フォルダのバッチファイル実行

## バッチファイル

```bat
rem remote.bat
rem ------ 定義 ------
set SERVER_PATH=\\192.168.11.7\users\test\desktop
set USERNAME=192.168.11.7\test
set PASSWORD=space
set NETDIR=G:

rem ------ 処理 ------
rem 1. 接続
net use %NETDIR% %SERVER_PATH% %PASSWORD% /user:%USERNAME% /Y

rem 2. 処理
%NETDIR%
call backup.bat

rem 3. 切断
net use %NETDIR% /delete /Y

pause
```

## JenkinsでのWindowsバッチコマンド設定

```bat
cd C:\Users\test\Desktop
call remote.bat
```

Jenkins on Windows の時に、net use を使うとエラーが発生する
http://iwa4.hatenablog.com/entry/2013/11/19/205408
⇒/userの指定に注意
エラーが出たときに解決に向かうための心構え

エラーが出て、
エラーが出て、
エラーが出てどうしようもなくなったとき、
先輩が問題の箇所を突き止めるまでが鮮やかだったので実際に起きた手順をまとめてエラーに立ち向かう心構えとして残しておきます。


ケーススタディ
-

こんなコードがあったとします

```ruby.qiita.rb
class Menu
  attr_accessor :name
  attr_accessor :price
  
  def info
    return "#{self.name} #{self.price}円"
  end
  
  def get_total_price(count)
    total_price = self.price *count
    if count >= 3
      total_price -= 100
    end
    return total_price
  end
  
end

menu1 = Menu.new
menu1.name = "ピザ"
menu1.price = 800

puts menu1.get_total_price(3)
```


１、エラー文をよく読む
-

上のコードを実行すると、下のエラー文が返ってきます。

```
〜/user/index.rb:10:in `get_total_praice`:wrong number of arguments (given 1 , expected 0 ) (ArgumentError)
〜/user/index.rb:23:in `<main>`
```

- エラーが起きている行の特定
- エラー内容の把握

ものによっては、親切なエラーが返ってこない場合もありますが上の２点に着目して情報が拾えるとGOODです！

今回はindex.rbファイルの10行目でArgumentErrorが、23行目でも何かエラーが起きていることがわかりました。

２，特定した情報から、仮設を立てて怪しい所を変えてみる
-

(given 1 , expected 0 ) (ArgumentError)
とありましたので、早速「ArgumentError]について調べてみた所、引数に関わるエラーのようでした。
１与えられているが、０が期待されている。つまり、引数に関わる
- 引数のメソッドの定義
- 引数の呼び出し
どちらかもしくは両方に誤りがあると仮定し、一度引数の表現でない記述に書き直して処理が通るか試してみました。

```ruby.qiita.rb
class Menu
  attr_accessor :name
  attr_accessor :price
  
  def info
    return "#{self.name} #{self.price}円"
  end
  
  def get_total_price
    count = 3
    total_price = self.price *count
    if count >= 3
      total_price -= 100
    end
    return total_price
  end
  
end

menu1 = Menu.new
menu1.name = "ピザ"
menu1.price = 800

puts menu1.get_total_price
```

３，仮設をもとにエラー文の変化に向き合う
-


すると、

```
〜/user/index.rb:11:in `get_total_praice`:wrong number of arguments (given 1 , expected 0 ) (ArgumentError)
〜/user/index.rb:24:in `<main>`
```

エラーの内容に変化はなく、但しエラーが該当する行数が10→11行、23→24行に変わりました。
該当のコードを抜き出してみると

```ruby.qiita.rb
total_price = self.price *count
puts menu1.get_total_price
```
ここでじっくりと問題の箇所を眺めて、問題を探します。
テキストエディタ上は色付いていて問題なさそうですが、ふと、　* の後ろにスペースがないことに気づきました。
これに気付いて直し試した所、無事正しく処理が通りました。

下記が正しいコードとなります。

```ruby.qiita.rb
class Menu
  attr_accessor :name
  attr_accessor :price
  
  def info
    return "#{self.name} #{self.price}円"
  end
  
  def get_total_price(count)
    total_price = self.price * count
    if count >= 3
      total_price -= 100
    end
    return total_price
  end
  
end

menu1 = Menu.new
menu1.name = "ピザ"
menu1.price = 800

puts menu1.get_total_price(3)
```

まとめ
-
基本的にエラーメッセージが返ってきた時、初心者にとっては完全に未知の返答である可能性が高いですが、
１，エラーメッセージ１文字１文字にきちんと向き合うこと
２，不足分は仮設を立てて検証を試し、新しいヒントを取りに行く
３，これを解決するまで繰り返す


今後エラーに立ち向かう時、心構えとして共にあらんことを。
（この考え方、姿勢を胸に勉強を続けてまいります。）

今日はこのあたりで失礼します。
Elastic Beanstalkの環境を一時停止する (2018年版)

# やりたいこと

Elastic Beanstalkでしばらく使わない環境があるので、EC2を落としておきたいのですが、後で復活するので環境は削除したくない。

# 試したこと

## eb stopコマンド (→NG)

だいぶ古い記事に書いてあった。
https://qiita.com/Hiroyama-Yutaka/items/ca875629c283ae062483

```bash
$ eb stop
usage: eb (sub-commands ...) [options ...] {arguments ...}
eb: error: unrecognized arguments: stop
```

EB CLI 3.0 にはそんなサブコマンドがないと怒られる。

## 環境の設定から容量の変更 (→NG)

![ImagineCheck production   設定.png](https://qiita-image-store.s3.amazonaws.com/0/7519/87dd4e83-17d7-33f6-c66c-deadbc6ebae6.png)

あえなく撃沈。
![ImagineCheck production   設定 (1).png](https://qiita-image-store.s3.amazonaws.com/0/7519/0e5f6dbe-459e-128e-6675-5a0ee1b6ff02.png)

## オートスケーリンググループを直接編集 (→OK)

Elastic Beanstlkで作った環境には、自動的にオートスケーリンググループが作成されているので、そいつを直接編集します。念のため、タグで環境名を確認しつつ...
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f373531392f62313038306338322d373831312d653938322d356231322d6438626435666235363366332e706e67  1596×974 .png](https://qiita-image-store.s3.amazonaws.com/0/7519/ef2f7324-698d-0b2f-20ab-10de6abc2bd8.png)

全部0インスタンスに設定を変更します。
![EC2 Management Console (6).png](https://qiita-image-store.s3.amazonaws.com/0/7519/5cfb1075-8ba9-aea5-0aa5-1b9597cc62c7.png)

どうやら無事止まったようです。
![ImagineCheck production   ダッシュボード.png](https://qiita-image-store.s3.amazonaws.com/0/7519/c7583132-56f6-d244-1c1d-81853c8a44fc.png)

これで勝手にアップしたりしないか、しばらく様子を見てみます。
Ruby版automatic field initialization？

# Rubyのinitialize

```ruby:init.rb
class User
  attr_reader :name, :income
  def initialize(name, income)
    @name = name
    @income = income
  end

  def real_user?
    @income > 10_000_000
  end
end
```

これを

```ruby:init2.rb
class User
  attr_reader :name, :income
  def initialize(@name, @income)

  def real_user?
    @income > 10_000_000
  end
end
```

こんなふうに書きたいというのはRuby（に限りませんが）を書いていると考えたことがあるかと思います

参考：http://melborne.github.io/2013/09/27/auto-attr-set-in-ruby/

# やりました

ご存知の通りRubyの自由度は高いです
なので、なんとかできないかと試してみたところ ……

```ruby:auto_init.rb

class Hoge
  extend AutoInit
  def_initialize :arg1, :arg2
  
  def show
    p [@arg1, @arg2]
  end
end

hoge = Hoge.new 1, 2
hoge.show # => [1, 2]

```

できました

…… はい、見ての通りクラスマクロ的ななにかです
def initialize ではなく def_initialize という名前のクラスメソッドですね

せっかくなのでさらについでに

```ruby:auto_init2.rb
class Fuga
  extend AutoInit
  def_initialize :arg1, :arg2 do |arg3|
    @arg3 = arg3.upcase
  end

  def show
    p [@arg1, @arg2, @arg3]
  end
end

fuga = Fuga.new 'hoge', 'fuga', 'piyo'
fuga.show # => ["hoge", "fuga", "PIYO"]
```

こんなふうにただの代入以外にもなにかしたい場合にも対応

# 実装

```ruby:auto_init_module.rb
module AutoInit
  def def_initialize(*names)
    class_eval do
      define_method :initialize do |*args|
        names.each { |name| instance_variable_set("@#{name}", args.shift) }
        instance_exec(*args, &proc) if block_given?
      end
    end
  end
end
```

こんな感じです、これだけです
def_initialize実行時点でinitializeをdefine_methodで定義しています

試してみたらできたといった感じかつやや黒魔術風味なので、変なバグがありそうな気もします
今の所わかっているのは、ベースがProcであるため、変数が足りないor多い場合もエラーにならず通ってしまうことくらいですか

なんやかんやすればなんとかなるとは思いますが、ちょっとした思いつきにそこまでする気力がありませんでした …… なのでgemにしたり等の予定はないです

お付き合い、ありがとうございました
Windows端末から.localの名前(mDNS)でPuTTYやTera TermでSSHできない場合はBonjourを入れると解決するかもしれない

Mac OS端末やavahiを導入したLinux端末では、xxx.localというローカルネットワークでのみ有効なホスト名が提供されます。
他のLinux端末からは`ssh xxx.local`とするとsshすることができますが、Windows端末からPuTTYやTera Termを利用してSSHを試みるとホストが見つからないというエラーになる場合があります。

そんなときは、Appleが提供するBonjourを導入すると解決する可能性がありますので、お試しください。
https://support.apple.com/ja-jp/bonjour

xxx.localという名前はmDNSという仕組みで動くもののようです。
BonjourはmDNSの機能を提供しているため、インストールするとxxx.localという名前で別端末にアクセスが可能になるそうです。
Windows10にも標準でmDNSの機能があるようで、PowerShellなどで名前解決は可能ですが、PuTTYやTera Termではうまく動作してくれないようです。

## 参考URL
- https://barbarossa.no-ip.org/wp/?p=1370
Unity 異なるシーンで変数を共有する簡単な方法

Unity初心者のメモ

私がOculus Goで動くコンテンツを作成していて、「ゲームシーンで保持しているスコアをリザルトシーンに出したい！」と思ったときに実践した方法です。
なおC#で記述しております。

# やり方
共有する変数を ``` static public ```で宣言します。簡単。
例えばゲームシーンでスコアを計算し、ゲームが終わったらリザルトシーンに遷移してスコアを表示するようにします。

```c#:Game.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Game : MonoBehaviour {
  public static float score = 0;       // スコア

  void Start () {
  }
	
  void Update () {
　　// コントローラーのトリガーを押したらスコアが加算される
    if(OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger)){
      score += 100;
    }
  }

  public static float getScore(){
    return score;
  }
}
```

コントローラーのトリガーが押されたら100スコアが加算されるとします。
``` public static float score ```で共有したい変数を宣言し,
値を取得する用のメソッドを``` public static float getScore() ```のように記述します。

```c#:Result.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Result : MonoBehaviour {
  
  void Start () {
    // ログ出力
    Debug.Log("Score: "+ Game.getScore());
  }
	
  void Update () {　
  }
}
```

参照したい別のシーンのクラスでは、``` Game.getScore() ```のようにクラス.メソッドの形でアクセスすれば、100ずつ加算された結果を参照することが出来ます。


# 注意
複雑な構造の場合や、色々な箇所から参照される場合には注意が必要です。
「クラス変数」にしたため、インスタンスを生成せずとも参照できてしまうので、他のすべての参照している箇所に影響が出ます。
単方向への参照など、シンプルな場合に使うのが良いです。
ESDocを使ってJSDoc形式のコメントからドキュメントを自動生成する

[ESDoc](https://esdoc.org/)を使えばJSDoc形式で書いたコメントからドキュメントをhtml形式で自動生成できて大変便利である。以下に設定方法を記す。

## esdoc と esdoc-standard-plugin を開発用にインストール

yarn を使った場合

```shell
yarn add -D esdoc esdoc-standard-plugin
```

## 設定ファイルの作成

package.json と同じディレクトリに「.esdoc.json」ファイルを以下の内容で作成。

```.esdoc.json
{
    "source": "./src",
        "destination": "./docs",
        "plugins": [
    {
        "name": "esdoc-standard-plugin",
        "option": {
            "test": {
                "source": "./src"
            },
            "manual": {
                "files": [
                     "./manual/manual_1.md",
                     "./manual/manual_2.md",
                     "./manual/manual_3.md"
                 ]
            }
        }
    }]
}
```

「manual」で指定したmarkdownファイルをもとに一つのhtmlページが作られるのがとても便利。

## 同じディレクトリに「README.md」を作成

この「README.md」が作成されるドキュメントの index.html となるのでどうしても必要。ここにドキュメントの概要を書く。

## package.json の script に実行コマンドを追加

```package.json
"scripts": {
    "docs": "esdoc",
}
```

実行すると、jsファイル内のJSDoc形式のコメントからクラスやメソッドの詳細仕様書がhtmlで作成される。非常に便利である。
ずんだの縦読み問題 php編

てぃーびーさんの[ずんだの縦読み問題](https://qiita.com/tbpgr/items/90abccf8297be0e42f8c)
をPHPで実装しました。
（結構愚直な実装です。）

## PHP
```php

$tweet = "
忙しくてついったいじれない
さみしい
つらい
";

$tweetExplode = explode("\n", $tweet); 
$tweetTrimmed = array_map('trim', $tweetExplode);

foreach($tweetTrimmed as $val){
    echo mb_substr($val, 0, 1, 'utf8');
}
# => 忙さつ
```
Ruby4ます連算

```:ruby
a=gets.to_i;
b=gets.to_i;
puts [a+b,a-b,a*b,a/b].join(" ")
```
参考
https://www.amazon.co.jp/4%E3%81%BE%E3%81%99%E9%80%A3%E7%AE%97-%E5%9F%BA%E6%9C%AC%E7%B7%A8-%E5%B1%B1%E7%94%B0%E5%B9%B8%E5%AD%90/dp/405304796X
Pythonには、Pythonの立場がある

pythonにおけるイコール(=)は、代入ではない。
>Assignment statements in Python do not copy objects, 

インタープリタ設計するときに代入なんて概念を持ち込まない。
pythonの場合、プログラムを入力した時点でオブジェになる。
コンパイラ設計の場合、メモリー・レジスタ間の代入つまりLOAD/STORE/MOVEが存在する。
pythonの立場で考えると「浅いコピーおよび深いコピー」論争は、なくなる。
また、Pythonの値渡しと参照渡しの論争は、なくなる。

```
a=123
```
と書いた場合、123という整数のオブジェにaというエリアスをつけるという意味です。

+ オブジェクトとは、MITで発展したオブジェクト指向
+ オブジェとは、ソルボンヌで発展したオブジェクト指向

```
b=a+1
```
a+1 というオブジェにbというエリアスつけるといういみです。
+ エリアスとは、名前みたいなもの
もともとaliasとは、ファイルのコピーを作らないで名前を付けたのが始まりで別名と訳した。
>訳した人は、死んじゃったので言うけど日本語にシステムエンジニアという言葉追加した人。プログラマという呼び方嫌いだった。

+ オブジェとは、つかみどころのない物を表しています。

```
p=print
for i in range(5):　p(i)
p('Hello world')
```
printというオブシェにpというエリアスをつける
実行結果は、

```
0
1
2
3
4
Hello world
```
# pythonには、pythonの立場がある
GoogleCloudNext in Tokyo '18に参加した

## 前提
Googleが提供するクラウドサービスの展示会に参加してきたのでレポートを書きました。
非エンジニア向けに社内用に書いたのですが、一部修正して公開します。
[GoogleCloudNext in Tokyo '18](https://cloud.withgoogle.com/next18/tokyo)

## GoogleCloudNext in Tokyo '18参加レポート

GCPの対抗馬であるAWSを普段使っている自分がGoogleのカンファレンスに行って感じたことを紹介します。

キーワードは `ハイブリットクラウド` でした。
Googleは企業にGoogleのクラウドサービスをどう提供できるのかを考えています。
ただ、新規のサービスに比べて既存サービスの方が何十倍も多いのが実情です。
既存サービスはそれぞれに巨大なシステムが存在し、Googleのサービスにリプレイスをするのは余程のメリットがなければ行えません。
そこで、Googleが提案していたのは既存システムとの併用を提供することでした。
多くのセッションでGoogleのクラウドサービスと既存のシステムの併用ついて扱っていました。それがハイブリットクラウドです。 
ハイブリットクラウドの一例として提案していたのはGoogleが強みとしている分析ツールのBigQueryを導入する事例です。
分析ツールは基幹システムと分離して考えることができますし、既にある分析ツールと平行運用することも可能です。

昨今のシステムエンジニアはクラウドサービスの特性を見分けて、より最適化されたシステムを組み上げるスキルが求められています。
ウチの会社ではAWS、GCP、オンプレと様々なコンピュータリソース環境が混在しており、そのどれもにメリット・デメリットがあります。
自分の担当だけでなく他のクラウドサービスで何が出来るのかを常にインプットし続けることが重要だと感じました。
Line Loginで言語指定をする

# Line Loginページの言語を変更したい
※仕様が見つからなかったので対処療法的ですが
例としてLine Loginの認可画面の言語を英語に変更したい場合、URLの引数に `lang=en`を追加すると英語になる
langに渡す値はLineホームページで言語指定したときのURLを使えば良さそうです。
指定言語が`English(US)`だったときのURLが`https://line.me/en-US/`の場合は`lang=en-US`

### 日本語
![Before](https://qiita-image-store.s3.amazonaws.com/0/217834/7448b5df-52c9-ffe3-0c09-5a0184c9f2af.png)

### 英語
![After.png](https://qiita-image-store.s3.amazonaws.com/0/217834/9ba0a81d-32ec-cea3-11bd-fe73268a712a.png)



`ui_locales`ではないのか。。。
`.well-known/openid-configuration`も使えないらしい。。。
RailsでDXOpalを使ってみた

# はじめに

[DXOpal](https://github.com/yhara/dxopal)というブラウザで動作するゲームライブラリをRailsで動かしてみたときの備忘録です。

![dxopalonrails.gif](https://qiita-image-store.s3.amazonaws.com/0/191521/cde8054d-bfc7-1098-5a4d-305655d61104.gif)


# やったこと
## Railsアプリの作成

まず、`rails new`でアプリのひな型を作成

```shell-session
rails new dxopal_rails --webpack=vue
```

今後、SPAやPWAにすることも考慮に入れて、`--webpack=vue`を追加している。

あとは、実際のゲーム画面を表示する`view`と`controller`を作成。

```shell-session
rails g controller game index
```

その後、作成した`game_controller.rb`を下記のように修正。

```ruby:game_controller.rb
class GameController < ApplicationController
  def index
  end

  def main
    main = File.open('./app/views/game/main.rb')
    source = main.read
    render json: source
  end
end
```

`main`というメソッドを追加し、そこでゲームのソースコードを読み取ってJSON形式で展開させている。

最後に、`routes.rb`を編集して、`game/main`へのルーティングを設定する。

```ruby:routes.rb
Rails.application.routes.draw do
  get 'game/index'
  get 'game/main'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
```

とりあえず、これでDXOpalが動くひな型はできた。
次に、DXOpalの導入を行う。

## DXOpalの導入

まず、`gem install dxopal`で`DXOpal`をインストール。

```shell-session
gem install dxopal
```

次に、`app/views/game`ディレクトリまで移動し、`dxopal init`を実行する。

```shell-session
dxopal init
```

その際、`index.html`と`dxopal.min.js`と`main.rb`が作成される。
`index.html`の中身を`index.html.erb`内に貼り付けて、以下のようにする

```erb:index.html.erb
<h1>Game#index</h1>
<p>Find me in app/views/game/index.html.erb</p>

    <script type="text/ruby">
      DXOpal.dump_error{ require_remote 'main' }
    </script>

    <canvas id="dxopal-canvas"></canvas>
    <div id="dxopal-errors"></div>
```

`dxopal.min.js`は`app/assets/javascript`内へ移動させて、`application.js`を以下のように書き換える。

```js:application.js
//= require rails-ujs
//= require activestorage
//= require dxopal.min
//= require turbolinks
//= require_tree .
```

最後に、`DXOpal`を`Gemfile`に追加し、`bundle install`を行う。
僕の場合、`thor`のバージョンでエラーが起きていたので、下記のように修正し、`bundle update`と`bundle install` をそれぞれ実行したね。

```:Gemfile
gem 'dxopal'
gem 'thor', '>= 0.19.1'
```

# おわりに

最後に、Railsのサーバーを建てればOK！

```shell-session
rails s
```

これで`DXOpal`をRails上で実行できるようになった。

このとき作ったサンプルはこちらからダウンロードできる。
[DXOpalOnRails](https://github.com/S-H-GAMELINKS/DXOpalOnRails)

# 参考資料

[yhara/dxopal](https://github.com/yhara/dxopal)

[https://yhara.github.io/dxopal/](https://yhara.github.io/dxopal/)
mysqliの場合のトランザクション

mysqliの場合のトランザクション

```
$mysqli->begin_transaction();

$query = "DELETE FROM ...";
$result = $mysqli->query($query);

$query = "INSERT INTO ...";
$result = $mysqli->query($query);
if (!$result) {
    $mysqli->rollback();
    exit;
}

$mysqli->commit();
```
PandoraFMS用URL監視プラグインモジュール自作(大したことしてない)

こちらの[URL](https://pandorafms.jp/download/20160226-PandoraFMS-OSC2016-TokyoSpring.pdf)を参考にしました。

参考URL内の設定は接続可否のチェックなので、Shellコマンドを以下のように変えて設定。

~~~sh:httpステータスを確認するcurlコマンド
$ curl -I -s https://example.org | head -1 | cut -d" " -f2
~~~

要点は以下の通り。

+ HTTPヘッダのみ表示。
+ プログレスメータは表示しない。
+ headコマンドに-1オプションを付けてHTTPヘッダの1行目だけ表示させる。
+ cutコマンドで2つ目のフィールドだけ取得する。

こいつを参考URLの`プラグインコマンド`、`プラグインパラメータ`に分解して組み込みます。

~~~sh:プラグインコマンド
/bin/sh
~~~
~~~sh:プラグインパラメータ
 -c 'curl -I -s _field1_ | head -1 | cut -d" " -f2'
~~~

これでHTTPステータスが取得できます。
パラメータマクロとして、\_field1\_にURLがマッピングされます。

モジュールコンポーネント設定は以下の通り。

+　`種類` Generic Numeric
+　`警告状態 最小:最大` 400:499
+　`障害状態 最小:最大` 500:599

400番台を警告、500番台を障害にしました。
その他設定も可能かもしれませんが、とりあえずやりたいことがこれで事足りるので
これでいいかな、ってな感じです。

簡単にHTTPステータスチェックのモジュール作成ができました。

PandoraFMS、結構楽ですよ。
SAS Viyaにおける元データの種類

SAS ViyaはAIプラットフォームになります。Webブラウザ上で機械学習の設計、実行ができるStudioという環境も用意されていますが、開発者はプログラミングコードで開発することも可能です。デモ版ではJupyter Notebookが使えて、簡単に使い方を学べるようになっています。

今回はSAS Viyaで利用できる解析元データの種類について解説します。

## CSVファイル

CSVファイルは `upload` メソッドを使ってSAS Viyaにテーブル登録できます。

```py
out = sess.upload('Data/iris.csv')
```

## HTML

HTMLのテーブルから情報を読み込むことができます。 `datamsghandlers` というライブラリを読み込みます。

```py
from swat.cas import datamsghandlers as dmh
```

そしてHTMLを読み込みます。

```py
htmldmh = dmh.HTML('Jupyter_Saved_Work/Data/bank.html')
```

## Excel

CSVと同じようにExcelファイルを読み込めます。

```py
exceldmh = dmh.Excel('Jupyter_Saved_Work/Data/disaster_cty_list_ytd_14.xls')
```

## データベース

外部データベースからデータ読み込みもできます。この場合、PythonのDB-APIを使いますので、SQLiteやMySQL、PostgreSQLなど幅広いデータベースと連携できます。

```py
dmh.SQLTable.create_engine('sqlite://path/to/database.sqlite')
```

----

データソースとしてHTMLを使うのは面白いです。Web API化されていないデータソースを扱う際などに便利です。また、データベース化されていないCSVやExcelファイルを取り込むこともできるので、過去の資産を機械学習で分類したいといった時にもSAS Viyaが活躍するでしょう。

[SAS for Developers | SAS](https://developer.sas.com/home.html)
【Azure】AzureMediaServicesでライブストリーム配信

# はじめに
Unityで動画のライブストリーム配信をやろうと思って色々調べる中で、AzureMediaServicesで簡単に出来ることが分かったので、需要が少ないのは理解していますが備忘録として手順を残しておきます。
(色々と問題があるため最終的には使ってないので、残しておかないとロストテクノロジーになってしまう)

# 注意
本記事ではAzureサービスを利用するため、手順を実行すると多少のお金がかかります。

### 対象読者
・Azureもサーバも殆ど触ったことない
・何故か自前でライブストリーム配信システムを組む事を強いられている人

### AzureMediaServicesとは
すごく簡単に言うと、1からメディアサーバ作る手間をかけずに、ポチポチ作業だけで簡単にできますよっていうサービスだと思う。

### 構成
今回試した構成のポンチ絵
![1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/e858f54b-02d9-1a07-605e-19a989a8eb4e.png)

# 作業
# Azure Side
### リソースグループ作成
Azure上のフォルダみたいなもの。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/216921/b6074d91-fbce-64b2-1354-9d0455d70bee.png)

### MediaServices作成
MediaServicesとStorageAccountを作る

![3.png](https://qiita-image-store.s3.amazonaws.com/0/216921/e4f74ac3-c555-1870-cf78-e8eeddf55257.png)
![5_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/4fbf88dd-88ce-3f36-d02a-c29329d79b30.png)

### ライブイベントの開始
![6_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/1b774281-93a8-8d0d-1c5d-f6a3ab3debab.png)
![7_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/9860dc67-355b-bb8c-e977-fdf5cec1afd8.png)
![9.png](https://qiita-image-store.s3.amazonaws.com/0/216921/0a605f25-565e-083a-d734-566cfd360ff5.png)
![10_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/422502ef-ca04-9302-94ac-e733dceb819e.png)
![11_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/cce95069-925f-99dd-4f1b-472e6282fb82.png)
![12_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/322fb529-40d8-0eaf-2646-5a3fb7eae626.png)
![13_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/817fdcda-ec9e-748f-8a39-f18b5ea28d7d.png)

取り込みURL(プライマリ)のアドレスをコピーしておく
![14_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/3c3c0edd-d7dc-79e3-a924-40b566f27e52.png)

この時点ですでに放送の準備は完了しているため、ここからはOBSで実際に映像を配信する設定を行う

# OBS Side
### 配信の設定

先ほどコピーしたURLを以下に張り付けて、適当なストリームキーを入力する
![15_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/838782e8-bf12-f462-de65-3f969019478a.png)

画面の構成はOBSそのものの説明なので省く。よしなにやってほしい。
配信開始を押下する。
![16_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/badd7049-d5a5-e24d-812a-c25506ef4d22.png)

# 動作確認
Azureに戻って、以下の通りライブイベントの視聴を選択するとOBSから配信した映像がそのまま再生される。
![17_1.png](https://qiita-image-store.s3.amazonaws.com/0/216921/0b38ea06-efda-dc7d-875d-d223411d120d.png)

# 後片付け
AzureMediaServicesでライブイベントを実行中は分単位で課金されるため、用が済んだら停止しておくことを忘れないように注意
AE JSONデータがエラーではじかれる　（ドツボにハマった事例）

#やりたい事
AEのエクスプレッションの数値などjsonファイルで制御
しかし出来ない・・・
jsonファイルインポートエラーではじかれる・・・

#めちゃめちゃ解決に時間がかかりました。

ネットで落ちているJSONファイルはインポート出来るのに、自分で作成したファイルはインポートできない事態になっておりました。

まずdreamweaverで作成したjsonが何故エラーかと言いますと、dreamweaverは"（ダブルクォーテーション）を打つと自動的にブラケットを閉じる為 " "二個自動で付きます。
extendscriptをやってるとそんな機能が無いので自分で "string"とダブルクォーテーションを２つ打ちます。
その癖で""とdreamweaver上で打つと　 " " " ３つ付いている事になります。また厄介な事にdreamweaver上では間の二つ目のダブルクォーテーションが見えなくなってしまいます。
だからエラーを吐かれてもどこが間違っているのかわからない状態になってしまいました。
設定方法を教えてもらったが、ちょっとAEのJSONを書くのには別のテキストエディタnote++を使う事にします。。。

はぁー。変な事に時間を費やしてしまいました。。。

#基本的な使い方
###JSONデータの書き方はこう。

sample000.json

```json
{
	"name":"youtool",
	"sex":"male"
}

```

###AEでの使い方はこう。
dataValue または　sourceData
どちらかでデータを取ってこれる。
dataValue は配列で呼ぶ
sourceDataは文字列で呼ぶ（多分そんな感じ）

```jsx
//sample000.jsonには配列として[0][1]しかないから単純ですね。
footage("sample000.json").dataValue([0]);//これでyoutoolの名前が取れます。
footage("sample000.json").dataValue([1]);//これで生別のmaleが取れます。
//sourceDataで取得する場合は
footage("sample000.json").sourceData.name
footage("sample000.json").sourceData.sex

//今テストでやったらこういう形でも取得出来た
footage("sample000.json").dataValue([name]);//これでもデータ取れました。
```

#JSONデータのパターン参考
###その１
sample001.json

```json
{
	"person":{"name":"youtool","sex":"male"},
	"person01":{"name":"yamada","sex":"female"}
}
```

```jsx
footage("sample001.json").dataValue([1,0])//yamadaが取れる
footage("sample001.json").sourceData.person01.name//yamadaが取れる

```

###その２
sample002.json

```json
{
	"persons00":[
		{"name":"youtool","age":35},
		{"name":"yamada","age":28}
	],
	"persons01":[
		{"name":"hanako","age":8},
		{"name":"tarou","age":3},
		{"sub":[
			{"name":"kaori","age":23},
			{"name":"kanako","age":18}
		]}
	]
}
```

```jsx
footage("sample002.json").dataValue([0,0,0]) //youtool
footage("sample002.json").sourceData.persons00[1].name //yamada
footage("sample002.json").sourceData.persons01[1].name //tarou
footage("sample002.json").sourceData.persons01[2].sub[1].name //kanako
footage("sample002.json").dataValue([1,2,0,0,1]) //23
```


ちなみにjson内に改行コードを入れたい場合は
「//n」で改行出来ます。

```json
"text" : "この後に改行コード\\n入った！！"

//result
この後に改行コード
入った！！
```
BitBucketでGoogleの認証を使うとcloneの時に聞かれるアカウント名とパスワードがわからない話

# どんなことが起きたか
BitBucketでログインをする際に、Googleアカウントを利用できるみたいなので、軽い気持ちで、ぽちっと押してログインをした。

cloneをするときに、メールアドレスとパスワードを聞かれたのだが、そういえば…パスワードってなんだ？と思い、GoogleアカウントでログインをしたからGoogleアカウントのメールアドレスとパスワードを入力すれば入れるかな？と思って入力したものの、入れない。

# 解決策

[https://bitbucket.org/account/password/reset/](https://bitbucket.org/account/password/reset/)にアクセスをしてパスワードを再設定する。その際に、メールアドレスの入力を求められるが、これはログイン中のGoogleアカウントで利用しているメールアドレスを入力する。

メールに記述されているURLを開き、パスワードを設定すれば、Googleアカウントのメールアドレス+設定したパスワードでログインできる。

とりあえず、これで解決するのだが、Googleアカウントでログインした際の一番最初のパスワードの状態についてご存知の方がいれば教えてください。
RuboCopエラー対応（Layout/EmptyLineAfterGuardClause）

# はじめに

Rails（Ruby）環境でコーディングをしていた際に、RuboCopでこんなエラーが出ました。

一部抜粋 & 編集

```bash
app/decorators/file_name.rb:63:5: C: Layout/EmptyLineAfterGuardClause: Add empty line after guard clause.
    return something if method.nil?
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

## RuboCop とは?

Rubyのコードを整形してくれるやつです。

> RuboCop is a Ruby static code analyzer and code formatter

https://github.com/rubocop-hq/rubocop

自分が今回書いたコードの中身は、早期リターンを入れたelse付きの後置if文です。

```ruby
def method_name
  return "something" if method_A.nil?
  method_B(引数)
end
```

コードの内容は単純で、`method_A` の中身が `nil` だったら文字列 `"something"` を返し、そうじゃなければ、`method_B(引数)`を実行する。という内容です。

## 早期returnとは？

> あまり起きないケース、あるいは重要でないケースでifのネストを深くしたり、else句を使うのを避けるためのテクニックです。

引用
https://qiita.com/n_slender/items/e062454114facd00a942

# RuboCopのエラーメッセージとその内容

上記コードでも動くのですが、`RuboCop` 的には正しくありません。

その時のエラー文が

```bash
app/decorators/file_name.rb:63:5: C: Layout/EmptyLineAfterGuardClause: Add empty line after guard clause.
    return something if method.nil?
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

でした

# どう対応したか？

以下のようにコードを書き換えました。

```ruby
def method_name
  return "something" if method_A.nil?

  method_B(引数)
end
```

# なぜ、こう対応したか？

エラー文

```
Layout/EmptyLineAfterGuardClause
```

で、ググると、`RuboCop`の公式ドキュメントが出てきます。

参考
https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Layout/EmptyLineAfterGuardClause

このページのOverviewには下記のように書いてあります。

> This cop enforces empty line after guard clause

「このコップ（警察）は、ガード節の後には空行を必ずいれとけ」と、言っています。

なので、空行を入れました。

## ガード節とは？

> 処理の対象外とする条件を関数やループの先頭に集め、早めに return や continue/break で抜ける方法です。ネストを減らし異常系と正常系の処理がわかりやすくなるメリットがあります。

引用
https://qiita.com/kouyan/items/7b8b456b626447a1e24e

<img width="677" alt="スクリーンショット 2018-09-27 17.23.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/14191/a73b4c8b-1840-2a8c-bc57-562ed4a12286.png">

なので、ガード節の下に空行入れました！

今日は以上です！

# 参考

- https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Layout/EmptyLineAfterGuardClause
- https://sakanasoft.net/rubocop/
M5StackでJPEGの画像表示に手間取った話(micropython)


# TL;DR

* M5StackでJPEG画像が表示できず詰まってた話。
* 原因はJPEGの形式がグレースケールだったからというなんともな話。
	* 残念ながら対応してないっぽい
* バージョンはmicropythonのfirmware4.0.0で起こってました。
* Arduinoでは試していないです。


#ことの始まり
M5Stackのfirmwareをmicropythonに入れ替えまして、コードをガシガシと書いていこうと思いとりあえず液晶に何か表示がしたいと思い簡単にスクリプトを書いてみたところこれが動かなくて七転八倒してました。

## 書いたコード

```main.py
from m5stack import lcd
import uos

uos.mountsd()
lcd.clear()
lcd.image(0, 0, "/sd/text.jpg", 0, lcd.JPG)
```

この様にmicrosdカードにjpegの画像を置いてそれをlcd上で表示するという非常にシンプルなコードです。しかし、これが動かない。

## 試したけど効果がなかったこと
* firmwareが書き込めているのか試してみる
	* そもそもpythonが動いているのか？
		* ターミナルからつないでみたらちゃんと動いてた
* lcdが壊れていないか確認する
	* `lcd.print`を利用して表示する
		* 表示出来た
* OSのバージョンを片っ端から試してみる
	* エラーがどこに出てるか解らなかったので闇雲に
		* [github](https://github.com/m5stack/M5Cloud/tree/master/firmwares)にあった`3.9.8`, `3.9.9`, `4.0.0`をそれぞれ試す
			* 効果なし 

## 試したら効果があったこと
* 画像を変えてみた
	* 変更した画像は表示ができた

ということで、入れてた画像が悪かったのですが、何が悪かったのか見た目には解らなかったです。どちらも同じjpegに見える…というわけで`identify`コマンドを使って比較をしてみました。

```
sh-3.2$ identify images/image.jpg
images/image.jpg JPEG 550x370 550x370+0+0 8-bit sRGB 293925B 0.000u 0:00.000
sh-3.2$ identify images/text.jpg
images/text.jpg JPEG 320x240 320x240+0+0 8-bit Gray 256c 10369B 0.000u 0:00.000
```

怪しそうなのはsRGBとGrayの辺りですね。
というわけで、ImageMagickを使ってに変換をかけてみました。

```
$ convert text.jpg -type truecolor text_true.jpg
```

 変換後のファイルをsdに置いて実行したところ無事表示することが出来ました。

# まとめ
なんだかんだで表示が出来たのですが、まさかこんなところでハマるとは思っても見なかったです。カラー液晶がせっかくあるんだから、最初からカラーにしておけば引っかからなかったかもしれないなぁと思うと非常に残念
JavaScriptとrubyの基礎的な部分の比較をしてみた

#はじめに
最近JavaScriptを勉強しているので普段使っているRubyとの書き方の違いについてまとめて見ました。

#変数
ruby・・・スネークケース
JavaScript・・・キャメルケース

```ruby:ruby
user_name = 'bob'
```

```javascript:javascript
var userName = 'bob';
```

```javascript:es6
let userName = 'bob';
```

#定数
原則としてruby・JavaScript共に全て大文字で、単語はアンダースコアで区切る。

```ruby:ruby
HOGE = "hoge"
CONSUMPTION_TAX = 1.08
```

```javascript:javascript
const HOGE = "hoge";
const CONSUMPTION_TAX = 1.08;
```

#メソッド・関数の定義
rubyのメソッド名はスネークケースで定義します
JavaScriptの関数名はキャメルケースで定義します。

```ruby:ruby
def get_triangle_area(bottom, height)
  bottom * height / 2
end

#呼び出し
get_triangle_area(100, 50)
```

```javascript:javascript
function getTriangleArea(bottom, height) {
  return bottom * height / 2;
};

//呼びだし
getTriangleArea(100, 50);
```
###JavaScriptのアロー関数について
functionの代わりに「**=>**」を使うことができる。

```javascript
let getTriangleArea = (bottom, height) => {
  return bottom * height / 2;
};

//呼び出し
getTriangleArea(100, 50)；
```

関数の中身が1行の場合、{...}とreturnを省略できる。

```javascript
let getTriangleArea = (bottom, height) => bottom * height / 2;
```
引数が１つの場合引数の()を省略できる。

```javascript
//円の面積
let getCircleArea = radius => radius * radius * Math.PI

//呼び出し
getCircleArea(10);
```
引数の無い場合の()は省略不可

```javascript

let hello = () => console.log("hello world");

//呼び出し
hello();
```

#式展開
rubyは#{}で囲う

```ruby:ruby
name = 'bob'
puts "hello! #{name}"

>hello! bob
```

JavaScriptは`（バッククオート）で文字列を囲み、${}を使用する

```javascript:javascript
let name = 'bob';
console.log(`hello!! ${name}`);

> hello! bob
```

#終わりに
記事を最後まで読んでいただきありがとうございます！何かご不明点やご指摘あれば、コメントいただけると幸いです(^_^)

#参考
[JavaScript本格入門](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88JavaScript%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E3%83%A2%E3%83%80%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AB%E3%82%88%E3%82%8B%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E7%8F%BE%E5%A0%B4%E3%81%A7%E3%81%AE%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/477418411X)
Rails newでMySQL指定する方法(MySQL ver.8.0)

# 個人的メモ
MySQL ver.8.0 の時のrailsの情報が少ないためQiitaでも作成
個人wiki https://hackmd.io/s/SkTtlb9FX

## ステップ1 MySQLでuser作成

コマンドラインでMySQLにrootログインし、新規user作成
nameとpasswordは任意
mysql_native_password指定する事が大事


```bash=
mysql>$ create user 'name'@'localhost' identified with mysql_native_password by 'password'
```

## ステップ2 rails new

任意のディレクトリ内で

```bash=
$ rails new アプリ名 -d mysql
```
  
次の2項目をステップ1で作成したものに変更

```yaml=
$ sudo vi ./config/database.yml
username
password
```

## ステップ3 DB作成&migratre

```bash=
rake db:create:all
rake db:migrate
```
Dockerイメージが「No such image」エラーで削除できない時

# TL;DR

なぜか`Error: No such image:`と表示されて削除できない時、**リポジトリ＋タグ指定**だと削除できました。

# どゆこと？

あるはずのイメージが「ない」と言われる自体が発生。
もちろん　`-f`も効かず。

```bash

# "docker_web"イメージを消し去りたい。
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker_web          latest              dad996f63f1c        3 hours ago         1.14GB
ruby                2.3                 3d2218e08844        6 days ago          941MB
postgres            9.6                 c0b5c11b5690        2 weeks ago         229MB

$ docker rmi dad
Error: No such image: dad

$ docker rmi -f dad
Error: No such image: dad
```

（原因は、コンテナ起動中にディレクトリ動かしちゃったからです。爆）

# リポジトリ＋タグ指定でも削除可能

これは知らなかった。

```bash

$ docker rmi docker_web:latest
Untagged: docker_web:latest
Deleted: sha256:dad996f63f1c31bfde8e0b8974c8d385d97c163cef5d42342d6a09d0fe5da249
Deleted: sha256:c04b53411a5a03f4620e6b048d3414125f4f76d88dffd1692d296d370c9e32eb
Deleted: sha256:8460b75e11712750b82e8af96697c19c485335174a943353e3c685989bf21f6f
Deleted: sha256:e5785608340eafc8411dfbe082ed7500be3aac6b70c89e0df73de858e1dffe0d
Deleted: sha256:c507792db613a27ce6ea85cdd6a85e8fc6a8b4115f84d624eb33af437edfb819
Deleted: sha256:c5f575548ff6fff29eb7a64d8721882687d4d96d4f95c718a1e8022561761717
Deleted: sha256:d50557be0da8e2ada87a315c96b1a84b1f82733faa8477b325ed73cebde55a3d
Deleted: sha256:dca6f9e82fd4a2094908dbdbbe825e8db7b4c61e1479b38cd772f071c08ed283
Deleted: sha256:9cc3b4252bfde216b7d06f96aacccebc48fa459234992b3f8fce74846929ca44
```

# さいごに

やさしく扱ってあげましょう←
CoreDataのvalidate機能について、validate<Key>(_:)が呼び出されなくて困った件

iOS開発初心者がCoreDataの勉強中に詰まったところを簡単ではありますが、まとめておきます。

## 動作環境
- xcode9.4.1
- Swift4.1.2

## CoreDataの検証メソッドの動作について
CoreDataの検証メソッドについて、管理オブジェクトコンテキストが保存されるタイミングで、コンテキストが更新／挿入／削除が行われた管理オブジェクトを持つとき、

- `validateForUpdate()`
- `validateForInsert()`
- `validateForDelete()`

が呼ばれます。
これらのメソッド中で`validateValue(_:forKey:)`が呼ばれ、プロパティごとの検証がされます。
`validateValue(_:forKey:)`の中では、キー<key>に対して名前が`validate<Key>(_:)`のメソッドを検索し、見つかればそのメソッドを呼び出します。
これにより、エンティティの各キーに対してカスタム検証メソッドを実装できます。

## 発生した問題
下記のメソッドを作成しましたが、呼び出されていませんでした。
エラーメッセージが出ず、`validate<Key>(_:)`のメソッドが呼び出されないまま、他の処理が動いていました。

```
func validateTitle(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
...
```

## 解決法
下記のように、`func`の前に`@objc`を記述することで、メソッドが無事呼び出されました。

```
@objc func validateTitle(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
...
```

## 原因の考察
Swift4以前では、暗黙的に`@objc`がつけられ、Objective-Cから使用できていました。
しかし、Swift4からは、明示的に`@objc`を用いて、Objective-Cから使用できることを宣言しなければならなくなりました。
つまり、CoreDataの内部処理をObjective-Cで行っていると推測でき、`@objc`の宣言が必要になっているのだと思います。

### 気づいた経緯
Xcodeのバージョンアップで、code Generationを指定できるようになりました。
その指定がswiftになっていたため、試しに`@objc`をつけてみたところ正しく動作しました。
ただし、code GenerationをObject-Cに指定して、`@objc`をつけないで実行しても、メソッドが呼ばれることはなかったため、code Generationは原因では無かったようです。
CentOS 6系のVagrantが初回起動でエラーを吐く場合

## はじめに
bentoから落としたばかりのCentOS 6系の仮想マシンが、初回起動から失敗するため、ひとまず動かすための手順を記載します。
（´-`）.｡oO（もっといい方法があれば教えてください……）

## 再現環境
環境|バージョン
---|---
イメージ| [bento/centos-6.7(2.2.7)](https://app.vagrantup.com/bento/boxes/centos-6.7)<br /> [bento/centos-6.8(2.3.4)](https://app.vagrantup.com/bento/boxes/centos-6.8)
Vagrant|2.1
VirtualBox|5.2.12

ホストマシンは、MBP Pro (Late 13), macOS Sierra/ High Sierraで確認しています。

## 初回起動から失敗する
[bento](https://app.vagrantup.com/bento)にあるCentOS6系の仮想マシンが、初回起動で失敗します。

```result
[xxx] GuestAdditions versions on your host (5.2.12) and guest (5.1.18) do not match.

...

Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:

mount -t vboxsf -o uid=500,gid=500 vagrant /vagrant

The error output from the command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device
```
はじめから入っているvirtualboxのGuestAdditionのバージョンが合わないのが、根本原因っぽいです。
いろいろ調べてみましたが、GuestAdditionを合わせるためにビルドが必要のようです。

仮想マシンはエラーは出ても一応起動しています。`vagrant ssh`後、以下のコマンドを実行してビルド準備を整えます。

```update.sh
sudo yum -y install update kernel
sudo yum -y install kernel-devel kernel-headers gcc gcc-c++
```

このあと、仮想マシンを再起動させると、中断していたセットアップが再開し、問題解決です。

## 参考

https://qiita.com/shifumin/items/a3f72225bcb947fcab21
https://qiita.com/YusakuS16/items/94c430a7ef735ed08a16
https://qiita.com/a-suenami/items/3b04151ce6e7d5b72a3e
PHP 配列で要素の値が最大値のキー名を取得（要素の値の数値が最大になるキーを取得したい）

# PHP 配列で値が最大の要素のキー名を取得したい

「[php 配列 値 最大値のキー](https://www.google.com/search?q=site:qiita.com+php+%E9%85%8D%E5%88%97+%E5%80%A4+%E6%9C%80%E5%A4%A7%E5%80%A4%E3%81%AE%E3%82%AD%E3%83%BC)」を Qiita に絞り込んで検索してもドンピシャなのが出てこなかったので自分のググラビリティとして。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

![](https://img.shields.io/badge/php-v5.6.40-blue '検証済みバージョン') ![](https://img.shields.io/badge/php-v7.1.33-blue '検証済みバージョン') ![](https://img.shields.io/badge/php-v7.4.4-blue '検証済みバージョン')

```php
$maxes   = array_keys($array, max($array)); // 値が最大の要素を抜き出す
$key_max = $maxes[0]; // 最初に出現した最大値のキー名を返す
```

- 「[array_keys](http://php.net/manual/ja/function.array-keys.php)」 @ PHP マニュアル
- 「[max](http://php.net/manual/ja/function.max.php)」 @ PHP マニュアル

## TS; DR

```php:データ
$array = [
    'banana' => 4,
    'carrot' => 1,
    'daikon' => 12, // <- 値 MAX
    'egg'    => 1,
    'apple'  => 12, // <- 値 MAX
];
```

```php:最大値が出現した順に取得
$maxes = array_keys($array, max($array));
var_export($maxes);
```

```php:結果
array (
  0 => 'daikon',
  1 => 'apple',
)
```

```php:キーをソートしてから取得
ksort($array, SORT_NATURAL);
$maxes = array_keys($array, max($array));
var_export($maxes);
```

```php:結果
array (
  0 => 'apple',
  1 => 'daikon',
)
```

- [オンラインで動作を見る](https://paiza.io/projects/v47WjCD0oL35Ojmam5FOHw) @ paiza.IO

## 動作確認

- PHP v5.6.40, v7.1.33, v7.4.4

## 参考文献

- 「[Return index of highest value in an array](https://stackoverflow.com/questions/1461348/return-index-of-highest-value-in-an-array)」 @ StackOverflow
- 「[php How to get the key of max value in array](https://www.google.co.jp/search?q=php+how+to+get+the+key+of+max+value+in+array)」 @ Google 検索
- 「[php 配列 値 最大値のキー](https://www.google.co.jp/search?q=php+%E9%85%8D%E5%88%97+%E5%80%A4+%E6%9C%80%E5%A4%A7%E5%80%A4%E3%81%AE%E3%82%AD%E3%83%BC)」@ Google 検索
[C#] IDisposableで計画的に解放処理！

IDisposableはいいぞ という話

# IDisposableとは？
System.IDisposableのこと
基本的にC#では色々な解放処理は自動でやってくれる
しかし明示的に解放をしたい時もある
そのような時に強力な力を発揮するインターフェイス！

# 実際の使用例
```c#:ファイル読み込み
using (StreamReader sr = new StreamReader("何かファイル"))
{
 var text = sr.ReadToEnd();
}
```
ファイルを開いた際には閉じる必要がある
これをIDisposableを使うことで自動で閉じるような作りになっている

# 何がいいぞなのか？
## 早期リターンとの相性が良い
例えば何か処理を行なった後に解放というような流れ
この時に早期リターンを使い途中で抜けた場合、解放処理まで流れない
もしくは早期リターン内で解放処理を呼び出しという とてもナンセンスなコードになる

```c#:あまりよろしくない
var ex = Example();
/* 何かしらの処理 */
if(/* 早期リターン */) return;
ex.Close();
```

解放処理を確実に行なえるため、早期リターンでの途中抜けをしても問題がなくなる

```c#:とてもクール！
using (new ExampleScope())
{
 if(/* 早期リターン */) return;

 /* そして処理は続く・・・ */
}
```

## 解放忘れがなくなる
usingスコープで宣言さえすれば、あとは解放処理を叩く必要がなくなる
自分以外の人が使う時に、「え？これ解放しないといけないの？」という現実競合が起こらなくなる！

# 実装の仕方
```c#:IDisposableの実装
public class Example : IDisposable
{
 public Example()
 {
   /* コンストラクタ */
 }

 public void Dispose()
 {
   /* 解放処理をここへ */
 }
}
```
簡単に実装できる
使い方は`using(new Example()){/*処理*/}`で呼び出せばいいだけ

# まとめ
IDisposableはいいぞ
PHP7+MySQL5.7でPDOを使おうとしたら「could not find driver」

CentOS7にPHP7とMySQL5.7をインストールしてPDOを使おうとしたら「could not find driver」エラーが出たのでメモ。

# やったこと
## PHP7をインストール
```
yum install epel-release
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum install --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd
```

## MySQL5.7をインストール
```
yum remove mariadb-libs
rm -rf /var/lib/mysql/
yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
yum install mysql-community-server
```

## PDOでデータベース接続
```php:php
$dsn = 'mysql:dbname=' . DB_NAME . ';host='.DB_HOST;
$pdo = new PDO($dsn, DB_USER, DB_PASSWORD);
```

すると、「**could not find driver**」エラーが発生。

# 解決
こちらを参考にさせていただきました。。

[PHP7+Nginx+MariaDBでPDO接続したとき"could not find driver"が出た際にやったこと](https://qiita.com/toriiico/items/e2d951bc7e598d7609fb)

「**php-mysqlnd**」をインストールしたところ、解消されました。

```
yum install --enablerepo=remi,remi-php70 php-mysqlnd
```
無限forkの収拾方法

これは前世紀のノウハウなので、今ではもっとまともな手段があるとか、現代のUNIXではこの手は使えないのかもしれない。

プロセステーブルオーバーフローになって、原因のプロセスをkillしたいが、プロセスが作れないので何もできない、ということがある。
コンソールログインは出来るがコマンドが一切起動できないというだけなら、対処はできる。

ログインできるということはそのログインシェルのプロセスは動いているので、exec コマンド名 でコマンドを実行する。コマンド終了に伴ってログアウトになるので、その都度ログインしなおす、という面倒くさいことをする。
この場合パイプが使えないので、いちいちファイルにリダイレクトする。
たとえば、本来は
ps -ほげ | less
で、プロセスを目で探してkillしたいのなら、
exec ps -ほげ >/tmp/file
再度ログイン
exec less /tmp/file
再度ログイン
kill プロセスID
(killは内部コマンドなのでexec不要)

この知識が役に立ったことは人生で1~2度しかない。
LambdaからLambdaを並列で呼び出す方法（node）

# はじめに
lambdaからlambdaを並列で呼び出し、かついい感じに子lambdaからステータスを受け取って親lambdaが返却するやり方を知りたかったが、google先生に聞くとStepFunctionばかり出てくるのでまとめた。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/131037/28c67d18-70df-0096-24a0-3c6d98f2c124.png)

# こたえ
async使えばいけるぞ

```parallel.js
var async = require('async');
const AWS = require('aws-sdk');
var lambda = new AWS.Lambda();

function callParallelLambda(arg) {
	return function(callback2) {
		var payload = {
			key: 'key' + arg.id,
		}
		//子lambdaへのリクエストパラメータは文字列で渡す
		payload = JSON.stringify(payload);
		var params = {
			FunctionName: 'childelambda', // 子lambdaの名前。
			InvocationType: "RequestResponse", // 子lambdaの呼び方。レスポンス受けたいので同期で呼ぶ。
			Payload: payload // 子lambdaへのリクエストパラメータ
		};
		lambda.invoke(params, function (err, data) {
			// if elseでcallbackしないと、"既にcallbackが呼ばれているぞ"というエラーになる
			if (err) {
				callback2(null, err)
			} else {
				const response = {
					statusCode: 200,
					headers: {},
					body: { "message": "呼び出せました", "data": data }
				};
				callback2(null, response)
			}
		});

	}
}

exports.handler = (event, context, callback) => {
	// コールバック関数の配列を作成
	var callbacks = []
	for (var i = 0; i < 5; ++i) {
		console.log(i)
		callbacks.push(callParallelLambda(i));
	}

	async.parallel(callbacks, function (err, results) {
		console.log('error = ' + err);
		console.log('results = ' + results);
		callback(null, results);
	});
}
```

# 注意点
- 親lambda関数のロールにlambda実行権限をつけること
- [lambdaの同時実行数のデフォルトは1ルートアカウントあたり1000](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/concurrent-executions.html)なので、それ以上の予定がある場合はAWSに土下座するかparallel limitを使ってlambdaの制限時間の許す限り頑張ってみてください
SQLのIN句に複数カラムを指定する方法とNULLのものも含めて検索する方法

SQLの検索で、

```sql
SELECT * FROM table
WHERE (column1 = value1 AND column2 = value2) OR (column1 = value3 AND column2 = value4);
```

というようなものを書きたいときに

```sql
SELECT * FROM table
WHERE (column1, column2) IN (
  (value1, value2),
  (value3, value4)
);
```
と書くことができます。

個人的にMySQL独自の記述だと思っていたけども、SQL99の標準として対応しているということを知りました。
確かに`PostgreSQL 9.5`と`Oracle 11.2`でも使えることを確認しました。

この構文に名前があるのかを調べたところ、
[INとEXISTSの違い](http://d.hatena.ne.jp/Sikushima/20100627/1277616745)
にて「行値構成子」、「行値式」というのだと書かれていました。

ただ、残念なのが、`NULL`を検索する事ができないです。
例えば下記のようなデータを持つ**test_table**がある場合に、

|id|name|content|
|---|---|---|
|1|hoge|hogehoge|
|2|piyo|piyopiyo|
|3|fuga|*NULL*|

```sql
SELECT * FROM test_table
WHERE (name, content) IN (
  ('hoge', 'hogehoge'),
  ('fuga', NULL)
);
```

というSQLを実行すると結果はid=1のものしか返ってきません。
content=nullの検索でunknownになるからだと思います。

やや強引ですが、`NULL`の場合に、そのカラムに絶対に入らない値を指定することで検索できます。

```sql
SELECT * FROM test_table
WHERE (name, COALESCE(content, 'NULLの場合')) IN (
  ('hoge', 'hogehoge'),
  ('fuga', 'NULLの場合')
);
```
1行で描けるかんたんシェーダ5点盛り

#シェーダを描きたい

　Unityでシェーダを描きたい！　でも何を書けばいいかわからない！　という方へ。
　1行で描ける（正確には改変できる）シェーダを5つ程考えたので、コピペなり写経するなりしてシェーダを触ってみる手がかりになれば幸いです。

#導入

![image.png](https://qiita-image-store.s3.amazonaws.com/0/288125/f12a86b3-9957-2f27-bd24-3ceb359fe2c3.png)

　Assets欄から

Create > Shader > Unlit Shader

　を選んでシェーダを作ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/288125/6944f01c-aaf8-deed-6387-e8b9e5b333b7.png)

　新しく作成された「New UnlitShader」を選んで、右上に表示される「Open」ボタンを押します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/288125/3235ed4a-46af-d1ec-38c6-0f9e4d4938db.png)

　60行ぐらいの難しそうなコードが出てきますが、大事なのは53行目の「return col;」です。ここを書き換えれば簡単なシェーダならここ1行で表現できます。

　では、実例を見ていきましょう。

#グリーンバック

<img width="763" alt="green.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/288125/88465058-f257-36af-3c86-8e3d04e6dc8f.png">

```GLSL
return float4(0,1,0,0);
```

　背景撮影に便利です。右の方にいるのは私のアバターです（かわいい）。ソースの中身は至極簡単で、コンマで区切った最初の数字がR,G,Bを表しているので、0,1,0を入れれば緑色になります。

#マケドニア国旗

<img width="714" alt="マケドニア.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/288125/c26aa2ec-9c26-1d91-c9fb-e7080566d53a.png">

```GLSL
return float4(1,step(sin(10*atan2(i.uv.y-.5,i.uv.x-.5)),0),0,0);
```

　正式名称は不明ですが、マケドニア国旗に良く似ているのでマケドニア国旗と呼ばれているアレです。実際のマケドニア国旗は8分割ですが、20分割ぐらいした方がマケドニア感（マケドニア感とは？）が増すのでそうしています。

　赤は全部1を入れておいて、緑を放射状に入れることによりマケドニア感を出しています。xy平面内の点の角度は、$tan^{-1}(\frac{y}{x})$で出ますので、角度によって周期的に緑を足すようにしています。周期性を出すにはstep(frac(ほげ),0.5)でも可能ですが、step(sin(ほげ),0)の方が短いのでそうしています。

#スペクトラム

<img width="732" alt="rainbow.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/288125/c4ef0d4b-628c-0fbe-7305-0b6541f84d1f.png">

```GLSL
return float4(step(cos(20*i.uv.x),0),step(cos(20*(i.uv.x+2.09)),0),step(cos(20*(i.uv.x+4.19)),0),0);
```

　一行が長くてあまりエレガントなワンライナーではないですね。すいません。RGBをそれぞれ違う周期で足していくことにより虹色を表現しています。Unityのシェーダでは円周率の定数を使えないので（使えるのかもしれませんが、デフォルトでは使えませんでした）有効数字3桁で近似しています。線の幅がまちまちなのはそのせいです。

#的

<img width="735" alt="target.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/288125/069a30d9-d85e-7aa5-deab-11d86fe2614b.png">

```GLSL
return 1-step(sin(50*distance(float2(.5,.5),i.uv)),0);
```

　弓道に使われてそうな的です。ちなみにこのタイプの、同心円がいくつも並ぶものは霞的と言います。distance関数（2次元ベクトル同士の距離を計算する）を使えば極めてシンプルに表現できます。ちなみに先頭に「1-」をつけて白黒反転させているのは、霞的の中心が白いのを再現するためです（弓道経験者のこだわり）。言い忘れましたが、returnに白黒を返す場合は、4次元配列ではなく1次元の変数を指定するだけで良いようです。

#グリッド

<img width="683" alt="grid.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/288125/f9611d59-ad6f-af20-5f82-ff8460e242ba.png">

```GLSL
return step(sin(20*i.uv.x),0)+step(sin(20*i.uv.y),0)*(1-2*step(sin(20*i.uv.x),0));
```

　F1に使われてそうな白黒グリッドです。なんだかアバターがレースクイーンに見えてきました。これもあまりエレガントなやり方ではないですね。良い実装があったら教えてください。
2018/9/27 【保存版】備忘録としてブックマークを整理

## Swift
- [そのまま使える！iOSアプリを作るためのswiftサンプル集](https://qiita.com/ryupaka/items/54192d304253103c07e9)
- [[Swift] 左右フリックでカードを選ぶTinderUIを実装する](https://www.yoheim.net/blog.php?q=20171105)
- [Outlet cannot be connected to repeating content – Xcodeエラー](https://easyramble.com/outlet-error-in-repeating-content.html)
- [[iPhone] UIButton, ボタンをコードで設定する](https://i-app-tec.com/ios/button-code.html)
- [Swift：タッチイベントの際にタッチした座標を取得する方法２通り](https://qiita.com/Kyomesuke3/items/d86cefa9dbd7bd2d7cf0)
- [Swift：addGestureRecognizerの使い方](http://programming-beginner-memo.com/?p=13)
- [Swift frameとboundsの理解をちょっとだけ深める](https://qiita.com/naodroid/items/fdcb956221a82cc8480a)
- [[iPhone] UILabel 位置、サイズ、font、背景色などの設定](https://i-app-tec.com/ios/uilable-utilites.html)
- [[Swift]空の配列に既存の配列を追加する/ 配列を結合する方](https://code-schools.com/swift-array-add/)
- [[Swift3]ローカル通知の実装方法](https://qiita.com/yamataku29/items/f45e77de3026d4c50016)
- [iOS 10以降のNotificationの基本](https://qiita.com/aokiplayer/items/3f02453af743a54de718)
- [UIの学習のために生まれたUI](http://www.standardinc.jp/reflection/article/ui-was-born-for-learning-the-ui/)
- [[Swift] BWWalkthrough を使って、簡単にウォークスルーを導入する](https://nobuhiroharada.com/2018/04/13/walkthrough-sample/)

## そのほか

- [【初心者向け】プログラミング言語選びを間違えないように言語の特徴と職種をまとめました](http://harv-tech.hatenablog.com/entry/choose-lang#Javascript)
- [プログラミングの初心者を抜け出すための習慣](https://kuranuki.sonicgarden.jp/2018/01/practice-of-programming.html)