OmniAICreator/Qiita-1.07M huggingface dataset:
magento2におけるロケールの当て方

本記事は[Magento2 Advent Calendar 2018](https://adventar.org/calendars/3176) 18日目の記事になります。
#はじめに
magento2において、文字列は、ロケールファイル（csv）を複数のファイルで継承・上書きして表示しています。
 
本記事では、magento2で文字列を翻訳、変更するためのロケールディクショナリの作り方を紹介します。 

公式DevDocsの[Frontend Developer Guide](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/translations/xlate.html)と[Configuration Guide](https://devdocs.magento.com/guides/v2.3/config-guide/cli/config-cli-subcommands-i18n.html)を見ればだいたいのことが分かるかと思いますが、その中でも注意すべき点や見落としがちな点をご紹介できたらと思います。

#目次
1.[ロケールファイルの配置場所と優先順位](#ロケールファイルの配置場所と優先順位)
2.[Translation packageの作り方](#translation-packageの作り方)
3.[まとめ](#まとめ)

#ロケールファイルの配置場所と優先順位
magento2のロケールファイルの配置は以下のようになっています。（[公式DevDocs参照](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/translations/theme_dictionary.html)）

1. Module translations: <module_dir>/i18n/
2. Theme translations:
     1. < parent_theme_dir >/i18n/ (iterated through all ancestor themes)
     2. < current_theme_dir >/i18n/
3. Translation package: app/i18n/
4. Magento database

ここで注意すべき点は、バージョン2.2系から優先順位が 1 < 2 < 3 < 4 ではなく 1 < 3 < 2 < 4 に変更されたことです。
変更箇所・変更時点は[github](https://github.com/magento/magento2/commit/1412a4cdc625d9924533473be36efc1c4b58fcc3#diff-c22eaa6dc74ae3994815841cb5b7fdd8)に公開されています。

![github-translate.php.png](https://qiita-image-store.s3.amazonaws.com/0/287468/2058c309-9bb5-eda4-ea0a-be0095ad8592.png)

したがってロケールファイルを作る際、プロジェクト全体を翻訳したい場合は3のpackageに、その中でもtheme単位で翻訳したい場合は2のthemeに作る形になるかと思います。

#Translation packageの作り方
2のTheme translationsに関しては< current_theme_dir >/i18n/にcsvファイルを置くだけで機能します。

3のTranslation packageに関しては、app/i18n/< vendor >/< package >/の中に

- registration.php
- language.xml
- xx_YY.csv(xx_YYは国際規格である[ISO 639-1](http://www.iso.org/iso/home/standards/language_codes.htm)(言語コード)と[ISO 3166](http://www.iso.org/iso/country_codes.htm)(国コード)からなるコードです。例:ja_JP)

と3つのファイルを作る必要があります。

###registration.php
```registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::LANGUAGE,
    'magento_xx_yy',
    __DIR__
);
```
###language.xml
```language.xml
<?xml version="1.0"?>
<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd">
    <code>xx_YY</code>
    <vendor>vendorName</vendor>
    <package>packageName</package>
    <use vendor="vendorName" package="packageName"/>
</language>
```
codeに関してはvendor/magento/framework/Locale/Config.phpを参照すると良いです。

useの部分では継承する親のロケールファイルのvendor名とpackage名を記述します。（package名は大文字小文字に気をつけてください！）

###xx_YY.csv
```php:xx_YY.csv
"String to overwrite","上書き後の文字列"
```
左に上書きしたい文字列を記述し、カンマで区切り、右に上書き後の文字列を記述します。

ここまで来たら
`php bin/magento cache:clean`
`php bin/magento cache:flush`
で適用されます。

#まとめ
本記事では、magento2で文字列を翻訳、変更するためのロケールディクショナリの作り方を紹介させていただきました。

注意すべきポイントなど、少しでも皆様の参考になりましたら幸いです。

ご覧いただきありがとうございました:notes:
searchkick language: 'japanese' と Elasticsearch 6.5 系を組み合わせるとインデックスの作成に失敗する

## 概要

Elasticsearch 6.5 はインデックス作成時に stemmer をチェックするようになり([elastic/elasticsearch #34601](https://github.com/elastic/elasticsearch/pull/34601))、それに伴い [searchkick.gem](https://github.com/ankane/searchkick) を日本語設定で使おうとするとエラーになる可能性がある。

## Elasticsearch の挙動確認

以下のようなリクエストを 6.4, 6.5 それぞれの Elasticsearch に送ってみる。もちろん `hogehoge` などという stemmer は存在しない。

```shell:発行するリクエスト
curl -XPUT -H "Accept: application/json" -H "Content-type: application/json" localhost:9200/testdayon -d '
  {
    "settings": {
      "analysis": {
        "analyzer": "kuromoji",
        "filter": {
          "hoge": {
            "type": "stemmer",
            "language": "hogehoge"
          }
        }
      }
    }
  }'
```


### 6.4は成功する

```json:レスポンスボディ
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "testdayon"
}
```

### 6.5は失敗する

```json:レスポンスボディ
{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "Invalid stemmer class specified: Hogehoge"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "Invalid stemmer class specified: Hogehoge",
    "caused_by" : {
      "type" : "class_not_found_exception",
      "reason" : "org.tartarus.snowball.ext.HogehogeStemmer"
    }
  },
  "status" : 400
}
```

## [searchkick.gem](https://github.com/ankane/searchkick) は Elasticsearch 6.5だとうまく動かない可能性がある

`searchkick language: 'japanese'` してインデックスを作成しようとすると、以下のようなリクエストを Elasticsearch に発行する。 `JapaneseStemmer` は存在しないので ([stemmer のリスト](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stemmer-tokenfilter.html))、6.5系だとこのリクエストは失敗する。

```json:PUTリクエストのボディ(一部)
{
  "settings": {
    "analysis": {
      "analyzer": "kuromoji",
      "filter": {
        ...(省略)
        // この部分が不正になる
        "searchkick_stemmer": {
          "type": "stemmer",
          "language": "japanese"
        }
        ...(省略)
```

## 対策

プルリクを送ったら直してくれました。

https://github.com/ankane/searchkick/pull/1216

searchkick の最新ブランチ、もしくは次にリリースされるであろう v3.1.3 を使えば大丈夫そうです。
brew cleanupでDirectory not emptyとなった場合の対処

##経緯
brew cleanupを実行した際にerrorで終了しました。

```bash
$ brew cleanup
Removing: /usr/local/Cellar/icu4c/62.1... (250 files, 67.3MB)
Error: Directory not empty @ dir_s_rmdir - /usr/local/Cellar/icu4c/62.1
```

解決に意外と手こずった上、原因は単純なものだったので対処法を残しておきます。

##確認
エラーとなったディレクトリの情報を確認します。

```bash
ls -l /usr/local/Cellar/icu4c/
total 0
drwxr-xr-x  12 test  admin  384 Aug 20 15:52 62.1
drwxr-xr-x  12 user  staff  384 Dec 18 17:29 63.1
```

以前お試し用に作ったユーザーでinstallを実行した際にファイルが作成されたため、権限がなくてエラーになっていたようです。

##対処
ユーザーとグループを修正します。（ユーザーだけでもいいかも）

```bash
$ sudo chown -R user:staff /usr/local/Cellar/icu4c/
```

正しいものに変更されていることを確認します。

```bash
$ ls -l /usr/local/Cellar/icu4c
total 0
drwxr-xr-x  12 user  staff  384 Aug 20 15:52 62.1
drwxr-xr-x  12 user  staff  384 Dec 18 17:29 63.1
```

##再実行

```
$ brew cleanup
:
:
==> This operation has freed approximately 1.6GB of disk space.
```

```bash
$ ls -l /usr/local/Cellar/icu4c
total 0
drwxr-xr-x  12 user  staff  384 Dec 18 17:29 63.1
```

cleanupが正常終了し、ディレクトリも削除されました。

おそらくディレクトリを直接削除するだけでいいとは思いますが、brewが他に何かしているかもしれないので権限を修正してbrewに削除させるのが安全でしょう。
GASでライブラリを作る

[前回](https://qiita.com/shintarow/items/d53986e873d962f7a3c8)、GASで短縮URLを作成する方法に関して書いたのですが、短縮URLを作成する作業は別のシートやGoogleフォームから送られたURLを短縮したいなどの需要があるときに、毎回コピペするのも面倒だと思うので、[公式ページ](https://developers.google.com/apps-script/guides/libraries)を見ながらライブラリにして流用できるようにしてみます。

### 手順


#### 1. ライブラリにするスクリプトを作成する
Google Apps Scriptを新規で立ち上げます。


![tejun1.png](https://qiita-image-store.s3.amazonaws.com/0/37884/6f01ff24-fd29-703e-c822-dad8875d1d59.png)

立ち上がった画面でライブラリにしたいスクリプトを書きます。

```javascript

/**
* bitlyで短縮URLを作成する。
*
* @param 短縮したいURL
* @return 短縮されたURL
*/
function makeBitlyShortUrl(longUrl) {

  const ACCESS_TOKEN = 'Bitlyで取得したアクセストークを記述';
  const ACCESS_URL   = 'https://api-ssl.bitly.com/v4/shorten';

  var payload = {
      'long_url': longUrl,
  };

  var headers = {
      'Authorization' : 'Bearer ' + ACCESS_TOKEN,
      'Content-Type': 'application/json',
  }

  var options = {
      "method"      : 'POST',
      'headers'     : headers,
      'payload'     : JSON.stringify(payload),
  }

  var response = UrlFetchApp.fetch(ACCESS_URL, options);
  var content = response.getContentText("UTF-8");
  return JSON.parse(content).link;
}

```

#### 2.ライブラリとして登録する

ヘッダーメニューから公開を選択し、実行可能APIとして導入をクリック。

![スクリーンショット 2018-12-18 16.54.23.png](https://qiita-image-store.s3.amazonaws.com/0/37884/876c7237-36c8-4c25-f86b-4599e8c0e20b.png)

クリック後に、以下のポップアップが表示されるので、バージョンの説明とアクセス権限を選び、配置をクリックすると、登録が完了します。

![スクリーンショット 2018-12-18 17.42.00.png](https://qiita-image-store.s3.amazonaws.com/0/37884/439b45d8-3792-96c8-949b-bba87f1f1187.png)

次に出るポップアップに表示される`API　ID`は呼び出し側のGoogle Apps Scriptで利用します。

![スクリーンショット 2018-12-18 17.47.05.png](https://qiita-image-store.s3.amazonaws.com/0/37884/df280f1d-491c-0de7-c27e-7e3e87c90de8.png)

#### 3.ライブラリを利用する
Google Apps Scriptを新規で立ち上げる or すでに利用されている GASの編集画面を立ち上げて
ヘッダーメニューから、リソースを選択し、ライブラリをクリック。

![スクリーンショット 2018-12-18 17.55.49.png](https://qiita-image-store.s3.amazonaws.com/0/37884/ba1933db-5f41-9169-0293-edb078e01629.png)

立ち上がったポップアップで、ライブラリに追加の横にあるフィールドに　2で表示された、 `API ID`　を入力して追加をクリック。
読み取れると、ポップアップの上部に今回作成したライブラリが追加される。
バージョンの選択し、識別子を入力して保存をクリック。

*※ 呼び出し側のスクリプトでは識別子に入力された値を使って、メソッドをコールします。*

![スクリーンショット 2018-12-18 18.04.16.png](https://qiita-image-store.s3.amazonaws.com/0/37884/3572ad68-3507-0ba8-a737-f4a967fcb5e3.png)

これで準備が整ったので、スクリプト側でライブラリに定義された、識別子+ `.`　を入力するとライブラリ側で定義したメソッド名が保管され表示されます。

![スクリーンショット 2018-12-18 18.30.00.png](https://qiita-image-store.s3.amazonaws.com/0/37884/8f06441a-0d8c-d475-3cd6-43ff1dc4b03a.png)

これで、ライブラリの作成と呼び出しは完了です！
GASのレベルをあげて色々と業務に役立つツールを作っていきたいです！

以上、明日もよろしくおねがいします！
line_profiler with multiprocessing

## はじめに

pythonの処理時間計測ツールの定番、line_profilerだけど、マルチプロセスなプログラムで動かすのにちょい苦労したのでメモ。

## どれどれ

そもそも公式ドキュメントって
 https://github.com/rkern/line_profiler の下の方にあるのくらいだよね? 不親切！

で、

```python
from multiprocessing import Process

def child(num):
    ...

def main():
    for i in range(5):
        p = Process(target=child, args=(i,))
        p.start()
```

みたいなプログラムでボトルネックを探そうと思ってcProfileやline_profilerを使うわけだが、

```python
from multiprocessing import Process

@profile
def child(num):
    ...

@proile
def main():
    for i in range(5):
        p = Process(target=child, args=(i,))
        p.start()
```

なんてやってもchildの中までは計測してくれないのよね。普通の関数ならもちろんいけるよ? でも別プロセスにしちゃうとダメっぽい。cProfileも同様。で、いろいろググったり公式ドキュメント見たりしながらもサクっと正解は転がっておらず試行錯誤。(stackOverflowのQAがとても参考に)

## お願い、できて

結論、子プロセスに wrap をかませることにより成功。

```python
from multiprocessing import Process
from line_profiler import LineProfiler

def child(num):
    ...

def wrap(num):
    prof = LineProfiler()
    prof.add_function(child)
    prof.runcall(child, num)
    prof.print_stats()
    prof.dump_stats('xxx%d.prof'%num)

def main():
    for i in range(5):
        p = Process(target=wrap, args=(i,))
        p.start()
```

dump でファイル名をプロセスごとに分けてあげないと最後に終了したので上書きされてしまう模様。

## おわりに
もっといい方法がありそう。
100均Xmasツリーをラズパイで光らせてみた

あちこちで見かけるキラキラ光るXmasツリーを眺めていたらラズパイでXmasツリーを光らせたくなりました。
100均ツリーとデコレーションライトをラズパイにつないでPythonでPWM制御したらふわふわ光っていい感じ！
若干点灯パターンに不規則性をもたせたかったのでデューティ比の上げ下げ間隔をランダムに変えています。

## 購入した材料
- ミニチュアツリー(ダイソー)
![IMG_5169.JPG](https://qiita-image-store.s3.amazonaws.com/0/316625/6e11326b-189a-ad7f-1b21-38f791ef8fe2.jpeg)


- デコレーションライト(ダイソー) ※電池2本で動き、常時点灯のもの
![deco.JPG](https://qiita-image-store.s3.amazonaws.com/0/316625/f48fea1c-6926-9d1b-07c4-5706806e5d8c.jpeg)


## 配線
3Vで駆動するLEDなので3.3Vでも多分問題なさそう。今のところ制限抵抗無しで動かしています。
配線の加工は面倒なので、みの虫クリップを使ってLEDの電池ボックスとラズパイを接続。
下記コードはGPIO21を電池ボックスの+側に、GNDを-側に接続したもので動作させています。
![IMG_5186.JPG](https://qiita-image-store.s3.amazonaws.com/0/316625/330e4ef8-d325-80a7-f036-a74acc9bc920.jpeg)


## デコレーションライトを光らせるコード
PWM出力周波数やデューティ比の刻み値やスリープの時間はお好みで調整下さい

```python:xmastree.py

import RPi.GPIO as GPIO
import random
from time import sleep

LED1 = 21
GPIO.setmode(GPIO.BCM)
GPIO.setup(LED1, GPIO.OUT)
pwm = GPIO.PWM(LED1, 60) # PWM出力周波数を60Hzで設定
pwm.start(0)

try:
    print("press ctrl+c to exit program")
    while True:
        step_value = random.randint(1, 3) # デューティ比の刻み値を1〜3の範囲でランダムに生成
        for dc in range(0, 101, step_value): # デューティ比を0〜100%まで指定の刻み値で上げる
            pwm.ChangeDutyCycle(dc)
            sleep(0.01)
        for dc in range(100, -1, -step_value): # デューティ比を100〜0%まで指定の刻み値で下げる
            pwm.ChangeDutyCycle(dc)
            sleep(0.01)
except KeyboardInterrupt:
    print("program exited")

pwm.stop(0)
GPIO.cleanup(LED1)
```

それでは、良いクリスマスを！
![IMG_5108.JPG](https://qiita-image-store.s3.amazonaws.com/0/316625/374aefe7-63e8-40be-7461-81a87cc78668.jpeg)
コマンドのパスを通す

すぐ忘れるので、メモ

## 書き込む場所
`.bash_profile`

## 書き込む内容
今回は、phpunitのコマンドのパスを通す。
`場所はどこでもいい。`

```
alias phpunit='vendor/bin/phpunit'
```

## 登録コマンド一覧を表示
`alias`

```
$ alias
alias phpunit='vendor/bin/phpunit'
```

## 参考
https://eng-entrance.com/linux-command-alias
プログラミング言語と驚き

# 免責

* 社内勉強会でネタとして発表したLT資料です
* 口頭での説明を前提としていて、資料中には十分な説明がない点をご了承ください

----

# 達人プログラマー (p.17)

> **毎年少なくとも一つの言語を学習する。**
> 言語が異なると、同じ問題でも違った解決方法が採用されます。つまり、いくつかの異なったアプローチを学習することにより、幅広い思考が可能になるわけです。

----

# 過去に出会ったプログラミング言語で（当時）印象に残った点をたった1つ挙げるとしたら

----

# BASIC

* 行番号。セルフ採番ってマジですか

```basic
 10 REM 5つ数える
 20 FOR I = 1 TO 5
 25 IF I = 3 THEN GOTO 40
 30 PRINT I
 40 NEXT
```

----

# Pascal

* 手続きと関数がキーワードレベルで違う

```pascal
procedure print(n : integer);
begin
  writeln(n);
end;

function sum(x,y : integer) : integer;
begin
  sum := x + y;
end;
```

----

# C

* マクロでコンパイル前にコード置換できる

```c
#include <stdio.h>

#define MAX(x, y) ((x) > (y) ? (x) : (y))

int main(void) {
    printf("%d\n", MAX(1, 2));
    return 0;
}
```

----

# sh

* esac! esac! esac!

```sh
case "$COMMAND" in
   "pull") echo "..." ;;
   "push") echo "..." ;;
   "help") echo "..." ;;
   "*")    echo "..." ;;
esac
```

----

# Perl

* 正規表現のパワー

```perl
while (<>) {
  if ($_ =~ /^[0-9]+$/) {
    print $_;
  }
}
```

----

# Ruby

* すべてがオブジェクト

```ruby
10.times {|i|
  puts "#{i}: Hello"
}
```

----

# ML

* カリー化による関数の部分適用

```ml
fun add x y = x + y;
val increment = add 1;
val result = increment 10;
```

----

# Prolog

* 異次元

```prolog
father(波平, サザエ).
father(波平, カツオ).
parent(X, Y) :- father(X, Y).
sibling(X, Y) :- parent(Z, X), parent(Z, Y), X\=Y.

?- sibling(X, Y).
X = サザエ, Y = カツオ

?- parent(波平, Z).
Z = サザエ
Z = カツオ
```

----

# Java

* 長っ

```java
package com.example.hello;

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}
```

----

# Python

* インデントでブロックを表す

```python
def hello(msg):
  if msg == "World":
    print("Hello, ", end="")
  print(msg)

hello("World")
hello("world")
```

----

# C++

* 演算子オーバーロード

```cpp
Complex& operator+=(const Complex& z) {
    this->real += z.real;
    this->imag += z.imag;
    return *this;
}
```

----

# C# 

* Javaだね

```csharp
namespace HelloWorld {
    class Hello {
        static void Main() {
            Console.WriteLine("Hello World!");
        }
    }
}
```

----

# Scheme

* プログラムはデータ、データはプログラム

```scheme
(define (fib n)
  (cond
    ((= n 0) 0)
    ((= n 1) 1)
    (else
      (+ (fib (- n 1))
         (fib (- n 2))))))
```

----

# JavaScript

* プロトタイプ

```js
function Greeting() {}
Greeting.prototype.hello = function(msg) {
    console.log("Hello " + msg);
}
function Human() {}
Human.prototype = new Greeting();
new Human().hello("World");
```

----

# SQL

* 宣言的（←→手続き的）

```sql
SELECT * FROM employee
  WHERE employee.department_id IN (1, 2, 3)
  ORDER BY employee.id DESC;
```

----

# Scala

* パターンマッチ

```scala
(1 to 100) map { x =>
    (x % 3, x % 5) match {
        case (0, 0) => ”FizzBuzz”
        case (0, _) => “Fizz” 
        case (_, 0) => “Buzz” 
        case _ => x.toString
    }
} foreach println
```

----

# Go

* 日付フォーマットの指定

```go
package main

import "fmt"
import "time"

func main() {
    now := time.Now()
    fmt.Println(now.Format("2006-01-02 15:04:05"))
}
```

----

# いろんな言語に触れてみよう :smile:
BeautifulSoup4 であるページが参照している内部のimg,js,cssをピックアップする(+おまけ)

## 目的

`http://example.com` というサイトがあって、レスポンス内容に含まれている

* `img`タグで呼んでいる画像URL
* `script`タグで呼んでいるスクリプトのURL
* `link`タグで呼んでいるスタイルシートのURL

をピックアップした後に、 **同じホスト名から取るもの** をリストアップするだけのもの。

## コード

```py3
import requests
from bs4 import BeautifulSoup

def _fetch_targets(url: str) -> list:
    """指定したURLにアクセスした際に、直後に取る画像,JS,CSSファイルのURLリストを作る
    """
    session = requests.Session()
    resp = session.get(f"{url}/")
    soup = BeautifulSoup(resp.content, 'html.parser')
    # Image
    img_tags = soup.find_all('img')
    img_tags_origin = [
        s.attrs['src'] for s in img_tags
        if s.attrs['src'].startswith(url)
    ]
    # JS
    script_tags = [
        s for s in soup.find_all('script')
        if 'src' in s.attrs
    ]
    script_tags_origin = [
        s.attrs['src'] for s in script_tags
        if s.attrs['src'].startswith(url)
    ]
    # CSS
    css_tags = [
        s for s in soup.find_all('link')
        if 'stylesheet' in s.attrs['rel']
    ]
    css_tags_origin = [
        s.attrs['href'] for s in css_tags
        if s.attrs['href'].startswith(url)
    ]
    # 一括加工
    targets = img_tags_origin + script_tags_origin + css_tags_origin
    return [t.replace(url, '') for t in targets]

# 使い方
if __name__ == '__main__':
    _fetch_targets('http://example.com')
```

### 中身概要

基本的には`BeautifulSoup4`の機能に乗っかり、「タグを探索→特定属性によるフィルタ→全部を束ねて整形」というシンプルな構成

＊ `img`タグは、「いくらなんでもsrcはあるだろう」と決めつける
＊ `script`タグは、タグ内に直接書くことも可能なので、「`src`属性を持っていること」でフィルタリング
* `link`タグは、いろいろと入り乱れているので、「`rel`属性が`stylesheet`であること」でフィルタリング


### linkタグの属性について

CSSのものだけを`link`タグから抽出するときに`rel`属性を使うのだけれど、リストであることを初めて知った気がする。


## 本当の目的

`Locust.io`を使ったサーバーへの負荷テストをしたくて、アクセス先だけでなくそのページが参照しているリソースも含めて処理したほうが負荷テストになるかなと思い実装してみた。

### 残りのコード

```py3:locustfile.py
from locust import HttpLocust, Task, TaskSet

# --------
# この辺に、さっきの_fetch_targetsが入る
# --------

def generate_get_task(task: Task, url: str) -> callable:
    """タスクジェネレータです
    """
    def _get_task(task: Task):
        task.client.get(url)
    return _get_task


class TopPageWithResources(TaskSet):
    """テスト振る舞いの定義セット
    """
    def __init__(self, parent):
        """アクセス対象のテストをまるごとセットする
        """
        super().__init__(parent)
        self.tasks = []
        self.tasks.append(generate_get_task(self, '/'))
        for t in _fetch_targets(self.locust.host):
            self.tasks.append(generate_get_task(self, t, counter))


class WebsiteUser(HttpLocust):
    """テスト実行の実設定
    """
    task_set = TopPageWithResources
    min_wait = 500
    max_wait = 900
```

動的に増やすときの正しい位置~~を調べるのが面倒~~がわからなかったので、
タスクを定義する関数を別途用意して、テスト対象 + `_fetch_targets`で見つけたURL全てを、`tasks`に突っ込んでみた。

### こんな感じになる

<img width="831" alt="スクリーンショット 2018-12-18 16.59.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/6805/9d4fc710-07cc-ffaa-ec8e-a1ab20a17207.png">

トップページの構成が変わっても、そのままシナリオとして使えそうで、個人的には便利かなと思っている。
電圧計を自作する

分圧回路を使った電圧計を作る機会が多いため、
新しく作る時にスムーズに作ることができるよう、備忘録としてまとめておきます。

# 分圧回路の仕組み
VCCの電圧は、図の抵抗R1・R2の比率でVOUTに出力されるようになっています。
<img width="215" alt="分圧回路.png" src="https://qiita-image-store.s3.amazonaws.com/0/256451/e30a4296-a87a-d23c-237c-f8026e8effe4.png">

最大電圧がおおよそ分かっている場合、あとは取り出したい電圧の範囲になるよう、
抵抗値を計算して制作することができます。

# 抵抗値の計算
以下のサイトで計算できます。
[抵抗計算ツール](http://sim.okawa-denshi.jp/teikokeisan.htm)

今回は例として、最大電圧22VになるVINを、0〜3.3Vになるよう変換します。
以下のような結果になります。
<img width="736" alt="22V-3.3Vpng" src="https://qiita-image-store.s3.amazonaws.com/0/256451/9403649e-4cc4-2685-5baf-ae7db79b9b50.png">
R1が6.8kΩ、R2が1.2kΩという結果になりました。
これらの抵抗を準備して、制作していきます。

# 回路の実装
材料を準備して、電圧計を制作します。
- 抵抗
    - 6.8kΩ
    - 1.2kΩ
- ターミナルブロック
- ユニバーサル基板
- ピンヘッダ、もしくはピンソケット（1×3ピン）

回路図に沿って配線し、はんだ付けします。
![DSC_0109.png](https://qiita-image-store.s3.amazonaws.com/0/256451/6ee4b6f0-57d3-eee9-c028-000ee935d135.png)

# プログラミング
VOUTの値をアナログ入力で受け取ります。
Arduinoマイコンを使用します。

```c:voltage_divider.ino
void setup()
{
  Serial.begin(115200UL);
}
void loop()
{
  float value = analogRead(A0);
  value *= 3.3;    // 取り出したい電圧の最大値
  value /= 1024;   // アナログ入力の分解能(10ビット)
  value /= 1.2;    // R2の値
  value *= 8;      // R1+R2の値(6.8+1.2 = 8)
  Serial.print("Voltage is:")
  Serial.println(value);
  delay(1000);
}
```

# 配線・動作
| Arduino       |       分圧回路 |    電池    |
|:-----------------:|:------------------:|:------------------:|
| -             |              ターミナルブロックの<br>+(プラス)穴 |        +(プラス)        |
| -           |             ターミナルブロックの<br>-(マイナス)穴 |       -(マイナス)       |
| A0             |              VOUT |        -        |
| GND             |              GND |        -        |
表のように配線し、プログラムを実行します。
シリアルモニタを確認すると、以下のように1秒毎に電圧が表示されるようになります。
<img width="753" alt="シリアルモニタ電圧表示.png" src="https://qiita-image-store.s3.amazonaws.com/0/256451/293d5884-d7bf-352a-a786-d81fba36c7da.png">

# まとめ
写真で載せた通り、かなり小さくまとめることができました。
今後作ることになった時にも、スムーズに作ることができるよう心がけたいです。
AWS CLIをDocker環境で実行する

###やったこと
AWS CLI(1.16.76)とSAM(serverless application model)をDocker環境で実行できるようにする。

### Dockerfile

```dockerfile
FROM python:3.6

ARG pip_installer="https://bootstrap.pypa.io/get-pip.py"
ARG awscli_version="1.16.76"

# Install awscli
RUN pip install awscli==${awscli_version}

# Install sam
RUN pip install --user --upgrade aws-sam-cli
RUN mkdir /data
RUN chmod -x /data

ENV PATH $PATH:/root/.local/bin
```
※ awscli_versionはよしなに変えてください。


###コンテナ起動

ビルド

```shell
docker build -t aws-cli .
```

コンテナの起動

```shell
AWS_ACCESS_KEY_ID="<your aws access key id>"
AWS_SECRET_ACCESS_KEY="<your aws access key>"
AWS_DEFAULT_REGION="<aws default region>"

docker run -it \
    -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
    -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
    -e AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION \
    -v $(pwd):/data \
    aws-cli /bin/bash
```
カレントディレクトリが/dataディレクトリにマウントされます。
docker内で指定したバージョンのCLI、SAMが使用できます。

試しにコンテナ内で

```shell

aws s3 ls
```
と打ってs3のバケット一覧が取得できればOKです。

###終わりに
aws cliの環境を整えようとするとpythonやpipのバージョンを合わせたりが面倒だったので、コンテナで運用すると楽になりました。本番環境へのデプロイにも使えると思うので、ぜひ活用してみてください。
副業とオープンロジと私

[OPENLOGI Advent Calendar 2018](https://qiita.com/advent-calendar/2018/openlogi)の18日目の記事です。

# 概要
今年の3月（2018年3月）から[オープンロジ](https://www.openlogi.com/corp/)に副業で参画させていただいています。
約1年ほど副業で関わらせていただいたので勤務形態や行ったことなどを書いていきたいと思います。

私の普段の業務はサーバサイドの仕事をやっているので副業でもそちらの方面で関わっています。

# 応募のきっかけ
たまたま[この記事](https://blog.openlogi.com/2018/01/24/challengeopenlogi/)を見つけて応募しました。

応募の一番の理由は「**本業を週5で続けつつ、毎日の終業後1 ~ 2時間くらいの稼働でも働けそう**」という点でした。

# 働き方
私の場合ではありますが、基本的に **リモートで1日あたり1時間程度稼働するスタイル** です。
週に1回程度の頻度でオフィスに出社して打ち合わせを行い、「この1週間に行った作業の確認」や「次の1週間で行うタスクの確認」などを行います。
オフィスにいるのは2時間程度です。

# 仕事の進め方
上述の通り基本的にはリモートで関わっておりますのでオンラインでのやりとりが多いです。
不明点があればSlackやRedmine、GitHubのPull Requestで確認するというスタイルです。

面と向かってのコミュニケーションが少ない分、**こまめな報告や成果をわかりやすくするため何か作業をしたらPRを作成したりQiitaに記事を投稿するなどに気をつけました。**
比較的円滑に進められたのではないかと自分では思っています。（あくまで自分で思っているだけです）

# この約1年間で行ったこと
## ログの集約
副業を始めた直後にログの集約を行いました。
すでにサーバに出力されているLTSVログを`td-agent`でAmazon S3に送り、Amazon Athenaでselectできるようにするというタスクです。
システムのコア部分を知らなくても進められるタスクなので初動から貢献していけたのではないかと自分では思っています。（あくまで自分で思っているだけです）

この業務をしているときは調査などが多かったのでその内容をいくつかQiitaにまとめてあります。
いくつか例としてあげると以下の通りです

* [td-agent3（Fluentd v1.0）でS3に「LTSV形式のログ」を保存する](https://qiita.com/abetomo/items/184056035a1cfda24a33)
* [FluentdでS3に送ったログをAmazon Athenaで集計する](https://qiita.com/abetomo/items/d242881d0ac260864a05)

## 本体機能に関わる修正
細かいタスクの内容を説明しても伝わらないことが多いと思うので割愛しますが「副業でも進めやすいタスク」について説明してみようと思います。

（どちらかというとタスクを割り振る側の話でタスクを受け取る側の私が話すのはおかしいのですが、進めやすいタスクを振っていただきスムーズに進められたので感謝の気持ちで紹介します。）

副業ということで

* 稼働時間が少ない
* 基本的にリモートなのでコミュニケーションが取りにくい

以上のような課題があります。
ですので、これらの課題が悪さしないようなタスクを割り振る必要があります。

ポイントをあげると以下の通りです。

* 稼働時間が少ないのでスケジュールに比較的余裕のあるタスク
* 独立性の高いタスク
    * 稼働が少なく、面と向かってのコミュニケーションも少ないので他の方との連携が多いと混乱・不具合・スケジュールの遅れの原因になるリスクがあります
    * そこで他のタスクとの連携が少ないタスクを割り振るとうまく行く印象です

# まとめ
オープンロジに副業で関わることについて書きました。
**本業ではあまり触れない技術に触れられ、自分の稼働できる範囲内で副業で関われて実りのある1年でした。**
ドメイン駆動設計のドメインモデルって何？ 「クラウドワークス Advent Calendar 2018」に学びたい要約まとめ。

[「実践ドメイン駆動設計」を読んだので、実際にDDDで設計して作ってみた！ - Qiita](https://qiita.com/APPLE4869/items/d210ddc2cb1bfeea9338#%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%A2%E3%83%87%E3%83%AB)

[クラウドワークス Advent Calendar 2018 - Qiita](https://qiita.com/advent-calendar/2018/crowdworks)

>クラウドワークスの方々がいい事をかきます。

# ドメインモデルとは？

>システムの鍵となる概念と用語を文書化するために作成されるものです。


# よく更新するものらしい。ひたすら見直すコアなものらしい。

>全設計書の中で、もっとも高頻度で更新をしたのが、このドメインモデルになります。

# 名前がすごく重要らしい。表記ゆれは迅速に修正した方が良いらしい。

>- プロフィールにある画像を「画像」と呼ぶのか「写真」と呼ぶのかでも人によって違うかも

>- こういった表記をチーム全体で統一するために、気づいたことがあれば早い段階でチーム全体で納得のいくものに定めて

# メソッドに関しても同様で名前が重要らしい

>メソッド(振る舞い)についても同様で、申請1つとっても申請を「送信する(post)」「申請する(request)」「提出する(submit)」... など、色々な言い方ができます。

# どの設計書を更新すべきかなど、設計書の設計運用を話し合ったほうが良いらしい

>DDDの設計をやる上で、前にやった設計書（ドメインモデルなど）の更新は必須になると思いますが、どの設計書を更新するべきかはチームで都度話し合って決める必要があると思いました。

# 「ロバストネス分析」という大戦艦みたいなのがいるらしい

>というのも、ユースケース図はロバストネス分析を行うための準備の役割を果たすところが大きいので、ロバストネス分析で見つかった違和感や修正すべき点などは、ロバストネス分析で全て補完するようにしました。








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Yarn+VueCLI環境をDockerで構築する

# 背景
vue入門の際にvagrant上に構築するとホットリロードが面倒なことになりましたので、
とYarn+VueCLI環境をDockerで実現してみました。

# 筆者の環境
Ubuntu18.04(正確にはpop-os!)
Docker version 18.09.0

# Dockerのインストール
Ubuntuの方は[こちら](https://docs.docker.com/install/linux/docker-ce/ubuntu/)
Macの方は[こちら](https://docs.docker.com/docker-for-mac/install/)
Windows home editionの方は[こちら](https://docs.docker.com/toolbox/toolbox_install_windows/)
Windows pro editionの方は[こちら](http://docs.docker.jp/windows/step_one.html)

# Dockerfileをつくる
まずはフォルダを作ってから、中に空のファイルを作成しましょう。

```bash
mkdir vue_docker # フォルダを作る
cd vue_docker # フォルダの中に移動する
touch Dockerfile # 空のDockerfileを作る
```

その後viでもVScodeでも何でも良いので以下のようにDockerfileを記述します。

```Dockerfile
# node:alpineというイメージ(Dockerを構成してる基礎みたいなもの)をベースにvueに必要なものを記述していく。
# ちなみにalpineというのは軽量版Linuxで、Dockerではよく使われている
FROM node:alpine

WORKDIR /app

# apkはalpineのパッケージマネージャ
RUN apk update && \
    apk add --no-cache git curl && \
    curl -o- -L https://yarnpkg.com/install.sh | sh

ENV PATH $HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$PATH

# ホットリロード
ENV CHOKIDAR_USEPOLLING=true
RUN yarn global add @vue/cli

EXPOSE 8080

CMD ["/bin/sh"]
```

# ビルドしてコンテナを起動する
`Dockerfile`のあるフォルダで以下のコマンドを実行し、コンテナを作成して実行しましょう。
***注意:windowsの方はDocker quickstart terminalsを管理者権限で実行してください***

```bash

docker build -t イメージ名 . # -tで名前をつけてイメージをビルド
docker run --name コンテナ名 -it -p 8080:8080 -v $PWD:/app イメージ名 # --nameでコンテナ名をつけてコンテナを新たに立ち上げる
```

|オプション等|意味|
|:------:|:--:|
|-p|ポートの受け渡し ホストのポート:コンテナのポート|
|--name|コンテナに名前をつける|
|-it|STDINを常に開いてttyを割り当てる|
|-v|共有フォルダ ホスト:コンテナ|
|$PWD|現在のパスを出力してくれる|

コマンド実行後コンテナの中に入れるかと思います。

# コンテナ内の作業
vue-cliはビルド時に導入済みなので、自由にプロジェクトを作ってください。
#### 例

```bash
vue create アプリケーションの名前 -d # ディレクトリを作りvueアプリケーションを作成する
cd アプリケーションの名前 # ディレクトリ移動
yarn serve # サーバーを起動
```

このあと[http://localhost:8080](http://localhost:8080)にアクセスすると無事表示されるかと思います！
***注意:windowsの方は[http://192.168.99.100:8080](http://192.168.99.100:8080)です。***
vagrantでは面倒だったホットリロードも効きます。



# 以下作業中に必要になりそうなコマンド

### CPUが異常に回るとき
vueアプリケーションのフォルダの中に `vue.config.js` というファイルを用意して、以下のように記述してから`yarn serve`を実行してください。node_modulesを監視対象から外すと良いようです。

```js
// vue.config.js
module.exports = {
    // options...
    devServer: {
        watchOptions: {
          ignored: /node_modules/,
          aggregateTimeout: 300,
          poll: 1000,
        },
    }
}
```

### vueプラグインのインストール
```bash
docker exec -it コンテナ名 sh # コンテナに入ってシェルを起動
yarn add vuex # vuexとかvue-routerとか
```

### コンテナ名などの情報を確認する

```sh
docker ps -a # -aをつけることで停止状態のコンテナも一覧化する
```

### コンテナを停止する

```sh
docker stop コンテナ名
```

### コンテナを再起動してアプリケーション編集を再開する。
`docker run`で作ったコンテナは停止後も消えずに残っています。
二回目以降コンテナを起動したいときには以下のようなコマンドを入力します。

```sh
docker start コンテナ名
```

その後再度 `yarn serve` をするためには以下のコマンドを入力しコンテナ内にアクセスします。

```sh
docker exec -it コンテナ名 /bin/sh # runとは違い、execは既に起動しているコンテナでコマンドを実行する。
```

その後、コンテナ内で以下のようにコマンドを入力します。

```sh
cd アプリケーションの名前 # ディレクトリ移動
yarn serve # サーバーを起動
```
MWS 代引きオーダーの出荷通知

# はじめに
MWSを使って出荷管理系のシステムを構築するときには避けて通れない**出荷通知**！
出荷通知といえばsubmit_feedの``_POST_ORDER_FULFILLMENT_DATA_``なのですが、
最近よく分からないエラーが出ていました。

```xml
<Result>
	<MessageID>1</MessageID>
	<ResultCode>Error</ResultCode>
	<ResultMessageCode>XXXX</ResultMessageCode>
	<ResultDescription>YYYYYYYYに一致する注文は出荷できません。</ResultDescription>
	<AdditionalInfo>
		<AmazonOrderID>111-111111-111111</AmazonOrderID>
	</AdditionalInfo>
</Result>
```

OrderIdは間違っていませんし、そもそも「YYYYYYYYに一致する注文は出荷できません。」ってその「YYYYYYYY（数字）」ってなんの番号です？
OrderにもOrderItemにもそんな番号存在しないしお手上！
どうせ今回だけのイレギュラーでしょ！平気平気！
とか思っていたのですが、そのあと1日で2回出ました。（対応せざるを得ないよなあ）
とは言っても手がかりはないし...と途方に暮れていると物販側がオーダーの共通点を見つけてくれました。
**どうも決済が代引きのものの出荷通知が失敗しているようです。**
お、これは勝ちました。と思って調べてみたらなかなか闇が深い。

# フラットファイルで代引きオーダーの出荷通知をするには
[代金引換決済の注文管理](https://aws.typepad.com/jp_mws/2012/02/order_processing_of_cod.html)

> 出荷通知のフィードでは、代金引換の注文に対し、「代金引換」(cod-collection-method)の項目に「DirectPayment」を指定して確認する必要があります。その値を指定せずに出荷通知フィードを代金引換注文に対して送信した場合、処理エラーが発生します。代金引換の注文には、必ず「DirectPayment」を指定するようにしてください。

なるほど。速攻で解決できるやないですか。
設定したら一発やないですか！
でも私たちはXMLでのフィードなのでこの通りにはいきませんよね...

# 公式のxsdを見てみる
XMLでfeed_submitするときはどんな指定の仕方かな...
https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderFulfillment.xsd

いや、ないですやん。
codの項目ないですやん！
メロスは激怒しました。

# 調査は続く
探しに探した結果、フォーラムに希望が一筋。
[アマゾンapiシステムや出荷情報確認について](https://sellercentral-japan.amazon.com/forums/t/api/1536)

>Amazon MWSのAPIでもCODの出荷通知を送信することはできます。
CODの出荷通知を行う際はCODCollectionMethod要素を設定いただく必要があります。
仕様するオペレーションはフィードAPIのSubmitFeedをご使用頂ければと思います。

ほんとなのかよ？

ちなみにCODCollectionMethodで調べてみたら``_POST_PAYMENT_ADJUSTMENT_DATA_ ``には存在ました。
https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderAdjustment.xsd

# XMLで代引きオーダーの出荷通知をするには
結果から言うと、CODCollectionMethodでDirectPaymentを指定すると正常に処理できました。

```xml
<Message>
  <MessageID>1</MessageID>
  <OperationType>Update</OperationType>
  <OrderFulfillment>
    <AmazonOrderID>111-111-111</AmazonOrderID>
    <FulfillmentDate>2018-01-01</FulfillmentDate>
    <FulfillmentData>
      <CarrierName>日本郵便</CarrierName>
      <ShipperTrackingNumber>A111</ShipperTrackingNumber>
    </FulfillmentData>
    <CODCollectionMethod>DirectPayment</CODCollectionMethod>
    <Item>
      <AmazonOrderItemCode>11111111</AmazonOrderItemCode>
      <Quantity>1</Quantity>
    </Item>
  </OrderFulfillment>
</Message>
```

# まとめ

＿人人人人人人人人人人人人人人＿
＞　隠しパラメータは存在する　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣


ブログで見たい方はこちら
[MWS 代引きオーダーの出荷通知](http://nabesys.com/article/2018/12/18649/)
10分間隔で 10時〜23時台の配列をつくる

## こういう配列がほしい

```ruby
["10:00",
 "10:10",
 "10:20",
 "10:30",
...
...
 "23:30",
 "23:40",
 "23:50"]
```

## どうやってやる？


```ruby
interval = 10;
[*10..23].product(0.step(60 - interval, interval).map{|n| n.to_s.rjust(2, '0')}).map{|hour, min| "#{hour}:#{min}"}
```

これでいけた。
interval の値を変えれば、任意の分間隔での配列作れるはず。

## なんか

もっと cool なやり方あったら教えてくれよな :wink:
TerraformのBackendで共通のS3とDynamoDBを使う

TerraformのBackendにS3やDynamoDBを使用できますが、各Terraformプロジェクトで共通のものを使うことができます。

例えば`terraform-state-for-my-company`というS3バケットと、`terraform-state-lock-for-my-company`というDynamoDBテーブルを作成します。

```terraform-state.tf
resource "aws_dynamodb_table" "terraform_statelock" {
  name           = "terraform-state-lock-for-my-company"
  hash_key       = "LockID"
  read_capacity  = 5
  write_capacity = 5

  attribute {
    name = "LockID"
    type = "S"
  }
}

resource "aws_s3_bucket" "terraform_state" {
  bucket = "terraform-state-for-my-company"
  acl    = "private"

  versioning {
    enabled = true
  }
}
```

S3とDynamoDBを作成するリージョンはどこでも構いません。Backendを利用するTerraformプロジェクトのAWSプロバイダのリージョンと異なってていも、問題なく使用することができます。節約のために料金が安いリージョンを選択することも可能です。

Backendを使いたいTerraformプロジェクトで以下のようにBackendを設定します。
例）`my-project`

```my-project-terraform/backend.tf
terraform {
  backend "s3" {
    bucket         = "terraform-state-for-my-company"
    dynamodb_table = "terraform-state-lock-for-my-company"
    key            = "my-project"
    region         = "us-west-2" # S3やDynamoDBが作成されているリージョン
  }
}
```

私の場合は、最初に作成したS3とDynamoDBも1つのTerraformプロジェクトとして管理しています。こちらも自身のS3やDynamoDBを使うことができるので、その場合は一度S3とDynamoDBをapplyし、Backendの設定を追加します。

## まとめ
これでプロジェクトごとにS3やDynamoDBを作る必要がなくなりました。会社で複数のTerraformプロジェクトがある場合は便利です。
git 初コミット

#git クローンからプルリクまで

1. ローカルにディレクトリを作成する
2. git clone URL
3. git branch
4. git branch firstcommit
5. git branch　firstcommitができている事を確認する
6. git checkout firstcommit
7. git branch firstcommitブランチが選択されている
8. echo "初コミット"> first.txt
9. ローカル確認
10. git add first.txt
11. git commit first.txt
12. コミットコメント記載
13. git push origin firstcommit
14. プルリク画面を開いて
15. れびゅあーを設定してプルリク投げる
16. マージしてもらう
Google Analyticsしか知らないあなたのためのGoogle Tag Managerを調べてみた

# 前提
**Google Analytics**は知っている前提です。

お話の流れとしては、サービスをローンチする前に、ちゃんとGoogle Analytics埋め込まれてたか確認しようとしたら、**Google Tag Manager**というものが使われていて、なんじゃこれ？となったので調べたことをまとめたメモです。

# まず安直に検索結果の上位の解説ページを見てみる

[Googleタグマネージャとは？初心者でも分かる利用方法と導入手順](https://ferret-plus.com/1745) から

> また計測 タグを1ページずつ ページに直接埋め込んでいくと、仕様変更でタグの差し替えをしなければならないことがあります。その際、 ページの数だけ タグを書きなおす作業も発生します。
> このようにツールを活用するほど、計測 タグの管理は煩雑になります。このような問題を解決してくれるのが タグマネージャです。
> 今回は、 Googleが提供する タグマネージメント ツールの「 Google タグマネージャ」について解説します。

計測ツールを切り替えるためにということかな。Google Analyticsを使っていたけど、別な計測ツールに切り替えるようなケースを想定しているのであろうか。そんなことなかなか想定できないけど。

Google Analyticsを乗り換えて止める確率と、Google Tag Managerを乗り換えて止める確率、おんなじくらいじゃない？

# ちゃんと公式サイトをみよう

よく「公式サイト」をみよ！「公式ドキュメント」「公式APIドキュメント」を見よ！と言ってるので自分も見ます。

[Google マーケティングプラットフォーム > タグマネージャ](https://marketingplatform.google.com/intl/ja_ALL/about/tag-manager/)

## メリット一覧
- コンバージョン トラッキングやサイト分析、リマーケティングなどで使う独自のタグを、追加、更新できる
- 管理画面からいつでも自由にタグを追加、更新できる
- 使いやすいエラーチェックでサイトがスムーズに動作することが保証される
- ウェブ用とモバイルアプリ用のさまざまな Google タグと第三者タグが利用できる
- 細かくアクセス制限をかけて共同作業ができる
- さまざまな環境でのタグのテストができる

# 追加で調べる

[Googleタグマネージャ（GTM）のメリット、デメリットまとめてみました](https://www.e-n-a.jp/archives/4433)

## 1. 広告を出稿する際に、各社のタグをいちいち貼るために、HTMLファイルを編集する必要が無くなり、管理画面でできる
エンジニアが稼働したり、非エンジニアがHTMLをめちゃくちゃにしたりすることがなくなっていいかも

## 2. バージョン管理機能がある
とはいえGitなどソースコード管理をしていたらそこでできるはず。メリットある？

## 3. プレビューモードと呼ばれるデバッグ機能で公開前にテストができる
これは良さげですね。ちゃんと動いているのかというのが不安になるから
Macにcmakeをインストール方法

#Macにcmakeをインストールしたい

##手順
　**1.下記から自分のPCにあったバージョンのcmakeインストーラーをダウンロード。**
https://cmake.org/download/

　**2.ダウンロード完了後cmake起動。ここでアプリケーションを確認するとちゃんと表示されている。**

　**3.PATHの設定を行う。**

PATHの設定内容を確認できる

```terminal:
export -p 
```
PATHへの追加方法

```terminal:
export PATH=$PATH:追加したいコマンド検索パス
```
再度こちらを実行し、上記の検索パスが追加されていることを確認

```terminal:
export -p 
```

(参考URL)
https://qiita.com/soarflat/items/d5015bec37f8a8254380

**4.完了！**

※全体的に参考にさせてもらったページがこちら。
https://qiita.com/tenmihi/items/09e1e6b273d8db51f4a1
ランダムフォレストで遊んでみた～その１～

#　背景
ほぼ未経験なのですが、データサイエンティストとして転職しました。（やばいです）
右も左もわからない業界ですが、勉強頑張っていきます。
自分でやったことを、備忘録としてQiitaに残していこうとおもいます

※その1なので、きっとその2も出す

ランダムフォレストで何をするかというと、ハワイマウナロア島で観測されているCO2濃度をターゲットとして行きたいと思います。

参考：https://www.esrl.noaa.gov/gmd/ccgg/trends/full.html

#　本題


```python:main.py
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score
```

もろもろをインポート



```python:main.py

input_file = ('./co2.csv')

#ファイル読み込み
df = pd.read_csv(input_file,parse_dates = ['date'])

#欠損値であると思われる－99.99をNaNに変更
nan = df['value'].replace(-99.99,np.nan)
df = pd.concat([df,nan],axis=1)
df.columns = ['date','value_old','trend','value']
#NaNをffillで置換
df_new = df.drop('value_old',axis=1)
df = df_new.fillna(method='ffill')
df.to_csv('notnull.csv')
```
NaNではなく、-99.99という欠損値っぽいデータがあったため、一度np.nanに変換したのちにffillにて置換

```python:main.py

df2 = df.copy()
df2['date'] = pd.to_datetime(df2['date'])
df2.set_index('date',inplace = True)
print(df2['1959-01':'1999-12'])

#1959年1月から開始
df2 = df2['1959-01':'2018-11']

#1959年1月1日から1999年12月1日までと、それ以降でわける
df_be = df2[:'1999-12']
df_af = df2['2000-01':]

df_be.info()
df_af.info()
```
日付を分割。
csv読み込み時に、parse_datesを指定しているけど、この状態だとスライス機能が使えないため、datetime型に変換。

```python:main.py
#trainとvalに分割
X_train = df_be.copy()
y_train = df_be.copy()
X_test = df_af.copy()
y_test = df_af.copy()
X_train=X_train.loc[:,['trend']]
y_train=y_train.loc[:,['value']]
X_test=X_test.loc[:,['trend']]
y_test=y_test.loc[:,'value']
```
なんか、クソ汚い。copy()ってしなくてもいいのでしょうか。
ちょっとわかんなかったので、一旦これで進めます。

```python:main.py

model_RF = RandomForestRegressor(random_state=0)
model_RF.fit(X_train,y_train)


y_train_preds = model_RF.predict(X_train)
y_test_preds = model_RF.predict(X_test)

print('[RF_model] MSE train : %.3f, test : %.3f' % (mean_squared_error(y_train, y_train_preds), mean_squared_error(y_test, y_test_preds)))
print('[RF_model] R^2 train : %.3f, test : %.3f' % (r2_score(y_train, y_train_preds), r2_score(y_test, y_test_preds)))

print(y_test)
print(str(y_test_preds))

y_train.to_csv('y_train.csv')

np.savetxt('y_test_preds.txt',y_test_preds)

```
ランダムフォレストを実行。

結果は
[RF_model] MSE train : 0.875, test : 522.674
[RF_model] R^2 train : 0.997, test : -2.680

test全然できていない。。。

特徴量が少なすぎるからだと思いました。

#　あとがき

pandasの取扱いを早く慣れたいと感じました。
そのためにもプログラミングがんばります。

また、plotを早く覚えなければ。
ファイル検索をもっと楽にしましょう

# FzFとは

Fzf (Fuzzy Finder) はコマンドライン用のファジーファインダー（あいまい検索）ツールです。
ファジー理論はここで説明しないですが、goo辞書からファジーの簡単な意味を引用させていただきます。

> （１）境界が不明確であること。あいまいであること。柔軟性があること。また、そのさま。「ファジーな考え方」
> （２） 人間の認識のあいまいな部分をコンピューターで処理する技術。

Google検索バーで文字を入力始まると、候補が下部に出てくるような感じです。

# FzFのインストール

Githubからインストールできますし
> https://github.com/junegunn/fzf

Homebrewから直接インストールも可能です。

```bash
$ brew install fzf
```

# FzFを実行してみましょう

インストールを完了したら、早速実行してみましょう。例のために似たような名のいくつファイルを用意しました。
![list.png](https://qiita-image-store.s3.amazonaws.com/0/151468/8e8bfa80-1a4d-2f3c-241b-42d215955dbd.png)

では、`fzf`を実行してみましょう。

```bash
$ fzf 
```
ファイルは以下のようにリスト化されます。
![fzf1.png](https://qiita-image-store.s3.amazonaws.com/0/151468/f193f7d8-c4fc-710b-f19b-da93a5f4b4e4.png)

ここでファジーの方が始まります。検索結果を絞るために、文字も入力できます。例えば、`example2.txt`をを出力したい場合は、まず`example`から入力すると
![fzf2.png](https://qiita-image-store.s3.amazonaws.com/0/151468/d654d4f4-c5f4-c8d4-82f2-3895d134871d.png)

当てはまる候補ファイル名に絞られます。ここからマウスやキーボードでファイルを選択できます。適切なファイル名にたどり着いたらENTERキーを押すと標準出力に表示されます。
![fzf4-2.png](https://qiita-image-store.s3.amazonaws.com/0/151468/17cab6e2-8911-bf53-c883-edf060d9f6bf.png)

ファジーファインダーだから、ファイル名に入力されている文字が存在したら、候補として表示されます。
![fzf3.png](https://qiita-image-store.s3.amazonaws.com/0/151468/db440065-6516-4bea-d0a5-6950f26d203a.png)

いい感じですね。

# FzFが便利になる場合

標準出力に出すだけだとあまり意味ないので、他のコマンドと組み合わせましょう。検索しているファイルを開きたい場合は、`open`コマンドと組み合わせて、


```
$ open $(fzf)
```

ファイルを選択してから、そのまま開けます。

もちろん、少ないファイルのディレクトリに実行すると、あまり魅力を感じないと思いますが、数百ファイルがあれば、かなり助かります。ファイルが多いと、普通の`ls`でもGUIから検索しても結構時間かかるので、ファジーファインダーから選択した方が楽です。

# 結論

`fzf`はファジーファインダーで、ターミナルからのファイル検索をもっと楽できるし、他のコマンドと組み合わせるともっと効率化できます。

###### Disclaimer
※ 日本語は母語ではないので、どこかで間違ってたらすみません。
学習サービス掛け合わせでPaizaの練習問題が解けた話

私のようにpaizaでJavaScript入門編1・2をクリアしたにも関わらず
**スキルチェック何も手が付かないんだけど…、と絶望した**方の役に立てばと思い書きました。
あと自分の備忘録。

##はじめに

どうも、3日前からJavaScriptに手を付け始めました初心者です。Qiita初投稿。

学習に使っているサービスは [paiza](https://paiza.jp/works) です。

順調にJavaScript入門編1→2とクリアし、次は問題をやろう！と
[プログラミング練習問題のページ](https://paiza.jp/learning/page/problems)へ進みました。


##1．絶望した
入門編はクリアしたのにDランクの問題すら全く手が付けられない…
という事態になりました。

ちなみに回答しようとしたのは[掛け算](https://paiza.jp/learning/multiplication)です。

**なぜ？**

Paizaはnode.jsが予め仕込まれているため、標準入力については入門編で触れられておらず、下のように突然の標準入力が現れたことで

**「えっ！何これ！？聞いてない！どこに入力して良いかもわかんない！！！」**

という状態に。
![kaitou02.png](https://qiita-image-store.s3.amazonaws.com/0/328195/9af34d77-25c7-195a-05b4-0e9f8c91b1b1.png "JavaScript標準入力")

Qiitaやteratailを見て回りましたが、そもそも過ぎて適切な回答が見当たらない…と絶望しました。


##2．どうやって理解したのか

**「これはもう別サービスで触れているのが無いか入門編漁りをしよう！」**と
[progate](https://prog-8.com/) と [CODEPREP](https://codeprep.jp/) も始めてみました。

progateは「varじゃなくてlet！？paizaと違うこと言ってる！」となっただけで標準入力の記載はなし。

答え(？)は…**CODEPREPにありました！！！**

javascript入門 基本操作編
[②JavaScriptの「型」を学ぼう - 5 配列(Array)](https://codeprep.jp/books/3/chapters/2/sections/5)
を読んだら突然開眼しました！


左側にあるヒント欄に
配列を表現するには [] を宣言します。

```javascript
var array = [];
```

配列にデータを追加するにはpush関数を利用します。

```javascript
array.push('Welcome to CODEPREP');
```

配列からデータを取得するには、配列の中で取り出したいデータのインデックス(格納している場所を表す数値)を指定してデータを取り出します。
インデックスの指定には[]を利用して、中にインデックスを指定します。

インデックスは0番目から始まるため、1番目の値を取得するためには、次のように記述します。

```javascript
array[0];
```

ということはさっきの
![kaitou02.png](https://qiita-image-store.s3.amazonaws.com/0/328195/9af34d77-25c7-195a-05b4-0e9f8c91b1b1.png "JavaScript標準入力")
の15行目を変更すればいいのでは！？となり、下記のように入力しました。

```javascript
console.log(lines[0] * lines[1]);
```

入力される値が
a
b
と改行区切りで与えられていたので

lines[0] で 配列の1番目となる a が、
lines[1] で 2番目となる b が引っ張ってこれるということでは？

ということで

**できたーーー！！**

![paiza01.png](https://qiita-image-store.s3.amazonaws.com/0/328195/b2eab2ba-d072-8a39-65bb-81eae9a59852.png)


そして早速次の足し算やってみよう！と開いたら改行区切りじゃなくてスペース区切りということで line[ ] 内をどう指定したらいいか分からなくなって即詰みました…。
引き続き…頑張ります…。

あと個人的な感想としてはCODEPREPは何も知らない状態で始めるにはハードル高すぎでは？とも思いました。
長時間動き続ける AWS Lambda Function を作ってみようとした

# はじめに
タイムアウトに負けずに長時間動き続ける Lambda Function を作る試みです。Step Functions とか使えという話ではあるのですが、できれば外部の設定を持ち込まずにコードだけで完結させたいところです。
Azure の Lambda 相当のサービスである Azure Functions には Durable Functions というものがあり、C# や JavaScript だけで長時間実行し続ける特殊な関数を記述することができます。この　Durable Functions からアイデアを拝借し、AWS 上で簡易的な Durable Functions もどきを作れないか検証しました。

# コード
https://github.com/nakatsuchi/zombie-functions

# 概念とコードの説明
超簡単に用語の説明だけしておきます。
元ネタの Durable Functions について詳しくは [MSのドキュメント](https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview) を参照してください。

## オーケストレータ
ジョブ全体の実行フローの制御をする関数です。コード中の `orchestrator` 関数がこれに相当します。
この関数は必ず決定的である必要があります。つまり、入力が同じなら常に同じ実行の流れで同じ結果を返さなくてはなりません。また、I/O処理も一切行ってはいけません。

## アクティビティ
オーケストレータから呼び出され、実際の処理を行う関数です。コード中の `print` 関数がこれに相当します。オーケストレータとは異なり、決定的である必要はなく、I/O処理も可能です。

# 実行方法
1. Dynamo DB のテーブルを作成します。名前は `ZombieFunctionsHistory` としてください。Primary partition key に `jobId` (String型) を指定しておきます。
2. Lambda 関数のパッケージをビルドします。コマンドは `npm install && npm run package` です。
3. 適当な Lambda 関数を作成し、2. で作成したパッケージをアップロードします。ロールは Dynamo DB の読み書きに加え、自身に対する `lambda:Invoke` を許可しておく必要があります。
4. あとは普通に Lambda 関数を実行します。

# 仕組み
ポイントは `callActivity` です。`callActivity` の呼び出しは次に示すような動作をします。

- 既に関数が実行されていて結果が Dynamo DB テーブルに記録されている場合は、実際には関数を実行せずに記録済みの結果を返す。
- 関数が未実行の場合は関数を実行し、結果をテーブルに記録する。その時点で現在の Lambda 関数の呼出を打ち切り、再度同じ Lambda 関数を最初から実行する。

これにより、同じ Lambda 関数が再度最初から実行されたときには、実行済みの処理はスキップして未実行箇所まで一気に進み、未実行処理のところまで到達したらその処理を実行して一旦 Lambda 関数の実行を打ち切る、という流れになります。結果として、各処理が都度、新しい Lambda 関数呼び出しとして実行され、タイムアウトしない長時間の実行が理屈上可能にまります。

# オリジナルの Durable Functions と比較した課題
- オーケストレータ関数とアクティビティ関数が同じコンテキストで動いているため、オーケストレータ関数からみてアクティビティ関数を非同期実行できません。したがって、一つのジョブ内で複数のアクティビティ関数を並列実行するようなことはできません。
- アクティビティ関数が失敗した場合のリトライの仕組みがありません。
- Lambda 関数の実行は "at least once" であり、一度の呼び出しによって同時に複数起動することがあります。その場合、不整合が生じて正しく動作しません。(たぶん)
- オーケストレータ関数の実行を一時停止させることができません。Durable Functions では、処理を一時停止させて一定時間経過後に再開させることが可能で、一時停止中は課金されません。外部処理の完了をポーリングしながらのんびり待つようなケースでは重要な機能です。
- 外部イベントの発生を待機する仕組みがありません。
- その他、挙げるとキリがありません

# まとめ
非常に簡易的なものではありますが、長時間動き続ける Function の基礎が実現できました。完全な実装になるまでにはまだまだ検証すべきことが多そうです。気が向いたらやります。
VSCode 用 SystemVerilogの拡張を作る（#2）

# 拡張機能と言語を紐付ける
package.json の

- activationEvents
- languages

の設定が絡んでいます。
languagesが言語の定義となっており、

- id
- aliases
- extensions
- configuration

を設定します。

```json
    "languages": [
      {
        "id": "sv",
        "aliases": [
          "SystemVerilog",
          "Verilog",
          "sv"
        ],
        "extensions": [
          "v",
          "vh",
          "sv",
          "svh"
        ],
        "configuration": "./language-configuration.json"
      }
    ],
```

上記だと、idが識別子でなんでも良いです。aliasesも、適当でいいです。
extensionsが重要で、この拡張子を持つファイルはすべてid:svとカテゴライズされることになります。
configurationは言語の括弧やコメントの種類を指示します。
configurationの意図は括弧の自動補完機能と、対応括弧のサーチのためだと思われますので、無くても大丈夫です。

この言語定義によるid:svをactivationEvents側で設定すると、extensionsで指定した拡張子ファイルを開くと対応した拡張機能が起動する仕組みとなっているようです。

```json
  "activationEvents": [
    "onLanguage:sv"
  ],
```
NeovimでのGolang開発環境を整理する

僕はGolangで開発する際、Neovimを使用しています。
Golangのバージョンアップに伴い、gocodeによる補完がうまく動かなくなったりと色々と問題が発生したので、プラグインや設定の見直しを行いました。その際の備忘録を書いていきます。

## 前置き
プラグインマネージャーには[dein](https://github.com/Shougo/dein.vim)を使わせてもらっているので、他のツールを使っている方は適宜読み替えていただけると助かります。

メインで利用するプラグインは以下の通りです。

- [vim-go](https://github.com/fatih/vim-go)
- [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim)
- [deoplete](https://github.com/Shougo/deoplete.nvim)

以前まではvim-goのみで補完や文法チェック、フォーマッティングまで全部お任せできていたのですが、上述したようにgocodeを利用した補完が難しくなったため、LSP(Language Server Protocol)に一部機能を任せる形に設定しています。
Golangにおけるgocode/LSPについての経緯・情報については以下の記事を参考にさせていただきました。ありがとうございます。
https://mattn.kaoriya.net/software/lang/go/20181217000056.htm

※追記：ちなみに最近見つけた[coc.nvim](https://github.com/neoclide/coc.nvim)という補完ライブラリがLSPクライアントとしても非常に優秀でした。気になる方はぜひ試してみてください。

## 各種プラグイン設定
### vim-go
特に特別な設定は行なっていませんが、LSPを導入することによって不要になる機能でキーマッピングがぶつかるものを無効化しています。

```toml:dein.toml
[[plugins]]
repo = 'fatih/vim-go'
hook_add = '''
  " 保存時に必要なimportを自動的に挿入
  let g:go_fmt_command = "goimports"
  " LSPに任せる機能をOFFにする
  let g:go_def_mapping_enabled = 0
  let g:go_doc_keywordprg_enabled = 0
'''
```
### LanguageClient-neovim/deoplete
deopleteについても特に特別な設定は行なっていません。
NeovimのLSPクライアントの設定も基本的には公式のREADMEに沿った形です。
languageサーバーにはgo-langserverを設定している例が多いですが、内部ではgocodeが使われているとのことですので、Golang公式がサポートしているという[gopls](https://github.com/golang/tools/tree/master/cmd/gopls)を設定しています。
そのため設定を変更する前にgoplsを取得しておきます。

```
go get -u golang.org/x/tools/cmd/gopls
```

```toml:dein.toml
[[plugins]]
repo = 'Shougo/deoplete.nvim'
on_event = 'InsertEnter'
hook_add = '''
  let g:deoplete#enable_at_startup = 1
'''

[[plugins]]
repo = 'autozimu/LanguageClient-neovim'
build = 'bash install.sh'
rev = 'next'
hook_add = '''
  set hidden
  let g:LanguageClient_serverCommands = {
      \ 'go': ['gopls']
      \ }
  let g:LanguageClient_loadSettings = 1
  nnoremap <silent> K :call LanguageClient#textDocument_hover()<CR>
  nnoremap <silent> gd :call LanguageClient#textDocument_definition()<CR>
'''
```

~~ちなみに[bingo](https://github.com/saibing/bingo)というLanguageサーバーも完成度が高く、快適に利用出来るので、気になる方は一度試してみることをオススメします。~~

※上で紹介したbingoについては開発の継続がされなくなりましたので、goplsを使うようにした方が良さそうです。

## まとめ
自分自身まだ調べながら試行錯誤中ですので、より良い設定が見つかれば随時更新していきたいと思います。
記載内容に誤りがあったり、これも記載しておいた方がいいという点などございましたら、ご指摘いただけると助かります。
Rails ActiveSupport の HashWithIndifferentAccess って何？

キーがシンボルでも文字列でもアクセスできるようにしてくれるっぽい。

```ruby
HashWithIndifferentAccess.new(a: 1)['a']
=> 1
```

```ruby
HashWithIndifferentAccess.new(a: 1)[:a]
=> 1
```

普通のハッシュじゃ無理なこと。

[ActiveSupport::HashWithIndifferentAccess](https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html)









<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Ruby on Railsにて時間を10段階で表示する方法

Railsを用いて、例えば8時間30分などを8.5へ変換するにはどうすれば良いか、考えてみた。

# バージョンの確認
Rails：5.1.4
Ruby：ruby 2.4.1p111

# 手順
ヘルパーモジュールに10段階へ変換させるメソッドを組み込み、表示させたいviewファイルに読み込ませる。

# 例
Worktimeというモデルが作成されている。

```ruby:db/schema.rb
create_table "worktimes", force: :cascade do |t|
  t.datetime "work_time"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end
```
ヘルパーにメソッドを定義する。

```ruby:app/helpers/work_times_helper.rb
module WorkTimesHelper
  
  def time_10div(time)
    x = time.hour #例えば、8時間30分の8の値へアクセス。
    y = time.min #例えば、8時間30分の30の値へアクセス。
    y = y/60.to_f #60で割り、to_fメソッドを使用すると、30分→0.5、15分→0.25という値へアクセス出来る。
                  #to_fメソッドを使用しないと小数点以下の値へアクセス出来ないので注意。
    y = y.round(2) #この場合は小数点3桁目を四捨五入している。例)10分→0.17
    sum = x + y #最後に加算する。
    "#{sum}" #8時間30分→8.5へ変換される。
  end
  
end
```

コントローラに

```ruby:app/controllers/work_times_controller.rb
def hoge
@worktime = Worktime.new(work_time: "08:30:00")
end
```

などと定義して、

```ruby:app/views/work_times/hoge.html.erb
<%= time_10div(@worktime.work_time) %>
```
とviewファイルに記載すれば、8.5と表示される。
※routesファイルの編集や時間の設定などは省略。
Scalaで文字列->Enumにできるようにちょっとだけ使いやすくする

scalaでEnum的なことをするときよくこんな感じで実装しますが

```scala
sealed abstract class Color
object Color {
  case object Red   extends Color
  case object Blue  extends Color
  case object Green extends Color
}
```

結構↓みたいな使い方をした場合が多いです。

```scala
// 取ってきたデータ（StringやShortとか）からEnumに変換したい
scala> val red = Color("red")
red: Option[Color] = Some(Red)

// valueを持たせたい
scala> Color.Red.code
res17: String = #FF0000
```

こういう時一個traitを用意してEnumそれを継承するだけで便利になる気がします。

```scala
trait Enum[A <: { def name: String }] {
  val values: List[A]
  def apply(name: String): Option[A] = values.find(_.name == name)
}

sealed abstract class Color(val name: String, val code: String)

object Color extends Enum[Color] {
  case object Red   extends Color("red", "#FF0000")
  case object Blue  extends Color("blue", "#0000FF")
  case object Green extends Color("green", "#008000")

  lazy val values = List(Red, Blue, Green)
}
```

文字列以外も対応したい場合は `EnumValue` を用意して、必要に応じて `extends` した方が一番使いやすい気がします。
([こちら](https://gist.github.com/gakuzzzz/4ad53153e28b3a6e0aa6)に参考しました！）

```scala
trait EnumValue {
  type Value
  val value: Value
}

trait Enum[A <: EnumValue] {
  val values: List[A]
  def apply(value: A#Value): Option[A] = values.find(_.value == value)
}
```

ただし　`values` をいちいち定義して `case object` 全部入れないといけないのが手間かかりますので…
そこはreflection使うとよりいい簡潔にかけると思いますが、また別の機会に試してみます。