OmniAICreator/Qiita-1.07M huggingface dataset:
CSSの圧縮

# CSSの圧縮

[Water.css][watercss]に感化されて開発を始めた私ですが、他の開発者の**ファイルが小さいのは何故か**という素朴な疑問を持ちました。

# ○○○.min.×××？

ライブラリ等を使っているとしばしば見掛けるこの"○○○.min.×××"という名前。
正直気にもしませんでした。
jQueryにしろ何にしろ、そうあるからそう使っているだけでした。

# Water.cssを覗き見

すると、minは改行などの**無駄な文字列を消し小さくしたもの**だと気付きました。
そして、これこそが**ファイルが小さく済む理由**なのだと理解しました。

# 実際にしてみる

｢CSS 圧縮｣
出てきたのは沢山のツールたち。
オンラインで使うものもあれば、コマンドで実行するものもありました。
取り敢えず私は、[refresh-sf.com][refresh]を使ってみました。
すると、**1,000文字近く短く**なったのです。

|状態|行数|文字数|比率|
|:---:|---:|---:|---:|
|圧縮前|244|3,587|1(△0%)|
|圧縮後|1|2,227|0.63(△37%)|

行数については置いておいて、これはとても驚きました。

# しかし納得はできなかった

だが、実際に圧縮後のソースを読んでみると、まだまだ小さくなれそうです。
オンラインなどは汎用的なシステムであるが故に、後から上書きするから取り敢えず最初に0にしておくだとか、そういった処理はなされません。
酷いとこにあっては、**同じ値が6箇所も**充てられていました。
それを無くすだけでも十分に小さくなります。

# 自力で小さくしてみる

今回私が圧縮を試みたのは開発中の[Doc.css][github]です。
一部の要素に対して作用し、可読性を高める目的で開発を始めました。
だからこそ、こういった規則性があるだとかは自分が一番知っています。
なので私は、自力で小さくしようと考えました。

## display値で絞る

今回、[Doc.css][github]により影響を受ける要素はそこまで多くなく、displayがblockであるものに関しては**基本的に同じ**marginやpaddingを与えています。
なのでまずはdisplayがblockか否かでグループ分けをしてみました。

|displayの値|タグ|
|:---:|:---|
|block|blockquote,button,code,h1,h2,h3,h4,h5,h6,hr,img,ol,p,table,textarea,ul|
|blockじゃない|a,li,tbody,td,tfoot,th,thead,tr|

tableに関しては諸事情でblockに分類されましたが、のちほど上書きするので気にしません。

## 特有の値を除外する

例えばcolorだとかoutlineだとか、**意図的に一部の要素にのみ充てたい値**があります。
それだけを選出し、一時的にファイルの後ろの方に追いやりました。
こうすることで**特有でない値が残る**
ので、**どれが共用可能か**がはっきりします。

# 編集後

大分小さくなりました。
作業のために改行はしてありますが、ここで圧縮前後と比較してみます。

|状態|行数|文字数|比率|
|:---:|---:|---:|---:|
|圧縮前|244|3,587|1(△0%)|
|圧縮後|1|2,227|0.63(△37%)|
|編集後|38|1,716|0.48(△52%)|

圧縮後のファイルから**文字数を500近くの削減に成功**しました。
では最後に、改行を処理したものも比較してみます。


|状態|行数|文字数|比率|
|:---:|---:|---:|---:|
|圧縮前|244|3,587|1(△0%)|
|圧縮後|1|2,227|0.63(△37%)|
|編集後|38|1,716|0.48(△52%)|
|最終版|1|1679|0.47(△53%)|

最終的に、**53%近くの削減に成功**しました。

# 感想

共用化可能な部位を探すのは単純に頭の体操になるだけでなく、プログラムを組む上でも大分重要な観点だろうと思いました。
こことここは共用化できる、ここは無理そうだと、そういった判断は**実際の仕事の上でも活用できます。**
便利なツールに頼るのは楽ですが、たまにはこうして一手間かけてみるのも良いものだなと感じました。

# 最後に

今回、私が開発を進めたCSSはDoc.cssと名付け、[Github][github]上に公開した。
特徴としては以下が挙げられる。

- 一部の要素に対し適用される。
- 圧縮版は2kB以下と小型である。
- ドキュメントとして読みやすい。(←私的見解)

サンプルは[こちら][demo]から確認できるので、是非ともご覧頂き、感想や意見、指摘を頂きたい。
[demo]: https://re-frain-org.github.io/?key=Doc-CSS&page=content
[github]: https://github.com/re-frain-org/Doc.css/
[refresh]: http://refresh-sf.com
[watercss]: https://watercss.netlify.com/
[JavaScript] 擬配列オブジェクトから配列を作る最適解の考察（スプレッド演算子 vs Array.from()）

# 概要


* 「配列型」や「反復型」の擬配列オブジェクトから配列のインスタンスを作る機会が多いので、最適解が何かを調べてみました。

# 方法

* 構文が分かりやすい以下のコードのどちらが速いかを比較してみました。回転数は 100万回。実行環境は Google Chrome 74.0.3729.169 です。

```javascript:[...xxx]
const max = 1000000
console.time()
for (let i = 0; i < max; ++i) {
  const a = [...document.body.childNodes]
}
console.timeEnd()
```
```javascript:Array.from(xxx)
const max = 1000000
console.time()
for (let i = 0; i < max; ++i) {
  const a = Array.from(document.body.childNodes)
}
console.timeEnd()
```

# 結果

* スプレッド演算子がかなり速いようです。構文としてもスマートなので、こっちを使っていこうと思います。

|statement|Google Chrome<br>74.0.3729.169|Safari<br>12.1|
|---------|---:|--:|
|[...xxx]|**`11421.31689453125ms`**|**`649.917ms`**|
|Array.from(xxx)|`16186.26708984375ms`|`678.806ms`|

* もっと速いのがある場合は、コメント欄で教えて下さい！

# 学習

|日本語|英語|例|
|:---:|:--:|:--|
|配列型|array-like|arugments<br>NodeList|
|反復型|iterable|Map<br>Set<br>String|
ZabbixAgentでプロセス単位のメモリ量を確認する

OSのメモリは標準テンプレートで確認できますが、
たとえばphp-fpmのメモリ量だけ確認したいなど、プロセス単位で知りたいとき、
ZabbixでスクリプトとUserParameterを使って確認する方法です。

## 対象OS
Centos,Debian
## カスタムスクリプト作成
※ZabbixAgentがインストールされているサーバで実施

スクリプト用ディレクトリ作成

```
sudo mkdir /etc/zabbix/script
```

スクリプト作成

```
sudo vi /etc/zabbix/script/proc_mem.sh 
*以下を記載
#!/bin/bash
  
[ -z "$1" ] && COMM='.*' || COMM="$1"
[ -z "$2" ] && EUSER='.*' || EUSER="$2"
[ -z "$3" ] && MODE='sum' || MODE="$3"
[ -z "$4" ] && ARGS_PATTERN='.*' || ARGS_PATTERN="$4"
  
PLIST=$( ps -eo rss,comm,euser,args --no-headers )
  
case "${MODE}" in
 "min")
   echo "${PLIST}" \
     | awk -v comm="^${COMM}$" -v euser="^${EUSER}$" -v   args_pattern="${ARGS_PATTERN}" \
       'BEGIN {MIN=0;CNT=0}{
          if (($2 ~ comm) && ($3 ~ euser)){
            args="";
            for(i=4;i<=NF;i++){args=args""$i};
            if (args ~ args_pattern) {
              if (CNT == 0) { MIN=$1;CNT+=1 } else if ( MIN > $1 ) { MIN=$1 }
            }
          }
        } END {print MIN}'
 ;;
 "max")
   echo "${PLIST}" \
     | awk -v comm="^${COMM}$" -v euser="^${EUSER}$" -v args_pattern="${ARGS_PATTERN}" \
       'BEGIN {MAX=0}{
          if (($2 ~ comm) && ($3 ~ euser)){
            args="";
            for(i=4;i<=NF;i++){args=args""$i};
            if (args ~ args_pattern) {
              if (MAX < $1) { MAX=$1 }
            }
          }
        } END {print MAX}'
 ;;
 "avg")
   echo "${PLIST}" \
     | awk -v comm="^${COMM}$" -v euser="^${EUSER}$" -v args_pattern="${ARGS_PATTERN}" \
       'BEGIN {SUM=0;CNT=0}{
          if (($2 ~ comm) && ($3 ~ euser)){
            args="";
            for(i=4;i<=NF;i++){args=args""$i};
            if (args ~ args_pattern) { SUM+=$1;CNT+=1 }
          }
        } END {printf("%d\n", SUM/CNT)}'
 ;;
 "sum")
   echo "${PLIST}" \
     | awk -v comm="^${COMM}$" -v euser="^${EUSER}$" -v args_pattern="${ARGS_PATTERN}" \
       'BEGIN {SUM=0}{
          if (($2 ~ comm) && ($3 ~ euser)){
            args="";
            for(i=4;i<=NF;i++){args=args""$i};
            if (args ~ args_pattern) { SUM+=$1 }
          }
        } END {print SUM}'
 ;;
 *)
   exit 1
 ;;
esac
   
exit 0
```

権限変更

```
sudo chmod 655 /etc/zabbix/script/proc_mem.sh
sudo chmod 655 /etc/zabbix/script/proc_mem.sh
```

## Zabbix Agent UserParameter追加
※ZabbixAgentがインストールされているサーバで実施

```
sudo vi /etc/zabbix/zabbix_agentd.conf 
*以下を追加 
UserParameter=script.proc.mem[*],/etc/zabbix/script/proc_mem.sh "$1" "$2" "$3" "$4" 

# zabbix agent再起動
```

## Zabbix Serverで値がとれるか確認
※Zabbixサーバで実施

```
zabbix_get -s zabbix_agentのip -k 'script.proc.mem[プロセス名]'
(例)zabbix_get -s zabbix agentのip -k 'script.proc.mem[nginx]'
16940
値が帰ってくれば、成功。上記例では、nginxが使用しているメモリは16940KBになります
```
labelの使い方と注意点

こんばんは

HTMLでlabelタグを使うときの注意点について、忘備録程度ですがまとめました

1.forとidの要素名は同一にする

2.nameとidの要素名は一致しなくてもよい

```
<div class="control"><label for="mymail">メールアドレス</label>
    <input id="mymail" type="email" name="mymail">
</div>
```
Openstack CLI環境構築

## CentOS7の場合
```
必要なパッケージインストール
yum install epel-release
yum install gcc
yum install python-devel python-pip
pip install --upgrade pip
pip install python-openstackclient
 
個別インストール
pip install python-{muranoclient,ironicclient,cinderclient,senlinclient,novaclient,magnumclient,troveclient,designateclient,glanceclient,barbicanclient,monascaclient,neutronclient,swiftclient,heatclient,cloudkittyclient,manilaclient,ceilometerclient,mistralclient}
pip install python-keystoneclient
```

## Debian8の場合
```
apt-get update -y
apt-get install git jq
git config --global http.sslVerify false
 
OpenStack CLI用仮想環境構築手順
# 必要パッケージインストール
apt-get install gcc
# pyenvダウンロード
git clone https://github.com/yyuu/pyenv.git /usr/local/src/.pyenv
 
# pyenv使用準備（全ユーザー用）
echo 'export PYENV_ROOT="/usr/local/src/.pyenv"' >> /etc/profile.d/pyenv.sh
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> /etc/profile.d/pyenv.sh
echo 'eval "$(pyenv init -)"' >> /etc/profile.d/pyenv.sh
source /etc/profile.d/pyenv.sh

# 最小限のライブラリのみ入れるためminicondaをインストール
pyenv install miniconda3-4.1.11

# miniconda利用準備
pyenv rehash

# alias設定（PATHに入れるとpyenvが使えなくなるので使うコマンドだけalias）
echo 'alias activate="source $PYENV_ROOT/versions/miniconda3-4.1.11/bin/activate"' >> /etc/profile.d/pyenv.sh
echo 'alias py36="activate py36"' >> /etc/profile.d/pyenv.sh
echo 'alias deactivate="source $PYENV_ROOT/versions/miniconda3-4.1.11/bin/deactivate"' >> /etc/profile.d/pyenv.sh
echo 'alias conda="$PYENV_ROOT/versions/miniconda3-4.1.11/bin/conda"' >> /etc/profile.d/pyenv.sh
source /etc/profile.d/pyenv.sh

# OpenStack CLI用仮想環境作成（Python3.6）
conda create -n py36 python=3.6

# OpenStack CLI用仮想環境選択（source $PYENV_ROOT/versions/miniconda3-4.1.11/bin/activate py36 が実行される）
py36

# OpenStack CLI用仮想環境にopenstackコマンドインストール
pip install python-openstackclient==3.8.0

# デフォルトのPythonバージョンが変更されていないことを確認
pyenv versions
deactivate
python -V
 
# OpenStack CLI用環境変数設定
source project-openrc.sh
 
■ CLI使用時は以下を実行する
py36
source project-openrc.sh
```
PythonでSambaサーバーにあるExcelファイルを編集する

# 概要
PythonからSambaファイルサーバーに接続し、xlsxファイルを開き、編集、保存する。
なお、一時ファイルを作らずに作業を行う。

# 環境
- Ubuntu Server 18.04.2 LTS
- Python 3.6.7

# 追加パッケージ
- openpyxl
- pysmb

# コード

```python
import io
import platform

import openpyxl
import smb
from smb.SMBConnection import SMBConnection


conn = SMBConnection(
    "username",
    "password",
    platform.uname().node,
    "remote_name",
    use_ntlm_v2=True,
)
# ファイルサーバーに接続する
conn.connect("hostname", 139)

root = "/"
filepath = "/hoge.xlsx"

# 開く
with io.BytesIO() as inputfile:
    conn.retrieveFile(root, filepath, inputfile)
    workbook = openpyxl.load_workbook(inputfile)

# ここで編集操作など

# 保存
with io.BytesIO() as outputfile:
    workbook.save(outputfile)
    outputfile.seek(0)
    conn.storeFile(root, filepath, outputfile)
```
OCI Databaseの課金停止方法がわかりにくい問題

# イントロダクション
こんな記事を見つけたので、ついでに補足してみる。

* [Power On/Off your Oracle Databases in 1 minute and save $$$](https://www.oc-blog.com/2019/05/15/power-on-off-your-oracle-databases-in-1-minute-and-save/)

タイトルを見て何かと思ったけれど「DBaaSの課金停止の方法がわかりづらい」って話。経験者にとっては常識でも、初心者は気付きづらいところ。ブログの本文では「Hidden Feature」と言われている。

**Hidden Feature: On/Off of the DBCS VM instances**

課金停止とは関係ないけれど、管理コンソールを日本語表示にしたときは翻訳問題があって、シャットダウンなのか削除なのか直感的にわかりづらい。**Terminate**と**Stop**では、まったく意味が違うので気をつける必要がある。


|メニュー表記（英語）|メニュー表記（英語）|意味|
|:-----:|:-----:|:-----|
|Terminate|終了|削除すること|
|Stop|停止|OSもしくはDBをシャットダウンすること|

# 課金が「停止するサービス」と「停止しないサービス」

停止（シャットダウン）したときに課金が停止するかは、サービスのタイプやシェイプに依存する。基本的にはLocal NVMeを利用したDenseIOシェイプは課金停止しない(Local NVMeとはベアメタル筐体内のNVMeディスクのこと)。またストレージ費用は、インスタンス停止とは関係なく使用量に応じて課金される。

**停止すると課金が停止するサービス**

* DBaaS VMインスタンス
* Autonomous DB（ADW/ATP）
* Exadata CS（ミニマム1か月は課金）

**停止しても課金が停止しないサービス**

* DBaaS BMインスタンス
* BYOL to IaaS（課金停止するのはIaaS部分だけ。DenseIOはIaaS部分も課金停止しない)

気をつけるのは、とくに次の2つだろう。Terminateしないと課金停止しないので、安く使うためにはデータのバックアップと組み合わせる必要がある。

* DBaaS（BM）EE High Performance, EE Extreme Performance
* Compute（DenseIO）

またDBaaSはReserved Public IPが使えないので、再作成するとPublic IPが変わってしまう。CPUコア数が多いならば、動的にコア数を絞ることくらいしかできないかも。


# VMシェイプの課金停止方法
冒頭で紹介していたブログにも記載があるので簡単に紹介する。

1.停止したいインスタンスを選択して**[DB System Details]**ページを表示。ページ左下の**Nodes**をクリック。
![dbaas01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/51571f12-fea9-59e3-f51c-805060e9a734.png)
2. 右にある**「…」**をクリックして**「Stop（停止）」**を選択。最終的にステータスが**STOPPED**になればOKである。たしかにHidden Featureかも。
![dbaas02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/62f7adcb-af12-123c-f3ef-f42d91df7088.jpeg)

最近長めの記事を書いてきたので短いのはいいですなあ。

<font color="red">2020/2追記。以下Webページに課金停止の詳細が書いてある。</font>

* [もしもみなみんがDBをクラウドでうごかしてみたら 第17回 課金と停止について - Autonomous Database/DBCS/ExaCS](https://blogs.oracle.com/otnjp/minamin-cloud-017-stop-usage)
Linux版のUnityでビルド対象にMacOSを選べないことへの対処

Linux版のUnityは次のリンク先等からインストールできるUnityHubでインストールすると思うのですが、MacOS向けにビルドするようにする場合は2019年5月時点ではちょっと手順を踏む必要があったのでメモ。一回作業したら後はやらなくてよくなるので対処は楽です。

" Unity Hub v2.0.0 Release
https://forum.unity.com/threads/unity-hub-v2-0-0-release.677485/

## 対処法

対処法は次のリンク先に書かれています。

" Can't build Mac OS X target on Linux (Ubuntu 18.04)
https://forum.unity.com/threads/cant-build-mac-os-x-target-on-linux-ubuntu-18-04.586255/

具体的には次の手順を踏むと対処できます。

1. Installs→Addから目的のバージョンのUnityを選択し、追加モジュールに`Mac Build Support (Mono)`も選択するようにしてインストール[^1]
2. インストールしたUnityのインストールディレクトリ(`~/Unity/Hub/Editor/<バージョン>`)に移動
3. `Editor/Data/PlaybackEngines`の中に`MacStandaloneSupport`というディレクトリを作成
4. 次のファイルを`Editor/Data/PlaybackEngines/MacStandaloneSupport`に移動
  - ivy.xml
  - modules.asset
  - optool
  - UnityEditor.OSXStandalone.Extensions.dll
  - UnityEditor.OSXStandalone.Extensions.dll.mdb
  - Variations
  - Whitelists

これで完了です。2〜4の手順はコマンドで示すと次のようになります。

```
cd ~/Unity/Hub/Editor/<バージョン>
mkdir Editor/Data/PlaybackEngines/MacStandaloneSupport
mv ivy.xml modules.asset optool UnityEditor.OSXStandalone.Extensions.dll UnityEditor.OSXStandalone.Extensions.dll.mdb Variations Whitelists Editor/Data/PlaybackEngines/MacStandaloneSupport
```

[^1]: Unityを既にインストールしているなら大丈夫だとは思いますが念のため、Unityをインストールするには右上の自分のアイコン→Manage License→ACTIVATE NEW LICENSEからライセンスを有効化する必要があります。

## 原因…？

`~/Unity/Hub/Editor/<バージョン>`にある`modules.json`を見てみると分かるのですが、`Mac Build Support (Mono)`のインストール先が`{UNITY_PATH}/Editor/Data/PlaybackEngines/MacStandaloneSupport`ではなく`{UNITY_PATH}`になっており、それが原因で正しい場所にMacOS用のモジュールがインストールされていないのが原因です。ただ、インストールする前に`modules.json`を書き換えればいいという訳でも無いため具体的な修正方法は分かりません。多分その内治ると思います。それまではこういう手順でインストールしたものを移動させると大丈夫です。
privateとprotectedメソッドをPHPUnitでテストする方法

Javaの[JUnitでprivateメソッドをテストする方法はこちら](https://qiita.com/ponsuke0531/items/5ebb0c5b793e92ba178e)

- 環境 : PHP7.3

# ReflectionClassを使ったprivateとprotectedメソッドを実行するメソッドを用意すると便利にテストできる
**便利ポイント**

1. パラメータには、「実行するメソッド名」とその「メソッドの引数」を指定できるようにする。
    - privateもprotectedも同じやり方でできるのでメソッド名と引数を指定すれば実行できる
2. パラメータで`array $param`とすることでメソッドの引数が1つでも複数でも指定できるようになる
    - メソッドの引数が３つの場合(`private function A($a, $b, $c)`)は、`doMethod('A', [$a, $b, $c]);`となる
    - メソッドの引数が1つの場合(`private function A($a)`)は、`doMethod('A', [$a]);`となる
3. メソッドにしておけばprivateとprotectedのメソッドをいくつあっても簡単。な気がする。

```php:privateとprotectedメソッドを実行するメソッド
    /**
     * privateメソッドを実行する.
     * @param string $methodName privateメソッドの名前
     * @param array $param privateメソッドに渡す引数
     * @return mixed 実行結果
     * @throws \ReflectionException 引数のクラスがない場合に発生.
     */
    private function doMethod(string $methodName, array $param)
    {
        // テスト対象のクラスをnewする.
        $controller = new FormController();
        // ReflectionClassをテスト対象のクラスをもとに作る.
        $reflection = new \ReflectionClass($controller);
        // メソッドを取得する.
        $method = $reflection->getMethod($methodName);
        // アクセス許可をする.
        $method->setAccessible(true);
        // メソッドを実行して返却値をそのまま返す.
        return $method->invokeArgs($controller, $param);
    }
```

## 例えばこんな感じ
```php:FormController.php（テストしたいクラス)
<?php

namespace App\Http\Controllers;

class FormController extends Controller
{
    public function __invoke()
    {
        $param = array();
        $param['data'] = $this->ceateListData();
        return view('form', $param);
    }

    private function ceateListData(): array
    {
        $data = [
            // 内容はどうでも良いので省略
        ];
        return $this->addId($data);
    }

    protected function addId(array $data): array
    {
        if (count($data) !== 0) {
            // 内容はどうでも良いので省略
        }
        return $data;
    }
}
```
```php:FormControllerTest.php(テストクラス)
<?php

namespace App\Http\Controllers;

use PHPUnit\Framework\TestCase;

class FormControllerTest extends TestCase
{
    /** @test */
    public function privateメソッドをテストする()
    {
        // privateメソッドを実行して結果を取得する.
        $list = $this->doMethod('ceateListData', []);

        $actual = gettype($list);
        $this->assertEquals('array', $actual);
    }

    /** @test */
    public function protectedメソッドをテストする()
    {
        $data = [(object)['data' => 'sample1'], (object)['data' => 'sample2']];

        // protectedメソッドを実行して結果を取得する.
        $list = $this->doMethod('addId', [$data]);

        foreach ($list as $v) {
            $this->assertIsInt($v->id);
        }
    }

    private function doMethod(string $methodName, array $param)
    {
        // 内容は先頭と同じ
    }
}
```
Elmでaタグの遷移を止めて別のことをさせたい

[検証用コード](https://gist.github.com/miyamoen/08740930e498fab4aaa882a77900dafe)
[サンプルアプリケーション](https://github.com/miyamoen/a-click-sample)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74093/50a927e9-9c97-f60b-a2f0-4c2cb4346abd.png)

# まとめ

aタグの内側のタグにstopPropagationとpreventDefaultを有効にしたイベントリスナーを貼ると止めれる


# はじめに

ElmでURLのルーティングをしたいなら[Browser.application](https://package.elm-lang.org/packages/elm/browser/latest/Browser#application)を使う必要があります
Browser.applicationを使ったElmアプリではaタグのリンクやhistory backなどのURLの変更を統一的に扱うことができます

[サンプルアプリケーション](https://github.com/miyamoen/a-click-sample)をcloneしてelm reactorで動かしてみてください

```sh
git clone https://github.com/miyamoen/a-click-sample.git
cd a-click-sample
elm reactor
```

（動かすのが面倒な人は上の画像をみてください）

一覧ページと各詳細ページ（といっても内容は変わりませんが）があり、主たる機能として画像を回すことができます

特におかしなところはありませんね。カードコンポーネントをクリックすると詳細ページに飛んで、回すボタンを押すと回ります

では次は、[ここらへん](https://github.com/miyamoen/a-click-sample/blob/e16fcdca69bdc33fb0d3587b0bb436eabbf4f955/Main.elm#L271)のTrueをFalseに変えたりしてみてください（elm reactorはhot realoadがついてないので手動でリロードしましょう）

```elm
    -- 親のaタグのclickイベントを発火させないようにする
    , stopPropagation = False

    -- ブラウザのaタグでの遷移の挙動を止める
    , preventDefault = False
```

どうでしょうか。ボタンをクリックしたら回るんだけど遷移もしちゃったり、こんな画像が出るようになったりしませんか？（elm reactorでの挙動です。お使いのdev serverの404ページが出ると思います）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74093/9c8aa760-d0f1-2424-5f7b-a61d6ac18207.png)


False, Falseがデフォルトのイベントハンドラになります。この設定では回るは回るけど一緒に遷移もしちゃう、という動きになります
__遷移するのは止めて別のこと（回す）をしたい__、というのが今回の趣旨になります


## やり方

```elm
onCustomClick : msg -> Attribute msg
onCustomClick msg =
    Html.Events.custom "click"
        (JD.succeed
            { message = msg
            , stopPropagation = True
            , preventDefault = True
            }
        )
``` 

aタグの内側のボタンや任意のタグでこの`onCustomClick`を使ってイベントハンドラを登録するだけです
aタグ自身に付けてもだめです。止められません
aタグの親に付けてもだめです。`useCapture=true`なんて知りません

簡単ですね

## くわしいせつめい

まずイベントの発生順序とかについて調べてきてください

わたしは[【DOMイベントのキャプチャ/バブリングを整理する 〜 JSおくのほそ道 #017】](https://qiita.com/hosomichi/items/49500fea5fdf43f59c58)で勉強した

Elm関係ないですね。Elmあんまり関係ないんですよ

`Browser.application`はaタグに対して専用のclickイベントハンドラを貼ってます
よって内側でstopPropagationすれば上に伝播しないということになります


# おわりに

aタグの内側のタグにstopPropagationとpreventDefaultを有効にしたイベントリスナーを貼ると止めれます

おとは好きなだけスパムを回してください
MySQL - [PDO]PHP 経由でメモリリミットを回避し、CSV ファイルのファイルサイズ関係なくダウンロードをできるようにする方法

# 課題

CSV ダウンロード機能を実装してみたのはいいが、ある程度のファイルサイズになると
メモリリミットでエラーになったり、PHP からの応答待ちでタイムアウトしたりという課題がある

これを CSV のファイルサイズに関係なくダウンロードをできるように改善する方法をスクリプトで残した

参考まで簡単に手元でも確認できるソースを用意してみた
https://github.com/oz-urabe/qiita-for-csv-download

# もともとの問題のある処理

1. デフォルトのバッファモードで DB からデータを取得 [解決方法1]
2. 取得したデータを配列に格納 [解決方法2]
3. 格納した配列を echo などで出力

# 解決方法1

デフォルトのバッファモードで DB からデータを取得

- [src/csv-download.php#L11](https://github.com/oz-urabe/qiita-for-csv-download/blob/master/src/csv-download.php#L11)

```
$stmt = $pdo->prepare('SELECT * FROM dummy');
$stmt->execute();
```

ここで問題となるのが、[PHP:バッファクエリと非バッファクエリ](https://www.php.net/manual/ja/mysqlinfo.concepts.buffering.php#mysqlinfo.concepts.buffering) から抜粋した以下の記事

```
クエリは、デフォルトではバッファモードで実行されます。
つまり、クエリの結果がすぐに MySQL サーバーから PHP に転送され、
PHP プロセスのメモリ内に結果を保持し続けるということです。
これで、その後で行数を数えたり結果ポインタを
移動 (シーク) したりといった操作ができるようになります。 
```

保持してくれることで、取得後の値を php 側であとから加工しやすくなるが、メモリリミットの問題を引き起こしやすくなるため、デフォルトの挙動が有用であるかはケースバイケース

以下のように追記した

- [src/csv-download-tuned.php#L6](https://github.com/oz-urabe/qiita-for-csv-download/blob/master/src/csv-download-tuned.php#L6)

```
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$stmt = $pdo->prepare('SELECT * FROM dummy');
$stmt->execute();
```

純粋な PDO で記述しているが、他の DB 接続方法でも同様に対応できる。
また、ORM や フレームワークごとにも対応方法が定義されていると思うので、案件ごとにドキュメントを見てください。

# 解決方法2

取得したデータを配列に格納 という処理ですが、以下のように処理されています。
これは関数の中で配列を作り、それを返り値としています。

- [src/csv-download.php#L15](https://github.com/oz-urabe/qiita-for-csv-download/blob/master/src/csv-download.php#L15)

```
    $csv = [];
    while ($row = $stmt->fetch()) {
        $csv[] = sprintf(
            '%d,%s,%s,%s,%s,%s MB',
            $row['id'],
            $row['name'],
            $row['comment'],
            $row['created'],
            $row['updated'],
            memory_get_peak_usage(true) / 1024 / 1024
        );
    }
    return $csv;
```

単純に理解できると思いますが、配列が大きくなるとメモリ消費が大きくなります。
つまり、配列に保存しない方法を考えればよいわけです。

- [src/csv-download-tuned.php#L17](https://github.com/oz-urabe/qiita-for-csv-download/blob/master/src/csv-download-tuned.php#L17)

```
    while ($row = $stmt->fetch()) {
        yield sprintf(
            '%d,%s,%s,%s,%s,%s MB',
            $row['id'],
            $row['name'],
            $row['comment'],
            $row['created'],
            $row['updated'],
            memory_get_peak_usage(true) / 1024 / 1024
        ); 
    }
```

`yield` を使うと、その場で配列を生成せず、反復可能なオブジェクトを返します。こうすることでメモリに値を貯め込むことをせず、 `foreach` の処理内で csv を `echo` などで出力するタイミングで値を取得していくような動作となります。


※ `yield` が使えない古い php の場合においても、配列に溜め込まず、 関数内で `echo` するような処理にすればよいです。

# 補足

試しに github に配置したソースを使って、メモリリミットの現象が回避できるか検証していただいてもよいかと思います

https://github.com/oz-urabe/qiita-for-csv-download.git
CORSでXMLHttpRequest がエラーになる対処方法

### はじめに

GitHub Pagesで電車遅延を知らせるWebページを作っていた時に[CORS](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)にハマったので対処方法をまとめました。

## 環境

ブラウザ：chrome バージョン 74

```javascript:JavaScript
const xhr = new XMLHttpRequest();
xhr.open("GET", `https://rti-giken.jp/fhc/api/train_tetsudo/delay.json`, true);
xhr.responseType = 'json';
xhr.onreadystatechange = function() {
  if(xhr.readyState === 4) {
    if(xhr.status === 200) {
      //
      // JSON遅延データ処理
      //
    }
  }
};
xhr.send();
```



## エラーメッセージ

実行すると以下のメッセージが出る。

```
Access to XMLHttpRequest at 'https://rti-giken.jp/fhc/api/train_tetsudo/delay.json' from origin 'https://username.github.io' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

## 対処方法

chrome.exeの起動オプション（引数）に --disable-web-security、--disable-web-securityを付ける。クライアント側の対応のみで解決する。

## 参考

[Access-Control-Allow-Originのエラーを回避してWebサービスを呼ぶには？](https://web.plus-idea.net/2018/03/allow-control-allow-origin-plug-in/)

[鉄道遅延情報のjson](https://rti-giken.jp/fhc/api/train_tetsudo/)
現在作業しているGitブランチに対応するPRをブラウザで開くコマンド

現在作業しているブランチのPRが既に作られている場合、そのPRをブラウザで開く関数です。

依存

- `hub`コマンド
- `open`コマンド

```zsh
function pr-open {
    local url=$(hub pr list -h $(git symbolic-ref --short HEAD) -f "%U")
    if [ -z "$url" ]; then
        echo "The PR based this branch not found."
        return 1
    fi
    open $url
}
```
ターミナルの自由な場所で入力する方法

# やりたいこと

出力した文字に続いて、入力すること。

```bash

$ ./main
Input: 〇〇〇 ＜◁＝＝ ここに入力

```

# C ソースコード

```c:main.c

#include <stdio.h>

int main(void)
{
    char buf[6] = {0};
    printf("Input: ");
    fflush(stdout);
    fgets(buf, sizeof(buf), stdin);
    puts(buf);
    return 0;
}

```

# Rust ソースコード

```rust:main.rs

use std::io::{stdin, stdout, Read, Result, Write};

fn main() -> Result<()> {
    let mut buf = [0; 5];
    print!("Input: ");
    stdout().flush().unwrap();
    stdin().read_exact(&mut buf)?;
    println!("{}", String::from_utf8(buf.to_vec()).unwrap_or_default());
    Ok(())
}

```

# 結論

入力の直前でflushして、バッファを吐き出せばできる。

# 最後に

Rustでしばらく考えても分からず、一度は諦めていましたが、
Cを書いてる最中にfflush使えば、いけそうだと閃いて、成功しました。

もっと別の方法で実現する方法があれば、教えてください。
Shapes & Drawing -p5.js Tutorial [JavaScript for Beginner]

## レッスン動画
[1.3: Shapes & Drawing - p5.js Tutorial]
(https://www.youtube.com/watch?v=c3TeLi6Ns1E)

***レッスンで使うWebサービス***
[p5*js Web Editor](https://editor.p5js.org/)
[p5*js Reference](https://p5js.org/reference/)

## メモ

```
// Syntax
instruction (__,__,__);

// Sample 1
createCanvas (400,300,200);
rect(100,50,25,75);

// functionName
”rect” | rectangle(長方形)
```

# Code1

```javascript:p5.js

// lineが最前面に表示
function setup(){
  createCanvas(400,400);
}

function draw() {
  backGround(220,0,200);
  rect(100,50,25,75);   //長方形 (x,y,w,h);
  line(0,50,400,300);
}

```

## Preview1
![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282183/f94b64b1-2c71-7d7c-0e13-819f075cb4e1.png)


## Code2
```javascript:p5.js

function setup(){
  createCanvas(400,400);
}
// rectが最前面に表示
function draw() {
  background(220, 0, 200);
  line(0,50,400,300)
  rect(30,20,55,55);
}
```

## Preview2
![ダウンロード (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282183/7f8d572f-b5e7-b334-a7bc-851de8eba312.png)
Androidのリリース用署名情報をbuild.gradleで管理する

リリース用の署名情報(alias、パスワード、keystoreなど）を app/build.gradle に組み込みたい場合がある。

やり方は色々あるが、今回は2つの方法を紹介

## 方法1. app/build.gradleに直書き
一番シンプルで簡単
git管理に含まれちゃうけどね

```groovy:app/build.gradle
android {
...
    signingConfigs {
        debug {
        }
        release {
            storeFile file('release.keystore')
            keyAlias '***'
            storePassword '***'
            keyPassword '***'
        }
    }
```

実装コード
https://github.com/ikemura23/Android-Kotlin-Lab/commit/a85e0fdb4d81039361fee970d115dd1998c4b46b

個人プロジェクトなどはこれでいいんじゃないかな

## 方法2. 別のgradleファイルに書き出す

署名情報をgitに含めたくない場合を想定

会社のプログラムはこれでいいんじゃないかな

[今更ながらAndroid の keystore と 署名(signingConfigs) の管理・運用について考えてみた](https://qiita.com/taki4227/items/c5685ec722a195764237#gradle%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%A4%96%E5%87%BA%E3%81%97%E3%81%A6%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80)
を参考にした

まず release.gradle というファイルを作成する。

```groovy:release.gradle
signingConfigs {
    debug {
    }
    release {
        storeFile file('release.keystore')
        keyAlias '***'
        storePassword '***'
        keyPassword '***'
    }
}
```

そのファイルを build.gradle から読み込む。

```groovy:app/build.gradle
android {
...
    apply from: 'release.gradle', to: android
```

最後に release.gradle をgitに含めないよう.gitignoreに追加して終わり

```.gitignore
app/release.gradle
```

コミット例
https://github.com/ikemura23/Android-Kotlin-Lab/commit/9ab38238a402b2bd1f3104763229aa0cb63c32ec

もし新しい人がプロジェクトにアサインして環境構築する場合、release.gradle をどこからか持ってくる必要があるけどね。

## 備考
たぶん個人プロジェクトも方法２で管理した方が良いね。

他にもっと良い方法があれば知りたいなー
PHPの基本文法 -関数の引数について-

# PHPの基本文法 -関数の引数について-
PHPの関数について、整理してみました。

## 関数とは
変数は値を入れておく箱でしたが、関数は幾つかの処理をまとめて入れておくものです。
関数には、最初から用意されている「組み込み関数」と、自分で定義する「ユーザ定義関数」があります。

「組み込み関数」とは、プログラミング言語などの仕様にあらかじめ用意され、標準で使用できる関数のことを言います。
例えば、`isset()`、`isNull()`、`empty()`, `var_dump()`などがそれに当たります。

逆に「ユーザー定義関数」とは、ユーザーが作成した関数のことを言います。
例えば、

```php5
<?php

function func()
{
    echo "Test";
}

func();

?>
```

## 引数について
引数は、関数を呼び出すときに渡す値です。
関数の中では、その値を使用して処理を行い、必要に応じて結果を返します。
PHPの関数は引数のリストにより、関数へ情報を渡すことができる。
このリストは、「,](カンマ）で区切られた式のリストです。
引数の評価は、左から右の順番で行われます。

### 「値渡し」と「参照渡し」について
引数には、「値渡し」と「参照渡し」があります。
「値渡し」は、変数のコピーを渡す方法で、関数側で変数の内容を変更しても、元の変数には影響しない。
「参照渡し」は、変数への参照を渡す方法で、関数側で変数の内容を変更すると、呼び出し側の変数も同様に変更される。

```php5
//引数「string」を「参照渡し」する関数
function add_str(&$string)
{
    $string = 'Hello ' . $string;
}

$str = 'World';
add_str($str);
echo $str;  //Hello Worldが出力される
```

### デフォルト引数値
デフォルト引数値は、引数の既定値です。デフォルト引数値を指定するには、関数の定義において、代入演算子の「＝」を使用して、引数にデフォルト値を指定する。PHPでは、配列やNULLをデフォルト値にすることもできる。

```php5
function hello($str = "world")
{
    return "Hello $str! <br/>";
}

echo hello();       //Hello world
echo hello(null);   //Hello !
echo hello("Tom");  //Hello Tom!
```
デフォルト引数値を使用する時の注意点
デフォルト引数値は、定数式である必要がある。変数やクラスのメンバーは指定することができない。
またデフォルト引数値を有する引数は、デフォルト引数値がない引数の右側に全てある必要がある。

```php5
//間違った例
function greet1($str = "Hello", $name)
{
    return "$str $name ! <br/>";
}
//第２引数を省略して関数をコールすることはできない
echo greet1("Tom");


//正しい用例
function green2($name, $str="Hello")
{
    return "$str $name! <br/>";
}

//第２引数を省略して関数をコールすることができる
echo greet2("Tom");
```

### 可変長引数リスト
可変長引数リストは、引数の数が変わる関数を定義するためにサポートされている機能です。
可変長引数リストと使用するには、「func_num_args」関数と「func_get_args」関数を使用する。
サンプル↓

```php5
<?php
function avg()
{
  $sum = 0;
  for($i = 0; $i < func_num_args(); $i++){
    $sum += func_get_arg($i);
  }

  $avg = $sum / func_num_args();
  var_dump($avg);
  return $avg;
}
echo avg(2,1,2,1,3,4,5,3,6);
?>
```
PythonでSambaサーバーにあるWordファイルを編集する

# 概要
PythonからSambaファイルサーバーに接続し、docxファイルを開き、編集、保存する。
なお、一時ファイルを作らずに作業を行う。

# 環境
- Ubuntu Server 18.04.2 LTS
- Python 3.6.7

# 追加パッケージ
- python-docx
- pysmb

# コード

```python
import io
import platform

import docx
import smb
from smb.SMBConnection import SMBConnection


conn = SMBConnection(
    "username",
    "password",
    platform.uname().node,
    "remote_name",
    use_ntlm_v2=True,
)
# ファイルサーバーに接続する
conn.connect("hostname", 139)

root = "/"
filepath = "/hoge.docx"

# 開く
with io.BytesIO() as inputfile:
    conn.retrieveFile(root, filepath, inputfile)
    doc = docx.Document(inputfile)

# ここで編集操作など

# 保存
with io.BytesIO() as outputfile:
    doc.save(outputfile)
    outputfile.seek(0)
    conn.storeFile(root, filepath, outputfile)
```
VBSを勉強する一日目

これは、微妙に必要にかられて（？）VBSを学ぶ事になったので
その記録です。
需要があるかわかりませんが、微妙につまづいたところも含めて、
自分の覚書的に残します。

参考本：VBScript サンプル大全集
環境：Windows10

#最初の一歩#

###ファイルをそのまま実行###

```vb
Option Explicit

Dim LngTotal

WScript.Echo "１～１０の合計を計算します"

LngTotal = 0

Call TestProc()

WScript.Echo "１～１０の合計：" & LngTotal

Sub TestProc()

  Dim i

  For i = 1 To 10
    LngTotal = LngTotal + i
  Next

End Sub
```

１：テキストエディタでコードを書く
２：vbsの拡張子で保存する
３：保存したファイルをダブルクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100769/9fd400d0-5428-fdaa-48ba-6ec2a979d4e3.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100769/69818ab9-81af-96f5-46ca-9e18bbc040ce.png)

＊＊注意＊＊
テキストファイルの文字コードはShift-JISにする事。


####コマンドプロンプトで実行###
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100769/44903064-f358-4aaf-104e-fdcc0f0b469b.png)


コマンドプロンプトで作成したファイルがある場所まで移動。

```cscript ファイル名```

を入力してエンターで実行


####優先するWSHの指定###
wscript.exeを優先するとき
```cscript //H:wscript```
cscript.exeを優先するとき
```cscript //H:cscript```

wscript.exeを優先するとファイルをダブルクリックしたときに
上記に記載したように、メッセージボックスに出力されます。

cscript.exeを優先するとメッセージボックスは出ずにプログラムが実行されます。

＊＊注意＊＊
普通にコマンドプロンプトを起動して、WSHの指定をしようとしても
```Cscript エラー：規定のスクリプト　ホストを変更できません。```
となり変更できませんでした。

管理者権限でコマンドプロンプトを起動して行う必要があります。

- 管理者権限でコマンドプロンプトを起動する -
    -  Windows キー + X
    - A キー
    - Alt + Y

####ロゴを表示しない###

```cscript ファイル名 //nologo```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100769/8b02938c-28df-13f9-0c25-047c3d9f1002.png)

赤い四角でかこった部分が表示されなくなりました。
（まだ、これの便利さは実感していません・・）


####スクリプトの強制終了###
キーボードのCtrl+c
(これは使えそうです。）
EC2についてまとめる(EC2内の設定のみ)

## 1.1. やろうとしていること
EC2ではlambdaからきたpostを受取り、推論サーバーに渡して推論を行った後結果を返す。<br>
EC2内の動きで必要になるポイントは、
1. サーバーを立ち上げた後自動的にアプリケーションが実行されてほしい
2. 簡単に環境を整えたい

の2つである。これに対して私は、
1. Systemdを用いてサーバ起動時の動作を設定する。
2. Dockerを用いて環境を設定する。

## 1.2. サービスの説明
### 1. Systemdについて[1]
Systemd : Linuxの起動処理やシステム管理を行う仕組み<br>
Systemdファイルの基本構成要素は **Unit, Service, Install** の３つ。
**Unit, Install** にユニットファイルの共通的な設定内容を書き、**Service** で自ユニットファイルの実行内容の設定を行う。
#### ファイルの書き方について
##### Unit
+ Description : ユニットの説明を書く
+ After/Before : 指定したユニットの実行順番の依存関係を設定
+ Requires/Wants : ユニットの依存関係の定義 <br>
  2つのコマンドの違いは、依存関係のユニットが失敗したときの処理
  - Wantsの場合、依存ユニットが失敗したときでも自ユニットは失敗にならない。

##### Service
+ Type : 5種類存在する。デフォルトはsimple
  - simple
  - forking
  - oneshot
  - notify
  - dbus
+ ExecStart : 実行するコマンドラインを書く

##### Install
+ WantedBy/RequiredBy : ”*systemctl enable ~~*" でユニットをenableしたときに、.wants, .requires にシンボリックリンクを作る。
動作としては"Wants=", "Requires="と同じような感じになる。

### 2. Dockerについて
Docker : Linuxのコンテナ機能を使ったアプリケーションの実行環境を構築/運用するためのプラットフォーム[2]<br>

今回は、pythonをベースに
1. WebフレームワークであるBottleでpostに対するレスポンスを設定した。
2. DLフレームワークであるchainerで推論部分の動作を作成した。

そしてこれをdockerにいれて動作するような環境を作成した。

## 1.3. サービスの設定方法
#### 1. Systemd
##### コード
```systemd:dl_app.service
[Unit]
Description=start_dl_app
Requires=docker.service
After=docker.service

[Service]
Type=simple
ExecStartPre=-/usr/bin/docker container rm dl_app
ExecStart=-/usr/bin/docker container run -i -v /home/ec2-user/document/server:/myvol -p 8080:8080 --name dl_app dl_app
[Install]
WantedBy=multi-user.target
```

1. Systemdファイル作成
2. /etc/systemd/system/の下にファイルを置く
3. SystemdファイルがServiceとして認識されたか確認する
`systemctl list-unit-files --type=service`の出力に現れれば正しく認識されているということ。
4. enableして起動する
`systemctl enable ~~`で認識され、`systemctl start ~~`で起動。

#### 2. Docker
##### コード
```dockerfile:Dockerfile
FROM python:3

RUN pip install bottle chainer matplotlib pillow

WORKDIR /myvol
CMD python index.py
```
dockerコンテナ内に入り、コマンドを入力
+ `docker image build -t dl_app ./ Dockerfile`
+ `docker container run -it -p 8080:8080 -v [マウントするパス]:./myvol --name dl_app dl_app`

### (注意)EC2サーバーの設定[3][4]
まず、dockerをinstallする必要あり
また、各ファイルをEC2内に入れるためにS3とマウントする。
最後にマウントしてあるディレクトリから推論サーバー作成に必要なファイルを移して終了

## 参考サイト
[1] [systemdの*.serviceファイルの書き方](https://qiita.com/masami256/items/ef0f23125cf8255e4857)
[2] [いまさらDockerに入門したので分かりやすくまとめます](https://qiita.com/gold-kou/items/44860fbda1a34a001fc1)
[3][EC2インスタンスにS3をマウントする](https://qiita.com/shicky1121/items/e19b50308c79e5a6081e)
[4][s3fs を使って EC2 に S3 の Bucket をマウントする](https://qiita.com/monry/items/fa3bebd69e04a08ae12f)
pythonの困ったとき用のメモ

pythonを今学んでいるのですが、ノート代わりに忘れそうなことをメモしておくことにしました。言葉を覚えるのが難しい。

#予約語
関数や変数名に使用できない単語のこと。
これを使うと構文エラーが起こる。知らないと気付かなさそう。

[False, await, else, import, pass, None, break, except, in, raise, True, class, finally, is, return, and, continue, for, lambda, try, as, def, from, nonlocal, while, assert, del, global, not, with, async, elif, if, or, yield]

#ライブラリとモジュールとパッケージ
ライブラリはある程度まとまったよく使う処理（関数・クラスなど）を他から読み込めるようにしたファイルのこと。
（pythonではライブラリと表記があったらだいたいモジュール）

pythonコードをまとめたもので、他のプログラムから再利用できるようにしたファイルのことをモジュールという。
importすることでモジュールが使えるようになる。

パッケージは＿＿init＿＿.py(そういえばimportするか実行するかの時に毎回勝手に出来上がっていた)と複数のモジュールがディレクトリに集まったもの。

#クラスとオブジェクト
- クラス…データ構造を作る仕組み
    - 数値・文字列・リストなどもクラスから作られたオブジェクト！
    - 作るときはキャメルケース（頭文字を大文字に）
- オブジェクト…データ（属性）とメソッド（関数）を持ったもの
- インスタンス化…クラスからオブジェクトを作る事
- コンストラクタ…クラスの初期化を行うメソッド
    - ＿＿init＿＿の部分
- メソッド…クラスに定義された関数
- 継承…既存クラスを元に新しいクラスを作る仕組み
    - クラスを継承するにはクラスを()の中に書く
    - super().＿＿init＿＿()で親クラスのコンストラクタを呼ぶ
- 多重継承…複数の親クラスから継承する事
- オーバーライド…メソッドを独自の機能で上書きする事
phpで配列にエラー文を追加したい

phpでお問い合わせフォームを作りながら学習しているのですが、送信ボタンを押された時のエラー表示で躓いたので、学習した内容をメモします！

## 作りたいもの
- お問い合わせフォーム
- 名前入力欄が空白の場合は、エラー文「お名前を入力して下さい」
- メールアドレス欄が空白の場合は、エラー文「メールアドレスを入力して下さい」
- 上記のエラーを配列に入れて表示したい

## phpで配列にエラー文を追加する方法
調査した結果、配列にエラー文を追加するには、以下の２種類の方法があるみたいです！

- 角カッコ[]を使用する方法
- array_push()関数を使用する方法

今回は、角カッコを使用して実装してみたいと思います！

ソースコード

```php:ソースコード
<?php
  $errors = [];
  if(empty($_POST['name'])){
    $errors[] = "お名前を入力して下さい";
  }

  if(empty($_POST['mail'])){
    $errors[] = "メールアドレスを入力して下さい";
  }
?>
```

上記のように実装したところ、無事、配列にエラー文が格納されました!

## 参考にしたサイト
[phpで配列に要素を追加する方法まとめ](http://skillcamp.tech/blog/?p=315)
Javaのバージョン確認


**・インストールしたJavaのバージョンを確認をしたい時**
windowsの場合
コマンドプロンプトを開く
macの場合
ターミナルを開く

「java -version」のコマンドをコピーして貼り付け。
下のように表示されます。

```
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
```

**・確認方法**
「java version」の直後のダブルクォートで囲まれた部分（1.8.0_131）がバージョンです。
「Java HotSpot(TM) 64-Bit」が64ビット版。64ではない場合は32ビット版です。

記事の掲載理由
環境構築の際に、既にインストールされているJavaが64bitなのか32bitなのか気になったため記載しました。
heroku + PHP + SendGrid環境でメール送信するのに詰まったメモ

# はじめに
自作サイトをherokuにアップしたものの、PHPのmb_send_mail()が動かなかった。
調べてみたところ、そもそもherokuのデフォルト設定ではメール送信には対応してないとのこと。

https://qiita.com/negi3d/items/2714534897f90915d392
上記記事を参考に、SendGridアドオンの導入→APIキーの取得云々を済ませコードを追加しても、動かず手詰まりに。
```heroku logs --tail```
でlogを見てみると、
SendGrid\Emailなんてものはないですよ、と怒られている模様。

# 解決策
SendGridの公式サポートサイトを確認した。
https://sendgrid.kke.co.jp/docs/Integrate/Code_Examples/v3_Mail/php.html
現在はSendGrid\EmailではなくSendGrid\Mailを利用するのが正しいようだ。

```php:send.php
<?php
      require 'vendor/autoload.php';

      $email = new \SendGrid\Mail\Mail();
      $email->setFrom("test@example.com", "Example User");
      $email->setSubject("Hello from SendGrid");
      $email->addTo("test@example.com", "Example User");
      $email->addContent("text/plain", "Hello world");
      $sendgrid = new \SendGrid(getenv('SENDGRID_API_KEY'));
      try {
          $response = $sendgrid->send($email);
          print $response->statusCode() . "\n";
          print_r($response->headers());
          print $response->body() . "\n";
      } catch (Exception $e) {
          echo 'Caught exception: '. $e->getMessage() ."\n";
      }
?>
```
ブロックチェーン上に読書感想文を書けるサービス作った

# TL;DR

ブロックチェーンを利用したDappsの開発を勉強中です。
一度サンプルアプリケーションを作ってみたかったので作りました。
とりあえずざっくり作りたかったのでいろいろ適当です。


#サービス概要

https://iread-decent.herokuapp.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114040/4f1e1079-82ae-c181-a049-21b60477b8fe.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114040/eb195c94-1b13-6dbf-9b69-474c47aa845e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114040/d1f55518-393e-de4e-56cf-3e2f4030ab5d.png)



サービス名は「IRead」としました。
いろいろ勉強で本を読むのですが、読むだけで終わってしまい、読んで得た知見・学んだことを共有できずにいました。
そこでIReadを使って本を読んだ感想文をブロックチェーン上に記録することで、学びの証跡を残せ、それを自分の公開鍵で自分の学びであることを証明できます。


# 解説

## GitHub

https://github.com/theMistletoe/IRead

## 使用した技術

* Truffle
* solidity
* react（Next.js）

## 工夫した点

### solidity

https://github.com/theMistletoe/IRead/blob/master/contracts/BookReportToken.sol

肝となるコントラクトコードについてはERC721の規格を継承しています。
OpenZeppelinのコードを継承する形ですね。


このERC721に準拠したsolidityのコードを書く正解がちょっと分かりませんでした。
同じように他の方のERC721トークンの実装を見ると継承しているものの、コントラクトの属性を継承した子のフィールドに直接もってやり取りしているようだったので、それだとonlyOwner制約などの恩恵を受けられないのではと思いました。

なので今回はアプリケーションの属性についてはトークンのメタ情報（tokenURI）にJSON形式で保持することにしました。


実装方針が正しいかどうかは不明なので詳しい方がいれば教えてください。

### react

https://github.com/theMistletoe/IRead/blob/master/client/comps/AllReports.js


reactについてはてんで素人で書いたので間違い・不正があれば突っ込んでください笑

一点だけ、全トークンを表示するときに、トークンがburnされているとトークンlengthが合わなくなって全件取得できなかったので、
burnされたトークン含め過去発行されたトークンの総数の取得をTrensferイベントから取得しています。
（burnされるとtotalSupply関数で取得されるトークン数も-1される）



# 参考

- https://qiita.com/shiki_tak/items/f4c9f6ef80a9347daf03
- https://truffleframework.com/boxes/react
- https://nextjs.org/learn/basics/getting-started
- https://reactjs.org/tutorial/tutorial.html
- https://kognise.github.io/water.css/
[追記あり]Backlogで特定ユーザーが担当者の未完了課題一覧を取得するシェル 

未完了のBacklogの課題を一覧したいとき、担当者が自分のものであればダッシュボードで確認できますが、他メンバーの課題を ~~プロジェクト跨いで画面から確認できなかったので~~ 、APIを用いて抽出しました。

**追記:プロジェクトを跨いで検索できました。**
画面上部右上の ... から
<img width="165" alt="スクリーンショット 2019-09-10 18.48.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/c79f1761-80e2-7803-8e34-bed7e7b16747.png">

ただ削除済みのメンバーは選択できず。urlのcondition.assignerId=で直接指定すればいけるかも（未検証）


課題の引き継ぎ漏れがないかなどをプロジェクト横断してチェックするのに使えます。 **異動などで無効化したユーザーが担当者のままの課題** も検索できました。

シェルでcurl打ってるだけですが共有します。

# 未完了課題一覧の取得

## インプット

スペースID、APIキー、対象ユーザーIDがわかれば利用できます。

 - スペースID =  [スペースIDとは？](https://backlog.com/ja/support/general/what-id/)
 - APIキー = [APIの設定](https://backlog.com/ja/help/usersguide/personal-settings/userguide2378/)
 - ユーザーID = 10XXXXXXXX みたいな数字のやつ。ユーザ情報から見れる「tarou」のようなIDではない。

ユーザーIDは、ちょっとややこしいので [別の記事](https://qiita.com/cof123/items/d2f472d3ab9b6a685908) にしました

## スクリプト

[Backlog API:課題一覧の取得](https://developer.nulab.com/ja/docs/backlog/api/2/get-issue-list/) を叩くだけです。

```shell:issue_list_by_user.sh
#!/usr/bin/env bash

# parameter
if [ $# -ne 3 ]; then
    CMDNAME=`basename $0`
    echo "Usage: $CMDNAME <space> <api-key> <user_id>" 1>&2
    exit 1
fi
SPACE=$1
API_KEY=$2
USER_ID=$3

# execute
url="https://${SPACE}.backlog.jp/api/v2/issues?apiKey=${API_KEY}&assigneeId[]=${USER_ID}&statusId[0]=1&statusId[1]=2&statusId[2]=3"
curl --globoff ${url}

exit 0
```

> assigneeId[]=${USER_ID}

これで指定ユーザーが担当者の課題のみを抽出しています。

> statusId[0]=1&statusId[1]=2&statusId[2]=3

これで未完了(未処理、処理中、処理済み）の課題のみを抽出しています。

### 呼び出し

「スペースID」「APIキー」「ユーザーID」を指定して実行

```shell:
$ sh issue_list_by_user.sh xxx ffffffffffffffff 10xxxxxxxxxx
```

実行するとレスポンスがjson形式でドバッと出ます。
いったんファイルに保存するなりjq使うなりで整形すると確認しやすいです。

```shell:
$ sh issue_list_by_user.sh xxx ffffffffffffffff 10xxxxxxxxxx | jq '.[] | {issueKey, summary, updated, status }'
```

上記のjqを通した場合の出力例

```json:
{
  "issueKey": "TEST_PJ-10",
  "summary": "追加機能Aについて",
  "updated": "2019-05-01T10:00:000",
  "status": {
    "id": 2,
    "name": "処理中"
  }
}
{
  "issueKey": "TEST_PJ-11",
  "summary": "追加機能Bについて",
  "updated": "2019-05-10T10:00:000",
  "status": {
    "id": 1,
    "name": "未対応"
  }
}
{
  "issueKey": "XXX-21",
  "summary": "打ち合わせ",
  "updated": "2019-03-01T10:00:000",
  "status": {
    "id": 3,
    "name": "処理済み"
  }
}
```

# 留意点

検索できる課題は、APIキーを発行したユーザーが参加しているプロジェクトのみ。
BacklogユーザーID(10XXXXXXXXのような数字)の調べかた by シェル

BacklogAPIでユーザーIDを指定して情報を取得する場合のユーザーIDは
ユーザ情報から見れる「tarou」のようなIDではなく、10XXXXXXXX のような数字のほうのIDを指定してやる必要があります。

これが画面からは確認できなかったのでAPIを叩いて確認します。


# 方法

方法として思いつくのは

- (1) ユーザー一覧から取得
- (2) 特定プロジェクトのユーザー一覧から取得
- (3) 課題からユーザー取得

の３つ

それぞれ以下の制限があります。

> (1) ユーザー一覧から取得

これは管理者権限がないと取得できません。
(管理者権限をもつユーザーが発行したAPIキーが必要)

> (2) 特定プロジェクトのユーザー一覧から取得

管理者権限がなくても取得できます。
ただ、登録解除したユーザーのIDは取得できません。

> (3) 課題からユーザー取得

管理者権限がなくても取得できます。
登録解除したユーザーのIDも取得できました。
目的のユーザーが更新したことのある課題をみつけて指定してやる必要があります。

# 指定するパラメータについて

スペースIDとAPIキーの指定が必要ですが、それについては以下を参照ください。

 - スペースID =  [スペースIDとは？](https://backlog.com/ja/support/general/what-id/)
 - APIキー = [APIの設定](https://backlog.com/ja/help/usersguide/personal-settings/userguide2378/)

# (1) ユーザー一覧から取得

管理者権限が必要。
で、私は管理者権限を持っていないので、この方法は試せていません。

なので動作確認できてませんがシェルだけ書いたので、権限持ってる人で試しもらえると嬉しいです。 :relaxed:

[Backlog API:ユーザー一覧の取得](https://developer.nulab.com/ja/docs/backlog/api/2/get-user-list/) を叩くだけ。

```shell:user_list.sh
#!/usr/bin/env bash

# parameter
if [ $# -ne 2 ]; then
    CMDNAME=`basename $0`
    echo "Usage: $CMDNAME <space> <api-key>" 1>&2
    exit 1
fi
SPACE=$1
API_KEY=$2

# execute
url="https://${SPACE}.backlog.jp/api/v2/users?apiKey=${API_KEY}"
curl --globoff ${url}

exit 0
```

「スペースID」「APIキー」を指定して実行

```shell:
$ sh user_list.sh xxx ffffffffffffffff
```

# (2) 特定プロジェクトのユーザー一覧から取得

[Backlog API:プロジェクトユーザー一覧の取得](https://developer.nulab.com/ja/docs/backlog/api/2/get-project-user-list/) を叩くだけ。

```shell:project_user_list.sh
#!/usr/bin/env bash

# parameter
if [ $# -ne 3 ]; then
    CMDNAME=`basename $0`
    echo "Usage: $CMDNAME <space> <api-key> <projectIdOrKey>" 1>&2
    exit 1
fi
SPACE=$1
API_KEY=$2
projectIdOrKey=$3

# execute
url="https://${SPACE}.backlog.jp/api/v2/projects/${projectIdOrKey}/users?apiKey=${API_KEY}"
curl --globoff ${url}

exit 0

```

「スペースID」「APIキー」「プロジェクトIDまたはキー」 を指定して実行

```shell:
$ sh project_user_list.sh xxx ffffffffffffffff TEST_PJ
```

この記事ではシェルで書いていますが、
phpであれば [この記事](https://qiita.com/d2cdot-mmori/items/d2697778b6765d994bd1) が同じ方法で、わかりやすく書かれていました。

# (3) 課題からユーザー取得

[Backlog API:課題情報の取得](https://developer.nulab.com/ja/docs/backlog/api/2/get-issue/#) を叩くだけ。

```shell:issue_detail.sh
#!/usr/bin/env bash

# parameter
if [ $# -ne 3 ]; then
    CMDNAME=`basename $0`
    echo "Usage: $CMDNAME <space> <api-key> <issueIdOrKey>" 1>&2
    exit 1
fi
SPACE=$1
API_KEY=$2
issueIdOrKey=$3

# execute
url="https://${SPACE}.backlog.jp/api/v2/issues/${issueIdOrKey}?apiKey=${API_KEY}"
curl --globoff ${url}

exit 0
```

「スペースID」「APIキー」「課題IDまたはキー」を指定して実行

```shell:
$ sh project_user_list.sh xxx ffffffffffffffff TEST_PJ-100
```

ドバッと課題コメントの履歴や担当者情報などが取れます。その中にあるassigneeのidなどからユーザーIDを特定可能です。
(No.4) おじさんが、何を開発するのか目標を立てるよ

# 前回までのあらすじ
- GitHubを利用して、おじさんの成果物を公開する準備が整いつつあるよ
    - GitHubにユーザを登録したよ。
        - [(No.1) おじさんが、Git・GitHubを利用できるようにしてみる - GitHubにユーザを登録する](https://qiita.com/resojisan/items/4cd09b7a5f33ca8a925d)
    - GitHubを利用してみた。
        - [(No.2) おじさんが、Git・GitHubを利用できるようにしてみる - GitHubを利用してみる](https://qiita.com/resojisan/items/75dcc83ea55af0db329f)
    - GitHub上のリポジトリを複製（クローン）することが出来たよ。
        - [(No.3) おじさんが、Git・GitHubを利用できるようにしてみる - GitHubからリポジトリを複製（クローン）する](https://qiita.com/resojisan/items/f119d8b71e3bba9eadec)


# 今回の目的・背景
- GitHubでおじさんの成果物を公開する準備が整いつつあるけど、おじさんには肝心の成果物が無いんだよ（汗）。
- そもそも、おじさん。プログラミングで何をつくりたいのか、漠然としてたよ。
- 目標がないと、心が折れそうだから、何を開発するのか目標を決めてみるよ。
- おじさん、何かやるって宣言しないと、すぐにゴロゴロして、気が付いたら朝になってるから、覚悟して宣言するよ。
- 最近、脂汗がひどいよ（涙）。お風呂に入っても入っても、脂汗が出てくるよ。

# 目標
- みんなLINEやら、何やらメッセージを送信するアプリを使っているけど、似たようなものを開発してみたいと思うよ。
- もちろん、おじさんのスマートフォンにもLINEはインストールされているよ（照）。
- でも、おじさんには友達がいないから、毎日LINE Payや、LINEスタンプの宣伝しか送られてこないよ（涙）。
- 宣伝や広告でも通知が来ると、なんだか、おじさん嬉しいよ。
- いつか、宣伝や広告以外が送られてくることを祈っているよ。だからLINEはアインインストールすることが出来ないよ。
- あれだけ多くの人が利用しているものを、おじさんも開発することが出来るなら、おじさん、何か変われる気がするんだよ。

# 影響を受けた記事
- おじさん得意の[ネットサーフィン](https://www.weblio.jp/content/%E3%83%8D%E3%83%83%E3%83%88%E3%82%B5%E3%83%BC%E3%83%95%E3%82%A3%E3%83%B3)（照）で、次の記事をみつけたのが発端だよ。
    - [1ヶ月でLINEクローンを開発！LINEの新卒エンジニア技術研修をご紹介](https://engineering.linecorp.com/ja/blog/detail/150/)
        - この記事からは、人をとても大切にする会社だって、おじさん感じたよ（涙）。
        - おじさんが若かったとき、「人を大切にする会社は生き残るんだ」って、親父がいつも言ってたよ。それを思い出したよ（涙）。
- 研修の目標が明確だったから、おじさんの目標にも利用出来るかと考えたんだよ。
- おじさんはいつも自分で何も生み出さないから、このような素敵な事例があると嬉しいよ。


# とはいえ、何から手をつければ良いのか・・・
- おじさん、「開発の基本のキ」も知らないので、おじさんのお得意のネットサーフィンで調べてみるよ（汗）。
- 色々調べてみて、少しでも目標に近付けるようにチャレンジしてみるよ。


# 参照
[1ヶ月でLINEクローンを開発！LINEの新卒エンジニア技術研修をご紹介](https://engineering.linecorp.com/ja/blog/detail/150/)
まじか！ docker の volume にパスの長さが影響するなんて (gitlab)

## 結論

* gitlab を docker で立ち上げる時、 `--volume` のパスの長さが、長過ぎる時は気をつけろ。

## 正常起動

* 正常起動とエラーとの違いは、 volume のパス。
    * 正常起動: `${HOME}/Downloads` 
    * エラー: `${PWD}` 
* HOME と PWD を展開した時の長さが全然違う。(今回の場合の桁数)
    * 正常起動(HOME): 14 バイト
    * エラー(PWD): 83 バイト

```shell
docker run --detach \
  --hostname localhost \
  --publish 10080:80 \
  --publish 10022:22 \
  --name gitlab \
  --restart always \
  --volume ${HOME}/Downloads/gitlab/config:/etc/gitlab \
  --volume ${HOME}/Downloads/gitlab/logs:/var/log/gitlab \
  --volume ${HOME}/Downloads/gitlab/data:/var/opt/gitlab \
  gitlab/gitlab-ce:latest
```

## エラー

```shell
docker run --detach \
  --hostname localhost \
  --publish 10080:80 \
  --publish 10022:22 \
  --name gitlab \
  --restart always \
  --volume ${PWD}/gitlab/config:/etc/gitlab \
  --volume ${PWD}/gitlab/logs:/var/log/gitlab \
  --volume ${PWD}/gitlab/data:/var/opt/gitlab \
  gitlab/gitlab-ce:latest
```

* エラー内容

```
Error executing action `run` on resource 'bash[migrate gitlab-rails database]'
```

```
There was an error running gitlab-ctl reconfigure:

bash[migrate gitlab-rails database] (gitlab::database_migrations line 51) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1'
---- Begin output of "bash"  "/tmp/chef-script20190521-24-51lpum" ----
STDOUT: rake aborted!
PG::ConnectionBad: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/opt/gitlab/postgresql/.s.PGSQL.5432"?
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:55:in `block (3 levels) in <top (required)>'
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Tasks: TOP => gitlab:db:configure
(See full trace by running task with --trace)
STDERR: 
---- End output of "bash"  "/tmp/chef-script20190521-24-51lpum" ----
Ran "bash"  "/tmp/chef-script20190521-24-51lpum" returned 1
```
【JavaScript】動画倍速機能の実装

Wordpressのプラグインで、動画倍速ってないんですね。
これを元に開発しようかな。

## 動画（音声）を倍速にする機能（ボタンクリック）

```html:index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="main.js"></script>
</head>
<body>
    <output id="res">
        <video src='/Users/matsumurashun/Downloads/pu-tyan.mp4' width='500' height='300' controls loop></video>
        <form>
            <input type="button" value="1倍速">
            <input type="button" value="2倍速">
            <input type="button" value="3倍速">
        </form>
    </output>    
</body>
</html>
```

```javascript:main.js
window.onload = () => {
    const btn = document.getElementsByTagName("input");
    const video = document.getElementsByTagName("video")[0];

    btn[0].addEventListener('click', () => {
        video.playbackRate = 1.0;
        video.defaultPlaybackRate = 1.0;
    }, false);

    btn[1].addEventListener('click', () => {
        video.playbackRate = 2.0;
        video.defaultPlaybackRate = 2.0;
    }, false);

    btn[2].addEventListener('click', () => {
        video.playbackRate = 3.0;
        video.defaultPlaybackRate = 3.0;
    }, false);
}
```

## 動画（音声）を倍速にする機能（プルダウン選択）
```html:index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="main.js"></script>
</head>
<body>
    <output id="res">
        <video src='/Users/matsumurashun/Downloads/pu-tyan.mp4' width='500' height='300' controls loop></video>
        <form>
            <select>
                <option value="1">1倍速</option>
                <option value="2">2倍速</option>
                <option value="3">3倍速</option>
            </select>
        </form>
    </output>    
</body>
</html>
```

```javascript:main.js
window.onload = () => {
    const selector = document.getElementsByTagName("select")[0];
    selector.addEventListener('change', (it) => {
        video.playbackRate = setRate(it.target.value);
    });
    const setRate = (val) => {
        return Number(val);
    }
}
```

`playbackRate`:再生速度の倍率
`Number`:`Number`オブジェクトで、引数に入れれば文字列を数値に変換してくれる