OmniAICreator/Qiita-1.07M huggingface dataset:
sed と awk （６）リモートサーバへの書き込み

sed を他のコマンドと組み合わせて、リモートサーバーで実行します。おそらく、複数のサーバーを管理しているときに便利です。

# scp 
ローカルの環境から、リモートにsedファイルを転送。IPアドレスは存在しえない数です。

```bash
$ scp ntp.sed azureuser@12.345.67.890:/home/azureuser/
```

# ssh でリモート環境でコマンドを実行

`-t` がリモートでコマンドを実行するオプション

```bash
 ssh -t azureuser@12.345.67.890 sed -i.bak -f /home/azureuser/ntp.sed /home/azureuser/ntp.conf
```

* [ssh(1) - Linux man page](https://linux.die.net/man/1/ssh)

# 結果

リモートで実行したのと同じになる。ちなみに下記のログはsedコマンドで、実IPを書き換えてみた。

```bash
$ ssh azureuser@12.355.67.890
Enter passphrase for key '/Users/ushio/.ssh/id_rsa':
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.15.0-1040-azure x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

5 packages can be updated.
0 updates are security updates.

New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


Last login: Mon Apr  1 02:08:51 2019 from 12.345.67.890

azureuser@tsuyoshis:~$ ls
drivers  employees  ntp.conf  ntp.conf.bak  ntp.sed  parsecsv.sh  test  words
azureuser@tsuyoshis:~$ cat ntp.conf
driftfile /var/lib/ntp/ntp.drift
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable
server ntp.example.com prefer
pool ntp.ubuntu.com
restrict -4 default kod notrap nomodify nopeer noquery limited
restrict -6 default kod notrap nomodify nopeer noquery limited
restrict 127.0.0.1
restrict ::1
restrict source notrap nomodify noquery

```
【CraftCMS】投稿データのhard delete

投稿データを削除した後に「破棄済み」を選択するとまだ残ってた。

<img width="359" alt="スクリーンショット 2019-04-01 11.28.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/23195/759e1959-b242-b605-56d4-61d9413138af.png">

どうやら論理削除しかしてくれないようなのでこのままだとアレな感じ。
どうやったら消せるのか調べた。

CRAFT_PATH/config/general.phpに以下を追記する。

```php:general.php

'softDeleteDuration'  => 0 // デフォルト値は2592000らしいので30日間？
```

~~まぁ0だと間違った時あーっ！となってしまうので864000(10日間とか)くらいでよいのかなと。~~
0だとSoftDeleteDurationは停止してしまうようでした。

破棄してから設定値の時間経過後にgcが実行されるのはランダムなのだが
その確率を設定する項目をapp.phpで定義

```php:app.php
return [
	'components' => [
        'gc' => [
            'probability' => 10000, // 1 in 100
        ],
    ],
];
```

100アクセスに1回gcが走る・・・と思う。。。

速攻でハードデリートしたい場合は以下のコマンド

```sh
./craft gc --delete-all-trashed
```

ちゃんと用意されてんだなぁ

**おわり**
数年ぶりのRails入門【セットアップ編】

バックエンドの開発はいろいろあります。
ただ、個人開発程度なら「rails」でいいんじゃね？的な感じに僕の中でなってきましたので、数年ぶりにRailsに入信したいと思います。
強くてニューゲームで今回はセットアップ！やってきます。

# 注意事項
この記事書きながらセットアップしています。
なので、ベストプラクティスな方法ではないと思います。
ご容赦ください。

## 事前準備
dockerでセットアップやってくぜい！なので、dockerとdocker-composeくらいはlocalマシンに導入しといてください。

# セットアップ
## railsパクってくる
docker hubの公式rails imageがあるのですが、更新が止まってる？っぽいので、今回はこれを使って開発環境を作っていきます。
[https://hub.docker.com/r/bitnami/rails](https://hub.docker.com/r/bitnami/rails)

## docker-composeの作成
以下のようなdocker-composeを作成し、保存します。

```yml:docker-compose.yml
version: "3.2"

services:
    app:
        image: bitnami/rails:5.2.3-0
        volumes:
            - type: bind
              source: ./app
              target: /app
        ports:
            - "3000:3000"
        command: sleep infinity
    db:
        image: postgres:10
        environment:
            - "POSTGRES_USER=postgres"
            - "POSTGRES_PASSWORD=mysecretpassword1234"
```
作成したら以下コマンドでコンテナを作成し、コンテナ内へ入ります。

```bash:コマンド
docker-compose up -d
docker-compose exec app bash
```

## railsアプリの作成
カレントディレクトリは/appになっているので、railsアプリを作成します。(今回はdb=postgresでかつapiモードで作成します。)

```bash:コマンド
rails new . --api -d postgresql
```

そしたらpqのGem周りで怒られるので、エラーがでないように修正します。

```bash:コマンド
・エラー文
An error occurred while installing pg (1.1.4), and Bundler cannot continue.
Make sure that `gem install pg -v '1.1.4' --source 'https://rubygems.org/'` succeeds before bundling.
---
・対応
sudo apt-get update
sudo apt-get install libpq-dev
bundle install
```
bundle installでエラーが出なくなればokです。
最後にdatabaseの接続設定を行っておきましょう。(default部分を以下のように編集します。)

```yml:config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db # 追記[docker-composeで記述したdbサーバを指定]
  username: postgres # 追記
  password: mysecretpassword1234 #追記
  # For details on connection pooling, see Rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
```

以下コマンドでdatabaseが作成されることを確認します。

```bash:コマンド
rails db:create
```

## railsの起動
すべての準備は整いました。
railsを起動してみます。

```bash:コマンド
rails s -b 0.0.0.0
```

![スクリーンショット 2019-04-01 11.15.23.png](https://qiita-image-store.s3.amazonaws.com/0/47132/e9e5bb5f-8adf-8f43-7949-0d6c37802cbd.png)


# おわりに
docker使うとlocalが汚れないし、複数メンバーでの開発の場合、開発環境に差異が生まれにくい、かつ、高速で環境構築できるのでいいですね〜。
ただ、知見ないとハマりやすくはありますが。。。

railsの公式ページを見てるとv6がbetaバージョンで公開されていますね。
v6でどういった進化を遂げるか期待です！
vue.js + Vetur(VS Code Extension)にしたらファイルのauto formatでエラーになってしまった話

ちょっと社内GUIを作らなくてはいけないというタスクが実はありまして。

でもしばらくはあまり優先度も高くないんで放置してましたが、そろそろ再開しようかなと思いいろいろ調べていました。

いやー、今は便利になってんですね。ほんの３ヶ月前程はこんなのなかったと思うんだけど。

[Vue.js install](https://ja.nuxtjs.org/guide/installation)

``create-nuxt-app`` ですか。いやいや超便利。 Vue.js + Element で行こうかなと。

・・・なのですが、新規プロジェクトを作った後、ページ編集等を行い、autosaveで自動整形がかかった瞬間からはまったのでその解決方法のメモ。

ちなみにその時点で入れていたのは、

[Vue.js Extension Pack](https://marketplace.visualstudio.com/items?itemName=mubaidr.vuejs-extension-pack)

ただ、インストールして何もしないと以下のエラーにはまる模様。

## はまったエラー

![スクリーンショット 2019-04-01 10.58.37.png](https://qiita-image-store.s3.amazonaws.com/0/317673/b13ee307-1b14-925b-bb89-f287a2ed3717.png)

何かしらファイルに変更をかけ、saveすると自動整形がかかる。

しかしこの状態だと ``npm run dev`` がエラーを吐いてコケる。

## 解決策

[ここ](https://github.com/vuejs/vetur/issues/543) をみて解決。

具体的に自分がやったのは以下の点。( ``Solutions`` と書かれているところ以降をやった)

1. [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) Extension を追加インストール
2. settings.json に以下を足す

```json
  "eslint.autoFixOnSave": true,
  "eslint.validate": [
    "html",
    "css",
    "javascript",
    "javascriptreact",
    { "language": "vue", "autoFix": true },
    { "language": "vue-html", "autoFix": true }
  ],
```

3. package.json に以下を足す

```json
"eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": "plugin:vue/recommended",
    "parserOptions": {
      "parser": "babel-eslint"
    }
  },
```

これで解消しました。

VeturやPrettierを個別に入れている方も同じ問題にはまると思うので、これで解消するのではないかと思います。

参考になれば幸いです。
プラグイン機構を持つアプリの作り方[C#とJava]

少し、表題の件で調べてみたのでこちらでも投稿。
ただ、プラグインアーキテクチャは2003年頃に活発な動き(論文やら記事やら)がありましたが、最近はあまり議論されない内容のようです。
今回は参考文献のサンプルを実装して基本的な作り方についての感触をつづっています。

##### 基本的な作り方

* インターフェース(GUI、コマンド)を定義する
* インターフェースの拡張方法を定義する
* 定義したインターフェースを実装したプラグイン、ホストアプリケーションを作成する

##### 基本的な利用方法

* プラグインは何がしかの実行形式ファイルにする
* ホストアプリケーションはそのファイルを特定の場所に格納して利用する

##### C#の場合

* インターフェースを定義したdllを作成する
* 定義されたインターフェースを実装したプラグインをdllで作成する
* プラグインを読み込んで利用するホストアプリケーションを作成する

![PluginSystem(CS).png](https://qiita-image-store.s3.amazonaws.com/0/220327/8815e683-47ad-ada0-d3be-27f5e75f68d9.png)

![PluginSystem(CS)_deployment.png](https://qiita-image-store.s3.amazonaws.com/0/220327/1f3fe78e-c1c2-ae81-6f6a-916f0eae1441.png)

##### Java の場合

* プラグイン用にインターフェースを定義する
* 定義されたインターフェースを実装したプラグインをjarで作成する
* Jarファイルには、プラグインクラス名を記したマニフェストファイルを作成する
* プラグインを読み込んで利用するホストアプリケーションを作成する

![Class_Plugin System(java).png](https://qiita-image-store.s3.amazonaws.com/0/220327/fb06ba74-7bc5-8a64-1821-3b5f5c47725c.png)

![Deployment_Plugin System(java).png](https://qiita-image-store.s3.amazonaws.com/0/220327/848c0b50-42ef-1c45-9bdf-ec5563e763b8.png)

##### pythonなどインターフェースを持たないものではどう実装するのか？

Pythonはインターフェースを持たずに、多重継承を許容する仕様のようです。
実装する場合はかなり気を付けないと他モジュールの影響に苦しみそう…
こちらは引き続きの調査事項…

##### 個人的な所感

* C#やJavaなどで実装する場合はどういうプラグインを作れるようにするかを含めたインターフェースの定義が必須になる
* IDEのようなものを実現したいならVisualStudioやEclipseのプラグイン開発のインターフェースを参考にすると良さそう
  * https://docs.microsoft.com/ja-jp/visualstudio/extensibility/starting-to-develop-visual-studio-extensions?view=vs-2017
  * https://gihyo.jp/dev/serial/01/eclipse-plugin/0001
* 記載していないが、Pythonなどのインターフェースが存在しない言語では多重継承を利用して実装するみたい
* デスクトップアプリの場合、VisualStudioやEclipseの例を見る限りは、基本的なGUIの構成やデザインは現状変わっていない
  * それぞれに対して拡張を定義する機構を持っている
  * メニュー/ツールバー/ツールウィンドウ

[同じ内容やコードはこちらを参照してください（主にこっち）]
https://github.com/dandan611/SampleOfPluginSoftware

##### 参考文献

* Visual Studio 拡張機能の開発を始める
  * https://docs.microsoft.com/ja-jp/visualstudio/extensibility/starting-to-develop-visual-studio-extensions?view=vs-2017
* プラグイン開発入門 第1回 開発の基本　Eclipse のプラグイン開発の基本を学ぶ
  * https://www.ibm.com/developerworks/jp/opensource/library/os-eclipse-plugindev1/index.html
* .NETによるプラグイン機能を持つテキストエディタの作成
  * https://codezine.jp/article/detail/1
* プラグインで拡張できるJavaプログラムを作る
  * https://codezine.jp/article/detail/1271
* EclipseやSpringで使われている基盤技術OSGiとは
  * https://www.atmarkit.co.jp/fjava/special/osgi/osgi_1.html
* Writing Plugin-Based Applications
  * https://www.developerfusion.com/article/4371/writing-pluginbased-applications/
プラグインアーキテクチャ
https://decomo.info/wiki/translation/adc/cocoa/foundation/introduction_to_dynamically_loading_code/0600_plugins
AnsibleのvarsをInSpecに連携

#AnsibleのvarsをInSpecで使用する例

この例ではvarsをターゲットノードに書き出して、InSpecで利用する。
この場合、インベントリー情報やplaybook vars, set_factsなどにより設定された値も(設定後に書き出す限り)利用可能。

他に、インベントリー情報をコントローラーノード上で入手してInSpecで利用する方法が紹介されていた。
https://qiita.com/ochiba/items/5dcf93bcf423a441b1f8


#Playbook
copyモジュールを使用し、varsの内容を対象ノード上のJSONファイル (/tmp/vars.json) に保存

```yml:playbook

---
- hosts: all
  vars:
    foo:
      bar: baz
  tasks:

  - name: Dump vars for InSpec
    copy:
      content: "{{ vars | to_nice_json }}"
      dest: /tmp/vars.json

... # 処理本体
```


ユーザーが設定する特定の範囲のみの連携で良いならば必要に応じて絞り込み。

```yml
      content: "{{ foo | to_nice_json }}"
```

#InSpecテスト
InSpecテストの先頭において、InSpec jsonリソースの機能を使用して、リモートノード上のJSONファイルを読み込む

```ruby:test/integration/default/default_test.rb

vars = json('/tmp/vars.json').params

... # テスト本体
```

読み込み後、例えば vars['foo'] として {"bar"=>"baz"} を参照できる。


#参考

- [Read Chef attributes within the tests ? #541](https://github.com/inspec/inspec/issues/541)
- [ローカルのAnsibleからvagrantノードに対して収束させるtest-Kitchen環境例](https://qiita.com/hiroyuki_onodera/items/5ccbb54f00617d8472be)
- [Chefでユーザーによるdeep_mergeを必要としないnodeオブジェクトのjson書き出し](https://qiita.com/hiroyuki_onodera/items/75f6ea446d47f1c57e3e)
- [InSpecでchefのattributeを使う](https://qiita.com/dai624fuji/items/0da0544c9cff153ef230)
jsdoで複素数

#概要

jsdoで複素数やってみた。

#写真

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18104/7fa1ce8c-000e-09a5-ecec-8eddaf61de7c.png)

#サンプルコード

```
var a = new Complex(5.0, 6.0);
var b = new Complex(-3.0, 4.0);
document.write("a = " + a + "<br />");
document.write("b = " + b + "<br />" );
document.write("RealOf(a) = " + a.getReal() + "<br />" );
document.write("ImaginaryOf(a) = " + a.getImaginary() + "<br />" );
document.write("b + a = " + b.plus(a) + "<br />" );
document.write("a - b = " + a.minus(b) + "<br />" );
document.write("a * b = " + a.multi(b) + "<br />" );
document.write("b * a = " + b.multi(a) + "<br />" );
document.write("exp(a) = " + a.exp() + "<br />" );

```

#成果物

http://jsdo.it/ohisama1/4UsS

以上。
[JavaScript]正規表現(繰り返し)

# 正規表現・繰り返しについて

今回は正規表現の中の繰り返しに関する表現方法を紹介したいと思います。

以下が繰り返しに関する構文になります。

| *       |      直前の部分式が0回以上の繰り返し    |
|:-----------------|------------------:|:------------------:|
| +       |              直前の部分式が１回以上の繰り返し
| ?       |              直前の部分式が０回か１回の繰り返し
| {n}     |                直前の部分式がn回の繰り返し   
| {n,}      |             直前の部分式がn回以上の繰り返し         |
| {,m}    |           直前の部分式がm回以下の繰り返し         |
| {n,m}   |       直前の部分式がn回以上、m回以下の繰り返し          |


これらが正規表現で用いる繰り返しの表現になります。
Chainerでcupy.cuda.driver.CUDADriverError: CUDA_ERROR_INVALID_PTX: a PTX JIT compilation failedが出たときの対処法

久しぶりにchainerを使ってモデルを組んでみたら
```
cupy.cuda.driver.CUDADriverError: CUDA_ERROR_INVALID_PTX: a PTX JIT compilation failed
```
が出た。。。

https://twitter.com/__krmkrm__/status/1084011330082762752

らしいが、それでも治らない場合はcupyのバージョンと、CUDAのバージョンがずれているということだ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/295666/bfca5e53-d47f-c182-5ebd-275249cd0eb6.png)
https://docs-cupy.chainer.org/en/latest/install.html

なので、まずcupyのバージョンとCUDAのバージョンをチェックしよう。

```
nvcc -V & pip freeze | grep cupy
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/295666/5f1df014-67c7-b0ce-d600-314fe5565994.png)

自分はcupy-cuda100をダウンロードしてて、CUDA が9.1になっていた。
人によって、バージョン状況は異なると思うが、

- cupy.cuda.driver.CUDADriverError: CUDA_ERROR_INVALID_PTX: a PTX JIT compilation failed
- original error: libcublas.so.10.0: cannot open shared object file: No such file or directory

などのエラーが出ていれば、cupyとCUDAのバージョンミスマッチによるエラーであることの可能性があるので、以下の手順を試すと直るかもしれません（僕は直りました）。

1 複数バージョンのcupyがある場合は不要なバージョンをアンインストール（僕はcupy-cuda100だけにしました）。

```
pip uninstall cupy-cudaxxx

(CUDA10.0用のcupyをダウンロードする場合)
pip install cupy-cuda100
```
2 CUDA 10.0のダウンロード

https://developer.nvidia.com/cuda-10.0-download-archiveからダウンロードする

3 CUDA 10.0へ切り替える
switch-cudaをダウンロードして、実行する。

```
git clone https://github.com/phohenecker/switch-cuda

cd switch-cuda

source switch-cuda 10.0
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/295666/89f8ad22-62d9-b35f-dbea-868afa6bd44e.png)

これでcupy とCUDAのバージョンがあうので上記のエラーなく実行できるはずである。
【メモ】Pandas の read_csv でパースエラーが出たとき

# 問題

このようなエラーが出て、入力CSVファイルに問題が無いように見えて困っていた。

```
Error tokenizing data. C error: EOF inside string starting at line
```

#解決
下記に書いてあるとおり、engine='python' を指定するとエラーが起きなくなった。

[Pandas CSV error: Error tokenizing data. C error: EOF inside string starting at line](https://www.shanelynn.ie/pandas-csv-error-error-tokenizing-data-c-error-eof-inside-string-starting-at-line/)

根本的にはCSV側の問題を特定すべきだが、c engine でエラーが出ていても python engine だと回避してくれる事があるのは短期的な補修には役立つ知識だと思われる。

欠点は速度が低下すること。長大なファイルの取り扱い時には差が出てくる可能性大。
VS Code で Python の Rename Symbol ができないときの対処法

久しぶりに以前Pythonで書いたコードを開いてみたのですが，なかなかアレなコードだったので，リファクタリング（機能はそのままに，実装方法を改善すること）をすることにしました．

そのときに，名前の一括変更ができず手こずったので，対処法を共有しておきます．（要約は[こちら](#tldr)）

# Pythonのリファクタリングには，ropeのインストールが必要

Visual Studio Codeには，F2キーを押すことで，コードの中で使われている変数や関数などの名前を，一括して書き換えられる機能があります．
（cf. [Refactoring source code in Visual Studio Code # Rename symbol](https://code.visualstudio.com/docs/editor/refactoring#_rename-symbol)）

これを使って，ある関数の名前を書き換えようと思ったのですが，失敗しました．
![VSCode曰く「Renameに失敗したで」「リファクタリングしたいんやったらropeを入れてや」とのこと](https://qiita-image-store.s3.amazonaws.com/0/253921/941b5f3c-ff49-3c2f-e7cc-400b68578814.png)

どうやら，リファクタリング機能の利用には，ropeというパッケージが必要なようです．「インストールしますか」と聞かれているので，Yesを押して，よしなに実行してもらいましょう．

ちなみに，パッケージのインストールは`pip install ***`，アンインストールは`pip uninstall ***`です．
（cf. [【Python】pipの使い方 | TASK NOTES](https://www.task-notes.com/entry/20150810/1439175600) ※2015）

あと，もし権限がないとか言われてインストールできなかったら，コマンドプロンプトを管理者権限で開いて，そこで，`pip install rope`してください．

# Workspaceで開くのも忘れずに！

これで準備ができたはず！そう思ったのですが，F2キーを押し，名前を書き換え，`Enter`キーを押しても変化がありません！どうしてでしょうか？（再現VTR）
![20190331224346.gif](https://qiita-image-store.s3.amazonaws.com/0/253921/1df302f3-87e3-bd15-ed7a-29e6cc392e8d.gif)

困ったらGoogle先生に聞きましょう^^「vscode python rename symbol not working」などで調べていると次の情報がヒットしました．

[rename does not work · Issue #1260 · Microsoft/vscode-python · GitHub](https://github.com/Microsoft/vscode-python/issues/1260)
> I slove the problem . the rename does work when the file in workspace .

「ワークスペース」とやらで開いたら動いたそうです．ワークスペースって何だよっと思ったので，「Macの話ならいいや」と，スルーしていた別の記事も見てみます．

[python - Visual Studio Code (Mac OS) rename symbol doesn't work - Stack Overflow](https://stackoverflow.com/questions/55017139/visual-studio-code-mac-os-rename-symbol-doesnt-work)
> I solved the problem by first closing the open folder I was in:
>
> File > Close Folder.
>
>then navigating to a sub folder of .py file I was editing, and opening it. >In my case it was
>
>  1.  Click the little document icon in the upper left of screen
>  2.  In the welcome screen, choose "open folder"
>  3.  navigate to my desktop folder (where my .py file is)
>
>Now refactoring works as expected

要は「まずはフォルダー単位で開いて，それからファイルを開くと良いぜ」ということらしいです．
`Ctrl`+`Shift`+`E`で，VSCodeのエクスプローラを開いてみると，確かに「NO FOLDER OPENED」となっていますね．
![「NoFolderOpened」だってよ！](https://qiita-image-store.s3.amazonaws.com/0/253921/9c0222ee-2c80-cf44-43c5-5b3fd4a22fa9.png)

[Open Folder]から，カレントディレクトリ（いま開いているファイルがあるフォルダの階層）を指定しましょう．以下のように，「NO FOLDER OPENED」と書かれていた場所がカレントディレクトリの名前に変わっているはずです．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/1709101d-91b8-8a71-6ee0-cb8b061a474c.png)

あとは，開きたいファイルを選択して，F2（Rename Symbol）を実行してみます．
![ちゃんと動いたよ！](https://qiita-image-store.s3.amazonaws.com/0/253921/60388fd6-1f2c-ae4a-e5bc-176f5ea062c9.gif)

ちゃんと動きました！良かった！

ちなみに，別のフォルダを開くときは，`Ctrl` + `K`, `O` でもできます．

対処法は意外と単純でしたね．

- ropeのインストール
- ファイル単体ではなく，フォルダ単位で開くこと

これらができていなかったために，Rename Symbol に失敗したようです．

初歩的過ぎて発信されてないのか，検索力が足りないのか，日本語の情報が全然ヒットしなかったので，一連の流れも含めて書き留めておきました．誰かの時短に繋がれば幸いです．

# TL;DR

- まずはVSCodeのターミナルを開く（`Ctrl`+`@`）→`pip install rope`しよう！
- Workspaceを開く（`Ctrl`+`Shift`+`E` → Open Folder）→ファイルを選択し直そう！
MacOS10.14.4 Juman++とKNPをPythonで使う設定

homebrewでインストールします

```bash
brew tap uetchy/nlp
brew install knp jumanpp
```

pipコマンドでPyKNPをインストールします

```bash
pip install git+https://github.com/ku-nlp/pyknp
```

pythonから使えます

```python
from pyknp import Juman

jumanpp = Juman()
result = jumanpp.analysis(sen)
for mrph in result.mrph_list():
    print("見出し:%s, 読み:%s, 原形:%s, 品詞:%s, 品詞細分類:%s, 活用型:%s, 活用形:%s, 意味情報:%s, 代表表記:%s")

```

mojimoji

```bash
pip install git+https://github.com/studio-ousia/mojimoji
```
mastodonで特定のハッシュタグの画像urlを取得する

#はじめに
今回はmastodonで特定のハッシュタグの画像urlを取得するプログラムを作りました。動機は今度friends.nicoがサービス終了してしまうのでサーバ上にある画像を保存したいと考えたからです。
プログラミング初心者なので結構ガバガバなので何か指摘があったらコメントしてください。

#全体の流れ
1. モジュールインポート
2. ログイン
3. 値を決める
4. 任意の回数ループして画像urlを取得する



#プログラム
解説はコメントにだいたいかいてあるはずなので頑張ってコードとコメントを読んで理解してください。そんなに難しいものではないと思います。
また、画像のダウンロードはirvineというソフトを使いました。


```python
#マストドンにおいて特定のハッシュタグの付いた画像tootの画像のurlをすべて取得するプログラム

#モジュールインポート
from mastodon import Mastodon
import re

#login、あらかじめいろいろ取得しといて
mastodon = Mastodon(
    client_id="app_key.txt",
    access_token="user_key.txt",
    api_base_url = "https://****.***" #じぶんのインスタンスで
)




#main
hashtag = 'おっぱい' #任意のワード
max_id = 1145141919810893 #このid以下のものを取得これは下のプログラムでいうrowのリストの中にあるから適当にしらべて
get_number = 1919 #取得するtoot数
cycle = (get_number//40)+1 #ループ回数、下のやつでlimitを40回にしたのは処理を軽くするため

#ループ
while(cycle > 0):
    tl = mastodon.timeline_hashtag(max_id=max_id,hashtag=hashtag,limit=40) #tootを取得、リスト、limitは40まで
    cycle = cycle - 1 #ループ回数
    count = 0 #これはなくてもいいけどデバッグ用に置いておくあとで`print(count)`すればいい

    #画像のurlのみ取得
    for row in (tl):
        count = count+1
        if row['media_attachments'] == []:
            max_id = row['id'] #最後の['id']を取得してループ
        else:
            print(row['media_attachments'][0]['url']) #ここに[0]はさむのは辞書、リスト、辞書の内包表記になってるから
            max_id = row['id'] #最後の['id']を取得してループ
```

#注意ポイント
`mastodon.timeline_hashtag`の`limit`がの限界が40までなのでたくさんさかのぼるためには`max_id`(指定したid以下のtootを取得する)を変えていく必要があります。`while`でループしているのはそのためです。


#おわりに
ぱうーとかでつかえそうですね。

#参考にした記事
https://qiita.com/itsumonotakumi/items/1f9273a07f1f7189921f
https://toshipedia.jp/201803133574/
Rのいつもの呪文はsnippetで

RStudio でスクリプトを書く時はいつも以下を先頭に書くようにしている。これで mac でも plot/ggplot2 でちゃんと日本語が出る。いつも書くので、RStudio の Tools > Global Options... > Code > Enable code snippets の横の Edit snippets で登録しておく。以下をそのまま、コメントも空行も含めて登録できる。素晴らしい。日本語も問題ない。以下、自分のための備忘録として。「[Rをはじめよう](https://www.yodosha.co.jp/yodobook/book/9784758120951/)」からだいぶ拡張。

```R
# 
# ○○の解析
# 解析対象：
# 解析方法：
# 
# 2019/01/01 Daisuke TOMINAGA

library(tidyverse);
library(ggfortify);                                   # lm()/glm() で autoplot() したいから
rm(list=ls());                                        # スクリプティング試行錯誤用
par(family = "HiraKakuProN-W3");                      # plot() で日本語 on mac
theme_set(theme_bw(base_family = "HiraKakuProN-W3")); # ggplot で日本語
```
![RStudio_global_options_code.png](https://qiita-image-store.s3.amazonaws.com/0/377279/94676176-21b1-0610-1d3d-b9de7d144695.png)
![RStudio_edit_snippet.png](https://qiita-image-store.s3.amazonaws.com/0/377279/671fdbb0-9569-4780-55f9-0549138b496f.png)
SQLite3でデータ中の文字列を一部分だけ置き換えたい

# はじめに

ちょっと修正したいと思っていたら、意外と簡単にできたのでメモ。

# 環境

以下のようなテーブルがあります。

- テーブル名  
  位置情報

|項目|内容|
|---|---|
|日時|yyyy-mm-dd HH:MM:SS形式の文字列|
|緯度|実数|
|経度|実数|

ここで、PCの日付設定が間違っていて、2019年3月30日のデータが2019年2月18日として登録されていることがわかった。

# SELECT文で確認

```sql:
SELECT 日時, REPLACE(日時, "02-18", "03-30") FROM 位置情報 WHERE 日時 LIKE "%02-18%";
```

上記のSQLを実行すると以下の結果が返ってきた。

```
2019-02-18 05:52:07|2019-03-30 05:52:07
2019-02-18 05:52:15|2019-03-30 05:52:15
2019-02-18 05:52:17|2019-03-30 05:52:17
2019-02-18 05:52:19|2019-03-30 05:52:19
2019-02-18 05:52:21|2019-03-30 05:52:21
2019-02-18 05:52:23|2019-03-30 05:52:23
2019-02-18 05:52:25|2019-03-30 05:52:25
2019-02-18 05:52:27|2019-03-30 05:52:27
2019-02-18 05:52:29|2019-03-30 05:52:29
2019-02-18 05:52:31|2019-03-30 05:52:31
2019-02-18 05:52:33|2019-03-30 05:52:33
2019-02-18 05:52:35|2019-03-30 05:52:35
2019-02-18 05:52:37|2019-03-30 05:52:37
2019-02-18 05:52:39|2019-03-30 05:52:39
2019-02-18 05:52:41|2019-03-30 05:52:41
2019-02-18 05:52:43|2019-03-30 05:52:43
2019-02-18 05:52:45|2019-03-30 05:52:45
```

# UPDATE文で更新

```sql:
UPDATE 位置情報 SET 日時 = REPLACE(日時, "02-18", "03-30") WHERE 日時 LIKE "%02-18%";
```

できた！
Javaで関数型っぽくクイックソートを実装する

# はじめに
Javaでlambda式やStreamを使ってクイックソートを実装してみました．
この記事の対象読者は次のような人です．

- Scalaを習得している人
- Javaの関数型っぽい機能に入門したい人


# lambda式
lambda式は`(引数)->戻り値`の形式で書くことができ，applyメソッドで関数を呼び出すことができます．

```java
import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function<String, String> addHoge = (final String str) -> str + "hoge";
        System.out.println(addHoge.apply("fuga"));
    }
}
```
また，式を複数書きたい場合はブロックを利用することが可能です．

```java
import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function<String, String> addHoge = (final String str) -> {
            String hoge = "hoge";
            return str + hoge;
        };
        System.out.println(addHoge.apply("fuga"));
    }
}
```

# Stream
Streamとはコレクションの要素に対して関数型の操作をサポートするクラスです．コレクションクラスの`stream()`メソッドを呼び出すことにより，Streamを利用することができます．

`stream()`を使って2の倍数を表示するプログラムを書くと，次のようになります．

```java:Java
Arrays.asList(3, 21, 34, 0).stream().filter(n -> n % 2 == 0).forEach(System.out::println);
```

Scalaだと次のようになります．Javaと比較すると`stream()`を書く必要がない分，コードがシンプルになります．

```scala:Scala
List(3, 21,34, 0).filter(_ % 2 == 0).foreach(println)
```

# ソースコード(Scala)
Javaでクイックソートを実装する前に，Scalaで実装したコードを示します．
クイックソートの`pivot`は配列の先頭に指定しています．

```scala
object Main extends App {
    println(quickSort(List(3, 21, 34, 0, -30, 55, 10)))
    
    def quickSort(nums: List[Int]): List[Int] = {
      nums.headOption.fold(List[Int]()){ pivot =>
        val left = nums.filter(_ < pivot)
        val right = nums.filter(pivot < _)
        quickSort(left) ++ List(pivot) ++ quickSort(right)
      }
    }
}
```

# ソースコード(Java)
次にJavaでクイックソートを実装したものを示します．

Scalaのコードと見比べると，Javaのコードの多さに圧倒されますが，ロジック自体はほぼ同じような実装になっていると思います．

ロジックに関して，唯一異なる点をあげるとしたら，foldメソッドです．Scalaのコードにはfoldメソッドを使っている箇所が存在しますが，JavaのOptional型(ScalaでいうOption型)にはfoldメソッドは存在しません．その代わりにmapメソッドとOrElseGetメソッド(ScalaでいうgetOrElseメソッド)を組み合わせて使用しています．

```java
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static java.util.stream.Collectors.toList;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        final List<Integer> nums = Arrays.asList(3, 21, 34, 0, -30, 55, 10);
        final List<Integer> sorted = quickSort(nums);
        System.out.println(sorted.toString());
    }

    private static List<Integer> quickSort(final List<Integer> nums) {
        return nums.stream().findFirst().map((final Integer pivot) -> {
            final List<Integer> left = nums.stream().filter(n -> n < pivot).collect(toList());
            final List<Integer> middle = Collections.singletonList(pivot);
            final List<Integer> right = nums.stream().filter(n -> pivot < n).collect(toList());
            return Stream.of(quickSort(left), middle, quickSort(right)).flatMap(Collection::stream).collect(toList());
        }).orElseGet(Collections::emptyList);
    }
}
```
Spring Boot メールで添付のファイル名が文字化けしたのでその対策

## メールの添付ファイルが文字化けする
```
org.springframework.boot:spring-boot-starter-mail
```
Web上にもQiitaにも沢山あるSpringのメール送信方法を使って添付ファイルを送信してみたら、添付ファイル名が見事に文字化けしていました。
<img width="308" alt="Screen Shot 2019-04-01 at 08.00.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/375776/79df5f9b-b149-3bb3-c59b-dd34b08014d9.png">

どうやらファイル名が日本語のみの場合はOKですが、ファイル識別子が入ったりするとこの文字化けが起こるようです（ここは詳しく調査していない）

```

    private void sendMail(File file) throws MessagingException, URISyntaxException, IOException {
        JavaMailSender sender = this.getMailSender();
        
        MimeMessage message = sender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true, StandardCharsets.UTF_8.name());
        
        String toAddr = this.mailToAddr;
        helper.setTo(toAddr);

        // 複数CCアドレスに対応（カンマ区切り)
        if (!StringUtils.isEmpty(this.mailCcAddrs)) {
            String[] ccAddrArr = this.mailCcAddrs.split(",");
            helper.setTo(ccAddrArr);
        }
        String subject = "テストメールです"; 
        helper.setSubject(subject);
        
        // メール本文テンプレ取得
        Path path = Paths.get(getClass().getClassLoader()
                .getResource("mail_template.txt").toURI());
                    
        Stream<String> lines = Files.lines(path);
        String template = lines.collect(Collectors.joining("\n"));
        String body = template.replace("[[Replace]]", toAddr);
        lines.close();
        helper.setText(body);
        
        // ファイル添付
        helper.addAttachment("添付ファイルの名称です 添付は template.txt", file);
        
        sender.send(message);
    }
```

## 以下の点を修正

### 添付ファイルのファイル名を一旦加工する

```
MimeUtility.encodeWord("ファイル名");
```

![Screen Shot 2019-04-01 at 07.59.36.png](https://qiita-image-store.s3.amazonaws.com/0/375776/131adab2-1017-17e7-a00e-1ac273ab1e0c.png)

### システムプロパティにメールの設定を追加する
最初の MimeMessage インスタンス作成の前にこのプロパティを変更しておく

```
System.setProperty("mail.mime.splitlongparameters", "false");
```
![Screen Shot 2019-04-01 at 07.59.20.png](https://qiita-image-store.s3.amazonaws.com/0/375776/ee6e271e-3994-01c6-86e6-06955289eeee.png)


## 上記修正後のファイル名を確認
<img width="304" alt="Screen Shot 2019-04-01 at 08.00.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/375776/a32df2ea-8b98-6860-0e33-34fc4fd4bd75.png">
Node.jsでkintoneにファイルアップロードする

最近よく利用するのでメモします。


```upload.js
const DOMAIN = 'sample.cybozu.com';
const AUTHORIZATION = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

const axios = require('axios');
const formdata = require('form-data');
const path = require('path');
const fs = require('fs');

const uploadFile = async (filePath) => {
    const url = `https://${DOMAIN}/k/v1/file.json`;

    const form = new formdata();
    form.append('file', fs.readFileSync(filePath), path.basename(filePath));

    const config = {
        headers: {
            'X-Cybozu-Authorization': AUTHORIZATION,
            'Content-Type': form.getHeaders()['content-type']
        }
    };

    try {
        let res = await axios.post(url, form, config);
        return res.data.fileKey;
    } catch (err) {
        console.log('err', err);
        throw new Error(err);
    }
}

async function main() {
    let filePath = './image.png';
    let fileKey = await uploadFile(filePath);
    console.log('fileKey', fileKey);
}

main();
php-master-changes 2019-03-31

今日はドキュメントの修正、一部開発者向けドキュメントの docs 下への移動、テストの修正、Windows でのビルドツールの修正、メモリリークの修正、拡張ロード時の DLL 互換性チェックの厳密化、preg_match() が CRLF の "\r" を無視しない問題の修正があった！

# 2019-03-31
## petk: [ci skip] Add ffi_parser.c info
- https://github.com/php/php-src/commit/04a9d6b915dbd98649363c8853b896163dc4e99f
- [7.4~]
- CONTRIBUTING.md のソースコードガイドに ffi_parser.c の情報を追記

## mbeccati: Fixed SKIPIF when --disable-mbregex is used
- https://github.com/php/php-src/commit/0dbb581cf4d7e99cadda368c9edce5a721dc4036
- [7.2~]
- ext/mbstring で、--disable-mbregex 利用時のテストスキップ条件の修正
- [先日の修正](https://qiita.com/sj-i/items/47539e0ff8cf81c828c7#mbeccati-fixed-skipif-when---disable-mbregex-is-used)と同様

## mbeccati: Fixed SKIPIF when --disable-mbregex is used
- https://github.com/php/php-src/commit/263c58785433a555a56cd6226a9fa96cf699a7f5
- [7.3~]
- ↑と同様

## petk: Move README files to a dedicated docs directory
- https://github.com/php/php-src/commit/8346b4c9f149c1a3d4e0631007e71bbbebd0b87d
- [7.4~]
- READNE.ﾅﾝﾁｬﾗｶﾝﾁｬﾗ をだいぶ docs 下へ移動
- [PR:3988](https://github.com/php/php-src/pull/3988) に議論の過程
- [まただいぶスッキリ](https://github.com/php/php-src/tree/8346b4c9f149c1a3d4e0631007e71bbbebd0b87d)したけど、もうちょっといけるのではないか多分

## weltling: Use wchar_t as native type in C
- https://github.com/php/php-src/commit/22091084fa40bf62a6d9ff55eff9518dd1560a95
- [7.4~]
- Windows 用のビルド時、VC の 1914 以上では [/Zc:wchar_t](https://docs.microsoft.com/en-us/cpp/build/reference/zc-wchar-t-wchar-t-is-native-type?view=vs-2017) を指定するよう修正

## weltling: Fix memory leak
- https://github.com/php/php-src/commit/a2c87c7f29929760e75e0357388dd39b9c7b42f7
- [7.3~]
-  win32/readdir.c で、メモリリークの修正

## weltling: Fix memory leak
- https://github.com/php/php-src/commit/ba2269ab9e88e6acc4f3626527ed5ccd24f02872
- [7.4~]
- [parse_str()](https://www.php.net/manual/ja/function.parse-str.php) の実装でメモリリークの修正

## krakjoe: correct readme [ci skip]
- https://github.com/php/php-src/commit/79c6636f15d6d7334ff75a2e73090b9454121a15
- [7.4~]
- README の修正、ビルドしてテストしてインストールみたいな

## krakjoe: typo [ci skip]
- https://github.com/php/php-src/commit/2c78b80e1e7656fd5bbed3a35ca8c3d8be213f15
- [7.4~]
- README で、typo の修正

## cmb69: Fix [#77827](https://bugs.php.net/bug.php?id=77827): preg_match does not ignore \r in regex flags
- https://github.com/php/php-src/commit/88460c017a06ce8865f1adcc8f70e511cf776e06
- [7.2~]
- ext/pcre で、preg_match() が正規表現フラグで CRLF の "\r" を無視しない問題の修正

## weltling: Implement stricter extension compatibility check
- https://github.com/php/php-src/commit/ddce7ada4c319dafa5cead0c0fb560a659f0763e
- Windows 版で、拡張ロード時にコアとの互換性チェックを厳密化

## weltling: Rework the VS version evaluation
- https://github.com/php/php-src/commit/6a624c1dfda0dbfaaff3e453e6cb58de12748fb3
- [7.4~]
- Windows 版で、VS のバージョンチェックを修正
- バージョン上がってもうまいこと判定していくの大変みたい

## weltling: Fix return
- https://github.com/php/php-src/commit/e4a664ecf84fb74ecb8046deb77a1218f2f6cb62
- [7.4~]
- Windows 版で、[先の修正](#weltling-implement-stricter-extension-compatibility-check)で返り値 void なのに FAILURE 返してたのを修正
360°写真が楽しすぎるので、360°用SNSを作ってみた話

# 要約
Nuxt.js x Firebaseで360°写真共有SNSを作りました。
360GRAMは[こちら](https://360gram.me/)。

# 作ったサービス
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【新サービスリリース】<br>Instagramがなかなか対応しないので、360°写真専用のSNSを作りました。<br><br>まだまだ機能は少ないですけど、thetaで撮った写真とか共有場所で困ってる人は是非上げてみてください！<br><br>360GRAM<a href="https://t.co/RMyokPf3Qy">https://t.co/RMyokPf3Qy</a><a href="https://twitter.com/hashtag/web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9?src=hash&amp;ref_src=twsrc%5Etfw">#webサービス</a> <a href="https://twitter.com/hashtag/%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BA?src=hash&amp;ref_src=twsrc%5Etfw">#個人開発</a> <a href="https://twitter.com/hashtag/360GRAM?src=hash&amp;ref_src=twsrc%5Etfw">#360GRAM</a></p>&mdash; 蟹江 東 (@kanieeast) <a href="https://twitter.com/kanieeast/status/1112234381114900480?ref_src=twsrc%5Etfw">March 31, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

いいね、コメントなど基本機能あるよ
![360gif4.gif](https://qiita-image-store.s3.amazonaws.com/0/18699/042a290d-783d-003a-195d-9f9e27198994.gif)

# なぜ作ったか
* 360°写真は普通の写真と違った面白さがあって好き
* Instagramが360°写真に対応していない→360°写真の共有場所がない
* Nuxt.js x Firebaseでなにか作りたい→作った

# 使った技術
* [Firebase](https://firebase.google.com/)

まぁみんなもはや知ってるよね。いわゆるMbaaSとかというやつです。
今回は、Firebaseの中の
・認証
・storage
・Firestore（DB）
・Hosting
を使っています。


* [Pannellum](https://pannellum.org/)

パノラマ写真ビューワーライブラリです。こういう系のライブラリは結構あって、いろいろ見比べてみて、今回はPannellumを使いました。

* [jimp](https://www.npmjs.com/package/jimp)

<img src="https://qiita-image-store.s3.amazonaws.com/0/18699/abe02247-70f9-c49d-661a-9963dc73d60d.png" width="100px">

クライアントサイドで画像を圧縮したりするライブラリです。

# 苦労したところ
## iPhoneは4096pxの大きさの写真までしか表示できない問題
これ、実際に動作確認してて気づきました…
360°写真は基本横にめちゃ長いわけです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/18699/b6b02e26-a15d-e7f0-b008-a7a532306469.jpeg" width="300px">

取り急ぎjimpで、画像が4096pxより大きい場合は、2000pxまで圧縮しています。

## cors問題
corsについては[こちら](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)を。  
先程書いたように、Pannellumを使ってパノラマを表示しています。そして、Pannellumはブラウザ上（`360gram.me`）で動きます。
一方画像自体のドメインは`firebasestorage.googleapis.com`であり、`360gram.me`と異なるので、設定でリソースへのアクセスを許可してあげなければなりません。
この問題に関しては、以下の記事で解決できました。
[Firebase StorageにCORSの設定をする - Qiita](https://qiita.com/niusounds/items/383a780d46ee8551e98c)

# もっとユーザーが増えたら実装したい機能
* フォロー
    * ほしい
* ハッシュタグ
    * ほしい
* 検索機能
    * 大変そう
* 位置情報タグ付け

# 感想

いままでゴミみたいなサービスを割と作ってきて、今回でやっと、Nuxtスキルも少し上がったかな、と思えました。
Nuxt.js x Firebaseも自分に染み付いてきて、昔と比べると結構モダーンになったな、と（昔はCakePHP x さくらインターネットの月500円サーバ）。  
あと、今まで自分はサービス作ってて途中で飽きてしまうことも多かったのですが、今回はほんとに自分がユーザーになれるものを作ってて飽きずにやれたので、やはりそこら辺の、そもそも何を作るのかを決めるあたりから大事だな、と実感できました。

# 終わりに
まだまだ360°写真を撮ってる方は少ないと思いますが、今回[360GRAM](https://360gram.me/)という置き場所を作りましたので、theta等デバイスを持っている方は、ぜひぜひ360GRAMでシェアしてみてください:camera:

[ワイキキにて](https://360gram.me/p/e62d89e7ab444e4d86fd9a77e99d7434)
<img width="1280" alt="Waikiki 2019-03-31 16.14.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/18699/9e6e1360-d4c0-b98d-7dcf-07a8e3bf20c3.png">


ではでは

English: https://medium.com/@taishi.k/360gram-my-nuxt-js-app-with-firebase-for-sharing-360-pictures-ba4c487b77bc
HTMLとヒトの感性

素晴らしいWEBサイトとは？一覧表にした価格コムのような素晴らしいサイトがある。これはもちろん、ブログや普通のサイトとは違った作りになっています。

リアルタイムに更新されていく一覧表。情報化社会の中で、最安値を比較するという独自の価値を持っています。HTMLというよりは複数の言語を組み合わせたサイトで、我々のような一般のサイト運営者には手出しができないものです。

価格コムはただの比較サイトではない。真似のできない価値を持っているから、指名検索もされて口コミで広がっていくのです。

しかし商品やサービスを数字でとらえるなら、客観性のある情報が必要です。PCならCPUが何ヘルツか、メモリがどのくらいか。しかしそのメーカーのパソコンの評価（使いやすさ、トラブル、耐久性等）は客観性のあるデータが出ません。

つまり口コミなのです。HTMLでは吹き出し形式の口コミが流行ってますが、表よりも生のヒトの意見を参考にする人々も多いのです。Google検索を使わずに、ツイッター検索やインスタグラムで検索する。そこには生のヒトの声があるからです。

サイト制作でも整理された情報サイトを作るか、ユーザーが参考になるようなレビューサイトを作るかがあります。どちらも人気で需要のあるものです。<a href="https://game-uru-ps-wii-ds.net/is-good-where-if-sell-the-game/" >ゲームサイトの例</a>のように、比較とレビューを組み合わせるのも王道パターンです。

人気サイトがやってることを真似する。アマゾンや楽天でも、ランキングやレビューは当然にあるものです。比較することと、口コミ。HTMLでは文字を打つことと、プログラミングでサイトを作ることの二通りがあるのです。
TinyPNGのAPIクライアントtinifyの使い方 [画像サイズの最適化]

webサービスに画像サイズの最適化でよくお世話になるのが[TinyPNG](https://tinypng.com/) です。
ただ大量に画像ファイルがある時、いちいちサイトでアップロード、ダウンロードは大変ですよね。
TinyPNGをAPI経由で利用するためのnode_moduleがあったので紹介します。
（API経由での最適化は月500ファイルと制限はあります。)

# プロジェクトの作成とtinifyの追加
まず作業ディレクトリの作成と、tinifyの追加を行います。

```
$ mkdir tinify-demo
$ cd tinify-demo
$ mkdir src dest
$ npm init -y 
$ yarn add -D tinify 
```

# TinyPNGのAPIキーの取得
TinyPNGのAPI-clientの利用にはAPIキーが必要です。
https://tinypng.com/developers
より、メールアドレスの登録をすれば取得できます。

<img width="1117" alt="スクリーンショット 2019-04-01 7.38.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/114396/0d6fdead-9a78-3bf2-284c-bee777eb12ae.png">



# index.jsの作成
実際の処理を行うindex.jsを書いていきます。
tinifyの最適化は以下数行のコマンドだけで利用できます。

```js
const tinify = require("tinify");
tinify.key = "APIキー";
 
tinify.fromFile("対象ファイルのパス").toFile("出力ファイルのパス");
```

今回はsrc以下の画像すべてを圧縮対象とするので、node.jsのfsを使ってファイルを取得し、ループで回すようにしました。

```
$ vi index.js
```

```js:index.js
const fs = require('fs');
const tinify = require('tinify');
tinify.key = 'TiniyPNGのAPIキー';

const srcDir = './src/';
const destDir = './dest/';
const targetFileType = /.*\.(png|PNG|jpeg|jpg|JPG|JPEG)$/;

const optimizeImage = async function (file) {
  const srcFile = srcDir + file;
  const destFile = destDir + file;

  // 最適化処理
  await tinify.fromFile(srcFile).toFile(destFile);

  // log
  console.log(`${file}  => ${Math.round(
      fs.statSync(destFile).size / fs.statSync(srcFile).size * 100)} %`);
};

fs.readdir(srcDir, (err, files) => {
  // 対象のファイルに対して最適化を実行
  files.filter(file => file.match(targetFileType)).forEach(file => {
    optimizeImage(file)
  })
});
```

あとは、node.jsでindex.jsを起動すればOKです。

```bash
$ node index.js
sample1.png  => 23 %
sample2.png  => 26 %
sample3.jpg  => 77 %
```
Docker(CentOS)イメージから新規ユーザを追加し運用できるようにするまで

##概要
DockerのCentOSイメージに新規ユーザを追加し、そのユーザで運用していける状態にする。最後にDockerfileを置いているので、手っ取り早く環境作りたい人はそちらを使ってみてください。

そもそもDockerだからrootで全部やればいい、という考えもあるので、この記事はrootでOKな人以外に向けた記事になります。
本番環境を想定して、root許可されてない同じ環境で試したい、そういう方に向けた記事になります。

##環境
CentOS Linux release 7.6.1810 (Core)

補足
macOS High Sierra 10.14.3
Docker version 18.09.1, build 4c52b90

##手順

###イメージの取得

CentOSのイメージを取得する。最新バージョンでよいのでバージョンの指定はしない。

```
docker pull centos
```

###起動
私はバックグラウンド起動する人なので-dオプションつけます。exitしたり複数コンソールからexecしたりするので。

```
docker run -d centos:latest /sbin/init
```

###実行
コンテナIDは起動時に表示されます。
もしくは docker ps コマンドでも確認できます。

```
docker exec -it コンテナID /bin/bash
```

### sudo権限付与
ユーザを追加してsudo権限を付与する。

####sudoインストール
```
yum -y update && yum clean all
yum -y install sudo
```

####ユーザ追加
```
useradd -m ユーザ名
```

####パスワード設定
```
passwd ユーザ名
```

####sudo設定
```
echo 'ユーザ名 ALL=(ALL) ALL' >> /etc/sudoers
```

##確認
作成したユーザでsudoできるか確認する。

```
su - ユーザ名
sudo コマンド
```


##Dockerfile
手順で実行したコマンドをDockerfileで書くと以下のようになる。
パスワードをコマンドライン上に書きたくない場合は、ログイン後に設定するようにDockerfileを書き換えてください。

```
FROM centos:latest
MAINTAINER kashipan

ARG USER
ARG PASSWD

RUN yum -y update && yum clean all && \
    yum -y install sudo && \
    useradd -m $USER && \
    echo "$USER:$PASSWD" | chpasswd && \
    echo "$USER ALL=(ALL) ALL" >> /etc/sudoers
```

###ビルド(イメージ作成)
--build-argでDockerfileで使用する変数を与えることができる。
Dockerfile配置ディレクトリで実行する場合は下記のコマンドです。

```
docker build -t イメージ名:タグ名 . --build-arg USER=ユーザ名 --build-arg PASSWD=パスワード
```

###ビルド後の確認
想定通りユーザが作成されていること、sudoでコマンド実行できることを確認する。

####起動

```
docker run -d イメージ名:タグ名 /sbin/init
```

####ユーザ指定でシェル実行

```
docker exec -u ユーザ名 -it コンテナID /bin/bash
```

※追記(2019/04/12)
上記ユーザ指定のシェル実行の場合、bash設定ファイルも読み込まれないし、通常のログインようになってくれない。
su でユーザ切り替える下記の方法がよいかと。

```
docker exec -it コンテナID su - ユーザ名
```

####sudo確認
なんでもいいですが、visudoでDockerfileで指定した設定が書き込まれているか確認する。下記のコマンドが実行できること、また一番下の行に```echo "$USER ALL=(ALL) ALL"```があることが確認できればいいです。

```
sudo visudo
```

以上！
オンプレミスの基幹システムをAWSに移行することになった話 1


# 初期スペック
* 社内SE
* 基幹システムを中心にWAMP環境でPHP歴10年ほど
* インフラ部分はWAMPであれば数回構築経験あり。設定ファイルのメジャーなパラメータなら理解してる。
* ルーターなどのネットワーク機器については、家のルーター設定できるくらいのレベル。DHCPあたりは知ってる。
* AWSはほぼ触ったこと無し

# はじめに
オンプレミスのサーバー寿命がそろそろ尽きるとのことで、買い替えするか、クラウド化するかというところで
新しいもの好きな自分はクラウド化を選択。
元々は付き合いのあったAWSパートナーの会社に依頼していましたが、基幹システムのスペックで構築すると
ランニングコストが厳しく、内製化する方向に。
2018年の11月から移行担当となり、現在(2019年4月)も対応中。
それなりに移行も最終段階になりつつあるので、これまでの対応内容などを少しずつ記録していこうと思います。

# 更新頻度
１Hくらいでまとめられた分だけ書いていきます。



 [オンプレミスの基幹システムをAWSに移行することになった話 2](https://qiita.com/Johnney/items/08dc050573a7b6499e43)
Digdagアーキテクチャについて

概要についてはこちら
https://qiita.com/dich1/items/feb9354378862d7c7e94

アーキテクチャページついて(部分意訳・要約)
http://docs.digdag.io/architecture.html

## 定義
### タスク
1バッチのこと

### オペレーター
処理の命令のこと

### ワークフロー
複数バッチが実行される、1ファイルのこと

### プロジェクト
.digのファイル名と同じディレクトリにある他のファイル

## 実行環境
下記3つでの実行が可能

- ローカル
- digdagサーバー
- dockerコンテナ

## ワークフローエンジンについて
様々な手動バッチ操作を、オペレータープラグインによって自動化する

- タスクが失敗すると警告を通知する
- ワークフローが想定時間内に終了しない場合、通知をする
- 定義を見直す時は、鳥瞰図をイメージしながら詳細を追うとデバッグや確認が容易になる

## タスクのグループ化について
タスクはグループにまとめることができる

- 依存関係のないタスクは並列的に実行される
- 依存関係のあるタスクは直列的に実行される
- 子のタスクが全て成功すると、親のタスクも成功する
- 子のタスクが失敗すると、親のタスクも失敗する
- ルートのタスクが失敗するか成功すると、実行全体が終了する

グループ化されている粒度を意識して読み込むことで把握がし易い

### パラメータについて
- グループ化したタスクの内、親タスクに定義した変数の情報は、子タスクでもエクスポートをすることで使用できる
- 親のタスク実行時に子のタスクが生成される。前のタスクの結果に応じて様々なタスクを実行できる

## 実行
- 起点となる.digファイルをdigdag runコマンド経由で実行する
- サーバー上で実行したい場合はプロジェクト(ディレクトリ)単位でプッシュできる
- dockerを使用する際は起点となる.digファイルにオプションを設定しておく
- デフォルトではイメージをキャッシュし再利用する
- 常に最新を利用したい場合pull_always：trueオプションを指定する


## URL情報
http://docs.digdag.io/architecture.html

## 雑感
構成はシンプルである気がする
macros & regex - two headed monsters

they are so hard and esoteric that very few even attempt to put any questions let alone answer them.  well, there are some ways to make life easier dealing with them as the following shows.  but that doesn't change the fact that lisp macros are quite different:rolling_eyes: and emacs regex sucks big time:frowning2:
#macros
there's a nice package called **macrostep.el** that allows on the spot macro expansion and is widely mentioned in forums and blogs; only i didn't know about it until recently:sweat_smile:  do make the following change not to compile macros during expansion:

```
(defadvice macrostep-expand (around macrostep-expand-no-compile activate)
  (flet ((byte-compile (s) s))
    ad-do-it))
```

#regex
there's a builtin package called **re-builder.el** but it's a bit clunky:tools: to use imo even with the addition of **pcre2el.el**.  so what i do is use **anzu.el** (who doesn't?) and define some operations in **isearch-mode-map**.
###customize anzu
```
(require 'anzu)
(global-anzu-mode +1)
(global-set-key [remap query-replace] 'anzu-query-replace)
(global-set-key [remap query-replace-regexp] 'anzu-query-replace-regexp)
(unless (keymap-parent lisp-mode-shared-map)
  (set-keymap-parent lisp-mode-shared-map prog-mode-map))
(define-key prog-mode-map [convert] 'anzu-query-replace-at-cursor-thing)
(put 'anzu-mode-lighter 'risky-local-variable t)
(setq anzu-mode-lighter `(" " ,(propertize "杏" 'face 'anzu-mode-line)))
```
###customize isearch
```
(define-key isearch-mode-map (kbd "C-S-y")
  (lambda ()
    "Pull string from kill ring into search string literally."
    (interactive)
    (setq isearch-yank-flag t)
    (let ((string (current-kill 0)))
      (if (eq (string-to-char string) ?\") (setq string (read string)))
      (isearch-process-search-string
       string
       (mapconcat 'isearch-text-char-description string "")))))

(define-key isearch-mode-map [convert]
  (lambda ()
    "copy escaped regex string & exit"
    (interactive)
    (when isearch-regexp
      (kill-new (format "%S" (if pcre-mode (pcre-to-elisp isearch-string) isearch-string)))
      (isearch-exit))))
```
with that, you can paste existing regex strings into **isearch** and when you are satisfied with the regex hits after some edits, copy the final **isearch** regex string into the kill ring:zap: ready for use in font locks and regex searches:ocean:
###pcre2el
if you use **pcre2el.el**, maybe the following is helpful:

```
(require 'pcre2el)
(add-hook 'prog-mode-hook 'rxt-mode)
(setq reb-re-syntax 'pcre)
```
if you activate **pcre-mode**, the above **isearch** works in **pcre** regex.  but the author of this package warns **pcre-mode** is experimental so use it at your own risk:skull_crossbones:
【新年度リリース】ECサイト外税化 

新年度になりました。

みなさん新年度最初のリリースは何を行いましたか？
私はECサイトを外税化しました。

## なぜやったか？

登録されている価格値は全て税込価格だったのですが、5% → 8% 増税の際には価格値を全て更新していました。

税率, 税金額の情報を持っていませんでした。

競合他社が外税で運用しているため、ユーザー目線だと一見はこちらの価格の方が高いと思われることがありました。

そして、新年度がスタートするから。
(取引先によりますが、公的機関だと年度の途中で内税→外税の変更はしてはいけない決まりがあるそうです)

## やったこと

ざっくり一覧

### 1.ユーザーサイド

* 外税金額表示に
 * 商品金額, 送料など 
* レジでの税金額算出, 表示
 * 商品金額合計 + 送料から算出
 * 割引もあれば割引後に算出
* 注文毎に税率, 税金額を保存
* 注文履歴の表示変更
 * 過去のものは内税表記のまま 

### 2.管理画面サイド

* 注文履歴
 * ユーザーサイド同様 
* 価格一覧
 * 外税額, 内税額どちらも表示
* 価格登録画面
 * 入力値に対しての税込額を表示
 * 購入時の税込金額は単価でなくもろもろの合計に掛かるので、ここでの税込表記はあくまでも見込み値となる
* 売上確認画面
 * 内税, 外税どちらも表示
 * 営業確認用
     * 内税購入での売上からは外税の見込み値を算出
     * 外税購入での売上からは内税の見込み値を算出

### 3.バッチ実装

リリース当日に流すやつ

* 価格バックアップ作成
* 価格値一括更新
* カート内金額一括更新

## ポイント

### 数ある決済手段

クレジットカード, コンビニ. ATM, 銀行ネットなどいろいろな決済方法を選べる場合が多いと思います。
決済代行会社を使われている場合は、そちらに注文情報(主に支払い方法と支払い金額)を渡せば問題ないですが、
(今回の場合) paidy決済は例外でした。

きちんと仕様を確認すれば問題ないですが、 [paidy API reference 2-1-2 Orderオブジェクト](https://paidy.com/docs/api/jp/index.html#2-1-2-order)
税金額を渡さず合計金額に齟齬が出るとエラーになってしまいます。

### 税率の保存

DB設計の際、値は消費税8%の8を持たせることにしました。
では、型はintegerか？

次の増税では10%になるのでintegerで問題はないかもしれませんが、
海外では小数点ありの税率があるそうです。
例: インドで12.5%
[全国間税会総連合会 世界の消費税(付加価値税)152ヵ国](http://www.kanzeikai.jp/img/f_users/r_6823811img20180928155338.pdf)

今後の税率がどうなるかはわかりませんが、小数点を考慮しておいても良いかもしれません。

### 金額更新

税込額 → 税抜額への変換になりますが、8%なのでほぼ割り切れません。
小数点以下の扱いは社内や取引先との決めの問題になるかと思います。

その結果、切り捨て, 切り上げ, 四捨五入になるかは商品によって異なりました。
なので、価格値一括更新は上記を考慮する必要があります。
※ ここは価格設定の話で、ユーザーが購入する際の端数処理は統一となります。

しかし、カート内金額の一括更新では以下にも注意が必要です。

* 商品がキャンペーン中(割引対象中)ではないか？

本システムの場合、カート内の金額情報には割引が適応された金額が入る仕様でした。
逆算でも問題なかったかもしれませんが、
今回は商品IDから税抜価格に更新した価格テーブルの値を元に、再度キャンペーン価格の計算をしました。

## 所感

15年近く運用しているサービスだったこともあり、レジフローや売上集計周りのコード,設計がとにかく古かった。
サービスの歴史を感じた。

価格設定から売上集計まで一連の流れを把握する必要があった。
ユーザーサイドから管理画面サイドの仕様も把握する必要があった。

社歴は長い方なので、大抵の仕様は把握してましたが 
本件に関してはブラックボックスすぎた。。。

後は、何事もトラブルが起きないことを祈るばかりです。
プログラム初心者のためのC#入門 #2 型

# #2 型
今回は型について説明します．
型には値型と参照型があり，それぞれ違った特性を持っています．
##値型
値型はデータを直接保持するものです．変数自身がデータであると考えておいてください．

###整数型
その名の通り整数を扱う型です．

|型名|扱えるデータ|
|:-:|:-:|
|byte|0～255の整数|
|sbyte|-128～127の整数|
|short|-32768～32767の整数|
|ushort|0～65535の整数|
|int|-2147483648～2147483647の整数|
|uint|0～4294967295の整数|
|long|-9223372036854775808～9223372036854775807の整数|
|ulong|0～18446744073709551615の整数|
整数リテラルを入力すると，自動でint型，uint型，long型，ulong型のうち，その値を格納できる最も範囲の狭い型(大抵の場合はint型)として処理されます．なので，uint型，long型，ulong型であることを特別強調したい時はサフィックスを付けます．

|型|サフィックス|
|:-:|:-:|
|uint|u / U|
|long|l / L|
|ulong|u / U または l / L または ul / UL または lu / LU|

    214                   // int型
    214u                  // uが付いているのでuint型
    2147483648            // int型の範囲を超えているのでuint型
    2147483648L           // Lが付いているのでlong型
    9223372036854775807u  // uが付いていて，uint型の範囲を超えているのでulong型

###浮動小数型
コンピュータで実数を扱う際，浮動小数(詳しくは知りませんが小数点を動かしてごにょごにょするみたいです)という考え方で近似的に表すのでfloat型と呼ぶようです．double型は倍精度浮動小数とも言われ，大体倍の精度になるため，double型です．decimal型は，float型，double型よりも扱える値の範囲が狭い代わりに精度が高く，2進小数で正確に表すことができない0.1などを正確に表すことができます．

|型名|扱えるデータ|
|:-:|:-:|
|float|±1.5e-45～±3.4e38の浮動小数|
|double|±5.0e-324～±1.7e308の浮動小数|
|decimal|1.0e-28～7.9e28の浮動小数|
実数リテラルも入力すると自動的にdouble型として扱われるため，float型，decimal型を表す際はサフィックスをつけます．また，上記のような指数表記もできます．

|型|サフィックス|
|:-:|:-:|
|float|f / F|
|decimal|m / M|

    3.1        // double型
    2.4e51     // double型
    3.1f       // fが付いているのでfloat型
    3.1m       // mが付いているのでdecimal型

###真理値型
真か偽かのみを格納する型．

|型名|扱えるデータ|
|:-:|:-:|
|bool|true / false|

###文字型
一文字だけ格納できる型です．

|型名|扱えるデータ|
|:-:|:-:|
|char|文字|

##参照型
値型がデータを直接保持するのに対して，参照型はデータが保存されているアドレスを保持します．変数はデータが格納されている領域のアドレスであると考えておいてください．参照型の変数には`null`という何もないことを意味する値を格納できます．

###文字列型
文字列を格納できる型です．char型を何個も連ねて文字を表します．

|型名|扱えるデータ|
|:-:|:-:|
|string|文字列|

###object型
全ての型の元になっている型でなんでも格納できます．

|型名|扱えるデータ|
|:-:|:-:|
|object|なんでも|
以下は使用例です．

```TypeSample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TypeSample
{
    class Program
    {
        static void Main(string[] args)
        {
            byte num = 200;
            sbyte num2 = 34;
            short num3 = 612;
            ushort num4 = 939;
            int num5 = 1245;
            uint num6 = 8346;
            long num7 = 18249L;
            ulong num8 = 127844918uL;

            float f = 3.7f;
            double d = 67.2;
            decimal m = 0.1m;

            bool b = true;

            char c = 'A';

            string str = "Hello.";

            object obj = null; 
        }
    }
}
```

ここで挙げた基本的な型以外にもたくさんの型があるので調べてみてください．

次回は[演算子](https://qiita.com/17t7037t/items/6f03549984eb08947b6a)について説明します．

##練習問題
float型のPIを定義し3.14で初期化したものを画面に出力してください．

<details><summary>解答例</summary><div>
サフィックスを付けるのは当然ですが，`PI`定数にしましたか？円周率がデタラメな値に書き換えられちゃうと困りますからね．細かいですが，こういうところをしっかり書いていくことがバグの少ないコードを書くことに繋がります．

```TypeSample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TypeSample
{
    class Program
    {
        static void Main(string[] args)
        {
            const float PI = 3.14f;
        }
    }
}
```
</div></details>
laravelでサーバーを立ち上げる方法（備忘録として）

環境
laravel: 5.5
php: 7.1
Apache: 2.2
composer: 1.8


## 1、ipアドレスを調べる

```
$ ip a
```
>ipアドレスが表示される



##2、artizsanコマンドを入力

```
$ php artisan serve --host 192.168.33.10 --port 8000
```
>hostの後ろにはipアドレスを、portの後ろには立ち上げるポート番号を入れる。

##3、表示されるアドレスでアクセスすればOK
>laravelを使っていないときの流れで

```
$ php -S 192.168.33.10:8000
```
と入力しないように注意。