OmniAICreator/Qiita-1.07M huggingface dataset:
傾斜をつけた割り勘計算ツールを作ってみた

![thumbnail](https://qiita-image-store.s3.amazonaws.com/0/135313/fb8544ca-260a-adec-63b8-1fa95158026c.png)

# はじめに

忘年会等の飲み会イベントで幹事を任されるのは若手の宿命。

かく言う私も例外ではありませんでした。私の勤務先の場合、社員の年齢差が大きいため傾斜をつけることがほとんど。ただ、この傾斜計算、参加者全員分の年次を把握したり傾斜の具合を微調節したりと意外に面倒で時間をとられます。

いい感じのサービスがないか検索してみたものの、PCサイト用のものはスマホでレウアウトが崩れるし、スマホ向けにはネイティブアプリばかりでPCからは利用できず。意外にもPC・スマホ双方で適切に動くものは見つけられませんでした。

ないなら作ればいい、そこで会社向けに作ったのがこの割り勘計算ツール。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">先日公開した割り勘計算ツール(<a href="https://t.co/w2j6PD7ZHu">https://t.co/w2j6PD7ZHu</a>)のベースとなった、会社向けver。<br>各組織の事前に登録しておる社員を選択できて、年次情報をもとに傾斜を計算してくれる仕組み。 <a href="https://t.co/PegFW5uHli">pic.twitter.com/PegFW5uHli</a></p>— icchi (@icchi_h) <a href="https://twitter.com/icchi_h/status/1082649092877107201?ref_src=twsrc%5Etfw">2019年1月8日</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

前振りが長くなりましが、今回作ったツールは上のものをベースに、外部公開向けの変更を加えたものです。

# 作ったもの
<https://warikan.tool.icchi.me>

実際に使ってみるとこんな感じ。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">傾斜をつけた割り勘の計算をやってくれるwebアプリを作りました。通常の傾斜以外にも男気や運試し（乱数）モードも実装しています。PWA対応。 <a href="https://t.co/RLpvO43mNm">pic.twitter.com/RLpvO43mNm</a></p>— icchi (@icchi_h) <a href="https://twitter.com/icchi_h/status/1082426547611430912?ref_src=twsrc%5Etfw">2019年1月7日</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

もともとは参加人数の多い飲み会後日のまとめ時に、Excelでやっていた傾斜計算をWebアプリに落とし込んだものでした。が、意外と飲み会現場で使っても便利で、個人的にはランダムに各自の支払料金を決める「運試しモード」が盛り上がるし、気に入っています。

# 構成
![structure_warikan-calcurator.jpeg](https://qiita-image-store.s3.amazonaws.com/0/135313/0c27c318-1d35-26b0-f83e-a114e0c12057.jpeg)

構成はいたってシンプル。

今回の仕様では、特に複雑な処理もないためWebで実装。SPAフレームワークには普段使い慣れているVueを使っています。スマホとの親和性も考慮してPWAに対応しました。クライアントサイドだけで完結するため、ビルドして生成した静的サイトをfirebaseでホスティングしています。

# コード
<https://github.com/icchi-h/warikan-calcurator>

# 最後に
ご意見ご要望お待ちしております。

方法はサイト内にも記載しているようにTwitterで投げてもらえれば。
> ご要望や不具合などのご連絡は、お手数ですが以下の方法でご連絡をお願いいたします。
>
> ハッシュタグ**#warikantool**とメンション**@icchi_h**をつけて[ツイート](https://twitter.com/intent/tweet?hashtags=warikantool&via=icchi_h)
> [@icchi_h](https://twitter.com/icchi_h) へダイレクトメッセージ

> <https://warikan.tool.icchi.me/about>

もし需要があるなら、結果を共有できるようにサーバーサイドを用意して連携させてみようかな。
"常に最前面でブラウザを表示したい"をpennywiseで解決する

こんな時ありませんか？

- youtubeでチューつリアルを見ながらコードを書きたい、でもIDEは全画面で開いていたい。
- とにかくいっぱいコピペする作業がある。
- twitterを横目に見ないと気が気でならない。

そういった方々にオススメのOSSがあるのでご紹介です。

# Pennywiseとは
「Pennywise」というElectronで作られたWEB ViewアプリのOSSです。
どこかのホラー映画で聞いたことのある名前とアイコンなのが印象的です。

Repogitry: https://github.com/kamranahmedse/pennywise

Pennywiseは独立したデスクトップアプリケーションとして起動し、WEB Viewとして機能します。
ただ、他のWEB Viewアプリと異なる点がいくつかあります。
以下、ご紹介していきます。

## Pennywiseの特徴
- 常にウィンドウの最前面に位置することができる
- 透過度を変更できる
- `yarn` か `homebrew` で簡単導入
- Windows, Mac, Linux対応
- リサイズ可能

## 導入
実際に動かしてみます。
導入方法としては、 `yarn` でのインストールと、 MacOSであれば `homebrew` でのインストールが可能です。

> homebrewの場合

```shell
$ brew cask install pennywise
```

> yarnの場合

```shell
git clone https://github.com/kamranahmedse/pennywise.git
cd pennywise
yarn install
yarn start
```

homebrewとしてインストールすると、アプリケーションとして追加され、ピエロのアイコンとして起動します。
一方で、yarnで実行する場合は、Electronアプリとして起動します。

<img width="183" alt="スクリーンショット 2019-01-10 2.08.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/203817/dec12e54-7339-9120-11e2-1b35b9aed9b9.png">

右がhomebrewでインストールしたもの、左がyarnでelectronとして実行するもの

これらを立ち上げると下記のような画面が立ち上がります。

<img width="1407" alt="スクリーンショット 2019-01-10 2.19.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/203817/0f31655f-09d6-e532-4972-db2c16ac4af3.png">

このpennywiseの画面は、他のウィンドウにフォーカスを当てても、後ろに回ることはなく、常に最前面で表示されます。

また、URLを入力後、WEBページを見る際に透過度を変更することが可能です。

不透明度 100%

<img width="750" alt="スクリーンショット 2019-01-10 2.22.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/203817/1833417d-a88f-419b-3c42-90368a55a91c.png">

不透明度 50%

<img width="750" alt="スクリーンショット 2019-01-10 2.23.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/203817/86a5117d-8d13-3c73-d951-46d1017e0753.png">

不透明度はGUIで変更できますが、ショートカットキーでも変更可能です。

## ショートカットキー
| ショートカット       | 説明 | 
|:-----------------|------------------:|
| Cmd/Ctrl + L     |     URL欄にフォーカス |     
| Cmd/Ctrl + D     |     デタッチモードになる<br>(Dockアイコンクリックで解除)|
| Cmd/Ctrl + Shift + D  |     ナビバーを表示|     
| Cmd/Ctrl + Shift + Up  |    不透明度を上げる|    
| Cmd/Ctrl + Shift + Down|    不透明度を下げる|   
| Cmd/Ctrl + Alt + I|  デベロッパーツールを開く|   

## 終わりに
インストールも簡単で、使ってみた感触では軽量なため使いやすかったです。
ウィンドウ間を往復する作業や動画を見ながらの学習、Twitterを眺める日常には便利そうです。
ただ、youtubeやTwitterの見過ぎにならないように注意が必要ですね。
composer の global インストールしたコマンドの実行（phpcsとか）の準備

VScode を使って、php のコーディングをしているんですが、ある日

> phpcs: Request workspace/configuration failed with message: Unable to locate phpcs. Please add phpcs to your global path or use composer dependency manager to install it in your project locally.

とメッセージが出て、phpcs が使用できなくなりました＾＾；
＊というより、しばらく使っていなかったら、いつの間にか使えなくなっていましたｗ

# 解消方法
エラーメッセージを読めばわかるのですが、原因は global にインストールしたコマンドに path が通ってないだけです。

以下のコマンドで、global 導入先を確認

```
composer global config bin-dir --absolute
or
php composer.phar global config bin-dir --absolute
```

path の設定に関して、Windows7 での方法ですが補足しておきます。

環境変数`＄PATH`に上記で確認したディレクトリを登録
`C:\Users\hogehoge\AppData\Roaming\Composer/vendor/bin`
サンプルのように、後半のディレクトリ指定がスラッシュで表記されているので、ちゃんとバックスラッシュに変更して登録してください。
`C:\Users\hogehoge\AppData\Roaming\Composer\vendor\bin`

これで解消されます。

# 余談
発生原因を追いかけるつもりは無いですけど、上記で解消されたため、むしろ「なんで今まで動いていたんだろう」って疑問がｗ
特になにかしたわけでもなかったので、もし原因がなんらかのアップデート絡みであれば情報共有するとだれかの役に立つかもと思い、記事を作成しました。
flexboxで横並びliにて複数行のバラバラな高さを揃えたい

[CSS3 - flexboxで横並びliにて複数行のバラバラな高さを揃えたい｜teratail](https://teratail.com/questions/67857)

を参考にしました。少しコードを少なくしていますが、上記リンクとほぼ内容は一緒です。

```html
<div class="h_section h_navi">
<ul>
<li><a href="">あああ</a></li>
<li><a href="">いいい</a></li>
<li><a href="">ううう<br>ううう</a></li>
<li><a href="">えええ</a></li>
<li><a href="">おおお<br>おおお</a></li>
</ul>
</div>
```

上記htmlにflexboxに関する一連のcssを単純に当てつつborder-leftをつけると、brしたborderが長く、brしていないborderが短くなってしまい、歪です。

そこで、a要素にも高さやflexboxなどcssを追記しました。それが下記です。

```css
.h_navi ul{
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.h_navi ul li{
  border-left: 1px solid #dadad9;
}
.h_navi ul li:last-child{
  border-right: 1px solid #dadad9;
}
.h_navi ul li a{
  display: flex;
  justify-content: space-between;
  align-items: center;
  height:100px;
}
```
PHPで連想配列のファイル入出力

ベーシックな内容ですが、慣れるまでに時間がかかったのでまとめてみました。

## 実現したいこと
* 連想配列をテキストファイル（txt, csv）に出力する
* テキストファイルの文字列を配列に格納する


## 連想配列⇄txtファイル

* `fwrite`の第二引数は**文字列**
* `fopen`の第二引数
    * `"w"`は書き出しモード（fopenが呼び出される度にデータがまるっと**上書き**される）
    * `"a"`は**追記モード**（既存のデータの後ろに追加される）

### 連想配列→txtファイル

* キーと値をカンマつなぎで文字列化
* `"\n"`を入れて改行して出力されるようにしている

```php
$data = array(
   array(1,"apple"),
   array(2,"banana"),
   array(3,"orange")
);
$file = fopen("data.txt", "w");
foreach($data as $key => $value){
   fwrite($file, $key.",".$value."\n");
}
fclose($file);
```

data.txtの中身はこちら

```
1,apple
2,banana
3,orange
```

### txtファイル→連想配列

* `file`で一行一要素とする**配列**が返される
* `explode`で文字列`1,apple`を`array(1,"apple")`に変換
* `$params[0]`がキー、`$params[1]`が値の連想配列に変換

```php
$data = file("data.txt");
$result = array();
foreach($data as $row){
   $params = explode(",", $row);
   $result[$params[0]] = $params[1];
}
```

配列`$result`の中身はこちら

```php

print_r($result);

Array ( [1] => apple [2] => banana [3] => orange )
```

上記の例だと、値の文字列の中に`,`が含まれると余分に分割される（例`1,apple,cherry`）
→`explode`の第三引数に要素数の上限を渡せば回避できる

```php
// $paramsの要素は2つまで！
$params = explode(",", $row, 2); // Array([1] => apple,cherry)
```

## 連想配列⇄csvファイル

### 連想配列→csvファイル

* `fputcsv`について
    * 第二引数は**配列**
    * 配列の要素をカンマ区切りで出力する
        * 1配列の出力が終わったら**改行**される

```php
$data = array(
   1 => "apple",
   2 => "banana",
   3 => "orange" 
);

$file = fopen("data.csv", "w");
fputcsv($file, $data);
fclose($file);
```

data.csvの中身はこちら↓

```
apple,banana,orange
```
値だけファイルに出力されている
ちなみにキーが文字列の場合も同様に値だけ出力された

```php

$data2 = array(
   "one" => "apple",
   "two" => "banana",
   "three" => "orange",
);

$file = fopen("data.csv", "w");
fputcsv($file, $data);
fclose($file);
```

キーも出力するには...

* `foreach`で配列をループ
* ループ内で`fputcsv`の第二引数に`array($key, $value)`を渡す

```php
$data = array(
   1 => "apple",
   2 => "banana",
   3 => "orange" 
);

$file = fopen("data.csv", "w");
foreach($data as $key => $value){
   fputcsv($file, array($key, $value));
}
fclose($file);
```

data.csvの中身はこちら

```
1,apple
2,banana
3,orange
```


### csvファイル→連想配列

* [txtファイル→連想配列](https://qiita.com/ayaka105/items/8d7bf99ecbefd24a2e99#txt%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E9%80%A3%E6%83%B3%E9%85%8D%E5%88%97)と同じ


## 最後に

もっとスマートな書き方ありましたらぜひ教えてくださいm(_ _)m
Qiitaやブログのタイトルは自分で考える必要なんてなかったんだ

# Ref

[追伸。そろそろおまえもstationでslackやWebアプリを一括管理をするように。　母より - Qiita](https://qiita.com/shojimotio/items/77678d55a2d1557f5e68#comment-8135b6116135fe6480f1)


[私は、心の中で叫んだ。「今までのブログタイトル付け方はなんだったんだ！」 ·](https://blog-c.cloudlance-motio.work/post/blog-title/)

# コピーメカ

[コピーメカ/キャッチコピー自動作成サイト](http://www.copymecha.com/index.php)

# 入力

![image](https://user-images.githubusercontent.com/13635059/50935364-29862400-14af-11e9-8c90-e86b93dc2c83.png)


# 結果

![image](https://user-images.githubusercontent.com/13635059/50935373-2d19ab00-14af-11e9-99e7-4089d8bf8844.png)

![image](https://user-images.githubusercontent.com/13635059/50935378-30149b80-14af-11e9-973b-db897091b5d1.png)

# 感想

- 予想以上のクオリティ。
- 自分で考えるよりも100倍ぐらい優れている気がした。
- 仮に「これはコピーメカでしょ」と多くのユーザーが感知するようになってさえ、役立つような気もした。
- メカというと自動生成チックな連想をするが、キャッチコピーのプロが書いたキャッチフレーズから逆算してキーワードをはめ込む方式のような気もした、あくまでメカチックに見えるサービス。



# 追記: 製作者

岡野弘文　Hirofumi Okano さん。

やはりコピーライティングを得意としている人らしい。

http://www.okano.ne.jp/profile/

>得意分野：美容、健康、能力開発、デザイン、コピーライティング
>得意業態：通信販売（マーケティング、ブランディング）、メディアミックスによるブランディング


---


https://github.com/YumaInaura/YumaInaura/issues/318

[qiita タイトル yumainaura - Google Search](https://www.google.com/search?q=qiita+%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB+yumainaura&oq=qiita+%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB+yumainaura&aqs=chrome..69i57j69i60l2j69i64.4245j0j7&sourceid=chrome&ie=UTF-8)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
PHPのDateTime::ISO8601はISO8601ではない


## 前提
以下のバージョンにおける情報です。

- PHP 5 >= 5.2.0
- PHP 7

## ISO8601と互換性がないDateTime::ISO8601
PHPには `DateTime::ISO8601` という定義済み定数があります。
この定義済み定数を利用して、以下のようなコードでフォーマットされた日付の文字列を取得できます。

```php
$date = new DateTime();
echo $date->format(DateTime::ISO8601); // 2019-01-09T14:20:03+0000
```

上のコードを実行すると `2019-01-09T14:20:03+0000` のような文字列を取得できます。

`DateTime::ISO8601` を指定して取得された文字列なので、`ISO8601` に互換性があることを期待したのですが、なんと互換性はありません。

`ISO8601` が規定している形式とは異なってしまっています。

## ISO8601で規定されている形式
では、ISO8601とどう異なっているのでしょうか。

ISO8601には「基本形式」と「拡張形式」の２種類の形式があります。
それぞれ以下のようなものです。

|形式|表記|
|---|---|
| 基本形式 | 20190109T142003+0000 |
| 拡張形式 | 2019-01-09T14:20:03+00:00 |

一見、 `DateTime::ISO8601` で得られる文字列は「拡張形式」のように見えますが、よく見るとタイムゾーンの表記が異なります。

拡張形式のタイムゾーンにはコロンが入りますが、 `DateTime::ISO8601` で得られる文字列にはコロンが入っていません。

よって、基本形式と拡張形式のどちらにも互換性のない文字列となってしまっています。

## ISO8601に互換性のない文字列によって起こる問題
このISO8601に互換性のない文字列をPHP内だけで扱う場合には問題は起きないかもしれません。
しかし、APIなど外部と連携するプログラムを書く場合には注意が必要です。

APIレスポンスとして受信した側が、この文字列を日時としてパースできない可能性があるからです。

### JavaScriptの場合
JavaScriptでは一部のブラウザで、パースできない問題があります。
APIをPHPで構築しフロントエンドのJavaScriptでそれを呼び出す、というシチュエーションは多くあるので要注意です。

```javascript
new Date('2019-01-09T14:20:03+0000')
```

|ブラウザ|パース可否|
|---|:---:|
|Chrome 71|○|
|Firefox 57|○|
|Safari 12|✗|
|Edge 18|○|
|IE11|✗|
|(Node.js v10)|○|

### Rubyの場合
Ruby 2.4.0で試したところ、パース可能でした。

```ruby
DateTime.parse('2019-01-09T14:20:03+0000')
```

### Pythonの場合
Python 3.6.2で試したところ、パース可能でした。

```python
from dateutil.parser import parse
parse('2019-01-09T14:20:03+0000')
```

## ISO8601に互換性のあるフォーマットの日時を取得するには

では、 `ISO8601` に互換性のあるフォーマットの日時文字列を取得したい場合はどうしたらいいでしょうか。

その場合には　`DateTime::ISO8601` ではなく `DateTime::ATOM` を使用します。

```php
$date = new DateTime();
echo $date->format(DateTime::ATOM); // 2019-01-09T14:20:03+00:00
```

上のコードでは、 `2019-01-09T14:20:03+00:00` のようなISO8601の拡張形式に互換性のある文字列が取得できます。

## ドキュメント
http://php.net/manual/ja/class.datetime.php
Twitterの検索で時間を含む期間指定をする方法

Twitter APIを利用して時間単位で指定期間のツイートを取得する方法を探しててわかったのでメモ。

## 検索条件

- キーワード検索: `あけ since:2018-12-31_23:59:59_JST until:2019-01-01_00:00:00_JST`
- URL: https://twitter.com/search?f=tweets&q=%E3%81%82%E3%81%91%20since%3A2018-12-31_23%3A59%3A59_JST%20until%3A2019-01-01_00%3A00%3A00_JST&src=typd

上記キーワード検索でフライングあけおめツイートが検索できます^^

### 検索パラメータ

- `since`: 指定日時以降のツイートを取得
- `until`: 指定日時以前のツイートを取得

`since`と`until`を利用すると期間指定できますが、`YYYY-MM-DD_hh:mm:ss_JST`の書式で指定すると日時も指定可能でした。`_JST`を末尾につけないとうまく検索できないようです。JSTは日本標準時となります。協定世界時(UTC)で検索したい場合には、`_UTC` とします。

UTCでも上記キーワード検索と同じ検索結果が得られます。

https://twitter.com/search?f=tweets&q=%E3%81%82%E3%81%91%20since%3A2018-12-31_14%3A59%3A59_UTC%20until%3A2018-12-31_15%3A00%3A00_UTC&src=typd


## 注意点

### パラメータだけでは検索できない

検索キーワードに`since`と`until`のみ指定は不可。キーワード+`since`と`until`で検索ができます。


### 日付書式

日時指定について調べていると`YYYY-MM-DD_JST_hh:mm:ss`と`_JST`を日付と時間の間につけて紹介されているブログがありましたが、それだと時間指定が無視されました。仕様が変わったのでしょうか？


### 公式機能か不明

Twitterの高度な検索ページだと日付しか指定ができず、日時指定に関する説明が公式ドキュメントからみつけることができませんでした。

Twitterの高度な検索
https://twitter.com/search-advanced?lang=ja&lang=ja

高度な検索の使い方
https://help.twitter.com/ja/using-twitter/twitter-advanced-search

なので、いつ使えなくなるかわからない感じです。(でしょうか？)

## 参考

Twitterのめっちゃ高度な検索
https://app.afonomics.com/TwitterMoreSearch/

TwitterAPIで期間指定してTweetを取得する方法 - Qiita
https://qiita.com/areph/items/0745cb744a12810334c6

高度な検索の使い方
https://help.twitter.com/ja/using-twitter/twitter-advanced-search
kintone から AWS API Gateway 経由で Lambda for Ruby ファンクションにリクエストを投げてみるテスト

kintoneのアプリからAWSにアクセスするテストです。
とりあえず結果だけ。説明は後ほど。

# テスト概要

 1. Lambda実行とCloudWatchLogsに書き込み出来るロールを作成します。
 2. Lambdaの作成と同時にAPI Gatewayも作成します。
 3. Lambdaにロールを設定します。
 4. API Gateway を作成します。
 5. kintoneアプリを新規に作成します。
 6. kintoneにAPI GatewayにPOSTするコードを作成します。
 7. kintoneアプリを実行します。
 8. CloudWatchにアクセスしてログを確認します。

# 1. Lambda実行とCloudWatch Logs 書き込みロールの作成

 1. IAMコンソールにてIAMロールを選択
 2. ロールの作成を選択
 3. 利用するサービスにLambdaを選択
 4. アタッチポリシーに一覧から「AmazonAPIGatewayPushToCloudWatchLogs」を選択
 5. ロール名を入力してロールを保存します

# 2. Lambda作成とAPI Gatewayの設定

 1. Lambdaコンソールにて関数の作成を選択
 2. 1から作成を選択
 3. Lambdaファンクション名を入力
 4. ランタイムでRuby2.5を選択
 5. 既存のロールにて前段で作成したロールをリストから選択
 6. 関数の作成を押下
 7. 保存押下
 8. トリガーの追加からAPI Gatewayを選択
 9. 新規APIの作成を選択
 10. セキュリティを選択
 11. 追加を押下
 12. 保存を押下してAPI Gatewayをデプロイ
 13. APIエンドポイントの生成を確認
 14. テストを選択
 15. テストイベントを保存
 16. テスト実行
 17. CloudWatchコンソールからログを選択
 18. ログを確認


# Lambdaファンクション
myHelloRubyTest1

```ruby
require 'json'

def lambda_handler(event:, context:)
    # TODO implement
    pp event
    pp context 
    { statusCode: 200, body: JSON.generate('Hello from Lambda! powerd by Ruby2.5') }
end
```

# kintone JavaScript

```javascript
(function() {
    "use strict";

    const url = 'API GatewayのAPI エンドポイント';
    const method = 'POST';
    const headers = {'Content-Type' : 'application/x-www-form-urlencoded'};
    const data = 'myName=Kazu&myJob=SE';

    var myIndexButton = document.createElement('button');
    myIndexButton.id = 'my_index_button';
    myIndexButton.innerHTML = 'Hello Ruby!!';
    myIndexButton.onclick = function() {
        kintone.proxy(url, method, headers, data, function(body, status, headers) {
            console.log(status, body);            
            if(status >= 200 && status < 300) {
                console.log("Success");
            }else{
                console.log("Error");
            }
        });
        return event;
    };

    kintone.events.on("app.record.detail.show", function(event) {
        kintone.app.record.getHeaderMenuSpaceElement().appendChild(myIndexButton);
    });
})();

```

# CloudWatch Logs
一部抜粋

```text
"body"=>"myName=Kazu&myJob=SE",
#<LambdaContext:0x000055a4a4f96d90
@function_name="myHelloRubyTest1",

```
Inspec

# 公式サイト
#### https://www.inspec.io/docs/

# コマンド例
inspec exec test.rb -t ssh://ユーザ名@IPアドレス -i Pathto鍵ファイル --sudo --log-level=debug

# rbファイルの記述例
### テスト用のコマンドを実行したいとき
```
control 'command' do
  title 'コマンド実行'

  describe command('cat /etc/ssh/sshd_config | grep Port | grep 22') do
    its('exit_status') { should eq 0 } # 終了コードが0であることで確認
  end
end
```
### ファイルの中身を確認したいとき
```
control 'file' do
  title 'ファイルチェック'

  describe file('/etc/ssh/sshd_config') do
    its('content') { should match '^Port 22$' } # 終了コードが0であることで確認
  end
end
```
### json形式ファイルの中身を確認したいとき
```
control 'json' do
  title 'json形式で設定を確認'

  describe json('/tmp/work/output.json') do
    its(['json, 0, 'Tags', 0, 'Value']) { should eq 'test' } # testタグがついていることを確認
　end
end
```
UnityのColorは定義されてる色が少なすぎる

Color.red とか、まぁ原色ぽいのはあるんですけどね。

Wikipedia さんによると、こんなにあるらしいですよ？

https://en.wikipedia.org/wiki/List_of_colors:_A-F
https://en.wikipedia.org/wiki/List_of_colors:_G-M
https://en.wikipedia.org/wiki/List_of_colors:_N-Z

なので、この↑の色を定義したColorConstクラスを作りました。

もちろん手打ちしてられないので、各ページのテーブルの箇所をドラッグしてコピペして、**T4Template**でソースコードに変換を。
色名にはスペースが入ってたり、スラッシュやピリオドが入ってたりでそのままだと変数名に出来ないので、適当に_とかブランクにReplace。
あと、全く同じ名前の色も存在したので、重複は削りました。

（行数が多すぎるのでgistへ)
https://gist.github.com/divide-by-zero/275c975d34f066ce3abe743f2ff16ea3

上記ファイルをAssetの配下どこでも良いので置いてけば

```cs
image.color = ColorConst.Wild_watermelon;
```

とか出来るようになります！　やったね！

ワイルドウォーターメロンってどんな色だろう・・・。
JMeterとjEnvのセットアップ

MacでJMeterのセットアップを行った際のメモ。ついでにJavaのversion管理するjEnvも。

- macOS Mojave 10.14.2


まずはHomebrewでインストールされるJavaのversion確認
![ 2019-01-09 12.35.13.png](https://qiita-image-store.s3.amazonaws.com/0/132235/a3a602c1-d460-71d2-5ace-d584ff78263e.png)

調べてみると最新のJMeterだと8か9が必要で更に、Eclipseを以前入れた関係でローカルにはすでに11がインストールされていた。
プロジェクト毎にversionを切り替えたかったのでjEnvのインストール。ついでにJmeterもHomebrewで入れておく。  

```
brew install jenv
brew install jmeter
brew info jmeter
```
![ 2019-01-09 12.39.38.png](https://qiita-image-store.s3.amazonaws.com/0/132235/fb9dbd50-97d0-11b9-244e-5edfdbf87dc4.png)

![ 2019-01-09 12.35.41.png](https://qiita-image-store.s3.amazonaws.com/0/132235/d7c3d459-c869-ec12-42f3-0815880e9f4a.png)

やっぱりHomebrewでインストールされるJmeterのversionをみても8か9は必要そう!


## Java8のインストール
Oracleから8のインストーラーをダウンロードする。
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

## jEnvでversionを切り替える
環境変数の追加とJMeterの日本語化を行う。

```
echo 'export PATH="$HONE/.jenv/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(jenv init -)"' >> ~/.zshrc

# JMeterの日本語化。空白にすることによってOSのロケールに合わせてくれる
echo 'export JMETER_LANGUAGE=" "' >> ~/.zshrc

# 反映
source ~/.zshrc
```

jEnvにjdkを追加する

```
jenv add /Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home
jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home
```
![ 2019-01-09 12.55.14.png](https://qiita-image-store.s3.amazonaws.com/0/132235/bfdd582d-1ec1-c89d-e54d-13d1e503c514.png)

登録ができたのでversionを切り替える。

```
jenv global 1.8
jenv rehash
```
![ 2019-01-09 13.01.50.png](https://qiita-image-store.s3.amazonaws.com/0/132235/8cfa199d-7a76-c913-a99e-ab3c6bfc8d8f.png)

JMeterの起動してみる

```
jmeter
```
<img width="1264" alt=" 2019-01-10 5.52.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/132235/36d87ccf-a8d2-08cb-503e-af6007ff26ab.png">

これで完了。

**参考** 
jEnv公式 http://www.jenv.be/
Jmeter公式 https://jmeter.apache.org/download_jmeter.cgi
npm に公開し、 patch をバージョンアップする方法

## npm に公開

```bash
$ git tag -a v1.0.0 -m "My first version v1.0.0"
$ git push origin tags/v1.0.0
$ npm publish ./
```

## patch のバージョンのアップ

```bash
$ npm version patch              # <- v1.0.0 からv1.0.1 にアップ
v1.0.1
$ git tag                        # <- git のtag も自動的に作成される
v1.0.0
v1.0.1
$ git push origin tags/v1.0.1    # <- ただし、git push まではやってくれないので、必要に応じて自分でgit push ...
$ npm publish ./                 # <- npm で公開
```

via: [初めてのnpm パッケージ公開 - Qiita](https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2#npm-%E3%81%AB%E5%85%AC%E9%96%8B)
GitHub Pagesで反映されないページをすぐに反映させる方法

この方法はGitHub Pagesでファイルを更新したときにすぐに反映されないときの**一時的な**対処法です。
# 対処法
~~URLの末尾に `?version=[コミットID]` を付けるだけです。~~
`?` から始まる文字列をつけてURLが変われば何でも良いようです。

```html:例
https://example.github.io/index.html?version=a1b2c3d
https://example.github.io/index.html?asdfsda
```

(元のURLでも1〜2時間後には更新が反映されていました。）
Swiftのprotocol extensionでデフォルト引数を使いたいとき

#はじめに
protocol extensionを使ってデフォルト引数を設定したい場合どうすればわからなくなったので調べたメモ

#やりたいこと
下記のようなプロトコルがある。

```Swift:
public protocol Test {  
     func getPage(_ url: URL)
}
```

この関数`getPage`の第二引数に新しく`name`という引数を設定したい
しかしこの引数、必ず必要というわけではない。
かつ
色んな所からこの関数が呼ばれているため、第二引数をすべての使っている場所で追加したくない。
デフォルト引数を設定したいと考えた

#プロトコルが適合された使用例

```Swift
class hogeClass: Test {
    func getPage(_ url: URL){
        //何かの処理
    }
}
```

#私のよくない例(その１)
プロトコルの定義にはデフォルト引数を設定できないので下記のようには書けない

```Swift:これはダメ
public protocol Test {  
     func getPage(_ url: URL,name: String? = nil)
}
````

#私のよくない例(その２)
## じゃあプロトコルを増やしてやるかと思った

```Swift
public protocol Test {  
     func getPage(_ url: URL)
　　　　　　　　　　func getPage(_ url: URL, name: String?)
}
````

##protocol extensionを使ってデフォルト実装をする
詳細Swift3より引用

```
プロトコル拡張にはメソッドやプロパティの設定(デフォルト)の実装が記述出来るといえます。
プロトコル拡張で定義された実装を既定実装(default implementation),
あるいはデフォルト実装と呼びます(252p 詳細Swift3)
```

とのことなので第二引数のデフォルトを`nil`に設定してデフォルト実装をした


```Swift
extension Test {
    func getPage(_ url: URL, name: String? = nil){}
}
```

#問題点
このままだと適合されたクラスはどうなるかというと、下記のように適合されたプロトコルに設定されている関数を呼ぶ必要があるため、同じ名前だが、引数数が異なる関数を設定する必要がある・・・

```Swift
class hogeClass: Test {
    func getPage(_ url: URL){
        //何かの処理
    }
    func getPage(_ url: URL, name: String?){
        //何かの処理
    }
}
```

うーんもっといい方法があるはず・・・・

#解決策
protocol extensionでよりよくする

## protocolの定義

```Swift
public protocol Test {  
     func getPage(_ url: URL)
　　　　　　　　　　func getPage(_ url: URL, name: String?)
}
````

## protocol extension

```Swift
extension Test {
    ///ここがポイント
    func getPage(_ url: URL){
         self.getPage(_ url: URL, name: nil)
　　　　　　　　}
}
```

## protocolが適合されているクラス

```Swift
class hogeClass: Test {
// ここのgetPage(url:)関数はprotocol extensionですでに定義されているため
//　　適合されているクラスでこの関数を実行する必要はない
//    func getPage(_ url: URL){
//        //何かの処理
//    }

    func getPage(_ url: URL, name: String?){
        //何かの処理
    }
}
```

これで大丈夫なはず
なにか間違いもっとこうしたほうがいいなどありましたら教えて下さい　🙏
「Invalid search term entered. GET returned: 400 無効な credential_type ID: NaN」で悩んでいる人へ朗報です。

※AnsibleTowerを利用している人向けの記事となります。

AWXユーザ、AnsibleTowerを利用している人が受けたことがあるエラー。
**Invalid search term entered. GET returned: 400 無効な credential_type ID: NaN**

![tower-3.3.1-error.PNG](https://qiita-image-store.s3.amazonaws.com/0/283423/bce1565b-114c-a903-3dfd-8c1308827382.png)

GUI上でジョブテンプレートを作成しようとすると、認証情報の箇所でエラーが出るものです。
AnsibleTowerの3.3.1(昨年10月25日に公開されたオンラインパッケージ)でも発生していたエラーです。
つい2ヶ月ほど前までこのエラーが表示されていました。
![tower-3.3.1.PNG](https://qiita-image-store.s3.amazonaws.com/0/283423/7615684d-f4e6-9fe0-2678-a230343b833f.png)


このエラーはブラウザの利用言語が日本語である場合に発生するエラーでした。そのためこのエラーで検索すると、「ブラウザの言語設定を英語環境にしましょう」「Chromeのプラグイン入れて言語環境変更させて対応させましょう」といった解決方法が紹介されていました。

しかしどうやら3.3.2以降のバージョンでは上記エラーが解決された模様です。

試しに3.3.3をインストールして確認してみました。

![tower-3.3.3.PNG](https://qiita-image-store.s3.amazonaws.com/0/283423/731ce893-3c0d-da56-7d9d-6af20936b39e.png)

![tower-3.3.3-ok.PNG](https://qiita-image-store.s3.amazonaws.com/0/283423/3a451d99-39f7-bd54-c0ec-c7d40a5b026b.png)

治っていました。
インストールしているAnsibleのバージョンも違うため正確な比較はできていませんが、同様のエラーが出て困っている人は(可能であれば)バージョンアップしてみてください。

[2019/1/10 2:15更新]
bundle版(AnsibleTowerのオフラインインストールパッケージ)でAnsibleのバージョンを同じにして確認しましたが、3.3.1ではやっぱり上記エラーが出ていました。
[IAM policy] bitbucket-pipelines からecrにDocker imageをPushできるためのpolicy


```bitbucket-pipeline-ecr-policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecr:BatchGetImage",
                "ecr:CompleteLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:InitiateLayerUpload",
                "ecr:PutImage"
            ],
            "Resource": [
                "arn:aws:ecr:<region>:<account>:repository/<name>",
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ecr:GetAuthorizationToken",
            "Resource": "*"
        }
    ]
}
```

Resource部分は、自分のECRのARNを記入
[IAM policy]AWSの adminでないUserにもconsole access時にMFA設定をしてもらうためのPolicy

# 背景

console accessのセキュリティ強化のため、IP制限をしたりすることもあるが、今回は、ConsoleAccess権を持っているがIAMの全部の権限はないUserに対して、MFA設定を個人で設定してもらえるようなPolicyを作成する


# Policy

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteVirtualMFADevice",
                "iam:CreateVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::351540792571:mfa/${aws:username}"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "iam:EnableMFADevice",
            "Resource": "arn:aws:iam::351540792571:user/${aws:username}"
        }
    ]
}
```

Resourceのところが`mfa/${aws:username}`と`user/${aws:username}`と異なってるところに注意！

自分で一旦設定したらDeactivateできないようにしているので、それが必要な場合は、`DeactivateMFADevice`的な権限も与えると良い
初めてのGCP pert3 (画像など静的なファイル設定方法)

とても短い文ですが大切なことなので。

GCPで静的画像を扱うには、ストレージ→ブラウザ→バケットに画像UPロードして
qs://バケット名/ファイル名.jpgみたいな感じで呼び出す方法しかないと思っていたのですが
（※実際この方法でも呼び出すことはできる）

もっと簡単で身近な静的画像、js,cssファイルを扱う方法がありましたので記載。


:relaxed:app.yamlに静的ファイル設置するフォルダを指定するだけで、
フォルダ内ファイルはすべて静的ファイルとしてみることができるようです。

・app.yaml

```
runtime: php55
api_version: 1
threadsafe: true

handlers:
- url: /www
  static_dir: www
  
- url: /.*
  script: index.php


```

static_dirでしているフォルダ名がそうで、
/www/以下のファイルはすべて静的ファイルとして使用できます。

・ファイル構成
app/yaml
/www/
　┣css/xxx.css
　┣js/xxx.js
　┗img/xxxx.jpg
など。

HTML記入例）

```
<img src="/www/css/xxxx.jpg" />
```

短いですがこれでまた一歩進めた。
GitLab CI上でdocker-composeを使ってSelenium Grid環境を構築する

ずっと出来ないと勘違いしてたのですが、Dockerの中でDockerって動かせるんですね。知りませんでした。
調べたら2013年頃の記事に「出来るようになったやで」と書いてありました。お恥ずかしい。
https://blog.docker.com/2013/09/docker-can-now-run-within-docker/

さて、Dockerの中でDockerが動くなら、Dockerの中でdocker-composeも動くわけで、ということはGitLab CIのDocker Executorの中でもdocker-composeを使って環境構築が出来るわけですね。
ちょうどSeleniumの実行環境をCIに乗せたいと思っていたので、せっかくなのでSelenium GridでChromeとFirefoxが動く環境をdocker-composeで構築してみました。

## TL;DR

以下の2ファイルをプロジェクトルートに配置すればOKです。

```.gitlab-ci.yml
outsrc:
  image: docker:stable

  variables:
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2

  services:
    - docker:dind

  before_script:
    - apk update
    - apk add --no-cache py-pip
    - pip install docker-compose

  script:
    - docker-compose up -d
    - # このへんにあなたのテストスクリプトを入れてね
```

```docker-compose.yml
version: '2'
services:
  hub:
    image: selenium/hub
    ports:
      - 4444:4444

  firefox:
    image: selenium/node-firefox
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - hub
    environment:
      HUB_HOST: hub

  chrome:
    image: selenium/node-chrome
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - hub
    environment:
      HUB_HOST: hub
```



## ハマったところ

### Selenium Hubへのアクセス

お使いのテストフレームワーク上で、Seleniumのホストを指定するところがあると思いますが、ここの指定は

- ホストOS上で実行する場合: `docker`
- テストコードもdocker-compose上のコンテナで実行する場合: `hub`

となります。ホストOS上で実行する際、 `localhost` では動きませんので注意が必要です。

### 使うイメージは `node` とついてるほう

最初Seleniumの事を良く知らなくてハマったのですが、今回のようにSelenium Grid、つまり1つのHubと複数のNode（ブラウザがインストールされたコンテナ）で実行するときは、 `selenium/node-***` を選ぶ必要があります。
`selenium/standalone-***` は使えませんので注意してください！

https://hub.docker.com/u/selenium/
麻雀の点数判定アプリを作る#3

#前回まで
グレースケール化，平滑化，閾値処理を行い，画像認識の準備が整いましたが，ここで問題が発生．僕の構想では牌を個別に認識するつもりでした．ご覧の通り，背景と牌の境界は明確になりましたが，牌同士の境界は消失しています．パラメータを調整して牌同士の境界を取り出そうとすると，牌そのものの画像情報が損なわれてしまう等の弊害が生じます．何より，最終的には様々な環境で撮られた写真を入力とすることを想定しており，細かいパラメータを設定してしまうとそれらに対応できなくなることが考えられます．理想は，その都度パラメータの最適化が行われることですが，現状僕には皆目その見当がつきません．

![gray_img.jpg](https://qiita-image-store.s3.amazonaws.com/0/335220/0f611c6d-1ac3-d228-083c-13b69575af7b.jpeg)


#そのまま分割する
`cv2.findContour`で輪郭を抽出することができます．

```find_contours.py
import cv2
import matplotlib.pyplot as plt

img_path = '/Users/mac/Desktop/sample/agari2.png'

img = cv2.imread(img_path)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
filtered_img = cv2.GaussianBlur(gray_img, (5, 5), 0)
ret,thresh_img = cv2.threshold(filtered_img,150,255,0)
image, contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
plt.imshow(image)

areas = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    if area > 10000:
        epsilon = 0.020*cv2.arcLength(cnt,True)
        approx = cv2.approxPolyDP(cnt,epsilon,True)
        areas.append(approx)

cv2.drawContours(img,areas,-1,(0,255,0),5)
plt.imshow(img)
```

`image, contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)`で輪郭を抽出します．返り値の`contours`は輪郭のリスト，`hierarchy`は階層構造のリストです．今回は画像認識の目処を立てるために関数の挙動をとりあえず見てみる，という体なので，後半の角形の近似は理解が及んでいません．必要になったら勉強します．

出力結果
![practice.jpg](https://qiita-image-store.s3.amazonaws.com/0/335220/d1855fa1-4884-a0cc-2187-e9876f838623.jpeg)

歪んでいます．近似の際パラメータを調整しなければならない時点でこの方法も諦めムードです．

<img width="670" alt="スクリーンショット 2019-01-10 0.46.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/335220/c8ef2e94-e524-54dd-4347-88bd91513a3f.png">

`cv2.boundingRect()`を使って輪郭の座標を取り出し，幅を14分割して牌をとりあえず取り出しました．ここから幾何変形`cv2.warpPerspective()`で各牌を整形しました．それぞれ正面からの角度が異なるため，変形率がまちまちでとても綺麗とは言えません．パラメータを一般化してパターンに対応することが不可能かというと，現状僕には分かりませんが，解決するにあたって足踏みすることは必至です．

ということで，僕が使える唯一の武器はほぼ望み薄になってしまったので，他の方法を探してみます．万策尽きた結果，画像認識に戻ってくることも十分考えられますが，ここは一旦引き上げます．

#精確かつパターンに対応できる方法を探す
理解が出来てなんぼだと思っていたので，当初は扱える問題の難易度よりも僕が理解できるかどうかに重点を置いていましたが，それでは問題解決はおろか土俵にすら立たせてもらえないことが分かりました．甘ちゃんでした．考え方を改めて，知らないものでも使ってみることにしましょう．ネットは広大なので，同じような境遇の先人が教えてくれる筈です．

###物体検出アルゴリズムYOLO
![20180614143533.png](https://qiita-image-store.s3.amazonaws.com/0/335220/5bb9d58e-c0c5-87bd-3b05-a1da6ceb5666.png)
>YOLOはリアルタイムオブジェクト検出アルゴリズムです。YOLO(You Look Only Onse)の名前通り、このアルゴリズムでは検出窓をスライドさせるような仕組みを用いず、画像を一度CNNに通すことで、オブジェクトを検出することができます.

参考:∞ReNom
https://www.renom.jp/ja/notebooks/tutorial/image_processing/yolo/notebook.html

比較的学習が用意で，何より精度，処理速度に優れているとのこと．これはいいかもしれません．次回はYOLOについてまとめることにします．
[laravel] 'htmlspecialchars() expects parameter 1 to be string,～' というエラーについて

#最初に
初投稿です。ものすごくピンポイントですが、結構苦しめられたのでメモとしてまとめます。laravelどころかコーディング経験も浅いので間違い等ありましたらご指摘願います。
#このエラーについて
```php
htmlspecialchars() expects parameter 1 to be string, array given
```
このような文章の場合、「htmlspecialchars()関数は第一引数にstring型を要求しているのに配列が渡っているぞ」というもの。laravelではviewで波括弧{{ }}を使って変数等を表示しようとしたときに現れることがある。

#htmlspecialchars()とは

phpで用意されている関数の一つで、フォームから送られてきた値や、データベースから取り出した値をブラウザ上に表示する際に使用する。主に、悪意のあるコードの埋め込みを防ぐ目的で使われる。[(→php-htmlspecialchars)](http://php.net/manual/ja/function.htmlspecialchars.php)
laravelでのblade上の波括弧{{ }}内の変数は自動的にhtmlspecialcharsに通されxss攻撃を防ぐ。5.3以前はhtmlentitiesを通す。[(→laravel-blade)](https://readouble.com/laravel/5.7/ja/blade.html)

#解決方法
エラー自体はとても単純で、波括弧{{ }}内にhtmlspecialcharsに対応しているstring等を入れる必要がある。配列を表示したいのであれば{{$array[i]}}のように一つの要素に絞る必要がある。stringだけでなく、変数がint等の計算結果であっても問題なく表示される。コントローラーからviewへ値を渡す段階では配列等でも問題はないが、波括弧{{ }}内では一つの要素に特定する必要がある。

#モデルのインスタンスは通る
今回記事にまでしてまとめようと思った原因であり、解決のきっかけにもなった。
一例として以下のような雰囲気のコードを書いた場合

```php:controller
$users = App\User::all();
return view('index', compact('users'));
```

```php:index.blade
@foreach ($users as $user)
    <p>{{$user}}</p>
    <p>{{$user->name}}</p>
    <hr>
@endforeach
{{$users}}
```

この場合エラーは出ない。'おそらく'モデルの機能だと思われる。

for内について、

`$user->name`は
`testUser`と表示される

 `$user`は
`{"user_id":1,"user_name":"testUser"}`のように表示される

for外について、
`$users`は
`{"0":{"user_id":1,"user_name":"testUser"},"1":{"user_id":2,"user_name":"adminUser"}}`のように表示される

明らかに複数要素あるのに問題なく表示される。詳しくlaravelのドキュメントを見れば記載されているはず。

## 追記 
**コメントありがとうございます!!!**
モデルの複数要素が上記のように表示されるのは`__toString()`を通したjson文字列として表示されるためです。
jsonをそのまま文字列化した一つの要素であるためエラーとなりません。

#あとがき(本題とは無関係)
~~青い本から来る人が多かったりするんですかね...?
自分はそうでした。~~
**エラーで迷ったらエラー文を見るのが一番**。自戒です。当たり前の事なんですけど自分の場合無駄にググっちゃったりするんです...
Kotlinでデザインパターン Iterator編

# はじめに

本記事は[Java言語で学ぶデザインパターン入門](http://www.hyuki.com/dp/)を見ながら
JavaではなくKotlinで実装してみようというものです。

![Java言語で学ぶデザインパターン入門](http://www.hyuki.com/images/dp1.png)

# 調べてみる

まずはIteratorとは何かというところから調べましょう。

[Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%86%E3%83%AC%E3%83%BC%E3%82%BF)ではIteratorについて次のように解説されています。

```
プログラミング言語において配列やそれに類似する集合的データ構造の
各要素に対する繰り返し処理の抽象化である。
```

**配列や類似する集合的データ構造の各要素に対する繰り返し処理の抽象化**です。
つまりは配列・リスト・独自データ構造などのデータの集まりでも
**同じインタフェース**で繰り返し処理ができるようにすることがIteratorの役目ということですね。

# 実装してみる

## Iterator

ある集合体クラスを繰り返すためのインタフェースを定義します。

```kotlin
interface Iterator {
    fun hasNext() : Boolean
    fun next() : Object
}
```

## Aggregate

集合体クラスを表すインタフェースを定義します。

```kotlin
interface Aggregate {
    fun iterator() : Iterator
}
```

## Book

集合体クラスの各項目をBookクラスとして定義します。

```kotlin
data class Book(val name : String)
```

## BookShelf

集合体クラスとしてBookShelfを定義
BookShelfは集合体クラスとしたいのでAggregateを実装します。
Aggregateを実装するとIteratorを取得できるようになりますので、
BookShelfの各要素に対して繰り返し処理を行うことができるようになります。


```kotlin
class BookShelf(maxsize : Int) : Aggregate {
    private val books : Array<Book?> = arrayOfNulls(maxsize)
    private var last : Int = 0

    val length : Int get() = last

    fun getBookAt(index : Int) : Book? {
        return books[index]
    }

    fun appendBook(book : Book) {
        this.books[last] = book
        last++
    }

    override fun iterator(): Iterator {
        return BookShelfIterator(this)
    }
}
```

## BookShelfIterator

BookShelfのためのIteratorをBookShelfIteratorとして定義
集合体クラスによって配列の要素を取得・追加するメソッドは異なります。
次のように集合体クラスごとにIteratorを実装したクラスを作成しインタフェースを揃えてやります。

```kotlin
class BookShelfIterator(bookShelf : BookShelf) : Iterator{
    private val bookShelf : BookShelf = bookShelf
    private var index : Int = 0

    override fun hasNext(): Boolean = (index < bookShelf.length)
    override fun next(): Object {
        val book = bookShelf.getBookAt(index)
        index++
        return book as Object
    }
}
```

## Main

上記で定義したクラスとインタフェースを使って、
集合体の各項目に対して繰り返し処理を実行します。

```kotlin
fun main(args : Array<String>) {
    val bookShelf : BookShelf = BookShelf(4)
    bookShelf.appendBook(Book("Around the World in 80 Days"))
    bookShelf.appendBook(Book("Bible"))
    bookShelf.appendBook(Book("Cinderella"))
    bookShelf.appendBook(Book("Daddy-Long-Legs"))

    val iterator : Iterator = bookShelf.iterator()
    while (iterator.hasNext()) {
        val book : Book = iterator.next() as Book
        println(book.name)
    }
}
```

次のようにFor文でぐるぐるまわすパターンだと、
配列やリストなど集合体を表すパターンごとに繰り返し処理を変えなければなりません。
これをなくすためのデザインパターンがIteratorなんですね。

```kotlin
    val array : Array<Book?> = arrayOfNulls(4)
    array[0] = Book("Around the World in 80 Days")
    array[1] = Book("Bible")
    array[2] = Book("Cinderalla")
    array[3] = Book("Daddy-Long-Legs")
    for(i in 0..3){
        // Indexでアクセスしたり、またはクラス固有のメソッドを呼び出したり
        println(array[i]?.name)
    }
```

Iteratorは自然に触れているデザインパターンですよね、
ForEachとか処理できるのもIteratorを実装しているからなわけですしね。
【2019年1月現在】PHP7.3でcomposerが使えなくなるバグの対策

2019年1月10日現在、PHP7.3をbrewでinstallしたMac機で、
composerコマンドを叩くと以下のエラーが出る事象がある。

```
PHP Fatal error: Uncaught ErrorException: preg_match_all(): JIT compilation failed: no more memory 
```


こちら、どうやらPHP7.3のバグらしい。
現在の回避策として、`pcre.jit=0`をpip.iniに付け加えればひとまずOKっぽい。

詳細参考：https://nnahito.com/articles/19
【windows10】nvmを使用してのNode.jsバージョン管理

## はじめに

今まで、MacにてNode.jsのバージョン管理ツールを使用して作業を行っていましたが、
windows10にNode.jsをインストール必要があったため、手順をメモします。

単純にwindowsにNode.jsをインストールするのであれば、公式サイトのインストーラーからインストールするのが早いです。

[Node.js(公式サイト)](https://nodejs.org/en/)

案件や開発環境によって、`Node.js`や`npm`のバージョン変更が必要なため、今回はバージョン管理ツールを使用してNode.jsをインストールする手順をまとめます。

※`nodist`を使用しようとしましたが、npmのバージョンを変更した際にエラーになったため、今回は`nvm`を使用します。

## 設定するバージョン

今回、設定するバージョンは下記の通りです。

|  コマンド  |  バージョン  |
| ---- | ---- |
|  node  |  v8.11.4  |
|  npm  |  5.6.0  |


## nvmをインストール

下記URLから最新バージョンの「nvm-setup.zip」をダウンロード

[nvmインストーラー](https://github.com/coreybutler/nvm-windows/releases)

ダウンロードが完了したら、「nvm-setup.zip」を展開します。

「nvm-setup.exe」を実行し、nvmをインストール

コマンドプロンプト、PowerShellを起動し、下記コマンドを実行

`nvm version`

下記のようにバージョンが表示されれば、インストール完了です。

`1.1.7`

## Node.jsをインストール

下記コマンドを実行し、Node.jsをインストールします。

`nvm install 8.11.4`

下記コマンドを実行し、インストールされているNode.jsのバージョン一覧を表示

`nvm list`

先ほど、インストールしたバージョンが表示されていれば、インストール完了です。

`8.11.4`

## Node.jsを使用する設定

下記コマンドを実行

`nvm use 8.11.4`

## node,npmのバージョンを確認

Node.jsのバージョンを確認

`node -v`

結果

`v8.11.4`

npmのバージョンを確認

`npm -v`

結果

`5.6.0`
brew upgrade --cleanup したらWarningが出るようになった

以下のバージョンにおいて、`brew upgrade --cleanup`するとWarningが表示されるようになった。

```console
$ brew -v
Homebrew 1.9.0
Homebrew/homebrew-core (git revision 53fc2; last commit 2019-01-09)
Homebrew/homebrew-cask (git revision b8834; last commit 2019-01-09)
```

```console
$ brew upgrade --cleanup
Warning: Calling 'brew upgrade --cleanup' is deprecated! Use 'HOMEBREW_INSTALL_CLEANUP' instead.
```

どうやら、 `brew upgrade --cleanup` はもうdepricatedのため、 `HOMEBREW_INSTALL_CLEANUP` という環境変数を突っ込んだほうがよい、ということらしい。([参考のPull Request](https://github.com/Homebrew/brew/pull/5165))

Fishの場合、`env HOMEBREW_INSTALL_CLEANUP=1 brew upgrade` としたところ、エラー無く通るようになった。

下記のfishのconfigを入れた状態であれば、`brew upgrade`だけで大丈夫だった。

```config.fish
set -x HOMEBREW_INSTALL_CLEANUP 1
```

https://brew.sh/2019/01/09/homebrew-1.9.0/ にも書いてあった
ulid の C# 実装 NUlid を使ってみた

## ulid とは

[【Qiita】ソート可能なUUID互換のulidが便利そう](https://qiita.com/kai_kou/items/b4ac2d316920e08ac75a)という記事で紹介されています。時系列でソートされる UUID のようです。

## NUlid とは

[【Github】RobThree/NUlid](https://github.com/RobThree/NUlid)

C# で実装された ulid ライブラリです。Ulid 型はタイムスタンプとランダム値で表される値で、Time プロパティから生成日時（UTC）を取得することができました。
重複しないID値をキーにしたいが、生成順にソートできるようにもしたいというようなケースで利用できそうです。

```c#
// 新規IDを生成
NUlid.Ulid id = NUlid.Ulid.NewUlid();

Debug.WriteLine(id.ToString());
Debug.WriteLine(id.Time);
Debug.WriteLine(id.Time.ToLocalTime());
Debug.WriteLine(BitConverter.ToString(id.Random));
Debug.WriteLine(id.ToGuid());
```
```console:出力結果
01D0SM8S9X08NG5YMG4C79CN7P
2019/01/09 15:39:06 +00:00
2019/01/10 0:39:06 +09:00
02-2B-02-FA-90-23-0E-96-54-F6
44336801-3d65-2b02-02fa-90230e9654f6
```

```c#
// 10個の値を生成
for (int i=0; i< 10; ++i)
{
    Debug.WriteLine(NUlid.Ulid.NewUlid());
}
 ```
```console:出力結果
01D0SMPX6A58EZR2KYFGCK3H81
01D0SMPX6B7M7G8BVGY5R44BFE
01D0SMPX6CEB94VCPWC9YX3F1Z
01D0SMPX6CESDT8N2AJWRAXZSP
01D0SMPX6D8VYKZ19M71NWFNY0
01D0SMPX6D5814C2Y0KAS6FK9T
01D0SMPX6EQAWGM9NWZQQ4TNQZ
01D0SMPX6FZAAHP2ZBQCZ29B5Z
01D0SMPX6F7R9QJGD50YX38VKC
01D0SMPX6GHWKSRXCFMCF264H0
```
指定したHTTPステータスを返してくれるやつ

## 概要

とある案件の試験でhttpステータス（200, 400, 500系）が返ってきた時の試験が必要だったのでちゃちゃっと作ったので一応メモ。

## 環境

PHP5.4以降なら何でも

## コード

```php
http_response_code(filter_input(INPUT_GET, 'ec', FILTER_SANITIZE_NUMBER_INT) * 1);
```

## 動かし方

コードを置いたディレクトリに移動して以下のコマンド。

```
$ ~> php -S localhost:8080
```
[PHP: ビルトインウェブサーバー - Manual](http://php.net/manual/ja/features.commandline.webserver.php)

後はお好きなようにぶっ叩くだけ（以下、一例）

```
$ ~> curl -I "localhost:8080/?ec=404"
HTTP/1.1 404 Not Found
Host: localhost:8080
Date: Mon, 07 Jan 2019 08:48:51 +0000
Connection: close
X-Powered-By: PHP/7.1.19
Content-type: text/html; charset=UTF-8
```
GETパラメータのecに好きなhttpステータスコードを渡せばそれを返してくれます。
【Blender】Blender必須ショートカット

環境メモ
⭐️Mac OS Mojave バージョン10.14
⭐️Blender v2.79.6
⭐️Mac Book


仕上がり
![kuma.jpg](https://qiita-image-store.s3.amazonaws.com/0/93155/0ce770de-fa9a-a7fa-7306-99dd06272a4d.jpeg)


1.Shift + S
<img width="608" alt="001_Shift + S.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/3341ad82-654a-5eb8-3bc6-69e104da9e14.png">
※メニューからは「オブジェクト」ー「スナップ」
<img width="569" alt="スクリーンショット 2019-01-12 10.24.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/7d3fb018-ff21-8923-587e-4b2792798c32.png">


2.Shift + D で複製
<img width="270" alt="スクリーンショット 2019-01-10 0.19.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/bd4f4293-72aa-833d-528b-1534c09fbc8f.png">


3.オブジェクトを選択した状態で「S」キーで全体の拡大・縮小
<img width="504" alt="スクリーンショット 2019-01-10 0.20.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/1f0b7553-5d15-332c-dc56-1ed33d6ead95.png">
※「メッシュ」ー「トランスフォーム」ー「拡大縮小」
<img width="652" alt="008_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/47e26239-60f9-44b7-1e04-6a41f5ba2f3b.png">



4.オブジェクトを選択した状態で「S」キーの後に「Y」でY軸の拡大・縮小
<img width="658" alt="スクリーンショット 2019-01-10 0.21.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/8ad9ba29-df49-094a-32db-0a02fbc3cb11.png">


5.オブジェクトを選択した状態で「S」キーの後に「X」でX軸の拡大・縮小
<img width="361" alt="スクリーンショット 2019-01-10 0.22.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/0e2630b7-feff-7b5d-7399-74dec1be60f3.png">

6.オブジェクトを選択した状態で「S」キーの後に「Z」でZ軸の拡大・縮小
<img width="326" alt="スクリーンショット 2019-01-10 0.23.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/dd23dc21-19b9-4ce3-75dc-9376c3b9828a.png">


7.Shift + オブジェクトを選択で選択解除
<img width="246" alt="スクリーンショット 2019-01-10 0.24.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/9559a49f-8f03-580a-3811-1e86812d575e.png">


8.「A」キーで、全選択/全選択解除で切り替わる
<img width="508" alt="スクリーンショット 2019-01-12 19.52.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/229f5e94-f228-aa60-ff50-f00bacd76f2c.png">

９.画面ビューの移動
左に移動　Ctrl + 4
右に移動　Ctrl + 6
上に移動 Ctrl + 2
下に移動 Ctrl + 8
<img width="676" alt="スクリーンショット 2019-01-14 12.51.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/79b245fc-636c-93da-60a2-40fa3f0eb510.png">

１０.「N」キー押すとプロパティが表示される
<img width="830" alt="スクリーンショット 2019-02-02 19.51.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/93155/9bba8182-8b95-776b-35a2-ebcffea6bba3.png">
TypeScriptってなんぞ（小並感

## ゴール

1. TypeScriptが何かをふわっと理解する
2. TypeScriptをわかった気になる

## TypeScript is 何？

> TypeScript の言語仕様では、TypeScript を「JavaScript の糖衣構文」と表現しています。この表現は真実で、おそらくこの表現があるから、この言語の対象ユーザー、つまり現在 JavaScript を使っているクライアント側の開発者がこの言語を手に取る重要な一歩になります。

https://msdn.microsoft.com/ja-jp/magazine/dn890374.aspx  
MSDNより。

要するにJavascriptの糖衣構文ってことですね。その後ろは「Javascriptユーザが触る言語として糖衣構文ってのは重要だ」ってことだと思います。多分。
糖衣構文なのか言語なのか...糖衣構文でもあるし言語でもある、と表現するのが正しいのかもしれませんね。下位互換なら任せろのMicrosoftなのでTypeScriptはPythonみたいに下位をバッサリってことは無いんじゃないかなって思ってます。
糖衣構文とは書いてありましたが、もうちょっと砕いて見ていくとNative Javascript（ECMAScript）に「静的型付け」「Null安全」「型推論」を加えた言語、と捉えるのがベターかと思います。最近流行ってる言語、Kotlin、Swift、GoもNull安全・静的型付け・型推論を備えてますね。TypeScriptも漏れずです。
先に書いた通り、Javascriptとの違いは「静的型付け」「Null安全」「型推論」だけです。それだけです。

書き方はJavascriptとそこまで変わりません。Javascriptを「より安全」に「より効率良く」書けるようにした言語がTypeScriptです。これはJavascriptに取って非常に重要なメリットになります。

## 軽くまとめ

* Javascriptに「静的型付け」「Null安全」「型推論」を加えた言語
* Javascriptをより安全により効率よく書ける言語

## TypeScript PlayGround

https://www.typescriptlang.org/play/

## TypeScriptにおける静的型付け/ Null安全

TypeScript

```typescript
let num: number = 1;

console.log(num);

// Type 'true' is not assignable to type 'number'.
num = true;

// Type '"hoge"' is not assignable to type 'number'.
num = 'hoge';

// Type 'null' is not assignable to type 'number'.
num = null;
```

Javascript（コンパイル後）  
※通常はコンパイル時にエラーになるのでコンパイルに失敗します。

```javascript
var num = 1;
console.log(num);
num = true;
num = 'hoge';
num = null;
```

このようにJavascriptでは型付けできずにバグの元になったり、無駄にテストケースが増えるといった事象を防げます。TDDで進めたとしてもコストは下がるのではないでしょうか。  
ちなみにnullの代入はtsconfig.jsonのstrictNullChecksをOFFにすることで可能になります。ただしstrictNullChecksは特別な理由が無い限りはOFFにすべきではありません。nullを許容したい場合は以下のように回避すべきです。

TypeScript（ユニオン型 / 共用型）

```typescript
let num: number | null = 1;

console.log(num);

num = null;

console.log(num);
```

strictNullChecksをOFFにしたら負け。ユニオン型も敗北一歩手前。

## TypeScriptにおける型推論

TypeScript

```typescript
let i = 1
console.log(typeof i);

// Type '"hoge"' is not assignable to type 'number'.
i = 'hoge';

let s = 'hoge';
console.log(typeof s);

// Type '1' is not assignable to type 'string'.
s = 1;
```

GoやKotlinと同じように型推論されており、見事にその期待通りの動きをしてくれています。

## 最後に

大分端折った感ある。
cactiの過去グラフが平均化されないようにする方法

## はじめに
このエントリはcactiの過去グラフを平均化せずに、ポーリングした値をずっと保持したいときの方法を記載します。

## 対象機器および環境

* cacti(1.1.38)

## 関連するエントリ
[CentOS7にcacti1.1.38をインストールする＋グラフを日本語化する](https://qiita.com/haruca_tech/items/47d8eb868f31ab3c20e1)


## 問題点


以下はインストール直後の「DataProfile」設定画面
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/ae022c1e-de4f-bd70-90ae-647530daf269.png)


せっかく５分おきにデータを取得していても、３日以上過去のものを参照しようとすると平均化されたデータしか参照できない。
そこで、過去にさかのぼってグラフを参照したときでも、５分おきに取得した値を参照できるようにする。

## 設定方法

### DataProfile設定

上部メニュ「Console」→サイドメニュ「Presets」→「DataProfiles」を選択
右上の「＋」マークをクリックし、新しいデータプロファイルを作成する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/94a3e7ac-828b-48db-f249-11605b431390.png)

　
新規データプロファイル設定画面で、必要事項を記載する。

Consolidation Functionsはプルダウン＋チェックボックスになっているので、すべて選択する。（すべて選択すると、「4selected」と表示される）
Defautlにチェックを入れ、「Create」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/97cf2f11-0709-e2b1-fc0f-2fb91a2ad212.png)

　
登録できると、以下の画面になるので、右側の「＋」をクリックする
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/8541841c-ee34-4adc-c494-b32c7c422cda.png)

　
すると、プロファイルの設定画面に遷移するので、「Rows」に105128、と入力する。（DataRetentionが自動計算され、１Yearと表示される）
そのほかも入力し、「Create」をクリックする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/5a06b6d0-c424-a106-746a-5dfd558fddfc.png)

同様に以下の４つのプロファイルを作成する

|Name|AggregationLevel|Rows|DefaultTimespan|
|:-:|:-:|:-:|:-:|
|Daily|Each Insert|157680|1 Day|
|Weekly|30 Minutes|26280|1 Week|
|Monthly|2 Hours|6570|1 Month|
|Yearly|1 Day|547|1 Year|


ここまで作成したら「Save」をクリックする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/604f9f7e-54a0-d3d2-4116-b3567c44fc1b.png)

### DataProfileのDataSourceへの適用

「Console」→「Templates」→「DataSource」を選択し、すべてのデータソースを選択して、最下部プルダウンメニュで「ChanageProfile」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/a780e8b6-2a26-807f-9963-ac876fb0f881.png)

　
プルダウンメニュで「1.5Years」を選択して、「Continue」をクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/334782/ad04467d-a16a-1280-5a1a-25e6397d8981.png)


今後作成するグラフ（のデータソース）は、過去1.5年分の５分取得値が閲覧できるようになる。




## 注意事項

データを平均化せず、取得した値をそのまま保持しておくため、データ容量を多く消費します。
今回の例（1.5年分）では、１データソースあたり、6MByte程度消費します。

トラフィックであれば「In」と「Out」で12MByte必要です。
同じIFでエラーを見ようとすると、「InDrop」「InDiscards」「OutDrop」「OutDiscards」で24MByte必要です。
合計して１インタフェイスあたり36MByte必要です。

1.5年の保管が不要であれば、半年／1年、など個別に設定することや、不要なIFはErrorを除外する、などして、データ量が爆発的に増えないように注意します。


## さいごに

この設定は全体にかかわるので、最初（インストール直後）にしておくとよいです。
"Recipe terminated with error." VSCodeでLuaJitLaTeXをcompileできるようにした

# 環境
- Windows 10
- TeX Live 2018
 - LuaLaTeX 1.07.0
 - LuaJitLaTeX 1.07.10 
- VSCode 1.30.2
 - LaTeX Workshop 5.19.0

# 原因
VSCodeのExtensionであるLaTeX Workshopのアップデートによって，`settings.json`内のtoolchainがrecipeに置き換えられた事に起因し，従来の設定ではLaTeXのコンパイルが出来なくなった．

# 道のり
詳しい状況と(u)pLaTeXとptex2pdfを使用している場合の解決策は[こちら](http://lyncs.hateblo.jp/entry/2018/04/15/055543 "VSCodeでTeXがいじれなくなった")で分かり易くまとまっていますが，Lua(Jit)LaTeXとlatexmkを使用している場合の設定の例は見つかりませんでしたので，色々参考にしつつ「とりあえずコンパイルはできる」状態にまで辿り着いたので共有しておきます．

# 修正後の設定(2019年1月時点)
`settings.json`の__USER SETTINGS__に以下の設定をコピペでドカンと記述すれば，とりあえずpdfは吐いてくれるようになりました．この設定下でも "Recipe terminated with error." は出ます．因みに設定内の細かな意味についてはよく分かっていません．既存のpLaTeX, ptex2pdf用のものをLua(Jit)LaTeX, latexmk用に必要部分を書き換えただけなので…


```
{
    "latex-workshop.latex.recipes": [
        {
            "name": "latexmk",
            "tools": [
                "latexmk"
            ]
        },
        {
            "name": "luajitlatex -> upbibtex -> luajitlatex*2",
            "tools": [
                "luajitlatex",
                "upbibtex",
                "luajitlatex",
                "luajitlatex"
            ]
        }
    ],

    "latex-workshop.latex.tools": [
        {
            "name": "latexmk",
            "command": "latexmk",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-pdf",
                "%DOC%"
            ]
        },
        {
            "name": "luajitlatex",
            "command": "luajitlatex",
            "args": [
                "-cmdx",
                "-kanji=utf8",
                "-fmt=luajitlatex.fmt",
                "%DOCFILE%"
            ]
        },
        {
            "name": "upbibtex",
            "command": "upbibtex",
            "args": [
                "%DOCFILE%"
            ]
        }
    ]
}
```

# 今後の修正事項
- 図表・参考文献の引用番号が反映されない．ここら辺はBibTeXの設定をどうにかすればいいとは分かりますが，勉強不足なので修正できてません．
- `\tableofcontents`で目次が出力されない．勉強不足なので以下略

こうしたら良くなるというのがあったらぜひ教えてください．

# 参考文献
- [VScodeで快適LaTeX環境を構築する方法](https://qiita.com/ichigo_abc/items/707e8a5def368a69e9a6 "https://qiita.com/ichigo_abc/items/707e8a5def368a69e9a6")
- [VSCodeでTeXがいじれなくなった](http://lyncs.hateblo.jp/entry/2018/04/15/055543 "http://lyncs.hateblo.jp/entry/2018/04/15/055543")
- [はじめてTeXを使う人が知っておくといいことまとめ](https://qiita.com/Tats_U_/items/01d48eb70a8b359b0d95 "https://qiita.com/Tats_U_/items/01d48eb70a8b359b0d95")

(僕みたいな)LuaLaTeX初心者には以下もおすすめです．
- [TeX処理系御伽話](https://qiita.com/yyu/items/6404656f822ce14db935 'https://qiita.com/yyu/items/6404656f822ce14db935')
- [今風なLaTeXに関するメモ](https://qiita.com/Aruneko/items/13e015bce0112143f277 "https://qiita.com/Aruneko/items/13e015bce0112143f277")
- [「pLaTeXからLuaLaTeXへの移行」に関するクイズ](https://qiita.com/zr_tex8r/items/ac9176e4611bf233a3e0 'https://qiita.com/zr_tex8r/items/ac9176e4611bf233a3e0')