OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonでバーコードを読み込む

#はじめに
自分でバーコードを読み込みたくなり試してみました。
pyzbarは、一次元バーコードとQRコードが読めるようです
一次元バーコードEAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 39

#実行環境
OS Windows 10
~~ZBar 0.10~~
pyzbar 0.1.7
pillow 5.0.0

#環境構築
ZBarをインストールしないで、pyzbarとpillowを追加すればいいみたいです。
~~Windowsの場合はZBarをインストールする。pipではエラーがでました
http://zbar.sourceforge.net/~~

pyzbarとpillowをコマンドプロンプトからインストール
pip install pyzbar
pip install pillow

#実行
今回はcode39のjpeg画像を読み込んでみました
![code39.JPG](https://qiita-image-store.s3.amazonaws.com/0/296388/71845cb4-2ae6-7794-9d37-451e1391c86f.jpeg)

```python
from pyzbar.pyzbar import decode
from PIL import Image

# 画像ファイルの指定
image = "code39.jpg"

# バーコードの読取り
data = decode(Image.open(image))

# コード内容を出力
print(data[0][0].decode('utf-8', 'ignore'))
```
<a href="https://www.amazon.co.jp/OpenCV%E3%81%A8Python%E3%81%AB%E3%82%88%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Michael-Beyeler/dp/4839965307/ref=as_li_ss_il?ie=UTF8&qid=1538313940&sr=8-1&keywords=python+opencv&linkCode=li2&tag=chokex2-22&linkId=515ff62677b969f0a27bad2e8b8ad8fa&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4839965307&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=chokex2-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=chokex2-22&language=ja_JP&l=li2&o=9&a=4839965307" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

#参考URL
参考にしたページ
[PythonでQRコードをデコード](https://qiita.com/igk2647/items/1f868c10107a6ce88b27)
[pythonで画像からQRコードを読み込む](https://python-minutes.blogspot.com/2017/06/pythonqr_28.html#more)

#変形例
pillowを使わずにopenCVを使う場合。

#実行環境
OS Windows 10
pyzbar 0.1.7
opencv-python 3.4.3.18

#環境構築
pyzbarとopencv-pythonをコマンドプロンプトからインストール
pip install pyzbar
pip install opencv-python

#実行
画像は最初と同じものを使用

```python
# -*- coding: UTF-8 -*-

from pyzbar.pyzbar import decode
import cv2

# 画像ファイルの指定
image = cv2.imread("code39.jpg")

# QRコードの読取り
data = decode(image)

# コード内容を出力
print(data[0][0].decode('utf-8', 'ignore'))
```

<a href="https://www.amazon.co.jp/Python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E2%80%95NumPy%E3%80%81pandas%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E5%87%A6%E7%90%86-Wes-McKinney/dp/487311845X/ref=as_li_ss_il?ie=UTF8&qid=1538489967&sr=8-7&keywords=python&linkCode=li2&tag=chokex2-22&linkId=5e5070123e2ef41e8d89efe09e951f94&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=487311845X&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=chokex2-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=chokex2-22&language=ja_JP&l=li2&o=9&a=487311845X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
#参考
https://pypi.org/project/pyzbar/
GASでスプレッドシートを扱うときの二次元配列の「教え方」

# これは何の記事か？

社内のノンプログラマにGASを教えて、みんなでラクしようぜ！という活動をしています。
業務の中で圧倒的に利用頻度が高いのが「スプレッドシート」。

スプレッドシートのデータを扱うときに

```js
const sheet = SpreadsheetApp.getActiveSheet();
const data  = sheet.getDataRange().getValues();
```

こんな感じで、「シートの中身を全部取ってきて、あとは二次元配列 `data`で扱う」ことをします。

ノンプログラマにプログラミングを教えるにあたって「ループ」「配列(しかも二次元)」というのはなかなかに難しい内容です。

今回はスプレッドシートを扱う上での二次元配列について、どう教えたらいいか、を書いてみます。
もっといい教え方、伝え方、理解の仕方、があったらぜひ教えてください！

# 前提

- 単純な「配列」についてはわかっている。

```js
const colors = ["red", "blue", "pink"];
Logger.log(colors[1]);

// blue が出力される
```

- 単純な「for文」についてはわかっている。

```js
for (let i=1; i<=10; i++) {
   Logger.log("カウント:" + i);
}

// カウント:1
// カウント:2 ... と10まで出力される
```



# テストデータ準備

[疑似個人情報データ生成サービス](https://hogehoge.tk/personal/)を利用して、10人分の名簿を作成しました。

![gas1.png](https://qiita-image-store.s3.amazonaws.com/0/8612/0236ce5c-b441-e0c0-d2a3-8b199879480f.png)


# GASでデータを取得する

```js:GAS
function myFunction() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const data  = sheet.getDataRange().getValues();
  Logger.log(data);
}
```

↑これの出力結果がこれ↓


![gas2.png](https://qiita-image-store.s3.amazonaws.com/0/8612/2cfdc7d2-e833-9417-0dbd-703d8f01a53e.png)


↓ 整形してみるとこんな感じ。`data` という配列に11個の要素が入ってます。

![gas3.png](https://qiita-image-store.s3.amazonaws.com/0/8612/2cec691d-aa11-67b9-bf39-5385447c4497.png)


# 一つの要素に注目

↓ `data` 配列の1つの要素に注目してみます。

![gas4.png](https://qiita-image-store.s3.amazonaws.com/0/8612/0ff45ba7-f122-0a93-0b5e-5827e9136cff.png)


つまり、`data` 配列の1つの要素には **スプレッドシートの1行分のデータが、A列から順番に配列として格納されている** です。

こんなイメージ。
![gas5.png](https://qiita-image-store.s3.amazonaws.com/0/8612/d3a87a5f-8fe9-3ee5-6f2b-f3ac7d41b06c.png)

なので、メールアドレスは下記で取り出せます。

```js
data[1][3] // ihiraga@jgjvbkn.os
```

# ここまでのまとめ

- `data[n]` には**１行分のデータが配列で入っている**
- それぞれのセルの番地 (ホントはセルじゃないけどイメージとして) は下記のようになってる。
- `data[行][列]`でアクセスできる

![gas6.png](https://qiita-image-store.s3.amazonaws.com/0/8612/ee12da26-58de-4827-4d0d-7cd0c410b9cf.png)

- 例えば `飛田一樹` のメールアドレスがほしければ `data[7][3]` でアクセスできる。


# 実務っぽく、リストにあるメールアドレスだけ取り出したい

参加者リストがあって、ある列の値だけを抽出したい、ってことあります。
ここからはループを使って二次元配列の中身を取り出していきます。

今回は「メールアドレスだけ」を取り出します。


```js
function myFunction() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const data  = sheet.getDataRange().getValues();

  for (let i=1; i<data.length; i++){
    Logger.log(data[i][3]);
  }
}
```

ポイントはここ↓ですが

![gas7.png](https://qiita-image-store.s3.amazonaws.com/0/8612/7597f3b9-888c-ce07-cb07-d5557585a512.png)

- 1行目(`data[0]`)はヘッダなので無視するために `for(var i=1;...)` として1からループさせます。
- 1 **行** ずつ処理するため、`data[i]` をループさせます。
- メールアドレスは必ず `data[i][3]` にあるので、**列**は3で固定です。



# つまづきポイント

私もそうでしたが、GASを触り始めた当時は「スプレッドシートは1から始まってるのに、GASになると0から始まってて1つずれちゃうじゃないかよなんてこったい」て思ってた時代がありました。

私は


```js
const data  = sheet.getDataRange().getValues();
```

これの右辺はスプレッドシートに対するアクションであり、現実世界。
これの左辺はGASの世界。GASの世界というのはプログラムの世界で、データを配列として扱う目に見えない世界。

...というイメージをしています。


# 最後に

んー、どうだろう。これで「わかった！」って思ってもらえるだろうか。。。
イラストとかアニメーションで視覚的に教えてくれる人いないかなｗ
(再度になりますが、もっといい教え方があったら教えてほしいです)
RubyGem  `require': cannot load such file --  (LoadError) 

# Rubygem ファイル追加の際に気をつけること

##  Overview

```
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- xsort/sortproj (LoadError)
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /Library/Ruby/Gems/2.3.0/gems/xsort-1.2.3/lib/xsort.rb:5:in `<top (required)>'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `require'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `rescue in require'
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:40:in `require'
	from /Library/Ruby/Gems/2.3.0/gems/xsort-1.2.3/bin/xsort:3:in `<top (required)>'
	from /usr/local/bin/xsort:22:in `load'
	from /usr/local/bin/xsort:22:in `<main>'


```

ドキュメントなどに記載されておりましたが、

自作Rubygem にファイルを追加していた際に、パス、権限、は間違い無いのに下記エラーが出ていました。

```
`require': cannot load such file --  (LoadError) 
```

（☝ ՞ਊ ՞）☝ これでてますが！

意味がわかりませんでしたが、

色々調査してみたところ

gem はgitで管理されていないと追加できないとのこと

なのでgitで追加してみました。

```
$ git add .
$ git commit -m "追加してみた"
$ git push
```

その後で

```
$ gem build xsort.gemspec 
$ sudo gem install xsort-1.2.3.gem
```

```
$ xsort
Usage: xsort [-v] [<path>] [-o] 
These are common detect commands used in various situations:
xsort version: 1.2.3
option:
-v: display xsort version number
-o: output result
-r: Just extracting output.pbxproj will not write to pbxproj of Xcode project

Regars !
```
正常に動作しました。

改修したgem 
https://github.com/keisukeYamagishi/xsort
参考資料
https://teratail.com/questions/149342
ROS2.0をWindows10にインストールする

## chocolateyをインストール
管理者権限でpowershellを起動して
`Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))`

- Set-ExecutionPolicyはスクリプトの実行権限を変更する

- iexは与えた文字列をコマンドとして実行する

## pythonをインストール
1. `choco install -y python`
1. `refreshenv`  
(2019/11/10追記)    
`choco install python --version=3.7.5`と入力する必要がある。  
デフォルトだとpython3.8がインストールされる。（現時点ではROS2はpython3.7に対応している模様）

## OpenSSLをインストール
1. [ここから](https://slproweb.com/products/Win32OpenSSL.html)Windows用のOpenSSLのインストーラ（Win64 OpenSSL v1.0.2.）をダウンロードして実行する
1. `setx -m OPENSSL_CONF C:\OpenSSL-Win64\bin\openssl.cfg`とpowershell上で実行
1. 環境変数に`C:\OpenSSL-Win64\bin\`を追加

- setx -mはシステム環境変数に値を設定する

## VisualStudio2017をインストール
## OpenCVをインストール
1. [ここから](https://github.com/ros2/ros2/releases/download/opencv-archives/opencv-3.4.6-vc16.VS2019.zip)ダウンロードして`C:\opencv`に解凍
2. `setx -m OpenCV_DIR C:\opencv`
3. 環境変数に`C:\opencv\x64\vc16\bin`を追加

## 依存関係をインストール
1. `choco install -y cmake`
2. [ここから](https://github.com/ros2/choco-packages/releases/tag/2019-10-24)パッケージをダウンロード
3. `choco install -y -s <PATH\TO\DOWNLOADS\> asio cunit eigen tinyxml-usestl tinyxml2 log4cxx`  
4. `python -m pip install -U catkin_pkg empy lark-parser lxml numpy opencv-python pyparsing pyyaml setuptools`
5. `python -m pip install -U pydot PyQt5`  
(2019/11/10追記)  
アンインストール後に再インストールしようとするとエラー(tinyxml2,tinyxml-usetl)が発生する現象に遭遇。  
[ここ](https://github.com/ros2/choco-packages/issues/5) を参考にC:\ProgramData\chocolatey\lib-badの下にある各パッケージのアンインストール用のps1ファイルを手動で実行すると再インストール可能になった。

## ROS2をダウンロード
1. [ここから](https://github.com/ros2/ros2/releases)ダウンロード
1. ros2-package-windows-AMD64.zipをダウンロードして
1. `C:\dev\ros2`に解凍

## ROS2セットアップ
1. `call C:\dev\ros2\local_setup.bat`

## サンプル実行
1. `ros2 run demo_nodes_cpp talker`
1. 別のターミナルを起動して同じようにセットアップした後
1. `ros2 run demo_nodes_py listener`

## インストールメモ
* 基本的に[このページ](https://index.ros.org/doc/ros2/Installation/Dashing/Windows-Install-Binary/)のROS2のインストール手順に従えばOK
* セットアップと実行はpowershellではできずコマンドプロンプトを使う必要がある。 
* インストールに詰まる場合はPowershellを管理者権限で実行しているか、PowerShell のスクリプトの実行ポリシーに問題はないかを確認すると良い。

(2019/11/10 インストール用のドキュメントURL等,Dashing用に更新)
(2019/11/13 一部手順が抜けていたので修正)
Sequelizeチートシート

## DB操作

### find
- 条件に合うオブジェクトを返す

```
Model.find({
  where: {id: 1}
});
```
### findAll
- 条件に合うオブジェクトを配列で全て返す

```
Model.findAll({
  where: {sampleId: 2}
});
```
### create
- レコードをinsertする

```
Model.create({
  name: 'はなこ',
  age: 25
});
```
### update
- レコードをupdateする

```
Model.update({
  name: 'まるこ',
  age: 22
});
```
### destroy
- 条件に合うレコードをdeleteする

```
Model.destroy({
  where: {id: 3}
});
```
## DB操作応用

### include
- 自分に対してbelongsToの関係にあるモデルをリレーションを持った状態でDBから取り出してくれる

```
ModelA.findAll({
  include: {
    model: ModelB
  }
});
```

### $or
- where句に複数の条件をORで指定する

```
Model.findAll({
  where: {
    $or: [
      {sampleId: 1},
      {sampleId: 3},
      {sampleId: 5}
    ]
  }
});
```
- 以下のwhere句と同じ

```where id=1 or id=3 or id=5```

### in
- where句に複数の条件をANDで指定する

```
var deleteObjectIds = [1, 2];
Model.destroy({
  where: {
    id: {
      in: deleteObjectIds
    }
  }
})
```
- 以下のwhere句と同じ

```where id=1 and id=2```

## 同期/非同期処理
- functions配列の処理が全て完了すると、Promise.allの処理に入る

```
var functions=[];

functions.push(Model.create({
  name: 'はなこ',
  age: 25
}));

functions.push(new Promise(function(resolve, reject) {
  Model.create({
    name: 'たろう',
    age: 25
  }).then(function(){
    // 処理
    resolve();
  }).catch(function(err){
    reject(err);
  });
}));

Promise.all(functions).then(function() {
  // 処理
  resolve();
}).catch(function(err) {
  reject(err);
});
```
[MacOS Mojave]pyenvでpythonのインストールがzlibエラーで失敗した時の対応

先日、macOS High SierraからmacOS Mojave 10.14にOS更新かけました。

その後pyenv 1.2.7で新しいpythonバージョンをインストールしようとすると、よくあるzlibエラーが出るようになりました:

```
pyenv install 3.6.0
```

```
180930202414.28657/Python-3.6.0/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1
```

High Sierra以前ではこれは基本的に`xcode-select --install`　で直せたが、Mojaveではそう上手く行かないようです。

また、`brew install zlib`　で試してもzlibが既にインストールされていると表示される。

```
Warning: zlib 1.2.11 is already installed and up-to-date
To reinstall 1.2.11, run `brew reinstall zlib`
```

<b>
解決策
</b>
xcode-selectの最新バージョン(2354)にMojave用のmacOS SDK headerがデフォルトで入っていないのが原因のようです。

マニュアルで以下をインストールする必要ある:

```
sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
```

すると、pyenvでのzlib問題が解決されるはずです（下記のようなものが出ればとりあえずオケ。）

```
zreactor$ pyenv install 3.6.0
python-build: use openssl from homebrew
python-build: use readline from homebrew
Downloading Python-3.6.0.tar.xz...
-> https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz
Installing Python-3.6.0...
python-build: use readline from homebrew
Installed Python-3.6.0 to /Users/zreactor/.pyenv/versions/3.6.0
```

Mac Mojaveリリース直後だからまだxcodeツールで対応が追いついていないという事なのでしょうが、今後解決されると期待ですね。
CSS3でレトロホームページを再現：１.marquee（マーキー要素)

こんにちは、@tacashionです。

# レトロゲームの次はレトロホームページ
昔風のホームページをCSS3で作成する機会があったので、記録を兼ねて紹介したいと思います。

## なつかしのmarquee要素
個人ホームページなどでよくあった、右から左に文字が流れる<marquee>要素。
ブラウザによって動いたり動かなかったりしますが、HTML5で正式には廃止されています。
そこで、ブラウザ依存せず再現する方法がないか調べてみると、CSS3でのアニメーションを利用して再現する方法があったので、参考にしつつ実装しました。

### サンプルページとHTML・CSS
[表示サンプル](http://tacashion.zashiki.com/samplecode/180930_marquee.html)
![スクリーンショット 2018-09-30 23.08.44.png](https://qiita-image-store.s3.amazonaws.com/0/289530/64a66143-7223-0b85-814d-4d570acb1ca9.png)
_この懐かしい感じ_



それでは、実装後のHTMLとCSSのコードを以下に記載します。
HTMLファイルにコピペすればすぐに確認できるようにCSSはヘッダーに記述しました。

```html:marquee.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>marquee</title>
<link rel="stylesheet" href=“marquee.css" type="text/css" media="all">

 <style type="text/css">
.welcomeTextWrapper {
background:aqua;
overflow:hidden;/* marquee:コンテンツ幅外で消えるように */
}

.welcomeTextWrapper .welcomeText {
display:inline-block;
padding-left:100%;/* marquee:画面外からスクロールするように */
white-space:nowrap;/* marquee:テキストが折り返さないように */
animation-name:maruquee;/* marquee:アニメーション設定のための名前を */
animation-timing-function:steps(200,end);/* marquee:カクカク感を調整 */
animation-duration:20s;/* marquee:スクロールにかける時間 */
animation-iteration-count:infinite;/* marquee:スクロールの繰り返し */
}

@keyframes maruquee {
0%  { -webkit-transform: translate(0%);}/* marquee:右端からスクロール */
100% { -webkit-transform: translate(-100%);}/* marquee:左端へスクロール */
}
</style>

</head>

<body>
<div id="wrapper">
<div id="contents">
<div class="welcomeTextWrapper"><p class="welcomeText">tacashionのホームページへようこそ！</p></div>
</div>
<!--/#contents-->
</div>
<!--/#wrapper-->
</body>
</html>
```

### ポイント：なめらか過ぎないスクロール
marquee風表現の工夫として、「なめらか過ぎない」アニメーションの実現のために、「animation-timing-function」を利用しています。

```css
animation-timing-function:steps(200,end);/* marquee:カクカク感を調整 */
animation-duration:20s;/* marquee:スクロールにかける時間 */
```

画面の右端から左端まで、20秒間で200回かけて移動するよう指定することで、なんとなくレトロ感を思わせるカクカクした動きにしています。

#### 注意点

今回、画面幅は成り行きで設定しているので、ウィンドウ幅が狭まるほど早く、なめらかな動きになります。
一定の動きにしたい場合は、コンテンツ幅を設定し、「animation-timing-function」と「animation-duration」を調整していく必要があります。

今後引き続き、レトロホームページを再現コードをいくつか紹介したいと思います！
配列から要素を削除する方法

####配列から要素を削除したい場合以下の方法がある。
- shiftメソッド　ー　先頭の要素を削除する
- popメソッド　ー　末尾要素を削除する
- spliceメソッド　ー　途中の要素を削除する。引数の第一引数には先頭に残す要素の数を、第二引数には削除する要素の数を代入する。
- sliceメソッド　ー　途中の要素を取り出す。引数の第一引数には先頭の不要な要素の数を、第二引数には必要な要素の最後の数を代入する。他のメソッドと異なり、元の配列の要素を変化させない。

```javascript
var men = ['Y','A','B'];
men.shift();
console.log(men);
 (2) ["A", "B"]

men.pop();
console.log(men);
 (2) ["Y", "A"]


men.splice(1,1);
console.log(men);
(2) ["Y", "B"]

var a = men.slice(1,2);
console.log(a);
["A"]

```
navbarの使い方

#はじめに
bootstrapの「navbar」クラスの使い方を学んだので、学んだ内容を記録する。

## 基本的な書き方
```
<nav class="navbar navbar-light">
  <a href="#" class="navbar-brand">brand</a>
</nav>
```

## 色を変える
```
<nav class="navbar navbar-dark bg-primary">
  <a href="#" class="navbar-brand">brand</a>
</nav>
```
## メニューリンクを表示する

```
<nav class="navbar navbar-light navbar-expand">
  <a href="#" class="navbar-brand">brand</a>
  <ul class="navbar-nav">
    <li class="nav-item"><a href="#" class="nav-link">Link1</a></li>
    <li class="nav-item"><a href="#" class="nav-link">Link2</a></li>
    <li class="nav-item"><a href="#" class="nav-link">Link3</a></li>
    <li class="nav-item"><a href="#" class="nav-link">Link4</a></li>
  </ul>
</nav>
```

## メニューリンクをハンバーガーメニューにする
```
<nav class="navbar navbar-light navbar-expand-md">
  <a href="#" class="navbar-brand">brand</a>
  <button class="navbar-toggler" data-toggle="collapse" data-target="#menu">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div id="menu" class="collapse navbar-collapse">
    <ul class="navbar-nav">
      <li class="nav-item"><a href="#" class="nav-link">Link1</a></li>
      <li class="nav-item"><a href="#" class="nav-link">Link2</a></li>
      <li class="nav-item"><a href="#" class="nav-link">Link3</a></li>
      <li class="nav-item"><a href="#" class="nav-link">Link4</a></li>
    </ul>
  </div>
</nav>
```
## 入力フォームを表示する
```
<nav class="navbar navbar-light">
  <a href="#" class="navbar-brand">brand</a>
  <form action="#" class="form-inline">
    <input type="text" class="form-control" placeholder="name...">
    <input type="password" class="form-control ml-1" placeholder="password...">
    <input type="submit" class="btn btn-primary ml-1" value="Login">
  </form>
</nav>
```

## 任意の文字列を表示する
```
<nav class="navbar navbar-light">
  <a href="#" class="navbar-brand">brand</a>
  <span class="navbar-text">ようこそ、ゲストさん</span>
</nav>
```

## 画面上部にnavbarを固定する
```
<navbar class="navbar-light fixed-top">
  <a href="#" class="navbar-brand">brand</a>
</navbar>
```
#感想
だいぶnavbarについてわかってきた。
フォームやポップアップの書き方についても、上記と同様に整理したい。

#参考
https://getbootstrap.com/docs/4.1/components/navbar/
http://bootstrap3.cyberlab.info/components/navbar.html
https://cccabinet.jpn.org/bootstrap4/components/navbar
AWS勉強 -仮想サーバーを構築する-

ネットワーク上に仮想サーバーを作成する!

# 仮想サーバーを構築する

パブリックサブネットの中に仮想サーバーを構築します!
仮想サーバーはAmazon EC2を用います.
仮想サーバーのことは「インスタンス」と呼ぶ.
このインスタンスにはパブリックサブネット内部で利用可能な「プライベートIPアドレス」を割り当てる.
プライベートIPアドレスはインターネットとは接続ができないので,インスタンスを起動する際にはもう１つ「パブリックIPアドレス」を設定するようにする.

## インスタンスを作成する

### インスタンスを作成する手順1 -リージョンの確認-

<img width="824" alt="スクリーンショット 2018-09-30 20.31.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/5f36a8f1-fdb2-22bc-45ba-39c4b3c6f736.png">

からの,

<img width="875" alt="スクリーンショット 2018-09-30 20.33.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/45a1c12a-8689-e0a1-6fc7-6e3b9c700017.png">

### インスタンスを作成する手順2 -インスタンスの作成を始める-

<img width="870" alt="スクリーンショット 2018-09-30 20.37.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/84361fc7-dfa7-278b-0c8a-6d5af23f99e4.png">

### インスタンスを作成する手順3 -AMIを選択する-

<img width="876" alt="スクリーンショット 2018-09-30 20.40.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/ddc8b0fd-35c5-8399-a3a3-c8742da2aee7.png">

### インスタンスを作成する手順4 -インスタンスタイプを選択する-

<img width="877" alt="スクリーンショット 2018-09-30 20.43.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/d283b760-c4bd-cc9c-716f-030f39070823.png">

### インスタンスを作成する手順5 -インスタンスの詳細情報を設定する-

<img width="877" alt="スクリーンショット 2018-09-30 21.06.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/9f2db214-5670-16e6-4d7d-4d8cade2034c.png">

下にスクロールして,

<img width="904" alt="スクリーンショット 2018-09-30 21.10.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/d3c48cba-6912-1396-79fe-595ba5d2ad12.png">

### インスタンスを作成する手順6 -ストレージを設定する-

<img width="882" alt="スクリーンショット 2018-09-30 21.14.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/a10f3107-3051-1de9-be0c-4342cef207f7.png">


### インスタンスを作成する手順7 -インスタンスに名前をつける-

<img width="886" alt="スクリーンショット 2018-09-30 21.15.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/fdec1a80-b259-2859-bf0c-9e9815037235.png">

からの,

<img width="852" alt="スクリーンショット 2018-09-30 21.19.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/6ce339bf-015f-b2b9-127e-e10f33002efb.png">

### インスタンスを作成する手順8 -セキュリティグループを設定する-

<img width="888" alt="スクリーンショット 2018-09-30 21.26.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/cd124504-b01a-c540-de25-3804036e8889.png">

### インスタンスを作成する手順9 -インスタンスを起動する-

<img width="905" alt="スクリーンショット 2018-09-30 21.37.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/43c33ce0-2d0e-e5ba-4cc6-d9dfd651eae6.png">

### インスタンスを作成する手順10 -キーペアを作成してダウンロード-

<img width="843" alt="スクリーンショット 2018-09-30 21.42.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/f439b305-6b14-aac3-c2f2-ea021976d2c6.png">

### インスタンスを作成する手順11 -インスタンスの起動-

<img width="886" alt="スクリーンショット 2018-09-30 21.48.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/f3f3afed-07f6-fde8-3fe2-89b8f3a5ab3d.png">

## インスタンスの確認

<img width="941" alt="スクリーンショット 2018-09-30 21.54.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/bf2cf28f-4ea2-231a-8c98-4f4b8b191adc.png">

## 感想

EC2,聞いたことしかなかったけど今回作成してみてどのようなものか分かった上,
用途も分かったので満足!
SORACOM KryptonでSORACOM Inventory AgentをBootstrap

SORACOM Kryptonを使ってSORACOM Inventory AgentのBootstrapをやってみたのでその備忘です。

# SORACOM Kryptonとは
デバイスの初期キッティングなどいわゆるプロビジョニングをするためのSORACOMサービスです。Kryptonを利用することでSORACOMのSIMをもとにしたデバイス認証だけでなく、AWSなどのクラウドサービスの認証情報や接続先設定などの情報を安全にデバイスにプロビジョニングできます。今回はSORACOM InventoryのプロビジョニングのためにKryptonを利用します。詳しくは以下をご参照ください。

https://soracom.jp/services/krypton/

# SORACOM Inventoryとは
Inventoryは、LwM2Mをベースにしたデバイス管理のためのサービスです。
LwM2M とはOMA (Open Mobile Alliance) が定めたM2M用プロトコルで、デバイス側にLwM2Mに対応したエージェントを動作させておくことでリモートでのデバイス管理を実現します。今回はこのエージェント初期設定をKrypton経由でおこないます。詳しくは以下をご参照ください。

https://soracom.jp/services/inventory/

# やってみた
基本はこのドキュメントにそっていけば大丈夫でした。

https://dev.soracom.io/jp/start/krypton_inventory/

こちらのドキュメントではGoのKryptonクライアントを利用していますが、今回はKryptonが提供しているAPIエンドポイントを直接実行してみます。

SORACOM InventoryのBootstrapまではドキュメント通りに実行してください。

Bootstrap時に下記のAPIを実行することでSORACOM Inventoryへのデバイス登録をSORACOM Kryptonが代わりに実行してくれます。

```
curl POST -H "Content-Type: application/json" -d '{"endpoint": "任意のエンドポイント名"}' https://krypton.soracom.io:8036/v1/provisioning/soracom/inventory/bootstrap
```

endpointを未指定にすると実行時にエラーとなりました。

無事にデバイス登録がおこなわれるとpskId、applicationKeyが返ってくるので、それ以降はドキュメントに記載があるの通りにLｗM2Mクライントにこれらの情報を指定することで無事連携が開始されます。
【将棋AI】「将棋AIで学ぶディープラーニング」を読む♪～レーティングを求める

<img width="200" style="float: left;" alt="将棋AIで学ぶディープラーニング" src="https://qiita-image-store.s3.amazonaws.com/0/233744/ded117b9-37c7-1b41-033d-960e63ca5fe1.jpeg">
第廿六夜は、先日にひきつづいてレーティングの話です。
今回は、参考のページに対戦成績を入力すると相対的なレーティング差からレーティングを求めるというものです。
【参考】
・[レート計算をする@コンピュータ将棋データベース](https://www.qhapaq.org/shogi/kifdb/)
###やったこと
（１）上記参考ページからレーティングを求める
（２）理論（ソースコード）を見る
###（１）上記参考ページからレーティングを求める
[昨夜の結果から、だいたいのレーティングはわかった](https://qiita.com/MuAuan/items/14881c9ca64e9a95ba72)が、やはり第三者的な意味でレーティングを出しておくことは意味があると思うのでやってみた。
結果は以下のとおりである。
data generated : 30/9/2018   total games: 76

<table><thead><tr><th>software</th><th>rating</th><th>error</th><th>games</th></tr></thead><tbody><tr><th>Gikou2D5</th> <td>2181</td> <td> +544/-117 </td><td> 10</td></tr>
<tr><th>Gikou2D3</th> <td>2036</td> <td> +150/-96 </td><td> 10</td></tr>
<tr><th>Gikou2D2</th> <td>1800</td> <td> +0/-0 </td><td> 56</td></tr>
<tr><th>Try</th> <td>1776</td> <td> +23/-29 </td><td> 70</td></tr>
<tr><th>Q22</th> <td>1695</td> <td> +104/-136 </td><td> 6</td></tr>
</tbody></table>

入力データ;sample2.csv

```sample2.csv
engine1,option1,engine2,option2,win1,win2,draw(-1=undef),drawadd,date(-1=undef),writer
Gikou2D2,+,Try,+,27.5,22.5,1,1,-1,undefined
Gikou2D3,+,Try,+,8,2,0,0,-1,undefined
Gikou2D2,+,Q22,+,4,2,0,0,-1,undefined
Gikou2D5,+,Try,+,9,1,0,0,-1,undefined
```
各データの意味は、[レート計算スクリプトの使い方@コンピュータ将棋データベース](https://www.qhapaq.org/shogi/shogiwiki/howtouseratescript/)にある。
※入力の仕方は上記のCSVファイルのとおりである
レーティングを正しく計算するために重要なことは、最初のSoftwareのレートを基準に計算しているので、そのレートが正しい必要がある。そのSoftwareを基準としたレート算出である。
※基本は[イロレーティング](https://qiita.com/MuAuan/items/0fcc34838e8b1ebb4bda)で示したとおりである。
###（２）理論（ソースコード）を見る
基本的な方程式は、以下のとおりである。
$ΔR=R-R_B$、$R_B$は基準となるソフトのレーティング、$R$は求めたいソフトのレートとすると、

```math
E_{ΔR}=\frac{1}{1+10^{−ΔR/400}}
```
式変形すると以下の通り

```math
R＝R_B-400\log (\frac{1-E_{ΔR}}{E_{ΔR}})
```
※**そもそも$1-E_{ΔR}$は相手の勝率だから、イロレーティングは勝率比の$\log$の400倍がレート差という定義なのがわかる**
ここまで式変形して、ソースコードを眺めてみると、
以下の関数でbias値（基準値）にレート差をプラスしてレートを計算している。

```py
    def get_beta_with_bias(self,i,bias):
        beta = 400*np.log10(self.p)
        beta += (bias-beta[i])
        return beta
```    
また、bias値（基準値）は以下で計算前に設定する必要がある。

```py
    for k in np.arange(n_trial):
        bt = bt_model(samples[k,:,:],p_init)
        bt.estimate()
        betas[k,:] = bt.get_beta_with_bias(0,1800)   #rate of 1st
        p_init = bt.p
```
の`bt.get_beta_with_bias(0,1800)`の1800を変更する。
そして、結果出力は、以下のように実施している。

```py
result = np.c_[range(K),q_50,q_75-q_50,q_50-q_25,n_games]
```
ということで、上記の算出されたレートには＋－がついているが、これはコードによれば再度サンプリング（思考実験して）、その中央値と２５パーセンタイル、７５パーセンタイルをとっているようである。
全コートは[ここ](https://www.qhapaq.org/shogi/kifdb/)からダウンロードして見られる。
###まとめ
・第三者的なレーティングを求めた
・どうやら、イロレーティングから求めているようだ

・今回は、対戦条件が通常とことなるが、何を見るのかを定めてレーティング・ランキングを掲載するというのもありうる
オブジェクト名を生かしたlistを作る

オブジェクトからリストを作成すると、オブジェクトの名前は失われてしまいます。

```{r}
a <- 1:3
b <- 11:13
c <- 21:23
list(a, b, c)
```

```:output
[[1]]
[1] 1 2 3

[[2]]
[1] 11 12 13

[[3]]
[1] 21 22 23
```

名前付きのリストにしたければ、`list(a = a, b = b, c = c)`のようにやるわけですが、オブジェクト名を2回書く必要があり、あまりスマートではありません。

ところがリストの特殊な形であるデータフレームを作成する関数`data.frame`では、明示的に名前を指定しなければ列名としてオブジェクト名が設定されます。

```{r}
df <- data.frame(a, b, c)
as.list(df)
```

```:output
$a
[1] 1 2 3

$b
[1] 11 12 13

$c
[1] 21 22 23
```

ということは、何かやり方があるはずです。

単純にやるなら、オブジェクトの名前を取得して、リストの名前にセットしてやれば良いので、例えば次のような関数を定義します。

```{r}
namedlist1 <- function(...){
  setNames(list(...), eval(substitute(alist(...))))
}
namedlist1(a, b, c)
```

```:output
$a
[1] 1 2 3

$b
[1] 11 12 13

$c
[1] 21 22 23
```

`eval(substitute(alist(...)))`の部分は、`rlang`パッケージを使ってもう少し簡潔に書くこともできます。

```{r}
namedlist2 <- function(...){
  setNames(list(...), rlang::exprs(...))
}
```

しかし、この場合は明示的に名前を指定した場合にもオブジェクトの名前が優先して使われてしまいます。

```{r}
namedlist1(a, hoge = b, c)
```

```:output
$a
[1] 1 2 3

$b
[1] 11 12 13

$c
[1] 21 22 23
```

リストの2つめの要素は名前が`hoge`になってほしいところでした。

ところでこの「明示的に名前を指定した場合にはその名前を使う」という動作も`data.frame`だと実現できています。

```{r}
as.list(data.frame(a, hoge = b, c))
```

```:output
$a
[1] 1 2 3

$hoge
[1] 11 12 13

$c
[1] 21 22 23
```

上記のように`data.frame`を`as.list()`でリストに変換する方法は、いつでも使えるわけではありません。`data.frame`には要素数が等しいという制約があるためです。

しかし`data.frame`は実際これをやっているわけですから、中身を覗いてそこだけ拝借すれば同じことができるのではないでしょうか？

やってみました。

```{r}
namedlist3 <- function(...){
  object_name <- as.character(eval(substitute(alist(...))))
  x <- list(...)
  vnames <- names(x)
  novnames <- !nzchar(vnames)
  if (length(novnames) > 0L){
    vnames[novnames] <- object_name[novnames]
  } else {
    vnames <- object_name
  }
  setNames(x, vnames)
}
namedlist3(a, hoge = b, c)
```

```:output
$a
[1] 1 2 3

$hoge
[1] 11 12 13

$c
[1] 21 22 23
```

できました。

要するに名前が設定されていない部分を探してオブジェクト名をセットしているだけなのですが、`data.frame`の中ではこういう地道なことが行われていたのでした。
AndroidStudio3.2で既存のAndroidStudioProjectでGradle Syncが失敗するトラブルの解決策


MacでAndroidStudio3.2で既存のプロジェクトを開くと以下のようなエラーが出て `Gradle sync` が失敗します。

```
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android 
```

こういう場合はMacのターミナル上で以下のコマンドを実行してからAndroidStudioを再起動すれば問題なくいけます。

```
cd  ~/Library/Android/sdk/ndk-bundle/toolchains
ln -s aarch64-linux-android-4.9 mips64el-linux-android
ln -s arm-linux-androideabi-4.9 mipsel-linux-android
```


## 参考サイト

https://stackoverflow.com/questions/35128229/error-no-toolchains-found-in-the-ndk-toolchains-folder-for-abi-with-prefix-llv
ずんだの縦読み問題 Brainf**k編

いつぞやのずんどこキヨシよりは楽よね、と。

ということで、Brainf\*\*k版の実装(32文字)です。

```brainfuck:BF版
,+[-.,.,.+[-----------[,+>]<],+]
```

なお、UTF-8日本語(3バイト文字)を前提として~~手抜き~~決め打ちしてます。

実行例は[ideoneでの実行例](https://ideone.com/R7MTje)を参照のこと。

参考: [ずんだの縦読み問題 Ruby編](/tbpgr/items/90abccf8297be0e42f8c)
さようなら、ロリ●ップ 〜FirebaseにWordPressサイトを移行する〜


こんにちは！こんにちは！

野良エンジニアになって1年が経ち、現場先にも慣れてきたある日。
ロ●ポップから「サーバ代払ってね」メールが来ていました。

個人事業主でもHPつくったほうが良いよ、とネットに書いてあったので作りかけのやつを1年くらい活用せずに放置しててサーバ代のこともわすれてました。

で、1年で10000円以上もサーバ代に使っていた事に気づきました（プランによります）。

活用してないのに。
ロリポッ●は好きなんですが、やはり節約したい。お金を。

独自ドメインも●リポップと同じ会社が提供するムー●ードメイン使ってるんですが、こちらは残して、WordPressで作成しているサイトを無料のFirebaseに移行することにしました。Firebase流行ってるし。

GitHubページやらも考えましたが、なんかFirebaseいじりたかった。

同じように、それほど活用できていないHPやらサイトを移行したいって人には参考になるかもしれません。

#(1)既存サーバからデータ抜く

抜くといっても、WPにログイン→プラグインインストール→データを落とすだけです。
下記の動画が参考になります。
https://www.youtube.com/watch?v=lbZeOhnUHww
わざわざ静的ファイルを吐く必要あるのかな？と思いつつしましたが、とりあえずやってみる。



#(2)firebaseでアカウント作成

firebaseのアカウントつくります。
https://console.firebase.google.com/u/0/?hl=ja

gmailなどでGoogleアカウント作成している場合はすぐに済みます。
Gアカウントでログインして、プロジェクト作成するとこまでやります。のちのちプロジェクトのIDがデプロイ時に必要になります。

プロジェクト追加→プロジェクト名決めるだけで簡単。
IDとかはめもっておきます。

後々必要になるので、Node.jsもDLしときます。

#(3)Firebaseのパッケージインストール
Firebase用のディレクトリ作って、下記の呪文を唱えます。

```
npm install -g firebase-tools
```
##はまる
上記の呪文を唱えると、下記のエラーが出現。

```
npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! path /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  { Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!   stack: 'Error: EACCES: permission denied, access \'/usr/local/lib/node_modules\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules' }
npm ERR! 
```
自分はMacBookでやったのですが、どうやら/usr/localの権限周りが原因のよう。なので、インストールするパスを変更しました。
Windowsの場合はどうなんだろう。。。

#(3)firebaseにデプロイ
事前にデプロイ用のjsonファイルつくっておきます。

```
{
  "hosting": {
    "public": "ここにデプロイ対象ディレクトリ名"
  }
}
```
Firebaseにターミナルからログイン

```
$ firebase login
```

firebase用のディレクトリ上でfirebase init

```
$ firebase init
```

デプロイ用のディレクトリつくり、さきほどつくったjsonファイルにつくったディレクトリの名称を記述します。
WPファイルをデプロイ用のディレクトリに配置します。jsonはfirebase用のディレクトリに配置。
そしてデプロイコマンド。

```
$ firebase deploy --project ここにめもったfirebaseプロジェクトのID 
```


#(4)確認
サイトが表示されているかどうか、firebaseのデフォルトドメインで確認。
https://shinsekai-d65a9.firebaseapp.com/

無事WPサイトが表示されました。

#まとめ

あとはDNS設定変えるだけでいけるはず。。。
これで年間1万円くらいは浮く。サイトによりけりで、サーバ借りてるままのがほういい場合もあるかもしれません。
トラフィックまったくない放置気味サイトとかはfirebaseでいいのかな？

##参考にさせていただいた記事・動画
https://qiita.com/kuronat/items/954d7348810ec14171af
https://www.youtube.com/watch?v=lbZeOhnUHww

#追記
Firebase、静的ファイルしか動かせないみたかったので（無知）、サイトを更新するときはローカルで更新してデプロイする必要がありそうな。まあ、良いか。
Golangで iotaの開始番号を指定する

例えば開始番号を`10`にしたい場合、このように書けばOKです。

```
const (
    FOO = iota + 10
    BAR
    BUZ
)
```

例

```
package main

import "fmt"

const (
    FOO = iota + 10
    BAR
    BUZ
)
func main(){
    fmt.Printf("%v\n", FOO) // => 10
    fmt.Printf("%v\n", BAR) // => 11
    fmt.Printf("%v\n", BUZ) // => 12
    return
}
```
ずんだの縦読み問題 ShellScript編


# 元ネタ

[ずんだの縦読み問題 php編 - Qiita](https://qiita.com/higuyume/items/7d3c03ddbbd6f4ad7aa1)
[ずんだの縦読み問題 Go編](https://qiita.com/kentfordev/items/d9a78e34d1e8bf2e703a)
[ずんだの縦読み問題 Perl編](https://qiita.com/sapi_kawahara/items/19fcdc074fab6d55acd5)
[ずんだの縦読み問題 Ruby編](https://qiita.com/tbpgr/items/90abccf8297be0e42f8c)
[ずんだの縦読み問題 Java 12 Early-Access 版](https://qiita.com/neko_the_shadow/items/67e96e613b7f06ddc5fc)

## 実装

```
#!/bin/sh

tweet1="忙しくてついったいじれない"
tweet2="さみしい"
tweet3="つらい"

echo ${tweet1:0:1}${tweet2:0:1}${tweet3:0:1}
```

```
 ~/tmp ./zunda.sh
忙さつ
```
Storyblokのdocs翻訳チャレンジその15！！！

# イントロダクション

マネジメントAPIであなたがアクセスできるすべてのデータをStoryblokから読み込んだり書き込んだりしてみましょう。これはStoryblokの機能を拡張するのにも使えます。例えば他のソースからデータをインポートするといったことです。

## レート制限

マネジメントAPIはフリープランで3リクエスト毎秒に、その他のプランで5リクエスト毎秒にレートが制限されています。

## 認証(Authentication)

認証に取り掛かる最も簡単な方法は、Storyblok appを使ってOAuth2トークンを生成することです。app.storyblok.comの[My Account](https://app.storyblok.com/#!/me/account)へ飛び、"Generate new token"をクリックします。

OAuth2トークンを使用することで、ユーザーネームとパスワードを永続的に格納しておく必要が無くなり、アクセスをいつでも取り消すことができます。

## 例

Node.js

```javascript
var axios = require('axios')

axios.get('https://api.storyblok.com/v1/spaces', {
  headers: {'Authorization': 'YOUR_AUTH_TOKEN'}
})
.then(function (response) {
  console.log(response.data)
})
.catch(function (error) {
  console.log(error.response.data)
})
```

Ruby

```ruby
gem 'redis'

RestClient.get 'https://api.storyblok.com/v1/spaces',
    {:Authorization => 'YOUR_OAUTH_TOKEN'}
```

PHP

```php
$request = new HttpRequest();
$request->setUrl('https://api.storyblok.com/v1/spaces');
$request->setMethod(HTTP_METH_GET);

$request->setHeaders(array(
  'Authorization' => 'YOUR_AUTH_TOKEN'
));

try {
  $response = $request->send();

  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
```
Bootstrapでcol-md-offset-2の空白が効かない。

#Bootstrapで空白を開けたい！
調べて見ると何やら`col-md-offset-2`とクラスを与えて上げるだけOKみたい…
と思いきや何故か効かない。

*調べて見るとBootstrapの3と4で書き方が違うらしい。。。*

##Bootstrap3とBootstrap4で書き方が違う！

#### Bootstrap3

これが3のバージョンでの書き方！→`col-md-offset-2`

```html
<div class="row">
    <div class="col-md-6 col-md-offset-2">
        これで２カラム分の空白が左の要素にできる！
    </div>
    <div class="col-md-2">
        右に２カラムを余らせる！
    </div>
</div>
```

#### Bootstrap4

これが4のバージョンでの書き方！→`offset-md-2`

```html
<div class="row">
    <div class="col-md-6 offset-md-2">
        これで２カラム分の空白が左の要素にできる！
    </div>
    <div class="col-md-2">
        右に２カラムを余らせる！
    </div>
</div>
```
ずんだの縦読み問題 JavaScript編

[ずんだの縦読み問題 Ruby編](https://qiita.com/tbpgr/items/90abccf8297be0e42f8c)

↑こちらのコメント欄に `JavaScript` で回答しちゃいましたが、記事化しました。

もっとスマートにできる気がしますが、今の自分の実力ではこんな感じです。`回答1` の方は、`trim()` を使わなくても結果としては大丈夫ですが、気持ち悪かったので。

__派生ネタ__

* [ずんだの縦読み問題 Perl編](https://qiita.com/sapi_kawahara/items/19fcdc074fab6d55acd5)
* [ずんだの縦読み問題 php編](https://qiita.com/higuyume/items/7d3c03ddbbd6f4ad7aa1)
* [ずんだの縦読み問題 Java 12 Early-Access 版](https://qiita.com/neko_the_shadow/items/67e96e613b7f06ddc5fc)
* [ずんだの縦読み問題 Go編](https://qiita.com/kentfordev/items/d9a78e34d1e8bf2e703a)
* [ずんだの縦読み問題 ShellScript編](https://qiita.com/VTRyo/items/8b353631711ac7e059bf)
* [ずんだの縦読み問題 Nim編](https://qiita.com/kentfordev/items/c256eaba2f32f89049e1)
* [ずんだの縦読み問題 JavaScript編 @erukitiさん](https://qiita.com/erukiti/items/49ccb0211a18b6bef44a)
* [ずんだの縦読み問題 Python編](https://qiita.com/Aizack/items/60ebd4d1e25ed671b86a)
* [ずんだの縦読み問題 Brainf**k編](https://qiita.com/angel_p_57/items/dade937b14eef2f4d866)

__※追記あり 2018年9月30日__
コメントにて @mascii さんより、回答2の改善したものを教えていただきましたので、以下のコードに追記しました。

# JavaScript

```javascript

const tweet = `
忙しくてついったいじれない
さみしい
つらい
`

// 回答1
console.log(tweet.trim().split("\n").map((s)=>s[0]).join(""))
// => 忙さつ

// 回答2
console.log(tweet.match(/(.)(.*)(?!\n)/g).map((s)=>s[0]).join(""))
// => 忙さつ

// 回答3 (@mascii さんより)
console.log(tweet.match(/^(.)/mg).join(""))
// => 忙さつ
```
[SeleniumWebdriver][Ruby]よく使う操作をモジュール化

今回は SeleniumWebdriver のお話になります。

Selenium では、Wait の処理をある程度してくれる機能はないので、
クリック前に１呼吸置きたい！
とか、
文字を入力する前に、必ず削除から入りたい！
とか、
その人、そのシステムによって、いろいろ出てくると思います。
なので、じゃあ作っちゃおう！というコーナーになります。

```operation_module.rb
# モジュールとして定義させます
module Operation
	# 1呼吸置いてからクリックモジュール
	def click(object)
		sleep 1
		object.click
	end

	# 削除してから入力モジュール
	def input(object,input_string)
		object.clear
		object.send_key "#{input_string}"
	end

    # これを忘れるとめっちゃ怒られます
	module_function :click
	module_function :input
end
```

やろうとしている操作は[[TestCafe]ページモデルを使用してみる](https://qiita.com/t_y_cafe/items/ce5f44c49f3c9e582857)と同じです。
他にもテスト用のモジュールを作って、そちらも呼び出します。

```Test.rb
require 'selenium-webdriver'
require_relative 'operation_module'
require_relative 'test_module'

driver = Selenium::WebDriver.for :chrome
driver.get "http://devexpress.github.io/testcafe/example/"

DisplayTitle = "Example"
MyName       = "t_y_cafe"
OutputResult = "Thank you, t_y_cafe!"

# ページ要素
Title        = driver.find_element(:xpath,'//*[@id="main-form"]/div/header/h1').text
NameBox      = driver.find_element(:id,'developer-name')
SubmitButton = driver.find_element(:id,'submit-button')


# 画面タイトル確認
Test::equal(Title,DisplayTitle)

# 名前入力
Operation::input(NameBox,MyName)

# submit
Operation::click(SubmitButton)

# 出力確認
OutputText   = driver.find_element(:id,'article-header').text
Test::equal(OutputText,OutputResult)

driver.quit
```

SeleniumWebdriver ではこうやってよく使う操作なんかはモジュール化して
好きなようにカスタマイズできるのがとても楽しいですね。
「好きなようにカスタマイズ」って言葉がもう、たまらないですね。
[Laravel5.7] Gmailの送信設定項目(設定項目のみの紹介)

Gmailでメール送信の設定をする場合の設定項目

```:.env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME={{ email }}
MAIL_PASSWORD={{ password }}
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS={{ email }}
MAIL_FROM_NAME={{ sender_name }}
```

以上の項目を設定するだけで、あとはgmailのアカウントさえ作成されていれば設定は完了。

# 送信テスト方法
`php artisan tinker`でLaravelのコンソールを立ち上げ、以下を実行すれば`to()`の指定先にメールが送信される。

```php
Mail::raw('Send test message.', function($message) {
    $message->to('test@example.com')->subject('test mail');
});
```
[TestCafe]ページモデルを使用してみる

自動化を実装していると、同じ要素を何度も操作したり、
同じ期待値が何度も出てきたり、というのはよくあることだと思います。

なので、その都度要素を指定しているとあとあと面倒になってきます。
何らかの修正が入り、要素の id や class が変わったりすると、
それに合わせてテストコードを修正するのは正直面倒です。

メンテナンスに工数が掛かる為、下手したらいらない子になってしまいます。
テスト規模が大きければ尚更ですね。

なので、要素は要素、操作は操作のクラスを作っておくと、
要素変更に合わせた修正は要素のファイルのみでよくなります。

以下は、TestCafe のチュートリアル画面から必要な要素のみを纏めたものになります。

```page_object.js
import { Selector } from 'testcafe';

export default class page {
    constructor () {

    /* -------------------------- */
    /* 入力画面                    */
    /* -------------------------- */
        // 画面タイトル
        this.pageTitle      = Selector('h1').withText('Example');
        
        // 名前インプットボックス
        this.boxNameInput   = Selector('#developer-name');

        // ボタン:submit
        this.buttonSubmit  = Selector('#submit-button');

    /* -------------------------- */
    /* 出力画面                   */
    /* -------------------------- */
        // 出力文字列
        this.outputText    = Selector('#article-header');

    }
}
```

この要素を使用して、操作するクラスを作ります。
画面タイトルを確認し、名前を入力してsubmitボタンを押して、
遷移先の表示を確認します。

```operation.js
// ここで先程のオブジェクトクラスを指定しています
import PageObject   from './page_object';


const page   = new PageObject();

// ついでに期待値もここで指定してしまいます
const title  = 'Example';
const myname = 't_y_cafe';


fixture('Getting Started').page('http://devexpress.github.io/testcafe/example');
test('My second test', async t => {
    await t
        
        // 画面のタイトルを確認
        .expect(page.pageTitle.textContent).eql(title)

        // 名前を入力
        .typeText(page.boxNameInput,myname)

        // 登録する
        .click(page.buttonSubmit)

        // 画面出力確認
        .expect(page.outputText.textContent).eql('Thank you, '+ myname + '!');
});
```

今回は、要素の一部をページオブジェクトパターンとして１クラスに纏めてみましたが、
画面が増えていってもやはりこの手法は有用だと思います。
LineChatBotの完成度を上げられる？Chips集(AWARDS追い込み用)

# 本記事の目的
LINEのAWARDS追い込み時期ということもあり、前回応募時に追い込みで対応した（一部機能制限あり）内容を共有する。
# Chips
## チュートリアル （動画）表示
友達登録時にチュートリアルの動画を表示する

- [followイベント](https://developers.line.me/ja/reference/messaging-api/#anchor-d2c981e5b9ab6aaca253183f323798541a101b5f)のリプライとして動画を送信
- [メッセージオブジェクト](https://developers.line.me/ja/reference/messaging-api/#anchor-e2c59da01216760e81e8ca10c55b2e28b276c3e5)の一種 [動画](https://developers.line.me/ja/reference/messaging-api/#video-message) として送信(再生可能なコンテンツの制限に注意)
  - 動画ファイルのURL（最大文字数：1000）
  - 最大長：1分
  - 最大ファイルサイズ：10MB

## スタンプ 転送
ユーザAからBotに送信されたスタンプをユーザBに転送する

  - [スタンプ](https://developers.line.me/ja/reference/messaging-api/#wh-sticker)オブジェクトとして受信したものをユーザBにPushする
  - [送信可能スタンプ](https://developers.line.me/media/messaging-api/sticker_list.pdf)に制限があることに注意
    - 送信可能でないスタンプがユーザAから送信されてきた場合、対応されていない旨のメッセージをユーザAに返す必要がある
    - 今年追加された標準スタンプも送信可能スタンプに含まれるようになった

## 絵文字 転送
ユーザAからBotに送信された絵文字をユーザBに転送する

- [テキスト](https://developers.line.me/ja/reference/messaging-api/#anchor-3190c42099a69c9e5c7f734707fe34b9fd1710fd)オブジェクトとして受信したものをユーザーBにPushする
- 以下の絵文字を含めることができる
  - Unicodeで定義された絵文字:特別な対応は不要
  - LINEが独自に定義した絵文字：対応可能なもの（後述の"送信可能絵文字"）は変換（要実装）したコードでPushする
- LINEが独自に定義した絵文字の中で[送信可能絵文字](https://developers.line.me/media/messaging-api/emoji-list.pdf) でないものは絵文字に変換しないままPushする

# まとめ
AWARDS締め切り直前にメンバに対して安易に「できますよ！！」と言ってしまい、「ハマる」ということがないよう参考にしていただければと考える。
GithubにPushしたら自動で更新させる

# 環境
・Linux（CentOS release 7.4）
・Apache 2.4.6
・MySQL 5.7
・PHP 7.1

#参考にする場所
[How to Handle GitHub Webhooks Using Django](https://simpleisbetterthancomplex.com/tutorial/2016/10/31/how-to-handle-github-webhooks-using-django.html)
fullEnglishしかねーのかよ...しびれるなぁ

#Cloneする
```text:CentOS（/home/op/app02/public_html/）
$ cd /home/op/app02/public_html/
$ git clone https://github.com/duri0214/Visualstudio-Django.git
  Cloning into 'Visualstudio-Django'...
  remote: Counting objects: 110, done.
  remote: Compressing objects: 100% (6/6), done.
  remote: Total 110 (delta 0), reused 1 (delta 0), pack-reused 104
  Receiving objects: 100% (110/110), 399.25 KiB | 0 bytes/s, done.
  Resolving deltas: 100% (19/19), done.
  Checking connectivity... done.
$ ls
  Visualstudio-Django   #増えた
```

#現時点のDiff
このリポジトリはローカルPCでいままでVPSに直で書いたものを再現しているもので、そこから接ぎ木した部分のDiff
https://github.com/duri0214/Visualstudio-Django/commit/10a0d9f6c70caf41f34ac2d1ebc255694981cbb0
![image.png](https://qiita-image-store.s3.amazonaws.com/0/94562/c98831de-0f7c-0b8d-e592-74f789dcd45d.png)


#ネームサーバーもapp02で設定
さくらのVPSの場合は、この設定ページにも書いてあるけど「データ送信」を押さないと「app02」が増えないので注意！
[ネームサーバーを設定](https://qiita.com/YoshitakaOkada/items/117c60a105fd895e41c7#%E3%83%8D%E3%83%BC%E3%83%A0%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E8%A8%AD%E5%AE%9A)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/94562/f9477fec-71d5-e2d6-e6fa-ad7c3ac11979.png)


#GithubWebhook
いわば更新情報の送信先だ。
http://app02.henojiya.net/api/byGithubUpdate に送信される
![image.png](https://qiita-image-store.s3.amazonaws.com/0/94562/b2cb46c8-67a0-3e7f-c56a-719b137d2cf2.png)

#Apacheの設定を変更して導線確保
バーチャルホストを増やします
[このへん](https://qiita.com/YoshitakaOkada/items/117c60a105fd895e41c7#%E3%83%90%E3%83%BC%E3%83%81%E3%83%A3%E3%83%AB%E3%83%9B%E3%82%B9%E3%83%88) 見てね
下のソースを見ると、コメントアウトされてる「★」があるけど、わざと潰している（後述）

```text:CentOS
$ su -
# vim /etc/httpd/conf/httpd.conf
```

```
<VirtualHost *:80>
  ServerName app02.henojiya.net
  DocumentRoot "/home/op/app02/public_html/Visualstudio-Django/"
  #★ WSGIScriptAlias / /home/op/app02/public_html/Visualstudio-Django/pj/pj/wsgi.py
  <Directory /home/op/app02/public_html/Visualstudio-Django/pj/>
    <Files wsgi.py>
      Require all granted
    </Files>
  </Directory>
  Alias /static/ /home/op/app02/public_html/Visualstudio-Django/pj/app/static/
  <Directory /home/op/app02/public_html/Visualstudio-Django/pj/app/static>
    Require all granted
  </Directory>
</VirtualHost>
```

```text:CentOS
# systemctl restart httpd
```

#django apache 複数 プロジェクト
コメントアウトされてる「★」がある...と書いたが、これをコメント解除すると Internal Server Error が起きるんだよね。app01も影響を受けて Internal Server Error になる。wwwのほうは影響を受けなかったのは「Pythonがらみを使っていないから」と思われる。

ひとつひとつコメントアウトして「WSGIScriptAlias」が原因であると特定した。その後ググってわかったのが、どうやらWSGIScriptAlias が複数あるとプロセスがケンカするらしいってこと。

#まだ調査中（誰か教えて！）
https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIProcessGroup.html
present?メソッドとpresenceメソッドの違い

## present?メソッドとは

対象のオブジェクトがnil, "", " "(半角スペース), [](空配列), {}(空のハッシュ)の時にfalase,それ以外の場合はtrueを返すメソッド(!blank?と同じ）。

```ruby
engineer = 'aoki'
engineer.present?
=> true

engineer = nil
engineer.present?
=> false

engineer = ""
engineer.present?
=> false
```


## presenceメソッドとは

`present?の結果がtrue`の時、`レシーバ自身`を返し、`present? の結果が false のときは nil を返すメソッド。

```ruby
engineer = 'aoki'
engineer.presence
=> 'aoki'

engineer = nil
engineer.presence
=> nil

engineer = ""
engineer.presence
=> nil

```

## 参考

[ActiveSupport の便利メソッド: try, blank?, present?, presence]
(http://www.techscore.com/blog/2012/12/25/activesupport-%E3%81%AE%E4%BE%BF%E5%88%A9%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89-try-blank-present-presence/)
Google Maps API入門(ドットインストール)

ドットインストールから参照。Google Maps API入門メモ。

# 01 Google Mapsを使ってみよう
* 開発者向けの公式サイトは https://developers.google.com/maps/?hl=ja

# 02 描画の準備をしよう
* 日本語設定で使いたい場合は ?language=ja
* さらに、地域の設定を日本にしたい場合は &region=JP
* API が読み込まれたあとに実行するコールバック関数を指定
* 今回使う API では非同期でスクリプトを読み込むことが推奨されているので、 async 属性と defer 属性をつける

# 03 APIキーを取得しよう
* Google API Console でプロジェクトを作成し、API キーを発行

# 04 マップを描画してみよう
* var target としてあげて、 document.getElementById で取得

```index.html
<script>
  function initMap() {
    'use strict';
    var target = document.getElementById('target');
    var map;
    var tokyo = {lat: 35.681167, lng: 139.767052};

    map = new google.maps.Map(target, {
      center: tokyo,
    }); 
</script>
```

# 05 マップのオプションを見ていこう
* disableDefaultUI=全画面表示だとかの UI を無効化するためのオプション
* 衛星写真にしたい場合は `mapTypeId: 'satellite'`

# 06 マップにイベントを設定してみよう
* イベントを設定するには、 map に対して addListener とする
* クリックした箇所の緯度経度を表示する。 e.latLng.lat() で緯度、 e.latLng.lng() で経度が取得

```
map.addListener('click', function(e) ({
  console.log(e.latLng.lat());
  console.log(e.latLing.lng());
});
```

# 07 マーカーを表示してみよう
* marker をどの map に配置したいかを指定
* title で marker にホバーした時の文字列を指定

```
marker = new google.maps.Marker({
  position: tokyo,
  map: map,
  title: 'Tokyo!',
  icon: 'icon.png'.
  animation: google.maps.Animation.BOUNCE
});
```
* ストンと落ちるような DROP も指定可能

# 08 インタラクティブにマーカーを操作しよう


# 09 情報ウィンドウを表示させよう
* 地図上に情報ウィンドウを配置。そのための変数を用意してあげて、この辺りでインスタンスを作る。
* 情報ウィンドウを表示するには、infoWindow.open(map); としてあげて、表示する map を指定

# 10 マーカーと情報ウィンドウを紐付けよう
* infoWindow.open(… 、とするが map に配置しつつ、 marker に紐付けたい場合は、このように書けば OK.

# 11 ジオコーディングを使ってみよう
Geocoding と、それから Reverse Geocoding について

* eocoding が、住所を緯度・経度に変換する仕組み。Reverse Geocoding はその逆
* つまり緯度・経度から住所を割り出す仕組み

# 12 住所を緯度経度に変換しよう
* address キーにしつつ、 form に入力された値を渡してあげれば OK.
* status を調べて 'OK' 以外だったら、処理を中断してあげる

```
document.getElementById('search').addEventListener('click', function() {
  geocoder.geocode({
    address: document.getElementById('address').value
  ), function(results, status) {
    if (status !== 'OK') {
      alert('Failed: '+ status);
      return;
    });
});
```

# 13 リバースジオコーディングを使おう
* マップをクリックした時の処理
* map とした後に addListener をくっつけてあげて、クリックした時に次の処理を行いなさいと書いていけば OK

# 14 緯度経度から住所を割り出そう
* everse Geocoding の場合は location で緯度・経度を渡してあげる。

# 15 Places APIを使ってみよう
* API を読み込む URL に $libraries=places と付ける必要があるので注意

# 16 施設情報を検索してみよう
* OK だったらなんらかの処理をして、 OK じゃなかったら alert('Failed:' status) を出してあげて、処理を中断してあげる

# 17 Geolocationを使ってみよう
* eolocation と Google Maps API を組み合わせることもよくある
Laravelでvue.jsを反映させるには、ハードリロードが必要だった(自動化もあった)

##Vueの更新が反映されず泣く（キャッシュの奴め）:

Laravel5.6で、vueのcomponentファイルを更新し、(/resources/assets/js/components内)
「npm run watch」とかしても、
「build success」と出るのに、なぜかvueコンポーネント内容が更新されず、かなり悩まされました。

しばし悩んで、とあるチュートリアル動画を見ていたら、
「**ハードリロードが必要**」というので、やってみると無事更新反映。

考えてみれば、jsファイルがキャッシュされるのは当たり前ですが、
「npm run watch」でその辺も面倒見てくれるのかと思ってしまい、理由になかなか気づけませんでした（汗

思わぬ落とし穴で時間食ったので、私同様ハマった方向けにメモを残します。


追記：最初のハードリロード以降は、無事私の環境では、run watchも機能してくれていますが、
やはり時々、ハードリロードが必要です。

##更に追記(キャッシュ回避自動化)：
以下を教えていただき、**キャッシュ回避が自動**でできるようになりました。ありがたし。
https://qiita.com/ryosukes/items/24a556b9e634c183f93b#ブラウザキャッシュの対策できんの

「キャッシュ回避に、URLパラメータを毎度更新するのが面倒だな」と思ってたので、これは便利でした。
ワイルドアームズのアプリが公開されたので、テキストをWAっぽくするブックマークレットでも作る

昔によく遊んだので、懐かしくって……(˘ω˘)
多分、需要は自分にしかないんじゃないかな！

# jsを実装！

```xtu.js
(function (baseDom) {
	const change = function (text) {
		return text.replace(/っ([!！])/g, function (m, p1) { return "ッ" + p1; }).replace(/([^<ッ!！?？])([!！])/g, function (m, p1, p2) { return p1 + "ッ" + p2; });
	}
	const replace = function (dom) {
		if (["IFRAME", "SCRIPT", "NOSCRIPT", "STYLE"].indexOf(dom.tagName) >= 0) {
			return;
		}
		if (dom.children.length > 0) {
			Array.from(dom.children).forEach(replace)
		} else if (dom.innerText && dom.innerText.trim().length > 0) {
			dom.innerText = change(dom.innerText);
		}
	}
	replace(baseDom);
})(window.document.body)
```

scriptタグだけは書き換えずにエラーにならないようにしてみる。

```ng.html
<h1>
ほげほげ！
<span>ふがふが！</span>
</h1>
```

ただこれだと、上みたいなサイトで上手くいかないんだよな……どうしたものかな。

# 最小化！

```minify.js
(function(a){const c=function(d){return d.replace(/っ([!！])/g,function(e,f){return"ッ"+f}).replace(/([^<ッ!！?？])([!！])/g,function(e,g,f){return g+"ッ"+f})};const b=function(d){if(["IFRAME","SCRIPT","NOSCRIPT","STYLE"].indexOf(d.tagName)>=0){return}if(d.children.length>0){Array.from(d.children).forEach(b)}else{if(d.innerText&&d.innerText.trim().length>0){d.innerText=c(d.innerText)}}};b(a)})(window.document.body);
```

# ブックマークレット用のURLを作成！

```bookmarklet
javascript:(function(a){const c=function(d){return d.replace(/っ([!！])/g,function(e,f){return"ッ"+f}).replace(/([^<ッ!！?？])([!！])/g,function(e,g,f){return g+"ッ"+f})};const b=function(d){if(["IFRAME","SCRIPT","NOSCRIPT","STYLE"].indexOf(d.tagName)>=0){return}if(d.children.length>0){Array.from(d.children).forEach(b)}else{if(d.innerText&&d.innerText.trim().length>0){d.innerText=c(d.innerText)}}};b(a)})(window.document.body);;
```

# ブックマークへの登録！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/24381a67-d6ec-f69d-0109-08bd29c27cd9.png)

chromeであればブックマークツールバーから、上のような形で登録ができるよ！

# 試さずにはいられない！

<img width=300 src="https://qiita-image-store.s3.amazonaws.com/0/235100/0584f084-14fa-f4ee-fc33-df60d875dd8b.png"/>

ちょっと感嘆符の勢いが足りない公式サイトでも

<img width=300 src="https://qiita-image-store.s3.amazonaws.com/0/235100/c29d8394-f634-8603-da8c-cf354e547c03.png"/>

この通り！！


# 感想！

:gun:こんなことをやっていないでイベントを回ってこよう🧛