OmniAICreator/Qiita-1.07M huggingface dataset:
Node-REDをsystemdでサービス化

# Node-REDをsystemdでサービス化
Node-REDユーザ会に掲載されているリンクにあるsystemdで登録するやつでは動きませんでしたので、
動くやつにしました。

以下の環境で実行しました。

- CentOS 7
- NVMでnode.jsをバージョン管理
- node.jsのバージョンはv8.10.0
- 何も考えずroot

systemdに登録するファイルを作成

```shell-session
$ vi /etc/systemd/system/node-red.service
```
ファイルの中身。
インストールしたnode.jsのバージョンが違う人は書き換えてください。

```properties
[Unit]
After=syslog.target network.target
Documentation=http://nodered.org/

[Service]
Environment="NODE_OPTIONS=--max-old-space-size=128"
Environment="NODE_RED_OPTIONS=-v"
ExecStart=/root/.nvm/versions/node/v8.10.0/bin/node $NODE_OPTIONS /root/.nvm/versions/node/v8.10.0/lib/node_modules/node-red/red.js $NODE_RED_OPTIONS
WorkingDirectory=/root/.node-red/
User=root
Group=root
Nice=10
SyslogIdentifier=Node-RED
StandardOutput=syslog
Restart=on-failure
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target
```

再読込みさせて終わり。

```shell-session
$ systemctl daemon-reload
$ systemctl start node-red
$ systemctl status node-red -l
● node-red.service - Node-RED is a tool for wiring together hardware devices, APIs and online services in new and interesting ways.
   Loaded: loaded (/etc/systemd/system/node-red.service; disabled; vendor preset: disabled)
   Active: active (running) since 水 2018-03-14 16:44:46 JST; 11min ago
     Docs: http://nodered.org/
 Main PID: 3619 (node-red)
   CGroup: /system.slice/node-red.service
           mq3619 node-red                                                      

 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [warn] [node-red/rpi-gpio] Info : Ignoring Raspberry Pi specific node
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [warn] ------------------------------------------------------
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [info] Settings file  : /root/.node-red/settings.js
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [info] User directory : /root/.node-red
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [warn] Projects disabled : set editorTheme.projects.enabled=true to enable
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [info] Flows file     : /root/.node-red/flows_Node-RED.json
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [info] Creating new flow file
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [info] Starting flows
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [info] Started flows
 3月 14 16:44:47 Node-RED Node-RED[3619]: 14 Mar 16:44:47 - [info] Server now running at http://127.0.0.1:1880/
```
Oracle Database Cloud Serviceのクラウド・ツールの更新が必要

#問題点
Oracle Database Cloud Service(DBCS)はPaaSサービスなので、バックアップやパッチ適用を管理画面から実行できるようになっています。
これは、

* Oracle Cloudの管理画面
* データベースサーバー上にインストールされたツール

で成り立っています。
Oracle Cloudの管理画面は頻繁に更新されますが、データベースサーバー内のツールは自動的に更新されないため、手動で更新しないといけません。
（古いバージョンのツールには、不要なバックアップファイルが削除されない、管理画面の操作が反映されないといったバグがあります）

---

### 2018/10/31 追記 

* 自動更新ができるようになっていました（いったん手動で自動更新ありバージョンまで更新する必要があります）

```
# dbaascli patch tools auto enable
```

https://docs.oracle.com/en/cloud/paas/database-dbaas-cloud/csdbi/configure-automatic-cloud-tooling-updates.html

---

#解決方法
* データベースサーバー内のツールを手動更新する（下記の方法はRACデータベースでは利用できません）

１. opcユーザーでデータベースサーバーにログインする
２. rootユーザーのシェルを起動

```
$ sudo -s
```

３. 最新版ツールが存在するか確認する

```
# dbaascli dbpatchm --run -list_tools
```

既に最新版がインストールされている場合は、以下のように表示されます

```
No applicable dbaastools rpms found
dbpatchm Execution completed
```

より新しいツールが存在する場合、一覧表示されます

```
Patchid : 17.4.5.0.0_171120.1542
Patchid : 18.1.1.0.0_171130.0801
Patchid : 18.1.1.1.0_180122.0952
Patchid : 18.1.2.1.0_180215.0915
Patchid : 18.1.2.1.0_180228.1052
Patchid : 18.1.2.1.0_180301.0107
Patchid : 18.1.2.1.0_180309.0517

```

４. 最新版ツールが存在していた場合、下記のコマンド例のようにインストールをおこないます

```
# dbaascli dbpatchm --run -toolsinst -rpmversion=18.1.2.1.0_180309.0517
```

５. 現在のバージョンは以下のコマンドで確認できます

```
# rpm -qa | grep -i dbaastools
dbaastools-1.0-1+18.1.2.1.0_180309.0517.x86_64
```
RecyclerViewで最後までスクロールしたのを検知する

メモ

```kotlin
    binding.recycler.addOnScrollListener(object: RecyclerView.OnScrollListener() {
      override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)
        val layoutManager = recyclerView.layoutManager as LinearLayoutManager

        val visibleItemCount = layoutManager.childCount
        val totalItemCount = layoutManager.itemCount
        val pastVisibleItems = layoutManager.findFirstVisibleItemPosition()
        if (pastVisibleItems + visibleItemCount >= totalItemCount) {
          // ここで最後までスクロールした時の処理を書く
        }
      }
    })
```
Xamarin.Android でシステムボリュームが変更されたことを検知する

teratail に投稿された質問への回答ですが、こちらにも貼っときます。

* [Android - Xamarin Android システムの音量のの値が変更されたことを知りたい．(117267)｜teratail](https://teratail.com/questions/117267)

Stackoverflow の回答にある Java-Android のコードを、 Xamarin.Android 用に少し「書き換え」ただけです。

* [android - Is there a broadcast action for volume changes? - Stack Overflow](https://stackoverflow.com/questions/6896746/is-there-a-broadcast-action-for-volume-changes/17398781#17398781)

```csharp
// MainActivity.cs
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Content;

namespace VolumeSample
{
    [Activity(Label = "VolumeSample", MainLauncher = true, Icon = "@mipmap/icon")]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            this.ApplicationContext.ContentResolver.RegisterContentObserver(
                Android.Provider.Settings.System.ContentUri, true, 
                new VolumeObserver(this, new Handler()));
        }
    }

    internal class VolumeObserver : Android.Database.ContentObserver
    {
        private readonly Context context;

        public VolumeObserver(Context context, Handler handler) : base(handler)
        {
            this.context = context;
        }

        public override void OnChange(bool selfChange)
        {
            base.OnChange(selfChange);

            var audioManager = (Android.Media.AudioManager)context.GetSystemService(Context.AudioService);
            var volume = audioManager.GetStreamVolume(Android.Media.Stream.System);
            Toast.MakeText(context, 
                           $"Current System Vol: {volume}", 
                           ToastLength.Short).Show();
        }
    }
}
```

``BroadcastReceiver`` を使うことでも実現できるようですね。
Project Euler 51「素数の桁置換」

問の意味を理解するのに一苦労だったのでほんのり補足書換してます。
結構遅い（2分弱）けど、脳ミソが痛いのでギブアップ。

# Problem 51 「素数の桁置換」
2桁の数○3の第1桁を置き換えることで 13, 23, 43, 53, 73, 83という6つの素数が得られる。
56○○3の第3桁と第4桁を同じ数で置き換えることを考えよう. この5桁の数は7つの素数をもつ最初の例である: 56003, 56113, 56333, 56443, 56663, 56773, 56993. 
よって, この族の最初の数である56003は, このような性質を持つ最小の素数である.
桁を同じ数で置き換えることで8つの素数が得られる最小の素数を求めよ. (注:連続した桁でなくても良い)

```python
# memo : 1の位を置き換えても8つの素数が得られることはない

from itertools import count, combinations

def hoge(num):
    checked = []
    for n in count(11, 2):
        if n % 5 == 0 or n in checked: continue
        l = list(str(n))
        for i in range(1, len(l)):
            # 何番目を何個置き換えるかの組み合わせ
            for c in combinations(( j for j in range(len(l)-1) ), i):
                lst_ans = []
                for k in list('0123456789'):
                    # 第1桁を0に置き換えることがないように
                    if c[0] == 0 and k == '0': continue
                    N = replace_and_list2num(l, c, k)
                    checked.append(N)
                    if is_prime(N):
                        lst_ans.append(N)
                    if len(lst_ans) == num:
                        #print(lst_ans)
                        return sorted(lst_ans)[0]

def replace_and_list2num(l, c, num):
    L = list(l) # 参照渡しをしないように
    for i in c: L[i] = num
    return int(''.join(L))

def is_prime(n):
    if n < 2: return False
    if n == 2: return True
    if n % 2 == 0: return False
    return all(n % i != 0 for i in range(3, int(n ** 0.5) + 1, 2))

print(hoge(8))
```
Thymeleafのfragmentで引数にデフォルト値を設定する方法

#備忘録

サンプル：デフォルト値設定

```html
<th:block th:fragment="frag(hoge)" th:with="hoge = ${hoge} ?: 'default'">
    <span th:text="${hoge}">hello</span>
</th:block>
```

```html:結果
<span>default</span>
```

#参考

[Allow fragment parameters to have default values #350](https://github.com/thymeleaf/thymeleaf/issues/350)
Dockerで起動しているMongoDBにリストアする


```
docker run --rm --link mongo_mongodb_1:mongo -v /var/www/mongo/backup/:/backup --network mongo_default mongo:3.2 bash -c 'mongorestore --db ${DATABASE_NAME} --host mongo /backup'
```

## オプションの説明

### --rm

```
--rm
```

今回走らせるdockerコンテナがexitしたときに、コンテナを削除する

### --link

```
--link mongo_mongodb_1:mongo
```

（container_name:ALIAS）
起動中のコンテナmongo_mongodb_1にmongoとして接続できるようにしている

`docker ps`したときに表示されるNAMESを指定している

```
$ docker ps
CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS                          PORTS                                      NAMES
79412c85455e        mongo-express                            "tini -- node app"       19 hours ago        Up 19 hours                     8081/tcp                                   mongo_mongo-express_1
d2381e8d539c        jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   19 hours ago        Up 19 hours                                                                letsencrypt-nginx
ecf74e818b8e        jwilder/nginx-proxy                      "/app/docker-entrypo…"   19 hours ago        Up 19 hours                     0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   nginx-proxy
88085298f1e5        mongo:3.2                                "docker-entrypoint.s…"   41 hours ago        Up 19 hours                     0.0.0.0:27017->27017/tcp                   mongo_mongodb_1
```

### -v

```
-v /var/www/mongo/backup/:/backup
```

今回走らせるdockerコンテナ内の`/backup`にホストの`/var/www/mongo/backup/`をマウントしている

backupディレクトリの中身は、以下のようになっている

```
$ ls -l backup/
合計 203496
-rw-r--r-- 1 admin admin     17545  3月 14 10:44 admin-sessions.bson
-rw-r--r-- 1 admin admin       200  3月 14 10:44 admin-sessions.metadata.json
-rw-r--r-- 1 admin admin     12507  3月 14 10:44 authors.bson
.
.
.
-rw-r--r-- 1 admin admin        92  3月 14 10:47 userinfos.metadata.json
-rw-r--r-- 1 admin admin     29198  3月 14 10:47 users.bson
-rw-r--r-- 1 admin admin        88  3月 14 10:47 users.metadata.json
```

### --network

```
--network mongo_default
```

もし、mongoが別ネットワーク上で起動している場合は、このオプションで、mongoが起動しているネットワークに接続する

### 実行コマンド

```
bash -c 'mongorestore --db ${DATABASE_NAME} --host mongo /backup'
```

`--link`で接続した`mongo`に、`--host mongo`で接続して、
`${DATABASE_NAME}`にリストアしている

## 確認

バックアップデータをDocker内のMongoDBにリストアできたか確認します。

まずは、MongoDBコンテナ内に入る

```
$ docker exec -it mongo_mongodb_1 bash
root@88085298f1e5:
```

mongoシェルに入って、データベースがあるか確認

```
root@88085298f1e5:/# mongo
MongoDB shell version: 3.2.19
connecting to: test

> show dbs		# データベース一覧を表示する
${DATABASE_NAME}	0.195GB
local         		0.000GB
```

無事、リストアできていることが確認できました。

あとは、実行コマンドを`init.sh`のようなシェルスクリプトにしてしまえば、開発環境の構築がラクになりそうですね！
HumHubでのLoggerの使い方

## 概要
HumHubでのLoggerの使い方を公式ドキュメントで調べようと思ったら、TBDになっていた。

- [HumHub Documentation](http://docs.humhub.org/admin-logging.html)

Yiiのドキュメントで調べて、`Yii::debug()`を使おうとしたら、
`Error: Call to undefined method Yii::debug()` になった。

- [The Definitive Guide to Yii 2.0](http://www.yiiframework.com/doc-2.0/guide-runtime-logging.html)

なので、HumHubのLoggerのソースを調べてみた。

## 関連
- [HumHubというCMSを使ってSNSを秒で作る](https://qiita.com/Esfahan/items/974687234566ef6b069d)

## ソースを追ってみる
ソースを調べて見たところ、debugは使えないみたい。

protected/vendor/yiisoft/yii2/log/Logger.php

```php
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\log;

use Yii;
use yii\base\Component;

/**
 * Logger records logged messages in memory and sends them to different targets if [[dispatcher]] is set.
 *
 * A Logger instance can be accessed via `Yii::getLogger()`. You can call the method [[log()]] to record a single log message.
 * For convenience, a set of shortcut methods are provided for logging messages of various severity levels
 * via the [[Yii]] class:
 *
 * - [[Yii::trace()]]
 * - [[Yii::error()]]
 * - [[Yii::warning()]]
 * - [[Yii::info()]]
 * - [[Yii::beginProfile()]]
 * - [[Yii::endProfile()]]
 *
 * For more details and usage information on Logger, see the [guide article on logging](guide:runtime-logging).
 *
 * When the application ends or [[flushInterval]] is reached, Logger will call [[flush()]]
 * to send logged messages to different log targets, such as [[FileTarget|file]], [[EmailTarget|email]],
 * or [[DbTarget|database]], with the help of the [[dispatcher]].
 *
 * @property array $dbProfiling The first element indicates the number of SQL statements executed, and the
 * second element the total time spent in SQL execution. This property is read-only.
 * @property float $elapsedTime The total elapsed time in seconds for current request. This property is
 * read-only.
 * @property array $profiling The profiling results. Each element is an array consisting of these elements:
 * `info`, `category`, `timestamp`, `trace`, `level`, `duration`, `memory`, `memoryDiff`. The `memory` and
 * `memoryDiff` values are available since version 2.0.11. This property is read-only.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Logger extends Component
{

/* snip */
```

## Usage
### ショートカットメソッドを使う場合

```php
use Yii;

Yii::trace('This is trace');
Yii::error('This is error');
Yii::warning('This is warning');
Yii::info('This is info');
Yii::beginProfile('This is beginProfile');
Yii::endProfile('This is endProfile');
```

### Logger instanceを使う場合

```php
use Yii;

$logger = Yii::getLogger();
// error
$logger->log('This is error', 1);
// warning
$logger->log('This is warning', 2);
// info
$logger->log('This is info', 3);
```

## ログの出力場所
以下のいずれかで、出力されたログを確認できる

- DBのlogテーブル
- https://サイトドメイン/admin/logging


## sqlのdebug方法
参考：https://www.yiiframework.com/wiki/857/show-raw-sql-query

```php
echo $query->createCommand()->sql;
```

```php
echo $query->createCommand()->getRawSql();
```
environment環境を用いた図・式挿入環境の簡略表記

卒業論文の執筆をし，よく使うLaTeX環境を自己定義環境で簡略表記できないかと思案．とりあえず式と図でうまくいったのでまとめておく．

#図
\begin{document}より前に

```tex:shiki.tex
\newenvironment{shiki}[2]{\begin{equation} #1 \label{eq:#2}}{\end{equation}}
```

と記述．引数は式の内容(#1)とラベル(#2)

本文中では，

```tex:shiki.tex
\begin{shiki}{式の中身}{ラベル名}
\end{shiki}
```

のように書けばよい．

#図
同様に，プリアンブル部に

```tex:zu.tex
\newenvironment{zu}[4]
{\begin{figure}[H] \centering \includegraphics　
[width=#1,pagebox=mediabox,clip,keepaspectratio]{#2} 
\caption{#3} \label{fig:#4}}{\end{figure}}
```

と記述．引数は幅(#1)，図のディレクトリ(#2)，キャプション名(#3)，ラベル(#4)

本文では

```tex:zu.tex
\begin{zu}{幅}{図のディレクトリ}{キャプション}{ラベル}
\end{zu}
```

とすればうまくいく．

式の"eq:"の部分や図のバウンディングボックス，アスペクト比の維持などの指定をいちいち書かなくてよくなる分は効率化が図られる（？）


#参考文献
[［改訂第7版］LaTeX2ε美文書作成入門](http://gihyo.jp/book/2017/978-4-7741-8705-1 "［改訂第7版］LaTeX2ε美文書作成入門")
NetCDF > 異なるサイズの.ncファイル | 同じncdump結果 > NetCDFのバージョン3と4の違い

```txt:動作環境1
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
NCAR Command Language Version 6.3.0
for WRF3.7.1, WPS3.7.1
  openmpi-1.8.x86_64 とその-devel
  mpich.x86_64 3.1-5.el6とその-devel
  gcc version 4.4.7 (とgfortran)
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

```txt:動作環境2
CentOS 6.8 (64bit)
  - on VMWare workstation
  - ホスト側はCore i7-6700
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
```

### 症状

WRF(Weather Research and Forecasting Model)とその前処理であるWPS、およびWRFの後続処理のF***T関連。

動作環境1で動いていたのと同じ環境を動作環境2で構築中。

WRFの処理結果までは同じであることは確認済。

F***Tで生成される.ncファイルに違いがある。

原因の切り分けのために試しに以下を実施してみた。

1. 動作環境2でビルドした実行ファイルF***Tを動作環境2で実行 (original)
2. 動作環境1でビルドした実行ファイルF***Tを動作環境2で実行 (copied)
    - 動作環境2にコピーして実行
3. 動作環境1でビルドした設定で、動作環境2でビルドしたファイルF***Tを動作環境3で実行 (sameConfig)
    
以下のファイルが得られた。

```bash
$ ls -l FXXXXXT_*
-rw-rw-r--. 1 wrf wrf 1536636 Mar 14 08:46 FXXXXXT_copied
-rw-rw-r--. 1 wrf wrf   50678 Mar 14 08:44 FXXXXXT_original
-rw-rw-r--. 1 wrf wrf 1536636 Mar 14 09:17 FXXXXXT_sameConfig
```

ファイルサイズが異なる。
一方で、ncdumpで出力される結果は同一となった。

copiedで使った実行ファイルは圧縮する機能が有効にでもなっているのだろうか?

動作環境1でビルドして動作環境1で実行した場合のファイルサイズも1536636 となっている。


### 原因

ビルドするところで以下のオプションを変えてビルドしてしまっていた。

```
#NETCDFVERSION=4
NETCDFVERSION=3
```

この設定の近辺に「Version 4は圧縮に関してずっといい」というコメントがある。

Version 3にした理由はメモに残っていない。

NetCDF-3とNetCDF-4の違いについては以下に詳しそう。
https://www.unidata.ucar.edu/blogs/developer/entry/netcdf_compression

圧縮の有無の違いはmd5sumの違いも生じさせてしまう。
Djangoのdjango_celery_beatというモジュール


Djangoつかって、
CeleryとCeleryBeatで定期的にタスクを仕込むときにハマりました。

CeleryBeat起動すると、PeriodicTaskをガンガン投げる事象が発生。
IntervalsでもCrontabsでもどっちもだめっぽい。

#### 結論
TimezoneをUTC以外つかってはいけませんでした。

`CELERY_TIMEZONE = 'Asia/Tokyo'`

参考URL：　https://github.com/celery/django-celery-beat/issues/129


以下、簡単な環境の説明です。
ざっくり以下のようなモジュールを入れてます。（PythonVersionは3.6.4です。）

```
Django==2.0.2
celery==4.1.0
django-celery==3.2.2
django_celery_beat=1.1.1

```


#### 色々調べた結果,以下のような設定に落ち着く
BrokerにはrabbitMQを使ってます。

apps/settings.py

```
（Celery系のとこだけ抜粋）
#
# Celery for periodic tasks like a cron.
#
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler'

# use rabbitmq
CELERY_BROKER_URL = 'amqp://guest:guest@localhost:5672//'
CELERY_RESULT_BACKEND = "rpc"

CELERY_ACCEPT_CONTENT = ['json']
CELERY_TIMEZONE = 'UTC'
CELERY_ENABLE_UTC = True

```


Djangoってあんまり日本語のサイトなくて辛いです。
PowerCLIでvROPSのアラートを取得


#モジュール読み込み
```powershell
Import-Module VMware.VimAutomation.vROPS
```

#接続
* 接続

```powershell
Connect-OMServer -server <サーバ名>
```

-User/-Passwordは入れないと聴いてくる


* 切断

```powershell
Disconnect-OMServer -server <サーバ名>
```

#コマンドレット確認

```powershell
Get-Command -Module VMware.VimAutomation.vROPS
```

#アラート出力
* 全アラート出力

```powershell
Get-OMAlert
```


* 条件フィルタ入れることも可能

```powershell
Get-OMAlert -Name "VM PCoIP Performance Degraded." -Criticality Critical -Impact Health
```


* ワイルドカードも使用可能

```powershell
Get-OMAlert -Name "*PCoIP*" -Criticality Critical -Impact Health
```


* 名前でwhereしてCSV出力とかも普通にPower Shellの構文で出来る

```powershell
Get-OMAlert | Where-Object {$_.Name -match "pcoip"} | Export-Csv "PATH" -Encoding Default
```
ESTK(Adobe ExtendScript Toolkit)でIllustratorのオブジェクトと対話する

# 説明想定
Illustratorとjavascriptの基本は抑えているけど、制御したいオブジェクトの調べ方がわからないってヒト。

# そもそもESTKとは
* コードの実行
* デバッグ
* コーディング

とかできる、アドビ謹製のツールです。ダウンロードは[Adobe Creative Cloudデスクトップ](https://www.adobe.com/jp/creativecloud/desktop-app.html)経由で行えます。
![creativecloud.jpeg](https://qiita-image-store.s3.amazonaws.com/0/238663/f0a052a5-48a9-23ec-2239-de3041e7728e.jpeg)

エディターとしての機能は貧弱なため、コーディングには使いづらいのが正直なところ。私はオブジェクトの調査、デバッグ、デバッグ後のちょっとしたお直しなどで使用してます。


# ESTKでオブジェクトを調べる
テキストフレームオブジェクトを例にした説明：
1.  ESTK立ち上げ
2.  次のコードをESTK入力

```js
var a = app.activeDocument.selection;
$.bp();

// 以下は説明
// 一行目
// app(オブジェクト):Illustratorアプリケーション
// activeDocument(オブジェクト):アクティブになっているドキュメント
// selection(オブジェクト):選択中の内容

// 二行目
// $(オブジェクト):デバッグ/情報出力用のオブジェクト
// bp(メソッド):ブレークポイント
```

1. ESTK左上のプルダウンで"Illustrator"を選択
![WS000001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/238663/b81ad564-bf04-bee2-acb5-4013ca8beb55.jpeg)

1. 調べたいデータをIllustratorでオープン

1. 調べたいオブジェクトを選択
![selectObj.jpeg](https://qiita-image-store.s3.amazonaws.com/0/238663/ac4d8269-0689-bf71-1cdc-8c427e9921af.jpeg)


1. ESTKのツールバーメニュー [ ウィンドウ > データブラウザ ]を選択

1. ESTK右上にある▶ボタンでスクリプトを実行
![WS000001 - コピー.jpeg](https://qiita-image-store.s3.amazonaws.com/0/238663/b42e8904-33ac-e327-7631-ee8819b33f0a.jpeg)

とすると、ブレークポイントで処理がサスペンドし、データブラウザにIllustratorオブジェクトの一覧が表示されます。
![WS000000.jpeg](https://qiita-image-store.s3.amazonaws.com/0/238663/53112e8b-9182-d27c-af4b-a647ea3f8094.jpeg)


＋ボタンをマウスでクリックすると、オブジェクトの内容を掘り下げることができます。
選択しているのは[TextFrame]というオブジェクトです。その下にプロパティやらメソッドがいっぱいぶらさがっています。

![browse.jpeg](https://qiita-image-store.s3.amazonaws.com/0/238663/63cbb4df-b19c-f32f-93b0-1bc0085cad8c.jpeg)

Illustratorオブジェクトの詳細を知るには[公式リファレンス](https://www.adobe.com/devnet/illustrator/scripting.html)が便利です。







<!-- # Illustratorのオブジェクト？
Illustratorを自動制御するExtendScriptを書きたいけど、処理したいオブジェクト名が何で、どのようなプロパティおよびその値があるのかわからないことが結構あります。 -->
laravel+mailhogでメールの仮想環境を作る

**2019年10月3日追記**
HomeSteadもこの記事を書いてからずいぶんバージョンアップしています。
Laravel5.8 + Homestead v9　以降（もっと前から対応していると思いますが）ならば
mailhogはセットアップ済みで.envで設定するだけで使えます。


以下の物を使用
homestead 6.5
PHP7
Nginx
Vagrant

mailhogがhomesteadに含まれているので
Laravelの仮想環境をhomesteadで作成した人は簡単にメール送信のテストができるようになります。

## mailhogが動いているか確認

``` bash
sudo lsofc -i:1025
```

結果が

```
COMMAND  PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mailhog 1195 vagrant    3u  IPv6  17743      0t0  TCP *:1025 (LISTEN)
```

となっていればmailogが動いています。

## Vagrantfileに追記

```
config.vm.network :forwarded_port, host: 8025, guest: 8025
```

ここでVMが起動済みならば再起動

## iptablesの追加

```
sudo iptables -A INPUT -p tcp -m tcp --dport 8025 -j ACCEPT
sudo /etc/init.d/iptables-persistent save
```

iptables-persistentがなかったら

```
sudo apt-get install iptables-persistent
```

## php.iniを修正
```
/etc/php/7.1/fpm/php.ini
/etc/php/7.1/cli/php.ini
```

```
sendmail_path = "/usr/local/bin/mailhog sendmail test@example.org"
```

## サービスの再起動
```
sudo /etc/init.d/php7.1-fpm restart
sudo /etc/init.d/nginx restart
```

## .envの修正
```
MAIL_DRIVER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
```

## ブラウザからアクセス
http://localhost:8025/

これで設定完了です。
Laravelで作成中のプログラムからmailを飛ばしてみて、
mailhog側で見れればOKです。
ERCトークン比較


||ERC20|ERC223|ERC721|
|---|---|---|---|
|規格策定日|2015/11/19|2017/03/05|2017/09/20|
|目的|トークンの標準化|ERC20の改良版|トークンごとの固有メタデータ保存|
|トークン発行|○|○|○|
|燃費|中|小|大|
|非対応トークンのフォールバック機能|☓|○|○|
|from指定のトークンの転送処理|○|☓|☓|
|NFT（トークンのユニーク化）|☓|☓|○|


# 参考
https://qiita.com/Morinikiz/items/d0d095a800394f951fbe#%E5%8F%82%E8%80%83
https://medium.com/blockchain-research-institute/erc721%E3%81%A8%E3%81%AF-38e80ea2b328
http://www.blockchainengineer.tokyo/entry/2017/12/31/223214
https://blockchainexe.com/erc721/

# 雑感

ERC20はもう使う必要がなさそう（ハードウェアウォレットへの対応くらい）
ERC223がまだ普及していないのはまだ確定していないから？
（ https://github.com/ethereum/EIPs/issues/223 ）

# 雑感２

short-address-attackってerc20だけの問題なのだろうか。

型情報持っているのにデータマッピング時にサイズ情報を検証できない？
アドレスにチェックサムがない
という原因で起きているからスマートコントラクト自体の問題なのか？

https://ericrafaloff.com/analyzing-the-erc20-short-address-attack/

# 雑感３

ERC721はサイドチェーンとかで動かさないとスケールするイメージがない
ethereum上では所有権だけ管理してメタデータには外部チェーンに保存するメタデータのIDだけ埋め込んで運用するとかなんらかの手法が必要な気がする



# トークン系のEIP

https://github.com/ethereum/EIPs/issues/223
https://github.com/ethereum/EIPs/issues/721
https://github.com/ethereum/EIPs/issues/777

http://y-nakajo.hatenablog.com/entry/2018/02/07/235913
@vue/test-utilsで非同期イベントのテスト

Vueのテストを書いていて、非同期処理の部分でちょっとはまったのでメモ。
結論として、以下の公式ドキュメントを読め、でした。
https://vue-test-utils.vuejs.org/ja/guides/testing-async-components.html

# tl;dr

- clickイベント時の処理をtestしたい
- 発火するmethodがasyncだとひと手間必要
- `flush-promises`使うと便利にかける


# テストケース

Vue componentでclick(イベントはなんでもいいですが)時に非同期にAPIを叩いて処理する、みたいなものがあったとします。
サンプルを公式ドキュメントからもってくると以下のような感じです。

```vuejs:App.vue
<template>
  <button @click="fetchResults" />
</template>

<script>
  import axios from 'axios'

  export default {
    data () {
      return {
        value: null
      }
    },

    methods: {
      async fetchResults () {
        const response = await axios.get('http://example.com/api')
        this.value = response.data
      }
    }
  }
</script>
```

テストファイルは以下のような感じ。(Jestつかってます)

```javascript:App.spec.js
import { shallow } from '@vue/test-utils'
import App from './App'

test('App', () => {
  it('fetches async when a button is clicked', () => {
    const wrapper = shallow(Foo)
    const fetchResults = jest.fn().mockResolveValue({data: 'value'})
    wrapper.setMethods({fetchResults})
    wrapper.find('button').trigger('click')
    expect(wrapper.vm.value).toEqual('value')
    expect(fetchResults.calls.length).toEqual(1)
  })
})
```

…がしかしこれはうまくいきません。
fetchResults 内の Promise が resolve する前にアサーションが呼ばれるので失敗します。

# 解決法

ドキュメントでは`$nextTick`を使う方法とasync/awaitを使う方法の2つが紹介されてますが、async/awaitの方が読みやすいのでそっちを使います。
要は、Vue vm内で非同期イベントがtriggerされた場合、vm内のtask queueでPromiseが処理されるのでそれをなんらか待つことができればよい、という感じです。

さっきのテストコードは以下になります。

```javascript:App.spec.js
import { shallow } from '@vue/test-utils'
import flushPromises from 'flush-promises'
import App from './App'

test('App', () => {
  it('fetches async when a button is clicked', async () => {
    const wrapper = shallow(Foo)
    const fetchResults = jest.fn().mockResolveValue({data: 'value'})
    wrapper.setMethods({fetchResults})
    wrapper.find('button').trigger('click')
    await flushPromises()
    expect(wrapper.vm.value).toEqual('value')
    expect(fetchResults.calls.length).toEqual(1)
  })
})
```

違いは、`flush-promises`[^1]をimportしたのと、itのcallbackを`async`にして、arrow function内で`await flushPromises()`している点です。
`flushPormises`でいまあるPromiseが全部resolveされるので、それを`await`すると無事非同期処理をはさみつつ、testがかけます。
こっちの方が読みやすいですね。
[^1]: `flush-promises`は別途installする必要があります。`yarn add -D flush-promises`など。
Bootstrap4をノンレスポンシブで使う

Bootstrap4をノンレスポンシブで使う方法のメモです。簡単。

# 公式のサポートはありません
Bootstrap3では公式が配布している`non-responsive.css`を追加するだけでしたが、Bootstrap4からは公式のサポートが無くなってしまいました。

:link: [Bootstrap](https://getbootstrap.com/)
:link: [Bootstrap4移行ガイド](http://cccabinet.jpn.org/bootstrap4/)
> Bootstrapの非レスポンスでの使用はサポートしない（non-responsive.css は提供しない）。

# ノンレスポンシブ化
- `bootstrap.min.css`を読み込んだ後に.containerのmin-widthを上書きする。

```css:app.css
.container {
  min-width: 1200px;
}
```

- グリッドシステムで画面幅を指定しない

画面幅を指定するクラス`xs, sm, md, lg, xl`は使わないでください。もしすでに使っている場合は取り除きます。たとえば、`col-md-6`は`col-6`に置き換えます。

以上！
【Swift】変数と定数

# 実行環境
- Swift4
- Xcode9.2

# 変数
一度代入した値を変更する必要があれば変数を使う。

## 定義
```swift
var 変数名: 型名
```
## 使い方例
### 正常パターン
```swift:型の明示あり
// 変数の宣言
var data: String
```
```swift:型の明示あり、初期化あり
// 変数の宣言
var data: String = "Hello"
```
```swift:型推論により型を省略して初期化
// 変数の宣言
var data = "Hello"
```
### 異常パターン
```swift:型の明示なし、初期化なし
var data // コンパイルエラー発生
```

## 代入例
```swift:
var data: String = "ABC"
// 変数に代入
data = "DEF"
print(data) // 結果: DEF

// 変数に再代入
data = "GHI"
print(data) // 結果: GHI
```

# 定数
一度代入した値を変更する必要がなければ定数を使う。

## 定義
```swift
let 変数名: 型名
```

## 使い方例
### 正常パターン
```swift:型の明示あり
// 定数の宣言
let data: String
```
```swift:型の明示あり、初期化あり
// 定数の宣言
let data: String = "Hello"
```
```swift:型推論により型を省略して初期化
// 定数の宣言
let data = "Hello"
```
### 異常パターン
```swift:型の明示なし、初期化なし
let data // コンパイルエラー発生
```

## 代入例
```swift:
let data: String
// 定数に代入
// 1度目の代入のため、コンパイルエラーは発生しない
data = "ABC"
print(data) // 結果: DEF

// 定数に再代入
// 2度目の代入のため、コンパイルエラーが発生する
data = "GHI"
```
Photoshopのレイヤーのロック解除出来ないのをしょっちゅうやるのでメモ失礼します。

https://helpx.adobe.com/jp/photoshop/kb/222402.html

Solutions （解決方法）

 ```

以下のいずれかまたは両方を実行します。

-- レイヤー名が [背景] の場合　：　

レイヤーパレットで背景をダブルクリックするか、もしくは [レイヤー] メニューから [新規] － [背景からレイヤーへ] を選択し、[新規レイヤー] ダイアログボックスで名前を入力し、 [OK] をクリックします。

 

-- レイヤー名が [インデックス] の場合　：　

[イメージ] メニューから [モード] を選択し、[グレースケール] または [RGB] のカラーモードを選択します。
```

なんでこんなデータが出来るのか謎だけどまぁしょうがない……
Qiita画像アップロード制限

月間2MB

記事投稿をすれば100MB

限定公開では無効

参考リンク
[初めてQiitaに投稿すると1ヶ月の画像アップロード制限が2MB→100MBにアップします](http://blog.qiita.com/post/75674629515/image-capacity-expansion)
intelliJでプロジェクト環境変数の設定

# 概要

新しいプロジェクトに配属された際にプロジェクト固有の環境変数を設定する必要があると思います。
そのintellijでの設定方法メモです。
おそらくwindowsも変わらないと思いますが、デモではMacを対象にしています。

# 設定方法

1. メニュー preference > Build,Execution,Deployment > Build Tools > Maven > Runnerを開く


2. Environment Variables の右端「...」をクリック


<img width="1107" alt="スクリーンショット 2018-03-14 14.37.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/114396/9b00f353-e7a1-5cca-48e7-8ef8d660d577.png">



3. 開いたウィンドウ下の+より追加していく


<img width="1103" alt="スクリーンショット 2018-03-14 14.37.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/114396/a5789ca8-1830-6c82-d788-48e18138998f.png">


以上

ここで設定した変数は、Runで設定するMavenプロジェクトの環境変数に自動的に設定されます。
Runの種類ごとに設定したい場合は、RunのEdit Configuration よりRunごと同様の設定を行なってください。
Angularで国際化対応する


基本的には公式サイトの[Internationalization][tutorial]の説明の通り。
ただコンパイル方法がJITとAOTによって違ったり、どの情報を元に言語を切り替えるかが開発者に任せられる前提だったので、自分のやりたい方法で多言語化できるまでに少しハマったので、国際化する方法をメモしておきます。

# コンパイル方法による違い
AOTとJITがあります。

## AOT
AOTは事前に言語リソースも含めてビルドする形になるので、動的に変更することができません。
よってURL自体を分けてしまう場合や、Webサーバーの機能で表示するページを振り分ける場合などに使用できます。
Angular自体の速度はAOTの方が早いようです。

## JIT
JITはページ表示後にAngularのコンパイル的なことをごにょごにょするみたいです。
パフォーマンスはAOTに劣るようですが、動的な言語リソースの選択が可能です。
私は今回JITコンパイルを採用しました。
S3にコンテンツを配置するのでブラウザの言語によって、返すコンテンツを変更する事が難しい(よく調べてない)点と、どの言語も同じURLでアクセスできるようにしたかったからです。

# 出し分け方法
[Internationalization][tutorial]によると`main.ts`は以下のようになります。

```typescript:src/main.ts
import { enableProdMode, TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

// use the require method provided by webpack
declare const require;
// we use the webpack raw-loader to return the content as a string
const translations = require(`raw-loader!./locale/messages.fr.xlf`);

platformBrowserDynamic().bootstrapModule(AppModule, {
  providers: [
    {provide: TRANSLATIONS, useValue: translations},
    {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'}
  ]
});
```

このプログラムだと固定の言語、今回は`fr`なのでフランス語にしか翻訳されたページが表示されません。
今回やりたかったことは、ブラウザの言語設定(chromeの設定から変更できる言語も考慮)に応じて切り替えることだったので、次のように`main.ts`を変更しました。

```typescript:main.ts
import {enableProdMode, TRANSLATIONS_FORMAT, TRANSLATIONS} from '@angular/core';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import 'hammerjs';

import {AppModule} from './app/app.module';
import {environment} from './environments/environment';

if (environment.production) {
  enableProdMode();
}

declare const require;

// 日本語の場合のみ日本語に翻訳する
const translationProviders = (() => {
  // ブラウザの言語を取得
  const browserLanguage: string = (() => {
    console.log(navigator.languages);
    if (navigator.languages.length > 0) {
      return navigator.languages[0];
    }
    if (navigator.language) {
      return navigator.language
    }
    return "en";
  })();
  console.log(browserLanguage);

  // 日本語だったら翻訳設定
  if (browserLanguage.match(/^ja$|^ja-/)) {
    const translations = require('raw-loader!./locale/messages.ja.xlf');
    return [
      {provide: TRANSLATIONS, useValue: translations},
      {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'},
    ]
  }
})();


platformBrowserDynamic().bootstrapModule(AppModule, {
  providers: [].concat(translationProviders) // 翻訳が必要な場合のみ、翻訳に必要なプロバイダーを追加する
})
  .catch(err => console.log(err));
```

これでブラウザの言語に応じて、英語と日本語の出し分けができるようになりました。



[tutorial]: https://angular.io/guide/i18n
CSSでデザイン調整可能なルビ

## 普通のパターン

普通、ルビはこんな感じで振る。

```html
<p><ruby>吾輩<rt>わがはい</rt></ruby>は猫である。名前はまだ無い。</p>
<p>どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番<ruby>獰悪<rt>どうあく</rt></ruby>な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。</p>
```

すると、こうなる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48750/9f487830-32f1-779d-fe60-d7dd2ab8dd7d.png)

ルビが入ることで行間が変化して、いまいち格好悪い。そして一部のブラウザ（Chromeなど）ではルビの位置をCSS微調整することができず、使いにくい。

## 別の方法を考える

そこで、`<ruby>`タグを使わないで以下のようにHTMLを組んでみる。

```html
<p><span data-ruby="わがはい">吾輩</span>は猫である。名前はまだ無い。</p>
<p>どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番<span data-ruby="どうあく">獰悪</span>な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。</p>
```

そしてCSSは、こう。

```css
[data-ruby] {
	position: relative;
}
[data-ruby]::before {
	content: attr(data-ruby);
	position: absolute;
	top: -1em;
	left: 0;
	right: 0;
	margin: auto;
	font-size: 0.5em;
}
```

すると、こうなる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48750/6588fb83-d8c7-d9c8-b893-0dd219eb81ea.png)

下から2行目の「獰悪」にルビが振られているが、行間が変化していないので、見栄えも悪くない。そのかわり行間は多めに撮っておいたほうが良さそう。ルビの位置もCSSで微調整することができる。

HTMLを変えたことで文書の意味も若干変わるが、まぁ単なる難読文字の場合、文書構造上、ルビはいらないだろうから、あまり気にしない。

音声ブラウザが読み間違えるような場合を懸念する場合は少し冗長だけども、以下のようにしておけば良いかもしれない（まぁこのあたり JavaScript で自動化しても良いだろう）。

```html
<ruby data-ruby="はにゅう">羽生<rt>はにゅう</rt></ruby>結弦
 vs. 
<ruby data-ruby="はぶ">羽生<rt>はぶ</rt></ruby>善治
```

```css
[data-ruby] {
	position: relative;
}
[data-ruby]::before {
	content: attr(data-ruby);
	position: absolute;
	top: -1em;
	left: 0;
	right: 0;
	margin: auto;
	font-size: 0.5em;
}
/* 以下追加 */
rt {
	display: none;
}
```

すると、こうなる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48750/94f0cb62-6000-2dd7-c999-e700167dee48.png)

どうでしょうか？

## 【補足】CSSの記述の意味

- `content: attr(属性名)` そのタグの指定属性の値を content として指定できる。
- `position: absolute; top: -1em;` 疑似要素によって挿入されたルビの位置をルビを振りたい対象の文字列の行の上端より -1em の場所にする。絶対配置の基準として、疑似要素の親要素に対して `position: relative` を指定しておく。
- `left: 0; right: 0; margin: auto;` こうすると左右中央揃えになる。
Google SpreadsheetでAWS SNSから通知をうけとり、データを更新する方法

元となっているアイデアは下記の記事です。
この記事を読んで、AWS SNSから通知をうけとりGoogle Spreadsheetを更新した際に気が付いたことをまとめます。

 [Google Spreadsheet を簡易 Webサーバーとして動かして、手軽にWebHookを受け取る方法](https://qiita.com/kunichiko/items/7f64c7c80b44b15371a3) by @kunichiko

# AWS SNSに接続する
SNSにWeb Hookを追加する場合、確認イベントに応答する必要があります。
requestObjが取れている状態であれば、下記のように簡単に対応できます。

```javascript
if(requestObj.Type === "SubscriptionConfirmation"){
    subscribeSNS(requestObj.SubscribeURL);
}
```

```javascript
function subscribeSNS(confirmURL){
  var options = {
    "method" : "get"
  };
  var result = UrlFetchApp.fetch(confirmURL, options);
  return JSON.stringify(result);
}
```

# ドキュメントの更新

```javascript
sheet.getLastRow();
sheet.getLastColumn();
sheet.getRange(row,col).getValue();
sheet.getRange(row,col).setValue(value);
```
これ以上必要な情報はありますか:-p

追記
あった。。。
getRange遅いので、できる限り大きい単位で読み書きした方が良いです。

```javascript
sheet.getRange(row,col,rowCount,colCount).getValues();
sheet.getRange(row,col,rowCount,colCount).setValues(value);
```

# その他注意点
## 型について
シートに文字列で数字を設定しても、取得すると数値型になっていたりします。
===を用いた比較が失敗したりするのでご注意ください。

## ロックの取得
追記以外の編集を行う場合には、排他処理のためにロックを取得する必要があります。waitLockを使えばロック取得に失敗するとエラーとなるので、SNSのようにリトライしてくれるWebhookであれば簡単に対応できます。

```javascript
function doPost(e) {
   var lock = LockService.getDocumentLock();
  lock.waitLock(5000);
  try{
    doPostImpl(e);
  }
  finally{
    lock.releaseLock();
  }
}

function doPostImpl(e) {

}
```
pandasで「Initializing from file failed」というエラーが出てしまった時の対処法[anaconda]

#はじめに
「pythonによる機械学習入門」という本をコードを書きながら読んでいたら、エラーでつまづいたのでメモしておきます。

#環境
anaconda 1.6.9
python 3.6.4

#エラーが出た状況と原因
コードの内容を簡単に言うと、csvファイルからデータを読み取り図式化するものだったのですが書いてある通りに実行しても

```
OSError: Initializing from file failed
```

と表示されて実行完了しませんでした。そこで、このエラー名で検索するとファイルのパス名に日本語を含む場合に発生するエラーだとのこと。自分はフォルダ名には日本語を含んでいなかったのですが、確かに配布されているcsvファイルには「高松」という日本語が含まれていました。
[Python3.6のpandasで「Initializing from file failed」が起きた場合の対策](http://own-search-and-study.xyz/2017/04/08/python3-6%E3%81%AEpandas%E3%81%A7%E3%80%8Cinitializing-from-file-failed%E3%80%8D%E3%81%8C%E8%B5%B7%E3%81%8D%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E7%AD%96/)

#対策
　この「高松」を「takamatsu」に変更して実行してみるとうまくいきました。この後も同様の問題が起こるのは困るので、原因と思われるpandasのアップデートを試みました。

　自分と同じ環境であればAnaconda Prompt上で`pip install -U pandas`と実行してpandasをアップデートしてみると日本語を含むファイルでも実行することができました。

```
pip install -U pandas
Requirement already up-to-date: pandas in c:\programdata\anaconda3\lib\site-packages
Collecting python-dateutil>=2 (from pandas)
  Downloading python_dateutil-2.7.0-py2.py3-none-any.whl (207kB)
    100% |████████████████████████████████| 215kB 1.8MB/s
Collecting pytz>=2011k (from pandas)
  Downloading pytz-2018.3-py2.py3-none-any.whl (509kB)
    100% |████████████████████████████████| 512kB 2.9MB/s
Collecting numpy>=1.9.0 (from pandas)
  Downloading numpy-1.14.2-cp36-none-win_amd64.whl (13.4MB)
    100% |████████████████████████████████| 13.4MB 2.3MB/s
Requirement already up-to-date: six>=1.5 in c:\programdata\anaconda3\lib\site-packages (from python-dateutil>=2->pandas)
Installing collected packages: python-dateutil, pytz, numpy
  Found existing installation: python-dateutil 2.6.1
    Uninstalling python-dateutil-2.6.1:
      Successfully uninstalled python-dateutil-2.6.1
  Found existing installation: pytz 2017.3
    Uninstalling pytz-2017.3:
      Successfully uninstalled pytz-2017.3
  Found existing installation: numpy 1.14.0
    Uninstalling numpy-1.14.0:
      Successfully uninstalled numpy-1.14.0
Successfully installed numpy-1.14.2 python-dateutil-2.7.0 pytz-2018.3
```

pandas自体はすでにアップデートされていると表示されましたが、numpyやdateutil,pytzなどがアップデートされて(2018/3/14時点)うまくいきました。
anacondaは2018/02ごろに入れたばかりのため、anacondaを利用している多くの人のpandasは自分と同じバージョンであると思うので、ぜひアップデートしてみてください。
ToolbarとTabbarの間の影を消す

Activityの直下にあるfragmentがTabLayoutをもっていて、Activityのtoolbarとtabbarの境目をなくしたいよねって話になった。

`android:elevation="0dp"`にしても変わらなかったのでメモ。

```
        <android.support.design.widget.AppBarLayout
                android:id="@+id/appBarLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:elevation="0dp"
                android:stateListAnimator="@null" ← これが必要
                >

        </android.support.design.widget.AppBarLayout>
```


# 参考 
https://stackoverflow.com/questions/26575197/no-shadow-by-default-on-toolbar
サブドメインのSSL証明書の期限一覧を作る

サブドメインを使っているサイトのSSL証明書の期限一覧を作るスクリプトです。

```bash:get_expire.sh
#! /bin/bash
#
#	get_expire.sh
#
#						Mar/14/2018
domain=$1
filename=$2
#
./get_expire_exec.sh $domain $filename | grep GM | \
	awk -F= '{print $2"\t"$1}' | \
	sed 's/ notAfter//' |  sort
#
#
```

```bash:get_expire_exec.sh
#! /bin/bash
#
#	get_expire_exec.sh
#
#						Mar/14/2018
domain=$1
filename=$2
cat $filename | while read pref
do
	host=$pref"."$domain
	echo -n $host" "
	echo | openssl s_client -connect $host:443 -servername $host \
		2>/dev/null | openssl x509 -noout -enddate
	echo
done
#
```

実行方法

```bash
./get_expire.sh  example.com in01.txt
```

例えば、in01.txt は次のようなファイルです。

```text:in01.txt
aichi
aomori
chiba
ehime
fukui
```

実行結果

```text
May 10 22:57:42 2018 GMT	ehime.example.com
May 12 00:39:38 2018 GMT	fukui.example.com
May 14 00:45:44 2018 GMT	aomori.example.com
May 15 01:06:24 2018 GMT	chiba.example.com
May 18 01:07:04 2018 GMT	aichi.example.com
```

動作の確認は、
Arch Linux (4.16.13-2-ARCH) で行いました。

ひとつのサイトの期限を調べる方法はこちらです。
[openssl で 証明書の期限を確認する](https://qiita.com/ekzemplaro/items/b479b1284e50718bd50b)
アプリ検討

- [価値仮説](https://qiita.com/sunada-ke/private/2c0e1026110a8a8a89a3)

- [購入に迷っている服や似合っている髪型などを他人に聞けるアプリ](https://qiita.com/sunada-ke/private/2aad706ebfeeba3898ba)

- [シナリオライティング](https://qiita.com/sunada-ke/private/f9a77545173af644bc25)
【Swift+Extension】Swift.RangeとNSRangeの変換

# String extension
```swift:String+Range.swift
import Foundation

extension String {
    
    func nsRange(from range: Range<String.Index>) -> NSRange {
        return NSRange(range, in: self)
    }
    
    func ranges(of searchString: String, options mask: NSString.CompareOptions = [], locale: Locale? = nil) -> [Range<String.Index>] {
        var ranges: [Range<String.Index>] = []
        while let range = range(of: searchString, options: mask, range: (ranges.last?.upperBound ?? startIndex)..<endIndex, locale: locale) {
            ranges.append(range)
        }
        return ranges
    }
    
    func nsRanges(of searchString: String, options mask: NSString.CompareOptions = [], locale: Locale? = nil) -> [NSRange] {
        let ranges = self.ranges(of: searchString, options: mask, locale: locale)
        return ranges.map { nsRange(from: $0) }
    }
    
}
```

## FYI
[NSString - Foundation | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/nsstring)
[Searching, Comparing, and Sorting Strings | Apple Developer Documentation](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/SearchingStrings.html)
俺のRailsデプロイがこんなに遅いはずがない

# きっかけ

Railsで開発してるのだが、最近**デプロイが非常に遅くなってきた。** Railsのデプロイは[Capistrano::Rails](https://github.com/capistrano/rails)を使用しているが、ログをみると`rails assets:precompile`に非常に時間がかかっていた。

なんとその時間　**＞約６分＜**

流石に１デプロイ６分はやってられないということで解決策を探すことに

# 解決策

`rails assets:precompile`はRubyだから**遅い**。C#で実装された[SassC](https://github.com/sass/sassc)を使おう。

# インストール

Macの場合は`brew install sassc` するだけ。Linuxの場合は以下を参考にSassCをインストールする。

[Ubuntu/CentOSでSassCをインストールする - 動かざることバグの如し](http://thr3a.hatenablog.com/entry/20180308/1520506843)

# 設定

Railsのアセットプリコンパイル周辺の設計はすごく良くできていて、Gemfileの

```
gem 'sass-rails', '~> 5.0'
```

をコメントアウトして

```
gem "sassc-rails"
```

を追加するだけ。あとは`bundle install`

# 結果

今まで６分かかっていた`rails assets:precompile`が１分で終わった。なんというビフォア・アフター

# 言いたいこと

- SassCマジ速い
- 無理にwebpackに乗り換えなくても改善はできる
pgpool-IIの起動がうまくいかないとき、pgpool_statusを消してみる

# TL;DR

`$logdir/pgpool_status`を消して再度起動する。



# pgpool-IIの起動がうまくいかない

具体的には起動から5分経たないとpcp_xxxコマンドを受け付けない。
9898が空いていない。
その間、ログには下記が1秒おきに出力され続ける。

```
LOG:  find_primary_node: checking backend no 0
LOG:  find_primary_node: checking backend no 1
```

[pgpool-general Info Page](http://www.sraoss.jp/mailman/listinfo/pgpool-general)

上記メーリングリストを漁ったら（というかググったら日っとした）下記のメールを発見

[[pgpool-general: 5667] find_primary_node problem](http://www.sraoss.jp/pipermail/pgpool-general/2017-August/005725.html)

たどってくと下記に添付されたログが合致（ここがググってたどり着いたとこ）

[[pgpool-general: 5675] Re: find_primary_node problem](http://www.sraoss.jp/pipermail/pgpool-general/2017-August/005733.html)

> Yes, I enable debug log, and I got:
> LOG:  find_primary_node: checking backend no 0
> LOG:  find_primary_node: checking backend no 1
> DEBUG:  pool_read: read 13 bytes from backend 0
> ...

で、それに対する回答

[[pgpool-general: 5678] Re: find_primary_node problem](http://www.sraoss.jp/pipermail/pgpool-general/2017-August/005736.html)

なんで？という質問者への回答

[[pgpool-general: 5681] Re: find_primary_node problem](http://www.sraoss.jp/pipermail/pgpool-general/2017-August/005739.html)

> No access to backend is logged, instead move to check backend 1.
> That means Pgpool-II skipped checking against backend 0 because it thinks node 0 is down.
> The only reason for this is node 0 status was marked as down in the status file.
急にoracleに繋がらなくなった！？～ORA-28001:パスワードが期限切れです～

##事象
つい数分前まで繋がっていたにもかかわらず、急にDBに繋がらなくなってしまいました。

ログを確認すると、【ORA-28001:パスワードが期限切れです】というエラーが出てました。

パスワードなんて変えた記憶もないし、ついさっきまで繋がっていたにも関わらずなぜだろうと調べた結果、

##原因
oracle11g のデフォルトの設定では、パスワードの有効期限が180日に設定されており、180日経過するとこのエラーが発生するみたいです

##対策

######①パスワードの有効期限を廃止
######②パスワードの再設定
######③アカウントのロック解除


---
※以下SQLplusで対象のデータベースにログインして後の手順。

######①パスワードの有効期限を廃止

```
> ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
```

######②パスワードの再設定

```
ALTER USER ユーザ名 IDENTIFIED BY 新パスワード;
```

######③アカウントのロック解除

```
ALTER USER ユーザー名　ACCOUNT UNLOCK;
```

これで、ログインすることができ、有効期限は廃止され180日でパスワードの期限切れエラーは出なくなるはずです！
WordPressのマルチサイトで利用しているプラグインの一覧を見るには「Active plugins」とゆうプラグインが便利

# タイトルで全部言っちゃうスタイル

デザイナーさんがスナック感覚でプラグインをポコポコ入れてたのを数年放置してたらエグい状況になってたが、サイト数が100を超えてて、いっこいっこ開いて確認するワケにもいかんしDBほじくるかと思ったが、調べてみたらプラグインがあった。

Active Plugins &mdash; WordPress Plugins
https://wordpress.org/plugins/active-plugins-on-multisite/

# つかいかた

インストール後にネットワークで有効化して、[設定]→[Active Plugins]。

# こんなん見れます

## プラグイン別に利用しているサイトの数

![Screenshot-2018-3-14 Active Plugins Across Network ‹ サイトネットワーク管理 サイト 本番系 — WordPress.png](https://qiita-image-store.s3.amazonaws.com/0/34041/9c4ada08-de52-9e3f-f4e3-12974b3b8fdb.png)

## 誰も使ってないプラグイン

![Screenshot-2018-3-14 Active Plugins Across Network ‹ サイトネットワーク管理 サイト 本番系 — WordPress(3).png](https://qiita-image-store.s3.amazonaws.com/0/34041/0e49a868-3ab1-d1c1-eed7-aaf1746378ac.png)

## サイト別に使っているプラグインの一覧

![Screenshot-2018-3-14 Active Plugins Across Network ‹ サイトネットワーク管理 サイト 本番系 — WordPress(2).png](https://qiita-image-store.s3.amazonaws.com/0/34041/b2fa7508-9e8a-3f4a-5d54-e4fa871b2804.png)
[PowerShell]NuGetからパッケージをダウンロードする


# [PowerShell]NuGetからパッケージをダウンロードする

## 経緯
社内の大幅組織変更の予定のため、EXCELでADのユーザー情報を一括で登録できるように検討したところ、ClosedXMLを使ってPowerShellからEXCELを操作できるという記事を見つけました。

> @miyamiyaさんの記事
> [PowerShell で ClosedXML を使って Excel ファイルを作成する](https://qiita.com/miyamiya/items/fd93d633afa0314f231a)

ただ、`ClosedXML`と`Microsoft Open XML Format SDK`は、GitだけでなくNugetにもあるのでダウンロードと配置の手間を省くため、PowerShellでNugetパッケージを取得する方法にしました。

## 環境
Windows 10 Pro 1703
Windows PowerShell ISE

## Powershellコマンド

- スクリプトを実行すると、ダウンロードすることができます。

```powershell:Nugetからダウンロードするスクリプト

try
{
    # パッケージプロバイダにNugetを追加
    Install-PackageProvider -Name Nuget

    # Nugetからパッケージ名を検索して、インストール実行
    Find-Package -Name DocumentFormat.OpenXml -Source https://www.nuget.org/api/v2 -RequiredVersion 2.5.0 | Install-Package
    Find-Package -Name ClosedXML -Source https://www.nuget.org/api/v2 -RequiredVersion 0.76.0 | Install-Package

    # パッケージのインストール確認
    Get-Package -ProviderName Nuget
}

catch [Exception]
{
    Write-Host $_.Exception.Message
}


```
~~

- '-Source https://www.nuget.org/api/v2` をつけていないとエラーでダウンロードできません。
- ダウンロードされると、`C:\Program Files\PackageManagement\NuGet\Packages`に依存関係を含めてフォルダが生成されています。
- ~~かなりのファイルがダウンロードされるので、若干時間がかかります。~~
- 依存関係が面倒だったので、バージョンを指定するように修正(2018/03/13)

![WS000000589.JPG](https://qiita-image-store.s3.amazonaws.com/0/90597/9ee16388-46f3-d18e-2724-849abb8e2c1b.jpeg)

## まとめ

PowerShellにNuGetが登録されていれば  
> ```powershell:
> Find-Package -Name <パッケージ名> -Source https://www.nuget.org/api/v2
> ```

でNuGetパッケージの検索を行い、 パイプラインでインストール指定を行うことでそのままダウンロードが行えます。

> ```powershell:
> Find-Package -Name <パッケージ名> -Source https://www.nuget.org/api/v2 | Install-Package
> ```

##  追記1.
'-Source https://www.nuget.org/api/v2` をつけていないとエラーになるか書いてある記事がありました。

> [senkousya/PS_startClosedXMLOnPowershell](https://github.com/senkousya/PS_startClosedXMLOnPowershell)

`Set-PackageSource`を使わなくてよかった。
危なく開発環境を壊すところでしたｗ

## 追記2.
- 依存関係が面倒だったので、スクリプトを変更しました。

 > ClosedXML -Version 0.76.0
 > DocumentFormat.OpenXml -Version 2.5.0

このバージョンであれば、二つのDLLの指定で行けそうです。

```powershell:ClosedXMLを使ったEXCELファイル作成

[Reflection.Assembly]::LoadFile("C:\Program Files\PackageManagement\NuGet\Packages\DocumentFormat.OpenXml.2.5\lib\DocumentFormat.OpenXml.dll")
[Reflection.Assembly]::LoadFile("C:\Program Files\PackageManagement\NuGet\Packages\ClosedXML.0.76.0\lib\net40-client\ClosedXML.dll")


$workBook = new-object ClosedXML.Excel.XLWorkbook
$workSheet = $workBook.Worksheets.Add("Sheet1")
$worksheet.Cell("A1").Value = "Hello world";
$workBook.SaveAs("c:\tmp\helloworld.xlsx")

```
Rubyで縦持ちデータから動的にモデルを作る

# コメントより
縦持ちテーブルをこのように利用することはアンチパターンだそうで、
まだまだ勉強不足であります。
詳しくはこちらで。。。
http://kyabatalian.hatenablog.com/entry/2016/12/19/193430

# はじめに
システム開発を行なっていると、頻繁にカラムの追加が発生するようなテーブルに出くわすことがあります。
その都度テーブル定義を変更すると言うのも一つの解法ですが、データを縦持ちにして変更に強くするというのも一つの手です。
けれど、プログラム上では一つのインスタンスとして扱いたい場合には、縦持ちテーブルは扱いづらいのです。
そこで、縦持ちテーブルから一つのモデルインスタンスを作成する方法をご紹介します。

# データ
今回は適当なデータとして以下を用意しました。

```ruby
details = [
  {'id' => 1, 'key' => 'name',   'value' => 'hoge'},
  {'id' => 2, 'key' => 'height', 'value' => '10'  },
  {'id' => 3, 'key' => 'width',  'value' => '5'   },
]
```

# モデルクラス
通常であれば、上記のようなデータに対して、

```ruby
class Profile
  attr_accessor :name
  attr_accessor :height
  attr_accessor :width
end

prof = Profile.new
prof.name   = (details.find {|d| d['key'] == 'name'})['value']
prof.height = (details.find {|d| d['key'] == 'height'})['value']
prof.width  = (details.find {|d| d['key'] == 'width'})['value']
```

という形で各keyに対してプロパティを作成していきます。

これでも良いのですが、今回は動的にインスタンスを作成してみます。

```ruby
class Detail
  PROP = {
    'name'   => Proc.new {|val| val},
    'height' => Proc.new {|val| val.to_i},
    'width'  => Proc.new {|val| val.to_i},
  }
end

class Profile
  Detail::PROP.each do |key, val|
    attr_accessor key.to_sym
  end

  def initialize(details)
    Detail::PROP.each do |key, val|
      detail = details.find {|d| d['key'] == key}
      if detail
        send(key + '=', val.call(detail['value']))
      end
    end
  end
end

prof = Profile.new details
```

DetailクラスでプロパティのKeyとValueの変換方法を定義しています。
ProfileクラスはDetailクラスの内容を元にプロパティの動的生成と、動的な初期化を行なっています。

# 考察
ここまでやる必要あるかどうかはそれぞれのプロジェクトに寄るでしょうが、Detail::PROPに手を加えるだけでカラム追加・削除と同じ効果が得られるようになります。
頻繁にカラム追加が起きるようなテーブルがある場合に、この方法を考慮に入れてみても良いのではないでしょうか。