OmniAICreator/Qiita-1.07M huggingface dataset:
プラグインを使わずページネーションを実装する

プラグインを使わずページネーションを実装する関数。
paginate_links関数だとhtmlを自由に変更出来ないので独自関数で対応。

```php:functions.php
/**
 * ページネーション
 */
function get_pagination($pages = null){

  global $wp_query, $paged;

  $output = '';
  $pages  = $wp_query->max_num_pages;

  if(empty($pages)){
    $pages = 1;
  }

  if(empty($paged)){
    $paged = 1;
  }

  if($pages != 1){

    $output = '<ul class="pagination">';

    if($paged > 1){
      $output .= '<li><a class="prev" href="' . get_pagenum_link($paged-1) . '">prev</a></li>';
    }

    $output .= '';

    for($i = 1; $i <= $pages; $i++){

      if($i == $paged){
        $output .= '<li><span class="is-current">' . $i . '</span></li>';
      }else{
        $output .= '<li><a href="' . get_pagenum_link($i) . '">' . $i . '</a><li>';
      }

    }

    $output .= '';

    if($paged < $pages){
      $output .= '<li><a class="next" href="' . get_pagenum_link($paged+1) . '">next</a></li>';
    }

    $output .= '</ul>';

  }

  return $output;

}
```

```php:functions.php
/**
 * ページネーション（ページ番号の個数を指定して表示する場合）
 */
function get_pagination($pages = null){

  global $wp_query, $paged;

  $output = '';

  // 全体のページ数
  $pages = $wp_query->max_num_pages;

  // ページ番号のリストの両端（最初と最後）にいくつの数字を表示するか
  $end_size = 1;

  // 現在のページの両側にいくつの数字を表示するか。ただし現在のページは含みません。
  $mid_size = 1;

  // 省略フラグ
  $dots = false;

  if(empty($pages)){
    $pages = 1;
  }

  if(empty($paged)){
    $paged = 1;
  }

  if($pages != 1){

    // 1ページ目のみ「mid_size」を変更
    if($paged == 1){
      $mid_size = 3;
    }

    $output = '<ul class="pagination">' . PHP_EOL;

    if($paged > 1){
      $output .= '<li><a class="prev" href="' . get_pagenum_link($paged-1) . '">prev</a></li>';
    }

    $output .= '';

    for($i = 1; $i <= $pages; $i++){

      if($i == $paged){

        // 出力
        $output .= '<li><span class="is-current">' . $i . '</span></li>';

        // 省略フラグ
        $dots = true;

      }else{

        if($i <= $end_size || ($paged && $i >= $paged - $mid_size && $i <= $paged + $mid_size) || $i > $pages - $end_size){

          // 出力
          $output .= '<li><a href="' . get_pagenum_link($i) . '">' . $i . '</a></li>';

          // 省略フラグ
          $dots = true;

        }elseif($dots){

          // 出力
          $output .= '<li><span>...</span></li>';

          // 省略フラグ
          $dots = false;

        }

      }

    }

    $output .= '';

    if($paged < $pages){
      $output .= '<li><a class="next" href="' . get_pagenum_link($paged+1) . '">next</a></li>';
    }

    $output .= '</ul>';

  }

  return $output;

}
```

```php:テンプレート
<?php if(have_posts()): ?>
<?php while(have_posts()): the_post(); ?>
表示コンテンツ
<?php endwhile; ?>
<?php echo get_pagination(); ?>
<?php endif; ?>
```
ubuntu/linuxコマンド（自分用memo）

##主なコマンド
|コマンド|内容|
|---|---|
|apt-get ~~|~~はpackage名(sudoが必要)|
|mkdir ~~|~~という名前のディレクトリ作成|
|rm -r ~~|~~というファイルORディレクトリ削除|
|cd ~~| ~~に移動（tabキーである程度入力してあると予測判定して入力してくれる）|
|ls |今いる場所のファイルORディレクトリリスト|
|sudo -i | rootユーザーになる荒技(使わない方がいいらしい)|
|sudo ~~|~~にコマンドを入れるとroot権限で実行してくれる|
|dpkg -l |apt-getでinstallしたものがリストで観れる|
|pwd|今いる場所のパスを表示|
|unzip ~~|~~にzipファイルを入れると解凍してくれる|
|apt-get update|毎回打っとくおまじないコマンド（パッケージの更新）|
System.Data.SqlClient.SqlConnection のnewでハングする

## 現象
System.Data.SqlClient.SqlConnection のnewでハングする。
同じソースでも別の環境では正常動作する。ソースには問題なし。
環境依存か？

## 原因

WindowsのPerformance Counterが破損している場合に発生する。
".NET Data Provider for SqlServer"をPerformance Counterが読み込んでいるとハングする。

## 対策

".NET Data Provider for SqlServer"をPerformance Counterが読み込みを解除する。
```
unlodctr ".NET Data Provider for SqlServer"
```



## 参照元

https://stackoverflow.com/questions/8408236/calling-new-sqlconnection-hangs-program
パラメータと軌跡（数学II）その３

## 数学の軌跡を求める問題
十分性の考察です。

### 問題

実数のパラメータ$t$によって，次のように定まる$x$，$y$を座標とする点Pの軌跡を求めます。
$$x=\frac{t}{1+t^2}\cdots\text{①},\quad y=\frac{1}{1+t^2}\cdots\text{②}$$


### 十分性の考察

$$ \therefore x^2+\left(y-\frac12\right)^2=\frac14\cdots\text{③}$$

$$\text{③}\Rightarrow \text{①}\wedge \text{②}$$
が示せるのかを考えてみます。

③を満たす$x$，$y$を

$$x=\frac{\sin\theta}2,\quad y=\frac{1+\cos\theta}2$$
とおきます。$\theta$の範囲は$-\pi<\theta\leqq\pi$としておきます。
このように，$\theta$を考えれば，円周上のすべての点をもれなく表すことができます。
すべての$\theta$について
$$\frac{t}{1+t^2}=\frac{\sin\theta}2,\quad y=\frac{1}{1+t^2}=\frac{1+\cos\theta}2$$
を満たす実数$t$が存在するでしょうか？存在すれば，

$$\text{③}\Rightarrow \text{①}\wedge \text{②}$$

が示せたことになります。
まず，$1+\cos\theta\neq0$，すなわち，$\theta\neq\pi$として，

```math
\begin{aligned}[t]
 t&=\frac{\frac{\sin\theta}2}{\frac{1+\cos\theta}2}\\
&=\frac{\sin\theta}{1+\cos\theta}\\
&=\frac{2\sin\frac{\theta}2\cos\frac{\theta}2}{2\cos^2\frac{\theta}2}\\
&=\frac{\sin\frac{\theta}2}{\cos\frac{\theta}2}\\
&=\tan\frac{\theta}2
\end{aligned}
```

$t=\tan\frac{\theta}2$となります。

<img width="1535" alt="スクリーンショット 2019-05-30 17.11.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426542/2b0b3df3-2ff8-64af-c224-a69ed279cf6a.png">


$-\pi<\theta<\pi$であるすべての$\theta$について，実数$t$が存在することになります。
また，$\theta=\pi$となる$t$は存在しないので$(0,\,0)$は軌跡上の点ではないので除きます。


求める軌跡は
$$\text{中心}\displaystyle{\left(0,\,\frac12\right)}\text{，半径}\displaystyle{\frac12}\text{の円。ただし，}(0,\,0)を除く$$
となります。


色々書きましたが，結局，パラメータである$t$を変化させて，グラフ上の点を追跡するのがいいのかなと思っています。
Catapultのトランザクションを解剖しよう！

今回は送信に成功したトランザクションの中身を解剖していきます。

まずは、Catapult Transaction Viewer を作成したのでそちらをご覧ください。
http://xembook.net/xembook-sdk/snapshot/20190526/examples/270_transaction.html?hash=047DE1D1BD9B67FE8C5910CA75457723FAD7DB1B565D854F49FCE5513E9A0DFD

この内容はCatapult APIの /transaction/{hash}の出力を必要な項目についてはコンバートをかけて見やすくしたものです。
生データはこちら（ノードの調子により接続できない場合があります。）
http://40.90.163.184:3000/transaction/047DE1D1BD9B67FE8C5910CA75457723FAD7DB1B565D854F49FCE5513E9A0DFD



###meta

```
height
	456616,0
compact(height)
	456616
hash
	047DE1D1BD9B67FE8C5910CA75457723FAD7DB1B565D854F49FCE5513E9A0DFD
id
	5CEF883528174C00014328AA
index
	0
merkleComponentHash
	047DE1D1BD9B67FE8C5910CA75457723FAD7DB1B565D854F49FCE5513E9A0DFD
```

カッコつきの値はViewer側でコンバートをかけたものが表示されておりAPIのレスポンスには含まれません。

height : 何番目のブロックに刻まれたかです。uint64で指定
compact(height): uint64 を 計算して普通の10進数で表記します。
hash：このトランザクションのハッシュ値です。
id：このノードが管理するトランザクションの管理IDです。アクセスするノードが変わればこのid値も異なるためあまり使用しません。
index：なんの値でしょうかね？
merkleComponentHash:こちらも勉強不足でまだわかりません。

###transaction

```
deadline
	952376648,23
Date(deadline)
	2019-05-30 17:37:04
maxFee
	0,0
compact(maxFee)
	0
message type
	0
message payload
	48656C6C6F212058454D426F6F6B2D73646B
hexToUtf8(message payload)
	Hello! XEMBook-sdk
recipient
	90E332F8DAE05D06D1B5247BC9AAF848CB4EB602B02B860979
base32.encode(recipient)
	SDRTF6G24BOQNUNVER54TKXYJDFU5NQCWAVYMCLZ
signature
	51A480353E63596294835A0ACD26CE5B5F173CEE6ED5877FC1C34557E2D1755EBB3FC43EEDC0F49DCD7FE281E1A19C6D523CB7587F306FE61A2E54E31131640A
signer
	C695653F97C566574A181C135AE8FDD52B9386D094377B6F46882D78DE527EAB
publicKeyToAddress(signer,0x90)
	SDRTF6G24BOQNUNVER54TKXYJDFU5NQCWAVYMCLZ
type
	16724
type.toString(16)
	0x4154
version
	36867
```

deadline:トランザクションの有効期限です。uint64型
Date(deadline)：2016-04-01 00:00 から deadline のミリ秒数だけ経過した時間を西暦表示しています。
maxFee：手数料のことかと思われます。uint64型
compact(maxFee)：手数料を10進数数値で表示しています。
message type：0が平文メッセージ、1が暗号化メッセージです。
message payload：メッセージをHEX変換したものです。
hexToUtf8(message payload)：HEX変換されたメッセージをutf-8に変換したものです。
recipient：受け取りアドレスをデコードしたものです。
base32.encode(recipient)：受け取りアドレスをbase32でエンコードしたものです。MIJIN_TESTはSから始まります。
signature：トランザクションを署名したときのハッシュ値です。
signer：署名者の公開鍵です。
publicKeyToAddress(signer,0x90)：署名者のエンコードアドレスです。
type：使用するトランザクションタイプ？です。
version：使用するトランザクションのバージョン？です。

###mosaics

```
id
	[853116887,2007078553]
toHex(id)
	77A1969932D987D7
amount
	0,0
campact(amount)
	0
```
id：mosaicを一意に識別するidです。uint64型
toHex(id):10進数で表記するととても長くなるので、16進数のHEX値で表記します。
amount:送信するmosaic量です。uint64型
compact(amount)：10進数表記です。





大体こんな内容になりました。
次回からはいろいろなトランザクションを発行していきたいと思います！

###関連記事
1. [Catapultアカウントを作ろう！](https://qiita.com/nem_takanobu/items/7bb0a3f472b8c7c41868)
2. [Catapultのトラザクションを送信しよう！](https://qiita.com/nem_takanobu/items/ed96c41ce0fb4e4058bd)
3. [Catapultのトランザクションを解剖しよう！](https://qiita.com/nem_takanobu/items/2892f994b17630edcdff)
Photon VoiceでMicrophone Deviceの抜き差しに対応する方法

# ソースコードを読む
Photon Voiceでマイクの抜き差し時にデバイスの更新がかからなかったので、いろいろ調べたけどどこにも書いておらず、最終的にソースコード読むことで解決しました。

``` CSharp
//マイクデバイスのリフレッシュ
PhotonVoiceNetwork.PhotonMicrophoneEnumerator.Refresh();
```
Docker で Gentoo コンテナを起動する

普段は macOS を使っていますが, Gentoo を使いたくなるときがちょいちょいあります.
漢なら stage1 からでしょ？とかとか突っ込まれそうですが, Gentoo is 選択 ということでこれはこれで.

# 1. Dockerfile を作る

```:Dockerfile
FROM gentoo/portage:latest as portage

FROM gentoo/stage3-amd64:latest

COPY --from=portage /usr/portage /usr/portage

# make.conf
RUN echo "USE=\"\${USE} -X\"" >> /etc/portage/make.conf && \
    echo "GENTOO_MIRRORS=\"rsync://rsync.jp.gentoo.org/gentoo-portage/ \${GENTOO_MIRRORS}\"" >> /etc/portage/make.conf

# timezone
RUN echo 'Asia/Tokyo' > /etc/timezone && emerge --config timezone-data
```

make.conf に MAKEOPTS, EMERGE_DEFAULT_OPTS, FEATURES を追加してもよいでしょう. USE フラグの取捨選択はお好みで.

# 2. コンテナを起動する

```bash:
$ docker build . -t gentoo && docker run --rm -it --name gentoo -d gentoo && docker exec -it gentoo /bin/bash
# ...
f6a4d3c38040 / #
```

ちな, rm オプションつけてるんで, $ docker stop gentoo をしない限り exit で抜けてもデータは残ってるよ.
全シートのカーソルをA1に移動するマクロ

#はじめに
毎回、新しい現場に行くたびにこのマクロ検索してカスタマイズして作ってるなぁと思い、
もう二度と書くのやめようとここに残すことにした。

#参考サイト
[全シートの選択セルをA1に設定する](https://vbabeginner.net/%E5%85%A8%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AE%E9%81%B8%E6%8A%9E%E3%82%BB%E3%83%AB%E3%82%92a1%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B/)
[VBA応用(シートの表示位置を左上に戻す。)](http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_040.html)

#ソース

```VBScript
Sub 全ページをA1にEx()
    Dim sht                     As Worksheet            '// 処理中のワークシート
    Dim shtVisible                                      '// 表示可能なワークシート
    Dim iRow, iCol                                      '// 縦、横座標
    Dim sHiddenSheet                                    '// 非表示シート名
    Dim oFilterStatus           As AutoFilter           '// オートフィルタ状態
    Dim oRangeFilter            As Range                '// オートフィルタ設定
    
    For Each sht In Worksheets
        If (IsEmpty(shtVisible) = True) And (sht.Visible = xlSheetVisible) Then
            Set shtVisible = sht
        End If
        
        '// シートが表示されている場合
        If sht.Visible = xlSheetVisible Then
            Call A1(sht)
        '// シートが非表示の場合
        Else
            sHiddenSheet = sHiddenSheet & "、" & sht.Name
            sht.Visible = xlSheetVisible
            Call A1(sht)
            sht.Visible = xlSheetHidden
        End If
    Next
    
    shtVisible.Select
    
    If (sHiddenSheet <> "") Then
        MsgBox sHiddenSheet, vbOKOnly, "非表示シートあり"
    End If
End Sub

Sub A1(ByVal sht As Worksheet)
        sht.Select
        
        '// ウインドウ枠の固定がされている場合
        If ActiveWindow.FreezePanes = True Then
            iRow = ActiveWindow.SplitRow + 1
            iCol = ActiveWindow.SplitColumn + 1
            Cells(iRow + 1, iCol + 1).Activate
        End If
        
        Set oFilterStatus = sht.AutoFilter
        '// オートフィルタが設定されている場合
        If Not oFilterStatus Is Nothing Then
            '// フィルタが掛かっている場合
            If oFilterStatus.FilterMode = True Then
                '// フィルタが掛かっている行の先頭を選択
                Set oRangeFilter = Range("A1").CurrentRegion
                Set oRangeFilter = Application.Intersect(oRangeFilter, oRangeFilter.Offset(1, 0))
                Set oRangeFilter = oRangeFilter.SpecialCells(xlCellTypeVisible)
                Range("A" & CStr(oRangeFilter.Row)).Select
            End If
        End If
        
        sht.Range("A1").Select
        ActiveWindow.Zoom = 100
        
        ActiveCell.Activate         ' Excel97対策
        ' スクロール列の設定
        ActiveWindow.ScrollColumn = 1
        ' スクロール行の設定
        ActiveWindow.ScrollRow = 1

End Sub
```

#おわりに
非表示のシートもA1に動かしたかったとか、
拡大率100%にしたかったとかそんなところ。
スクロールバーの位置も初期化したかったとか。

これから指定したフォルダの全ブックにこれを適用するマクロでも作る。
こんなことを人海戦術でやってる現場がまだまだあるんだぜ。

#謝辞
@nukie_53 さん
ご指摘ありがとうございました。
AtCoder problems メモ

## ただひたすらにAtCoderのCを解く

### ABC100 C.*3 or /2
*3をしても/2ができる回数に関係ない

```python
N = int(input())
A = [int(i) for i in input().split()]

ans = 0
for i in A:
    while True:
        if i%2 == 0:
            ans += 1
            i /= 2
        else:
            break

print(ans)
```

### ABC101 C.Minimization
何回かやってると(N-1)/(K-1)を繰り上げした回数が答え、実際に試すのが大事

```python
import math

N,K = [int(i) for i in input().split()]
A = [int(i) for i in input().split()]

print(math.ceil((N-1)/(K-1)))
```

### ABC102 C.Linear Approxiamation
http://www5e.biglobe.ne.jp/~emm386/2016/distance/manhattan02.html
上記のサイトによれば、絶対和誤差を最小にするのは$b$が配列$A$の中央値の時らしい

```python
import numpy as np

N = int(input())
A = [int(i)-j-1 for j,i in enumerate(input().split())]

ans = 0
b = np.median(A)
for i in A:
    ans += abs(i-b)

print(int(ans))

```

### ABC103 C.Modulo Summation
全ての$a$をかけて$-1$すると全て$a_{i}-1$が割ったあまりになる

```python
N = int(input())
A = [int(i)-1 for i in input().split()]

print(sum(A))
```

### ABC104 C.All Green
解説AC
コンプする問題をbit全探索で定め、コンプした際の点数を足し目標点数より低いものを選ぶ。
その後、貪欲法で足りない点数を補っていき最小回数を出力すれば答え。

```python
from itertools import permutations

D,G = [int(i) for i in input().split()]
L = [[int(i) for i in input().split()] for _ in range(D)]

ans = []
for i in range(2**D):
    tmp = 0
    index = 0
    index_li = []
    ans_tmp = 0
    for j in range(D):
        if (i >> j) & 1:
            tmp += L[j][0]*100*(j+1)+L[j][1]
            ans_tmp += L[j][0]
        else:
            index_li.append(j+1)
    if G >= tmp:
        for index in index_li[::-1]:
            p = 0
            while G > tmp:
                if p > L[index-1][0]:
                    break
                p += 1
                ans_tmp += 1
                tmp += index*100

    ans.append(ans_tmp)

print(min(ans))
```

## ABC105 C.Base -2 Number
-2進数の問題、基本的には2進数と同じだがNを更新するときに注意が必要

```python
N = int(input())

ans = 0
base = 1
N = -N
while N != 0:
    p = abs(N%(-2))
    N = (N+p)//(-2)
    ans += p*base
    base *= 10
    
print(ans)
```

### ABC106 C.To Infinity
2の5000兆乗はKの上限を余裕で超えるので出力されるのは1 or Sの2文字目しかない。
コーナーケースにしっかり注意しよう！(戒め）

```python
S = input()
K = int(input())

if K == 1:
    print(S[0])
    exit()
else:
    for i in range(K):
        if S[i] != '1':
            print(S[i])
            exit()
print(1)
```

### ABC107 C. Candles
連続するK個取り出した際に、かかる時間の求め方は結局3通りなので全探索

```python
N,K = [int(i) for i in input().split()]
X = [int(i) for i in input().split()]

ans = 10**9
for i in range(N-K+1):
    l = X[i]
    r = X[i+K-1]
    if l < 0 and r <= 0:
        tmp = -l
    elif l >= 0 and r > 0:
        tmp = r
    else:
        tmp = min(abs(l),r)*2 + max(abs(l),r)
    ans = min(ans,tmp)
print(ans)
```

### ABC109 C. Skip
リストにXを追加し各要素ごとの距離の最大公約数をだせば答え

```python
N,X = [int(i) for i in input().split()]
L = [int(i) for i in input().split()]

if N == 1:
    print(abs(L[0]-X))
else:
    P = [0]*N
    P[0] = abs(min(L) - X)
    for i in range(1,N):
        P[i] = abs(L[i]-L[i-1])

    def gcd( x, y ):
        while y != 0:
            x, y = y, x%y
        return x

    ans = gcd(P[0],P[1])

    for i in range(2,N):
        ans = gcd(ans,P[i])

    print(ans)
```
Vue Routerのreload実装する

Vue Routerにはreload機能がないため、自作スクリプト

```javascript

methods: {
    reload() {
        this.$router.go({path: this.$router.currentRoute.path, force: true});
    },
    something() {
        // reloadを呼び出すことで画面リロード
        this.reload();
    }
}
```
WordPressを使ったサイト制作標準フロー

:::note warn
こちらの記事は5年以上前の内容で特に開発環境構築まわりは、昨今の事情にあわないものとなりました。
2024年時点の考えを下記にまとめなおしましたので、こちらを御覧ください。
[WordPress標準制作フロー2024](https://qiita.com/koji-yamauchi/items/6a72ca8c2550f3433ce4)
:::

-----

WordPressを使ったサイト制作案件が多く手がけるようになって、この1年だけで10サイト以上WordPress案件に携わってきました。
色々と試行錯誤しながらやってきたなかで、ある程度WordPressをつかったサイト制作のフローが標準化してきたのでまとめていきたいと思います。

# 前提事項

* Web制作会社などでいちからサイトを制作することを想定  
  （汎用テーマなどを使って簡易に構築するとかではなく、ガッツリとそのサイト専用のテーマを作成する）
* それぞれのツールのインストール方法などは記載しない  
  （Qiita内で丁寧に手順を記載している記事があるので検索してみてください）

# Web制作にWordPressを導入した際の課題

1. 環境構築が手間。
1. 新規テーマ作成時の初期テンプレートの準備が大変。
1. サイトの引っ越しが生じる都度、DBの書き換えが必要となる。
1. 各操作がWeb画面のGUIベースで作業を自動化やコード化しにくい

# 対応策

## 1. 環境構築が手間。

### VCCWで環境構築の手間を解決する

LAMP環境をホストOSに構築したり、VirtualBoxでゲストOSに構築したりしてWordPressをインストールしている時期もありましたが、[VCCW]( http://vccw.cc/)の存在を知ってからはWordPress案件はすべてVCCWを使用しています。

VCCWを使えばコマンドひとつでWordPress開発環境をVagrant上に構築可能。
PHP_CodeSnifferやWP-CLI、WordMoveなどの便利なWordPress関連ツールもついてきて非常に便利です。

## 2. 新規テーマ作成時の初期テンプレートの準備が大変。

### Iemotoで骨組みとなるテーマファイルを一括生成

WordPressのオリジナルテーマをつくる際は、既存のデフォルトテーマを元にコピーして作成する方法などもありますが、コード内の名前を置換したり不要な記述を削除するが手間です。

[Iemoto](https://github.com/megumiteam/iemoto)を使用するといくつかの質問に答えるだけで、WordPressの基本的なテーマファイル構成とSassのコンパイルなどを行なうタスクランナーの設定まで自動でやってくれます。
（後述する、WP-CLIでもテーマの雛形を作成できますが、タスクランナーがついている分、Iemotoのほうが便利です。）

`Use gulp? (y/N)` は `y` でGruntではなく、Gulpのほうが動作が早いのでオススメ。
タスクランナーの実行はゲストOS側でも良いですが、ホストOSから実行したほうが楽だし早いので私はホスト側から実行しています。

## 3. サイトの引っ越しが生じる都度、DBの書き換えが必要となる。

### WordMoveでデプロイや他環境との同期を効率化

WordPressはパスをすべて絶対パスで記述するような方針のため、ローカルの内容をテスト環境へアップしたり、テスト環境の内容を本番に反映したりする際にDB書き換えが必要となり非常に手間です。

以前は自分でドメイン部分を変換して適用するようなコマンドラインツールを作成していましたが、やはり自分が困っていることは他の人も困っていて、すでに WordMoveという一般的な解決策がありました。

WordMoveを使えば、簡単にプラグイン、テーマ、DB、メディアなどを指定しそれぞれの環境と同期することが可能です。


####  よくあるケース

##### 途中で参加したプロジェクトメンバーがステージング環境のデータを開発環境に同期する。

```
wordmove pull -e staging -t -d -u -p
```

DBやメディア（アップロード画像）はGitなどで管理しないことが多いと思いますが、VCCWの設定ファイルなどをGitで管理している場合、新しくプロジェクトに参加する人はリポジトリをクローンした後はVagarntを立ち上げて、WordMoveで上記のようにステージングのデータを取ってくるだけですぐに作業を開始できます。

##### 本番環境に修正したテーマを適用する。

```
wordmove push -e production -t
```

テーマファイルの修正をステージングにアップ後に本番環境へ反映するには上記のようにコマンドひとつで簡単に実行できます。

## 4. 各操作がWeb画面のGUIベースで作業を自動化やコード化しにくい

### WP-CLIで作業をショートカット、シェルスクリプト化など

WP-CLIを使うとWordPressに関わる様々な作業がコマンドラインから簡単に行えます。
コマンドラインから行えるということは社内wikiで手順を共有しやすく、シェルスクリプト化も容易です。

よく使うコマンド例:

```
# WordPressのアップデート
wp core update
# プラグインをインストールして有効化
wp plugin install classic-editor --activate
# DBバックアップ
wp db export ~/backup.sql
# DBをリセットしてからインポート
wp db reset && wp db import ~/backup.sql
```

* コマンド一覧  
  https://developer.wordpress.org/cli/commands/

パーミッションや設定の問題で管理画面からプラグイン追加や更新が出来ない場合でも、SSHでサーバー接続可能な場合はWP-CLIから対応できますし、ログインアカウントが不明な場合もWP-CLIからアカウントを追加することが出来ます。

カテゴリ情報や固定ページなど初期データが大量にある場合もWP-CLIをつかったシェルスクリプトで一括で登録できるようにすると便利です。

# まとめ

* WordPressを使ったサイト制作ではまずはVCCWを使う
* テーマ作成はコピーではなく、Iemotoをつかって生成するのが吉
* 各環境間のデータ連携はWordMoveを使う
* 必要な作業はコマンドライン（WP-CLI）から行えないか検討する
Rancherコンテナー管理プラットフォームのノードテンプレート（AWS）の設定手順

# ノードテンプレートの設定手順
・右上の「User Preferences」のアイコンをクリックして、「Node Templates」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256080/e81bd813-6c6d-c8c0-b141-c0ce3e43cdbf.png)
・開く「Node Templates」画面に、右上の「Add Template」ボタンをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256080/09c6036a-b010-7800-8fd4-2070d7191ca4.png)
・開く「Add Node Templates」画面に、下記の画面のように情報を入力して、「Create」ボタンをクリックします
参照：[awsのAccess key とSecret Keyの作成／取得方法](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey)で検証用のIAMユーザーから取得してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256080/5a2427ef-0381-6519-904c-1a44e68b0314.png)
・次の画面に、クラスターノードを作成する場所のAZとVPCを選択して、「Next:...」ボタンをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256080/25221234-9111-6a7d-3bcc-1bde0b2e20a6.png)
・次の画面に、「Security Groups」にStandardを選択して、「Next:...」ボタンをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256080/f7b4175f-c176-6f9a-ae45-dc7f0bc864b9.png)
・次の画面に、下記の画面のように情報を入力して、「Create」ボタンをクリックします
「IAM Instance Profile Name」について、AWSのCloud Provider機能（AWSのロードバランサによるK8sサービス作成や、AWS EBSによる永続化Volume作成）を使用する場合のみ、設定が必要です。初心者レベルのハンズオンの場合は不要です。
参照：[IAM Instance Profile Nameの作成／取得方法](https://rancher.com/docs/rancher/v2.x/en/cluster-provisioning/rke-clusters/node-pools/ec2/#)で取得してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256080/08fb806d-46e3-fb69-34d2-d66273b2e58d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256080/6185b436-48c0-a63a-81ff-60d720bd2c90.png)
AWS RDS for Oracleでメンテナンスウインドウの開始時刻を変更する

※ここでの「メンテナンスウインドウ」とは、RDSの機能としてのメンテナンスウインドウではなく、Oracle Databaseとしてのメンテナンスウインドウを指しています。

RDS for OracleのスケジューラーはEST5EDT（米国東部標準時）であるため、設定された時刻の13時間遅れでメンテナンスタスク（統計情報収集等）が動作します。

このため、スケジューラーのタイムゾーンの変更手順について、以下に記載します。あわせて、メンテナンスタスク（メンテナンスウインドウ）のスケジュール変更手順も記載します。

## １．スケジューラーのタイムゾーンを変更する

### デフォルトタイムゾーンの変更
```
exec DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('default_timezone','Asia/Tokyo');
```

### 変更後の結果確認
```
SELECT * FROM dba_autotask_window_clients;
```

なお、EST5EDTのメンテナンスウインドウが残っている場合は、次のSQLを実行します。

```
exec DBMS_SCHEDULER.DISABLE(name=>'SYS.<メンテナンスウインドウ名>');
exec DBMS_SCHEDULER.ENABLE(name=>'SYS.<メンテナンスウインドウ名>');
```

## ２．メンテナンウインドウのスケジュールを変更する

### 現在の設定値を確認
```
SELECT * FROM dba_scheduler_windows;
```

### スケジュールを変更
```
exec DBMS_SCHEDULER.DISABLE(name => 'SYS.<メンテナンスウインドウ名>');
exec DBMS_SCHEDULER.SET_ATTRIBUTE(name => 'SYS.<メンテナンスウインドウ名>', attribute => 'REPEAT_INTERVAL', value => 'freq=<実行間隔(daily等)>; byday=<曜日(WED等)>; byhour=<時(24h表記)>; byminute=<分>; bysecond=<秒>');
exec DBMS_SCHEDULER.ENABLE(name => 'SYS.<メンテナンスウインドウ名>');
```

### 変更後の設定値を確認

```
SELECT * FROM dba_scheduler_windows;
```

## 参考

- https://www.ydc.co.jp/solution/standby/article/oracle_8.html
- https://docs.oracle.com/cd/E57425_01/121/ADMIN/tasks.htm
joolでnat64作ろうとしたらエラーが起きた

ubuntu16.04使ってjoolをつかってnat64を作ろうとしたらエラーが起きた

```
configure: error: in `/root/jool-4.0.1':
configure: error: The pkg-config script could not be found or is too old.  Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.

Alternatively, you may set the environment variables LIBNLGENL3_CFLAGS
and LIBNLGENL3_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
```

下記実行したら治った

```
apt-get install pkg-config
```
【PHP】PHPからApacheのバージョンを取得する

PHP から Apache のバージョンを取得する方法についての記事です。

--------------------------------------------------------------------------------

## コード

```php
function apacheVersion($pShell = null)
{
    //-- Apacheのバージョンを取得するためのコマンド
    $shell = (isset($pShell)) ? $pShell
                              : 'apachectl -v';

    //-- Apacheのバージョンを取得するための正規表現
    $regex = '/Apache\/(\d{1,2}\.\d{1,2}\.\d{1,2})/';

    switch(true) {
        //-- 1.環境変数からの取得を試みる
        case (preg_match($regex, getenv('SERVER_SOFTWARE'), $matchAry)):

        //-- 2.apache_get_version()での取得を試みる
        case (function_exists('apache_get_version') && preg_match($regex, apache_get_version(), $matchAry)):

        //-- 3.コマンドでの取得を試みる
        case (preg_match($regex, shell_exec($shell), $matchAry)):
            return $matchAry[1];

        //-- バージョン取得失敗
        default:
            return false;
    }
}
```

--------------------------------------------------------------------------------

## 使い方

```php
$version = apacheVersion();    // string(6) "2.4.39"

//-- Apacheをソースからビルドした環境やWindows環境等で
//-- Apacheのバージョンを取得するコマンドを指定したい時
apacheVersion('C:\apache\bin\httpd.exe -v');
```

--------------------------------------------------------------------------------

## なぜ三段構えになっているか

### 1.環境変数からの取得を試みる

この方法では、例えば PHP を CLI 版で動作させている時は取得できません。('SERVER_SOFTWARE' は定義されません。)

また、この方法で取得できるのは、Apache の `ServerTokens` の設定が、`Full` `OS` `Minimal` の時のみです。

公開環境では `Prod` を設定し、HTTP ヘッダに Apache のバージョンが公開されないようにするのが普通です。

```apache
ServerTokens Prod
```

この設定の場合、`getenv('SERVER_SOFTWARE')` には `'Apache'` という文字列しか入りませんので、バージョンを取得する事はできません。


### 2.apache_get_version()での取得を試みる

この関数で取得できる値は、基本的に 1 と同じです。

つまり、あまり実用性のない関数だというのが個人的な認識ですが、1 で失敗しても 2 で成功するケースがあるのかもしれないので、念の為に書いています。

### 3.コマンドでの取得を試みる

…というわけで、最終手段として Apache に直接聞いちゃえ！って事です。
CentOS7+RabbitMQインストール手順

```
yum install epel-release -y
yum update -y
yum install erlang -y
yum info erlang
rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc
yum install wget -y
wget https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.6.14/rabbitmq-server-3.6.14-1.el7.noarch.rpm
yum install rabbitmq-server-3.6.14-1.el7.noarch.rpm -y
systemctl enable rabbitmq-server.service
systemctl start rabbitmq-server
systemctl status rabbitmq-server
rabbitmq-plugins enable rabbitmq_management
firewall-cmd  --permanent --add-port=15672/tcp
firewall-cmd  --permanent --add-port=80/tcp
firewall-cmd  --permanent --add-port=443/tcp
firewall-cmd --reload
rabbitmqctl add_user admin 任意のパスワード
rabbitmqctl set_user_tags admin administrator
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
http://xxx.xxx.xxx.xxx:15672/  adminでログインできればOK。
```


引き続き、PHPからキューを使えるようにする。


PHPが入っていなければ下記で入れる。

```
yum -y install vim-enhanced
yum update -y
yum install epel-release.noarch -y
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum install httpd -y
systemctl start httpd.service
systemctl enable httpd.service
yum --enablerepo=epel install libmcrypt -y
yum --enablerepo=remi-php71 install -y php php-cli php-devel php-common php-mbstring php-mysql php-fpm php-gd php-mcrypt php-opcache php-pdo php-xml php-intl php-zip php-pear php-bcmath
```


### php-amqplib

```
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
yum install ansible -y
ansible --version
yum install git -y
composer require php-amqplib/php-amqplib 
```


### 送信処理 sender.php

```php
<?php
require_once __DIR__ . '/../vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;


$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->queue_declare('hello', false, false, false, false);

$msg = new AMQPMessage('Hello World!');
$channel->basic_publish($msg, '', 'hello');

echo " [x] Sent 'Hello World!'\n";

$channel->close();
$connection->close();
```




### 受信処理 receiver.php

```php
<?php
require_once __DIR__ . '/../vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;


$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->queue_declare('hello', false, false, false, false);

echo ' [*] Waiting for messages. To exit press CTRL+C', "\n";

$callback = function($msg) {
    echo " [x] Received ", $msg->body, "\n";
};

$channel->basic_consume('hello', '', false, true, false, false, $callback);

while(count($channel->callbacks)) {
    $channel->wait();
}
```
（オサーンの備忘録2019）iOSのプロジェクトのlinkerエラーでやった事まとめ

#podのリンカーエラーででやった事まとめ  

**エラー内容**

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

1. 当たり前だけど、「xxxx.xcworkspace」で開く
2. 念の為　キレイキレイのコマンド　pod install --repo-update
3. 自分の環境では

```
The `プロジェクト名[Release]` target overrides the `OTHER_LDFLAGS` build setting defined in `Pods/Target Support Files/Pods-プロジェクト名/Pods-プロジェクト名.release.xcconfig'. This can lead to problems with the CocoaPods installation
```
が出てたので、OTHER_LDFLAGSに$(inherited)追加
4. Build Active Architecture Onlyを**pods**と**project**で合わせる。**（これ大事）**
で、ビルドが通りました。


それとprovisioningでエラーになっていたので。
PROVISIONING_PROFILEを削除しました。
自分型アノテーションについて、いい加減理解する

###※追記：この記事は、「なぜミックスインではなく、自分型アノテーションを使うのか」という点など、本質的な部分を捉えられていない気がしてきました。学習が進み次第追記していきます。



自分型アノテーションとは、

<font color="Red"> 「私は、この型と一緒にじゃないと呼び出されませんよ！」</font>

という宣言のこと。

トレイトやクラスのなかで、

```
self: <クラス名 or トレイト名> =>
```

と記述することで、インスタンス化する際にwith をつけてその指定したクラスorトレイトを一緒に呼ばないとエラーが起きるようになる。

そして、そのトレイトやクラスの定義内部でのみ、指定したオブジェクトのメンバーを使用できる。

```scala

trait Greeter {
  def greet() = println("Hello!")
}

class Robot {
  self: Greeter =>
  
  def start() = {
    greet()
    println("Robot's")
  }
}
```

trait Robotは、「私はナイスなロボットなので、Hello!と挨拶する特性とセットじゃないと呼んでも来ませんからね！」
と宣言している。

コンソールで実行してみる。

```
scala> val robot = new Robot()
<console>:11: error: class Robot cannot be instantiated because it does not conform to its self-type Robot with Greeter
       val robot = new Robot()
                   ^

scala>  
```
まずは失敗例。
「Robotの宣言している自分型"Robot with Greeter"と、あなたが試そうとした単なる"Robot"は、型が一致しませんよ」
というエラー。
やはりロボットはあいさつするという能力と一緒じゃないとどうしても出てこない。

```
scala> val robot = new Robot with Greeter
robot: Robot with Greeter = $anon$1@7c46c9c3

scala> robot.start()
Hello!
Robot's

scala> robot.greet()
Hello!

scala> 

```

これならOK。当然greet()も実行できる。
超超最低限のReactのコンパイル環境の構築手順


備忘録として残します。

npmは入ってる前提。

#■やり方

初期化コマンドでpackage.jsonを作成

```shell
#npm init でいくつか質問されるが面倒なので-yオプションでとりあえず全てYesで答えて自動作成
npm init -y
```
トランスパイラ（バベル）インストール

```shell
npm install --save-dev babel-cli
```
上記コマンド実行後、package.jsonの「devDependencies」に「babel-cli」が追加されていればトランスパイラのインストール完了

```package.json
{
  "name": "name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.26.0"
  }
}
```
React関係のプラグインをインストール

```shell
#babel-preset-react
#babel-preset-es2015
#babel-preset-stage-2
npm install --save-dev babel-preset-react babel-preset-es2015 babel-preset-stage-2
```

`babel-preset-react`、`babel-preset-es2015`、`babel-preset-stage-2`の３つのプラグインのインストールが完了

```package.json
{
  "name": "name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1"
  }
}
```
コンパイルするプリセットを「.babelrc」に登録する。
ちなみにwindowsで「.」始まりのファイル名にする場合は`.ファイル名.`でリネームできます。

```..babelrc
{
  "presets": ["react", "es2015","stage-2"]
}
```

あとちょっとで終わりです。
次にトランスパイル用のコマンドを用意。
今回は手動コンパイル用と、ファイルの更新を監視して自動コンパイルしてくれる用の２つ用意します。
後者はIDEでコーディング用です。
いちいちjsx編集→手動コンパイル→ブラウザで動作確認はさすがに面倒ですので。

```package.json
{
  "name": "name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",

  "scripts": {
    "build": "babel ビルド元フォルダパス -d ビルド先フォルダパス",
    "buildauto": "babel　-w ビルド元フォルダパス -d ビルド先フォルダパス"
  },

  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1"
  }
}
```
これで完了です。
後は下記コマンドを実行すればコンパイルできます。

```shell
#手動
npm run build
```
```shell
#自動
#ファイルの変更を監視して、自動コンパイルしてくれます。
#コーディング中はこれで。
npm run buildauto
```
当然ですがコンソールが開いている間だけ自動コンパイルしてくれます。



以上です。
【学習メモ】 クラウド型DNSサービスのNSに独自のドメインを使えるか

# はじめに
たとえば ```hoge.com ``` を取得してクラウド型DNSサービスを利用しようとすると、
通常ネームサーバー名はサービス名に近いドメインが入ったものになります。

ネームサーバーのA/AAAAレコードを使って、
```dns.hoge.com ```や```ns.hoge.com ```、または```ns.oyagaisha.jp```のような、
DNSサービスが提供するFQDN独自のドメインを使ったネームサーバーを使いたいこともあるかと思います。

提供されたNSではなく、提供されたNSと同一のA、AAAAレコードを、
自由なFQDNに割り当ててNSとして使うこと、です。

その使い方が大手DNSサービスで許可されているのか確認しました。
この記事は2019年5月30日時点のものです。


# 結果

知名度からするとRoute53一択ですね。

2019/6/19現在

|サービス名|呼び名|可否|
|:--:|:--:|:--:|
|[Route53(AWS)](https://aws.amazon.com/jp/route53/)|ホワイトラベルネームサーバー|[可](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/white-label-name-servers.html)|
|[Coud DNS(Google)](https://cloud.google.com/dns/)|ホワイトラベルネームサーバー?|[?(公式で言及なし)](https://cloud.google.com/dns/docs/migrating) <br>[(google forumでは不可の模様)](https://groups.google.com/forum/#!topic/cloud-dns-discuss/UjBRmEaDWAo)|
|[Azure DNS(Microsoft)](https://azure.microsoft.com/en-us/services/dns/)|バニティネームサーバー|[不可](https://docs.microsoft.com/ja-jp/azure/dns/dns-delegate-domain-azure-dns#delegate-the-domain)|
|[Fast DNS(Akamai)](https://www.akamai.com/us/en/resources/dns-security.jsp)|バニティネームサーバー?|[不可](https://community.akamai.com/customers/s/question/0D50f00005RtrDfCAJ/how-do-i-use-vanity-name-servers-with-fast-dns?language=ja)|
|[Dyn(Oracle)](https://dyn.com/)|バニティネームサーバー|[可](https://dyn.com/blog/what-are-vanity-nameservers-and-do-you-need-them/)|

Cloud DNSは公式マニュアルに記述がなく、フォーラムで機能要求した旨の投稿がある(2018年12月)ことから、サポートされていないと思われます。

Oracle Dynは、Oracle Dyn自身では可能とも不可能とも言っていませんが、一般的には可能で、方法も書いているので可としました。その後避けた方が良い理由を述べていて否定的な立場であるようです。


# おまけ
サービスごとに割り振られるNS。

|サービス名|NS|
|:--:|:--:|
|Route53|ns-xxx.awsdns-xx.com/.net/.org/.co.uk|
|Coud DNS|ns-cloud-xx.googledomains.com|
|Azure DNS|nsx-xx.azure-dns.com/net/org/info|
|Fast DNS|axx-xx.akam.net|
|Dyn|nsxx.dns.dyn.com|
An error occurred (AccessDenied) when calling the CopyObject operation とaction does not apply to any resource(s) in statement がでた時の対処法

## 事象
IAMユーザー単位で閲覧/保存制御をかけているS3バケットが本番用とstg用で２つあります。
日時で本番からstg用にsyncをかけるのですが、
`An error occurred (AccessDenied) when calling the CopyObject operation` のエラーが出ました。

## 対処
https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-troubleshoot-copy-between-buckets/
AWS公式をみてみると、ズバリ書いてありました。

必要なことは4つです。
1. コピー元バケット: 使用している IAM ユーザーまたはロールによって s3:ListBucket と s3:GetObject の両方を許可
2. コピー先バケット: IAM ユーザーまたはロールによって s3:ListBucket と s3:PutObject の両方を許可
3. IAM ユーザー: s3:ListBucket および s3:GetObject をコピー元バケットへ許可
4. IAM ユーザー:　s3:ListBucket と s3:PutObject をコピー先バケットへ許可

私の場合、IAMロールはs3への全権限が与えられていたので、バケットポリシーだけを見直しました。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "huge",
            "Effect": "Deny",
            "NotPrincipal": {
                "AWS": "hogehoge"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::hogebucket-production/*"
        }
    ]
}
```
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "huge",
            "Effect": "Deny",
            "NotPrincipal": {
                "AWS": "hogehoge"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::hogebucket-staging/*"
        }
    ]
}
```

なぜだかわからないですが、`s3:ListBucket`はなくてもあってもいけたので消しました。
ちなみに`s3:ListBucket`権限を付与するのにはまた罠があり、Resourceを指定する時に`/*`をつけてはいけません。
考えてみればバケット単位の権限なのでまあそうかという感じなのですが、普通にハマりました。
間違えると、`action does not apply to any resource(s) in statement `というエラーが出てバケットを保存できません。
下記のように書いてみてください。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::bucketname",
            ]
        }
    ]
}
```

## 実行
コピー元 コピー先の順で指定します。
フォルダ指定もできます。
`aws s3 sync s3://hogebucket-production/uploads/huga s3://hogebucket-staging/uploads/huga`

## 余談
バケットポリシーの書き方は初めは難しいですよね。
EffectとPrincipalの組み合わせとか。
"Version": "2012-10-17"　てなんやとか。
CSSのcounterで自動連番

自分用メモです

参考サイト
[counter-increment](https://developer.mozilla.org/ja/docs/Web/CSS/counter-increment)
[CSSのcounter-incrementを使って簡単に自動で連番をつける方法](https://www.genius-web.co.jp/blog/cat-101/counter-increment.html)
[自動で連番付与できるCSS。counter-incrementの使い方](https://liapoc.com/counter-increment.html)

#基本の記述

```CSS:CSS
ul li {
  counter-increment: title;
}
ul li h2::before {
  content: counter(title);
}
```

#数字が増えない場合

```CSS:CSS
body{counter-reset:title;}
```
Lambda@Edgeからimgixに画像CDNを移行した話

今まではURLパラメータによる「動的な画像リサイズ＋圧縮」をLambda@Edgeで行っていたが、それを**[imgix](https://www.imgix.com/)という画像処理に特化したSaaSの画像向けCDN**に移行した背景と所感についてまとめてみる。

## TL;DR
- Lambda@Edgeはレスポンスサイズの上限が1MBなので、大容量画像に不向き
- imgixの方が、初回（キャッシュなし）時のレスポンスタイムが速い（およそ1000ms → 200ms）
- imgixは導入も手軽で、料金はLambda@Edgeとほとんど変わらない
- imgixはwebp対応ブラウザ（Chromeなど）に自動でwebpで返すことができる

## Lambda@Edgeの残念な点
### レスポンスサイズの上限が1MBまで
**Lambda@Edgeはレスポンスサイズの上限が1MBまで**という割と大きな欠点がある。例えば横2000pxにリサイズしたけど1MBを超えてしまうという場合に、リサイズせずにそのままオリジンの画像を返す必要がある。

### webp対応かの判定をする場合は遅くなる
imgixは`?auto=format`と付けると、Chromeなどのwebp対応ブラウザにはwebp形式で自動で返してくれる。

これの同等の機能をLambda@Edgeで実装する場合、キャッシュの有無にかかわらずUserAgentによる判定のLambdaを1つ挟まなければならず、そのLambdaの起動によってキャッシュありの場合でもレスポンスが遅くなってしまう。下画像でいえばViewer requestにあたる。（画像の処理を行うLambdaはOrigin response）

![cloudfront-events-that-trigger-lambda-functions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109606/a78f9398-2c8a-37e2-ad6d-d8317dc9b791.png)

### レスポンス速度が遅い
あとはLambda@Edgeはレスポンスが遅い。キャッシュがない画像をリクエストした際はLambdaが走るのだが、**おおよそ1~1.5秒ぐらい掛かる**。しかしimgixはwebpの判定とロスレス圧縮を加えても200ms～300msで返ってくる。画像処理がかなり速いのだ。

Lambda@Edgeはレスポンスが遅いため、画像のリリース時にわざわざCloudFrontのドメインを叩いてキャッシュを生成していたが、imgixにしてからはそれが必要なくなった。

## imgixは導入簡単で値段も安い
imgixのセットアップ自体もかなり手軽にできる。自分の場合はオリジンの画像をAmazon S3に保存しているが、バケット名とアクセス用IAMのキーを渡すだけでOK。ダッシュボードも見やすいしレンダリングに掛かった時間などもチェックできる。

![b12c210d6e2b5450f3ccf33dffac43d6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109606/705811ee-e32b-2ed2-4548-9577b49ecbc5.png)

値段もお手頃で、**オリジン画像の取得1000回で3\$、転送量1GBで0.01\$**しか掛からない。ほぼLambda@Edgeと変わらない値段だが、最低10ドルからという制限があるので注意が必要。

## imgixの代替案
imgixの他にも画像処理CDNを提供するSaaSはある。例えばメルカリやpixivが利用している「[ImageFlux](https://www.sakura.ad.jp/services/imageflux/)」もある。ただImageFluxは料金をサイトで公開しておらず、小規模サービスに導入するには一定のハードルがある。

他にもFastlyは「[Image Optimization](https://www.fastly.com/io)」を提供している。Fastlyの場合は画像に加えてJSやCSSなどの静的アセットも扱うことができるが、ImageOptimizerの値段は少し高く、契約もFastlyのサポートとコンタクトを取る必要がある。FastlyはVCLも扱えるのでCDNサービスとしては自由度が高く優秀だが、小規模サービスではimgixで十分すぎる。

## 結論
Lambda@Edgeのメリットを挙げるなら、AWSの証明書と組み合わせて無料でカスタムドメインが使えること、そして法人ならAWSに請求書をまとめられる事ぐらいになる。画像だけなら別にカスタムドメインじゃなくてもいいし、何よりセットアップが手軽で低料金なのがimgixの良いところだと思う。

一休.comも[imgix導入で画像最適化とサイトスピードを改善した話](https://user-first.ikyu.co.jp/entry/2018/07/02/070000)という導入事例があり、実際に自分も業務レベルで十分に扱える印象を受けている。サービスの画像周りで課題を抱えているなら、ぜひ検討して欲しい。
Excel (Office 365) > UI > 書式なし貼り付けを最速で実行する方法 > 右クリック, V

```txt:動作環境
Windows 8.1 Pro (64bit) 
Excel (Office 365)
```

### 概要

- 「書式なし貼り付け」を最速で実行する方法

偶然見つけた。

### 方法

![2019-05-30_15h33_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/7aa4ba9d-bbbe-25ae-36f2-e5224fd75ba4.png)

上記の(c)が「エイイ！ 最速、最速ゥ!!」
(cf. そこにしびれるあこがれるDIO様)


### コンテキストメニュー

![2019-05-30_15h32_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/ef28d9b2-509b-f255-a0dc-3f1768f6610d.png)

Vというコンテキストメニューはないような気がする。


### UI

- (b) マウス操作 + マウス操作
- (c) マウス操作 + キーボード操作

cの方が若干速い。
ミスをしにくい。
Bulmaのしたいこと別覚書き

Bulmaを使う環境で「あれしたいんだけど…」って時に探しにくかったので個人的によく使うものだけ抜粋です。

（V0.7.5）

そのほかについては公式ページをご覧ください。
https://bulma.io/documentation/

## 文字サイズを変える
| Class | Font-size |
|:--|:--|
| is-size-1 | 3rem |
| is-size-2 | 2.5rem |
| is-size-3 | 2rem |
| is-size-4 | 1.5rem |
| is-size-5 | 1.25rem |
| is-size-6 | 1rem |
| is-size-7 | 0.75rem |

## 文字を寄せる
| Class | Alignment |
|:--|:--|
| has-text-centered | センター寄せ |
| has-text-justified | 横いっぱいに広げる |
| has-text-left | 左寄せ |
| has-text-right | 右寄せ |

## 文字の太さを変える
| Class | Weight |
|:--|:--|
| has-text-weight-light | light |
| has-text-weight-normal | normal |
| has-text-weight-medium | medium |
| has-text-weight-semibold | semi-bold |
| has-text-weight-bold | bold |

## 上下センターに配置
親要素へ　```.is-vcentered```

## 左右センターに配置
親要素へ　```.is-centered```

## デフォルトで設定されてるmargin/paddingを取り除く

マージンを取る　```.is-marginless```
パディングを取る　```.is-paddingless```

## PCの時は横並び、スマホの時は縦並びになるボックス

```
<div class="columns is-desktop">
  <div class="column">1</div>
  <div class="column">2</div>
  <div class="column">3</div>
  <div class="column">4</div>
</div>
```
Webpack で ビルド時に環境ごとに読み込む環境変数を分けたい

# 概要
ほとんどの Laravel などのバックエンドフレームワークは環境変数ファイルが用意され、環境ごとに読み込まれる環境変数を動的に変えることができる機能が備わっています。
しかし、javascript の場合は環境変数を環境ごとに読み込む機能を自分で設定するか npm パッケージ を利用するしかなかったので、自分的ベストな方法をまとめておきます。

# 結論
Webpack の alias 機能を使えばパッケージやライブラリなしで環境変数を分けることができます!!!!!!

# 設定方法
今回編集するファイルは下記ファイルになります。

```
webpack.config.js
package.json
```

## 前提環境
開発環境は node サーバをローカルにたてて開発。
本番、ステージサーバは CI・CD を利用してビルド後デプロイするといった環境で行いました。

## フォルダ構成
フォルダ構成は下記のとおり Webpack を利用した際の一般的な javascript の開発構成です。
環境変数をステージ毎に切り替えるための .env フォルダを用意しています。このフォルダにステージごとの環境変数を定義した js ファイルを用意します。

```
.env
  |_ dev.js
  |_ stg.js
  |_ prd.js
dist
  |_ main.js
src
  |_ index.js
node_modules
package-lock.json
package.json
webpack.config.js
```
## 環境変数ファイルの作成
.env フォルダ内に環境変数用の javascript ファイルを作成します。

```javascript:dev.js
export default {
    apiUrl : 'https://dev-example.com'
}
```
```javascript:prd.js
export default {
    apiUrl : 'https://example.com'
}
```
このような感じでステージごとの環境変数を設定していきます。

## package.json の scripts 設定
package.json に `npm run <ステージ>`の実行コマンドを定義します。
ステージごとに環境変数定義ファイルを動的に読み込むために `NODE_ENV=stg` を設定します。
`NODE_ENV`は `webpack.config.js`ファイルで参照できる環境変数になります。環境変数の名前は何でも大丈夫です。
下記のようにステージごとに渡してあげる環境変数を変えてあげましょう。

```javascript:package.json
{
  "scripts": {
    "stg": "NODE_ENV=stg webpack --mode production",
    "prd": "NODE_ENV=prd webpack --mode production",
    "start": "NODE_ENV=dev webpack-dev-server --mode development --hot --inline --watch-content-base"
  },
// 省略
```

## webpack の設定
webpack.config.js に alias の設定を行います。

```javascript:webpack.config.js
const environment = process.env.NODE_ENV || 'dev';

module.exports = {
  mode: 'development',

  resolve: {
    alias: {
      userEnv$: path.resolve(__dirname, `.env/${environment}.js`),
    },
  },
// 省略
}
```

alias は 深くネストされた javascript ファイルのパスをいちいち書くのがめんどくさい人用にエイリアスとして設定できるようにしてくれる Webpack の機能です。
この alias を利用してステージ毎に環境変数ファイルを動的に読み込むように設定しています。

`process.env.NODE_ENV` は package.json で定義した環境変数が取得できます。
この環境変数によって、読み込みたい環境変数が定義されたファイルを動的に変更します。
※環境変数を定義したファイルまでのパスは絶対パスで指定しましょう。

```javascript
userEnv$: path.resolve(__dirname, `.env/${environment}.js`)
```

以上で設定は終わりです。

# 利用方法
javascript 側で環境変数を利用するときは下記のように import してあげましょう。

```javascript:test.js

import userEnv from 'userEnv';
console.log(userEnv.apiUrl);
```


あとはローカルや CI・CDで npm コマンドを実行しましょう。

```shell

// ローカル開発環境
npm run start

// CI・CDスクリプト
npm run stg
npm run prd
```

これでステージごとに環境変数を読み込むことができました。
環境変数を動的に切り替えるパッケージが結構あるみたいですが alias を使う方法だとパッケージいらずに環境変数を切り替えられるので簡単に利用できると思います。

※ ちなみに node サーバではなくフロント側の環境変数の設定方法なので漏れてはいけない key などの情報は設定しないでね。全部漏れちゃいますので

環境変数用のパッケージに `cross-env`や`dotenv`などがありますがそれらを利用する場合の違いやメリット・デメリットがよくわかってないのでわかる人いたら教えてくださいm(_ _)m
AtCoderのランキングをpythonでスクレイピングしてみる。

レート分布として水以上が強いのはわかるけどあんま参加してない灰色がめちゃくちゃ多いから実際のところどーなのよってのをスクレイピングして参加回数5回以上の参加者のレートを抜き出します。ランキングの表示形式とかが変わったら動かなくなるだろうけどサポートはしません。2019年5月30日現在、このコードは動きます。jupyter想定です。

```python
import urllib.request
l=[]
for r in range(1,311):
    print(r)
    d=urllib.request.urlopen("https://atcoder.jp/ranking?desc=true&orderBy=competitions&page="+str(r)).read().decode('utf-8').replace("	","").split("\n") 

    for i in range(len(d)):
        tmp=[]
        if d[i]=="<tr>":
            tmp.append(int(d[i+1].replace(r'<td class="no-break">',"").replace("</td>","")))
            tmp.append(d[i+2].replace("</span></a>","")[-18:].split(">")[-1])
            tmp.append(int(d[i+5].replace("<td><b>","").replace("</b></td>","")))
            tmp.append(int(d[i+6].replace("<td><b>","").replace("</b></td>","")))
            tmp.append(int(d[i+7].replace("<td>","").replace("</td>","")))
            l.append(tmp)
```
lにランキング、ユーザー名、現在のレート、最高レート、参加回数を入れます。

```python
%matplotlib inline
from numpy import*

df=array(l)
df=df[df[:,-1]>=5]
x=[float("inf"),2800,2400,2000,1600,1200,800,400,0]
current=[]
high=[]
for i in range(len(x)-1):
    current.append(len(df[:,2][ (x[i]> df[:,2]) & (df[:,2] >=x[i+1]) ]))
    high.append(len(df[:,3][ (x[i]> df[:,3]) & (df[:,3] >=x[i+1]) ]))
print(current,high)
```
レートで振り分けてcurrentとhighに入れます。
赤色から順に
[139, 223, 488, 948, 1947, 2669, 2715, 2647]人
[150, 255, 488, 998, 2028, 2680, 2660, 2517]人
であることが分かりました。

```python
from matplotlib.pyplot import*
pie(current, startangle=90,colors = ["red","orange","yellow","blue","cyan","green","brown","gray"])
```
![current.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369642/cab12a74-fc63-2c7a-d05f-d4124324ac9b.png)
灰、茶、緑、水色で同じような割合で存在するようです。

```python
pie(high, startangle=90,colors = ["red","orange","yellow","blue","cyan","green","brown","gray"])
```
![high.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369642/a05142d5-b6af-9637-2cea-aea84db4125f.png)
highでもあんまり変わりませんでした。おしまい。
Travis CIからSlackに通知する際の認証情報の暗号化（travis encrypt）について

## TL;DR

1. `.travis.yml`に直トークン書きたくないから`travis encrypt`したい
2. Travis「[Travis CLI](https://github.com/travis-ci/travis.rb) 使ってね」っ `gem install travis`
3. このプロジェクト`ruby`じゃないし、ローカルにも`ruby`入ってない…

というときに、`ruby`のDockerイメージを使ってアプリケーションに影響なくサクッとやりたい

## 準備

実践したのはmac + Docker for Mac環境ですが、Docker使えれば大丈夫なはずです

* macOS 10.14.5
* docker 18.09.2

## 想定プロジェクト

* GitHubで管理されている
* [travis-ci.com](https://travis-ci.com)でCIを回している
* アプリケーションルートに`.travis.yml`がある

## 手順

```
$ cd /path/to/project
$ docker run -it --rm --volume $(pwd)/:/app ruby bash
# cd app
# gem install travis
# travis login --com --github-token XXXXXXXX
# travis encrypt "xxxxxx:XXXXXXXX" --add notifications.slack --com
# exit
```

※ `--com`オプションについて
>[travis-ci.com](https://travis-ci.com/)を使ってるので`--com`オプションつけましたが、[travis-ci.org](https://travis-ci.org/)な場合はオプション無しでよいのかもしれません（未検証）

※ `--github-token`オプションについて
>GitHubで二段階認証を有効化している場合は、`Personal access token`を発行して指定する必要があります
GitHub > Settings > Developer settings > Personal access tokens から発行できます
必要なスコープは`repo`, `user:email`だと思われます
有効化していない場合は`--github-token`オプションなしでやれば、普通にuser/passの認証がされるのでそれで大丈夫だと思われます（未検証）

※ `travis encrypt`コマンドの部分はSlackのTravisアプリ画面の「セットアップの手順」に書いてあるのでコピーしちゃえば大丈夫です

上記うまくいけば`.travis.yml`に暗号化された認証情報が追記されているはずなので、コミットしちゃえばOK

```diff
+notifications:
+  slack:
+    secure: XXXXXXXXXXXXXXXX...
```

## まとめ

[Circle CI](https://circleci.com/)は設定ファイルじゃなくWeb上の設定画面でWebhookのURL指定するだけで通知できたので楽ちんだった
manjaroでのchromeでprogateを含むブラウザ上のエディタのカーソルの位置がおかしくなる

# 何が起こっていたか、とその原因
Progateは外部ライブラリの[Aceエディタ](https://github.com/ajaxorg/ace)というものを使っていて、そのAceエディタがmonospace(等幅フォント)なフォントをローカルに参照しにいくため、等幅フォントのインストール加減によっては等幅フォント以外のフォントでレンダリングされるという現象だった。

# 解決策
AceエディタのfontのCSSは以下のようになっています。

```css
{ font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace; }
```

ですので、monacoフォントをインストールしてchrome再起動で解決します。

## Arch系のOSの場合

AURにttf-monacoというパッケージがあるので、ソフトウェアの追加と削除からとか、yayとかaurmanを使って入れてください。

## Ubuntuの場合

```shell

curl -kL https://raw.github.com/cstrap/monaco-font/master/install-font-ubuntu.sh | bash
```

# ついでにCircleCIの公式ページもぶっ壊れてる時
`ttf-material-icon` というパッケージがあるのでそれをインストールしましょう。
【Storybook】iframe 内の `body` に任意のクラス名を追加する方法

`Storybook decorator` を使うことで Storybook の iframe 内の `body` に任意のクラス名を追加できます。 

```javascript

storiesOf('name', module)
  .addDecorator(story => {
    document.body.classList.add('hasHover');
    return story();
  })
  .add('other name', () => {
    // ..
  });
```
素のJSでのスムーススクロール

## どうしたいか
ページ内リンクをスムーズなアニメーションでスクロールさせたい。

### 条件
- スムーズな動作であること
- jQueryやライブラリは、不必要に用いないこと
- なるだけシンプルに、汎用的な構造にすること

## どうしたのか
`window.scroll`を用いて解決しました。
[MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/scroll)から引用しますと下記の部分です。

>スクロールの動作を変更する
>スクロールの仕方を変えたいなら、options で指定してください

>>window.scroll({
  top: 1000,
  behavior: "smooth"
});

### プロパティについて
| プロパティ       |       説明 |
|:-----------------|:------------------|
| top             | 左上を基準とした、表示させたい文書の水平軸上のピクセル |
| left           | 左上を基準とした、表示させたい文書の垂直軸上のピクセル |
| behavior           | smooth、 instant、 auto のうちどれか一つを含む文字列。初期値は auto |

※behaviorのinstantはautoと同動作で、一瞬で移動します。基本、smoothかautoかのどちらかを選択する形になるのかなと思います。

### 例
ページトップのボタンしかないし、定期的な改修もないよって場合なら、シンプルにこれだけで大丈夫。

```js:index.js
// EventTargetには、対象となる要素の参照を入れください。
EventTarget.addEventListener('click', (e) => {
  e.preventDefault();
  window.scroll({
    top: 0,
    behavior: 'smooth'
  });
});
```

ただ、ちょっと汎用的とは言い難いので、私の場合は下記のようにしました。

```js:index.js
// aタグ要素の参照を取得
const links = document.querySelectorAll('a[href^="#"]');

// 各aタグにクリックイベントを設定
for ( let i = 0; i < links.length; i++ ) {
  links[i].addEventListener('click', (e) => {
    // デフォルトのイベントをキャンセル
    e.preventDefault();

    // 対象（aタグ）のY軸の絶対座標を取得
    const elemY = links[i].getBoundingClientRect().top;
    // 現在のスクロール量を取得
    const scrollY = window.pageYOffset;
    // 対象までのスクロール量を算出
    const top = elemY - scrollY;

    window.scroll({
      top: top, // スクロール量の設定
      behavior: 'smooth' // スクロール動作の設定
    });
  });
}
```


## 最後に
このやり方を知るまでは、velocity.jsを使って、スムーススクロールを実装していました。
簡単なWEBサイトでもjQueryを入れて、前述のvelocity.jsを入れて・・・。ということをしていたので、かなり無駄なことをしていたなと思います。

ちなみにこのやり方は、[今どきのスムーズスクロール(2019年版)     - to-R Media](https://www.to-r.net/media/smooth_scrolling_2019/)でも解説されていました。さすが西畑先生です。
【Storybook】`storyshots-puppeteer` で異なるデバイスのビジュアルスナップショットを撮る方法

Storybook に `storyshots-puppeteer` を導入した後、異なるデバイスのビジュアルスナップショットを撮れるようにしたいと思い、下記のように書き換えました。

```javascript

import initStoryshots from '@storybook/addon-storyshots'
import { imageSnapshot } from '@storybook/addon-storyshots-puppeteer'
import pupDevices from 'puppeteer/DeviceDescriptors';

const supportedDevices = new Set(['iPad', 'iPhone 5', 'iPhone 6', 'iPhone 7 Plus'])

initStoryshots({ suite: 'Image storyshots: PC', test: imageSnapshot() })

function createCustomizePage(pupDevice) {
  return function(page) {
    return page.emulate(pupDevice);
  }
}

for (let supportedDevice of supportedDevices) {
  const pupDevice = pupDevices[supportedDevice];

  if (!pupDevice) {
    continue;
  }

  const customizePage = createCustomizePage(pupDevice);

  initStoryshots({
    suite: `Image storyshots: ${pupDevice.name}`,
    test: imageSnapshot({
      customizePage,
    })
  });
}
```