OmniAICreator/Qiita-1.07M huggingface dataset:
Scout APMを利用してHerokuのH12エラーを解析

## はじめに
Herokuでアプリを運用している際に、突然エラーが表示されたという経験はありませんか？このエラーの原因を解析したいが、優秀なDevOpsチームもいるわけでもないので、何をすれば良いか分からないという方々には、[Scout APM](https://scoutapm.com?utm_source=qiita&utm_medium=blog&utm_campaign=heroku_h12)が役に立ちます。ここでは、Herokuでよく見かける２つのエラーをScoutを使って、今までより早く、効率的にその問題の解析を行い、エラーコードを見つける方法を説明していきます。

## Herokuのエラーログについて
まず始めに、Herokuを使用している方に起こりやすい典型的なエラーと、それをデバッグするために、どうScoutを使用していくかを説明していきます。Herokuを頻繁に使用しているユーザーは何度も目にしたことがあるかもしれませんが、Herokuにてエラーが起こった際は、アプリケーションエラーページにおいて、HTTP503のコードと共に、”このサービスはご利用いただけません”と表示されます。
![image](https://cdn.buttercms.com/lS4evsChToO3Iu82f6XF)

残念ながら、この情報は開発者がデバッグするためには、ほとんど役に立ちません。しかし、Herokuのダッシュボード上のActivityタブにおいて、またはHerokuのCLIアプリケーションを使ってログを深掘りしていくと、その詳細が見えてきます。

```
$ heroku logs --tail
```

HerokuはH、R、Lという３つのアルファベットを使い、それぞれHはHTTPに関するエラー、RはRuntimeに関するエラー、LはLoggingシステムに関するエラーを表しています。またHerokuで使用されている、その他のエラー表記はこちらで確認出来ます。例として、下のスクリーンショットに表示されているエラーはH12のエラーということなります。

![image](https://cdn.buttercms.com/Ab3yblGRu2cqgffazNln)

## Scoutでエラーコードから解決策を導き出す
ここまで、ログをチェックし、どのようなタイプのエラーなのかを判別する方法を説明しました。ただ、エラーコードが分かったからというて、Herokuが公開している文書を参考にエラーを修正出来るかと言われたら、そうではありません。このようなエラーコードを見て何のエラーが起こっているかが分かったとしても、なぜ起こってしまったのかということまでは判別できないからです。ここで、それを説明してくれるのがScoutのようなアプリケーションパフォーマンスモニタリング（APM）です。Scout APMは、エラーコードがどこでなぜ起こったのかという情報まで提供してくれます。幸運なことに、Herokuのログシステムは、いつ、何のエラーが発生したかまでは教えてくれますので、典型的な２つのエラーを例として、そのエラーが起こったとき、一体どこでなぜ起こったのかをScout APMを使用して、精査してみましょう。

### H12：リクエストタイムアウト

Herokuではリクエストの完了までに３０秒以上かかったとき、このH12エラーが表示されます。このようなエラーは明らかに普通の反応時間の遅れとは異なるため、ScoutのOverviewページにおいて、大きなスパイクとして表示されます。これが調査開始の合図です。
![image](https://cdn.buttercms.com/S9N4O6XQAiXJCMy7Nj9w)

あなたがもしこのようなスパイクをScoutのチャートに表示されいてるのを発見したら、その周りをドラッグしてボックスとして囲います。すると、スパイクの中で起こっていたエンドポイントの簡単なリストが表示されます。その中で、要因と思われるエンドポイントを選択し、そのエンドポイントの中でエラーが発生した時間のトレースを見つけ出します。

この時点で、対象となるトレースを特定することができ、どこで時間やメモリーが消費されてたかがレイヤーごとにブレイクダウンされた情報から分かります。例えば、多くの時間がある一つのモデルに対するデータベースのクエリで消費されているとしたら、そのバックトレースと実際に実行されたクエリを見ることができます。

下記のような例では、多くの時間がコントローラーによって使用されていることがわかります。事実、このプロセスで４０秒以上かかっています。よって、これがH12のエラーコードがHerokuによって表示された原因と判別出来るわけです。

![image](https://cdn.buttercms.com/TGr0lkurT6GrtzSE2MLp)

さらに、上記ような例においては、コントローラータイムを細かく分割してくれる[AutoInstruments](https://docs.scoutapm.com/?_ga=2.166799102.1107802849.1567992573-1060759184.1557384149#autoinstruments)を使用することで、より詳細なデバックを可能にしてくれます。以上の作業を経て、コントローラーやバックトレースの中で問題のあるコードがどこに存在するかを確認することが出来ました。ここで、エディットアクション見ると、#edit 22において1 call の`sleep (40)` のせいで、このアプリが４０秒もプロセスに時間がかかってしまったと判明できるわけです。もちろん、このコードはこの説明をする目的で使用されましたが、Scoutを使うことで、これだけの情報を掴むことが出来ることをお分かりいただけたかと思います。

![image](https://cdn.buttercms.com/fzWLZMqQ0GehaLsvcwt6)

## 次は
Scout APMを使った、エラーコードR14/R15の解析について見ていきたいと思います。

[14日間無料トライアル](https://scoutapm.com?utm_source=qiita&utm_medium=blog&utm_campaign=heroku_h12)を実施中ですので、この機会に是非ご利用ください！
Google ColaboratoryでPython使ってみた

Google Driveでサインイン

https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja

上でPythonのコードを書く


```python:Untitled0.ipynb
# 三目並べの作成
import random

# ゲームの状態
class State:
  # 初期化
  def __init__(self, pieces=None, enemy_pieces=None):
      # 石の配置
      self.pieces = pieces if pieces != None else [0] * 9
      self.enemy_pieces = enemy_pieces if enemy_pieces != None else [0]*9

  # 石の数の取得
  def piece_count(self, pieces):
    count = 0
    for i in pieces:
      if i==1:
        count += 1
    return count

  # 負けかどうか
  def is_lose(self):
    # ３並びかどうか
    def is_comp(x, y, dx, dy):
      for k in range(3):
        if y < 0 or 2 < y or x < 0 or 2 < x or self.enemy_pieces[x+y*3] == 0:
          return False
        x, y = x+dx, y+dy
      return True
      
    # 負けかどうか
    if is_comp(0, 0, 1, 1) or is_comp(0, 2, 1, -1):
      return True
    for i in range(3):
      if is_comp(0, i, i, 0) or is_comp(i, 0, 0, 1):
        return True
    return False

  # 引き分けかどうか
  def is_draw(self):
      return self.piece_count(self.pieces) + self.piece_count(self.enemy_pieces) == 9

  # ゲーム終了かどうか
  def is_done(self):
    return self.is_lose() or self.is_draw()

  # 次の状態を取得
  def next(self, action):
    pieces = self.pieces.copy()
    pieces[action] = 1
    return State(self.enemy_pieces, pieces)

  # 合法手リストの取得
  def legal_actions(self):
    actions = []
    for i in range(9):
      if self.pieces[i] == 0 and self.enemy_pieces[i] == 0:
        actions.append(i)
    return actions

  # 先手かどうか
  def is_first_player(self):
    return self.piece_count(self.pieces) == self.piece_count(self.enemy_pieces)

  # 文字列表示
  def __str__(self):
    ox =('o', 'x') if self.is_first_player() else ('x', 'o')
    str = ''
    for i in range(9):
      if self.pieces[i] == 1:
        str += ox[0]
      elif self.enemy_pieces[i] == 1:
        str += ox[1]
      else:
        str += '-'
      if i % 3 == 2:
        str += '\n'
    return str

# ランダムとランダムで対戦

# 状態の生成
state = State()

# ランダムで行動選択
def random_actions(state):
  legal_actions = state.legal_actions()
  return legal_actions[random.randint(0, len(legal_actions) - 1 )]

# ゲームの終了までのループ
while True:
  # ゲーム終了時
  if state.is_done():
    break;
  # 行動の選択
  action = random_actions(state)
  #次の状態を取得
  state = state.next(action)

  #文字列表示
  print(state)
  print()
```

![スクリーンショット 2019-09-13 15.58.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265586/48d42270-67b6-2be1-f4b7-f28935a392f7.png)

Pythonのコードが実行できた。

GPUも時間制限付きで利用できるので、これは良き。
NI-DAQmx Python API 備忘録

意外と設定項目が多かったのでメモ．あとで追記する．


```python
import nidaqmx
from nidaqmx.constants import AcquisitionType, Edge

# Check NI device terminals
# using USB-6001
device = nidaqmx.system.device.Device("Dev3")
for tr in device.terminals:
    print(tr)

# Wait Trigger to PFI/0 
with nidaqmx.Task() as ditask:
    ditask.ai_channels.add_ai_voltage_chan("/Dev3/ai1")
    ditask.timing.cfg_samp_clk_timing(100, u'', Edge.RISING , AcquisitionType.FINITE) 
    ditask.triggers.start_trigger.cfg_dig_edge_start_trig("/Dev3/PFI0", Edge.RISING)
    ditask.in_stream.timeout = 200
    k=0
    ditask.read(1, 120) # sample, timeout [s];
    print(k)
```

Digital In/Out の例．

```python
import nidaqmx
from nidaqmx.constants import (LineGrouping)
from nidaqmx.errors import DaqError
import time
import sys

# Mainly coded for NI USB-6001
class DAQ_task:
    def __init__(self, devID="Dev0", taskType="di",
                port="port0", lineCh="line4:7"):
        self.task = nidaqmx.Task()
        if (taskType=='di'):
            self.task.di_channels.add_di_chan(
                "/" + devID + "/" + port + "/" + lineCh,
                line_grouping=LineGrouping.CHAN_PER_LINE
            )
        elif (taskType=='do'):
            self.task.do_channels.add_do_chan(
                "/" + devID + "/" + port + "/" + lineCh,
                line_grouping=LineGrouping.CHAN_PER_LINE
            )
        else:
            print("Unknown Task type: " + taskType)
    def startAll(self):
        self.task.start()    
    def stop(self):
        self.task.stop()
        self.task.close()
    def writeDO(self, tflist):
        self.task.write(tflist)
    def readDI(self):
        return self.task.read()
    
    def demoDIO(self):
        for i in range(5):
            self.writeDO([True,False,True,False])
            print(self.readDI())
            time.sleep(.05)
            self.writeDO([False,True,False,True])
            print(self.readDI())
        self.writeDO([False,False,False,False])
'''
moment.jsのisBetween()の比較対象に、当日も含ませる方法

## 背景
カレンダー形式のDatePickerで開始日と終了日を選択して、該当する期間の要素だけを連想配列から取り出したいというもの。
実装できたものの、自分が体験してきた検索は当日が含まれるモノばかりだった気がして、UX的にもそっちの方がいいと思ったため、調べた。

日付の比較にはmoment.jsを使用した。
[ここ](https://momentjs.com/docs/#/query/)にメソッドが載ってます。

## やりたいこと
[momment.js](https://momentjs.com/)の[isBetween()](https://momentjs.com/docs/#/query/is-between/)の比較対象に当日も含ませたい。

### 通常はこれ。間であればtrueを得ることが出来る
```javascript
moment('2010-10-20').isBetween('2010-10-19', '2010-10-25'); // true
```

### こういう当日でもtrueが欲しい
```javascript
moment('2010-10-20').isBetween('2010-10-20', '2010-10-20'); // trueが欲しい
```

## これで実現した
moment.jsのv2.13.0以降で、包括性を考慮した書き方が出来る。

```javascript
moment('2016-10-20').isBetween('2016-10-20', '2016-10-20', null, '[]'); //true
```
第４引数で、含めるのか除外するのか選択できる。
`[`は、含める。`(`は除外。

[参考](https://momentjscom.readthedocs.io/en/latest/moment/05-query/06-is-between/)
ADB コマンド が 使用できない 時 の 対処法

## 目的

- Windows10のPCでADBコマンドが実行できるようにする方法を知る。  
※本記事はWindows10の解決方法を記載していますが、インストールする際にmac用、Linux用の`SDK Platform-Tools`をインストールし、コマンドのパスを通せば実施可能

## この記事のターゲット

- Windows10でADBコマンドが実行できなくて困っている方
- Windows10にADBコマンドを実行できるようにしたい方
- 「ADBコマンドは実行できるが、Android端末に接続できない！」と困っている方は[こちら](https://qiita.com/miriwo/items/b490c5ea90bd78a20a85)の方法を試してみてほしい
- 下記のようにコマンドがないといわれ困っている方
![AS_ADB_01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/fd5f61c7-cbb3-7dc0-6c49-cc01440f7cfe.png)

## 実施概要

1. `AndroidStudio`の`SDK Platform-Tools`をインストール
1. ADBコマンドのパスを通す
1. ADBコマンドの実行確認

## 実施詳細

1. `AndroidStudio`の`SDK Platform-Tools`をインストール
  1. 下記のリンク先にアクセスする。  
  [https://developer.android.com/studio/releases/platform-tools](https://developer.android.com/studio/releases/platform-tools)
  1. ページのDownloadより`SDK Platform-Tools for Windows`をダウンロード`をクリックする。   
  ![AS_ADB_02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/ad062468-bd0f-c8c4-f30d-64b8bea35c0f.png)
  1.  利用規約を読みチェックボックスにチェックを入れ、`ダウンロードする: ANDROID・・・`をクリックする。  
  ![AS_ADB_03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/71e7fb26-49cf-b4c0-a4ef-897060f52245.png)
  1. ダウンロードが始まる。  
  ![AS_ADB_04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/4fe0d9fd-200d-1bb3-264d-bebec8ccc084.png)
  1. ダウンロードされたzipファイルを解凍し、今後移動することの少ない場所に設置する。  
  ![AS_ADB_05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/c56efe9b-4ca2-f266-1f75-d8948bd1b46b.png) 
1. ADBコマンドのパスを通す
  1. 画面内のタスクバーにあるWindowsマークを右クリックする。  
  1. 「システム」をクリックする。  
  ![AS_ADB_06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/ec881a66-f62a-8175-e839-a308dcaaa2f8.png)
  1. 「システム情報」をクリックする。  
  ![AS_ADB_07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/64b5e711-fa5d-3a6a-7d4c-1b26af81746f.png)
  1. 「システムの詳細設定」をクリックする。  
  ![AS_ADB_08PNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/cf3181b1-c28f-a1ec-48d7-8795ccbf605e.png)
  1. 「環境変数(N)」をクリックする。  
  ![AS_ADB_09PNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/e63803df-43ae-4aa7-4dc7-3950ebff926e.png)
  1. 「システム環境設定」の中にある「path」をダブルクリックする。  
  ![AS_ADB_11PNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/d0981ab4-65e0-c39a-3403-9700d6de86b1.png)
  1. `SDK Platform-Tools for Windows`の解凍品を設置したファイルの場所まで行き、`adb.exe`が表示できているフォルダまでのパスをコピーする。  
  ![AS_ADB_13PNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/ce2175b4-3be8-6124-ade1-11e04a17864a.png)
  1. 「環境変数名の編集」の「新規」をクリックする。  
  ![AS_ADB_12PNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/5c224343-6a5b-faf5-e4b3-92b4754311ee.png)
  1. コピーしたパスを張り付けて「OK」をクリックする。  
  ![AS_ADB_14PNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/596a45a8-f2f1-344f-983a-6c09371c7c0b.png)
1. ADBコマンドの実行確認  
  1. コマンドプロンプトを起動する。
  1. 下記コマンドを実行する。

  ```
  adb version
  ```
  1. 下記のように出力されれば作業完了  
  ![AS_ADB_15PNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bcc4a7b1-3725-ced4-e8c6-17d3424d769d.png)
URLから動画のサイズを参照


```
func resolutionForLocalVideo(url: URL) -> CGSize? {
    guard let track = AVURLAsset(url: url).tracks(withMediaType: AVMediaType.video).first else { return nil }
    let size = track.naturalSize.applying(track.preferredTransform)
    return CGSize(width: abs(size.width), height: abs(size.height))
}
```
1980 x 1080 などを取得できる
Function of OpenEntityManagerInViewInterceptor Spring MVC interceptor

# Function of OpenEntityManagerInViewInterceptor
1. Create a EntityManager instance and bind it to thread when start processing HTTP request
2. Close the EntityManager instance created before when finish processing HTTP request

# Why need it?
Assume entity A, its property 'type' set to entity B. Entity A is created by EntityManager, which is set to lazy loading. This EntityManager instance may be closed if a transaction loading entity A is finished. And then property 'type' of enitiy A is accessed on view layer. Since entity B is a proxy instance and being load if necessary. In order to load entity B, EntityManager which created entity A is necessary. At moment on view layer that EntityManager is gone. As result exception occurs.

If OpenEntityManagerInViewInterceptor is enabled, the EntityManager instance is available at the moment on view layer.

# How to enable it in Spring Boot?
OpenEntityManagerInViewInterceptor is enabled by default. Or you may enable it explicitly by adding below line in property file 'application.properties'.

```
spring.jpa.open-in-view=true
```
プロトタイプチェーンのしくみを知る

# はじめに

```javascript
function Car() {
}
function Truck() {
}
Truck.prototype = new Car();
let t = new Truck();
```
プロトタイプ継承をこのように紹介している書籍をみてとても気持ち悪いを思った。
理屈は分かるし、アイデアとして面白いと思う。
しかし、継承に気を取られその他を破綻させてしまうやり方はどうにも受け入れが難い。
プロトタイプのconstructorを付け替えれば済む話かもしれないが、しなくて良いことをしないまま解決したい。
よりスマートな方法を探して、整理します。
盲点があればご指摘ください。

### 継承しなくても継承の考え方は必要

```javascript
function Car() {
}
let car = new Car();
```

#### explicit prototype property(明示的なprototypeプロパティ)
コンストラクタ ⇒ プロトタイプ
この２つは常に対になって存在する
関数を定義すると、関数ごとにプロトタイプが作成される、ようだ。

#### implicit prototype link(暗黙のprototypeリンク)
インスタンス → プロトタイプ
※ 継承と呼ばれるのはこちら

#### 組み合わせ一覧

下記の図は、インスタンスを中心に読んでいただきたい。
・インスタンスのコンストラクタは誰か？を意識する
・インスタンスはコンストラクタに紐づくプロトタイプをプロトタイプリンクを通じて継承する
※ ⇒ はexplicit prototype property、↑ はimplicit prototype linkを表す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207346/df77e27f-11a0-f874-90f8-f34b80522dbd.png)

#### 実装編

class構文 + extendsを使用するとprototype linkの付け替えをうまくやってくれる
・サブクラスのプロトタイプはスーパークラスのプロトタイプをprototype linkで参照する
・サブクラスのコンストラクタはスーパークラスのコンストラクタをprototype linkで参照する

class構文 + extendsを使用しない場合は、prototype linkの付け替えを自分で行う必要がある。
どのように付け替えるのが適切か
Car.prototype → Object.prototypeはそのままでOK
Car → Function.prototypeはそのままで良いのか？
Car → Object → Function.prototypeとしたい。

```javascript
function Car() {
}
Object.setPrototypeOf(Car, Object);
let car = new Car();
```

#### 本題にもどります

```javascript
function Car() {
}
Object.setPrototypeOf(Car, Object);
// Object.setPrototypeOf(Car.prototype, Object.prototype); // デフォルトと同じなので不要

function Truck() {
}
Object.setPrototypeOf(Truck, Car);
Object.setPrototypeOf(Truck.prototype, Car.prototype);

let t = new Truck();
```

babelの変換結果を見ると、もっと色々な操作が入っているので、まだまだ足りないことがあるのでしょう。
引き続き勉強します。


```javascript
class Car {
}
class Truck extends Car {
}
let t = new Truck();
```
この糖衣構文の内部を完璧に理解することが目標です。
Professional Cloud Security Engineer受験記

##はじめに
2019/9/12にProfessional Cloud Security Engineerを受験して合格しましたので勉強法などを書きたいと思います。

バックグラウンドとしては、AWS歴3年、GCP歴1ヶ月で、Professional Cloud Architect Certification取得済み、一度Professional Cloud Security Engineer落ちて、再受験までの間にProfessional Data Engineer Certification合格して、2回目の受験でProfessional Cloud Security Engineerに合格しました。

##合格までの流れ
###本家サイトで出題範囲を確認する
https://cloud.google.com/certification/cloud-security-engineer
他のProfessional試験と同じで50問、2時間の試験です。日本語での提供はなく英語のみです。

###受験記的なブログを読む
http://deploy.live/blog/google-professional-cloud-security-engineer-beta-exam/
https://medium.com/@techie.rakesh/google-professional-cloud-security-engineer-beta-exam-review-e21445bc2979

CourseraのGoogle Cloud Platformのセキュリティ専門講座を拝聴
https://www.coursera.org/specializations/security-google-cloud-platform
コース2,3の動画を見て、クイズを受けてでわからないとこを調べました。

###本家の模擬試験を実施
https://cloud.google.com/certification/practice-exam/cloud-security-engineer?hl=ja

###QWIKLABSで実機確認
Security系のサービスを実際に触ってみて理解する。

###マニュアル確認
動画や実機確認でわからなかったところに関してマニュアルを読みました。

##結果
1回目の受験は不合格でした。再受験は、2週間開ける必要があったため、理解が足りていない箇所について実機で確認しまて、2回目で合格できました。Security試験に合格するとパーカーかバックがもらえます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/86200610-74be-45ef-a810-bb3232f85f31.png)

##投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。
VirtualBoxの仮想マシンを、コマンドラインから操作する

# `VBoxManage`

`VBoxManage`というコマンドを使うと、VirtualBoxの仮想マシンをコマンドラインから操作することができます。

いくつか、よく使いそうなものを試してみましょう。

コマンド自体の情報は、こちら。

[VBoxManage](https://docs.oracle.com/cd/E97728_01/E97727/html/vboxmanage.html)

以下でも確認できますが、出力内容が膨大になります…。

```shell
$ VBoxManage help
```

# 環境

OS

```shell
$ sw_vers 
ProductName:	Mac OS X
ProductVersion:	10.14.5
BuildVersion:	18F132
```

VirtualBox

```shell
$ VBoxManage -v
6.0.10r132072
```


# 仮想マシンの一覧

[VBoxManage list](https://docs.oracle.com/cd/E97728_01/E97727/html/vboxmanage-list.html)

起動しているもの、停止しているものなど含めて全部の仮想マシンの一覧。

```shell
$ VBoxManage list vms
```

現在実行中の仮想マシンの一覧。

```shell
$ VBoxManage list runningvms
```


# 仮想マシンの起動

[VBoxManage startvm](https://docs.oracle.com/cd/E97728_01/E97727/html/vboxmanage-startvm.html)

```shell
$ VBoxManage startvm "[仮想マシン名]"

## headlessの場合
$ VBoxManage startvm "[仮想マシン名]" --type headless
```

仮想マシンの名前は、`list`で確認しましょう。


# 仮想マシンの停止

[VBoxManage controlvm](https://docs.oracle.com/cd/E97728_01/E97727/html/vboxmanage-controlvm.html)

```shell
$ VBoxManage controlvm "[仮想マシン名]" poweroff
```


# 仮想マシンの情報を確認する

[VBoxManage showvminfo](https://docs.oracle.com/cd/E97728_01/E97727/html/vboxmanage-showvminfo.html)

```shell
$ VBoxManage showvminfo "[仮想マシン名]"
```


OSのインストールなどはさておき、これくらいあれば、作成済みの仮想マシンの操作で困らないでしょう。
【Flutter】iOSアプリがerror: unable to parse contents of file list '<package>/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks-xxx-input-files.xcfilelist'でビルドエラーになる

# 背景
Flutter製iOSアプリをビルドする際に、こんなエラーが出てきました。

```
error: unable to parse contents of file list '<package>/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks-xxx-input-files.xcfilelist'
error: unable to parse contents of file list '<package>/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks-xxx-output-files.xcfilelist'
```

また、色々と試行錯誤している中で下記のエラーも発生しました。

```
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

# 原因
cocoapodsのバージョンが古いことが原因でした。
cocoapodsのバージョンを`1.6.0`から`1.7.5`にアップデートしたところ、無事ビルドすることができました。
Marketing Cloudのデータ削除

#概要
Marketing Cloudからメールを送信したユーザーデータの複数件削除の方法についてまとめます。
MarketingCloudにデータが登録されていることを前提とします。
###対象データ
ログイン → Audience Builder → Contact Builder → すべての連絡先 内に存在するデータです。
<img width="1200" alt="ToContactBuilder.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/678d9e8d-9983-0ff7-1721-8b6753fb6ed1.png">
<img width="1047" alt="ContactBuilderToAllContact.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/685591fc-89bb-3925-958d-0d129a6d0adc.png">
![MarketingCloud_AllContactAll.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/41997850-90c5-ec30-e69f-7bdabc207b76.png)


#削除方法
削除方法は以下の3つです。
 1. UIから削除
 2. Marketing Cloud API(REST)を使用して削除
 3. データエクステンション

##1. UIから削除
####注意
大量データを削除することには向きません。

####削除手順
 1. ログイン → Email Studio → Email → 購読者 → すべての購読者 に遷移
  ![MarketingCloud_AllContactNoCheck.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/926690d0-b099-f05f-bffa-a7ca868e2b0f.png)
 2. チェックボックスにチェックをつけ、削除ボタン押下
 3. 削除完了

 ※左下部のセレクトボックスで25件か50件を選択できますが、大量のデータを削除する場合は、1.、2.を繰り返すことになるため、あまりお勧めできません


##2. Marketing Cloud API(REST)を使用して削除
[POST /contacts/v1/contacts/actions/delete?type=keys](https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/DeleteByContactKeys.htm) を使用します。

####注意
削除するキーのリストがあることが前提です。

####削除手順
以下の内容でAPIを実行する。

```
Host: https://{サブドメイン}.rest.marketingcloudapis.com
POST /contacts/v1/contacts/actions/delete?type=keys
Content-Type: application/json
Authorization: Bearer {アクセストークン}

{
    "ContactTypeId": 0,
    "values": [
        {key1}, {key2}
    ],
    "DeleteOperationType": "ContactAndAttributes"
}
```

※ サブドメイン・・・[Your Subdomain and Your Tenant's Endpoints](https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/your-subdomain-tenant-specific-endpoints.htm?search_text=token) 参照
※ アクセストークン・・・[POST /v1/requestToken](https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/routes.htm?search_text=token) を使用して取得する
※ key・・・Marketing CloudのSubscriberKeyのこと(ContactIdやEmailAddressを複数指定可能)
※ 上記、サブドメイン、アクセストークンについては、APIを使用している場合は、データを登録した時と同じものを使用可能です

##3. データエクステンションで削除する
####注意
UIで削除する方法に似ていますが、UIでの削除と異なる点は、データエクステンションという作成されたテーブルを元に削除する点です。

####削除手順
1. すべての連絡先の画面を開き、右上のゴミ箱アイコンのセレクトボックスから「データエクステンションから連絡先を削除」を選択する
![DeleteByDataExtention.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/f37bb1a5-a93d-2d9e-957d-698481d695ec.png)

2. 削除したいデータを含んだデータエクステンションを選択し、 **連絡先とデータエクステンションの両方を削除する** にチェックを入れ、 **連絡先の削除** ボタンを押下する
<img width="1048" alt="DeleteDataExtention.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/2b32228a-f9a2-a87e-2f51-c941a295567c.png">

3. 確認用のダイアログが表示されるので、**連絡先の削除** ボタンを押下する
<img width="699" alt="DeleteConfirm.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/3d04ffaf-6eb2-9f4d-ebd8-781f260f770f.png">

4. 削除完了

#参考

[Marketing Cloud API](https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/index-api.htm)
みんカラ、やめます。

#概要

blog移行の手順を書いてみます。

#旧blogを全部downloadする。

みんカラに、移行ツールは無いので、htmlを読んでファイルに落とす。
urlは、http://minkara.carview.co.jp/userid/*******/blog/p0/
なので、P0からP99までが、対象。

htmlの中の、<!-- interest_match_relevant_zone_start -->から
<!-- interest_match_relevant_zone_end -->まで、対象。5日分。
自分は、VBS。

#整形して、csvをつくる。

class="contentsTitle"　が、件名。
class="blogMemo"が、本文。
class="blogPostedが、日付。
手作業で、件名,本文,日付のCSVをつくる。
手作業は、エディターでやる。
自分は、oedit。

```
パンク修理。,千円。, 2019/08/08 09:42:06
日本製のタイヤ買った。,タイヤ、リアのリフレクター、５速に入らない調整で、８千円。, 2019/08/08 09:41:23
画鋲を踏んだ。,タイヤが裂けたので、ママの自転車、借りてた。違和感を感じたので、フロントタイヤ見たら、画鋲を踏んでた。最悪。, 2019/08/06 08:41:34
タイヤが、裂けた。,パンクかなと、見たら、タイヤが裂けてた。さすが、中華品質。, 2019/08/06 08:39:06

```


#blogシステムにアップロードする。

csvを読み込んで、x-www-form-urlencodedでPOSTする。
攻撃にならないよう、1秒待つ。
自分は、yumeblog。
アップローダーは、VBS。

以上。
GETとPOSTの違いを検証

# GETの場合

URLの末尾にパラメータを追加し送信される
```
http://localhost:3000/contacts?utf8=%E2%9C%93&authenticity_token=Wc7TNQl6%2FHJiXO5ztGQi0xL5Tu8rv89LHRF6cTjqZpT3NTu0P74bpu6ZI4jlGDZZRxkCBmBT8%2FIUxDJShYzO5Q%3D%3D&contact%5Bname%5D=get&commit=%E9%80%81%E4%BF%A1
```

URLにユーザ名やパスワードが含まれるため、それらの情報がブラウザの履歴に残ってしまう。

# POSTの場合

URLの末尾に追加されず、テキスト形式でbody部分にパラメータを追加し送信される。

![スクリーンショット 2019-09-12 12.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496792/dd0397b5-3b73-b631-1315-21ac52c49fcb.png)


~~サイトへのログイン時など、ユーザIDやパスワードなど人に見られては困る情報を送信するにはPOST送信が適している。~~

bodyにデータを含めて送信するためブラウザの履歴に残らない。パスワードやログイン情報をサーバに送る場合は機密性を考慮してPOSTが使用されます。GETの場合ブラウザによってURLに含められる文字数が制限されるため、大量のデータが送信されることも考慮して、formの送信ではPOSTが使用される。
Eclipse Papyrusで見た目をみんなと同じにする

# Papyrusを使ってみる

これまでPlantUMLでクラス図など書いていたのですが、クラス図からコード生成とかやってみたくて、

[OSSのUMLモデリングツールpapyrusを使ってみよう ~インストール編~ - Qiita](https://qiita.com/yurie/items/6681cd64491c5f0bc36b)

などを参考に、Papyrusを使い始めました。

上記記事では「Papyrusのパッケージ(Papyrus RCP)を使う」でインストールしていますが、せっかくなので私は
「Eclipseプラグインを追加する」でインストールしてみました(Help -> Install New Softwareですね)。

# なんか見た目が違う

ですが何かちょっと見た目が違うんです…
![ModelPerspective.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19629/10b32794-dfef-2bfa-e0ff-9d202ad232d2.png)



[Papyrus User Guide - Eclipsepedia](https://wiki.eclipse.org/Papyrus_User_Guide#UML_modeling)
などの表示と比べると何か微妙に違っています。

- Model Explorerにはクラスの一覧とか、ダイアグラムが出るはずなのに、xxx.diとかxxx.umlとかのリストしか出ない。
- Window -> Show View -> Model Explorerなどを選んでも変わらない。

Eclipseを知ってる人なら常識なのでしょうが、こういうときはPerspective(レイアウト設定的な何か?)を切り替えるようです。

# Papyrus用のPerspectiveへの切り替え方

1. Windows -> Perspective -> Open Perspective -> Otherを選択
![PapyrusPerspective.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19629/ade43be6-f978-0dc6-2861-fb96e1d6d364.png)

2. PapyrusのPerspectiveを選択
![PapyrusPerspective2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19629/ab3daf43-c827-45ec-25a1-0d655f5201d5.png)

3. User Guide などと同様な見た目になる。
![PapyrusPerspective4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19629/b2f8f17e-f761-50b9-9bc7-c0332e0ae0d9.png)
DockerでVuePressを始めてみる

# ディレクトリ構成

```
.
├── _docker-config
│   └── docker-compose.yml
├── docs
│   └── README.md
├── node_modules
├── package-lock.json
└── package.json
```

## 操作

```docker-compose.yml
version: "3"
services:
  node:
    image: node:12.10-alpine
    working_dir: /home/node/app
    volumes:
      - ../:/home/node/app
    ports:
      - 8081:8080
    environment:
      - HOST=0.0.0.0
```

`_docker-config` ディレクトリ内で

```
$ docker-compose run node npm init -y
$ docker-compose run node npm install -D vuepress
```

package.jsonを編集

```package.json
{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs"
  },
  "repository": {
    "type": "git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vuepress": "^1.0.4"
  }
}
```

編集後

```
$ docker-compose run --service-ports node npm run docs:dev
```

を実行して[localhost:8081](http://localhost:8081/)にアクセス。

以下が表示されればOk
[![Image from Gyazo](https://i.gyazo.com/1cbed84867e454fe7b4698bf30de37ba.png)](https://gyazo.com/1cbed84867e454fe7b4698bf30de37ba)

## 参考

[VuePress公式ドキュメント](https://vuepress.vuejs.org/)
スマホページで、フォントのサイズが同じですが、場所による、大きさが違う

# はじめに
最近スマホページの作成をしたのですが、フォントのサイズが同じpxで指定していますが、iOSで確認すると場所によって大きさがバラバラになります。どんな原因なのか、ちょっど調べてみました。実はスマートフォンの場合、自動的にフォントサイズを調整する機能があります（Chromeも）。この機能によって、フォントサイズが自動的に調整されています。

# 解決する方法
では、そのスマートフォンの自動的にフォントサイズを調整する機能をオフしたっら、解決できると思いますが、調べてみて、機能をオフにするためには、

```css:qiita.rb
body{
      font-size-adjust: none;
      -webkit-font-size-adjust: none;
}
```

もし、これでうまくいかなかったら、

```css:qiita.rb
body{
      -webkit-font-size-adjust: 100%;
}
```

簡単ですよね！
マイクロマウスをはじめまチュー（２）

[「マイクロマウスをはじめまチュー（１）」](https://qiita.com/tkato635/items/ec5312a6f9dffa101da7)の続きです。

#ハードウェア作成
購入したマイクロマウスの[「Pi:Co Classic3」](https://www.rt-net.jp/products/pico3)は組み立てキットなので、まずはハードウェアの作成が必要です。
説明書はWEBサイトからダウンロードします。説明書はハードウェアとソフトウェア共に充実しているので、
初心者でも安心して出来そうです。

- パート1 基礎知識編
- パート2 ハードウェア製作編
- パート3 環境構築編
- パート4 ソフトウェア開設編
- 操作説明書
- 部品説明用語集

説明書を一通り目を通して、リチウムポリマの充電器が必要なことが分かったので、
[「アールティロボットショップ」](https://www.rt-shop.jp/)で注文しました。
これから購入を考えている方は、充電器は必須と思いますので、組み立てキットと合わせて購入した方が良いと思います。

#半田付けの練習
組み立てキットには、半田付けが不慣れな人のために半田付けの練習基板が付属しています。
練習基板は、電子工作では定番のLチカです。私は練習の必要はないのですが、せっかくなのでやってみました。
無事にLEDが点灯しました。

![IMG_20190913_142457.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490861/b1a0ed5e-d5c5-886a-42a5-28227e9c41be.jpeg)

さあ、まずはハードウェアを作成しまチュー。
CSSで正方形の背景を作るサンプル

CSSで正方形の背景を作るサンプルを簡単に作るコードを公開したいと思います。
[サンプル](https://codepen.io/engineerhikaru/pen/ZEzXqGr)
##課題
widthやheightで指定するのでなく、親要素に対し幅いっぱいつまり可変なwidthとheightにしたい。

##コード
早速コードを書きます。

```html:HTML
<div class="square">
</div>
```

```css:CSS
.square{
  position: relative;
  width: 100%;
  padding-top: 100%;
  background: #eee; /* 好きな色に */
}
```
これだけでOKです。ポイントとしてはwidthとpadding-topを同じ値にする事です。
なお、padding-topはpadding-bottomにしても良いです。

##応用
この正方形の背景の中に文字を入れたい時は、position:absoluteを使っていきます。

```html:HTML
<div class="square">
  <p class="p-center">SQUARE</p>
</div>
```

```css:CSS
.square{
  position: relative;
  width: 100%;
  padding-top: 100%;
  background: #eee; /* 好きな色に */
}
.p-center{
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  width: 100%;
  text-align: center;
}
```
こんな感じで、めちゃ楽勝です。
自動採番のIDを取得する

#自動採番したIDを取得する

```java


		// 自動採番取得用メソッド
		@PostConstruct
		public void init() {
			SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert((JdbcTemplate) template.getJdbcOperations());
			SimpleJdbcInsert withTableName = simpleJdbcInsert.withTableName("orders");
			insert = withTableName.usingGeneratedKeyColumns("id");	
	}
```

インサートした後に自動採番で振られたIDを取得してreturnする

```java

public Order insert(Order order) {

    // ドメインの名前とSQLの？部分があっていれば自動的に入っていく
     SqlParameterSource param = new BeanPropertySqlParameterSource(order);
   
    // executeAndReturnKeyが勝手にインサート文を実行してくれる
     Number key = insert.executeAndReturnKey(param);

     order.setId(key.intValue());

	return order;
}

```

備忘録として残します。
何かご指摘あればお願いします。
簡単なHTML記述で「ハッシュタグをつけてツイートする」ボタンを作る。

Pythonでウェブアプリケーションを作っているときに、Twitterに投稿するボタンを作りたいと思って調べました。

実は、ツイート内容を指定してツイートさせるだけなら（ツイートのリンクに飛ばすだけなら）TwitterAPIは必要ありません。TwitterのAPIを使うために、デベロッパーとして登録して、そのためには英語でウェブアプリケーションの概要を説明して……。など面倒な作業を行う必要はないので安心です。

今回はBootstrapを使ってボタンを作っているので、厳密にはHTMLのみでないです。

実際の挙動は[こちら](https://airjikkyou.herokuapp.com/7/)で。ソースコードは[こちら](https://github.com/ttmone/airjikkyou/blob/master/templates/app/detail.html)。

## 本記事の概要
* HTMLの記述のみでツイートボタンができる
* ハッシュタグ、テキスト、@ユーザー、URLなどが指定できる
* 結局aタグのhref属性の指定でうまくやれる
* Bootstrapのおかげでボタンが簡単に作れる

## 実際に書いたコード
btn-primaryを指定したので青いボタンです。Djangoのために書いたものなので繁雑に見えますが、静的ページならより簡潔に書けます。

```html:detail.html
<a class="btn btn-primary" href="https://twitter.com/intent/tweet?url={{ request.scheme }}://{{ request.get_host }}{% url 'app:detail' post.pk %}&text={{ post.comment }}&hashtags=いつでもエア実況_{{ post.title }}_{{ post.episode }}話_{{ post.start_time|date:"Y年m月j日H時i分" }}から" target="_blank">
        ハッシュタグ付きでツイートする
</a>
```
チートシートっぽく書くとこう。

```html
<a class="btn" href="https://twitter.com/intent/tweet?url=(リンクにしたいURL)&text=(テキスト)&hashtags=(ハッシュタグ)&screen_name=(リプライにしたいアカウント)>
ツイートする
</a>
```
## 解説
* href="https://twitter.com/intent/tweet/" までは定型文。飛べばわかりますが、ツイート画面です。
* 最初の要素は"?"をつけて始める。以降は"&"で繋げる。
* 複数のハッシュタグをつけたいときは、半角スペースで区切ってあげる。
* target="_blank"を指定すると「新しいタブで開く」になる
* 改行の含め方はわかりませんでした。

## 感想
思いの外簡単にできて驚きました。APIとかいらないんですね。

それとBootstrapのおかげで、クラス指定だけでボタンになるのもすごい便利ですよね。おかげでCSSが全然わからない。
movie graphql

graphql을 연습해보았다.

```javascript:db.js
export const people  =  [
    {   id : "1",
        name : "sean",
        age : 49,
        gender : "female"
    },
    {   id : "2",
        name : "yumi",
        age : 49,
        gender : "female"
    },
    {   id : "3",
        name : "sohui",
        age : 49,
        gender : "female"
    } 
];

export const getById = id => {
    const filteredPeople = people.filter(person => person.id === String(id));
    return filteredPeople[0]
}

```

```javascript:resolvers.js
import {people, getById} from "./db";

const resolvers  = {
    Query : {
        people : () => people,
        // person : (_,{id}) => getById(id)
        person : (_,args) => console.log(args)
    }
}

export default resolvers;
```

```graphql:schema.graphql
type person {
    id : Int!,
    name : String!,
    age : Int!,
    gender : String!
}

type Query {
    people : [person]!
    person(id:Int!):person!
}
```
Angular : Firestoreのデータをページネーションしたい① ～ 超簡単なやり方

#Angular : Firestoreのデータをページネーションしたい① ～ 超簡単なやり方

###環境

```
Angular CLI: 7.1.4
Node: 10.15.3
OS: win32 x64
Angular: 7.1.4

"@angular/material": "^7.3.4"
```


###前提
Firestoreからとってきたデータを以下のようにngFor文でづらづらっと並べていくHTMLがあったとする。

```html
<div style="display:inline-block; width: 100%" *ngFor="let post of posts | async">
        <p>名前：{{ post.userName }}</p>
        <p>メッセージ：{{ post.userName }}</p>
        <p>投稿日時：{{ post.created }}</p>
</div>
```

###ページネーションのやり方
なんと*ngFor文のうしろにパイプをかまして"slice: [ページインデックス番号] : [1ページ当たりのデータ件数]" を追記するだけ！

例：

```html
<div style="display:inline-block; width: 100%" *ngFor="let post of posts | async | slice: 0:10">
```

これで1ページあたり10件表示するページネーションができる。


###ページャーの作り方
 あとは[ページインデックス番号]と[1ページ当たりのデータ件数]に渡す数値は変数にして関数を使って制御すればいい。HTMLにはページャー（クリックするとこ）を作成して、

```html
<ul class="pagination">
  <li><a class="page-link" href="#" (click)="pager(0)">1</a></li>
  <li><a class="page-link" href="#" (click)="pager(1)">2</a></li>
  <li><a class="page-link" href="#" (click)="pager(2)">3</a></li>
</ul>
```

コンポーネントのほうに、関数を作る。

```typescript
  begin= 0; //[ページインデックス番号]
  length = 10; // [1ページ当たりのデータ件数]
  pager(page: number) {
    this.begin = this.length * page;
  }
```
<br>

こんな風になるみたい。
<img src="https://image.itmedia.co.jp/ait/articles/1803/01/dt-bi2dt-at-041-02.gif">
ページャーがかっこいいのはBootstrapのスタイルシートをインポートしているようだ。

###結論
これだとデータ数が増えていったら手作業でページャーボタンを増やしていかなければならない。でも簡単ねー


参考：[Angularで「ページング」処理を実装するには？（ngFor／slice）](https://www.atmarkit.co.jp/ait/articles/1803/01/news157.html)

<br>
GASで自分のツイートを取得してスプレッドシートに記録するやつ

急にツイ消ししたくなった場合に備えて、自分のツイートをグーグルスプレッドシートに記録しておくことにしました。

[GASでTwitterの投稿とタイムライン取得](https://qiita.com/golyat/items/6b430986dbfd8dd1c239)
こちらの記事を参考にして書いてみました。

![20190828150010.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406061/43b4b722-3b85-bb5e-be81-133be3f4d987.jpeg)
画像のように記録されます。


```javaScript

 var twitter = TwitterWebService.getInstance(
 '**********',       // 作成したアプリケーションのConsumer Key
 '**********'  // 作成したアプリケーションのConsumer Secret
);

// 認証を行う（必須）
function authorize() {
  twitter.authorize();
}

// 認証をリセット
function reset() {
  twitter.reset();
}

// 認証後のコールバック（必須）
function authCallback(request) {
  return twitter.authCallback(request);
}

function getMyTweets() {
  var service  = twitter.getService();
  var json = service.fetch("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=ツイートを取得したいユーザーのid&count=30");
  var array = JSON.parse(json);
  
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('ツイートを保存したいシートの名前');
  var lastRow = sheet.getLastRow() +1;
  var lastId = sheet.getRange("D2").getValue();
  
  for(var i = 0; i <= array.length -1; i++) {
    
    var int = parseInt(i);
    
    if(i === 0){
      var recId = array[int]["id"];
      sheet.getRange("D2").setValue(recId);
    }
      
     var id = array[int]["id"];
      
     if(id > lastId){
       var time = array[int]["created_at"];
       var text = array[int]["text"];
        
       sheet.getRange(lastRow,1).setValue(time);
       sheet.getRange(lastRow,2).setValue(text);
       sheet.getRange(lastRow,3).setValue(id); 
     }
    lastRow = lastRow + 1;
    }
  }
```

自分のツイートを最新のやつから30件まで取得して、idが以前取得したツイートより大きければスプレッドシートに書き込む……という感じです。

ここ違うよ〜とかもっと良い書き方あるよ〜って場合は気軽にコメントください。
Travis CIのchrome安定版のバージョンが古くなっている。

Travis CIでLaravel5.8で作ったウェブアプリのブラウザテストとユニットテストをしています。
ブラウザテストの時に使うchromeのバージョンはTravis CIが指定しています。

```
$ google-chrome-stable --version
```

で毎回バージョンを確認して76がインストールされていたのですが、ある時からなぜか62がインストールされるようになりchrome driverとのバージョンが合わず、エラーを出しました。

Laravel Duskではchrome driverのバージョンを指定してインストールするコマンドが用意されています。
ですがchromeのバージョンが変わった時にいちいち.travis.ymlを書き直すのは面倒です。
なので自動でchromeのバージョンを確認してdriverをインストールできないかと考えていたのですが、[staudenmeir/dusk-updater](https://github.com/staudenmeir/dusk-updater)というライブラリでできることを発見しました。

###インストール

```
composer require --dev staudenmeir/dusk-updater
```

chromeのバージョンを確認してdriverをインストール

```
php artisan dusk:update --detect
```
CronTabを作成してみる

# Crontabとは
JOBを定期的に実行してくれるコマンドです。

# 登録方法
Cronの設定ファイルに記載することで実行してもらえます。
設定ファイルの起動は以下。

```bash
$ crontab -e
```

こちらを実行するとエディタが開かれるので、
一番下に実行したいコマンドを記載。
今回はShellScriptを記載し、それを定期実行するCronTabを設定しました。
なお、ShellScriptはchmodで権限を755にしておくこと。

```bash

*/5 * * * * ./home/vagrant/test.sh
```

### Cron設定ファイルの記載方法
「時間 実行するコマンド」と記載します。
時間は左から「分 時間 日 月 曜日」で記載します。
時は24時間表記、曜日は0から6まで日曜日から土曜日までに対応し、さらに7はまた日曜に対応。
また、ワイルドカードの使用、間隔の指定が可能です。

| 書き方 | 意味 |
|:-----------------|:------------------:|
| 00 8 1 * * | 毎月1日の8時に定期実行 |
| */1 * * * * | 毎分定期実行 |
| 00 12 * * * 1 | 毎週月曜日に定期実行 |


# 登録されているCrontabの確認
Crontab -l で設定されたcrontabを確認可能。
なお、ユーザー毎に設定するものであるため、
各ユーザーの設定値を確認する場合は、

```bash
for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
```
で可能。

# ほんとに実行されたよね？の確認。。
/var/log/cronに実行ログがある。
下に追記されているのでtailなどで見るのが手っ取り早い。

# 実行されてない場合の確認方法
### ログ出力
Cron設定のコマンドにリダイレクトを書くだけです。

```bash
crontab -e
```

```bash
*/5 * * * * bash /home/vagrant/test.sh >> /home/vagrant/test.log 2>&1
```

\>>でリダイレクトすれば追記してくれます。
なお、最後の2>&1は標準出力もエラー出力もする設定。
標準出力のみの場合は```test.sh 1> test.log```
エラーのみでいい場合は```test.sh 2> error_test.log```
とする。

### 結局は
Crontabに登録するコマンドを直叩きしてうまくいくかどうか確認して、
うまくいってからCrontabに登録するのが一番確実。
一行目のおまじない忘れとかスペース問題とかCrontabのログより気が付きやすいので。

```bash
bash /home/vagrant/test.sh >> /home/vagrant/test.log 2>&1
```



# 参考
 [crontabコマンドについてまとめました 【Linuxコマンド集】](https://eng-entrance.com/linux-command-crontab)
 [cronのログを見よう](http://www.sooota.com/cron%E3%81%AE%E3%83%AD%E3%82%B0%E3%82%92%E8%A6%8B%E3%82%88%E3%81%86/)
 [cronがうまく動かないときの調査](https://qiita.com/kkoito/items/28d9a453c425b08738d2)
Ethereumよく聞かれる質問（メモ）

# 注記
質問されてパッとでてこなかったり他のブロックチェーンとごっちゃになったりするので防止用メモです。
メモなので不定期に更新されます。

# Ethereum
## 仕様やスペック
### TPS

### ブロック生成時間

### ブロックに入るトランザクション数の上限
- トランザクション数に上限はないが、Gasの上限がある。この上限はGas Limitという。
- Gas Limitはブロックごとに異なり、Minerの投票によって決まる。
- 2019/09/13現在でMainnetのGas Limitは約8,000,000

参照元: https://medium.com/@piyopiyo/how-to-get-ethereum-block-gas-limit-eba2c8f32ce

### Gas消費量は何によって決まるのか

# Solidity

# Truffle, Ganache

#
夏の終わりの怖い話：Argument list too long(前編)

ある日、circle CIのジョブでエラーが出たんですよ。数千のファイルを削除するコミットで走ったジョブでした。

```
(EDITED)/root.sh: line 2: /usr/bin/dirname: Argument list too long
```

そりゃあ仕事ですからね、億劫ですがすぐに`rerun job with SSH`しましたよ。といっても例の如く１０分ぐらい待たされるんですが。で、ログインしてジョブを手動で動かしても同じエラーが出る。スクリプトを見てみましたがなーんの変哲もないスクリプトなんですよ。ただレポジトリのルートディレクトリをとっているだけ。

```
repository_root() {
    local cwd=$(cd $(dirname ${BASH_SOURCE[0]}) && pwd)
	echo "${cwd}/../../.."
}
```

この`dirname ${BASH_SOURCE[0]}`で`Argument list too long`エラーになるらしいんです。そりゃあすぐに`echo ${BASH_SOURCE[0]}`してみましたよ。でも`(EDITED)/root.sh`と出るだけです。

いやだな、こわいなと思いつつ、仕事ですからね、`set -x`いれてどういう引数を受け取っているか見ようとしたんですよ。



自分の目が信じられませんでした。

``` 
+++ repository_root
++++ dirname (EDITED)/root.sh
(EDITED)/root.sh: line 5: /usr/bin/dirname: Argument list too long
+++ echo /../../..
```

しかもそのすぐ上に同じくこの関数を呼び出していたんです。

```
+++ repository_root
++++ dirname (EDITED)/root.sh
+++ echo (EDITED)/../../..
```

もう気がおかしくなりそうになりながらroot.shを修正しました。[shell parameter expansion](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html)すれば流石に大丈夫だろうと思いましてね。

```
repository_root() {
    echo "${BASH_SOURCE[0]%/*}/../../.."
}
```

もう一度ジョブを走らせるとdirnameの部分はパスしたようです。ほっと一息ついたのも束の間でした。

次の瞬間私の目に飛び込んできたのは

```
+++ echo
+++ grep git
(EDITED)/git.sh: line 6: /bin/grep: Argument list too long
++ '[' '!' -z '' ']'
++ source ci.sh
+++ ENV1=
++++ echo
++++ grep ci
(EDITED)/ci.sh: line 4: /bin/grep: Argument list too long
+++ '[' '!' -z '' ']'
+++ ENV2=
++++ echo
++++ grep job
(EDITED)/ci.sh: line 8: /bin/grep: Argument list too long
+++ '[' '!' -z '' ']'
+++ '[' '!' -z '' ']'
+++ GIT_USER_NAME=username
+++ GIT_USER_MAIL=mail@addre.ss
+++ git config user.name $GIT_USER_NAME
(EDITED)/ci.sh: line 32: /usr/bin/git: Argument list too long
```

うわあああああああああ！！！！！

too longなリストはこのコミットで消された数千のファイル達でしょうか。誰か助けてください。そしてビルドを通してく

テープはここで終わっている。

やれやれ。失踪した前任者の行方とビルドが失敗する原因の手がかりはたったこれだけか。
しかししょうがない。これも仕事だからな。俺は早速この問題に取りかかった。
[後編に続く](https://qiita.com/umegaya/private/b9c6710240c4f20e6334)
google speech apiの音声変換で使う音声ファイル

映像(mp4)をmp3に変換し、wavに変換します。
wavに変換します。
wavに変換するときは、monoオーディオに変換することと、サンプルレートを忘れないようにしておく必要があります。

Audio Auditionでmp3からwavに変換しました。

変換する際の設定は以下のようにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/627aee15-f5e1-1024-c3f6-20dd5e6f07eb.png)


```python
import io
import os

# Imports the Google Cloud client library
from google.cloud import speech
from google.cloud.speech import enums
from google.cloud.speech import types

# Instantiates a client
client = speech.SpeechClient()

# The name of the audio file to transcribe
file_name = os.path.join(
    os.path.dirname(__file__),
    'resources',
    'audio.wav')


with io.open(file_name, 'rb') as audio_file:
    content = audio_file.read()
    audio = types.RecognitionAudio(content=content)

config = types.RecognitionConfig(
    encoding=enums.RecognitionConfig.AudioEncoding.LINEAR16,
    sample_rate_hertz=16000, # サンプルレート
    language_code='ja-JP') # 日本語指定

response = client.recognize(config, audio)

for result in response.results:
    print('Transcript: {}'.format(result.alternatives[0].transcript))

```

コンソールに日本語が表示されました！
php-master-changes 2019-09-01

この日は mysqli の E_STRICT 削除、substr_compare() / substr_count() の警告を例外投げるエラーに昇格する修正があった！

# 2019-09-01
## Girgias: Drop E_STRICT notice in mysqli extension
- https://github.com/php/php-src/commit/e895e962867123aff6ea703ff41670b7eb5c47f1
- [7.4~]
- ext/mysqli で、E_STRICT の警告を削除
- [PR:4406](https://github.com/php/php-src/pull/4406)

## Girgias: Promote warnings to errors in substr_compare()
- https://github.com/php/php-src/commit/0240b903c58211993ee11fdf137d809d6d75436d
- [substr_compare()](https://www.php.net/manual/ja/function.substr-compare.php) の警告を例外投げるエラーに昇格

## Girgias: Promote warnings to errors in substr_count()
- https://github.com/php/php-src/commit/d0754b86b1cb4774c4af64498641ddaaab745418
- [substr_count()](https://www.php.net/manual/ja/function.substr-count.php) の警告を例外投げるエラーに昇格
既存プロジェクトのDBをバージョン管理する

# 導入する経緯
現在ec-cube2の改修案件を複数人で作業をする事がしている。
ソースコードはgitで管理しているが、テーブル定義の変更など管理されていない為、誰がどういう変更をしているかわからない。
他にはデプロイの際に環境毎にクエリを直接挿入するが、人的ミスが発生しないようコマンドのみで完結できるようにしたい。

Laravelを使ったプロジェクトはマイグレーションファイルがあるので困ったことはないが、ec-cube2においてはマイグレーションツールはないので代用を探していたところ[Phinx](http://docs.phinx.org/en/latest/index.html)を知り、導入してみました。

## 今回使うツール
[Phinx](http://docs.phinx.org/en/latest/index.html)はCakePHP公式マイグレーションツールで本ライブラリを導入するだけで独立したコマンドツールとして導入できる。

# 手順
今回はローカルに導入するところまで
1. composerでPhinxを導入
2. .gitignoreにPhinx.ymlを追記
3. Phinx.ymlの生成
4. Phinx.ymlに設定を追加
5. マイグレーション定義ファイルの生成
6. マイグレーションの実行

既存テーブルは40個以上あるので、全てのテーブルを定義するのは手間なので、今回はsqlファイルで一括定義しています。
以降はしっかりバージョン管理していく感じです。

## composerでPhinxを導入

### composer.jsonがある時

```
composer install require robmorgan/phinx
```

### composer.jsonがない時

```
composer init #composer.jsonの生成が目的なので、設定項目は全て空白でもいい。
composer install require robmorgan/phinx
```

## .gitignoreにPhinx.ymlを追記
```
Phinx.yml
```

## Phinx.ymlの生成
```
$ vendor/bin/phinx init
Phinx by CakePHP - https://phinx.org. 0.8.1

created ./phinx.yml
```

## Phinx.ymlに設定を追加
今回はローカル環境での検証ですので、developmentの項目を各自の環境に合わせて変更してください。

```
development:
        adapter: mysql
        host: 127.0.0.1
        name: db_name
        user: root
        pass: 'pass'
        port: 3306
        charset: utf8
```

事前にマイグレーションファイルが格納されるDirectoryを生成する必要があります。
Directoryがなければマイグレーション定義ファイルの生成時にエラーが帰ってきました。

```
$ mkdir -p db/migrations
$ mkdir -p db/seeds
```
mkdirにオプション-pを付与するとエラーを表示せず記述したディレクトリが存在しなければ作成するという動作になる。

## マイグレーション定義ファイルの生成
今回はec-cube2の既存テーブルを初期テーブルとして生成します。
まずはマイグレーションファイルを生成します。

```
./vendor/bin/Phinx create InitialTable

```
initial.sqlの中身を以下のように書き換えます。
これで実行時にsqlファイルで定義されているテーブルを生成してくれます。

```php5

use Phinx\Migration\AbstractMigration;

class InitialTable extends AbstractMigration
{
    public function up()
    {
        $file =   'db/migrations/initial.sql';
        $this->execute(file_get_contents($file));
    }

}

```

続いて既存DBからテーブル定義のみのsqlをエクスポートしておきます。
今回はinitial.sqlという名前でエクスポートしました。
そのファイルを以下Directoryに格納します。

```
db/migrations/initial.sql
```

## マイグレーションの実行
マイグレーションを実行するとinitial.sqlの中で定義されたテーブルが生成されました！

```
./vendor/bin/Phinx migrate
```

## マイグレーションの状態を見る
現在どのマイグレーションまで実行されているかを確認するには以下のコマンド。
Status
up 同期済み
down 未同期

```
./vendor/bin/Phinx status 

 Status  [Migration ID]  Started              Finished             Migration Name 
----------------------------------------------------------------------------------
     up  20190913022811  2019-09-13 12:11:35  2019-09-13 12:11:38  InitialTable
     up  20190913024518  2019-09-13 12:11:38  2019-09-13 12:11:38  AddColumnCategoryTable
     up  20190913030727  2019-09-13 12:11:38  2019-09-13 12:11:38  AddColumnDtbProductsSetTable

```

普段Laravel使っているので1時間もしないうちに理解できました！
学習コストも低くておすすめです！

参考
[Phinx導入ガイド
](https://qiita.com/macchaka/items/3decc5f48a15f00e188c#3%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)
[Cakephp3 migrations plugin (Phinx) を既存の環境に導入する]()https://qiita.com/geerpm/items/f28a3dbf5aa744eb0ba7
Railsエラー GemNotFoundExceptionの解決方法

gitで既存のRailsアプリを新しくクローンし、bundle installをした結果以下のエラーが発生。

```
Traceback (most recent call last):
	4: from bin/rails:7:in `<main>'
	3: from bin/rails:7:in `require_relative'
	2: from /Users/ishizukatakero/projects/error-pictweet/error-pictweet/config/boot.rb:3:in `<top (required)>'
	1: from /Users/ishizukatakero/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
/Users/ishizukatakero/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require': cannot load such file -- bundler/setup (LoadError)
```

その後、

```
gem install bundler
```

を実行したが、以下のエラーが発生。

```
You have requested:
  sass-rails = 5.0.8

The bundle currently has sass-rails locked at 5.0.7.
Try running `bundle update sass-rails`
```

Gemfile.lockのsass-railsのバージョンを5.0.8に変更。
その後、

```
bundle update sass-rails
```

を実行し、その後、

```
bundle install
```

を実行して解決。
lessで grid-row/grid-column が計算されてしまう対策

## 発端

less環境で以下のようなGird用スタイルを組んだところ…

```css:コンパイル前
.classname {
  grid-row: 1 / 3;
  grid-column: 1 / 4;
}
```

以下のように出力されてしまった。

```css:コンパイル後
.classname {
  grid-row: 0.33333;
  grid-column: 0.25;
}
```

lessのコンパイル時に「1 ÷ 3」のように解釈して計算してしまうようでした。

[ググったところ同じようなトラブルの解決策があった。](https://stackoverflow.com/questions/45957961/problems-with-compile-grid-column-less)

## 解決方法

やり方は2通り。

```css:スラッシュをエスケープする方法
.classname {
  grid-row: 1 e("/") 3;
  grid-column: 1 e("/") 4;
}
```
```css:値を文字列として扱う方法
.classname {
  grid-row: ~"1 / 3";
  grid-column: ~"1 / 4";
}
```

好きずきだと思いますが、自分は後者の方が「値を文字列にしてるな」と分かりやすいので後者推しです。
php-master-changes 2019-08-31

この日は SoapServer::addSoapHeader() のエラー処理の修正、ZTS での alloca サポートを有効化する修正があった！

# 2019-08-31
## nikic: Check zpp before other errors in SoapServer::addSoapHeader()
- https://github.com/php/php-src/commit/ec9297592e30d5fe347bc4de21f01b2c4e04df54
- ext/soap で、[SoapServer::addSoapHeader()](https://www.php.net/manual/ja/soapserver.addsoapheader.php) のエラーチェックで ZPP のチェックを先に行うよう修正

## nikic: Reenable alloca support on ZTS
- https://github.com/php/php-src/commit/77a0fa101ed59f05ea07b03adb1cb66962fc45e7
- [7.4~]
- ZTS での alloca サポートを再有効化
- [Netware のサポートを落とした際](https://github.com/php/php-src/commit/2104bea5d756dfa40b605a4a2765a3bc4637a76c)に誤って無効化されていたもよう
Kubernetesで反映されているYAMLを好きなエディタで確認する方法

## はじめに
Kubernetesを日々運用していると、Manifestに正しくコンフィグを書いたつもりでも上手く反映されないなどのシーンがたまにあります。

こういう場合、実際に反映されている設定内容を確認する方法がいくつかあるのですが、その中で `kubectl edit` コマンドは、中でエディタを起動して内容を変更して反映する機能がついています。

## editのリスク

一見、この機能は便利に見えますが、本番環境でeditするのは極めて危険であり、宣言的なインフラ構成を守る、という意味でも変更を加えるときは極力 `kubectl apply` を使うべきです。

## editを閲覧のみで使いたい

editは、デフォルトではvi(vim)が起動するようになっていて、この状態では入力モードに遷移することが可能です。

そこで、viの閲覧モードである `view` を使うことができれば「余計な変更を加えるリスク」を抱えることなくviの体験で設定を確認することができます。

## やりかた

[Kubectlのリファレンス](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#edit)でも示されている通り、 `KUBE_EDITOR` という環境変数を使うと、デフォルトのエディタを変更することができます。

```sh
KUBE_EDITOR=view kubectl edit pod podname
```

ついでに、emacsなどの好みのエディタにすることもできるので、vi普段使わない人には便利かもしれません。

## その他の方法
`kubectl get pod podname -o yaml | vim -`

これを使うと、そもそも出力内容がエディタに渡るだけなので編集する心配もなくてよさそう。@superbrotherさんに教えてもらいました。
【UiPath Orchestrator】スケジュールに任意の休日(非稼働日)を設定する方法

#困っていること
基本毎日動かすロボットだが、社休日のような土日でも祝日でもないオリジナルの休日を設定できない

#対処方法
Orchestratorの「非稼働日設定」を使用する

１．Orchestrator管理画面右上にある自分のアイコンをクリックし、「設定」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/b782fc4c-96c2-f597-0a5b-070fb6fd7799.png)

２．設定タブより「非稼働日」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/69092fa3-114e-0ff7-11a4-8c6312c8dc92.png)

３．カレンダーが表示されるので、休日扱いにしたい日をクリックして選択、「保存」を押下し設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/ee5ba26f-837a-861f-dd5c-1a36b6ac23ca.png)
（関係ないけど1/22は私の誕生日です）

４．スケジュールタブで非稼働日を反映させたいプロセスを作成、もしくは編集し「非稼働日制限を適用」をオンにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/b6adc840-dbff-bf7e-2bee-7fa4d5805b08.png)

参考：[UiPathOrchestratorユーザーガイド](https://docs.uipath.com/orchestrator/lang-ja/docs/about-schedules#section-non-working-days)

#まとめ
祝日はAPIを使用することで検出できますが、社休日みたいなオリジナルの休日はOrchestrator側で指定ができるよーってお話でした。

社休日も関係なく動かしたいロボットは「非稼働日制限を適用」をオフにしておけばスケジュール通り動作するので、うまく使い分けて使用するのがよさそうです！
PHPの戻り値（return）無し関数の戻り値void型

↓↓↓ 既に答えが書かれている記事を発見
[PHPにおけるvoidとは何か](https://qiita.com/tadsan/items/154070f1ee4c7fe4ae47)

え、折角実験して遊んでたのに答えあるやん！
最初からググればよかった…

（いや、きっと自分で試した事にこそ意味がある！！）

## PHPのreturn無し関数の戻り値
PHP7.2以上を前提
Laravelでの検証を前提にして`logger()`を使わせていただきました。

```php
public function main(array $data): void
{
   $res = $this->noReternFunction($data);
   logger($res);  //出力: なし
   logger(gettype($res)); // 出力: NULL
}

private function noReternFunction(array $data): void
{
   // 何もしないぜ！！returnも返さねぇ！！
}
```

### 結果

NULLでした。
そして、`logger()`は検証には向いてない。