OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptで、クリックされた対象が、該当していれば動作する処理

クリックされた対象が、該当していれば動作する処理になります。

どなたかの、参考になりばと思います。

```javascript


    const genre_styles = document.getElementsByClassName("className")[0];
    const target = document.getElementById("IdName");
    let genre_styles_list = genre_styles.querySelectorAll("ndoe");
    const genre_styles__arr = Array.prototype.slice.call(genre_styles_list);
    let i;
    const reg_target = /genre_/;
    const active = "on";

    let needed = (str) => {//必要処理
        let reg = str.className;
        if (reg.match(reg_target)) {
            let n;
            let reg_text = reg.split(" ");
            for (n = 0; reg_len = reg_text.length, n < reg_len; n++) {
                if (reg_text[n].match(reg_target)) {
                    let reg_replace = reg_text[n].replace("genre_", "");
                    let dispelem = target.querySelector(`.${reg_replace}`);
                    prevmenu(dispelem);
                }

            }
        } else {
            return false;
        }

    };

    let prevmenu = (elem) => {//次のページのメニューの出現
        const first_nav = document.querySelector(".className");
        const reverse_elem = elem.querySelector(".className");

        first_nav.classList.add(active);
        elem.classList.add(active);

        reverse_elem.addEventListener("click", function (e) {
            e.preventDefault();
            first_nav.classList.remove(active);
            elem.classList.remove(active);
        }, false);
    }


    for (i = 0; len = genre_styles__arr.length, i < len; i++) {
        genre_styles__arr[i].addEventListener("click", function (e) {
            e.preventDefault();
            needed(this);
        }, false);
    }

}

```
変数名をランダムで決めて誰も追えないソースコードにする

#まえがき

<font color="red" style="font-size:200%">この記事が一番ためにならないと思います。</font>

#方法

evalを使います。
グローバル領域(window)に定義されるので、頑張って探してみてください。

```javascript

let variableName = "";
for (let i = 0; i < 10; i++) {
  // a ~ z で変数名を生成
  // 数字を含む際は先頭に数字が来ないよう注意する
  variableName += String.fromCharCode(0x61 + ~~(Math.random() * 26));
}
eval(`${variableName} = "hello world!";`);

```
javascriptのオブジェクトコピー

# javascriptのオブジェクトコピー

reactでアプリ作ってて，javascriptでオブジェクトをコピーしようと思ったらハマったので記事にしました．


## javascriptは基本参照渡し

javascriptではオブジェクトを代入する時に参照渡ししてしまうのでコピーのつもりで代入すると元の変数も書き換えられてビビります．

## オブジェクトのコピーってどうするの？

上記の問題を解決するために`Object.assign()`という関数を使います．
以下のように記述することでオブジェクトのコピーが出来ます．

```
let obj1 = {value: 'hoge'}
let obj2 = Object.assign({}, obj1);
```

#### 注意点

しかし，上記の関数には落とし穴があります．オブジェクトの中にネストされてオブジェクトが入っている場合は中のオブジェクトは参照渡しになります．

僕の場合は，オブジェクトの中にオブジェクトのリストが入っていました．ネストされたリストの中のオブジェクトを書き換えると，元の変数のオブジェクトも書き換えられてしまうのでおかしいな？って思ってたらやっぱり参照渡しされてました．オブジェクトの構造は以下のようになってます．

```js
// オブジェクトの構造
let targetObject = {
  // オブジェクトの中にオブジェクトのリストが入っている
  person_list = [
    {"name": "tokumaru", "age": 20},
    {"name": "tokutoku", "age": 22}
  ]
}
```


#### 解決方法

僕は，オブジェクトの中のリストをループで回してリスト内のオブジェクトを毎回コピーする感じにしました．
具体的には以下のようなコードになります．

```js
let newObject = {
  person_list = []
}

targetObject.person_list.forEach(function(person, idx) {
  newObject.person_list.push(Object.assign({}, person))
})
```

## まとめ

以上です．javascriptむずいヨ．
もっといい方法があるよって人はコメントよろしくお願いします．
JavaSrcriptで、removeClassメソッドやCSSメソッドを作ってみました

```javascript

CSSメソッド

function add_style_css(element, styleObj) {
    if (typeof styleObj === 'object') {
        let prop = [];
        for (let key in styleObj) {
            prop.push(key + ':' + styleObj[key]);
        }

        let adjust_arr_style = prop.join(';');

        element.setAttribute('style', adjust_arr_style);
    } else {
        throw new Error("css() 2nd arguments must be object.");
    }
}

使い方

add_style_css(element, { p: styleObj});

```

```javascript

removeClassメソッド

    const deletElement = (node, className) => {
        let classNames = className.trim().split(/\s+/);
        let nodeClass = (node.getAttribute('class') || '').trim();
        let nodeClassNames = nodeClass.split(/\s+/);
        let i = nodeClassNames.length;
        //trim() 呼び出し元の文字列の両端から空白を取り除いた新しい文字列。
        while (i--) {
            // 指定したクラスがあれば削除
            if (~classNames.indexOf(nodeClassNames[i])) {
                nodeClassNames.splice(i, 1);
            }
        }

        node.setAttribute('class', nodeClassNames.join(' '));
    };

 deletElement(node, "className");

```
S3の最終更新日時(Last Modified)の罠

S3の最終更新日時(Last Modified)の時間が思っていた時間と違いドキュメントも見つからなかったので、どのタイミングの時間なのか実験ました。
ドキュメントあったら教えてください。

# S3の最終更新日時(Last Modified)とは？
以下のようなS3のWebコンソール画面の最終更新日時の時間や、 `aws cli ls オブジェクト名` で表示されるS3オブジェクトが更新された時間のことです。

<img width="1479" alt="S3_Management_Console.png" src="https://qiita-image-store.s3.amazonaws.com/0/74514/95302e3e-ef4e-0854-f6bd-2cc0ed43cc11.png">

# 予想と結論
最初S3の最終更新日時の時間はS3オブジェクトがPUTされ、**参照できるようになった時間**かと思っていました。
しかし、実験の結果**PUT開始時間**であることがわかりました。

# 実験
まず大きめのファイルを用意します。

```
dd if=/dev/zero of=a.dat bs=1000 count=1000000
```

そして以下のコマンドでs3にファイルをアップロードします

```
date && aws s3 cp a.dat s3://katsuyan_tmp && date
```

以下がその出力結果です。

```
2018年 9月30日 日曜日 17時53分46秒 JST
upload: ./a.dat to s3://katsuyan_tmp/a.dat
2018年 9月30日 日曜日 17時54分02秒 JST
```


そして最後に以下のコマンドで最終更新日時を確認します。

```
$ aws s3 katsuyan_tmp
```

出力結果は以下のようにアップロードを開始した時間と大体同じになっていることがわかります。

```
2018-09-30 17:53:48 1000000000 a.dat
```


念のためS3のWebコンソールからも最終更新日時を確認します。
<img width="1479" alt="S3_Management_Console.png" src="https://qiita-image-store.s3.amazonaws.com/0/74514/95302e3e-ef4e-0854-f6bd-2cc0ed43cc11.png">



# まとめ
S3の最終更新日時(Last Modified)はS3オブジェクトのPUT開始時間みたいなので注意しましょう。
フルスクラッチでnuxtの環境構築していろいろ動かすまでの道のり

## プロジェクトファイルを作成する

```shell
$ mkdir my-app
cd my-app
```

## package.json を作成する

つくったプロジェクトファイル配下に、下記ファイルを作成する。

```json:package.json
{
  "name": "my-app",
  "scripts": {
    "dev": "nuxt"
  }
}
```

## nuxtのパッケージインストールする

```shell
$ npm install --save nuxt
```

nuxtのいろんなパッケージがインストールされます。package.jsonにもnuxtのバージョンなどが追記されます。

```shell
$ cat package.json
{
  "name": "cto.ac",
  "scripts": {
    "dev": "nuxt"
  },
  "dependencies": {
    "nuxt": "^2.1.0"
  }
}
```

## シンプルなvueファイルを作成してみる

myapp/pages/index.vueを作成します。

```shell
$ mkdir pages
$ touch pages/index.vue
```

```vue:index.vue
<template>
  <h1>my-app</h1>
</template>
```

## ブラウザで確認する

```shell
$ npm run dev
```

http://127.0.0.1:3000/ にアクセスすると表示されます。



## vueファイルを2つつくって遷移させてみる

index.vueを修正して、さらにこのindex.vueをコピーしてabout.vueファイルを作成します。

```vue:pages/index.vue
<template>
  <div>
    <h1>{{ title }}</h1>
    <nuxt-link to="/about">about</nuxt-link>
  </div>
</template>

<script>
export default {
  asyncData() {
    return {
      title: 'My app'
    }
  }
}
</script>
```

```vue:pages/about.vue
<template>
  <div>
  <h1>{{ title }}</h1>
  <nuxt-link to="/">top</nuxt-link>
  </div>
</template>

<script>
export default {
  asyncData() {
    return {
      title: 'about'
    }
  }
}
</script>
```

これで、 http://127.0.0.1:3000/  と http://127.0.0.1:3000/about を行き来できます。


## nuxt.config.jsファイルは必要かどうか？

[設定 - Nuxt.js](https://ja.nuxtjs.org/guide/configuration/)によれば、

> Nuxt.js ではデフォルトの設定でほとんどのユースケースをカバーしていますが nuxt.config.js で設定を上書きすることができます。

とあります。デフォルトの設定を上書きしたり追記するときに作ればいいでしょう。
外部向け用に使うサンプル用アドレスやドメインの話

WebアプリやUnityでのネット利用をする際、何らかの形で「表には出したくないけどなんらかのアドレスやURLが必要」な場合があると思います。例えば…

* テスト用に使うE-Mailアドレスが必要(送ったというエビデンスもほしい）
* コードを例にプレゼンすることになった
* 外部の会社とコードを共有することになった
* 体裁上、うちの会社とあそこの会社との縁はあまり公にしたくないごにょごにょ

適当な名前で作ると、実は会社や組織が使っているドメインで、海外の会社だと「てめーのテストメールせいで損害が出た訴訟」なんていうぶっ飛んだ話も可能性を捨てきれず…ムズカシイネ

実は、RFCでテスト用のドメインやIPアドレスが存在しているので、これを活用してガシガシテストしましょうという話です[^1]。

テストやサンプルに堂々使えるドメインは、

* example.com
* example.net
* *.test
* EXAMPLE.JP

など。IPアドレスでは

* 192.0.2.0/24

などです。　

この話は、「打つか投げるか」さんのブログ記事が詳しいので、こちらをご参照くださいませ。

[打つか投げるか test.comやaaa.comをテストデータに使うのはやめましょうという話](https://blog.ko31.com/201304/sample-domain-example/)

[^1]: あ、もちろん実際に通信して動作確認したいときは別ですよ！
WindowsServer Terminal Service上からの印刷が遅い件

Terminal Service上のWinFormsプログラムで印刷をかけるとクライアントで実行する数倍遅いという現象に対する調査

## 前提
プログラム上でプリンタ出力する際
1. 出力先プリンタや用紙サイズ、両面印刷、カラー印刷などの印刷オプションは別途選択したものを保存している
2. 印刷時に上で保存した設定を使用する。
3. RemoteDesktop Easy Printは基本的に使用しない。(一時的に使用する場合もあるがその場合のパフォーマンスは考慮しない)
4. ローカル環境で実行した場合印刷は1秒ほどで完了する。サーバー上では十数秒かかることも。


## 計測

用紙サイズをユーザー定義サイズとして高さ、幅を設定するとそれだけで2秒ほどかかっているようだ。

[以下調査中]


## 資料

- [>よくあるお問い合わせ\(FAQ\) \| OBCNetサービス](https://www.obcnet.jp/?module=Faq&action=Detail&WebFaqID=4132&from=list&already_disp=1)
- [リダイレクトプリンタを使って印刷すると、印刷処理に時間がかかります。](https://social.msdn.microsoft.com/Forums/ja-JP/afb9dcdd-8529-42d1-a57b-87151f061bd8/12522124801245212524124631248812503125221253112479124342035112?forum=vbgeneralja)
- [Remote Desktop Easy Print runs slowly in Windows Server 2012 R2](https://support.microsoft.com/en-us/help/3073630/remote-desktop-easy-print-runs-slowly-in-windows-server-2012-r2)
- [Easy print spooler file size and TOO SLOW](https://social.technet.microsoft.com/Forums/windowsserver/en-US/ca52f0c6-daaf-4c10-b9a8-0395b12b7e0a/easy-print-spooler-file-size-and-too-slow?forum=winserverTS)
- [Slow printing with Easy Print](https://social.technet.microsoft.com/Forums/en-US/c63446aa-f242-41a3-ad20-20628bdf9f41/slow-printing-with-easy-print?forum=winserverTS)
- [Printing over Remote Desktop Services \(TS\) is very slow on 2K8 R2 \- Microsoft Remote Desktop Services \- Spiceworks](https://community.spiceworks.com/topic/465082-printing-over-remote-desktop-services-ts-is-very-slow-on-2k8-r2)
- [Setting Windows Server 2008 Terminal Services Display Data Prioritization \- Petri](https://www.petri.com/setting-windows-server-2008-terminal-services-display-data-prioritization)
- [performance \- Find out the bottleneck for windows remote desktop server \(Terminal server\) \- Server Fault](https://serverfault.com/questions/332622/find-out-the-bottleneck-for-windows-remote-desktop-server-terminal-server)
- [AR7 very slow with windows server 2012 reemote app \| ActiveReports v7\+ \| ActiveReports \| GrapeCity Forums](https://www.grapecity.com/en/forums/ar-dev/ar7-very-slow-with-windows)
- [Remote desktop protocols A comparison of Spice, NX and VNC](chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html)
Google Cloud Functions(Python)からCloud Buildでビルド実行してみる

## 概要

Google Cloud Next ’18で発表されたCI/CDサービスのGoogle Cloud Buildですが、現状、トリガーは以下のgitリポジトリへのpushのみとなります。(2018/10/01時点)

- Cloud Source Repositories
- Bitbucket
- GitHub

ソースとしてCloud Storageにある圧縮ファイル(zip、tar.gz)を指定することができるので、Cloud Storageとも連携できるよね？と思ったので試してみました。

Google Cloud Buildについては以下をご参考ください。

Google Cloud Build
https://cloud.google.com/cloud-build/?hl=ja

Google Cloud Buildとは一体何者なのか
https://swet.dena.com/entry/2018/08/20/170836


## 実装

Cloud Functionsにビルドするソースは以下のような感じです。

Google API Clientが利用できるように```requirements.txt``` に含めておきます。

```txt:requirements.txt
google-api-python-client
```

Cloud Build APIでビルドリクエストの送信をする場合、JSONまたはYAML形式でパラメータを設定する必要があります。今回はJSON形式を利用しています。

詳しくは下記をご参考ください。

REST Resource: projects.builds
https://cloud.google.com/cloud-build/docs/api/reference/rest/v1/projects.builds

今回はJSON形式で、```source.storageSource``` でCloud Storageから読み込むソースを指定して、```steps``` で、```ls -l``` を指定して、ソースが解凍されて展開されたかを確認しています。

PythonのCloud Build API Clientについては下記ページからドキュメントやAPIのお試しができるAPIs Explorerへのリンクが用意されていました。

Cloud Build API Client Library for Python
https://developers.google.com/api-client-library/python/apis/cloudbuild/v1

```python:main.py
from googleapiclient import discovery
import json

def cloud_build_create_test(event, context):
  requestBody = '''
{
  "source": {
    "storageSource": {
      "bucket": "任意のバケット名",
      "object": "任意のファイル名(zip か tar.gz)"
    }
  },
  "steps": [
    {
      "name": "gcr.io/cloud-builders/docker",
      "entrypoint": "bash",
      "args": [
        "-c",
        "ls -l"
      ]
    }
  ]
}
  '''
  
  cloudBuild = discovery.build('cloudbuild', 'v1')
  request = cloudBuild.projects().builds().create(
    body=json.load(requestBody), projectId='[GCPのプロジェクトID]')
  response = request.execute()

```

とりあえず、API叩けば、Cloud Build実行できることが確認できました。
ちょっとしたバッチ処理なんかであれば、Cloud Buildを利用するのもありかもしれません。

## 参考

Google Cloud Build
https://cloud.google.com/cloud-build/?hl=ja

Google Cloud Buildとは一体何者なのか
https://swet.dena.com/entry/2018/08/20/170836

REST Resource: projects.builds
https://cloud.google.com/cloud-build/docs/api/reference/rest/v1/projects.builds

Cloud Build API Client Library for Python
https://developers.google.com/api-client-library/python/apis/cloudbuild/v1
lambdaからslackに投稿(KMSでencryption)

# 目標

lambdaからslackに投稿する

# 手順

## 1. slackのincoming webhooksを作成 -> URLをゲット

slackのapp manage ページに行ってincoming webhooksを作成し、どこのChannelに飛ばすかを設定する。


## 2. 必要なLibraryをローカルでインストールしてzipにする

https://qiita.com/Hironsan/items/0eb5578f3321c72637b4
今回は `slackweb` を使用(https://qiita.com/satoshi03/items/14495bf431b1932cb90b)


```python
import slackweb
slack = slackweb.Slack(url="<コピーしたURL>")
slack.notify(text="This is a test.")
```


## 3. Lambdaの設定画面でzipをUpload 

https://qiita.com/Hironsan/items/0eb5578f3321c72637b4

## 4. SLACK_URLに先ほどのURLを登録＋コード内では、以下のようにEnvを読み込む

```
   import os
   print os.environ["SLACK_URL"]
```

## 5. 試しに送ってみる

Lambdaをトリガーして送る。
失敗したときは、Cloudwatchのlogsからエラーを確認


## 6. 環境変数の暗号化

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/env_variables.html#env_encrypt
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/tutorial-env_console.html

SlackのURLを暗号化しておく

![image.png](https://qiita-image-store.s3.amazonaws.com/0/7059/285720c5-941c-6219-9e1a-3dab09deb311.png)

## 7. KMSを作成していない場合は、IAMから作成

作成するときに、policyでlambdaに使用権限を与えておけば良い

## 8. Enable helpers for encryption in transitにチェックを入れる

チェックを入れるとKMSを選択する部分になるので、作成したKMSを選択し、Encryptすると環境変数が見れなくなる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/7059/28e54730-23d4-c6f8-5f6d-1c2f301bc984.png)
Slackの"ワークスペースのカスタマイズ>Slackbot"を設定して数分でランチボットを作る

Slackの管理画面の[ワークスペースのカスタマイズ > Slackbot](https://allin.slack.com/customize/slackbot)で、

<img width="988" alt="slackbot" src="https://qiita-image-store.s3.amazonaws.com/0/62293/edfb4006-f8bd-0fa3-5aa3-b4929109d3b1.png">

例えば「ランチどうする？」に対して、お店の名前を改行区切りで入れておくだけで、ランダムに選ばれます。

<img width="391" alt="slack" src="https://qiita-image-store.s3.amazonaws.com/0/62293/049dbf8a-0308-564e-25f2-aec13cec0995.png">

こんな風に。
Python3: pdfminer で PDF から文字を抽出

次の記事を参考にしました。
[【Python】pdfから文字を抽出。pdfminer.sixの使い方](https://www.tech-tech.xyz/archives/python-pdf.html)

```py:pdf_parse.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	pdf_parse.py
#
#						Oct/02/2018
#
# ------------------------------------------------------------------
import	sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
file_pdf = sys.argv[1]
file_text = sys.argv[2]
sys.stderr.write(file_pdf + "\n")
sys.stderr.write(file_text + "\n")
#
rsrcmgr = PDFResourceManager()
codec = 'utf-8'
params = LAParams()
with open(file_text, "wb") as output:
	device = TextConverter(rsrcmgr, output, codec=codec, laparams=params)
	with open(file_pdf, 'rb') as input:
		interpreter = PDFPageInterpreter(rsrcmgr, device)
		for page in PDFPage.get_pages(input):
			interpreter.process_page(page)
	device.close()
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行方法

```bash
./pdf_parse.py cities.pdf result.txt
```

Arch Linux でのライブラリーのインストール方法

>```bash
yay -S python-pdfminer.six
```

Ubuntu でのライブラリーのインストール方法

>```bash
sudo apt install python3-pdfminer
```
lambdaの設定をsdkから更新する際の注意点

#lambdaの設定をsdkから更新する際の注意点

## やりたかったこと
デプロイ済みの複数のlambdaに設定していた環境変数の値を、sdkを使って一気に更新したかった

## どうなった？
設定してあった他の環境変数が消えてしまった・・・

## 結局のところ？
一度、設定情報を取得して、一部だけを更新したもので設定更新した。

## 説明
### デプロイ済みのlambdaの設定情報をjsonで表すと以下の通り
```
{
    FunctionName: 'service-stage-function1',
    Environment: {
        Variables: {
            env1: 'ume',
            env2: 'matsu',
            env3: 'take',
        },
    },
}
```

## 失敗例（更新したい環境変数だけを渡した場合）
```
'use strict';

const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();

const params = {
  FunctionName: 'service-stage-function1',
  Environment: {
    Variables: {
        env2: 'kame'
    },
  },
};

consr promise = lambda.updateFunctionConfiguration(params).promise();
promise.then((res) => {
    console.info(res);
});

// 出力　res
{
  FunctionName: 'service-stage-function1',
  Environment: {
    Variables: {
        env2: 'kame'
    },
  },
}
```

何気に上手くいったかもと思って、AWSマネジメントコンソールから該当のlambdaファンクションを確認すると、他の環境変数が消えてしまっていた・・・

##　成功例（一度、設定を取得して、更新したい環境変数の値だけを変えて渡す）
```
'use strict';

const _ = require('lodash');
const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();

const params = {
  FunctionName: 'service-stage-function1',
};

// 現在設定されている内容を取得
const promise = lambda.getFunctionConfiguration(params).promise()
.then((config) => {
    // 現在設定されている内容をコピーしないと、新しいenvだけになってしまう
    const variables = _.clone(config.Environment.Variables);
    variables.env2 = 'kame';
    const update = {
      FunctionName: functionName,
      Environment: {
        Variables: variables,
      },
    };
    return lambda.updateFunctionConfiguration(update).promise();
});
promise.then((res) => {
    console.info(res);
});

// 出力　res
{
  FunctionName: 'service-stage-function1',
  Environment: {
    Variables: {
        env1: 'ume'
        env2: 'kame'
        env3: 'take'
    },
  },
}
```

# 追記 2018/10/29
sdkで、大量に更新リクエストを投げると、TooManyRequestsExceptionとかLimitExceededExceptionとかリミット系例外が発生する事があります。

リトライしてタイミングをずらしてあげると、完了させられます。

デフォルトのオプションでmaxRetriesやretryDelayOptionsがありましたので
情報として載せて起きます。

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#constructor-property

こんな感じ

```
const AWS = require('aws-sdk');
const lambda = new AWS.Lambda({
  maxRetries: 10,
  retryDelayOptions: {
    base: 1000,
  },
});
```
CSS による「CSS ドーナツグラフの作り方」説明動画

# これは何
CSS だけを使って説明動画を作ってみたよ。というかできてしまった。

# デザイナーに優しい JS フリーな説明動画
JS を使わず、HTML も最小限だけにして、CSS である程度見栄えのするドーナツグラフを作ってみたんだけど、その説明動画もその流れで作っていたら、結局 JS を使わず、HTML も変更なしでできてしまった、という。

<p data-height="265" data-theme-id="0" data-slug-hash="YJyymY" data-default-tab="css,result" data-user="unau-takeyuki" data-pen-title="Instruction Movie with pure CSS; Donut Chart as an Example" class="codepen">See the Pen <a href="https://codepen.io/unau-takeyuki/pen/YJyymY/">Instruction Movie with pure CSS; Donut Chart as an Example</a> by Takeyuki Kojima (<a href="https://codepen.io/unau-takeyuki">@unau-takeyuki</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


Chrome 69 でしか試してないので、他のブラウザでどうなるのかはわかりません。ドーナツグラフだけなら、ベンダープレフィックスを適宜追加するなどして、多くの環境できちんと動くと思います。説明動画の方は、animation の keyframes の中で content 属性を使っている (W3C の仕様では対象外) ので、動く環境は少ないかもです。

「JS はどうも ...」というデザイナーに優しく、GPU がうまくやってるくれるかもしれない CSS animation だけ使っているので CPU にも優しい説明動画をお探しの方はどぞ。

# 参考
- [Animating the \`content\` Property](https://css-tricks.com/animating-the-content-property/)
- [ドーナツグラフを円アニメーションで表示する：CSS3\/HTML5\/JS](http://jsdo.it/Rio.Yanagi/7gU4)
GoogleChrome — 複数アカウントでもブックマークをリアルタイム共有できる拡張 TeamSync Bookmarks 


## 問題

- 複数環境でブックマークを共有したいが、Chromeに使うGoogleアカウントは別々にしておきたい
- 全部ではなく一部のブックマークだけを共有したい

## 解決

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/72aa1577-fb66-e4fa-f9d1-d6fd1e6d0ed6.png)

https://chrome.google.com/webstore/detail/teamsync-bookmarks/bcopfejjlalhckdkmofjciemgnjkffhj 


## 使い方

グループを作る

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/5b36e4c5-02d1-51a9-2054-e4caf1bdfc98.png)

自動的にChromeにブックマークフォルダが追加されるので、何かブックマークを置いてみる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/c68a693d-2f70-9648-15ff-ef3899be0d38.png)

他環境のGoogleChromeでも、TeamSync Bookmarks にログインして同じグループに参加すれば、リアルタイムでブックマークが同期される

## 備考

ブックマークフォルダ名を変えてしまうと、うまく動かないようだった

この仕組だと当たり前だが、グループ名は全ユーザーでグローバルなので、重複させられない様子

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/58e29379-ee18-501b-5849-f45ee041d84f.png)


## 環境

- Mac OS X Sierra
- Google Chrome Version 69.0.3497.100 (Official Build) (64-bit)








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
php-master-changes 2018-10-01

今日はテストの微修正、コンパイル時警告の除去、PDO_OCI での PDOStatement::getColumnMeta() サポート、.gitignore の改善、opcache の最適化っぽいの、phpdbg のバージョンを php 処理系本体にあわせる修正があった！

# 2018-10-01
## nikic: Fix test
- https://github.com/php/php-src/commit/ab2120e4e563104da06dec7a37945d86b28b1727
- テストでディレクトリへの symlink を何故か .phpt として作っていたのを修正

## nikic: Fixed bug [#75479](https://bugs.php.net/bug.php?id=75479)
- https://github.com/php/php-src/commit/db80e0e2ad016cbff55cc6e1311b7ffe9ad7101e
- [7.1~]
- sapi/apache2handler について、ZEND_SIGNAL 有効で出ていたコンパイル時の警告を修正
- zend_signal_init() は引数をとらないが、[ap_hook_child_init()](https://httpd.apache.org/docs/2.4/developer/modguide.html#hook_others) に渡すのは [2 引数の関数ポインタ](http://dsas.blog.klab.org/archives/50626863.html#ap_hook_child_init)

## remicollet: Fixed bug [#76908](https://bugs.php.net/bug.php?id=76908) 	PDO_OCI getColumnMeta() not implemented
- https://github.com/php/php-src/commit/0ae5f82135e68251b2480a41a47ead4adba51eb9
- ext/oci_pdo で [PDOStatement::getColumnMeta()](http://php.net/manual/en/pdostatement.getcolumnmeta.php) が実装されていなかったので実装

## remicollet: NEWS and UPGRADING
- https://github.com/php/php-src/commit/3d5fe90e7e0ebcf3b5d1405425e505668f4a1538
- ↑を NEWS と UPGRADING に追記

## KalleZ: Bug > Feature Request
- https://github.com/php/php-src/commit/e23a9d6a5c7daaf5dd070867c319149d3fff8666
- ↑ がバグ修正として NEWS へ書かれていたのを修正

## KalleZ: Update .gitignore to include the Windows deplister program (win32/build/deplister.c)
- https://github.com/php/php-src/commit/a698dcd24a4051cd28336bb1e28db1e1d6c52e79
- Windows 用のビルドツール deplister のビルドファイルを除外するよう .gitignore に追記

## KalleZ: Fix the deplister rule to not ignore the .c file (Anatol)
- https://github.com/php/php-src/commit/4fc5833b3ebda3078911808d296e62d5baa9bf52
- ↑でコード本体まで除外されてしまっていたので明示的に .obj と .exe を指定して除外するよう修正

## dstogov: Get rid of accel_deactivate() calback
- https://github.com/php/php-src/commit/c25e7439ae3917be171ae1ba55f78013f92c2e14
- ext/opcache で accel_deactivate() のコールバックを削除

## petk: Bump phpdbg version to PHP_VERSION
- https://github.com/php/php-src/commit/a3760badbea9569c6cf0cc7eda794f5b0cea2270
- sapi/phpdbg のバージョンが PHP 本体と元々別に管理されていたが、PHP 本体とあわせるよう修正

## dstogov: Turn accel_activate into module callback.
- https://github.com/php/php-src/commit/34a491d1ed5b3e593572b45542fd394b308e91a9
- ext/opcache で accel_activate() を [zend_extension の activate から module の RINIT へ](http://www.phpinternalsbook.com/php7/extensions_design/zend_extensions.html#zend-extensions-lifetime-hooks)移動
- タイミングを少し遅らせているとか？触るデータのその後のキャッシュへの乗り具合にでも影響するのだろうか……毎度のことながら Dmitry 御大のコミット解説ないと意図がよくわからずやで
AlibabaCloudのサポートを利用してみる

# はじめに
AlibabaCloudのサポートを利用してみます。

# 問い合わせ内容
[ApsaraDB for Redisのバックアップ/リストアをやってみる](https://qiita.com/wa-ta-ru/items/4a6670c4d1777589e5c9)
のクラスタのバックアップからのリストアについてです。

# コンソールからチケットを起票します。

![6f7eb229.png](https://qiita-image-store.s3.amazonaws.com/0/241104/f1c9f1a2-41d3-1310-5a63-a01c3aa8ed30.png)

![2bc9ea26.png](https://qiita-image-store.s3.amazonaws.com/0/241104/a230944b-105b-7a11-44cb-d88518bd1351.png)

![ca182fef.png](https://qiita-image-store.s3.amazonaws.com/0/241104/704d0986-3c49-d895-0754-c5fb061bf13a.png)

![d56f7ba3.png](https://qiita-image-store.s3.amazonaws.com/0/241104/caba1c44-6a8e-d820-59b7-92857e09f44e.png)

![6067be52.png](https://qiita-image-store.s3.amazonaws.com/0/241104/a9e9077f-ab8e-b07d-336c-0cbc17ef4017.png)

# サポート
## 一次受付の速度がとても早い

2018-10-02 06:17:19
↓
2018-10-02 06:17:55

自分もサポートしてましたが、これはとても早い。

## 優先度の調整
![16511fe2.png](https://qiita-image-store.s3.amazonaws.com/0/241104/6fca0cc7-9ed4-16a3-92a9-61d1f8fe2e9d.png)

**なぜこのようなことをするか？**

「困ってる」かどうかは
問い合わせのテキストで判断はできません。

- 本番利用して困ってる。どうにかしてほしいです。
- 検証利用したけど、できないよ？

といろいろな意味を含んでしまいます。
そこで、
**私は検証利用だから、ゆっくりでも問題ないですよ**
と伝えます。

本番利用でトラブルがたくさんの日も少ない日もあります。
サポートは人員リソースです。

どれだけ人数がいるかはわかりませんが
数十人とかで常時対応できる体制としても、限界があります。
それを超える予想外の出来事も考えられます。

調整できるようにすることは
サポートに依頼する者として
適切なことになります。

決して
**困ってるんだ。なんとかしてくれ**
はやめるべき内容です。

では、サポートの結果がでましたら追記します。
お待ちください。

# 追記
すんごい簡単なreveal.jsのDockerイメージ作った

今更感あるけどすんごい簡単に使えるreveal.jsのDockerイメージ作ったよ

## すごいけど・・・

reveal.jsは素晴らしいプレゼンテーション作成ツール。
Markdownや簡単なHTMLできれいなスライドが作れるというものです。

シンプルにやるなら、index.htmlに全スライドを直書き。  
長くなってくると嫌になってきます。  
そこはちゃんと考慮されてて、スライドを別ファイルに定義して、index.htmlから参照するという方式もサポートされています。

けど分割しても、index.htmlにそのファイルパスを書かないといけません。
index.html書きたくない！Markdownだけ書きたい！

## 作った

Markdownだけ書いてればプレゼンテーションが作成できるDockerイメージ作りました。

### 必要なもの

- Docker
- docker-compose

※この例では簡単のためdocker-composeを使っていますが、docker単体でもOKです。

### 使い方

#### 1. docker-compose.yml作成

こんな感じでdocker-compose.ymlを作ります。コピペでOK

```yaml
version: "2"

services:
  revealjs:
    image: uphy/reveal.js:3.7.0
    ports:
      - "8000:8000"
      - "35729:35729"
    volumes:
      - "./data:/reveal.js/data"
```

#### 2. デモデータ作成(省略可)

reveal.jsの設定等を含む設定ファイル、デモスライドを作成します。

```console
$ docker-compose run --rm revealjs init
```

データは`./data`に格納されています。  
Markdownの他、htmlでもスライドが書けます。

書き方については、[hakimel/reveal.js](https://github.com/hakimel/reveal.js/#instructions)を参照。
こんな感じに<section>タグだけ書けば作れます。

```html
<section>
  <h2>foo</h2>
</section>
```

#### 3. reveal.jsサーバー起動

```console
$ docker-compose up -d
```

http://localhost:8000
にアクセスすると、プレゼンが表示されると思います。

<img width="256" alt="Screen Shot 2018-10-02 at 7.35.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/39261/0fdce54b-ab05-5a82-1b52-1638a92e3d72.png">

#### 4. スライド編集

お好きなエディタで、作られた`./data`ディレクトリのスライドファイルを編集してください。
サーバーがファイルを監視しているので、編集すると自動的にブラウザが更新されます。

#### 5. 新規スライドページ追加

同様に、`./data`ディレクトリ以下にファイルを作成してください。
デフォルトでは`./data`ディレクトリ以下のすべてのhtml/mdファイルが対象となり、昇順にページが構成されます。

※config.ymlの`slides`を変更することで、指定された順にすることもできます。

#### 6. お片付け

使ったコンテナ削除しておきます。

```console
$ docker-compose down
```

`./data`ディレクトリについては、`docker-compose.yml`で永続化指定しているため、残ります。
`reveal.js`直で使うといらないファイルがプレゼンテーションごとにたくさん作られますけどコンテナなら必要なデータだけが残せますね！

## 実装について

reveal.jsに合わせてnode.js書くのがいいんだろうけど、Grunt全く分からないのでやめました。
reveal.jsとは別プロセスで、データディレクトリ(`/reveal.js/data`)を監視し、更新があったら`index.html`を再生成するという荒業をGoでやってます。Goはこういうのさくっと書けて素敵。

## 参考

Docker イメージ: https://hub.docker.com/r/uphy/reveal.js/
ソース: https://github.com/uphy/revealjs-docker
ApsaraDB for Redisのバックアップ/リストアをやってみる

# はじめに
ApsaraDB for Redisのバックアップ/リストアをやってみようと思います。
[ApsaraDB for Memcacheをバックアップから復旧（リストア）してみる](https://qiita.com/wa-ta-ru/items/192b380e470b8d3d7481)
と同じ内容になりそうなので書こうか悩んだのですが
[ApsaraDB for Redisをクラスタへアップグレードしてみる](https://qiita.com/wa-ta-ru/items/0203cf548506fefccacb)
での、クラスタ作成時にそれぞれのノードのバックアップが作成されてました。

![73f1c231.png](https://qiita-image-store.s3.amazonaws.com/0/241104/27a4f50a-9934-46dd-b234-aab5bcceb5ba.png)

バックアップの話は運用設計と一緒に別の機会にします。

# バックアップ/リストアを実行してみる

![c2a48285.png](https://qiita-image-store.s3.amazonaws.com/0/241104/8e7a19e3-060a-e186-a11f-21340a9a7bfb.png)

![b2edc1c1.png](https://qiita-image-store.s3.amazonaws.com/0/241104/fa305c23-4cc9-4a98-65af-92881e2f077b.png)

おや、できないですね。
r-XXXXXX-db-0かなとおも思ったのですが
難しい。
`The request processing has failed due to some unknown error.`
ですか。。。

# ドキュメントを確認してみます
[バックアップとリカバリ - ユーザガイド| Alibaba Cloud ドキュメントセンター](https://jp.alibabacloud.com/help/doc-detail/43886.htm?spm=a21mg.l28256.b99.41.6a40c633aCJJqn)

[エラーコード一覧 - よくある質問| Alibaba Cloud ドキュメントセンター](https://jp.alibabacloud.com/help/doc-detail/43906.htm)
を見ますと

|エラーコード|詳細|HTTP|ステータスコード|意味|解決策|
|InternalError|The request processing has failed due to some unknown error, exception, or failure.|500|内部エラーが発生しています。|もう一度お試しください。|

# まとめ
ふむ。内部エラーのようですね。どうにもなりません。。。
サポートに問い合わせしてみます。
結果はまた別の記事でお伝えしたいと思います。
QGISでラインをポイントに変換してｘｙ座標を取り出す

ニーズがあるかどうかわかりませんが、ラインデータをポイントに変換してxy座標を取り出すという作業をする機会があったのでやり方をメモ。

## ラインの頂点を抽出する

ベクタ→ジオメトリツール→頂点の抽出

![01.png](https://qiita-image-store.s3.amazonaws.com/0/60438/ad53c222-f92a-1e4e-4e98-8a50400ab4f4.png)

入力レイヤにラインレイヤを指定します。
![02.png](https://qiita-image-store.s3.amazonaws.com/0/60438/086efc42-4a0a-a975-6a32-3a7664881e47.png)

ラインの頂点にポイントが作成される
![10.png](https://qiita-image-store.s3.amazonaws.com/0/60438/67717b6c-5e1f-0317-467e-5256020344be.png)


## 出力すべきCRSに変換

最初から出力するCRSで作業している場合は良いのですが、今回はwgs84に出力したかったので変換します。

「頂点」レイヤを右クリック→エクスポート→地物の保存

![03.png](https://qiita-image-store.s3.amazonaws.com/0/60438/6933c698-e43e-3816-f95e-e44bb68c4d36.png)

CRSにWGS84を指定しました。保存形式はSpatialiteにしましたが、シェープファイルでも問題ありません。

![05.png](https://qiita-image-store.s3.amazonaws.com/0/60438/7143b1ed-b4f2-9aed-c25c-4382d4ed9ab0.png)

## フィールド計算機で座標を取得する

「フィールド計算機」でX、Y座標を取得します。
- 「新しフィールドを作る」にチェック
- 「出力フィールド名」は「lat」
- 「出力フィールドタイプ」→「小数点付き数値（real）」
- 「出力フィールド長」→m単位ぐらいまで出力したいなら「7」以上
- 座標を取り出す式は「$x」
![05.png](https://qiita-image-store.s3.amazonaws.com/0/60438/57a4107d-fa62-b330-949f-739e887bca45.png)

同様にY座標も計算します。
![06.png](https://qiita-image-store.s3.amazonaws.com/0/60438/1618d7e9-a6bc-3916-39ea-e9ff38f97e64.png)

新たに緯度と経度が出力された「lat」フィールドと「lon」フィールドが作成されました。
![07.png](https://qiita-image-store.s3.amazonaws.com/0/60438/72027e9e-45d9-f683-81b0-28930d080f75.png)

## CSV形式で出力する

- ポイントレイヤを右クリック
- 「エクスポート」→「地物の保存」
![08.png](https://qiita-image-store.s3.amazonaws.com/0/60438/49ace412-32a7-546e-8f9d-c47ed40fefc0.png)

- 「形式」→「カンマで区切られた値[CSV]」
- 「ファイル名」を適当につける→「Takesiro_Track」
- 「CRS」はデフォルトで
![09.png](https://qiita-image-store.s3.amazonaws.com/0/60438/6af86e5d-8d2c-7ea7-2656-88fd799aa343.png)

出力ファイル
![12.png](https://qiita-image-store.s3.amazonaws.com/0/60438/a4a5190c-9289-a920-6412-353b589ab721.png)


最終的にはこの形で利用します。
![11.png](https://qiita-image-store.s3.amazonaws.com/0/60438/f370a35d-48d2-c560-9462-40980d6012e1.png)

leaflet.jsで動く松浦武四郎マップ。赤色のルートがポイントに変換したラインデータ。Rのsfパッケージで読み込んでleafletパッケージで吐き出すほうが簡単でしたね・・・
![13.png](https://qiita-image-store.s3.amazonaws.com/0/60438/93595746-eafe-93e8-1f3c-78f2ac39726b.png)
ZEAM開発ログ v.0.4.14.2 Elixir / NIF 間で BigNum をやりとりする (Elixir での使用例)

ZACKYこと山崎進です。

Elixir/NIF間でBigNumをやりとりするの3回目は，具体的な使用例を説明したいと思います。

[「ZEAM開発ログ 目次」はこちら](https://qiita.com/zacky1972/items/70593ab2b70d192813df)

# コード例

型多相かつ型安全なNIFで紹介したコード例を一部改変します。

```elixir
  def asm_1(a, b) do
    OK.try do
      result <- case {a, b} do
        {a, b} when is_int64(a)   and is_int64(b)   -> asm_1_nif_ii(a, b)
        {a, b} when is_uint64(a)  and is_uint64(b)  -> asm_1_nif_uu(a, b)
        {a, b} when is_integer(a) and is_integer(b) -> asm_1_nif_bb(Asm.BigNum.from_int(a), Asm.BigNum.from_int(b))

        {a, b} when is_int64(a)   and is_float(b)   -> asm_1_nif_if(a, b)
        {a, b} when is_uint64(a)  and is_float(b)   -> asm_1_nif_uf(a, b)
        {a, b} when is_integer(a) and is_float(b)   -> asm_1_nif_bf(Asm.BigNum.from_int(a), b)

        {a, b} when is_float(a)   and is_int64(b)   -> asm_1_nif_fi(a, b)
        {a, b} when is_float(a)   and is_uint64(b)  -> asm_1_nif_fu(a, b)
        {a, b} when is_float(a)   and is_integer(b) -> asm_1_nif_fb(a, Asm.BigNum.from_int(b))

        {a, b} when is_float(a)   and is_float(b)   -> asm_1_nif_ff(a, b)
        _ -> {:error, :arithmetic_error}
      end
    after
      case result do
      	x when is_number(x) -> x
      	x when is_tuple(x)  -> Asm.BigNum.to_int(x)
      end
    rescue
      :arithmetic_error -> raise ArithmeticError, message: "bad argument in arithmetic expression"
    end
  end
```

```c
static
ERL_NIF_TERM asm_1_nif_bb(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
  unsigned a_neg, b_neg;
  VECTOR *a_v, *b_v;
  if(__builtin_expect((enif_get_big_num(env, argv[0], &a_neg, &a_v) == 0), 0)) {
    return arithmetic_error;
  }
  if(__builtin_expect((enif_get_big_num(env, argv[1], &b_neg, &b_v) == 0), 0)) {
    return arithmetic_error;
  }

  ERL_NIF_TERM result = enif_make_big_num(env, a_neg, a_v);

  enif_free(a_v->value);
  enif_free(a_v);
  enif_free(b_v->value);
  enif_free(b_v);

  return enif_make_tuple2(env, ok_atom, result);
}
```

`asm_1_nif_bf`，`asm_1_nif_fb` も同様に実装します。

次のようなコードを走らせてみます。

```elixir
iex> IO.puts "#{Asm.max_uint + 1} + 1 = #{asm_1(Asm.max_uint + 1, 1)}"
18446744073709551616 + 1 = 18446744073709551616
:ok
```

加算はまだ実装していないので，計算結果としては合っていませんが，BigNum を NIF で送受信できていることがわかります。

BigNum の加算や浮動小数点数への変換の実装については，C言語で書くのは面倒なので，言語処理系 micro Elixir / ZEAM の実装が進んでからに先送りしたいと思います。
ApsaraDB for Redisをクラスタへアップグレードしてみる

# はじめに
[ApsaraDB for Memcacheのアップグレード/ダウングレードを試してみる](https://qiita.com/wa-ta-ru/items/d154f28edc9ecdb7aff8)
と同じように、インスタンスのアップグレードをやってみます。今回は、標準の構成からクラスタもやってみます。

# コンソールから変更してみます

![326b99bb.png](https://qiita-image-store.s3.amazonaws.com/0/241104/0abf407b-d1c8-fafb-23b9-ca7659cbda14.png)

![09a36aa9.png](https://qiita-image-store.s3.amazonaws.com/0/241104/2a432a37-3675-2e76-f02f-e0b8f78f994a.png)

![5a95372c.png](https://qiita-image-store.s3.amazonaws.com/0/241104/5949df9b-0836-8925-e222-6e415c0b481b.png)

## 変更前の情報
```shell
[root@poc3 ~]# redis-cli -h r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> info
# Server
redis_version:2.8.19
redis_git_sha1:8cafdff3
redis_git_dirty:1


# Memory
used_memory:39397328
used_memory_human:37.57M
used_memory_rss:5152768
used_memory_peak:39433240
used_memory_peak_human:37.61M
used_memory_lua:36864
mem_fragmentation_ratio:0.13
mem_allocator:jemalloc-3.6.0

# Stats
total_connections_received:458
total_commands_processed:5810
instantaneous_ops_per_sec:7
total_net_input_bytes:222003
total_net_output_bytes:451778
instantaneous_input_kbps:0.28
instantaneous_output_kbps:3.22
input_limit_tokens:31457280
output_limit_tokens:31452526
input_strict_limit:0
output_strict_limit:0
rejected_connections:0
rejected_connections_status:0
sync_full:1
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
evicted_keys_per_sec:0
keyspace_hits:1
keyspace_misses:0
hits_per_sec:0.00
misses_per_sec:0.00
hit_rate_percentage:100.00
pubsub_channels:0
pubsub_patterns:0

stat_avg_rt:0
stat_max_rt:413

# CPU
used_cpu_sys:0.98
used_cpu_user:0.77
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Keyspace
db0:keys=1,expires=0,avg_ttl=0

# Cluster
databases:256
nodecount:1

# SSL
ssl_enabled:0
ssl_protocols:TLSv1,TLSv1.1,TLSv1.2
ssl_client_count:0
ssl_accept_count:0
ssl_reject_count:0
```

## 変更後の情報
少し瞬断されるようですね。

```shell
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> keys *
Error: Connection timed out
[root@poc3 ~]# redis-cli -h r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> info


# Stats
total_connections_received:686
total_commands_processed:11392
instantaneous_ops_per_sec:20
total_net_input_bytes:430952
total_net_output_bytes:699397
instantaneous_input_kbps:0
instantaneous_output_kbps:2
rejected_connections:0
sync_full:8
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:8
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:2264

# CPU
used_cpu_sys:2.36
used_cpu_user:2.01
used_cpu_sys_children:0.01
used_cpu_user_children:0.00

# Cluster
databases:256
nodecount:8

# Keyspace
db0:keys=1,expires=0,avg_ttl=0
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> get rkey1
"val1"
```

# まとめ
簡単にアップグレードできました。
クラスタにした分Memcacheのときより
台数が起動されクラスタを作るため時間が
かかりましたが、手軽にできていいですね。

# おまけ
クラスタから標準デュアルノードはできないようですネ。
![f1b234c2.png](https://qiita-image-store.s3.amazonaws.com/0/241104/72de3b65-82dd-6c0f-2793-c22039b9a597.png)
ApsaraDB for Redisってどんな感じ？

# はじめに
今回はAlibabaCloudのキャッシュサービス、Redisに触れます。

# ドキュメント
[ApsaraDB for Redis - オンデマンドのキーとバリュー型クラウドストレージサービス | Alibaba Cloud](https://jp.alibabacloud.com/product/apsaradb-for-redis)

# 特徴
[ApsaraDB for Redis (データベースサービス) プロダクトの詳細｜アリババクラウド](https://jp.alibabacloud.com/product/apsaradb-for-redis#product-details)

基本的にはMemcacheと近い特徴でで、可用性とRedisのPub/Sub機能があるといった感じでしょうか。

ただ、redisのバージョンは
**Redis 2.8（3.0と互換性あり）**
なんですね。

# コンソールから起動してみます
![fb135651.png](https://qiita-image-store.s3.amazonaws.com/0/241104/322d22cd-c196-56f0-e18c-ac9214f2d4cd.png)

![f160d77e.png](https://qiita-image-store.s3.amazonaws.com/0/241104/42c8c46f-0e7a-378a-8327-e670908ea8c0.png)

![c33e6f2f.png](https://qiita-image-store.s3.amazonaws.com/0/241104/0fd0aa2b-d024-7ac8-9963-f2b78866f874.png)

![e0d29e2a.png](https://qiita-image-store.s3.amazonaws.com/0/241104/698ba0ab-de4d-3e4f-554c-11e74c958af0.png)

[ApsaraDB for Memcacheを起動してみます。](https://qiita.com/wa-ta-ru/items/c562f5140b58fdc97ac3)
の経験があるので、パスワードのところの四苦八苦は
ないですね。
cacheのVSwitch(サブネット)を追加してVPCは事前に作成しており、ECSも起動しております。

# ホワイトリストの設定をします
![9f01d491.png](https://qiita-image-store.s3.amazonaws.com/0/241104/ddbaff36-1882-2b01-648f-a5417fc764d8.png)

![54a355f9.png](https://qiita-image-store.s3.amazonaws.com/0/241104/e91f568b-de71-9ed9-c499-91e3dbf041bc.png)

# パスワードアクセス不要を有効化します
![05ec1d93.png](https://qiita-image-store.s3.amazonaws.com/0/241104/a0c75745-7bf3-ea84-f132-fb84edad1676.png)

![a7032b9a.png](https://qiita-image-store.s3.amazonaws.com/0/241104/6f2c0af3-5dcd-6e3e-532c-5a6034b562d5.png)

![292f09ed.png](https://qiita-image-store.s3.amazonaws.com/0/241104/4ca31be5-bc80-3722-9fcd-4395f0b9f1da.png)

# ECSからアクセスしてみます。
ECSにredisパッケージをインストールしてみて確認してみます。

```shell
[root@poc3 ~]# yum -y install redis
[root@poc3 ~]# redis-cli -h r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com
[root@poc3 ~]# redis-cli -h r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> keys *
(empty list or set)
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> set rkey1 val1
OK
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> get rkey1
"val1"
r-e9b8f0dd3fe80f34.redis.japan.rds.aliyuncs.com:6379> exit
```

# まとめ
とても、簡単に扱えますね。
Redfisバージョンが、ちょっと古いのでこちらはサービスとして期待したいところです。
[Redis](https://redis.io)
nodist使ってもNode.jsのバージョン変わらない問題

>問題点


nodistでnode.jsのバージョン変更しようと思ったのに変更されない

```
C:>nodist 8.12.0
8.12.0
Default global pacakge update dsuccessful.

C:>node -v
v8.11.4
```



>解決策1: 文法のチェック

文法は"nodist X.XX.X"が正しい

正： nodist 8.12.0
誤： nodist v8.12.0


>解決策2: Node.jsのアンインストール

Node.js→nodistの順でインストールすると正常に動かない様子．

新規にインストールする場合はnodistのみインストールしてnodist経由でNode.jsを導入する．
すでにNode.jsをインストールしてある場合は，Node.jsをアンインストールでOK
UE4のBluePrintだけで壁蹴りを実装する

UE4のBluePrintで壁蹴りを実装してみましょう。
不思議なことに、日本語でUE4の「壁蹴り」「壁ジャンプ」と調べても出てこなかったので書きました。

壁蹴りの仕組みは自分が自作しているゲーム、ユニティちゃん＆グレイちゃんの次回体験版バージョンの基本機能として入れているものを、そのまま載せています。
![fee74a95-70bb-48bb-7235-08d5fce18c31.png](https://qiita-image-store.s3.amazonaws.com/0/104377/0362e957-0245-1757-9b30-72a2e38b1e26.png)

実装にあたり、以下のフォーラムを参考にしています。
[[Blueprint] Wall Jump fail](https://forums.unrealengine.com/development-discussion/blueprint-visual-scripting/3556-blueprint-wall-jump-fail)

※「UE4　Wall　Kick」と検索すれば他のも出てきます。

# 前提条件

今回記載する壁蹴りのシステムは、「3d」のSide Scroller Templateを使用しています。 
ロジックはBluePrintのみです。
今回はTraceを利用する方法で壁検出を実装します。
→Traceが重くてイヤ、という人は壁にオーバーラップ用のコリジョンを張り付けて判定する等、いろんな方法があるので調べてみてください。

# 壁蹴りの処理の流れ

今回実装した壁蹴りの処理は大まかに以下の通りです。

1.空中でジャンプのボタンを押す
2.キャラの少し上方向に半径50のSphereTraceを実行
3.WorldStatic、もしくはWorldDynamicがTraceで検出されたら、Launch Characterノードを実行

##①SphereTraceForOBjectでの壁検出

まず、壁判定用の関数を作成します。
SideScrollerCharacterという名前のBluePrintクラス（またはCharacterを継承したクラス）を開き、以下の画像のように関数を作成します。
![wallkick4.png](https://qiita-image-store.s3.amazonaws.com/0/104377/2c2f7322-2ba7-7b6a-cfa8-fff73c8d5c69.png)

処理の流れとして、GetActorUpVectoerに100をかけた位置に、半径（Redius）50のSpherTraceForObjectsを実行して、WorldStatic、WorldDynamicを検出するという内容になっています。
操作キャラクターよりも若干高い位置にすることで、地面のWorldStatic、WorldDynamicを検出するのを防いでいます。

SpherTraceForObjectsのDrawDebugTypeにFor Durationが選択されていますが、これはデバッグのためにTraceを画面に表示させているだけです。
![wallkick5.png](https://qiita-image-store.s3.amazonaws.com/0/104377/1eebb2d4-a47b-cec5-4193-1ff780651e73.png)

デバッグ以外で画面に表示させる必要性はないので、リリースするときは必ず以下の通りDrawDebugTypeをNoneに指定してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/104377/644b6705-c86f-4976-f287-116b403e669f.png)

これで壁検出ができました。

##②壁蹴り（壁ジャンプ）用の関数を作成

以下のように、ジャンプ用の関数を作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/104377/6c632b9e-7af4-e9ed-ae7b-ab0d5818d659.png)

CharacterMovementにあるisFallingでキャラクターが空中にいるか否かが取れます。
もし、地上にいる場合は、CharacterのJump関数でキャラクターにジャンプさせます。
空中にいる場合は、①で作成した関数（画像の場合、純粋関数となっている「Detect Wall」の部分）を呼び出して壁があるか判定し、もし壁があった場合はLaunch Characterを呼び出して斜め上の方向にキャラクターを若干飛ばしています。

※Launch Characterの詳細は[公式ドキュメント](http://api.unrealengine.com/JPN/Engine/Blueprints/QuickStart/6/)を見てください。

##③Jumpのインプットアクションイベントに、②で作成した関数を呼び出す。

以下のように、Jumpのインプットアクションに②で作成したジャンプの関数を呼び出します。
![walljump2.png](https://qiita-image-store.s3.amazonaws.com/0/104377/1570cf9c-6b1e-e9c4-7b75-7e8a4a23e700.png)

これで壁蹴りが実装出来ました。

この状態で壁の近く、かつ空中に居るときにジャンプボタンを押すと、以下のGifのように斜め上方向に壁蹴り（壁ジャンプ）すると思います。
![wallkick.gif](https://qiita-image-store.s3.amazonaws.com/0/104377/a49e4879-2d53-9648-8819-917d7056a257.gif)

#まとめ
というわけで、方法さえわかれば割と簡単に、かつ汎用的に使える壁蹴りの仕組みが出来ました。
壁蹴り、壁ジャンプをUE4で実装したいという人は参考にしてください。
WindowsからXUbuntu18.04にリモートデスクトップ接続

# 概要
リモートデスクトップ環境の構築手順です。いろいろハマったので、手順をまとめました。

# 環境
* サーバ側
    * XUbuntu 18.04.1 LTS
    * xfce 4.12
    * Gufw Firewall 18.04.0
    * X11VNC Server 0.9.13-3
* クライアント側
    * UltraVNC 1.2.2.2

# サーバ側（XUbuntu）の設定

## ソフトのインストール

### X11VNC Server
「ソフトウェア」から「X11VNC Server」をインストールする。
（`sodo apt install x11vnc`でもOK）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37903/c2b93d48-5703-b13c-01ff-e76cf637825a.png)

### ファイアウォールの設定アプリ
`$ sudo apt install gufw`コマンドでインストールする。
http://gufw.org/

## X11VNC Serverの設定
1. X11VNC Serverを起動する
2. Portに5900を入力して（最初から入力されている）、OKボタンを押す
![image.png](https://qiita-image-store.s3.amazonaws.com/0/37903/ff53e2cf-56b1-bf3c-4620-e31ef830ed34.png)

3. 以下の操作を行い、OKボタンを押す。
    * 「Accept Connections」にチェックを入れる
    * 「Shared」にチェックを入れる
    * 「Password」を入力する

>
 Accept Connections:
   Toggles whether VNC viewers are allowed to connect or not.  It corresponds
   to the "-R unlock" and "-R lock" remote-control commands.
>   
 Shared:
   Toggles whether multiple simultaneous viewer connections are allowed
   or not.  It corresponds to the "-R sh
>
 Password:
   Lets you set the session password viewers may use to gain full access
   to the display.  This will only work if x11vnc was started with the
   -gui icon or -gui tray mode.

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37903/840e22aa-3e14-68ec-3ecd-aab4b51ebfa9.png)
4. x11vncがポート番号5900で起動していることを確認する。

```shell-session
$ netstat -ap | grep 5900
(一部のプロセスが識別されますが, 所有していないプロセスの情報は
表示されません。それら全てを見るにはルートになる必要があります.)
tcp        0      0 0.0.0.0:5900            0.0.0.0:*               LISTEN      6730/x11vnc         
tcp6       0      0 [::]:5900               [::]:*                  LISTEN      6730/x11vnc         
```


## ファイアウォールの設定
1. gufwを起動する
2. ルールタブに移動する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37903/f4d6d233-b1d6-f27a-f53f-d2a67fda76b0.png)
3. 「+」ボタンを押す
4. 「VNC Filter」に「vnc」と入力し、「追加」ボタンを押す。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/37903/0a3ea7be-163c-aed2-11e9-38540b67df33.png)
5. → 「ルール」に追加される
![image.png](https://qiita-image-store.s3.amazonaws.com/0/37903/d2034195-2644-5059-ddef-cba8a4655508.png)


# クライアント側（Windows）の設定

## UltraVNCのインストール
VNCのViewerはいろいろありますが、今回はUltraVNCを使いました。
https://forest.watch.impress.co.jp/library/software/ultravnc/

## UltraVNCの設定
1. UltraVNCを起動
2. 「VNC Server」に「server-host:0」と入力する。
    * `sever-host`はサーバのホスト名
    * `:0`はVNCのディスプレイ番号0
![image.png](https://qiita-image-store.s3.amazonaws.com/0/37903/b3848373-829b-1ad1-fca3-e0ed1ba46407.png)
3. 「Connect」ボタンを押す
4. パスワードダイアログに、X11VNC Serverで設定したパスワードを入力し、「login」ボタンを押す。
5. → リモートデスクトップ完了

## その他
### X11VNCのログファイルの場所
`$HOME/.x11vnc.log.server-host\:5900`


# 参考サイト
https://www.osshinet.com/2018/06/16/win-19/
Neo4jでRDF, オントロジを扱う

一般的にRDFなんかでLinked Open Data(LOD)なんていうときはSPARQL Endpointなんかに格納するのだと思いますが、色々とあってNeo4jのようなグラフDBに格納したいと考えました。調べてみると、RDFとNeo4jのLGPというのは[基本的な構造が同じだから変換](https://neo4j.com/blog/neo4j-rdf-graph-database-reasoning-engine/)が可能とある。Githubに[neosemantics](https://github.com/jbarrasa/neosemantics)というプラグインも上がっています。ということでやってみます。

# neo4jのグラフモデルとRDFS/OWLのデータモデルの違い
Web Ontology Language(OWL)などのオントロジを変換する場合、OWLのクラスはneo4jではノードのLabelとして表現されます。また、DetatypePropertyはAttribute、ObjectProperyはRelationといった形で表現されます。グラフモデルの制約があって、厳密には変換が難しいそうですが利用にあたっては問題もないと思われます。
この辺りは、ライブラリの制作者の方が、入念に[解説](https://jbarrasa.com/2016/04/06/building-a-semantic-graph-in-neo4j/)されています。

# neosemanticsのインストール
Neo4jのサーバは立っている前提で進めます。まずはGitで対象のソースコードを取ってきて、Mavenでコンパイルします。

```git
git clone https://github.com/jbarrasa/neosemantics.git
cd neosemantics
mvn clean package
```

ここで`./target`以下にFatjarができるので（original-neosemanticsではないほう）、それをNeo4jのプラグインフォルダに格納します。加えてコンフィグファイルに以下を追記します。それぞれのファイルの場所は[ここ](https://neo4j.com/docs/operations-manual/current/configuration/file-locations/)を参照ください。再起動すると使えるようになっています。

```neo4j.conf
dbms.unmanaged_extension_classes=semantics.extension=/rdf
```

# RDF、TTL、OWLのインポート
Neo4jのサーバにアクセスして、まずは専用のインデックスを作ります。

```cypher
CREATE INDEX ON :Resource(uri)
```

まずは適当なTrplesファイルを読み込んでみます。ここではTurtleでシリアライズされたファイルをウェブから読み込んでいます。最初の引数が対象のファイル、二番目がファイルのフォーマット、最後がそのほかのパラメータです。可能なフォーマットはTurtle, N-Triples, JSON-LD, TrG, RDF/XMLとあります。詳細は[公式サイト](https://github.com/jbarrasa/neosemantics)を参照ください。
`file:///～`のように記載することでNeo4jサーバ内のローカルファイルを参照することもできます。

```cypher
CALL semantics.importRDF("https://www.w3.org/ns/org.ttl","Turtle",{ languageFilter: 'en' })
```

こんな感じで可視化ができます。
![graph.png](https://qiita-image-store.s3.amazonaws.com/0/51703/b8a63fa0-c102-cd34-b749-d4c9fbd7bafc.png)

オントロジのインポートについては、以下のように行います。
CALL semantics.liteOntoImport("http://ifcowl.openbimstandards.org/IFC4_ADD2.ttl", "Turtle")

他にもプレビューだけしてデータベースには書き込まない`semantics.previewRDF`というコマンドがあったりします。

#　参考
- [neosemantics](https://github.com/jbarrasa/neosemantics)
- [Importing RDFS/OWL ontologies into Neo4j](https://lju-lazarevic.github.io/ImportingRDFSOWL.html)
- [Building a semantic graph in Neo4j](https://jbarrasa.com/2016/04/06/building-a-semantic-graph-in-neo4j/)
ecs-cliに弄ばれる人生を脱した俺の人生はこれからだ

俺です。

ある日。というか2018/9/25JSTぐらいからなんですが、
以下なコマンドでデプロイしてたservice upがエラーを吐いたので泣く泣く対処した経緯を残します。

# 環境

AWS_DEFAULT_REGION=ap-northeast-1
ecs-cli: 1.6.0

# deploy & error messsage

- ecs-cli deploy command

```
ecs-cli compose -f docker-compose.ecs.yml \
--project-name orenopurojekuto  service up --force-deployment \
--target-group-arn "<orenotargetarn>" \
--container-name nginx \
--container-port 80 \
--cluster orenocurasuter
```

- error message

maximumPercentかminimumHealthyPercentを指定しないといかんざきと返されました。

```
time="2018-10-02T01:41:31+09:00" level=info msg="Using ECS task definition" TaskDefinition="orenosaikounotasuku:002"
time="2018-10-02T01:41:31+09:00" level=warning msg="You cannot update the load balancer configuration on an existing service." serviceName=orenopurojekuto
time="2018-10-02T01:41:31+09:00" level=error msg="Error updating service" error="InvalidParameterException: At least one of maximumPercent or minimumHealthyPercent must be present in DeploymentConfiguration\n\tstatus code: 400, request id: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" service=orenopuroject
time="2018-10-02T01:41:31+09:00" level=fatal msg="InvalidParameterException: At least one of maximumPercent or minimumHealthyPercent must be present in DeploymentConfiguration\n\tstatus code: 400, request id: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
```

- ecs-cli help

ただしhelpを見ると `Optional parameter` であり、デフォルト値は決まっていると。
どーゆー骨茶

```
$ ecs-cli compose service up --help
   --deployment-max-percent value          [Optional] Specifies the upper limit (as a percentage of the service's desiredCount) of the number of running tasks that can be running in a service during a deployment. Defaults to 200.
   --deployment-min-healthy-percent value  [Optional] Specifies the lower limit (as a percentage of the service's desiredCount) of the number of running tasks that must remain running and healthy in a service during a deployment. Defaults to 100.
```

# 対策

Optionalと言われてるはずのパラメータを指定した。

```
ecs-cli compose -f docker-compose.ecs.yml \
--project-name orenopurojekuto  service up --force-deployment \
--target-group-arn "<orenotargetarn>" \
--container-name nginx \
--container-port 80 \
--deployment-max-percent 200 --deployment-min-healthy-percent 100 \
--cluster orenocurasuter
```

```
INFO[0000] Using ECS task definition                     TaskDefinition=""
WARN[0000] You cannot update the load balancer configuration on an existing service.  serviceName=
INFO[0000] Updated the ECS service with a new task definition. Old containers will be stopped automatically, and replaced with new ones  deployment-max-percent=200 deployment-min-healthy-percent=100 desiredCount=2 serviceName= taskDefinition="
--以下省略--
```

完ってことで。