OmniAICreator/Qiita-1.07M huggingface dataset:
MTKViewとCAMetalLayerの実装差分

海外のMetalの解説書を読むと、大抵の場合、画面への描画にはまず`CAMetalLayer`を使う。`MTKView`ではなく。

この理由はわかる。**`MTKView`はラッパークラスであって、内部的には`CAMetalLayer`を使っている**。ので、まずは`CAMetalLayer`から学んでいこう、と。

> An MTKView object is backed by a CAMetalLayer object

https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/Drawables.html

それは正しいと思うが、個人的にはGPUプログラミング初心者は`MTKView`から始めたほうがいいと[思っている](https://booth.pm/ja/items/826318)。新しい概念がたくさん登場するので、ラッパーで簡単化できる部分があるのならその恩恵にあずかったほうが挫折の可能性が下がるかなと。

で、`MTKView`は、`CAMetalLayer`を直に使うことに比べて、具体的に何をどのように簡単化してくれているのだろうか。そのへんを整理するため、実装差分をこの記事で書き出してみる。

## 初期化

- `MTKView`の場合

```swift
let mtkView = MTKView(frame: frame)
```

- `CAMetalLayer`の場合

```swift
metalLayer = CAMetalLayer()
metalLayer.frame = frame
```

内部ではいろいろとあるかもしれないが、API的には`frame`をイニシャライザでセットできるかどうかの違いしかない。


## セットアップ

- `MTKView`の場合

```swift
mtkView.device = device
view.addSubview(mtkView)

mtkView.delegate = self
```

- `CAMetalLayer`の場合

```swift
metalLayer.device = device
view.layer.addSublayer(metalLayer)

let link = CADisplayLink(target: self, selector: #selector(onDisplayLink))
link.add(to: .current, forMode: .defaultRunLoopMode)
```

MTKViewはdelegateでループを処理するが、CAMetalLayerの場合は自分でループのしくみを用意する。


## ピクセルフォーマットを合わせる

これは同じ

```swift
metalLayer.pixelFormat = texture.pixelFormat
```

```swift
mtkView.colorPixelFormat = texture.pixelFormat
```

## レンダリングループの実装

- `MTKView`の場合

```swift
func draw(in: view) {
    autoreleasepool {
        render()
    }
}
```

- `CAMetalLayer`の場合

```swift
@objc func onDisplayLink() {
    autoreleasepool {
        render()
    }
}
```

## まとめ

あれ・・・結果としては、そんなに変わらない感じだった。レンダリングループを自前実装するか、delegateを使うか、という差はあるが、そんなに労力が減っている感はない。

簡単になるのは上で省略した、レンダリング時の、ドローアブルとかrender pass descriptorのハンドリングなのかもしれない。

> Using an MTKView object is the preferred way to interact with drawables. An MTKView object is backed by a CAMetalLayer object and provides the currentDrawable property to acquire the drawable for the current frame. The current frame renders into this drawable and the presentDrawable: method schedules the actual presentation to occur at the next display refresh interval. The currentDrawable property is automatically updated at the end of every frame.

> An MTKView object also provides the currentRenderPassDescriptor convenience property that references the current drawable’s texture; use this property to create a render command encoder that renders into the current drawable. A call to the currentRenderPassDescriptor property implicitly acquires the drawable for the current frame, which is then stored in the currentDrawable property.

> If you create your own UIView or NSView subclass that is backed by a CAMetalLayer object, you must explicitly acquire a drawable and use its texture to configure a render pass descriptor. You can also do this for your own MTKView object, but it is much easier to simply use the currentRenderPassDescriptor convenience property. For an example of how to acquire a drawable from a UIView or NSView subclass, see the MetalBasic3D sample.

（https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/Drawables.html）
NYTPhotoViewerの1.2→2.0で遭遇したエラーの解決方法

# はじめに
NYTimesの画像ビュワーOSS、NYTPhotoViewerを使っています。
バージョンを1.2.0→2.0.0に上げたところ、やっぱりひっかかったので、その解決方法をメモします。

# 要点
古いNYTPhotoViewerでは、直接NYTPhotoプロトコルを採用したクラスの配列をデータソースに使えた。しかし、新しいバージョンでは、
NYTPhotoViewerDataSourceプロトコルを採用したcoordinatorにNYTPhotoのデータをセットする考え方に変わった。このため、coordinatorを使う方式に書き換える必要がある。

# 遭遇したエラー

```swift
let photo = MyPhoto()
photo.image = image
let vc = NYTPhotosViewController(photos: [photo])
present(vc, animated: true, completion: nil)
```
という感じの3行目のNYTPhotosViewController()の箇所で

`Argument labels ‘(photos:)’ do not match any available overloads`

というエラーが発生しました。
インターフェース仕様が変更されたということですが、単なるリネームではなさそうです。
(ちなみに、MyPhotoはNYTPhotoプロトコルを採用している画像のデータソースです。)

# 解決

エラーが発生したメソッドをたどると、古いほうのNYTphotosViewController.mでは、

```obj-c:NYTPhotosViewController.m
- (instancetype)initWithPhotos:(NSArray *)photos {
    return [self initWithPhotos:photos initialPhoto:photos.firstObject delegate:nil];
```

というメソッドだったものが、新しい方ではこのメソッドにリプレースされていました。

```obj-c:NYTPhotosViewController.m
- (instancetype)initWithDataSource:(id <NYTPhotoViewerDataSource>)dataSource {
    return [self initWithDataSource:dataSource initialPhoto:nil delegate:nil];
}
```

従来は直接NYTPhotoプロトコルを採用したクラスの配列をデータソースに使えたのですが、新しいNYTPhotoViewerでは、
NYTPhotoViewerDataSourceプロトコルを採用したcoordinatorにNYTPhotoのデータをセットして、coordinatorを渡す発想になっています。

ですので、今までなかったcoordinatorを作れば、解決です。(公式Sampleにいう、[PhotoViewerCoordinator.swift](https://github.com/NYTimes/NYTPhotoViewer/blob/master/Example-Swift/PhotoViewerCoordinator.swift))

キモは、NYTPhotoViewerDataSourceプロトコルを採用すること。

要点を示すために、NYTPhoto一枚分を表示することに特化したcoordinatorを示します。

(なお、公式Sampleでは、NYTPhotoBoxというクラスも登場しますが、画像を1枚だけ見せたいという簡易な場合はNYTPhotoBoxは割愛できるので、ここでは省略して進みます。)

```PhotoViewerCoordinator.swift
class PhotoViewerCoordinator: NYTPhotoViewerDataSource {
    private var photos: [NYTPhoto]?
    
    lazy var photoViewer: NYTPhotosViewController = {
        return NYTPhotosViewController(dataSource: self)
    }()

    init(photos: [NYTPhoto]?) {
        self.photos = photos
    }
    
    @objc
    var numberOfPhotos: NSNumber? {
        return NSNumber(integerLiteral: 1)
    }
    
    @objc
    func index(of photo: NYTPhoto) -> Int {
        return 0
    }
    
    @objc
    func photo(at index: Int) -> NYTPhoto? {
        return photos?.first
    }
}
```

使うところでは、

```swift
let photo = MyPhoto()
photo.image = image
let coordinator = PhotoViewerCoordinator(photos: [photo])
let vc = NYTPhotosViewController(dataSource: coordinator)
present(vc, animated: true, completion: nil)
```

と書き換えてあげれば、今までのように使えますね。
C言語のインクリメント

#はじめに
C言語のインクリメントについてよく忘れるのでメモを残しておきます。
+を-と置き換えればデクリメントにも当てはまります。

#種類
```c
	x = x+1; /* 通常 */
	++x;     /* プリインクリメント */
	x++;     /* ポストインクリメント */
	x += 1;  /* 代入演算子 */
```
4種類ともxを1増加させています。
前後でxを利用していなければどれも同じです。
`++x`はプリインクリメントと呼ばれ、式で使用される前にxが1増加します。
`x++`はポストインクリメントと呼ばれ、式で使用された後にxが1増加します。
`+=`と書く代入演算子は`x = x+1`と同じ意味です。

#例
上記の複合パターンは奥深いため、まとめてみました。
##通常+代入演算子
```c
	array[i=i+1] += j;
=>	
	i++;
	array[i] = array[i] + j;
```
配列要素は優先度が高いため先に計算されます。
また`array[i=i+1] = array[i=i+1] + j;`とはなりません。

##代入演算子+代入演算子
```c
	array[i+=1] += j;
=>	
	i++;
	array[i] = array[i] + j;
```

##ポストインクリメント+代入演算子
```c
	array[++i] += j;
=>
	i++;
	array[i] = array[i] + j;
```

##プリインクリメント+代入演算子
```c
	array[i++] += j;
=>	
	array[i] = array[i] + j;
	i++;
```

##プリインクリメント+ポストインクリメント+代入演算子
```c
	array[++i + j--] += --k;
=>	
	i++;
	k--;
	array[i + j] = array[i + j] + k;
 	j--;
```

ここまでくると読みにくいので書かないと思いますが、このようになります。
Swift Package Manager 邦訳と使い方


# Package Manager 邦訳

https://swift.org/package-manager/


## Package Manager

Swiftコードを配布するための管理ツールである。
関連ソースファイルのダウンロード、コンパイル、リンクを自動化するためのSwiftビルドシステムが統一化される。

swift3.0以上で使える。

## Modules
Swiftはモジュールとしてコードを構成する。
それぞれのモジュールは名前空間を特定し、コードがモジュールの外側で使用される際は、アクセスコントロールを強制する。

プログラムは、最低限一つのモジュールに全てのコードを持つ。
またもしくは、`dependencies` としてその他のモジュールをインポートしている。
システムが提供するモジュール(macOSのDarwin, LinuxのGlibc)を除いて、`dependencies` を使用するためには、それらがダウンロードとビルドされる必要がある。

特定のプログラムを解決するコードをモジュールとして分離して使用すると、それらのコードは他でも再利用することが可能となる。
例として、ネットワークリクエストをする機能を提供するモジュールは、写真共有アプリやお天気アプリで共有できる。
モジュールを使用すると、自分自身で同様の機能を再実装するのではなく、他の開発者のコードをベースに構築することが出来る。

## Package

パッケージは、ソースファイルとマニフェストからなる。
マニフェストは `Package.swift` と呼ばれ、`PackageDescription` モジュールを用いて、パッケージ名とでその中身を定義している。

パッケージは一つもしくはそれ以上の `target` を持つ。
それぞれの `target` は 成果物(product) を指定する。
また一つ以上の `dependencies` を宣言ことが可能である。


## Products

`target` は その成果物(product)として、 `library` もしくは `executable` のどちらかをビルド出来る。
`library` は他のSwiftコードにインポートする事が可能なモジュールを含む。
`executable` はOSで実行することが出来るプログラムである。

## Dependencies

targetの `dependencies` はそのパッケージのコードによって必要とされるモジュールである。
一つの `dependency` は、そのパッケージのソースへのURLと使用することができるパッケージのバージョンのセットからなる。
パッケージマネージャーの役割は、プロジェクトの全ての `dependencies` のダウンロードとビルドプロセスを自動化することによって「coordination コスト」を減らすことである。
これらは再帰的な処理である。(一つの `depencency` はそれ自身の `dependencies` を持ち、またそれぞれ `dependencies` を持つ事ができ、`dependency graph` を構成する。)
Package Managerは全ての `dependency graph` を満たすために、全てをダウンロードしてからビルドする。

---

# パッケージ関連コマンド

## パッケージの初期化

```terminal
$ swift package init
```

* オプション
	* --type
		* library ライブラリーパッケージの作成、デフォルト
		* executable 実行可能パッケージの作成

ex: 実行可能パッケージの作成例

```terminal
$ mkdir battle_ship
$ cd battle_ship
$ swift package init --type executable
$ swift run # 実行
```

**NOTE:**

* main.swiftファイルが作られる
* `Sources` ディレクトリ配下に、その他の必要なソースファイルを追加していく
* `swift run` で実行できる


## パッケージのビルド

```terminal
$ swift build
```

## パッケージのテスト

```terminal
$ swift test
```


## 実行可能パッケージの実行

```terminal
$ swift run
```

## モジュールの追加 (依存関係の追加）

以下マニフェストファイル(Package.swift)に追記する

* dependenciesへのパッケージの追加
* 使用するtargetのdependenciesに追加

ex: SwiftStreamの追加

dependenciesに追記

```Package.swift
...
    dependencies: [
        // 依存するモジュールを追加
         .package(url: "https://github.com/ysn551/SwiftStream.git", from: "1.0.0"),
    ],

```

targetのdependenciesに追記

```Package.swift
...
    targets: [
        .target(
            name: "PackageSample",
            // targetが使用する場合は、追加する
            dependencies: ["SwiftStream"]),
        .testTarget(
            name: "PackageSampleTests",
            dependencies: ["PackageSample", "SwiftStream"]),
    ]
```


## モジュールの更新

```terminal
$ swift package update
```
Movidius Neural Compute StickをMac+VMWare Fusionで動かす

#概要
Macでディープラーニングやーてことで、
Mac+VirtualBoxで動かなかったので、VMWare Fusionで再チャレンジしました。
<img width="643" alt="IMG_6814.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/195932/d2a0f599-3aa7-6a94-6746-36ccaad86500.jpeg">

#環境
##Mac
- MacBook Pro (Retina, 13-inch, Late 2013)
- プロセッサ：2.4 GHz Intel Core i5
- メモリ：16 GB 1600 MHz DDR3
- macOS Sierra 10.12.6

##VMWare Fusion
- バージョン 8.5.10 (7527438)

##Ubuntu（仮想マシン）
Ubuntuはお手軽に[日本語Remix](https://www.ubuntulinux.jp/News/ubuntu1604-ja-remix)を使いました。

#つまづいたところ
##apt updateでエラー
Ubuntuインストール直後、apt updateしようとするとエラーになります。
これは既知の問題で、appstreamcliが原因なので、[この記事](http://shimolab01.blogspot.jp/2017/09/ubuntuappstreamcli.html)を参考に対処しました。

##NC SDKのインストールでエラー
[公式のQuick Start](https://developer.movidius.com/start)に沿って、インストールを進めたのですが、

```
$make install
```

を実行すると、

```
Installation failed. Error on line 485
```

と表示され、失敗しました。
フォーラムに[該当する投稿](https://ncsforum.movidius.com/discussion/475/make-install-failed)があったので、コメントを参考にしgitでバージョンを指定しcheckout後、makeすると成功しました。

```
$git checkout v1.10.00.03
$make install
```

##exampleのビルドでエラー
NC SDKのインストール後、サンプル実行させようと、

```
$cd examples/caffe/GoogLeNet && make
```

とすると、

```
Caffe Import Error
```

というエラーが発生しました。
フォーラムに[類似の投稿](https://ncsforum.movidius.com/discussion/323/caffe-import-error-with-fresh-installed-sdk-help-ncsdk-1-09-00-04-x86-64-ubuntu-16-04)があったので参考にして、

- PYTHONPATH環境変数の設定
- OpenCVのインストール
- python decoratorの再インストール

とやって、何が効いたかわかりませんが、もう一度make installすることで解決しました。

##VMWare FusionにMovidius NCS接続
仮想マシンのUbuntuにNCSを接続するために、VMware Toolsのインストール、VMWare Fusionの設定が必要です。

VMWare Toolsのインストールは、[この記事](https://qiita.com/suppy193/items/7c6905003c02a697f159)を参考に行いました。

USBの設定は、仮想マシンが停止している状態で、設定->USBとBluetoothを開き設定します。
詳細USBオプションのUSB互換性をUSB3.0に指定することをお忘れなく。
<img width="643" alt="Ubuntu__64_ビット__16_04__USB_と_Bluetooth_と_Ubuntu__64_ビット__16_04.png" src="https://qiita-image-store.s3.amazonaws.com/0/195932/f3251a53-7cf1-ac81-b839-55113683cc44.png">

#サンプルの実行
GoogLeNetを使って画像分類を行うサンプルを実行してみます。
サンプルコードは、入力の画像ファイルパスをハードコーディングしてあるので、実行時に引数で指定できるように変更しました。
入力した画像ファイルはこちらです。
![gorilla.jpg](https://qiita-image-store.s3.amazonaws.com/0/195932/73cbd9dd-9518-e600-110d-697f0f37cf15.jpeg)


実行すると、
> prediction 0 (probability 0.979) is n02480855 gorilla, Gorilla gorilla  label index is: 366
> prediction 1 (probability 0.008675) is n02483362 gibbon, Hylobates lar  label index is: 368
> prediction 2 (probability 0.00828) is n02481823 chimpanzee, chimp, Pan troglodytes  label index is: 367
> prediction 3 (probability 0.001655) is n02483708 siamang, Hylobates syndactylus, Symphalangus syndactylus  label index is: 369
> prediction 4 (probability 0.001351) is n02487347 macaque  label index is: 373

ちゃんと'gorilla'と認識されました。
Mosquitto で Username と Password を使う

次のページを参考にしました。
[Mosquitto Username and Password Authentication -Configuration and Testing](http://www.steves-internet-guide.com/mqtt-username-password-example/)

Ubuntu 24.04 でのソフトのインストール方法

```bash
sudo apt install mosquitto
sudo apt install mosquitto-clients
```

1 password.txt というファイルを作成します。

```text:password.txt
steve:password
jim:topsecret
```

2 このファイルを暗号化します。

```bash
mosquitto_passwd -U password.txt
```

次のようなファイルに変換されます。

```text:password.txt
steve:$6$4lRl06+qx3nS+0Gx$SZUEnAv/2u+RhIHJV7lM4NHh7R8AZcrtW1lqdqJ77N36meVnya+lvkX++/S1J+JzBrGWiLG5B20e8tfk1hM9oQ==
jim:$6$JtT1tjFAMAaxMQCt$hZc7Uuaa8UAwC61p/oy3JUAe0kExDskehtKwD6YRUezOajYHT7ZQcpX+1g3ofjsDBqs4LpSaHr3e9rAXc5pG+A==
```

3 変換されたファイルを /etc/mosquitto/ にコピーします。

4 /etc/mosquitto/conf.d/robot.txt というファイルを作成

```text:/etc/mosquitto/conf.d/robot.txt
allow_anonymous false
password_file /etc/mosquitto/password.txt
```

5 mosquitto を再起動します。

```bash
sudo systemctl restart mosquitto
```

次は、ローカルでサーバーを動かしている時の接続例です。

## サブスクライブ

```bash
mosquitto_sub -d -t orz \
        -u jim -P topsecret \
        --topic sensors/topic_1
```

## パブリッシュ

```bash
mosquitto_pub -d -t orz -m "こんにちは Feb/09/2018 PM 13:47" \
        -u jim -P topsecret \
        --topic sensors/topic_1
```

パスワードが合っていない場合の実行結果


```text
Client null sending CONNECT
Client null received CONNACK (5)
Connection error: Connection Refused: not authorised.
Error: The connection was refused.
```
Bottleのアクセスログ記録


Pythonの軽量Webフレームワークにおいて、標準出力に表示されるアクセスログをログファイルへ記録するやり方を公開します。


```conf:logging.conf
[loggers]
keys=root

[handlers]
keys=fileRotatingHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=fileRotatingHandler

[handler_fileRotatingHandler]
class=logging.handlers.TimedRotatingFileHandler
level=DEBUG
formatter=simpleFormatter
args=('./log/application.log', 'd', 1, 10)

[formatter_simpleFormatter]
format=%(asctime)s: %(threadName)s: %(levelname)s: %(name)s: %(message)s
datefmt=
```

```py3:sever.py
from bottle import Bottle, request, response
from functools import wraps
import logging                            # ログ記録
import logging.config                     # ログコンフィグ

# -------------------------------------------------
# ロギング設定
# -------------------------------------------------
logging.config.fileConfig('./conf/logging.conf')
logger = logging.getLogger(__name__)

# -------------------------------------------------
# デコレータ
# -------------------------------------------------
# アクセスログ取得用（デコレータ関数）
def log_to_logger(fn):
    @wraps(fn)
    def _log_to_logger(*args, **kwargs):
        actual_response = fn(*args, **kwargs)
        # modify this to log exactly what you need:
        logging.info('ACCESSLOG: %s %s %s %s' % (request.remote_addr,
                                        request.method,
                                        # request.url,
                                        request.urlparts.path,
                                        response.status))
        return actual_response
    return _log_to_logger

# デコレータ関数の拡張
app = Bottle()
app.install(log_to_logger)

# -------------------------------------------------
# ルーティング
# -------------------------------------------------
@app.route('/')
def home():
    return ['hello, world']

# quiet=Trueでサイレントモード
app.run(host='0.0.0.0', port='8081', quiet=True)
```

上記コードを実行すると以下のような結果となります。

```
$ python3 sever.py &
$ tail -f log/application.log
YYYY-MM-DD HH:MM:SS,ddd: MainThread: INFO: root: ACCESSLOG: xxx.xxx.xxx.xxx GET / 200 OK
```
Puppeteer 1.0 で超簡単ヘッドレスブラウザ体験

# Puppeteer 1.0が出た:thinking:
https://github.com/GoogleChrome/puppeteer

# なにこれ:thinking:
ChromeのDevToolsチームが開発しているヘッドレスブラウザ。
ようするにサーバで実行されるNode.jsのJavaScriptで、目隠し状態Chromeを簡単に操作できるようにしたフレームワーク。
**なんて読むのか知ってる人マジで教えてください。ぱぺってぃあ？**

筆者は全然テスト自動化の経験とかないのですが、JavaScriptで動かせる、導入も楽そう、という二点が強烈だったのでポコポコ試してみた。

# 環境構築めっちゃ楽:thinking:
node v6.4.0以上(aysnc/await使うなら7.6.0以上)で

```powershell
npm i --save puppeteer
```

**～fin～**

# 書いてみる:thinking:
もちろんjavascriptで書く。

APIはここ↓
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#
普通にChromeなので大抵のことはできる。

・公式のサンプル

```javascript
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();
```

ブラウザ立ち上げてexample.comにアクセスしてファイル名指定してスクショ。
直感的で良い。

# 書いてみた:thinking:
・なんかしらのログイン画面でIDPW入力、ログインするスクリプト

``` javascript:login.js
let i = 1;

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://example.com/dokokano/login/page'); // ページを指定

  // id入力
  const inputIdElement = await page.$('input[id=input_userid]'); // 入力フォームのエレメント取得
  await inputIdElement.focus(); // フォームにフォーカスを当てる

  // 文字入力
  await inputIdElement.press('u');
  await inputIdElement.press('s');
  await inputIdElement.press('e');
  await inputIdElement.press('r');
  await inputIdElement.press('i');
  await inputIdElement.press('d');
  await page.screenshot({path: `login_${i++}.png`});
  console.log('id entered.');

  // パスワード入力
  const inputPasswordElement = await page.$('input[id=input_password]');
  await inputPasswordElement.focus();
  await inputPasswordElement.press('p');
  await inputPasswordElement.press('a');
  await inputPasswordElement.press('s');
  await inputPasswordElement.press('s');
  await page.screenshot({path: `login_${i++}.png`});
  console.log('pass entered.');

  // ログインボタンクリック
  console.log('login start.');
  const loginButtonElement = await page.$('input[id=loginButton]');
  await loginButtonElement.click();
  // 処理、画面遷移を待つ
  await page.waitFor(3000);
  await page.screenshot({path: `login_${i++}.png`});
  console.log('login executed.');

  // 終了
  await browser.close();
})();
```
**入力系はもっといい書き方がある気がする。いや絶対ある。**
ご教授いただけると幸いです。

# 動かしてみる:thinking:

もちろんNodeなので、上記ファイルを動かす場合は以下コマンド。

```powershell
node login.js
```
console.logはそのままコンソールに表示される。
スクショは上記ファイルの書き方だとlogin.jsと同じディレクトリに保存される。

```
puppeteer_test
  ├login.js
  ├login_1.png
  ├login_2.png
  └login_3.png
```

login_3.pngがログイン後の画面のスクショならOK :D

# つかいみち:thinking:
仕事での実運用とかテスト自動化とかを考えると、まだまだ[Selenium](http://www.seleniumhq.org/)に軍配あがります。クロスブラウザだし。ぱぺってぃあChromeだし。

しかしこの手軽さは良いです。特に普段JS書いてる人ならなんの抵抗もなく書けると思います。
無限に回して10分に一回スクショとか、該当する画面に遷移して期待する要素がなかったらログ吐くとか、簡単なテストは本記事で紹介した程度の知識でもすぐ書けますね。

なによりChrome謹製なので、今後に期待です。
Glassfish4.1上でJacksonを含むアプリを動かす際の注意事項

# Glassfishでアプリを動かす際に、使用しているライブラリが参照するJacksonがどうも古い
というところから、なぜ動かないのかはまったのでメモ。

# 結論
どうやらGlassfishのmodulesの中にJacksonのjarがあり、そのバージョンが古い。
そして、Jackson依存のライブラリを利用するために、MavenのPOMで依存関係を指定しても、
Glassfish上のJacksonライブラリをクラスローダーで先に読み込んでしまうため、
古い方のライブラリが優先されてしまうよう。

#対応策
もう直接ライブラリのバージョンアップしちゃいました。
Tomcatとかでも同じようなことを書いてある記事があったので、そちらを参考に、
ライブラリをアップデート（やるときは自己責任でお願いします。）
## 対象ファイル
+ jackson-core.jar
+ jackson-databind.jar
+ jackson-annotations.jar
+ jackson-jaxrs-base.jar
+ jackson-jaxrs-json-provider.jar

とりあえず元ファイルはバックアップを取ってから実行することをお勧めします。

私はLineのBotを試したりしたかったので、Jacksonの2.8.10を入れてますが、他のバージョンでも、
関連ライブラリのバージョンがそろっていれば問題ないかも。
RLMSupport.swiftは手で差し替える

# はじめに
`pod update`で、Realm Swift 2.10.1→3.1.1にバージョンアップしたところ、RLMSupport.swiftで、`Use of undeclared type ‘RLMSyncPermissionResults’`や`’RLMSyncPermissionValue’`というエラーが発生。既視感があったので、最新のソースと比較し、差分があることを確認。手で差し替えることにしました。

# 解決方法
`pod update` でアップデートされない`RLMSupport.swift`を手で入れ替えてあげる。

https://github.com/realm/realm-cocoa/blob/master/Realm/Swift/RLMSupport.swift

のソースを丸ごとコピペして置換すれば、解決します。
Mosquitto で Let's Encrypt の証明書を使う

次のページを参考にしました。
[Using Let’s Encrypt certificates with mosquitto](https://mosquitto.org/blog/2015/12/using-lets-encrypt-certificates-with-mosquitto/)

/etc/mosquitto/mosquitto.conf
に次を加えます。
example.com は変更して下さい。

```text
listener 8883
cafile /etc/ssl/certs/ISRG_Root_X1.pem
certfile /etc/letsencrypt/live/example.com/fullchain.pem
keyfile /etc/letsencrypt/live/example.com/privkey.pem
```

サーバーのリスタート

```bash
sudo systemctl restart mosquitto
```

サブスクライブ

```bash:go_sub.sh
mosquitto_sub -d -t orz -h example.com \
	-p 8883 --capath /etc/ssl/certs/ \
	--topic sensors/topic_1
```

パブリッシュ

```bash:go_pub.sh
mosquitto_pub -d -t orz -m "こんにちは Jan/23/2021" -h example.com \
	 -p 8883 --capath /etc/ssl/certs/ \
	--topic sensors/topic_1
```

実行時の様子

パブリッシュ

```text
$ ./go_pub.sh 
Client mosq-jbiGkrRFKrFE5DiycV sending CONNECT
Client mosq-jbiGkrRFKrFE5DiycV received CONNACK (0)
Client mosq-jbiGkrRFKrFE5DiycV sending PUBLISH (d0, q0, r0, m1, 'sensors/topic_1', ... (27 bytes))
Client mosq-jbiGkrRFKrFE5DiycV sending DISCONNECT
```

サブスクライブ

```text
$ ./go_sub.sh 
Client mosq-u0Wpvcgg46Y05Tco2C sending CONNECT
Client mosq-u0Wpvcgg46Y05Tco2C received CONNACK (0)
Client mosq-u0Wpvcgg46Y05Tco2C sending SUBSCRIBE (Mid: 1, Topic: orz, QoS: 0, Options: 0x00)
Client mosq-u0Wpvcgg46Y05Tco2C sending SUBSCRIBE (Mid: 1, Topic: sensors/topic_1, QoS: 0, Options: 0x00)
Client mosq-u0Wpvcgg46Y05Tco2C received SUBACK
Subscribed (mid: 1): 0, 0
Client mosq-u0Wpvcgg46Y05Tco2C received PUBLISH (d0, q0, r0, m0, 'sensors/topic_1', ... (27 bytes))
こんにちは Jan/23/2021
```

Python3 の接続例
[Python3: Let's Encrypt の証明書を使ったブローカーに接続](https://qiita.com/ekzemplaro/items/4519c56995189ad0dba4)

Node.js の接続例
[Node.js: Let's Encrypt の証明書を使ったブローカーに接続](https://qiita.com/ekzemplaro/items/1e0aee06f9a9d39af94c)


## エラー対策
/var/log/mosquitto/mosquitto.log　にエラーが出て サーバーが起動できない時
```text
1740980405: Error: Unable to load server certificate "/etc/letsencrypt/live/example.com/fullchain.pem". Check certfile.
1740980405: OpenSSL Error[0]: error:8000000D:system library::Permission denied
```

以下のパーミッションをゆるくすると問題が解決します。
私は、0755 にしました。

```text
/etc/letsencrypt/live
/etc/letsencrypt/archive
```
grepのちょい技テキなメモ

# grepのちょい技テキなメモ


### ある条件Aで grep検索をかけ絞り込んだファイル（行ではない）から、さらに別条件Bでgrepしたいとき。

最初の条件Aの抽出結果が行でなくファイルであることがポイント。

```
grep -rl <条件A> <検索対象> | grep <条件B> 
```

例)　"foo" という文字列を含むファイルから "bar" をいう文字列を含まないファイルを探したいとき。

```
grep -rl "foo" . | xargs grep -L "bar"
```
Python で Java の CyclicBarrier を実装してみる

マルチスレッドのデザインパターンを引き続き復習します。
[前記事 : Python で Java の CountDownLatch を実装してみる](https://qiita.com/shinkiro/items/75f3561d6bc96694ce30)

実は、Python 3.2 から[バリアオブジェクト](https://docs.python.jp/3/library/threading.html#barrier-objects)がサポートされているので、こんな劣化版を作る意味はないのですが、勉強勉強。

### バリアって何よ

並列コンピューティングにおけるバリア（英: Barrier）とは、同期方法の一つであり、ソースコード中でスレッドやプロセスがある箇所で停止し、他の全てのスレッドプロセスがバリアに到達するまで進行しないようなものを示す。

from [Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%AA%E3%82%A2_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%A6))

### CountDownLatch との違い

待機を解除する条件が、スレッド同士の待ち合わせと関係がないのが、CountDownLatch。 関係するのが、CyclicBarrier。極端な話、CountDownLatch はある 1 つのスレッドの中で、何回もカウントダウンをしても良い。


サンプルコード

```Python
# coding:utf-8

import threading

class CyclicBarrier(object):
    def __init__(self, count):
        assert count > 0, "count は 1 以上の値を与えてください。入力値[{}]".format(count)
        self.count = count
        self.condition = threading.Condition()

    def await(self):
        self.condition.acquire()

        self.count -= 1
        while self.count > 0:
            self.condition.wait()

        self.condition.notifyAll()
        self.condition.release()

    def broken(self):
        if(self.count > 0):
            return False
        else:
            return True

def worker(barrier, n):
    print("Worker: {}".format(n))
    barrier.await()

if __name__ == "__main__":
    # 5 回 barrier.await() が呼ばれたらバリアは破壊される
    count = 5
    barrier = CyclicBarrier(count)

    for i in range(count-1):
        thread = threading.Thread(target=worker, args=(barrier, i))
        thread.start()

    barrier.await()

    if(barrier.broken()):
        print("バリアは壊れました")
```

実行結果

```
Worker: 0
Worker: 1
Worker: 2
Worker: 3
バリアは壊れました
```
Qiita API > Nページ目の2記事だけ取得 | 変更差分の検知は?

https://qiita.com/api/v2/docs

### ユーザ関係なし

例: https://qiita.com/api/v2/items?page=50&per_page=2

### ユーザ指定

API情報: https://qiita.com/api/v2/docs#get-apiv2usersuser_iditems
例: https://qiita.com/api/v2/users/7of9/items?page=50&per_page=2

> 指定されたユーザの投稿一覧を、作成日時の降順で返します。

「作成日時」というのは「新規作成日時」のようで、このAPIでは更新があった記事を若いページ番号で取得することはできなさそう。

差分の検知は~~難しい~~できないかもしれない。

### 変更差分の検知

- 記事
    - 新規作成: 若いページ番号で取得可能
    - 記事変更: 若いページ番号で取得不可能
- コメント
    - 投稿: 若いページ番号で取得可能
    - コメントの変更: 若いページ番号で取得不可能
Sublime Text 3 > 設定 > Toggle the View Read-Only | Shift_JISファイルの破壊防止

```txt:動作環境
Windows 10 Pro (64bit) Fall Creators Update適用済
Sublime Text Version 3.0, Build 3143
```

ファイルをReadonlyで閲覧だけしたい。

以下のパッケージが使いやすかった。
https://packagecontrol.io/packages/Toggle%20the%20View%20Read-Only

- ファイルごとのReadonly設定
    - フォルダ単位では設定できない?
- ファイルを閉じるとReadonly設定は解除される
- Sublime TextでReadnoly設定でも別のエディタで書換え可能
- エディタ内で書き換えそのものを禁止する
    - 別のパッケージでは書換えは許可して保存時に禁止であったが、使いにくかった
        - Toggle Read-Only
- エディタの左下にReadonly表記があり、Readonlyファイルとそうでないファイルの識別が可能
    - 例: `SHIFT_JIS, Readonly, Line 12, Column 19`

### Shift_JISファイルの破壊防止

Sublime Text3とConvertToUTFの組合せでShift_JISファイルが30回くらい破壊された。ファイルのReopen with encodingでも復活しないため、作業の手戻りとなる。
Sublime Text2とConvertToUTFの組合せでは3回程度しか破壊が起きなかった。Sublime Text3になってから安心して使用できない (2018年2月現在)。

Windows環境でのShift_JISファイル変更は秀丸エディタを使うようにしつつある。
閲覧性はまだSublime Textの方が慣れているため、Sublime TextはReadonlyとして使うことを検討中。
日本語を使わないUbuntuやCentOS上では引き続きSublime Textを使うだろう。Shift_JISの問題がなければ、Sublime Textは使いやすい。
試してみる


```
\begin{align}
\qquad &ax^2+bx+c = 0 \\
\Leftrightarrow &\quad x^2 + \frac{b}{a}x = - \frac{c}{a} \\
\Leftrightarrow &\quad x^2 + \frac{b}{2a} x + \frac{b^2}{4a^2} = \frac{b^2}{4a^2} - \frac{c}{a} \\
\Leftrightarrow &\quad (x + \frac{b}{2a})^2 = \frac{b^2 - 4ac}{4a^2} \\
\Leftrightarrow &\quad x + \frac{b}{2a} = \pm \frac{\sqrt{b^2-4ac}}{2a} \\
\therefore &x = \frac{-b \pm \sqrt{b^2-4ac} }{2a}
\end{align}
```

```math
\begin{align}
\qquad &ax^2+bx+c = 0 \\
\Leftrightarrow &\quad x^2 + \frac{b}{a}x = - \frac{c}{a} \\
\Leftrightarrow &\quad x^2 + \frac{b}{2a} x + \frac{b^2}{4a^2} = \frac{b^2}{4a^2} - \frac{c}{a} \\
\Leftrightarrow &\quad (x + \frac{b}{2a})^2 = \frac{b^2 - 4ac}{4a^2} \\
\Leftrightarrow &\quad x + \frac{b}{2a} = \pm \frac{\sqrt{b^2-4ac}}{2a} \\
\therefore &x = \frac{-b \pm \sqrt{b^2-4ac} }{2a}
\end{align}
```
【React Native】便利コマンド一覧

# 共通
### キャッシュクリーン
＊事前にjsビルド実行を停止しておく。

```
$ ./node_modules/react-native/scripts/packager.sh --reset-cache
```

### 停止
＊取得したIDを利用

```
$ lsof -i -P | grep 8081
node      638281 {name}  415u  IPv6 ndausd8e920      0t0  TCP localhost:8081->localhost:23423 
$ kill -KILL 638281
```


# Android
### 端末を指定してインストール
＞接続中の端末と起動中のエミュレーターのID表示

```
$ adb devices

List of devices attached
06157df6a5bdc802        device
```

＞端末指定の起動
＊取得したIDを利用する。

```
$ react-native run-android --deviceId 06157df6a5bdc802
```

### SHA1表示

```
$ keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
```

### キーハッシュ作成

```
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | base64
```


# iOS


随時追加予定です。
オススメの便利コマンドありましたら、ご指摘お願いします。
oracle-enhancedのOCIError: ORA-01000エラー解消

## 概要

>ORA-01000: 最大オープン・カーソル数を超えました。
>ORA-01000: maximum open cursors exceeded

OracleをActive Recordで使うためのgem、rsim/oracle-enhancedで起こり得る最大オープンカーソル超過問題について原因と解決策をメモ。確認環境はRails 5.1系、oracle-enhanced 1.8.2。

## 解決方法

Oracleで設定されているOpen Cursorsよりもやや少ない数をdatabase.ymlでstatement_limitとして設定する。

```
SQL> select name,value from v$parameter where name = 'open_cursors';
=> 300
```

```database.yml
default: &default
  adapter: oracle_enhanced
  statement_limit: 250
```

Open Cursorsが1200ならstatement_limitを1000、300なら250など。エラー文面からは超過しないように一致するよう設定すればよいようにも読めるが、実際には余剰にカーソルが消費されることがありギリギリだと超過エラーが発生する。

## 解説

見ての通り、Oracle側で設定されたOpen cursors以上にカーソルを消費しようとした場合に発生するエラー。adapter 1.8.0からstatement_limitのデフォルト値が１０００になっており、Oracle側のopen cursorsがそれを下回るような環境ではエラーが発生するようになった。
QuasarFramework(Vue.js)をWebpackで、buildしたときに発生したUncaught SyntaxError: Unexpected token < を解決したときの話

QuasarFramework(Vue.js) + Firebaseで、アプリケーションを作っているときに、`Uncaught SyntaxError: Unexpected token <`が発生してしまったんですが、それを解決した時の話です。

# 症状編
QuasarFramework(Vue.js) + Firebaseで、アプリケーションを作っているときに、vue-routerの設定をhistoryモードにして、Build後のファイルをFirebaseにデプロイしたところ、vue-routerで設定したchildrenのrouteにアクセスすると以下のエラーが発生してしまいました。

`Uncaught SyntaxError: Unexpected token < manifest.js`
`Uncaught SyntaxError: Unexpected token < app.js`
`Uncaught SyntaxError: Unexpected token < vendor.js`

そのときの、routes.jsの設定は以下のようにしていました。

```javascript:routes.js
...
export default new VueRouter({

  // history modeにしてあります。
  mode: 'history',
  scrollBehavior: () => ({ y: 0 }),

  routes: [
    { path: '/dashboard',
      component: load('HelloTop'),
      children: [
        { path: 'hello', component: load('Hello2') }
      ]
    },
    { path: '/', component: load('Hello') },
    // { path: '/', component: load('Hello') },
    // Always leave this last one
    { path: '*', component: load('Error404') } // Not found
  ]
})
...
```

この場合、childrenの/dashboard/hello にアクセスすると、上記のerrorが発生するという状況です。

# 原因編
errorの内容は、manifest.js, app.js, vendor.jsのファイルの参照に失敗しているっぽいので、この参照の設定を正しくしてあげる必要があるようです。

なぜ参照errorが発生しているのかを調べたところ、stack over flowに、原因と解決方法の回答がありました。
https://stackoverflow.com/questions/41756874/uncaught-syntaxerror-unexpected-token-in-dist-index-html?answertab=active#tab-top

完全には理解してないですが、まとめると
「index.htmlのscriptのURLが絶対pathになっていない場合は、ブラウザの挙動によって、scriptファイルを相対パスで参照してしまうことがあるので、scriptのURLを絶対pathに変更してあげたら問題が解決するよ」
ということらしいです。

今回の例だと、`/dashboard/hello`にアクセスしたあとは、manifest.js, app.js, vendor.jsの参照URLが、`/dashboard/manifest.js`とかになってしまい、うまくファイルを読み込めないという状況になっているぽいです。（たぶん）

# 解決編
解決策も先程のstackoverflowの回答欄にありました。
index.jsの、buildのpublicPathを、`/`に修正するだけでOKのようです。

```javascript:index.js
...
build: {
    env: require('./prod.env'),
    publicPath: '/',
    productionSourceMap: false,

    // Remove unused CSS
    // Disable it if it has side-effects for your specific app
    purifyCSS: true
  },
...
```

もしくは、routes.jsのmodeをhashに戻せば、相対パスのままでもOKのようです。

# まとめ
modeをhistoryにしたところ思わぬところで、errorが出てしまいました。うまく解決できて良かったですが、そもそもmodeのhashとhistoryの違いもよくわからないまま、historyにしてしまったところが原因かもしれません。
jQuery の trigger の第2引数が便利だ

# jQuery の trigger の第2引数が便利だ

知らなかったのでメモ

```js
jQuery('#id').on('change', changeAction);
function changeAction(event, argument1, argument2, argument3) {
    console.log('argument1: ' + argument1);
    console.log('argument2: ' + argument2);
    console.log('argument3: ' + argument3);
}
jQuery('#id').trigger('change', ['hoge', 'fuga', 'foo']);
```

って書くと、

jQuery('#id') の value値変更時は、

```
argument1: undefined
argument2: undefined
argument3: undefined
```

trigger 実行時は、

```
argument1: hoge
argument2: fuga
argument3: foo
```

ってコンソールに出力されます。


jQuery(document).ready 時のみ、実行させたくない処理がある時とか、
function の外に変数とか用意せずに↓な感じでかけるので便利。

```js
jQuery(function(){
    jQuery('#id').on('change', changeAction).trigger('change', [true]);
    function changeAction(event, readyFlg) {
        // ここに共通処理

        if (readyFlg !== true) {
            // ここの処理は、jQuery(document).ready時には実行しない
        }
    }
});
```
Capybaraで画面要素の表示順を検証する

たとえば`Item`の一覧ページで要素がソートできていることを検証したいとします。

テストデータの`Item#title`はランダムな文字列が入っているという前提があれば、下記のコードで検証できます。

```ruby
expect(page.text).to match %r{#{item_1.title}.*#{item_2.title}}
```

他の箇所にも表示されている場合は`within`で検証する範囲を絞ればOK。

```ruby
within('.item-list-container') do
  expect(page.text).to match %r{#{item_1.title}.*#{item_2.title}}
end
```
Ubuntu環境でanacondaとpyenvを使わずにscikit-learn, mecab, mecab-NEologdを単体導入した話

# 前置き
この記事は`pyenv + anaconda`の記事を読みまくった初心者機械学習エンジニアが、
サービス導入する時のサーバー(Ubuntu 16.04.2 LTS)に
この2つを入れるべきなのかを考え抜いた結果、単体インストールを試みた記事です。

# そもそもpythonのバージョンをサーバーで分ける必要があるのか
pyenvを導入する理由は人それぞれだと思うが、以下の理由が結構でかいのではと思う

- pipでライブラリなどを入れた場合、グローバル空間に入っちゃうので複数のバージョンが入れられない

- Linux環境だと、Pythonは2系/3系の2つしかパッケージでは入れられない。

僕が導入を試みているサーバー環境だとそもそもpythonで動いているサービスが存在していないので、
複数バージョンを入れるケースもなく、必要もないと考えた。

また、Ubuntu 16.04.2 LTSではデフォルトでPython 3.5/Python 2.7が入っている。
最新のPython 3.6を入れる必要があるか考えた。

[What’s New In Python 3.6](http://docs.python.jp/3.6/whatsnew/3.6.html)

読んでみて、自分の開発しているスクリプトを見た。
一つも取り入れている新しい機能もなく、3.6も必要ないと感じた。

そうすると、pyenvいらないのでは？と思ったのである。

ただしpip、お前には入ってもらう。

```bash
$ sudo apt install python3-pip python3-dev
$ sudo pip3 install --upgrade pip
```

参考 : [pyenvが必要かどうかフローチャート](https://qiita.com/shibukawa/items/0daab479a2fd2cb8a0e7)

# SVM使うだけで本当にanacondaまで入れる必要あるのか？

これまで、開発に導入している[SVM(サポートベクターマシン)](https://qiita.com/arata-honda/items/bc24cbd953bd9d2c743c)はscikit-learnのライブラリとして使用しているので*anaconda*で一発導入していた。

anadondaの説明については、[puhitakuさんの記事](http://www.zopfco.de/entry/2017/04/03/233811)が分かりやすかったので引用させて頂く。

>Anacondaは簡単に言うと「最初からNumpyやJupyter Notebookが入っていて、ビルド済みバイナリをインストールすることで利用者の環境構築が省け、ついでに複数バージョンのPythonを管理したり環境を切り替えることもできる一大ディストリビューション」である。

読んでみて、自分の開発しているスクリプトを見た。
numpy, pandasは使うが、Jupyter Notebookやmatplotlibも使わない。

>複数バージョンのPythonを管理したり環境を切り替える

切り替えない

あれこれもはや導入する意味あるのだろうかと考えた結果、

**単体インストールでいいんじゃね**

と結論を出しました。

というわけで、単体インストールを行ったので、コードを残しておく。

## mecabのインストール

```bash
$ sudo apt-get install mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8
```

## numpy, scipy, scikit-learn, mecab-python3のインストール

```bash
$ sudo pip3 install numpy scipy scikit-learn pandas mecab-python3
```
memo : scikit-learnはビルドに`numpy`と`scipy`を使っているので、入れていないとimportできないので入れておく。

## mecab-NEologdのインストール

新語に対応した[mecab-NEologd](https://github.com/neologd/mecab-ipadic-neologd)も導入する

```bash
$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ ./bin/install-mecab-ipadic-neologd -n
$ sudo sed -i -e '5,5d' /etc/mecabrc
$ sudo sed -i -e '4a\dicdir = /usr/lib/mecab/dic/mecab-ipadic-neologd' /etc/mecabrc
```

最後の二行は

```bash
$ echo `mecab-config --dicdir` "/mecab-ipadic-neologd"
```

でインストール先のmecab-ipadic-neologdを確認して、パスが `/usr/lib/mecab/dic/mecab-ipadic-neologd`なっていたらそのままお使いください。(適宜ここ2行は環境に合わせてください)

参考 : [Pythonの環境管理ツール良し悪し](http://www.zopfco.de/entry/2017/04/03/233811)

# 最後に
何かを入れて使うということは"*入れる意味がある*"はずなので、
たまには脳みそを使って意味を考えたり調べたりするべきだと思いました。
これはあくまで僕の環境下で且つ僕の思想なので、これが必ずしも正しいとは限らないし、
anacondaを使わなければならない事例も出てくるはずなので、
すごいニッチな記事になりましたが参考になれば幸いです。

また、もっとこういうことを考えたほうがいいとか、お前はまだまだだなどあれば、ご教授して頂けると幸いです。
DBにアクセスするWebApiをPython＋Bottleで実装したらすごく簡単だった

# 試してみた経緯
仕事でMySQLのDBアクセスをODBC経由など直接，クライアントPCから行っているのだが，ODBCのバージョンに依存する場合が多いためそろそろ移行できないかと思った．とりあえずWebAPIを構築して，サーバーに対してURLアクセスすれば，ソケット通信を用意する必要もないし，PythonのスクリプトはApacheに搭載してCGIで処理してしまえばいいやって思った．
開発難度と工数の見積もりをする必要もあったので，勉強のつもりで組んでみた．

結論から言うと，めちゃめちゃ簡単に実装できました．

### この記事ので注意事項．
- Bottleの基本的な使い方、ルーティングは省略します．
- Pythonで実装する時にURLで引数を渡す等は省略します。
- 以下のコードはカッコつけてJsonとか使っていますが，戻り値はタプルのリストになります．
- DBの構成等は省略します．

# コード全文

```Python
import json
import mysql.connector
from bottle import route, run

@route('/<foo>/<bar>', methods=['GET'])
def GetZone(foo, bar):
    conn = mysql.connector.connect(host="localhost", port=3306, user="root", password="root", database="test")
    cur = conn.cursor()
    query = "SELECT hoge, fuga FROM test_tbl WHERE id='%s' AND user='%s' AND num IS NULL" % ( foo, bar)
    print(query)
    cur.execute(query)
    result = cur.fetchall()
    cur.close()
    conn.close()
    return json.dumps(result)

run(host="0.0.0.0", port=8080, debug=True, reloader=True)
```

あとは以下で実行．

```
$ Python test.py
```

URLにアクセスすると，Resultを返してくれる．

```
http://localhost:8080/0001/user
```

# まとめ
最初はFlaskで組んでましたが，どの解説記事みてもFlaskにｱﾚﾓｺﾚﾓって全部やらせようとしてるのが多かった．
また，思った以上に依存関係になるのかな？エラー吐いたりすること多く，戸惑ったためBottleに変更．
自分はBottleでWebを組んでたりするので，その場合はそのままBottleのライブラリをインポートして使ったほうがいいかなと思ったのと，標準ライブラリをメインに使用していくことでネットに転がっている小規模な情報パズルで大きくならず，コード量も少なく構築することができた．
URLでセットしたい値を渡す実装も，例にしているサイトはだいたいが引数1つの場合が多いのだが，2つ以上引数がある場合はコレで対処可能ってことも覚えた．
Promiseのシンプルな書き方メモ


いつもPromise書こうとした時に、書き方忘れるのでメモ

ポイントは、

* promiseの呼び出し方を見た目シンプルにする
* 非同期処理（taskA,taskB,taskC）を同期処理させる
* それぞれの処理結果を渡していく
* require（promiseライブラリ）は使わない前提


```javascript

// 以下のpromise関数不要でした
// Promiseの呼び出し関数
// const promise = (v) =>
// 	new Promise((resolve, reject) => {
// 	  resolve(v);
// 	}
// );

// 非同期処理taskA
const taskA = (v) => {
  return new Promise((resolve, reject) => {
    console.log("taskA",v);
    v = v+1;
    resolve(v);
  });
}


// 非同期処理taskB
const taskB = (v) => {
  return new Promise((resolve, reject) => {
    console.log("taskB",v);
    v = v+1;
    resolve(v);
  });
}

// 非同期処理taskC
const taskC = (v) => {
  return new Promise((resolve, reject) => {
    console.log("taskC",v);
    resolve(v);
  });
}

// エラー処理
const onRejectted = (v)=>{
  console.log("onRejectted",v);
}

// -----------
// メイン処理
// -----------

// promise(1) // まずPromiseの最初の呼び出し部分は引数渡すだけにする
Promise.resolve(1) // まずPromiseの最初の呼び出し部分は引数渡すだけにする
.then(taskA) // 次にthenで各非同期処理を呼び出す
.then(taskB)
.then(taskC)
.catch(onRejectted);
```

実行結果

```sh
$ node simple_promise.js
taskA 1
taskB 2
taskC 3
```


Promiseの書き方（見た目）が分かりにくいので、直感的に分かり易くなるよう意識しました。
文字列結合は何回からStringBuilderに変えたほうがいいのか

「Javaで文字列結合するときはStringで+演算子を使うよりStringBuilderを使うべき」
「文字列結合が少ないときはパフォーマンスの変化はそうでもないが、多くなるとStringBuilderを使ったほうがよい」
といったことを時々聞きます。

実際に文字列結合を繰り返し大量に行う場合は、StringBuilderが何よりも効率が良いですが、[あっち](http://d.hatena.ne.jp/nowokay/20140408)や[こっち](https://qiita.com/ota-meshi/items/40d5dcb0e99574a8a368#stringbuilder%E3%81%A8stringbuffer)で既に検証結果が出ているので、置いておきます。

しかし実際にコーディングを行っているときは、たとえば文字列を[文字列]と囲って表示させたいときなど、2,3回だけ文字列結合を行う場合が多々あります。
その場合、StringBuilderのインスタンスを改めて作って、その中に文字列を入れて、2,3回だけ文字列結合をし、またString型に戻す……というのが無駄な気がしてなりません。

では文字列結合を何回するようになってからStringBuilderに変えたほうがいいのでしょうか。
ググってもなかなか出てこなかったので、自分で調べてみました。

# 測定

測定方法は

+演算子を使う場合：文字列を宣言→適当な文字列をn回結合する

```ruby:PlusTest.java
	public static void main(String[] args) {
		for(int j = 0; j < LOOP; j++){
			String str = "s";
			plus(str, BUILD_NUM);
		}
	}

	private static String plus(String str, int n) {
		for (int i = 0; i < n; i++) {
			str += "p";
		}
		return str;
	}
```

StringBuilderを使う場合：文字列を宣言→StringBuilderインスタンスを作成→適当な文字列をn回結合する

```ruby:StringBuilderTest.java
	public static void main(String[] args) {
		for(int j = 0; j < LOOP; j++){
			String str = "s";
			sb(str, BUILD_NUM);
		}
	}

	private static String sb(String str, int n) {
		StringBuilder sb = new StringBuilder().append(str);
		for (int i = 0; i < n; i++) {
			sb.append("b");
		}
		return sb.toString();
	}
```

この一連の流れを1000万回繰り返し、かかった時間を計測します。
ちなみに計測は10回前後繰り返して、中央値をとるようにしています。

# 結果

結合回数0回
+演算子:16ms[^1]
StringBuilder:172ms

1回
+演算子:390ms
StringBuilder:203ms

2回
+演算子:780ms
StringBuilder:265ms

3回
+演算子:1170ms
StringBuilder:281ms

……と、予想を裏切る結果になりました。
ちなみにStringBuilderの計測時間はかなりバラつきがあり、結合0回（ただ宣言しただけ）のときより、1回のほうが短いこともありました。2,3回結合回数が増えた程度では、誤差の範囲でしか変動しなさそうです。
どちらにしろ、+演算子を使うよりも普通に早いです。

# そもそも+演算子は何をやっているの？

+演算子で文字列結合しようとすると、コンパイラでStringBuilderインスタンスを作って結合しているようです（[参考](https://qiita.com/yoshi389111/items/67354ba33f9271ef2c68)）。
なので、「+演算子を使う場合：文字列を宣言→適当な文字列をn回結合する」というのは、正しくは「文字列を宣言→(StringBuilderインスタンスを作成→結合)*n」ということになります。
ただ、1回だけ結合する場合でも、測定した結果だと倍の時間かかっているんですよね……。文字列インスタンスを無駄に作ってたりしているんでしょうか。

# 結論

1回結合するだけならコンパイラが勝手にやってくれるのでどっちでもいい（むしろコードがごちゃつくので+演算子を使ったほうがいい）はずですが、神経質になるならStringBuilderを宣言して使うほうがいいのかな、という感じです。
ループで2回以上まわすのなら無駄なStringBuilderの宣言を減らすためにStringBuilderを使ったほうがいいです。

[^1]: 0msか16msのどちらかしか出なかったので信用ならない数値ですが、そもそもfor文を無駄にまわしているだけのコードの時間を測定しているだけなので無視しています
Emacsは美しい(CSV編集モードがすごい)

世の中にはCSV直編集族というのがいるらしい

## 発端
お仕事でCSVを編集する機会がそれなりにある。
問題はそのCSVがサーバー上にあってデータを編集するには都度新しいCSVをローカルから送る必要があるってことで、Macで都度Excelを立ち上げてCSVを編集、scpして動作確認するという流れがどうにも辛いところだった。
それを解決する手段を模索し始めた時Emacsならなんとかできるんじゃないんか？と思ったのが始まりでした

## CSV直編集族の仲間入り
どうやって導入したかは思い出せない。
元々入っていたかもしれないしMelpaから持ってきたのかもしれないがEmacsでCSVを編集することができる。
編集するだけならどんなエディタにもできるんだけどEmacsはそれを読みやすくしてくれる。
読みやすいって正義だよね
<img width="476" alt="スクリーンショット 2018-02-09 11.27.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/189219/1bf599b5-299c-471c-c38e-e2ffa9714c41.png">
このやばいCSVが

<img width="456" alt="スクリーンショット 2018-02-09 11.27.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/189219/de595526-4b79-23e1-52f6-dfe9cf56342a.png">
こうなる

これで、何も恐れず、Excelも使わずCSVを好きに改変できる

## まとめ
Emaｃｓは美しい
Excelを使う人が大量にいる中でさえエディタ一本で戦えるお前は本当に美しい
Git コマンド

#Gitコマンド

最近コマンドgit管理しようと勉強しているので、よく使うコマンドメモ

##ブランチ一覧　作成　移動　削除　
```
git branch                        //ローカルブランチ一覧

git branch -r                     //リモートブランチ一覧

git branch --merged               //マージ済み

git branch --no-merged            //未マージ一覧

git branch -a　                   //全ブランチ一覧

git checkout <branch_name>        //ブランチ移動

git checkout -b <branch_name>     //新規ブランチ作成

git branch --delete <branch_name> //ブランチ削除

git branch -D <branch_name>       //強制削除
```

##リモートブランチからブランチ作成(例)
```
git branch -r

結果
hogehoge
testtest

git checkout -b hogehoge origin/hogehoge
```

##変更内容確認
```
git diff HEAD　//前回変更分からの差分
```
#変更取消
```
git checkout <filename> //指定のファイルの変更取消
git checkout .          //全てのファイルの変更を取り消し

**どちらもファイルの追加または削除の取り消しはできないので注意**
```

##ファイルステージにアップ
```
git status         //アップロードファイル確認

git add .          //全てのファイルをファイルステージにアップ

git add <filename> //指定したファイルをアップ
```
##ファイルステージ取り消し
```
git reset HEAD <filename> //指定したファイル名のアップを取り消し

git reset HEAD .          //全てのファイルのアップを取り消し
```

##コミット操作
```
git commit -a           //変更のあったファイルすべて

git commit --amend      //直前のコミットを取り消す

git commit -v           //変更点を表示してコミット

git reset --soft HEAD~2 // 最新のコミットから2件分をワークディレクトリの内容を保持し取り消す

git reset --hard HEAD~2 // 最新のコミットから2件分のワークディレクトリの内容とコミットを取り消す
```
##マージ
```
git merge <branch_name>
```
##プッシュ
```
git push origin <branch_name>
```

##一時退避
```
git stash

git stash pop //戻す

git stash list //退避一覧

git stash clear //退避削除
```

##ログ確認
```
log --graph --date-order --all --pretty=format:'%h %Cred%d %Cgreen%ad %Cblue%cn %Creset%s' --date=short
```
##git作成
```
git init
git remote add origin <url> // オリジナルがここですよ。
git fetch
git pull origin  master // オリジナルのmasterを引っ張ってこい。
git pull origin branchname // ブランチを引っ張ってる時はこちら。
git checkout branchname // 引っ張って来たブランチに切り替える。
```

随時更新していきます。
CloudFrontの下でWordpressを実行する時に色々ハマった話 前編


長くなったので、前編後編に分けます。

## WordpressをAWSで動かす構成例
### 構成図
以下の構成で、WordpressをAWSで動かします。
![スクリーンショット 2018-02-09 9.20.00.png](https://qiita-image-store.s3.amazonaws.com/0/177247/095363df-f387-9719-dad4-edd721cbb5bf.png "スクリーンショット 2018-02-09 9.20.00.png")

+ EC2でWordpressを実行
+ インターネットからはCloudFrontへアクセス
+ CloudFrontでHTTPからHTTPSへリダイレクト
+ CloudFrontからEC2へはHTTPでポート番号8080へアクセス

本来であれば、CloudFrontとEC2の間にApplication Load Balancerを挿むのが良いと思います。
どちらにしても、以下の対応は必要です。

## CloudFrontの設定
### Distribution Settings
![IMG_5239.PNG](https://qiita-image-store.s3.amazonaws.com/0/177247/bb9d6daf-e223-874a-ae07-3024bd549113.png "IMG_5239.PNG")

##### Alternate Domain Names (CNAMEs)
ここには、公開するFQDNを入れます。

##### SSL Certificate
Custom SSL Certificate を選択し、ACMで作った証明書を選択します。

### Origin Settings
![IMG_5241.PNG](https://qiita-image-store.s3.amazonaws.com/0/177247/b6979f4c-6673-2495-96f1-e0b149a8a71e.png "IMG_5241.PNG")

##### Origin Domain Name
ここには、EC2のパブリックDNSを入力します。

##### Origin Protocol Policy
HTTP Only を選択します。

##### HTTP Port
EC2側で待ち受けているポート番号にします。
（この例では8080です）

### Cache Behavior Settings
![IMG_5243.PNG](https://qiita-image-store.s3.amazonaws.com/0/177247/414756ad-5c34-643d-5a75-eb24b16947ea.png "IMG_5243.PNG")

次の考えで作成していますが、キャッシュ設定はそれぞれのサイトタイプによって設計が必要です。

+ 管理画面、ログイン画面はキャッシュしない
+ PHPもキャッシュしない
+ それ以外はデフォルトTTLでキャッシュする

#### 管理画面とログイン画面
![IMG_5245.PNG](https://qiita-image-store.s3.amazonaws.com/0/177247/120f3c54-f94a-c252-5b28-550fa4992c61.png "IMG_5245.PNG")
![スクリーンショット 2018-02-09 10.20.48.png](https://qiita-image-store.s3.amazonaws.com/0/177247/641847bf-27e3-5095-2d60-ef4005e8a2ad.png "スクリーンショット 2018-02-09 10.20.48.png")

##### Path Pattern
管理画面用の設定では「/wp-admin/*」を、ログイン画面用の設定では「wp-login.php」を設定します。

##### Origin
Origin Settingsで作ったOrigin IDを選択します。

##### Viewer Protocol Policy
CloudFrontでHTTPSへリダイレクトする為、Ridirect HTTP to HTTPSを選択します。

##### Allowed HTTP Methods
Get, HEAD, OPTIONS, PUT, POST, PATCH, DELETEを選択します。

##### Cache Based on Selected Request Headers
Whitelistを選択し、以下を通します。

+ Authorization
管理画面にベーシック認証を入れる時などに必要です。

+ CloudFront-Forwarded-Proto
Origin側へプロトコルを通知します。

+ Host
Origin側へアクセス先ホスト名を通知します。

##### Object Caching
Customizeを選択します。

+ Minimum TTL / Maximum TTL / Default TTL  
全て0にします。

##### Forward Cookies
Allを選択します。

##### Query String Forwarding and Caching
Forward all, cache based on allを選択します。

#### ログイン画面以外のPHP [*.php]
基本的にはログイン画面と同様なので、割愛します。
例えば、普通のブログサイト等ではTTLを増やすといった形が取れるかと思います。

#### それ以外 [Default(*)]
下記以外はデフォルトのままです。

##### Viewer Protocol Policy
CloudFrontでHTTPSへリダイレクトする為、Ridirect HTTP to HTTPSを選択します。

##### Cache Based on Selected Request Headers
Whitelistを選択し、その他と同様に以下を通します。

+ Authorization
管理画面にベーシック認証を入れる時などに必要です。

+ CloudFront-Forwarded-Proto
Origin側へプロトコルを通知します。

+ Host
Origin側へアクセス先ホスト名を通知します。

##### Forward Cookies
Allを選択します。

##### Query String Forwarding and Caching
Forward all, cache based on allを選択します。

[後編](https://qiita.com/kunitaya/items/876a12cc803c5d495f43)へ続く。
MacにSentinelをインストールする

# 背景
JavaxSpringで開発中のWebシステムではRedisの冗長化のためにRedis-Sentinelを利用している
開発環境だけは設定をかえて〜という回避策は、共通の部分でSession管理にRedis-Sentinelを使うように設定していたため、書き換えるのも難しいかった。
そこで、開発環境でもSentinel動かせばいいじゃない！ということで調査しました。

# 方法

```
brew install redis
brew services start redis
redis-sentinel /usr/local/etc/redis-sentinel.conf
```

### 注意
* 上記だけではSentinelはログイン時に起動はしません（Redisだけ）
* redid-sentinel /usr〜で、フォアグラウンドで動作しますが、ターミナル閉じると停止しちゃいます


# 構築される環境

```
Redis
IP：127.0.0.1
PORT：6379

Sentinel
IP：127.0.0.1
PORT：6379
Master名:mymaster
```

# 動作確認方法

```
Sentinelへ接続
redis-cli -p 26379

Redisのmasterの情報を取得
sentinel masters

Sentinelと接続解除
quit

Redisへ接続
redis-cli -p 6379

Redisの全key情報を取得
keys *

cloud portal-wwwのTomcatを起動して、ブラウザでアクセス＆ログイン

Redisの全key情報を取得して、値が帰ってきていればOK
keys *
```

# 後述
最初はDockerを使って構築すればと考えていましたが
仮想ネットワーク（Macだとdocker0？）のために、Sentinelが回答するIPが
仮想のIPとなるためあきらめました。
解決のヒントとしては「Sentinelの設定値のANNOUNCE_IP」「Dockerのネットワークのhost network」あたりかなとは思ったのですが。。。
どなたかMac x DockerでSentinel構築したよというかたいれば教えてください。

# 追記
ログイン時にSentinelを自動起動させるには、以下のファイルを設置すれば可能となりました。
デフォルトインストールした場合に限ります。

~/Library/LaunchAgents/homebrew.mxcl.redis-sentinel.plist

```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>KeepAlive</key>
    <dict>
      <key>SuccessfulExit</key>
      <false/>
    </dict>
    <key>Label</key>
    <string>homebrew.mxcl.redis-sentinel</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/opt/redis/bin/redis-sentinel</string>
      <string>/usr/local/etc/redis-sentinel.conf</string>
      <string>--daemonize no</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>WorkingDirectory</key>
    <string>/usr/local/var</string>
    <key>StandardErrorPath</key>
    <string>/usr/local/var/log/redis-sentinel.log</string>
    <key>StandardOutPath</key>
    <string>/usr/local/var/log/redis-sentinel.log</string>
  </dict>
</plist>
```
Application Load Balancerにコンソールからhttpsリスナーを追加出来ない時

#まとめ
* コンソールから出来ない時はIAMの権限確認
* それでもダメならCLIからやってみる

#現象
* ALBにコンソールからhttpsリスナーを追加しようとしたら"Access denied to certificate"と言われ追加出来ない
    * 作成時も同じ
    * インポートした証明書でもACMで発行した証明書でも同じ

#権限周りの確認
* EC2, ALB, ALBv2, CertificateManager等、思いつく辺りはアクセス権限がある
* AdministratorAccessをつけてみたが結果変わらず
* つまり権限の問題ではなさそう
    * （なのでAdministratorAccessはここで外しました。）

#CLIからのトライ
* 同じエラーでは無いがコンソールでダメでもCLIでは行けるという話がある
    * [既存の ELB に SSL 証明書を追加しようとすると Server Certificate not found for the key というエラーになる件の解決方法](https://qiita.com/ynii/items/694d60614b98f73f780f)
* CLIからトライ
    * 既に他のAWSのconfigで設定していたので、[awscliの設定切り替え](https://qiita.com/ryuzee/items/e3ce493f132f1981f57a)を元に設定
    * AWSドキュメントの[チュートリアル: AWS CLI を使用した Application Load Balancer の作成](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/tutorial-application-load-balancer-cli.html)のHTTPS リスナーの追加通りのコマンドを実行

```
aws elbv2 create-listener --load-balancer-arn loadbalancer-arn \
--protocol HTTPS --port 443  \
--certificates CertificateArn=certificate-arn \
--default-actions Type=forward,TargetGroupArn=targetgroup-arn
```
* 出来た！