OmniAICreator/Qiita-1.07M huggingface dataset:
JavascriptとTypscriptの注意点

## Typescriptのクラス宣言

Typescript（以下TSとする）では、以前のJavascript（以下JSとする）のクラス定義の方法は推奨されないようだ。
なので、class演算子を用いたクラス定義を用いるべきということで、内容をまとめる。

以下は古い宣言方法で、非推奨。

```typescript:oldClassDeclare.ts
let Person = function(name, age) {
    this.name = name;
    this.age  = age;
}

// Personインスタンスを生成
let taro = new Person('太郎', 20);
```

以下が新しい宣言方法。

```typescript:newClassDeclare.ts
class Person {
	private name: string;
	private age: number;
	constructor(name: string, age: string) {
		this.name = name;
		this.age = age;
	}
}

// Personインスタンスを生成
let taro = new Person('太郎', 20);
```

## JSとTSのexport・importまわり

JSやTSでファイル分割して、インポートする機会は多いと思う。
ただ、TSでJSと同じようにインポートすると危険らしいので（理由は不明）、分ける必要があるらしい。
どういうことだろうか。

#### JSのエクスポート・インポートの仕方

まず、以下のようなJSファイルがあるとする。

```javascript:jsFunctionUtil.js
function getOK() {
  return "OK";
}

function getNO() {
  return "NO";
}

module.exports = {okFunc: getOK, noFunc: getNO};
```

外部ファイルの関数を利用する場合は、以下のようにする。

```javascript:useJsEternalFunction.js
const functionUtil = require("./jsFunctionUtil.js");

console.log(functionUtil.okFunc()); //getOK関数を実行する
```


#### TSのエクスポート・インポートの仕方

```typescript:tsFunctionUtil.ts
export function getOK() :string{
  return "OK";
}

export function getNO() :string{
  return "NO";
}
```

```typescript:useTsEternalFunction.ts
import { getOK, getNo } from "./tsFunctionUtil.ts";

console.log(getOK()); //getOK関数を実行する
```

ちなみに、クラスをexportする場合は、export classでいける。
やっかいなのが、TSであってもJSのエクスポート・インポート方法が使えてしまうというところ。
JSの方法でもいけることはいけるが、不具合が出るらしいので（理由は不明）、正式な方法を使うようにしたい。
もだんC++でマージソートをしてみる

新しいC++は古いC++とは別物になる事は周知の通りです。
そこで、モダンだと私が思う方法でマージソートを実装してみようと思います。
(独学および規格書までは読んでないにわかなので、あくまでもモダンっぽい何かです)

ま、[std::merge](https://cpprefjp.github.io/reference/algorithm/merge.html)を使うだけですが

```c++:mergesort.cpp
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>

template<typename T>
std::vector<T> merge_sort(typename std::vector<T>::iterator begin, typename std::vector<T>::iterator end){
  if(begin + 1 >= end)
    return std::vector<T>(begin, end);

  auto size = end - begin;
  auto mid = size / 2;
  std::vector<T> result;
  result.reserve(size);

  std::vector<T> left  = merge_sort<T>(begin, begin + mid);
  std::vector<T> right = merge_sort<T>(begin + mid, end);
  std::merge(left.begin(), left.end(),
             right.begin(), right.end(),
             std::back_inserter(result));
  return result;
}

int main(){
  using std::vector;
  using std::cin, std::cout, std::endl;

  vector<int> input;
  int size;
  cout << "size:";
  cin >> size;

  input.reserve(size);
  std::copy_n(std::istream_iterator<int>(cin), size, std::back_inserter(input));

  cout << input[0];
  std::for_each(std::begin(input) + 1, std::end(input),
    [](int x){ cout << "," << x ;}
  );
  cout << endl;

  auto res = merge_sort<int>(input.begin(), input.end());

  cout << res[0];
  std::for_each(std::begin(res) + 1, std::end(res),
    [](int x){ cout << "," << x ;}
  );
  cout << endl;
}
```

std::mergeの仕様のせいで内部ソートじゃないのが若干気にはなりますね。

std::copy_nでn個の要素を`cin`から`vector`へ入力できるテクニックはなかなか便利なのではないでしょうか

n個の要素まではソート済みだからそれ以降をマージソートしてくれ　みたいな関数があると便利っぽい気がしますね

なお`using`宣言をカンマ区切りで複数同時に行っているのでc++1zを指定しないと怒られます。

---

もっとモダンに美しく書けるor内部ソートをカッコよく書ける手段があるのならば教えて頂けると幸いです。
RailsのActiveRecordで使ってしまうその場しのぎのテクニック5つ

# はじめに
RailsのActiveRecordでよく使ってしまうテクニックをまとめてみた。
大体、試行錯誤の果てに生まれたり見つけたりしたものなので、パフォーマンスや正しさなどはわからない

全体的にもっとスマートな書き方があったら教えてほしいです。

## LEFT JOINに条件を加える
INNER JOINであれば、whereを書けばとりあえず条件は書けるが、LEFT JOINだとそうもいかない
[リレーションに条件を加えたり](https://teratail.com/questions/78053)、Arelを使う方法もあるが、どっちも嫌なので


```rb
User.joins("LEFT JOIN messages ON(messages.user_id = user.id and messages.opend = 1)")
# eager_loadingしたいときは
User.eager_load(:messages).joins('AND messages.opend = 1')
```

みたいな感じで書いている。

Rail5から``left_joins``というそのまんまなメソッドが追加されたが、これだとうまくいかなかった。なぞ。

参考: [railsでのeager_loadの結合条件の追加はできますか？
](https://ja.stackoverflow.com/questions/22812/rails%E3%81%A7%E3%81%AEeager-load%E3%81%AE%E7%B5%90%E5%90%88%E6%9D%A1%E4%BB%B6%E3%81%AE%E8%BF%BD%E5%8A%A0%E3%81%AF%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%81%8B)

## NULLや空文字の入ったカラムで並び替えする
NULLが入ったカラムを昇順に並び替えすると、NULLの入ったレコードが先頭に来るが、そうなって欲しくないとき

```rb
User.order('users.image IS NULL ASC')
# もしくは
User.order("users.image = '' ")
```

と書くとNULLや空文字のレコードが下の方に並び替えられる

参考: [MySQLのソートで空白の行を下げようとしたらハマった話](http://aym.sakura.ne.jp/system/20160426/)

## countした値で並び替えたい
記事(article) has many コメント(comments)みたいなリレーションで、記事についたコメントの件数で並び替えたいとかよくある

```rb
  scope :popular, -> {
    article_ids = Article.
      joins(:comments).
      group('comments.article_id').
      order('count_commnets_article_id desc').
      count('comments.article_id').
      keys
    where(id: article_ids).order(['FIELD(articles.id, ?)', article_ids])
  }
```

countを使うと、prefixにcount_がつくようなのでそれでorder
``{ article_id => count_comments_article_id }``のハッシュが返されるので、``keys``でarticle_idだけ取り出して、FIELD関数で並び替え

これももっとうまい方法がある気がするが慣れるとササッとかけるし、応用が効くのでつい頼ってしまうやつ

## スコープをモジュール化する

```rb
module readable
  def self.included(base)
    base.class_eval do
      scope :already_read, -> {
        where(read: true)
      }
    end
  end
end
```

上のコードはmoduleがincludeされたときに、class_evalメソッドでブロック内をクラスメソッドのように扱ってるらしい
scopeって要はクラスメソッドの糖衣構文だったので確かそう
特異クラスとかそのへんはちょっと勉強中

## ランダムなレコードを1件取得する
MySQLであれば`order("RAND()")`とかで済ませてしまうのだけれど、DB移行なんて滅多にないものの、わざわざ依存を作ってしまうのは良くないと思い始めた。

```rb
Blog.find(Blog.pluck(:id).sample)
```

というわけで読みやすさなども兼ねて上記で落ち着いている。大体はテストで使う。

参考: [Rails ActiveRecordでランダムにレコードを1件取得する](https://easyramble.com/get-record-randomly-with-active-record.html)

## (おまけ)uniqがdeprecatedになってた
ちょっと本題からは逸れるが、気づかなくてハマってしまったので

uniqはrubyのArrayクラスとかにもあるメソッドなんだけど、railsではdistinctみたいな使い方もできる
その2つの使い分けをどこでしているかは調べていないが、**空のActiveRecord::Relationに対してuniqするとArrayが返って**、その後のwhere句とかで落ちてしまうみたいなことがあった。

なのでdistinctを使いましょうということでした。

参考:[deprecate `Relation#uniq` use `Relation#distinct` instead.](https://github.com/rails/rails/commit/adfab2dcf4003ca564d78d4425566dd2d9cd8b4f)
pyenv自体をアップデートして"No such file or directory"となった時

homebrewでpyenvをインストールしていて、homebrewでpyenvがアップデートされた時、以下のエラーが発生した。

```shell-session
$pip
/Users/nnyn/.pyenv/shims/pip: line 21: /usr/local/Cellar/pyenv/1.2.4/libexec/pyenv: No such file or directory
```

`~/.pyenv/shims/python`の中身が古いパスのままになっている。
これを最新のパスにするには以下を実行する。

```shell
pyenv rehash
```
rbashをちゃんと設定するために気をつけること

CI から SSH を許可するために、秘密のデータを置く専用の場所に置いたり鍵を暗号化して置いたりするわけですが、破られた場合の次の策として `rbash` を設定しようとしていました。 `rbash` を使用すると、実行可能なコマンドに制限のかかったユーザを作成することができますが、うっかり不十分な制限になってしまうことがあります。

## `.bash_profile` だけではダメ（かも）

CentOS 7 で作られる `.bashrc` が

```
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi
```

としているおかげで、 `.bash_profile` で設定した `PATH` が上書きされてしまいます。
`.bashrc` で設定するようにしましょう。

## ビルトインコマンドが使える

```
$ ssh user@host 'test -f /etc/passwd && echo test'
test
```

もっと厳しくするには、`enable -n COMMAND` を `.bashrc` に追記して不要なビルトインコマンドを無効化します。

## scp で .bashrc を上書きできる

`chown` で root に所有させたりして、該当ユーザは読み込みだけにします。
その他 `.profile`, `.bash_profile`, `.bash_logout` あたりも注意。

## 任意のコマンドを実行できるコマンドを許可してしまう

`awk`, `find` など。 `EDITOR` を使うやつも注意。
一旦、自前のシェルスクリプトで引数を制限してしまうのも良いかもしれません。

### scp, rsync で任意のコマンドを実行できる

表からはわからないので注意。

```bash
scp -S /bin/echo . example@localhost:/
```

とすると、実行したマシン上で任意のコマンドが実行できる。

これが困るのは `rbash` で制限している時。 `scp` は、上記の `echo` で示した通り、手元とリモートの両方の `scp` で動作するので、リモートマシンにも `scp` の `PATH` を通す必要がある。しかし、 `rbash` は直接起動したコマンドしか面倒を見れないので、 `rbash` による制約を回避できてしまう。

```bash
#!/bin/bash

if [[ " $@" = *" -S"* ]]; then
   echo "Command failed: $@" >&2
   exit 1 
fi

/bin/scp $@
```

代わりに上記のようなシェルスクリプトを制限するユーザの `PATH` 上に置いておく。

`rsync` も似たようなことが出来てしまうので、

```bash
#!/bin/bash

if [[ " $@" = *" -rsh"* || " $@" = *" -e"* ]]; then
   echo "Command failed: $@" >&2
   exit 1 
fi

/bin/rsync $@
```

---

まだ抜けがありそうな気がする。
Xcode 実機インストールができない場合の対応

####codesignは、キーチェーンに含まれるキー”access”へアクセスしようとしています。
<img width="400" alt="4f17d5c1de15aaa8840aa8c986db7237.png" src="https://qiita-image-store.s3.amazonaws.com/0/266239/b6685cf7-bc1d-b846-017b-cc21031aa4d7.png">
 
#### “accountsd”がキーチェーン”buildagent”を使おうとしています。
<img width="400" alt="3d371385c507a2fd017a06f46d1f5862.png" src="https://qiita-image-store.s3.amazonaws.com/0/266239/1e4c55c5-d078-b1c2-b2d0-2385f011cce9.png">

もしくはこういうエラーが出てXcodeから実機にインストールできない場合
PhaseScriptExecution [CP]\ Embed\ Pods\ Frameworks
xxxx..framework: unknown error -1=ffffffffffffffff
Command /bin/sh failed with exit code 1
http://www.cnblogs.com/vipstone/p/7813524.html 

1） /Users/[USER NAME]/Library/Keychains フォルダをデスクトップなどに移動して再起動。
2） 再起動した後にキーチェーンを再作成するウィンドウが出る場合は、ログインパスワードを入力して再作成。
冒頭のウィンドウが出る場合でもログインパスワードで認証OKとなる。
FlutterでTextFieldを最下部に配置する

# こんなのを作る
<img src="https://qiita-image-store.s3.amazonaws.com/0/237025/45203cf6-d8b7-e95d-d47d-4d361ade16dc.png" width=40%> <img src="https://qiita-image-store.s3.amazonaws.com/0/237025/72de6469-7827-73b7-91b2-af9f34a9e671.png" width=40%>

# どうやるのか
TextFiledを最下部に配置するには、以下のように全体をColumnでwrapし、TextFiledの上に配置するWidgetをExpandedでwrapします。

```dart
new Column(
  children: <Widget>[
    new Expanded(
      child: new SingleChildScrollView(
        child: new Column(
          children: <Widget>[
            new Container(
              padding: new EdgeInsets.all(5.0),
              child: new Text(
                "Test",
                style: new TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
            new Container(
              padding: new EdgeInsets.all(5.0),
              child: new Text(
                "Test",
                style: new TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ],
        ),
      ),
    ),
    new TextField(
      autofocus: true,
      style: new TextStyle(
        fontSize: 20.0,
        color: Colors.black,
      ),
      controller: _controller,
      decoration: new InputDecoration(
        border: InputBorder.none,
        hintText: 'コメントを追加',
      ),
    ),
  ],
)
```
Amazon SageMakerのノートブックインスタンスが開始しない場合の対応法

# 1. まとめ

Amazon SageMakerをAWS Management Consoleで利用する際に，ノートブックインスタンスが起動しないことがある．開始しない場合は[AWS CLI](https://docs.aws.amazon.com/cli/latest/index.html)の[start-notebook-instance](https://docs.aws.amazon.com/cli/latest/reference/sagemaker/start-notebook-instance.html)を利用すると起動できる．（起動できない場合もある）
 
# 2. 目次

- 1. まとめ
- 2. 目次
- 3. 事象
- 4. 解決方法
- 5. 事象の原因
- 6. 注意点
- 7. 参考リンク

# 3. 事象

ノートブックインスタンス一覧では下記の通り**Failed**になっている

![エビデンス①.png](https://qiita-image-store.s3.amazonaws.com/0/262328/da75c410-067b-d342-b62d-e34e247bcb85.png)

ノートブックインスタンスを選択すると下記のエラーメッセージが表示されている．少し待ってと書いてあるので，試しに１日待ってみたが復旧はしなかった．

ノートブックインスタンスが停止状態だと中に入っているデータにアクセスする方法はないと思われる．（たぶん）

```
This Notebook Instance type is temporarily unavailable. We apologize for the inconvenience. Please try again in a few minutes, or try a different instance type.
```

![エビデンス②.png](https://qiita-image-store.s3.amazonaws.com/0/262328/5bc0d934-2f8e-51cb-9ef7-69348c9283ba.png)

# 4. 解決方法

ノートブックインスタンスを[AWS CLI](https://docs.aws.amazon.com/cli/latest/index.html)の[start-notebook-instance](https://docs.aws.amazon.com/cli/latest/reference/sagemaker/start-notebook-instance.html)を利用することで，復旧できることを確認した．

```bash
$ aws sagemaker start-notebook-instance --notebook-instance-name sagemaker-20180611-tf-01 --profile akatsuka-dev
```

# 5. 事象の原因

今回このようなことが起きた正確な原因は不明だが，私の場合はノートブックインスタンス一覧画面にて1秒未満の間隔で複数の停止しているインスタンスの開始ボタンを押下して再開させようとしたら発生した．

# 6. 注意点

ノートブックインスタンスを利用する上での注意点

今回は，[AWS CLI](https://docs.aws.amazon.com/cli/latest/index.html)を利用し再起動させることでデータにアクセスできた．が何かしらの問題があり，ノートブックインスタンスにアクセス出来なくなり，データにアクセスできなくなる事はあると思うので，定期的に作業内容をバックアップを取ったほうが良い．定期的にバックアップを取る方法は別の投稿で記載することとする．

# 7. 参考リンク

[AWS CLI](https://docs.aws.amazon.com/cli/latest/index.html)
[start-notebook-instance](https://docs.aws.amazon.com/cli/latest/reference/sagemaker/start-notebook-instance.html)
nagios4をdockerで動かしてメール通知

* [jasonrivers/nagios](https://hub.docker.com/r/jasonrivers/nagios/)
    * [GitHub](https://github.com/JasonRivers/Docker-Nagios)

## 設定

* ./objects/contacts.cfg
* ./conf.d/nw_office.cfg
* ./conf.d/custom-host.cfg

を作成する

```nginx:./objects/contacts.cfg
define contact {
    contact_name            nagiosadmin             ; Short name of user
    use                     generic-contact         ; Inherit default values from generic-contact template (defined above)
    alias                   Nagios Admin            ; Full name of user
    email                   nagios@localhost ; <<***** CHANGE THIS TO YOUR EMAIL ADDRESS ******
}

define contactgroup {
    contactgroup_name       admins
    alias                   Nagios Administrators
    members                 nagiosadmin
}
```

* nagios@localhost を検知時受け取りたいメールアドレスに置換する。


```nginx:./conf.d/nw_office.cfg
define host{
    use        custom-host
    host_name  host1
    address    192.168.0.4
}

define service{
    use                     generic-service
    service_description     check_ssh_host1
    host_name               host1
    check_command           check_ssh
    check_interval          1
}
```

* 監視の周期を短くするため以下作成

```nginx:./conf.d/custom-host.cfg
define host{
	name                            custom-host
	notifications_enabled           1
	event_handler_enabled           1
	flap_detection_enabled          1
	#failure_prediction_enabled      1
	process_perf_data               1
	retain_status_information       1
	retain_nonstatus_information    1
	check_command                   check-host-alive
	max_check_attempts              2
	notification_interval           60
	notification_period             24x7
	notification_options            d,u,r
	contact_groups                  admins
	register                        0
}
```


## 起動

```sh:
docker run \
 --name nagios4 \
 --restart=always \
 -p 0.0.0.0:8080:80 \
\
 -e MAIL_RELAY_HOST="リレーサーバー" \
 -e MAIL_INET_PROTOCOLS="ipv4" \
 -e NAGIOS_FQDN="FQDNを適当に設定" \
 -e NAGIOS_TIMEZONE="Asia/Tokyo" \
\
 -v /etc/localtime:/etc/localtime \
 -v $(pwd)/conf.d:/opt/nagios/etc/conf.d \
 -v $(pwd)/objects/contacts.cfg:/opt/nagios/etc/objects/contacts.cfg \
 jasonrivers/nagios:latest
```

* http://localhost:8080 にアクセス。
    * nagiosadmin / nagios

* swapが無くてcritical表示されるのが嫌な場合は、 objects/localhost.cfg を修正する。

## 実行コマンドの場所

* /opt/nagios/libexec/check_〜

## グラフ表示

* graphed-service を付ける

```diff
 define service{
-   use                     generic-service
+   use                     generic-service,graphed-service
    service_description     check_ssh_host1
    host_name               host1
    check_command           check_ssh
    check_interval          1
 }
```

![スクリーンショット_2018-07-02_10-03-44.png](https://qiita-image-store.s3.amazonaws.com/0/25728/8a445a17-da86-0272-651f-d8e3913b18e0.png)
AlibabaCloudでカスタムイメージを作成してみた

# はじめに
今回は、AlibabaCloudで
自分のカスタム化したイメージの作成をやります。

# 準備

[AlibabaCloudのAutoScalingのユーザーデータについて](https://qiita.com/wa-ta-ru/items/63818a4940036946a4be)
の記事のROSを起動します。
これでnginxが入っているECSが起動されます。

# ECSのコンソールを開く
インスタンスの管理を押してください。

![0bd7af1d.png](https://qiita-image-store.s3.amazonaws.com/0/241104/b6abacc5-6590-ee9c-1bb9-722ea6107089.png)

![8b7d7b18.png](https://qiita-image-store.s3.amazonaws.com/0/241104/a0c40420-5f15-f1bb-5268-769657bab9fd.png)

![578af425.png](https://qiita-image-store.s3.amazonaws.com/0/241104/67bb40e0-1b28-d542-e900-330f3fb7a7c2.png)

これでnginxが組み込まれたカスタムイメージが作成されます。

![933440df.png](https://qiita-image-store.s3.amazonaws.com/0/241104/03ac916d-7758-c498-7225-cca980116e22.png)

# 新規カスタムイメージを使って、コンソールからECSを起動する

[アリババクラウドのECSを東京リージョンの最安値で起動してみる！](https://qiita.com/wa-ta-ru/items/defd0114030fdfa95ea1)
のところでイメージを下記に変えれば、起動できます。

![079a2346.png](https://qiita-image-store.s3.amazonaws.com/0/241104/c6b562c1-80ec-69c4-0029-161ca4fa39d4.png)

## 新規カスタムイメージを使って、ROSから起動する

[AlibabaクラウドのECSを東京リージョンの最安値で起動してみる！(ROS版)](https://qiita.com/wa-ta-ru/items/9af5027860c730c328b5)
こちらの記事でParameterのイメージをところがcentosでなく、カスタムイメージのIDをいれるのがポイントです。

![933440df.png](https://qiita-image-store.s3.amazonaws.com/0/241104/03ac916d-7758-c498-7225-cca980116e22.png)

![296ede48.png](https://qiita-image-store.s3.amazonaws.com/0/241104/0e1ac51f-eb13-f44f-9699-694561680396.png)

# まとめ
これで、自分の設定が入ったイメージの
仮想マシンの起動ができるようになりました。

いつもCentOSのイメージのECSを起動した後に
ミドルウェアやアプリを入れるのは大変ですからネ。
既に組み込んだイメージの作成があると便利になります。
歴史上の戦いを地図上に表示するやつを作った。


# 窪田文也 / glucose inc.

---

# 戦争に関するデータを集めたい！

---

## ミッドウェー海戦のDBPediaのページを見ると
→ http://dbpedia.org/page/Battle_of_Midway 

---

# `rdf:type`に`dbo:MilitaryConflict` がついている

<ミッドウェー海戦>はDBPedia上で軍事的衝突の一種であると分類されている。
そして、戦いの記事はほとんどが属性を持っている。
→ 戦いに関する記事を集めることができる！

---

# dbo:date で勃発した日付がわかる！
→ 1942-06-07 (xsd:date)

---

# geo:lat geo:long で勃発した緯度経度がわかる！
→ 28.200001
→ -177.350006

---

# dbo:commander で参加した司令官がわかる！
→ チェスター・ニミッツ
→ 南雲忠一
→ フランク・J・フレッチャー
→ 山本五十六
→ レイモンド・スプルーアンス
→ 近藤信竹

---

# 地図+年号で三次元的に戦いを歴史上の戦いを表現する！

---

# 司令官で戦いを絞り込めるようにする！

---

# という機能があるインタラクティブな地図のアプリケーションがTevereです！

---

# iOS版デモ

---

# TODO:
* 選択された年代に存在している国も表示されるようにしたい。
  * 国境線とかは面倒
  * 首都のあった場所に何か置くくらいは頑張ればできそう

---

# ここから余談

---

# Tevereってなに

---
# Tevereってなに

* ローマにあるテヴェレ川
* 大河ドラマと掛けて著名な川の名前にしたかった
* ローマは戦いばっかりしている
* ルビコンは有名だけど大河ではない
* ググラビリティは低い

---

# 実装はどんな感じ？

---
# 実装はどんな感じ？
* http://dbpedia.org/sparql にSPARQLを投げる。
* そのあと集めたデータを整形して、JSONにしてMongoDBに突っ込む。
* JSONを返すREST APIにして、ReactやiOSで描画する。
* UIを頑張る。

---

# DBPediaで似たようなものを作って遊びたい人(いたら)への勧め

---

# DBPediaで似たようなものを作って遊びたい人(いたら)への勧め
- `rdf:type`はすごい
- 「それが何であるか」が明確になっているデータはおそらくここにしかない
- 興味分野の`rdf:type`を見つけて、そこから記事と記事の関係を割り出せないかを考える
  - 今回だったら同年代に起きた他地域の戦争
  - 同じ戦いに参加した司令官

---

# ブクマ集め

---

# ブクマ集め
* https://anond.hatelabo.jp/20180601103051
* 匿名ダイアリーで宣伝してコツコツ稼いだ。
* 匿名は無名に勝る
* ただ思ったよりPV的なインパクトは少ない気がする
* 英語圏の方が情報量が多いのであっち方面で宣伝したい。

---

# 謝辞

---

# 謝辞

LODに関わるみなさま、自分は単なるデータ消費者ですが、楽しくプログラミングをさせていただいています。
ありがとうございます。

---

# 終わり
AlibabaCloudのAutoScalingのユーザーデータについて

# はじめに
前回の[AlibabaCloudのECSのユーザーデータについて](https://qiita.com/wa-ta-ru/items/e41d0638c1da1ca91e92)ではECSのユーザーデータに触れました。
さて、今回はAutoScalingでのユーザーデータの使い方についてさらっと触れます。

# 起動するユーザーデータはコチラ

```shell
#!/bin/sh
yum update -y
yum install -y nginx
systemctl enable nginx.service
systemctl start nginx.service
```

# コンソールからECSを起動するとき

![e5c8811c.png](https://qiita-image-store.s3.amazonaws.com/0/241104/fbcf4af0-cef5-e9b2-5c8b-c87d633336a4.png)

と入れるだけでOKです。
あ、すいません。同じ画像なので全く変えてません。（笑）

# ROSからECSを起動するとき

**"ALIYUN::ESS::ScalingConfiguration"**
のパラメータで

```json
        "UserData": {
          "Fn::Base64": {
            "Fn::Join": [
              "\n",
              [
                "#!/bin/sh",
                "yum update -y",
                "yum install -y nginx",
                "systemctl enable nginx.service",
                "systemctl start nginx.service"
              ]
            ]
          }
        }
```

といれればOKです。

[User data - User Guide| Alibaba Cloud Documentation Center](https://www.alibabacloud.com/help/faq-detail/49121.htm)

# まとめ
これで、Auto Scalingでもnginx起動するためにSSHせずできるようになりました。
Macでgit difftool

# Macでgit difftool

Gitのコミット間の差分をツリー表示で比較したいと思って数時間迷子になったのでメモ。
WindowsだとWinMerge一択なのに。。

## Macの差分比較ツール
ググると使えるもの・微妙なもの・罠なもの等色々出てきますが、結局以下に落ち着きました。
* [Meld][1]

.gitconfigも書いてくれてます。やさしい。

なお、--dir-diffで起動しないと差分ファイルの数だけ閉じては開きを繰り返すのは他のツールと変わらないので注意。

## --dir-diffをつけ忘れると悲惨なことになるので
.zshrcとか.bashrcとかにエイリアス作っておくのが個人的におすすめです。

```
alias gd="git difftool --dir-diff"
```
とかね。
こうすると例えば

```
gd HEAD~ HEAD
```
で直前のコミットの差分をツリー形式でさくっと確認できます。

[1]:https://yousseb.github.io/meld/
TEMPファイルを作らずにフォームで受け取ったZIPをメモリ上で展開・解凍する手順

# はじめに
ZIPファイルを受け取ったあと，なんとなくTEMPファイルを作ったりしてディレクトリやサーバの容量を無駄に食うことがあります．**TEMPファイルを作らず**，**フォームから受け取ったZIPをメモリ上で展開・解凍**する手順について説明します．

## 開発環境
- Ruby 2.3.3
- Sinatra

```:Gemfile
gem "sinatra"
gem "rubyzip"
```

# 手順

## フォームからの受け取り
ここはそれほど難しくはなく，```form enctype="multipart/formdata"```を指定するだけです．

```slim:upload.slim
form method="post" action="/convert" enctype="multipart/form-data"
    p
        label for="uploadFile"
            | ZIPファイル：
        input type="file" name="uploadFile" id="uploadFile"
    p
        input type="submit" value="送信"
```


## Sinatraでの受け取り
Sinatraではformから受け取ったpostのパラメータをparamsに格納します．

```rb:config.rb
require "zip"
require "base64"

# 省略
post '/convert' do 
    data = params["uploadFile"]["tempfile"]
end
```

## zipの展開
展開したzipからファイル名とデータ本体を受け取り，それらの対応を返す関数を作ります．

```rb
def extract(data)
    retval = {contents: [], streams: []}
    Zip::InputStream.open(data) do |ios|
        while (entry = ios.get_next_entry)
            retval[:contents] << entry.name
            retval[:streams] << entry.get_input_stream.sysread
        end
    end
    retval
end
```

## zipの圧縮
受け取ったファイル名とデータ本体の対応させてファイルを圧縮します．
下の例では，``` zos.close_buffer```でStringIOを返す関数を作っています．

```rb
def archive(contents, streams)
    Zip::OutputStream.write_buffer do |zos|
        for i in 0...contents.size
            zos.put_next_entry(contents[i])
            zos.write streams[i]
        end
        zos.close_buffer
    end
end
```

```Zip::OutputStream.write_buffer```は内部でyieldしているので， **ブロックを与えないと余裕でLocalJumpErrorを吐く** ので注意してください．昔からのくせで```f = File.open(path)```みたいな処理を書くと怒られます．

## Base64へ変換

```Base64.strict_encode64``` で改行なしのBase64を作ります．


## Sinatraの修正
以上の関数を使ってSinatraのコードを以下のように修正します．

```rb:config.rb
require "zip"
require "base64"

# 省略
post '/convert' do 
    data = params["uploadFile"]["tempfile"]
    pair = extract(data)
    out = archive(pair[:contents], pair[:streams])
    Base64.strict_encode64(out.rewind.read)
end
```

```StringIO.rewind``` は現在位置をファイルの先頭に戻す関数です．

これで，TEMPファイルを全く作らずに，メモリ上だけで完結するような処理を実現できます．

# 終わりに
以上のようなコードを応用すると，

- 受け取ったZIPファイルに何かを差し込みたい
- ZIPファイルの検証や確認
- ダウンロード予定のZIPファイルをシングルページに埋め込みたい

などなど，ファイルIOやリクエストを極力減らせます．シングルページだと30%ぐらいレンダリングが速くなるらしいですよ．

## 余談
どうでもいいですけど，なんでcontentsとstreamsをわざわざ分けたんでしょうね．例えば，```contents.size != streams.size```が成立する可能性を考えてないです．

コードを書いているときにスペースを連打しすぎて頭がおかしくなったのでしょうか？　Qiitaのエディタは自動インデントが効かないのでカロリーを消費しすぎます．

コードが非常にキモいので書き方を真似しないように．エラったらごめんなさい．

### 追記(2018/07/03)
試しに10MB程度のZIPを差し込むとChromeでは問題なく動作しましたが，Firefoxは固まりました．たぶん，ブラウザ本体がBase64を解釈する処理が重いのかと．Base64を埋め込むなら画像とかにしましょう（戒め）

ちなみに，CADソフトのFusion360でシミュレーション・レポートを書き出すと，画像がBase64で埋め込まれています．HTML単体で10MBぐらいありますが開くのにそれほど時間がかからないです．Firefoxも固まらないので，**ファイルは分割して埋め込む**，もしくは**レンダリングに関わらないように埋め込む**のがベストだと思います．
メモ的なStream

#目的
streamでざっくりどんなことができるか知る。
とりあえず見てビビらない。なんとなくかけるようにする。

#コード
##基本形
```
		// 例えばこんなリストを作る
		List<String> list = new ArrayList<String>();
		list.add("sample");
		list.add("sample1");
		list.add("sample2");
		list.add("sample3");
		list.add("sample4");
		list.add("sample5");

		list
		.stream() // 対象のcollectionの加工開始
		.filter(s -> s.length() == 6) // 中間操作（加工）
		.forEach(s -> System.out.println(s)); // 終端操作（最後の処理）
		
		 // sampleのみ出力
```
このようにcollectionのstream()メソッドを使い、いくつかの中間操作を行い最後に終端操作を行うことで形にする。

##基本だけど
stream()はListで使われているけど、ListにメソッドがあるだけでインターフェイスとしてStreamは存在する。だから

```
Stream<String> st = list.stream();
st.forEach(s -> System.out.println(s));
```

のようなこともできる。


##終端操作
###forEach
voidなメソッドなので注意

```
list.stream().forEach(s -> sampleClass.stringList.add(s));
sampleClass.stringList.stream().forEach(s -> System.out.println(s));
```

###collect
stream()でいじってもListは返してくれないのでcollect()を使う

```
List<String>editList = list.stream().filter(s -> s.length() == 6).collect(Collectors.toList());
		editList.stream().forEach(s -> System.out.println(s));
```

他にも要素数を返すcount()など操作あり



##中間操作を使う
後は種々の中間操作を入れ込むだけ
使用頻度が高そうなものを記載

```		list
		.stream()
		.distinct() // 重複削除
		.filter(s -> !s.isEmpty()) // isEmpty()でないものみ残す
		.sorted() // 単純に昇順
		.sorted(Comparator.reverseOrder()) // 単純に降順
		.map(changeToLength) // 作成したFunctionを使用する
		.forEach(s -> System.out.println(s));
```

なお作成したFunctionは以下

```
		// Stringを引数、Integerを戻り値としてchangeToLengthというFunctionを作成
		// String s に対して{}内の処理を行う。
		Function<String, Integer> changeToLength= (String s) -> {
			return s.length();
		};
```
UbuntuとApacheでウェブサーバを立てる

# 筆者の環境
- Ubuntu16.04(KAGOYA VPS KVM)

# Apacheって何
- ブログやホームページを公開するために使う事が出来るウェブサーバ

# 特徴
- phpやCGIを用いた動的コンテンツの表示が出来る
- リバースプロキシとしても使用できる
- 使われ始めてからの歴史が長い

# 初期ページを表示するまでの手順
### 1. ポート解放とApacheのインストール、起動
```bash
# rootユーザとしてログインしておくかsudo su -

# パッケージのアップデート
$ apt update

# ufw(ファイアウォール)をインストール
$ apt install ufw

# インストール直後はufwはファイアウォールとして指定されないためufwを有効化
$ ufw enable

# 「このコマンドを実行するとssh接続が切れるかも知れませんがいいですか？」と聞かれるので y を入力してEnter

# sshのポートを開く
# これを行わないとssh切断したあと接続出来なくなってしまいます！
$ ufw allow 22

# Apacheが使用するポートを開く
$ ufw allow 80

# Apacheをインストールする
$ apt install apache2

# Apacheが稼働している事を確認する
$ curl localhost && echo success || echo failed

# successと表示されればApacheは起動出来ています。
# 表示された長いhtmlはデフォルトページのhtmlソースです。

# 自分のIPアドレスを確認する
$ ifconfig | grep "inet addr:"

# 192.168.1.xや127.0.0.1といったIPアドレスが表示されると思います
# これらはローカルIPや、グローバルIPと呼ばれます。
# 127.0.0.1は、ループバックアドレスと呼ばれ、自分自身を表すIPアドレスとなります。
```

### 2. 実際にページを表示してみる
同じネットワーク内の他のPCからウェブサーバを利用してみます。
ブラウザを起動し、先ほど確認したローカルIP、又はグローバルIPをアドレスバーに入力します。

このような画面が表示されると思います。
![スクリーンショット 2018-07-02 2.04.52.png](https://qiita-image-store.s3.amazonaws.com/0/266455/3ffbc0f8-a777-8a56-1fdb-6d4a7d984857.png)
Apacheではこれが初期ページとして設定されています。

# ページを追加、変更する
### 1. ページを追加する
Apacheがブラウザに送ってくれているhtmlは /var/www/html/ となっている様です。
ここを ドキュメントルート と呼びます。
ここにファイルを配置する事でApache経由で参照する事ができるようになります。

```bash
# ドキュメントルートに移動する
$ cd /var/www/html/
# 新しいページのファイルを作成する、アクセスする際のページ名は「test.html」とします
$ echo "Hello World!" > ./test.html
```

### 2. 実際にページを表示してみる
他のPCからページを
同じネットワーク内の他のPCからウェブサーバを利用してみます。
ブラウザを起動し、下記のようにアドレスバーに入力します。
`IPアドレス/test.html`

この様な画面が表示されます。
![スクリーンショット 2018-07-02 0.07.53.png](https://qiita-image-store.s3.amazonaws.com/0/266455/a7714f81-4a06-a4f4-4d12-09b361f9d3d1.png)
以上となります、Nginxが気になる方はこちら
> https://qiita.com/noma3629/items/807f25f9eb13525eebef

---
今回の記事ではこちらにお世話になりました。
> Ubuntuでapacheを使ったwebサイトのローカル環境を作ってみる（基礎）
> http://d.hatena.ne.jp/bicycle1885/20110508/1304871358
go コマンドが実行できない（MSpanList_Insert エラー）

# go コマンド実行時に「fatal error: MSpanList_Insert」が発生する

## 私の実行環境

- go：1.6.0
- macOS：10.13.5
- goのバージョン管理：goenv

## エラー内容の一部
```
failed MSpanList_Insert 0x9a1000 0x9fefaa79cb3c 0x0 0x0
fatal error: MSpanList_Insert

runtime stack:
runtime.throw(0x637260, 0x10)
	/usr/local/go/src/runtime/panic.go:530 +0x90 fp=0x7ffeefbff1c0 sp=0x7ffeefbff1a8

...

runtime.schedinit()
	/usr/local/go/src/runtime/proc.go:434 +0x79 fp=0x7ffeefbff6a0 sp=0x7ffeefbff658
runtime.rt0_go(0x7ffeefbff6d8, 0x3, 0x7ffeefbff6d8, 0x0, 0x0, 0x3, 0x7ffeefbff858, 0x7ffeefbff85b, 0x7ffeefbff863, 0x0, ...)
	/usr/local/go/src/runtime/asm_amd64.s:138 +0x132 fp=0x7ffeefbff6a8 sp=0x7ffeefbff6a0
```

## 解決方法
**goのバージョンをあげる**
エラー内容でググるとすぐ出てきますが、goにバグがあるようです。
バージョンをあげると解決しました。
これから触っていこうという感じなので、ひとまずバージョンをあげて対応しました。
私の場合、 `1.10.3` にあげて動作しました。

https://github.com/golang/go/issues/17335

以上。
Railsでutf8mb4設定

Railsで公開APIからデータを収集し、MySQLに保存するプログラムを書いて動かした所、ActiveRecordエラー発生。
MySQLのutf8mb4対応の問題だった。

# 環境
- Ruby 2.5.1
- Rails 5.2
- MySQL 5.7

# エラー 
```
ActiveRecord::StatementInvalid (Mysql2::Error: Incorrect string value: '\xF0\x9F\xA4\x94 \x0A...' for column 'xxxx' at row 1: INSERT INTO ...
```

# 原因
Insertするデータに絵文字が含まれていた。
自分で入力していない、APIから収集したデータだったので、発見に手間取った。

# 対処
```diff:config/database.yml
- encoding: utf8
+ encoding: utf8mb4
+ charset: utf8mb4
+ collation: utf8mb4_bin
```

テーブルを作り直す。

```
rails db:rollback
rails db:migrate
```

# 参考
https://qiita.com/dany1468/items/6431e486b8949cadcbe0
Flask で遊んでみた

軽量なフレームワークをなにか一つは身につけたいと思い、Flaskを勉強してみた。
##Flaskとは
Wikipediaから
>Flask（フラスク）は、プログラミング言語Python用の、軽量なウェブアプリケーションフレームワークである。標準で提供する機能を最小限に保っているため、自身を「マイクロフレームワーク」と呼んでいる。Werkzeug WSGIツールキットとJinja2テンプレートエンジンを基に作られている。

##やってみたチュートリアル
内容としては簡単な一言掲示板の作成。
環境構築の時間など抜きに30分もあればできてしまうサイズ。
https://a2c.bitbucket.io/flask/tutorial/index.html

以下章ごとの一言メモ
##Step 0: フォルダーを作成する
FlaskではJSやCSSなどはstatic下、HTMLはtemolate下へ格納。

##Step 1: データベース スキーマ
SQLiteを利用。

##Step 2: セットアップ
アプリケーションの実行を示す

```flaskr.py
if __name__ == '__main__':
    app.run()
```
は最後に挿入する。
後半コードを追加したときにこれの下に追加してしまってハマった。

##Step 3:データベースを作成する

```flaskr.py
def init_db():
    with closing(connect_db()) as db:
        with app.open_resource('schema.sql') as f:
            db.cursor().executescript(f.read())
        db.commit()
```  
データベースの初期化コードが上記のまま写経したところ動かなかった。
どうも

```flaskr.py
def init_db():
    with closing(connect_db()) as db:
        with app.open_resource('schema.sql') as f:
            db.cursor().executescript(f.read().decode('utf-8'))
        db.commit()
```

このように書かないといけない模様。

##Step 4: データベースの利用
ここで"g"が登場する。
Flaskの中で使えるグローバル変数のようなものでデータベースとの接続などを入れておくと便利っぽい。

##Step 5: View関数
ここでurl_forとredirect_template関数が登場。
<dl>
<dt>url_for</dt>
<dd>url_for('アクション名')で指定</dd>
</dl>

<dl>
<dt>redirect_template</dt>
<dd>redirect_template('ビュー名',ページ内での変数 = クラスでの変数)</dd>
</dl>
といった使い分け。
##Step 6:テンプレート
Jinjs2を使用。
<% endblock %>を<% end block %>と勘違いし、一瞬ハマった。

##step 7:スタイルを追加する
こちらは特になし。

##感想
癖があまりなく、軽量フレームワークをうたっていることもありすぐ覚えられそう。
日本語文献がほぼほぼなさそうなのがネックかなぁ。
固定文字列をプログラム領域に格納する

Arduino、特に容量の小さいATTiny85などを使っている場合、意味のわかる長い文字列をLCDやSerialに表示するとすぐに変数メモリが足りなくなってしまいます。

そんな時は[Fマクロ](http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=1830)を使うと便利です。

例えば　

```
Serial.print( "Hello World." );
```
で使用している "Hello World."　をプログラム領域に格納する場合、
プログラムの頭に

```
#include <avr/pgmspace.h>
```
を追加し、

```
Serial.print( "Hello World." );
```
を

```
Serial.print( F("Hello World.") );
```
のように変更します。

![スクリーンショット-2018-07-02-0.50.15.png](https://qiita-image-store.s3.amazonaws.com/0/59911/9ff1b7ac-2a81-8070-9623-a491fe0b2254.png)
Thread.sleep中の割り込みをJUnitでテストする方法

## はじめに
Thread.sleepの割り込み例外発生をJUnitで起こす方法を調べたので、備忘として残します。

■環境
Java 8
JUnit 4
## 概要
「テスト実行中スレッド」から「割り込み用スレッド」を起こします。
「割り込み用スレッド」から「テスト実行中スレッド」へ割り込みをかけます。

割り込みをかけるために、「割り込み用スレッド」には「テスト実行中スレッド」を教えておく必要があります
`Thread.currentThread()`で処理実行中のスレッドを取得することができます。

## コード
```Java:テスト対象コード
public class SampleClass {
    public void sample() throws InterruptedException {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw e;
        }
    }
}
```
```Java:テストコード
@Test
public void testSample() {
    try {
        // 割り込み用スレッドを定義する
        final class InterruptThread extends Thread {
            Thread targetThread = null;

            public InterruptThread(Thread thread) {
                targetThread = thread;
            }

            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                    targetThread.interrupt();
                } catch (InterruptedException e) {
                }
            }
        }

        // 割り込み用スレッドを開始する
        InterruptThread th = new InterruptThread(Thread.currentThread());
        th.start();

        // テスト対象コードを実行する
        SampleClass target = new SampleClass();
        target.sample();
        fail();
    } catch (InterruptedException e) {
        assertEquals(e.getMessage(), "sleep interrupted");
    }
}
```
[Android, Java]日数の差分を計算する便利メソッド


#やりたいこと

日数の差分を計算する便利メソッドを作りたい

引数として文字列の日付情報を受け取る
→　例えば```2018/01/01```と```2018/01/20```
→　引数として受け取った日付の差分を整数で返す

#実装内容

```.java

    public static int dateDiff(String dateFromStrig, String dateToString) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Date dateTo = null;
        Date dateFrom = null;

        // Date型に変換
        try {
            dateFrom = sdf.parse(dateFromStrig);
            dateTo = sdf.parse(dateToString);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }

        // 差分の日数を計算する
        long dateTimeTo = dateTo.getTime();
        long dateTimeFrom = dateFrom.getTime();
        long dayDiff = ( dateTimeTo - dateTimeFrom  ) / (1000 * 60 * 60 * 24 );

        System.out.println( "差分日数 : " + dayDiff );
        return (int) dayDiff;
    }

```
PuppeteerでinnerTextを使って要素を選択する

「"Accept" と書かれたボタンを押したい！」というような場面、あると思います。

CSSのセレクタでは対応できないので、XPathを使って指定します。

```js
const xpath = `//button[text() = "Accept"]`;
await page.waitForXPath(xpath);
await (await page.$x(xpath))[0].click();
```

`page.waitForXPath` は `page.waitForSelector` のXPath版です。

`page.$x` は `page.$$` のXPath版です。戻り値は `Promise<Array<ElementHandle>>`、つまり配列であることに注意しましょう。

## 参考資料

* [Puppeteer: Click on element with text \- Stack Overflow](https://stackoverflow.com/questions/47407791/puppeteer-click-on-element-with-text)
* [page\.waitForXPath - Puppeteer](https://pptr.dev/#?product=Puppeteer&show=api-pagewaitforxpathxpath-options)
* [page\.$x - Puppeteer](https://pptr.dev/#?product=Puppeteer&show=api-pagexexpression)
joinメソッドを解剖してみる

#joinメソッドが使えない実装があったため

開発中にjoinメソッドが利用できない要件があったため、joinと同じ動きをさせ、かつちょい改良したものを作りました。
いろいろ勉強になったので、メモります。というかメソッドに頼りすぎるのもよくないと痛感。

#配列内にある名前を羅列し、かつ間に入れる文字を交互にする
題名だとわかりづらいですが、要は

"鈴木","田中";"山本","神崎";"中村"
という形で、文字列をだすという要件でした。

初期は、

```ruby.rb

class Connector

  attr_accessor :delim

  def initialize
    @connector = []
  end

  def push(str)
    @connector.push(str)
  end

  def connect
    @connector.join(@delim)
  end

end

connector = Connector.new
connector.push("鈴木")
connector.push("田中")
connector.push("山本")
connector.delim = ","
puts connector.connect

#=> 鈴木,田中,山本
```

だったのですが、,と;を交互に出すとなるとjoinが利用できません。

```ruby.rb

class Connector

  attr_accessor :delim

  def initialize
    @connector = []
    @delim = []
  end

  def push(str)
    @connector.push(str)
  end

  def connect
    connected = ""
    @connector.each_with_index do |connector, index|
    index += 1
    connected += index.to_s
    connected += "."
      if index == @connector.size
        connected += connector
      else
        if index % 2 != 0
          connected += connector
          connected += @delim[0]
        elsif index % 2 == 0
          connected += connector
          connected += @delim[1]
        end
      end
    end
    connected
  end
end


connector = Connector.new
connector.push("鈴木")
connector.push("田中")
connector.push("山本")
connector.push("神崎")
connector.push("中村")
connector.delim.push(",")
connector.delim.push(";")
puts connector.connect

#=> 鈴木,田中;山本,神崎;中村
```


each_with_indexを利用して、配列の中に順番に入れていきました。
Microsoft Edgeでjavascript,cssファイルが文字化けする

# Microsoft EdgeでUTF-8が文字化けする

ヘッダーのcharsetに「UTF-8」を設定してある状態で、UTF-8で設定してあるjavascriptファイルとCSSファイルを読み込むと文字化けしてしまった。

chromeやfirefoxでは発生しなかった。

原因がわからなかったため、苦肉の策でHTML側から定義を送るように修正して対応

```sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
  <script src="test.js"></script>
  <script>
  var entry = {
     "1" : "テスト１",
     "2" : "テスト２"
  };
  $(document).ready(function(){
      testController.initialize(entry);
      $("#test").html( testController.getParam(1) );
  });
  </script>
</head>
<body>
        <p id="test"></p>
</body>
</html>

```

```test.js
var testController = function(){
    var returnObj = {};
    var entry = {};

    returnObj.initialize = function (entry_param){
        entry = entry_param;
    }
    returnObj.getParam = function (type){
        if(type in entry){
            return entry[type];
        }
        return "";
    }
}();

```

具体的なコードは少し違うが、パラメータを渡すようにして作った感じが伝われば良いと思います。

# 原因

調べると、同じ事例のケースがあり試してみたところ、確かに文字化けしたため、たぶん原因だと思われる。

https://qiita.com/KyoPeeee/items/34a5c212152d9e590277

対処方法は不明です。
標準入出力の操作方法(Obj-C)

## はじめに

「HackerRank」というプログラミングの問題を解くサイトがあります。
https://www.hackerrank.com

こちらのサイトでは「標準入力を取得する→問題を解く→解答結果を標準出力する」という流れで問題を解きます。

Objective-Cで標準入出力を操作する方法に手間取ったので、備忘録として残しておきます。

## 環境

- OS：macOS High Sierra 10.13.1
- Xcode：9.2

## プロジェクトの作成

標準入出力を扱うには、コマンドラインツールのプロジェクトを作成します。

Xcodeを起動し、「Create a new Xcode project」をクリックします。
<img width="836" alt="スクリーンショット_2018-07-04_0_05_59.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/138245/deee9951-e6eb-ec80-d79b-841c4d823071.jpeg">

[macOS]タブにある「Command Line Tool」を選択して[Next]ボタンをクリックします。
<img width="739" alt="スクリーンショット_2018-07-04_0_06_26.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/138245/8a0814de-778c-fcbd-c3bc-11a575aefe02.jpeg">

あとは通常のプロジェクトと同様にして作成します。

## 標準入出力の実装(Obj-C)

コマンドラインツールのプロジェクトはほぼ空のメインファイルのみ存在します。

```objc:main.m(before)
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}
```

`@autoreleasepool` 内を以下のように書き換えます。

```objc:main.m(after)
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 標準入力を取得する
        NSData *stdinData = [[NSFileHandle fileHandleWithStandardInput] availableData];
        NSString *stdinString = [[NSString alloc] initWithData:stdinData encoding:NSUTF8StringEncoding];
        
        // 標準入力を半角スペース区切りで配列に格納する
        NSArray *stdinArray = [stdinString componentsSeparatedByString:@" "];

        // TODO: 問題を解く
        // ここでは標準入力をそのまま解答とする
        NSArray *result = [stdinArray copy];

        // 解答を半角スペース区切りで文字列とする
        NSString *stdoutString = [result componentsJoinedByString:@" "];
        
        // 解答を標準出力する
        NSFileHandle *fileHandle = [NSFileHandle fileHandleWithStandardOutput];
        [fileHandle writeData:[stdoutString dataUsingEncoding:NSUTF8StringEncoding]];
        [fileHandle writeData:[@"\n" dataUsingEncoding:NSUTF8StringEncoding]];
        [fileHandle closeFile];
    }
    
    return 0;
}
```

## 標準入出力のデバッグ

通常のプロジェクトと同様、 <kbd>⌘R</kbd> でデバッグします。

標準入力を受け付けるまで待機するので、画面右下のコンソールに値を入力して <kbd>Enter</kbd> を押下します。
<img width="1012" alt="スクリーンショット_2018-07-04_0_28_45.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/138245/741f1a00-d107-e4b4-d89f-1855e3cfe2d8.jpeg">

今回は標準入力をそのまま標準出力しているため、標準入力と同じ値が太字で出力されます。
<img width="1013" alt="スクリーンショット_2018-07-04_0_30_55.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/138245/8df71d0a-4b6e-ab76-fbdd-c74326045697.jpeg">

## おわりに

今回作成したプロジェクトをGitHubで公開しました。
https://github.com/uhooi/StdinoutTemplates

実際の出力には `NSLog` を使うことがほとんどだと思いますし、標準入力は使わないので、このようなプログラミングサイトにしか使わないかもしれません。

## 参考リンク

- [[改編]Swiftを使ってPaizaの問題を解く - Qiita](https://qiita.com/hirothings/items/9e2d184349c7650d8bbe)
UbuntuとNginxでウェブサーバを立てる

# 筆者の環境
- Ubuntu16.04(KAGOYA VPS KVM)

# Nginxって何
- Apacheの代替となり得るWebサーバ

# Apacheとの違い
- C10Kをクリアしていて静的コンテンツを返すレスポンスが早い
  - C10Kとは・・・クライアント一万人接続問題の事
- イベント駆動
  - 一応Apacheでもイベント駆動には出来るがNginxの方が早い

「え？今時 ApacheはC10Kクリアしてないの？」と思いましたが、Apacheの武器はそこではない様です
下記ページでわかりやすく書かれていました。
> Nginxとは？Apacheとの違いについてエンジニアに聞いてみた
> https://academy.gmocloud.com/qa/20160616/2761

phpやCGIを使用した動的な処理をしたい場合はApache
速度や可能アクセス数を求められる場合にはNginx
といった使い方になりそうです。
どっちも使って、お互いのデメリットを埋める事も出来るそうです。

# 初期ページを表示するまでの手順
### 1. ポート解放とNginxのインストール、起動
```shell-session
$ apt update

ufw(ファイアウォール)をインストール
$ apt install ufw
インストール直後はufwはファイアウォールとして指定されないためufwを有効化
$ ufw enable
「このコマンドを実行するとssh接続が切れるかも知れませんがいいですか？」と聞かれるので y を入力してEnter

sshのポートを開く
これを行わないとssh切断したあと接続出来なくなってしまいます！
$ ufw allow 22

Nginxが使用するポートを開く
$ ufw allow 80

Nginxをインストールする
$ apt install nginx

Nginxが稼働している事を確認する
$ curl localhost
curlでウェブページにアクセスすると、そのページのhtmlの内容が帰って来ます

自分のIPアドレスを確認する
$ ifconfig | grep "inet addr:"
192.168.1.xや127.0.0.1といったIPアドレスが表示されると思います
これらはローカルIPや、グローバルIPと呼ばれます。
127.0.0.1は、ループバックアドレスと呼ばれ、自分自身を表すIPアドレスとなります。
```

### 2. 実際にページを表示してみる
同じネットワーク内の他のPCからウェブサーバを利用してみます。
ブラウザを起動し、先ほど確認したローカルIP、又はグローバルIPをアドレスバーに入力します。

このような画面が表示されると思います。
![スクリーンショット 2018-07-01 23.47.42.png](https://qiita-image-store.s3.amazonaws.com/0/266455/0dc1527c-4bac-7fc5-df5a-1f8bdfebda1a.png)

Nginxではこれが初期ページとして設定されています。

# ページを追加、変更する
### 1. ドキュメントルートを確認する
```shell-session
$ grep "root" -r /etc/nginx/ | grep "html"
/etc/nginx/sites-available/default:     root /var/www/html;
```
私の場合はこう表示されました。
Nginxのバージョンなどによってパスが違う様なので、このように調べるのが確実です。
どうやらページとなるhtmlファイルが保存されているのは　/var/www/html　ディレクトリの様です。
ここを ドキュメントルート と呼びます。
### 2. ページを追加する
```shell-session
ドキュメントルートに移動する
$ cd /var/www/html/
新しいページのファイルを作成する、アクセスする際のページ名は「test.html」とします
$ echo "Hello World!" > ./test.html
```

### 3. 実際にページを表示してみる
他のPCからページを
同じネットワーク内の他のPCからウェブサーバを利用してみます。
ブラウザを起動し、下記のようにアドレスバーに入力します。
```IPアドレス/test.html
```

この様な画面が表示されます。
![スクリーンショット 2018-07-02 0.07.53.png](https://qiita-image-store.s3.amazonaws.com/0/266455/a7714f81-4a06-a4f4-4d12-09b361f9d3d1.png)
以上となります。

Apacheが気になる方はこちら
> [UbuntuとApacheでウェブサーバを立てる - Qiita](https://qiita.com/noma3629/items/03742bad0f57a4f46b07)

---
今回の記事ではこちらにお世話になりました。
> 仮想マシン（Ubuntu）にWebサーバーNginxをインストールしブラウザからWEBページを表示確認する方法
> https://hajipro.com/vagrant/vagrant-ubuntu-nginx
VBScriptでUTF-8、改行コードLFのファイルを読み込む

## 1. はじめに
今回はVBSCriptで文字コードがUTF-8、改行コードがLFのテキストファイルを読み込む方法について説明したいと思います。
ポイントは`ADODB.Stream`を利用することです。このオブジェクトを利用すると文字コードや改行コードを指定してファイルを読み書きすることができます。

## 2. ソースコード

```vb
'*********************************************************************
' Purpose: filePathで指定されたファイルをUTF-8、改行コードLFで読み込み、
'          取得した行単位で動的配列のdatatListに設定する
' Inputs: filePath:対象となるファイルパス
'         datatList:１行のデータを格納する動的リスト（参照渡し）
' Returns: なし
'*********************************************************************
Sub ReadFile(ByVal filePath, ByRef datatList)
  Dim input
  Set input = CreateObject("ADODB.Stream")
  input.Open                   ' Stream オブジェクトを開く
  input.Type = 2               ' ★ポイント１
  input.Charset = "UTF-8"      ' ★ポイント２
  input.LineSeparator = 10     ' ★ポイント３
  input.LoadFromFile filePath  ' ★ポイント４

  ' 対象ファイルから1行ずつ読み込む
  Dim line
  Dim aryStrings
  Do Until input.EOS
    line = input.ReadText(-2)    ' ★ポイント５
    If InStr(1, line, "#") = 1 Then
      ' WScript.echo("COMMENT.")
    Else
      dataList.add line
    End If
  Loop

  ' Stream を閉じる
  input.Close
End Sub
```

**★ポイント１**
`Type`プロパティにテキストファイルとして開くため`2`を指定します。
この値は[StreamTypeEnum](https://msdn.microsoft.com/ja-jp/library/cc389884.aspx)で定義されています

> Stream オブジェクトに保存するデータの種類を表します。

| 定数 |	値 | 説明 |
|:----:|:---:|:---|
| adTypeBinary | 1 | バイナリ データを表します。|
| adTypeText | 2 | 既定値です。Charset で指定された文字セットにあるテキスト データを表します。|

**★ポイント２**
`Charset`プロパティに文字コードを指定します。今回は`UTF-8`を指定します。

**★ポイント３**
`LineSeparator`プロパティに改行コードをLFとするため`10`を指定します。
この値は[LineSeparatorsEnum](https://msdn.microsoft.com/ja-jp/library/cc389826.aspx)で定義されています。

> テキスト Stream オブジェクトの行区切りに使われている文字を表します。

| 定数 | 値 | 説明 |
|:---:|:---:|:-----|
| adCR | 13 | 改行復帰を示します。 |
| adCRLF | -1 | 既定値です。改行復帰行送りを示します。|
| adLF | 10 | 行送りを示します。|

どうして数がこんなに飛び飛びなんでしょうか、ＭＳさん謎です。

**★ポイント４**
`LoadFromFile`メソッドの引数に対象ファイルのファイルパスを指定します。

**★ポイント５**
`ReadText`メソッドでファイルのデータを読み込みます。メソッドの引数には１行づつ読み込むため`-2`を指定します。
この値は[StreamReadEnum](https://msdn.microsoft.com/ja-jp/library/cc389881.aspx)で定義されています。

> Stream オブジェクトから、ストリーム全体、または次の行を読み取るかどうかを表します。

| 定数 | 値 | 説明 |
|:----:|:---:|:----|
| adReadAll | -1 | 既定値です。現在の位置から EOS マーカー方向に、すべてのバイトをストリームから読み取ります。これは、バイナリ ストリームに唯一有効な StreamReadEnum 値です (Type は adTypeBinary)。|
| adReadLine | -2 | ストリームから次の行を読み取ります (LineSeparator プロパティで指定)。|

## 3. さいごに
今回はVBSCriptで文字コードがUTF-8、改行コードがLFのテキストファイルを読み込む方法について説明しました。
`ADODB.Stream`を利用すれば可能なことが分かったかと思います。
使ってみて分かったのは定数値に順序性がなくていまいちって感じでした。~~（なぜですかね？ＭＳさん）~~
【Go】A Tour of Go 2日目


タダです。

A Tour of Go 2日目で学んだことを記録していきます。

# 定数
変数宣言のvarをconstに変えると定数になる

```
func main() {
	const Hello string = "hello"
	Hello = "bye" // Helloに代入はできない
}
```

# ポインタ
ポインタ型の変数は、型の前に*をつける
アドレスは変数の前に&を付ける

```
func callByValue(i int) {
    i = 20 // 値を上書きする
}

func callByRef(i *int) {
    *i = 20 // 参照先を上書きする
}

func main() {
    var i int = 10
    callByValue(i) // 値を渡す
    fmt.Println(i) // 10
    callByRef(&i) // アドレスを渡す
    fmt.Println(i) // 20
}
```

# 関数
関数は `func` で始まる
引数も戻り値もない場合は次のように宣言する

```
func hello() {
	fmt.Println("hello")
}

func main() {
	hello()
}
```

引数がある場合は変数と型を宣言する

```
func sum(i, j int) {
	fmt.Println(i + j)
}

func main() {
	sum(1,2)
}
```

エラーを返す場合は、以下のようにする
自作のエラーは、errorsパッケージを用いて作れる

```
package main

import (
    "errors"
    "fmt"
    "log"
)

func div(i, j int) (int, error) {
    if j == 0 {
        // 自作のエラーを返す
        return 0, errors.New("divied by zero")
    }
    return i / j, nil
}

func main() {
    n, err := div(10, 0)
    if err != nil {
        // エラーを出力しプログラムを終了する
        log.Fatal(err)
    }
    fmt.Println(n)
}
```

# マップ
マップは、キーバリューの対応で保存するデータ構造

```
var month map[int]string = map[int]string{}

month[1] = "January"
month[1] = "February"
fmt.Println(month) //map[1:Junuary 2:February]
```

# 配列/スライス
Goの配列は固定長
可変長配列はスライス

配列は以下のように表現する

```
var arr[4]string

arr[0] = "a"
arr[1] = "b"
arr[2] = "c"
arr[3] = "d"

fmt.Println(arr[0]) // aと表示される
```

stringのスライスは次のように宣言する

```
var s[]string

s := []string{"a", "b", "c", "d"}
fmt.Println(s[0]) // "a"
```

スライスに対する操作には、append()でスライスの末尾に要素を追加、rangeでは配列やすらいに格納された値を先頭から順番に処理する

```
package main

import "fmt"

type Vertex struct {
	Lat, Long float64
}

var m = map[string]Vertex{
	"Bell Labs": {40.68433, -74.39967},
	"Google":    {37.4202, -122.08408},
}

func main() {
	fmt.Println(m) //map[Bell Labs:{40.68433 -74.39967} Google:{37.4202 -122.08408}]
}
```
pythonで多次元連想配列を扱う

pythonで多次元連想配列を実装する備忘録です。

# やりたいこと

例えばPerlだと以下のように簡単にハッシュ(pythonだと辞書)の多次元連想配列ができます。

```perl
#!/usr/bin/perl

my %hash = {};
$hash{'a'}{'b'}{'c'} = 'd';
$hash{'e'}{'f'} = 'g';

print $hash{'a'}{'b'}{'c'}, "\n";
print $hash{'e'}{'f'}, "\n";
```

これをpythonでやろうとすると以下のようにエラーが発生します。

```python
#!/usr/bin/env python3

hash = {}
hash['a']['b']['c'] = 'd'

print(hash)
```

```shell-session
$ ./example.py
Traceback (most recent call last):
  File "./example.py", line 4, in <module>
    hash['a']['b']['c'] = 'd'
KeyError: 'a'
```

Perlだと簡単にできるのにpythonだと一手間加えないとできなかったので備忘録として書いておきます。

# 多次元連想配列のやり方

`defaultdict` を使ってやるやり方が簡単かと思います。

```python
#!/usr/bin/env python3
from collections import defaultdict

nested_dict = lambda: defaultdict(nested_dict)
hash = nested_dict()

hash['a']['b']['c'] = 'd'
hash['e']['f'] = 'g'

print(hash['a']['b']['c'])
print(hash['e']['f'])
```

これで、やりたいことが出来ました :)
データベースの保存データを暗号化する3つの手法

# はじめに
今回は、セキュリティアタックへの対策のため、データベースの保存データを暗号化する方法を調査したので、ざっと紹介したいと思います。
主にクラウドインフラ上に構築する、商用WEBアプリケーションへの導入という観点でまとめています。

# データ暗号化の方針
１．ストレージの暗号化
２．アプリケーション層で暗号化し、暗号化データを保存
３．データベースの機能で透過的な暗号化

# 1．ストレージの暗号化
## 概要
データベースの保存データだけでなく、ストレージやシステムそのものを暗号化する手法。

## プロダクト例
・cryptsetup / LUKS(Linux Unified Key Setup)など
・Amazon S3のストレージ暗号化など
・その他

## 動作概要

### 暗号化
暗号化前のデータがアプリケーションからOSに渡される
↓
事前に決められたキーによりデータが暗号化される
↓
暗号化されたデータがストレージに書き込まれる

### 復号
暗号化されたストレージ上のデータがOSに読み込まれる
↓
事前に決められたキーによりデータが復号される
↓
復号されたデータがOSからアプリケーションに渡される

## OS側の権限奪取への耐性
ストレージへのアクセス権と同時に、暗号化キーや暗号化パスワードが盗まれた場合、データ盗難が可能と考えられる。
稼働中のシステムの場合、常時データを参照する必要があるため、アプリケーションサーバの権限を奪取されれば、データ盗難が可能と考えられる。

## データベース側の権限奪取への耐性
OS側で透過的に復号されるため、データ盗難が可能と考えられる。

## SQLインジェクションへの耐性
OS側で透過的に復号されるため、データ盗難が可能と考えられる。

## 物理的なストレージ盗難への耐性
生の状態の暗号化キーや暗号化パスワードが含まれていなければ、データ盗難の対策になると考えられる。

## 寸評
「クラウドインフラ上に構築する商用サービス」という観点の場合、ストレージの暗号化に対応しているインフラ自体が少ない。
分かりやすい選択肢としては、AWS（S3のストレージ暗号化）になりそう。

# 2．アプリケーション層で暗号化し、暗号化データを保存

## 概要
アプリケーション層（Javaなどのサーバサイドプログラム）で暗号化をし、データベースに渡す手法。
復号キーは、データベースサーバとは切り離されたWebサーバに持つものと想定。
データベース側のSQL関数で暗号化することもできるが、実質的にはこの手法と同じものと考える。

## 動作概要

### 暗号化
アプリケーション上で、事前に決められたキーによりデータが暗号化される
↓
暗号化されたデータがデータベースエンジンに渡される
↓
暗号化されたデータがストレージに書き込まれる

### 復号
暗号化されたストレージ上のデータがデータベースエンジンに読み込まれる
↓
暗号化されたデータがアプリケーションに渡される
↓
事前に決められたキーによりデータが復号される

## プロダクト例
・プログラミング言語側のencrypt関数など
・opensslライブラリなど

## OS側の権限奪取への耐性
Webサーバへの直接的な侵入で考えると、暗号化キーが漏洩する可能性が高いため、データ盗難が可能な確率が高いと考えられる。
※暗号化キーの管理自体にセキュリティ対策がされていれば、データ盗難の対策となる可能性がある。（データベースのレコード毎に暗号化キーを変える。キーの生成ロジック自体を隠蔽するなど）
データベースサーバへの直接的な侵入で考えると、暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。

## データベース側の権限奪取への耐性
暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。
しかしながら、データベースの権限が奪取され、データベースエンジンにアクセス可能な時点で、Webサーバ側の権限が奪取されている可能性が高いはず。

## SQLインジェクションへの耐性
WebアプリケーションにSQLインジェクションの脆弱性があった場合、暗号化キーが漏洩しておらず、また、復号化を経由しないアタックだった場合は、データ盗難の対策になると考えられる。
※テーブルやレコード毎に暗号化キーを変えておくと、部分的な暗号化キー漏洩のリスクヘッジになると考えられる。

## 物理的なストレージ盗難への耐性
暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。

## 寸評
Webアプリケーションレベルでは、有効な対策と考えられる。（SELECT文での検索などをするためには実装上の工夫が必要だが）
暗号化キーをどのような単位で、どのように管理するかが重要になってくる。


# 3．データベースの機能で透過的な暗号化

## 概要
データベースエンジン側の機能により、透過的にデータの暗号化を行う手法。
※データベース側のログデータに生のデータが保存されてしまうことがあるので、利用する場合は、レプリケーション機構やエラー機構などのログに生データが残っていないか要注意。

## 動作概要

### 暗号化
生データがアプリケーションからデータベースエンジンに渡される
↓
事前に決められたキーによりデータが暗号化される
↓
暗号化されたデータがストレージに書き込まれる（一部のログなどは生のまま）

### 復号
暗号化されたストレージ上のデータがデータベースエンジンに読み込まれる
↓
事前に決められたキーによりデータが復号される
↓
生データがアプリケーションに渡される

## プロダクト例
・各データベースエンジンの透過的データ暗号化機能（TDE）

## OS側の権限奪取への耐性
Webサーバ、データベースサーバのどちらに侵入されても、データ盗難が可能と考えられる。

## データベース側の権限奪取への耐性
データ盗難が可能と考えられる。

## SQLインジェクションへの耐性
データ盗難が可能と考えられる。

## 物理的なストレージ盗難への耐性
暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。

## 寸評
SELECT文での検索が透過的に行われるため便利だが、セキュリティ対策できる余地が限られてしまう。
また、各種ログにデータが残りやすいため、その点も不安がある。

# まとめ
こんな感じで、データベースに保存するデータを暗号化する方法をまとめてみました。
少し軸が替わりますが、データ漏洩対策の観点としては、データベースの暗号化以外に、
「中間のデータ（メモリ上のデータやキャッシュデータ）」
「各種ログデータ」
への注意も重要になります。

個人的には、
「３．データベースの機能で透過的な暗号化」のデータベース全体への対策をベースにしつつ、
秘匿性の高い個人情報などは、アプリケーションでの実装の工夫も含めた、「２．アプリケーション層で暗号化し、暗号化データを保存」
を組み合わせる形でいいのではないかと思いました。
このテーマについては、まだまだ検証・検討すべきことが多いと思います。

お気づきの点がありましたらアドバイス頂ければと思います。