OmniAICreator/Qiita-1.07M huggingface dataset:
Spring MVCでMySQLにJDBC Templateを使って接続してみた

# はじめに

- [前回](https://qiita.com/neriai/items/6b27fba2aa1af7b60bb8)の環境を元に、データベースへの接続の実装をしてみました。

# Mavenから依存関係の追加

pom.xmlを開き、<dependencies>内の最終行に追加してください。

## MySQL JDBCコネクタの追加

```xml
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.45</version>
</dependency>
```

## Spring JDBCの追加

```xml	
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${org.springframework-version}</version>
</dependency>
```

## クリーンアップとインストール

1. プロジェクトを右クリックし、「実行 > Maven clean」を実行します。
2. 同じく、「実行 > Maven install」を実行します。

# MySQLのセットアップ

## MySQLのインストール

```
brew install mysql
```

## MySQLの起動

```
mysql.server start
```

## データベースの作成

```
CREATE DATABASE sandbox DEFAULT CHARACTER SET utf8;
```

## テーブルの作成

```
create table users(id int, name varchar(20));
```

## データの投入

適当にInsertしておいてください。

# JDBCの接続設定

root-context.xmlを開き、<beans>内の最終行に追加してください。

## 接続設定

```xml
<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName">
        <value>com.mysql.jdbc.Driver</value>
    </property>
    <property name="url">
        <value>jdbc:mysql://127.0.0.1:3306/sandbox</value>
    </property>
    <property name="username">
        <value>root</value>
    </property>
    <property name="password">
        <value></value>
    </property>
</bean>
```

## JDBC Templateの設定

```xml
<bean class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSource" />
</bean>
```

# 接続確認プログラムの実装

## コントローラーの実装

```java:HomeController.java
package com.sandbox.app;

import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
 
		List<Map<String, Object>> list = jdbcTemplate.queryForList("SELECT * FROM users");
 
		model.addAttribute("data", list.get(0).get("name") );
	
		return "home";
	}
}
```


## ビューの実装

```jsp:home.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
	<head>
		<title>Home</title>
	</head>
	<body>
	<h1>
		Hello world!  
	</h1>
	<p>  DB's data is ${data}. </p>
	</body>
</html>
```

## Tomcatの起動

プロジェクトを右クリックし、「実行 > サーバーで実行」を実行します。以下のようなページが表示されれば成功です。

![FireShot Capture 066 - Home - http___localhost_8080_app_.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/e1f5300f-2774-9d08-4b05-495edfedbbd6.jpeg)

# まとめ

- JPAとの違いってなんだろう？
- 実践的にはORMライブラリを使うのだろうか？
Dockerで自己証明書付きFTPSサーバを起動する

Dockerで自己証明書付きFTPSサーバを起動するメモ

## Dockerfileの記述

```dockerfile
FROM stilliard/pure-ftpd

RUN mkdir -p /etc/ssl/private && \
  openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 2048 && \
  openssl req -subj '/CN=ftps.local/O=DOCKER/C=JP' -x509 -nodes -newkey rsa:2048 -sha256 -keyout \
    /etc/ssl/private/pure-ftpd.pem \
    -out /etc/ssl/private/pure-ftpd.pem && \
  chmod 600 /etc/ssl/private/*.pem

CMD /run.sh -c 5 -C 5 -l puredb:/etc/pure-ftpd/pureftpd.pdb -E -j -R -P $PUBLICHOST -p 30000:30009 -s -A -j -Z -H -4 -E -R -G -X -x
```

## ビルド

```bash
docker build -t=ftpd .
```

## 起動

```bash
docker run -d --name ftpd \
	-p 21:21 \
	-p 30000-30009:30000-30009 \
	-e "PUBLICHOST=localhost" \
    -e "ADDED_FLAGS=--tls=2" \
	ftpd
```

## ユーザ追加


```bash
docker exec -it ftpd /bin/bash
```

```bash
pure-pw useradd {user_name} -f /etc/pure-ftpd/passwd/pureftpd.passwd -m -u ftpuser -d /home/ftpusers/{user_name}
```
プログラミング言語論とか

この記事は[みす裏 Advent Calendar 2017](https://adventar.org/calendars/2443)５日目のために書かれました。

友達に「意味論、意味論ってなんだ」と聞かれたので、自分に分かる範囲でなるべく簡単に説明してみよう。読者としては「プログラミングはしたことあるけど、プログラミング言語論って何？」という人を想定している。なので、「IMPとかλ算法は分かるよ、でもSystem F（とその派生）はちょっと自信ないかな……」って人は読んでも無駄です。暇で暇で仕方ないなら、この記事のどこに間違いがあるか探してみよう。

この記事を読むことで、この分野の人たちってこんなことしてるんだなあとか、もしくは面白そうだから少し勉強してみようかな、とか思ってもらえれば成功。よくわからん！　ってなったら私の失敗なのでそういう時はコメントに書いておくと優しい人が教えてくれるかも。

----

# 言語＝構文＋意味

プログラミング言語をしっかりと定義するときには、まず**構文**、次に**意味**が与えられる。どのように構文を決めるかを構文論、どのように意味を決めるかを意味論という。これでは知ってる人にしか伝わらないので、身近な例で説明しよう。次の式は計算するといくつになるだろうか？

```
(1) 1 + 2 × 3
```

答えは「7」だ。では、次の式はどうだろう。

```
(2) 1 + × 2 3
```

これには答えられない。そもそも「正しい」式ではない。では、次の式は？

```
(3) 1 + 2 ^ 3
```

これは「9」と答える人もいれば、人によっては「0」と答えるかもしれない。

私たちが(1)に「7」と答えられるのは、「数式」の構文と意味についての共通理解があるからだ。つまり、`+`は左側の項と右側の項の和を計算し、`×`は積を計算するが`+`より優先順位が高いという認識がある。(2)では、私たちの考える数式の体を成していない。これは、「`+`と`×`の両側には項がある」とか、「数字が連続することはない」といった構文の規則にしたがっていないからである。(3)では`^`が２項演算であると予想がつけば構文は想像できる。しかし、`^`の意味（＝`^`がどのような演算をするのか）については色々な流儀がある。

## どのように議論するのか？

ここからは少し難しいかも？

構文論は構文を（たいていの場合帰納的に）定義する。その書き方にはいくつかあるが、[BNF（Backus-Naur form）](https://ja.wikipedia.org/wiki/バッカス・ナウア記法)が使われることが多い。数式の例でいえばこんな感じだ。`(数字)`と書いたところは`0`、`1`、...のような整数を表す文字が入ると思ってほしい。

```
E ::= T | E + E
T ::= (数字) | T × T
```

この構文規則によって`1 + 2 × 3`が生成されるので、`1 + 2 × 3`は正しい構文を持つと言える。一方、`1 + × 2 3`は生成できないので正しくない。

意味論は正しい構文を持つ項が何を表しているかを定義する。意味論の書き方には横線を使った記法が使われることが多い。横線の上には前提をいくつか並べ、下にはそれらの前提から導ける結論を書く。上に何もないときはそれが自明であるという意味になる。

```
前提1 前提2 前提3 ...
-------------------
       結論
```

ここで、ある式`E`が計算の結果`n`になることを`E → n`と書くことにすると、上で与えた構文に対応する数式の意味は次のようになる。

```

--------------
(数字) → (数値)

  E1 → m   E2 → n
--------------------
E1 + E2 → （mとnの和）

  T1 → m   T2 → n
--------------------
T1 × T2 → （mとnの積）
```

一番上は`13869948`と書いてあったらそれはそのまま13869948という整数の１つを表すということである。2番目は`+`の左側と右側がそれぞれ`m`と`n`と計算できるなら、それらの和が計算できるということを表している。3番目も同様。

初めはもう少しプログラミング言語らしく`if-then-else`を定義しようとか思ってたけど、長くなってきたからやめておこう。調べればいくらでも出てくるし。

# 何が嬉しいんだ？

「よくわからないけど、そんなことしなくてもプログラミングはできるし、一体何が嬉しいの？」というのが普通の感想だろう。実際、現実に使われているプログラミング言語は非常に複雑で、それを上手く扱える理論を構築することは不可能に近い。

しかし例えば、現実には直線や円、正三角形などの理想的な図形は存在しないが、幾何学は図形について多くの性質を証明しているし、それらは現実に生かされてもいる。それと同じく、簡略化されていてもこのように定義を与えることで数学的に厳密な議論が可能になり、**プログラミング言語が満たす性質を証明する**ことができるようになる。このことはソフトウェアの形式的検証（型理論、モデル検査など）では大いに活用され、堅牢なソフトウェアを作るために利用されている。

----

本当はもっとくだらない記事を書きたいんだけど、投稿する場がなくて……
カラムにnullが含まれるなら結果がnullになるmax()

SQLの`max()`関数は、対象カラムの`null`でない値の最大値を集約値として返します。

ところが、**対象に`null`が含まれるなら`null`を結果にしたい**という場面と少なからず出会います。
よくあるのは、有効期限。

- 「無期限」を`null`の有効期限として表現している
- 期限レコードが複数ありそのうち最も遅い日時を取得したい

ありそうな要件です。もちろん「無期限」レコードが含まれているなら結果も「無期限」になってほしいので、表題通り「カラムに`null`が含まれるなら結果が`null`になる`max()`」パターンそのものですね。

さてこの集約、一発で式が思い浮かぶでしょうか？
あれっ簡単かと思いきやややこしいぞ。
副問い合わせとかしないと無理？

心配ありません。副問い合わせなしでそんなに長ったらしくもならず書き下ろせます。
まずは二通り、Oracle専用の書き方と標準SQLだけによる書き方をご紹介します。対象カラムの名前は`end_date`とします。

Oracle専用
---
Oracleは`keep`構文により、指定ソート条件で先頭群になるレコードか末尾群になるレコードだけを集約関数の対象にできます。

```sql
max(end_date) keep (dense_rank last order by end_date nulls last)
```

この式は「`null`が最後に来るように`end_date`で昇順ソートし、その末尾群についての`max(end_date)`」と書いてあります。求めていた通りの式ですね。

標準SQLのみで
---
標準SQLのみでもそれほどややこしい式にはなりません。

```sql
case when count(case when end_date is null then 1 end) = 0 then max(end_date) end
```

「`end_date`が`null`であるレコードを数え、それが0であるなら`max(end_date)`（そうでなければ`null`）」
と書いてあります。こちらも同仕様です。

Oracleユーザーならどちらを選びますか？
---
RDBのOSS移行も近い視野に入れているプロダクトであるなら可搬性から標準SQLのものを採用するしかありません。
そうでない場合。
一時的な問い合わせだったり、アプリコードの寿命のうちにRDB移行が視野に入らないような開発条件であるならOracle専用の前者を選びたいと私は考えます。

ここで強引めにエムスリーアドベントカレンダーというテーマに寄せていくのですが、私自身はコードレビュー文化のない職場だった前職からコードレビュー文化のあるエムスリーに来て、今さらながら“見てもらえるコード”をいかに書くか模索中です。

その目で二つの式を見比べてみます。

前者は、`order by end_date nulls last`とあり、「`null`はどんな日付よりも遅いのだ」という意図をそのまま書き下ろしています。

それに比べると後者は「`null`が含まれなければ`max()`」という条件式ですから意図を理解するのにワンステップ思考を要求する上、その「`null`が含まれなければ」も実際には「`null`であるレコードを数え、それが0であるなら」と迂遠な書き方になるのでもうワンステップ思考を要求されます。

コードの意図を理解するための余計なステップをレビュアーにも将来の改修者にも踏ませたくないと考えると、使わずに済ませられる方言であっても使えるときには使いたいとなるのです。エムスリーに来るまではあまりしてこなかった発想だったかなと思っています。
Project Euler Q34 【桁の階乗】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
$145$は面白い数である. $1! + 4! + 5! = 1 + 24 + 120 = 145$となる.

各桁の数の階乗の和が自分自身と一致するような数の和を求めよ.

注: $1! = 1$ と $2! = 2$ は総和に含めてはならない.

## 解答

> n>=7で10**n -1 > 9!*nなので、最高でも9!*7までの範囲を検索すれば十分である。

引用元：[Project Euler 34 - Qiita](https://qiita.com/cof/items/e00a3a85d486f5cc507b)

いつもこの辺の「どこまでやれば十分なのか」がよく分からない。
$999999 < 9! * 6 = 2177280$、$9999999 > 9! * 7 = 2540160$なので、
$2540160$までやれば十分か。

```bash
seq 3 2540160 |
awk -v FS= '{printf $0" ";s=0;for(i=1;i<=NF;i++){x=1;for(j=1;j<=$i;j++){x*=j};s+=x};print s}' |
awk '$1==$2{s+=$1}END{print s}'
40730
```

## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/034.html
Python2.7+PyQt4でメインウィンドウからダイアログボックスを表示させる メモ

#メインウィンドウからダイアログボックスを表示させる

メインウィンドウもダイアログボックスも最初にクラス宣言する。


```python
#!/usr/bin/python
# -*- coding: utf-8 -*-

from PyQt4 import QtGui
from PyQt4 import QtCore
import sys

import mainwindow_ui #QtDesignで作成したメインウィンドウ ボタンを1個配置
import dialogbox_ui #QtDesignで作成したダイアログボックス

class DialogBox(QtGui.QDialog, dialogbox_ui.Ui_Dialog):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
    
class MainWindow(QtGui.QMainWindow, mainwindow_ui.Ui_MainWindow):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(lambda: self.pushButtonAction())

    def pushButtonAction(self): #ボタンをクリックするとダイアログボックスが表示する
        self.dia = DialogBox()
        self.dia.exec_()
        


def main():
    app = QtGui.QApplication(sys.argv)
    form = MainWindow()
    form.show()
    app.exec_()



if __name__ == '__main__':
    main()           
```
ポアソン分布とガンマ分布のイケナイ関係


[yutanihilationさんの記事](http://notchained.hatenablog.com/entry/2017/12/02/091230)でアドベントカレンダーに空きがあるのを知ったので登録してみました．
タイトルはteramonagiさんリスペクトです([指数分布とポアソン分布のイケナイ関係](https://www.slideshare.net/teramonagi/ss-11296227))．


# Rでポアソン過程の観測値から期待値を密度推定したい

```r
plot(density(rpois(100, 1.5)))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/149890/3d03bc06-8d69-25ea-b35a-a7da64b4cace.png)

orz...


## 問: ポアソン過程で得られた観測値がxの時，期待値λの分布は何分布？

## 答: 形状母数k = x + 1， 尺度母数θ = 1のガンマ分布

## 証明

ポアソン分布は期待値λ(> 0)の事象がX回起きる確率を教えてくれる離散確率分布で確率質量関数は以下の通り．

$$
Poisson(X) = \lambda ^ X e ^ {-\lambda} / X!
$$

従って，ある事象がx回(0以上の整数)起きた時の期待値の確率密度関数は

$$
P(\lambda) = \lambda ^ x e ^ {-\lambda} / x!
$$

となる．

ガンマ分布の確率密度関数は形状母数をk，尺度母数をθとして

$$
Gamma(X) = X ^ {k - 1} e ^ {-X/\theta} / \Gamma(k)
$$

と表される．
ここでΓはガンマ関数．
X = λ，k = x + 1, θ = 1の時，

$$
Gamma(\lambda) = \lambda ^ x e ^ {-\lambda} / \Gamma(x + 1)
$$

となる．
xは0以上の整数より，x+1は自然数だから，

$$
\Gamma(x + 1) = x!
$$

よって

$$
Gamma(\lambda) = \lambda ^ x e ^ {-\lambda} / x!
$$

となってP(λ)と一致する．

## Rで確認

例えばある事象を3回観察した時の期待値の分布は

```r
library(dplyr)
library(ggplot2)

x <- data.frame(
  X = 3,
  lambda = seq(0, 15, 0.1)
) %>%
  mutate(
    p = unlist(Map(dpois, x = X, lambda = lambda)),
    gamma = dgamma(lambda, shape = X + 1, rate = 1)
  )

ggplot(x, aes(x = lambda)) +
  geom_line(aes(y = p), lwd = 2, color = 'blue') + #青線
  geom_line(aes(y = gamma), lwd = 2, lty = 2, color = 'red') #赤線
```

ポアソン分布の確率質量関数から導出した期待値の分布(青線)と，ガンマ分布(赤線)が一致

![image.png](https://qiita-image-store.s3.amazonaws.com/0/149890/22e64800-9b48-e623-0e29-1c6ddd695c5a.png)

# 応用例

## 期待値の密度推定

期待値1のポアソン分布に基く乱数を100個生成した時，

- ヒストグラム(ビン幅1)
- カーネル密度(青点線)
- 混合ガンマ分布(赤線)

により期待値の分布を見てみる．

```r
set.seed(123) # 乱数固定
X <- rpois(100, 1) # ポアソン分布に従う乱数生成
lambda <- seq(0, 20, 0.1) # ポアソン分布の期待値の密度の推定範囲を指定
X_dens <- X %>% # 混合分布を生成
  setNames(nm = .) %>%
  lapply(function(X) {
    data.frame(
      X = X,
      lambda = lambda,
      p = dgamma(lambda, X + 1)
    )
  }) %>%
  bind_rows() %>%
  group_by(lambda) %>%
  summarise(p = mean(p)) %>%
  mutate(X = NA_integer_)


ggplot(
  data.frame(X) %>%
    mutate(y = 1 / n()), 
  aes(x = X)
) +
  geom_col(aes(y = y), fill = NA, color = 'gray50') + # 乱数のヒストグラム
  geom_density(color = 'blue', lty = 2) + # 乱数の密度分布
  geom_line(data = X_dens, aes(x = lambda, y = p), color = 'red') + # 期待値の密度分布
  scale_x_continuous(breaks = -2:10, limits = c(-2, 10))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/149890/a821801d-24cd-00f2-b515-0fe7c9379535.png)

カーネル密度を使うと，本来あり得ない負の回数が起きる確率が推定されてしまう．
乱数が離散値であるため，マルチモーダルな密度分布が得られてしまう．
こういった問題を混合ガンマ分布では回避できる．

#感想

負の二項分布がポアソン分布の期待値がガンマ分布に従う時の分布に相当するから，データの過分散対策に使おうとか，ベイジアンでMCMCする時にポアソン分布の期待値の事前分布にガンマ分布を使おうっていうのはこの辺から来てるのかな……？
天下りが過ぎて，うまくいきそうなのはわかるけどなぜかわからなかったけど，納得できた．

また，ガンマ分布はWikipediaなんか見ても，どういう時に使うかは書いてあるけど，どういう時に起きるかは書いていなくて，一体ナニモノぞといった感じがしてしまう．
非負で連続値をとる確率過程はガンマ分布で! なんて言われても……．
まさしくポアソン分布の期待値は非負の連続値をとるのだけれども，実際これがガンマ分布に従うことが今回わかって嬉しい．

あと，混合分布の厳密(？)な作りかたがよくわからず，積分値が1になるよう，混合する各分布におけるxの確率密度の平均を混合分布のxにおける確率密度としてプロットしてみたけどあっているのだろうか……．
@Getabakoの投稿目次

[Scratch編](https://qiita.com/Getabako/items/fbb7d8b9ba7681b7191a)

[Unity編](https://qiita.com/Getabako/items/55daf89bbd2e0998a16c)

[blender編](https://qiita.com/Getabako/items/6c2364f07458351d4370)

[ゲタバコ先生のホームページ遊びに来てね♪](http://getabako.wp.xdomain.jp/)
D3.jsで埼玉県地図を描くときの基本（topojson）

[D3.jsで日本地図を描くときの基本(geojson)](https://qiita.com/sand/items/422d4fab77ea8f69dfdf "D3.jsで日本地図を描くときの基本(geojson)")
[D3.jsで埼玉県地図を描くときの基本（topojson)](https://qiita.com/sand/items/e8c82f1d61ca4e7bdfb7 "D3.jsで埼玉県地図を描くときの基本（topojson)")
[D3.jsで埼玉県の地図上に市町村ラベルを描く](https://qiita.com/sand/items/e11e597d88ee6745c22f "D3.jsで埼玉県の地図上に市町村ラベルを描く")

　前回はGeoJSONフォーマットのデータを使って、D3.js(v4)で日本地図を描く方法を紹介しました。今回はTopoJSONフォーマットのデータを使って地図を描く方法を紹介したいと思います。同じ日本地図ではアレなので、今回は埼玉県の地図を描くことにします。


 今回作成した埼玉県地図
https://s3-ap-northeast-1.amazonaws.com/kuki-app-bucket/japanmap/saitama.html

# １．TopoJSONについて
　GeoJSONは経度緯度の配列をデータとして持っていて、ポイントやライン、ポリゴンを描くことができました。TopoJSONはアーク（弧線）の配列を持っています。しかも境界線のデータを共有するとかして、GeoJSONに比べてデータ量が格段に少なくなります。私が持っている埼玉県のデータで言えば、TopoJSONが422KBで、GeoJSONが3,449KBになります。全然違いますね。

　さてTopoJSONデータフォーマットに対して、そのままではd3.geoPath()を適用できません。D3.jsで地図を描くにはGeoJSONフォーマットに変換する必要があり、そのためにtopojson.jsライブラリを読み込みます。

　以上の注意点を除けば、GeoJSONの時と全く同じプログラムが適用されます。

# ２．D3.jsのプログラム

　念のためにソースコードを掲載します。TopoJSON=>GeoJSO変換、以外は前回の日本地図のソースと同じです。

```html:
<!doctype html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.0/d3.min.js" type="text/JavaScript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js"></script>
  </head>
  <body>
    <svg></svg>
    <script>
      var width = 1200,
          height = 800;
      var scale = 40000;
      d3.json("./saitama.topojson", createMap);
      
      function createMap(topoSaitama) {
        var geoSaitama = topojson.feature(topoSaitama, topoSaitama.objects[11]);　//TopoJSON=>GeoJSO変換
        var aProjection = d3.geoMercator()
            .center([ 139.5, 35.9 ])
            .translate([width/2, height/2])
            .scale(scale);
        var geoPath = d3.geoPath().projection(aProjection);
        var svg = d3.select("svg").attr("width",width).attr("height",height);

        //マップ描画
        var map = svg.selectAll("path").data(geoSaitama.features)
          .enter()
          .append("path")
            .attr("d", geoPath)
            .style("stroke", "#ffffff")
            .style("stroke-width", 0.1)
            .style("fill", "#5EAFC6");

        //ズームイベント設定    
        var zoom = d3.zoom().on('zoom', function(){
            aProjection.scale(scale * d3.event.transform.k);
            map.attr('d', geoPath);
        });
        svg.call(zoom);

        //ドラッグイベント設定
        var drag = d3.drag().on('drag', function(){
            var tl = aProjection.translate();
            aProjection.translate([tl[0] + d3.event.dx, tl[1] + d3.event.dy]);
            map.attr('d', geoPath);
        });
        map.call(drag);
      }
    </script>
  </body>
</html>
```

　まずtopojson.jsライブラリを読み込みます。

```html
    <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js"></script>
```

 TopJSONのデータをGeoJSONのフォーマットに変換します。

```js
        var geoSaitama = topojson.feature(topoSaitama, topoSaitama.objects[11]);　//TopoJSON=>GeoJSO変換
```


　それ以外は、前回のプログラムと全く同じです。
Scratch編目次

[主人公の表示、主人公の横移動](https://qiita.com/Getabako/items/4a0aa08db9b0642f313c)

[重力と主人公のジャンプ](https://qiita.com/Getabako/items/1d4932a2ffd7b01242f1)

[ステージの横スクロール](https://qiita.com/Getabako/items/6bfb0830f0f12058415b)

[弾の発射](https://qiita.com/Getabako/items/5fde5a9feac587df8dfe)

[敵キャラの移動、ダメージ処理、重力調整](https://qiita.com/Getabako/items/1ea102134d0c1bf2f97d)

[主人公の体力ゲージとダメージ処理](https://qiita.com/Getabako/items/f476f80004f0f3defbbd)

[ゲームオーバー処理&クリア処理](https://qiita.com/Getabako/items/a29160d3420c01d79b99)

[アニメーションの遷移](https://qiita.com/Getabako/items/49e78133a78f66f8634a)


[目次へ戻る](https://qiita.com/Getabako/items/ab1bb2e1b0cbb7dd7c68)

[ゲタバコ先生のホームページ遊びに来てね♪](http://getabako.wp.xdomain.jp/)
Vanilla JS や TypeScript で Custom Elements を書く際の注意点

Vanilla JS や TypeScript を使って Web Components の Custom Elements を書いてビルドした結果、ブラウザのコンソールに

```
Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
```

というエラーが出ることがあります。

## 原因

Custom Elements が ES5 形式のコードになってしまっているのが原因です。

仕様では、Custom Elements は ES6 の class 構文である必要があります。しかし、ビルド時に TypeScript や Babel を通すことで、意図せず ES5 形式のコードになってしまっていることがあります。この時、上記のエラーが出ます。

## チェックポイント
### TypeScript を使っている場合

Compiler Options の `--target` が `"ES6"` になっているか確認します。

```tsconfig.json
{
  "compilerOptions": {
    "target": "ES6"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
```

### Babel を使っている場合

Babel でトランスパイルをすると ES5 形式のコードになってしまいますが、[`babel-plugin-transform-custom-element-classes`](https://www.npmjs.com/package/babel-plugin-transform-custom-element-classes) を併用することで上記のエラーを回避することができます。

```.babelrc
{
  "presets": ["env"],
  "plugins": ["transform-custom-element-classes"]
}
```

## ES5 形式のコードをそのまま使いたい場合

ES6 をサポートしていないブラウザも対象にする必要があるなど、ES5 形式のコードをそのまま使いたいというケースもあるかと思います。

この場合、Custom Elements を宣言する前に [`custom-elements-es5-adapter.js`](https://github.com/webcomponents/webcomponentsjs#custom-elements-es5-adapterjs) という polyfill を読み込むと、 ES5 形式の Custom Element を正常に動かすことができます。
Dockerでcron動かしつつRailsサーバを動かす

* Alpine Linux 3.4
* Ruby 2.3.4
* Rails 5.0.3


# 問題点

docker-compose.ymlの `command` に下記を指定して `docker-compose up`するとcronを動かしつつRailsサーバを動かすことが出来る。

````yaml:docker-compose.yml
services:
(略)
    command: bash -c "crond && bundle exec rails s -b '0.0.0.0'"
````

この状態でコンテナのプロセスを確認すると、PID 1で上記のコマンドが動いており、その子プロセスとしてcrondとRailsサーバが動いていることが確認できる。

ここで `docker-compose stop` でコンテナを停止しようとする。
`docker-compose stop` はPID 1のプロセスにSIGTERMを飛ばすつごう、子プロセスのRailsサーバは特に停止しないので、最終的には強制終了 (Exit 137) されてしまう。


# 対応

docker-compose.ymlの `command` を、`exec` でRailsサーバを起動するよう変更する。


````yaml:docker-compose.yml
services:
(略)
    command: bash -c "crond && exec bundle exec rails s -b '0.0.0.0'"
````

これでPID 1のプロセスがRailsサーバに入れ替わるので、`docker-compose stop` でRailsサーバが停止してくれる。
起動用のスクリプトを別途呼び出すようにしている場合でも、最終的に `exec bundle exec rails s -b '0.0.0.0'` で起動してあげれば大丈夫。なはず。


# 参考

* [rails, whenever and docker - cron tasks doesn't run - Stack Overflow](https://stackoverflow.com/questions/43559233/rails-whenever-and-docker-cron-tasks-doesnt-run)
* [docker-stopでコンテナ停止時にスクリプトを実行する - Qiita](https://qiita.com/panage/items/321851bff1a1b306b316)
* [Dockerコンテナー内のbashからアプリケーション停止処理を実施するTIPS - めもめも](http://enakai00.hatenablog.com/entry/20140824/1408855090)
オリジナルのコマンドを作った話

# はじめに  
これは[Vim2 Advent Calendar 2017 12日目](https://qiita.com/advent-calendar/2017/vim2)の記事です
普段は基本的に zsh + tmux + vimで全てが完結するよな環境で作業をしているのですが  
コーディング中はできれば全てをvim上で色々出来るようになれば色々幸せになれるのでは
と思ってやってみたので今回記事にしたいと思います。  
~~アドベントカレンダーに参加したくて必死でネタを絞った~~  

# やったこと  
ふだんはRubyを触っている人間でRubocopを使う時にターミナルに戻るのが  
めんどくさかったのでvimscriptで今開いてるファイルへ実行できればいいなって感じで作りました  

書いたコード [GitHub](https://github.com/723gt/vim-rubocop)  

```vimscript:main.vim  
:command Rubocop call Rubocop()

function Rubocop()
  let fileName = expand("%:p")
  if fileName =~ '.rb$'
    let rbc = 'rubocop '

    let log = system(rbc.fileName)
    echo log
  else
    echo "Not Ruby file"
  endif
endfunction
```  

1行目でコマンドを定義する  
`:command コマンド名 実行するコマンド or 関数` 
コマンド名は大文字から始める

関数の中身  

`let filename = expand("%:p")`  
今開いてるファイルのフルパスを取得  
.rbの拡張子かを判別して真だった場合はrubocopを実行して結果を表示する  

vimrcで書いたmain.vimを読み込ませる  

```vimrc 
:source /ファイルの/ディレクトリ/rubocop/main.vim
```
## 動作  
<img width="142" alt="スクリーンショット 2017-12-05 14.16.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/98200/60db1821-a359-0bbb-f9b9-e20e05236aff.png">

<img width="82" alt="スクリーンショット 2017-12-05 14.17.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/98200/28d5dfbf-e74b-4911-ffe8-9931e734b0fb.png">  
<img width="296" alt="スクリーンショット 2017-12-05 14.16.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/98200/a6cef291-0d4c-6445-68b6-f2b55e1e0f8c.png">


# おわりに  
結構簡単に新しいコマンドを作れるので 
まだやったことない人、今のvimじゃ満足できなくなってる人  
ぼくのかんがえたさいきょうのvimをドンドン作ってみてください
アニメーションの遷移

主人公のポーズを立ちポーズ、歩行２パターン、攻撃ポーズの４つ作りましょう
![8-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/2cd92b77-4826-ac3d-a5b0-92c1b59cc69e.png)

アニメーションの遷移　入力するスプライト：主人公
![8-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/53527494-d47f-c933-8e6a-5dc7ab342c8f.png)

[解説動画はこちら♪](https://www.youtube.com/watch?v=4Bpf584xZOE&t=135s)

[目次に戻る](https://qiita.com/Getabako/items/fbb7d8b9ba7681b7191a)
filter_input関数とセッションについて

filter_input関数は、取得する変数の名前の所に$_SESSIONを書いてはいけない。

```php
filter_input(INPUT_POST, '$_SEESION['SAMPLE']'); 
```

そもそもセッションをフィルタリングするのはおかしな話で、$_SESSIONに格納されている情報は、サーバ側で作成し、格納した値であり、安全性は格納するタイミングで確保するべきものだからです。

GETやPOSTはユーザ由来の情報なので、安全性が確保されていないため、取得するタイミングででフィルターなりチェックなりする必要があるためあります。

なので、通常は取得する変数の名前の所に$_SESSIONを書かない。

```php
filter_input(INPUT_POST, 'name'); 
```

なのでこのように書くのが通常となります。
C++ Builder XE4, 10.2 Tokyo > TMemo > 最終行に移動する実装

```txt:動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)
```

### 処理の概要

TMemoで任意の場所を表示している状態から最終行の表示状態にしたい。

## v0.1

### 参考

[[Delphi] TMemoで、先頭行/最終行/指定行へ移動する](https://www.blackcat.xyz/article.php/ProgramingFAQ_del0006) by くろねこ研究所さん

上記にDelphi実装(SendMessage使用）があるものをC++ Builder実装(かつPerform使用)に変更してみた。

### code

```Uni1t.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_addClick(TObject *Sender)
{
	for(int loop = 0; loop < 10; loop++) {
		Memo1->Lines->Add(L"TEST");
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_moveLastClick(TObject *Sender)
{
	int iLineNow = Memo1->Perform(EM_LINEFROMCHAR, Memo1->SelStart, 0);
	int iLineLast = Memo1->Perform(EM_GETLINECOUNT, 0, 0);

	// debug
	String msg = IntToStr(iLineNow) + L":" + IntToStr(iLineLast);
	OutputDebugString(msg.c_str());

	Memo1->Perform(EM_LINESCROLL, 0, iLineLast - iLineNow);
	Memo1->SelStart = Memo1->Perform(EM_LINEINDEX, iLineLast - 1, 0);
}
//---------------------------------------------------------------------------
```

### 動作

下記の手順では最終行に移動する[成功]。

1. スクロールバーで移動
2. TMemo内の行をクリックしてカーソル位置を調整
3. 最終行移動処理をする

下記の手順では最終行に移動しない[失敗]。

1. TMemo内の行をクリックしてカーソル位置を調整
2. スクロールバーで移動
3. 最終行移動処理をする

原因は、スクロールした状態と実際のカーソル位置(SelStart)のずれによる。

## v0.2

以下の実装とした。
上記の二通りの操作でも正常に動作する。

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_addClick(TObject *Sender)
{
	for(int loop = 0; loop < 10; loop++) {
		Memo1->Lines->Add(L"TEST");
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_moveLastClick(TObject *Sender)
{
	int lineCnt = Memo1->Lines->Count;
	Memo1->Perform(EM_LINESCROLL, 0, lineCnt);
	Memo1->SelStart = Memo1->Perform(EM_LINEINDEX, lineCnt, 0);
}
//---------------------------------------------------------------------------
```
SSLストアでRapidSSLのファイル認証タイプを購入しようとしたら取扱終了してたので泣く泣くメール認証タイプに切り替えた話

#前置き
巷を騒がせている(?)SymantecのChrome無効化問題ですが、つい最近思わぬ余波を受けました。
そのときに起きためんどくさかった事をメモします。
[シマンテック社SSLに関するChromeでの無効化について](https://www.ssl-store.jp/system/controllpanel.php/docs/20171127)

#Symantec無効化を受けて焦る(2017年9月頃？)
AWSのサービスはだいたいCertificate Managerの証明書を使っているのですが、オンプレで運用しているものはSSLストアのRapidSSLを活用してたりします。
なんてったってファイル認証タイプは1620円！お安い！
※FujiSSLも安いのですがあまり使った事ないので手を出せず…

そこにSymantecのChrome無効化問題発生！Σ(￣□￣)
RapidSSLは無効化対象の証明書…
どうしよう…

困っていたところ、SSLストア内で下記の記述を発見！
>シマンテックCAは2017年12月1日までにDigiCertのシステムに移管される予定ですが、移行が済んでからは旧シマンテックCAから発行された証明書はChromeでは信頼されないものとして扱われます。具体的にはChromeでは該当ページに警告やエラーが表示されることになります。

つまり…？
2017年12月1日以降に購入すれば、Chromeでも無効化されないじゃん！天才！

幸い2017年12月以前に期限が切れる証明書無かったので、アクティベートはおいおいするとして購入は12月1日にまとめてする事にしました。

#ちょっと不安になったのでSSLストアに確認(2017年11月末ごろ)
そもそも、誰にも確認してないし、実は12月1日に購入してもダメだったらどうしよう…
という突然の不安に駆られました。(もっと早く気付け)
とりあえず聞くだけタダだしSSLストアに問い合わせじゃー！

結果、12月1日以降に購入したRapidSSLはChromeの無効化対象ではないという認識で間違いないとの事。
ふぅ、よかったよかった(￣∀￣;)

#衝撃の12月1日
よっしゃー、RapidSSL買ったるどー、買いまくったるどー

![取扱終了.png](https://qiita-image-store.s3.amazonaws.com/0/106608/70231496-45b6-aa48-318a-382a0939dbb5.png)

(　ﾟдﾟ) ・・・ 
　 
(つд⊂)ｺﾞｼｺﾞｼ 
　 
(；ﾟдﾟ) ・・・ 
　 
(つд⊂)ｺﾞｼｺﾞｼｺﾞｼ 
 
（；ﾟ Дﾟ） …！？

嘘…だろ…？

#その後
せめて告知出してくれよ…orz
この記事書いてる12月5日現在もSSLストアのサイトトップにはRapidSSL1620円の表示出てるし…Twitterは今年1回しかつぶやいてないし…絶対告知無しだよ…
そもそも11月末にRapidSSLに問い合わせたときに教えてくれよ…orz
まさか取扱中止するなんて思ってないから、12月1日以降も取り扱っていますか？なんて聞かないから察してくれよ…orz

と嘆いていても仕方ないので、メール認証タイプで購入する事にしました。

###めんどくさかった事その1.社内の承認取り直し
お値段が1620円から2980円へ大幅アップ…

関係各所へ事情を説明
違うんです、急に取扱中止になったんです、私悪クナイ私被害者アル

そしていったんあげた申請のやり直し…
年末でバタバタしてる時期なので権限持ってる人がなかなか捕まらないというおまけつきorz

###めんどくさかった事その2.認証用のメールが受信出来ないメアドに設定されている
ファイル認証タイプだと、認証用ファイルを管理画面からダウンロードして対象のFQDNが設定されているサーバのドキュメントルートへ配置するだけだったのですが…
その名の通りメール認証なので、メールでの認証を行わなければならず…
その認証用のメールが届くメールアドレスは、
**admin@(ドメイン or 対象のFQDN)
administrator@(ドメイン or 対象のFQDN)
hostmaster@(ドメイン or 対象のFQDN)
webmaster@(ドメイン or 対象のFQDN)
postmaster@(ドメイン or 対象のFQDN)**
のいずれか、もしくは
**Whois情報 担当メールアドレス**
との事。 

メールの設定をしていないドメインなので、後者を選択するわけですが…
なんと古から受け継がれし受信出来ないメアドが設定されているではありませんか。

ドメインレジストラは<del>分かりにくさに定評のある</del>お名前.comなので、早速Whoisの情報を変更しにGo!Go!

どれどれ、登録者名義変更と…
メール認証送付先…Σ(￣□￣)
また認証かい！
選択肢は下記2つ
・新しい登録者・現在の登録者による認証
・新しい登録者・現在の管理者による認証

まぁ下一択ですな(´_ゝ`)

当然管理担当者情報も古い情報になっているので、そちらの変更も必要に。
幸いこちらは認証無しで、新しいメアドに通知がくるだけだったのでスムーズに変更出来ました。

そして改めて登録者名義を変更。
この時、新しい登録者のメアドと、現在の管理者のメアドにそれぞれ認証メールが飛んでくるので、それぞれを承認。

ふぅ…SSL証明書のメール認証するためにドメイン登録情報の変更のメール認証までするなんて…わけがわからなくなりそう

そしてそして、変更したWhoisの情報がSSLストアに反映されるのに時間を要し、私のヘイトは臨界点を突破したのでした。

#おわりに
とりあえず
SSLストアひどいよぉ( ﾉД`)ｳｴｪｪﾝ
と言いたい

まぁ一番ひどいのはSymantecなんですけどね
VBAからHeadless Chromeに挑戦

Headless？Selenium？こちらの説明は割愛させて頂き、
ExcelVBAからブラウザを立ち上げないで、操作してみよう的な感じです.
こちらのサンプルではyahoo!ファイナンスからデータを取得して、
シートに内容を書き出しています。

※動作させるのにSeleniumBasicのダウンロードが必要となります。

##Excelで動作させるための準備
####1. 下記サイトからSeleniumBasic-2.0.9.0.exeをダウンロード
https://github.com/florentbr/SeleniumBasic/releases/tag/v2.0.9.0

####2. chromedriver2.33をダウンロード
VBAのエラーが起きてしまうので、chromedriver2.33を別途ダウンロード（上記に含まれているchormedriverが古い？）
https://sites.google.com/a/chromium.org/chromedriver/downloads

ダウンロードしたzipからchromedriver.exeを1.があるフォルダにコピー
（以前のファイルは念のため、保存しておいたほうがいいかと思われます。）

####3. ExcelVBAの参照設定
ExcelVBAのメニューから「ツール」-「参照設定」でライブラリを開き、「Selenium Type Library」にチェック入れ、OK

####4. Chromeのバージョン
Headlessを使用する場合、Chrome59以上

##VBAの記入
```VBA
Dim driver As New Selenium.ChromeDriver

driver.AddArgument "headless"
driver.AddArgument "disable-gpu"
driver.AddArgument "window-size=1920,1080"
driver.Start
driver.Get ("http://stocks.finance.yahoo.co.jp/us/profile/AMZN")
driver.Wait 1000

Dim data1, data2, data3
data1 = driver.FindElementByCss("#globalDate > p > strong").Text
Worksheets("Sheet1").Cells(1, 1) = data1
   
data2 = driver.FindElementByCss("#main table.stocksTable").AsTable.Data
Worksheets("Sheet1").Cells(2, 1).Resize(UBound(data2, 1), UBound(data2, 2)).Value = data2

data3 = driver.FindElementByCss("#main table.boardFinCom").AsTable.Data
Worksheets("Sheet1").Cells(5, 1).Resize(UBound(data3, 1), UBound(data3, 2)).Value = data3

driver.Close
```

ブラウザを開いて操作感を出したい時や、もしくはどういう操作をやっているかを確認したいなら、下記コードをコメントにするとChromeが表示されます。
（Headlessの意味がなくなってしまいますが･･･）

```VBA
driver.AddArgument "headless"
driver.AddArgument "disable-gpu"
driver.AddArgument "window-size=1920,1080"
```
##取得イメージ
![result.PNG](https://qiita-image-store.s3.amazonaws.com/0/215992/667619a7-97b7-6505-cd4a-0edd3c0fabe5.png)

##終わりに
1. いくつものURLを手動で取得しているなら、データ収集の効率化が図れると思います。

2. 本当はPDFファイルもVBAから操作したいのですが、ハードルが高いようなので、勉強中です･･･
マイニングの体験談

# Minergate
Minergate という仮想通貨のマイニングを簡単にすることができるツールを発見したので自分のパソコンにインストールして使ってみました．

* CPUコア数 ⇒ 8

# 問題が発生
CPUを6コア渡してマイニングしてみた．

* PCが全く動かない（これはわかる）
* ネットワークがおかしくなった（？？？）
    * マイニングを終了しても治らない．再起動後復活．
* というか，CPU使用率100%になるので，パソコンが燃えそうで怖い．
  
## とりあえずWiresharkで確認してみた
- 特に変なパケット通信はなかった．

## アンインストール
というわけでよくわからないのでアンインストールしました．

なんでこうなるか，お分かりの人は，ご教授ください．

## 現在
minergateは使わず，LA BitZeny Poolによるプールマイニングで巷で話題のbitzenyを採掘しています．
OSSのノベルゲームエンジンを作った話

#はじめに
この記事は[個人開発Advent Calendar 2017 の20日目](https://qiita.com/advent-calendar/2017/private-development)です。

[<< 個人開発のJavaScriptビルドをWebpackに乗り換えた話](https://qiita.com/jkr_2255/items/65983825e589ac8f5ea1) || [できるだけコストをかけずにサービスを開発するためにしていること >>](https://qiita.com/kentosasa/items/a4322071ceb79890ae63)

#作ったもの
[簡易ノベルゲームエンジン「LINKS」](https://github.com/S-H-GAMELINKS/Novel.Game.Engine.LINKS)という、簡単なノベルゲームであれば直ぐにリリースできるエンジンを制作しました。

[サンプル動画](https://gamelinks007.net/web/statuses/99085699488207521)


C言語とDXライブラリにて制作しました。
現在は、[yumetodo さん](https://twitter.com/yumetodo?lang=ja)からリファクタリングを受けつつ、C++ へと移行を進めています。

#開発に至った経緯
元々、このエンジンは私が代表を務めている[ゲームリンクス](https://gamelinksweb.herokuapp.com/)というサークル内で使用する目的で開発に着手しました。

ゲームリンクス内でプログラミングができる人間が私しかおらず、おまけにノベルゲームの肝ともいうべきシナリオを書ける人間が５人もいました(まあ、私も含めてですけどねー)

要するに、プログラミング担当に負担がかかりやすい環境になっていたということです。

おまけに、ティラノスクリプトや吉里吉里といったノベルゲームエンジンを使用することにも問題がありました。

サークルメンバーの所持しているPCのスペックがそこまで良いものではなかったため、それらのノベルゲームエンジンで制作したゲームのデバッグがそもそもできないことがあったんですよね……。

おまけにサークルメンバーはそれぞれ遠方にいることもあり、あまりに大きなゲームデータをやり取りするのは面倒臭かったことも理由の一つですね。

プログラミング担当の負担を軽減し、かつ低スペックなPCでも快適に動作できるノベルゲームエンジンを使う必要性があった。
これが、「LINKS」の開発に着手したきっかけですね。

#開発中のあれこれ

開発当時は、C言語の入門書（猫でもわかるC言語だったかな……？）を使ってプログラミングの勉強をはじめて三か月程度でした。つまり、プログラミング三か月で、ノベルゲームエンジンを制作するという無茶苦茶なことを考えたわけです。

そのため、開発当初は試行錯誤の連続でしたし、失敗続きで嫌になることばかりでしたねー。
でも、その時苦労したおかげで色々とわかるようになった事柄もありますので、結果オーライなのかもしれませんね。

「LINKS」開発にあたってはまず、最低限度必要と思われる機能を洗い出し、順次実装していくことを基本方針にしました。

最低限度必要と思われた機能としては以下のものがあがりました
・セーブ機能
・ロード機能
・選択肢機能
・スキップ機能
・オート機能

これらの中でも特に苦労したのがセーブ・ロード機能周辺の実装でした。
当時、C言語をちょっとかじった程度でしたのでセーブデータの構造体を書き込んだり、読み込んだりというのが中々うまくいきませんでした。

そのうえノベルゲームでのセーブデータのロードは、セーブしたその文章のところから再開できるようにしないといけません。

その時に表示されていたキャラクターの立ち絵や背景画像、再生されているBGMなどをセーブデータをロードした後に再現する必要もあり、当時の私はかなり手こずっていましたねー。

一番手間取ったのは、行の管理ですね。「LINKS」はテキストファイルに立ち絵などの各処理を行うタグを記述していく方式です。そのため、セーブデータ内に「どのスクリプトの何行目でセーブしたか」がロード時にわかるようにしなければなりません。

そこで、行を管理している変数とルート管理用の変数の値をセーブデータ内に取り込むように変更しました。まず、ルート管理変数にセーブ時点での値を読み込んでやり、さらに行数を読み込むことで各スクリプトの指定の行から再開できるようになりました。

こんな感じで、小さな機能を少しずつ実装していく方式で開発とリリースを進めていきました。

ver 1.00 をリリースしてからはどんどん機能を追加していき、最終的には今年の四月ごろには当初実装したいと考えていた機能もほぼ終了してましたね。

#リリース後の反響

2016年6月にリリースして、現在まででザックリ300ダウンロードくらい。
まあまあ、ダウンロードされつつ利用されている模様ですねー。

元々がサークル内で使用する目的のエンジンでしたから、そんなにダウンロードもされないだろうと考えていましたねー。

あと、嬉しかったのが同人ゲーム制作ツールとして[こちらの記事](https://matome.naver.jp/odai/2138589554261439901)に取り上げられたことですかねー

あとは、OSSとしてリリースしてからはエンジン自体の簡素さから「教育用に使えないか？」というお話もいただけたりしていますねー。

#最後に

自分しか使わないだろうモノであっても、公開すると意外と需要があるという良い教訓を学べましたねー。

あとは開発中に、実際のノベルゲームの内部構造を挙動から推察して逆算する考え方とかコーディング関係のテクニックとかも身に付きましたし(OSSにするまでgitも知りませんでした……)

そういう意味ではOSS活動をするというのはエンジニアとしての成長に通じるいい機会なのかもしれませんねー。

まあ、今後もゆるーく開発を続けていこうかと思いますねー
ゲームオーバー処理&クリア処理

ゲームオーバー画面の非表示と表示　入力するスプライト：ゲームオーバー画面
![7-3.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/b1bf4dfd-e154-216e-f46c-16afe78b3f67.png)

ゲームオーバー処理　入力するスプライト：主人公
![7-4.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/1828338c-62f8-227c-8fde-47a31d89ebae.png)

ゲームクリア画面の非表示と表示　入力するスプライト：クリア画面
![7-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/81468dc8-0978-bd3a-66f2-5c98ec521748.png)

ゲームクリア処理　入力するスプライト：主人公
![7-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/6108f493-bbe4-5b9d-3b67-5235b87932cc.png)

[解説動画はこちら♪](https://www.youtube.com/watch?v=iX3KR5ioYs8)

[目次に戻る](https://qiita.com/Getabako/items/fbb7d8b9ba7681b7191a)
【完全無料】Hubot + Glitch で Slack Bot

かつて heroku + hubot で無料slack botブームがありましたがheroku有料化に伴い、代わりにglitchで実現する方法をまとめました。

- [hubot](https://hubot.github.com/) - github謹製slackbotアプリ
- [glitch](https://glitch.com/) - trelloの会社がやっている無料のnode.jsホスティング

順調にいけば15分以内に終わります。Hubot構築はとりあえず試す場合yeomanでgenerateするだけでよいでしょう。

## フロー

1. [Hubot構築](https://hubot.github.com/docs/)と[整備](https://qiita.com/deerboy/items/00ff9f71c046a2883974#hubot%E6%95%B4%E5%82%99)
1. GitHubにPush
1. [glitch](https://glitch.com/)でプロジェクト作成&GitHubリポジトリをImport
1. 動く

## Hubot整備

そのままGlitchにimportすると動かないので下記のローカル時点で下記対応をしておく

```
cd <PROJECT_DIRECTORY>
npm i coffee-script -S
```

package.jsonに起動スクリプトを記述。 `*****` の部分はslack管理画面のhubotページより取得したtokenを貼る。

```package.json

...

  "scripts": {
    "start": "HUBOT_SLACK_TOKEN=***** ./bin/hubot --adapter slack"
  },

...

```

ここまでできたらGitHubにpush。

## 最後に

よいBotライフを

## 追記

[2017/12/6] 5分で眠る + 容量制限が意外とシビアなので、結局GCE無料枠とかのがいい説。

## 参考

- [[Node.js] 無料で簡単にウェブアプリを公開できるサービス「Glitch」を使ってみた！](https://qiita.com/yonedaco/items/569bcc442872a1f9a03d)
DolphinでDualShock 3を使用する．

# Dolphinとは？
Wiiのエミュレーターです．
Bluetooth搭載のパソコンならWiiリモコンを使って遊べます．

# DualShock3の設定
1. MotionInJoyをダウンロード <br>
http://www.mediafire.com/file/kmzb11lqhqkhb5j/Maxmag-MotionInJoy.rar <br>
パスワードはmaxmogで解凍します．
2. M-INSTALL[ADMIN].batを管理者として実行する <br>
コマンドプロンプトが表示されるので，エンターキーを押す．<br>
3. DS3_Tool_Local.exeを管理者として実行<br>
<img src = "https://qiita-image-store.s3.amazonaws.com/0/191026/1ddfcb96-f6bb-4ce8-7305-4a2ca241c6cc.png" width=70%><br>
※.NETがない場合インストールが要求されますのでしてください．<br>
4. Driver Managerをクリック<br>
<img src="https://qiita-image-store.s3.amazonaws.com/0/191026/7870ea9c-cc3c-fe46-a9f5-369a26adf6de.png" width=70%><br>
5. HardwareLocation内のチェックボックスにチェックを入れて,Load driverをクリック<br>
<img src = "https://qiita-image-store.s3.amazonaws.com/0/191026/ab20469c-f136-6be4-5267-fd18353e2456.png" width=70%><br>

終わると音が鳴る．
6. install all をクリック(チェックはなくていいです)<br>
<img src="https://qiita-image-store.s3.amazonaws.com/0/191026/849f929e-3ccf-cc1f-f49a-78828a002f2a.png" width=70%>

終わると音が鳴る．
7. profilesのEnableをクリック<br>
<img src="https://qiita-image-store.s3.amazonaws.com/0/191026/6ad67bd7-0e91-9285-0e80-40a6aab191e3.png" width=70%>

※profilesのSelect one modeをXbox 360 Emulatorとしてください．<br>
これをしないとコントローラが認識されはしますがボタン配置がおかしくなります．
8. 以上<br>
後は,Dolphinのコントローラ設定でボタンを割り当てていくだけです．
dockerのいろいろ

## docker build for イメージ作成

作り方

* dockerfileいらない形式

> [inlines docker build](https://github.com/encodeering/docker-base/commit/71f92629c36b9f4881faed3d90ae9cefd812dd8c)

```
docker build -t image_name_and_tag . -f- <<-EOF
> FROM centos
> RUN yum install -y git vim
> EOF
```
不明点：上記の イメージ名後ろの点は何の意味でしょう、docker build --helpで見た感じだと、`PATH | URL | -` 三種類なので、dockerfileのpathが必要ないっし
> Usage:	docker build [OPTIONS] PATH | URL | -

* dockerfile形式

## docker run for コンテナー作成

> docker run -i -d --name container_name image_name_and_tag /bin/sh



## docker start

* docker command

> docker image ls [-a][-f since=tag]     // 各imageのサイズ docker image ls [name]
> docker system df    // 実際に使われている空間
> docker image ls -f dangling=true  // dangling imageを表示
> docker image prune  // dangling image削除

* docker build up

> docker run --name webserver -d -p 80:80 nginx // nginx container作成
> docker exec -it webserver bash // containerへアクセス
> docker commit --author "xx<mm@mail>" --message "---" webserver nginx:v2
> docker image ls nginx // 上記のimageをリストしてくれる
> docker history nginx:v2 // 修正の履歴を表示する

* docker start from build image

> docker run --name web2 -d -p 81:80 nginx:v2

* dockerfileの作成

> FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps

* dockerfileからcontainerの作成

> docker build -t nginx:v3 .     // nginx:v3のimageを作成
Shift_JISで書かれたファイルをUTF-8に変換

# 問題

Python使用時に発生した．
このエラー文　↓

```
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte
```

#対処
- nkfコマンドでUTF-8に変換した．

##インストール
まずはnkfをインストールする必要がある．

- centOSなら

```
yum -y install nkf
```

- Ubuntuなら

```
sudo apt-get install nkf
```


## 使用

- 文字コードの確認

```
nkf -g sample.txt
```

- 文字コードの変更

```
nkf -w --overwrite sample.txt
```


|オプション  |文字コード  |
|---|---|
|-w  |UTF-8  |
|-j  |JIS  |
|-s  |Shift_JIS   |
|-e  | EUC  |

※ --overwriteは上書きするという意味．別ファイルにしたい場合はリダイレクトする．

```
nkf -w sample.txt > sample.utf
```

## ワイルドカード指定して，too many open files.と言われたとき．

確認

```
ulimit -n 
1024
```

変更

```
ulimit -n 2048 ←お好きな数字
```
パケットについて

# パケットとは

>パケットとは通信回線を効率よく利用するために、送受信する通信データを小さく分割した、その一つひとつのまとまりのこと

らしいです

パケット自体は１と０の集まり（電気の波）なので、実態があるが分かりにくいですが、いろんなことに使えます

# パケット通信の流れ

 大学でパケット関連の研究をする中で、勘違いしていたことを踏まえて説明します

### ①パケットを作る 
PC内で何かしらのアプリケーションが動いて、通信（パケット）をAAA送りたい時
アプリケーションが
+-------------------------+
|&nbsp;&nbsp;data（独自プロトコル）&nbsp;&nbsp;|
+-------------------------+
を構築してTCPポートに送ります(TCPを使う場合)

### ②パケットを送る
パケットを受け取ったTCPポートが、いろいろつけて
+-------------+-------------------------+
|&nbsp;&nbsp;TCPヘッダ&nbsp;&nbsp;||&nbsp;&nbsp;data（独自プロトコル）&nbsp;&nbsp;|
+-------------+-------------------------+
となり
LANポート等の物理ポートが
+-----------------------------------+-------------+-------------------------+
|&nbsp;&nbsp;物理層ヘッダ（MACアドレス等）&nbsp;&nbsp;||&nbsp;&nbsp;TCPヘッダ&nbsp;&nbsp;||&nbsp;&nbsp;data（独自プロトコル）&nbsp;&nbsp;|
+-----------------------------------+-------------+-------------------------+
と色々書き換えてネットの海に送ります


物理ヘッダの転送先MACアドレスは、AAAのアドレスではないこと**
（理由は後々説明します）

### ②通信パケットを転送する
先ほどのパケットが「スイッチ」を通る時は**物理層ヘッダ**を見て転送を先を決めます

ですが、「ルータ」を通る時は**TCPヘッダを見て、物理層ヘッダを次のルータのMACアドレス書き換えて**転送をするようです

**「勘違いポイント②」
設定上はIPアドレスを見て転送しているみたいですが、厳密に言うとIPアドレスを見て転送先MACアドレスを決定しているようです**

# この勘違いに気づいた感想
厳密に言うと分かりにくくなる→ふんわりと説明する
だと勘違いして覚えてしまうことが多いと思う
ふんわり説明していいけど
**今から説明することは厳密に言うと間違っているから、自分で調べて見て**
って言って欲しいと思った

[カレンダー](https://qiita.com/advent-calendar/2017/yurue)遅れちゃいました〜
次は@rkonnoでした　次は遅れないように頑張ります！！
主人公の体力ゲージとダメージ処理

体力ゲージは少ない順に一つのスプライトにコスチューム違いで登録します
ドット絵とかで描くと楽でキレイに描けます
![6-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/f591daaf-4c09-9a50-5859-4fd16a0f479b.png)
![6-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/dff47057-bf16-959e-2554-037347a971ef.png)

体力ゲージの表示　入力するスプライト：体力ゲージ
![6-3.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/14db06e2-917e-da6c-7634-9b771233c1fa.png)

体力ゲージの変化　入力するスプライト：体力ゲージ
![6-4.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/a8a7659c-0f47-ef87-ec46-fa14f8ce90dc.png)

主人公のダメージ処理　入力するスプライト：主人公
![6-5.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/a64823d8-3660-9067-c172-3e56b2de724f.png)

主人公のダメージ時の無敵時間　入力するスプライト：主人公
![6-6.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/52371dc3-649b-d52a-e0df-502374ce65b8.png)

[解説動画はこちら♪](https://www.youtube.com/watch?v=Kkg649vWPvQ)

[目次に戻る](https://qiita.com/Getabako/items/fbb7d8b9ba7681b7191a)
Obj-CからSwift化したクラスをstoryboard/xibで利用する時のクラシュー原因

最近、現場でObjective-Cで開発されたプロジェクトにSwiftを使い、機能追加など行なっていますが、以下のクラッシュエラーが発生していたので調べてみました。

<h2>現象</h2>
SwiftコードでUIViewをカスタマイズしたサブクラスをObjective-Cのクラスに追加したらクラッシュエラーになった。

<h2>原因</h2>
Swiftコードに紐づいているStoryboard/xibをObjective-Cクラスに使う場合は設定が必要のようです。（普段は生成時に自動で設定されるが、何らかの理由で設定していなかった。）
Custom Class-> Moduleの下の **Inherit From Target** にチェックをする

![u30b9u30afu30eau30fcu30f3u30b7u30e7u30c3u30c8-2017-06-08-16.30.16.png](https://qiita-image-store.s3.amazonaws.com/0/32323/58ea3788-e6a0-7390-59b3-f85469e4f4e5.png)

もし、Ojbective-Cコードの中でSwiftを使われているアプリがロード中にクラッシュしたら確認してみてください。
参加してみた勉強会を種類別にまとめる

##この記事について

昨日は勉強家のメリットとデメリットについてまとめましたが
本日は勉強会の種類についてまとめていこうと思います。

###この記事を書いた人
23歳エンジニア1年目のエンジニア。
土日ももっと学習したくなり、ここ２ヶ月週２回程のペースで勉強会に参加中。

## 参加してみた勉強会
- LT
- 読書会
- プレゼンテーション
- カンファレンス

##LT
ライトニングトークと呼ばれ登壇者が関心のある事柄やこれまで経験された内容を5分ほどにまとめて話す形式。
短い時間に要点のみを聞けるので短時間でその事柄について知ることができる。
私が参加したLTではとても要点がまとめられていて時間効率が良いように感じました。

##読書会
各参加者が技術書などを持ち寄ってその本から学んだことや内容などを紹介し合うものです。
IT以外でも小説やビジネス書など本に縛りが無いものもあるのでビブリオバトルに近いです。
私は読書が好きなのでいろいろな本に出会うことができたので楽しく過ごせました。
幅広い知見を持ちたい方におすすめの勉強会です。

##プレゼンテーション
講演会のように登壇者がいて話す側と聞く側がはっきりします。
しっかりと腰を据えて登壇者の考えや技術を学びたい方におすすめです。
一般的にスライドに則って進行するので話の流れが掴みやすく講師の中には
聞き手にも話を振りながら進めたりと講師の技量によるところも大きいと感じました。

##カンファレンス
私が参加したのはPHPカンファレンス2017でしたがとにかく人が多かったです。
企業の出展ブースなどが多く各企業の代表やCTOなど一大イベントだけり力が入っていました。
実際に企業の方と話してみたい方やたくさんのエンジニアと話してみたい方にはオススメです。

##勉強会を見つけるには
私は[skill](https://play.google.com/store/apps/details?id=jp.co.ysinc.skill&hl=ja)や[connpss](https://connpass.com)でよく勉強会を探しています。
条件やカテゴリ毎で検索できる機能が便利です。ぜひ使ってみてください。

##勉強会を選ぶ基準
私は業務で使用する内容や興味のある企業の方の発表などをチェックしておいて
日程が合えば行くようにしています。

##まとめ

だらだら週末を過ごすよりは良いと思い、終業後や週末に勉強会に参加し始めて２ヶ月ほど立つのですが
個人的に面白そうな勉強会に参加し知見を広げることができました。
また情報共有をしてくれるエンジニアもできたので今まで知らない分野の知識も着くようになりました。

個人的に手を動かす時間を設けながら今後も興味がある分野などの勉強会には参加していこうと思います。

ここまでお読みいただきありがとうございました。
.zshrcの基本的な部分だけ設定ファイルを書いてみた

zshを少しでも使いやすくするため、.zshrcで基本的な部分だけの設定を書きました。
最低これを書けばそこそこ使えるようになると思う。(多分)

ここからはzshが端末にインストールされていることを前提に書きます。
まずは、設定ファイル(.zshrc)をホームに作成し、viやemacsなどお好みのエディタで編集。

##プロンプトの設定
ホスト名などに色をつけたいので、色の読み込み設定を記述。

```
autoload -U colors
colors
```


プロンプトの左側にホスト名やコンピュータ名を表示させる。

ホスト名とコンピュータ名を左側に表示させたい場合

```
PROMPT='%n%m# '
```

ホスト名のみを左側に表示させたい場合

```
PROMPT='%B%F{cyan}%n%f%b %# '
```

↑この表記の場合、色はシアン、太字でホスト名を表示。
{cyan}の部分はお好みの色に設定します。

プロンプトの右側にカレントディレクトリを表示させる。

```
RPROMPT='%B%F{green}[%d]%f%b'
```

↑この表記の場合、色はグリーン、太字でカレントディレクトリを表示。

##補完機能の追加
補完機能を追加する。

```
autoload -U compinit
compinit 
```

##コマンド履歴の設定
実行したコマンドの履歴をどこまで保存するかなどを設定。

```
HISTFILE=~/.zsh_history #保存先
HISTSIZE=10000 #保存するサイズ
SAVEHIST=10000
setopt hist_ignore_dups #直前に実行したコマンドは履歴に残さない
setopt share_history  #別タブで開いて実行したコマンドも入力履歴として共有する
setopt auto_pushd #cd+tabで以前移動したディレクトリを表示させる
setopt pushd_ignore_dups #同じディレクトリは追加させない
```

##エイリアスの設定
エイリアス(別名)を設定。

```
alias ls='ls -G'
alias ll='ls -lG'(※)
alias la='ls -A'
alias l='ls -CF'
#alias rm='rm -i'
#alias cp='cp -i'
#alias mv='mv -i'
#alias vi='vim'
alias -g G='| grep'
alias -g L='| less'
alias -g H='| head'
alias -g T='| tail'
alias -g S='| sort'
alias -g W='| wc'
alias -g X='| xargs'
alias tsp='tmux new-session \; split-window -h -d'
alias tvsp='tmux new-session \; split-window -d'
```
### 補足
(※)の部分のlsコマンドのエイリアス設定において、Macでは上記のエイリアス設定で動くが、Linuxでエイリアスの設定を記述する場合は、lsコマンドのエイリアスは下記のように記述する。(2017年12月27日追記)

```
alias ll='ls -lF'
```
ipv6 で MariaDB サーバに接続

mysql(MariaDB monitor)でipv6アドレスを用いてMariaDBに接続する。

```
# mysql -h fe80::20c:29ff:fedc:d61f%eth0 -u ipv6user --password=password
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 10.2.11-MariaDB MariaDB Server

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> select user,host,password from mysql.user;
+----------+-----------+-------------------------------------------+
| user     | host      | password                                  |
+----------+-----------+-------------------------------------------+
| root     | localhost |                                           |
| root     | 127.0.0.1 |                                           |
| root     | ::1       |                                           |
| ipv6user | %         | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
+----------+-----------+-------------------------------------------+
7 rows in set (0.00 sec)

MariaDB [(none)]>
```

リンクローカルアドレスに[ゾーンインデックス](https://ja.wikipedia.org/wiki/IPv6アドレス#リンクローカルアドレスとゾーンインデックス) %eth0 を付与しないと接続できなかった。

```
# mysql -h fe80::20c:29ff:fedc:d61f -u ipv6user --password=password
ERROR 2003 (HY000): Can't connect to MySQL server on 'fe80::20c:29ff:fedc:d61f' (22 "Invalid argument")
```

参考までに ping(ping6) の実行結果。

```
# ping6 fe80::20c:29ff:fedc:d61f%eth0 -c 4
PING fe80::20c:29ff:fedc:d61f%eth0(fe80::20c:29ff:fedc:d61f%eth0) 56 data bytes
64 bytes from fe80::20c:29ff:fedc:d61f%eth0: icmp_seq=1 ttl=64 time=0.509 ms
64 bytes from fe80::20c:29ff:fedc:d61f%eth0: icmp_seq=2 ttl=64 time=0.512 ms
64 bytes from fe80::20c:29ff:fedc:d61f%eth0: icmp_seq=3 ttl=64 time=0.494 ms
64 bytes from fe80::20c:29ff:fedc:d61f%eth0: icmp_seq=4 ttl=64 time=0.457 ms

--- fe80::20c:29ff:fedc:d61f%eth0 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 0.457/0.493/0.512/0.021 ms
unzipで複数のzipを解凍

# 問題
```
unzip *.zip
```

のように普通に指定してやると，filename not matchedというエラー文が出ます．

# 対処法

シングルクォーテーションで囲む

```
unzip '*.zip'
```


*をエスケープ

```
unzip ¥*.zip
````
敵キャラの移動、ダメージ処理、重力調整

変数を作るときに「敵の初期位置X」と「敵の重力」は「このスプライトのみ」にチェック！！

敵の表示・非表示　入力するスプライト：敵
![5-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/4bc6b4db-001a-e72a-c53a-1e06ec532d00.png)

ステージに合わせた敵の出現　入力するスプライト：ステージ
[ここ](https://qiita.com/Getabako/items/6bfb0830f0f12058415b)で作成したステージの表示・非表示に画像のように「敵の表示」を追加
![5-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/f1acc424-86ff-bf79-36ab-1b235f0f3a22.png)

敵の座標　入力するスプライト：敵
![5-3.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/2cd4cbe4-0541-17c4-e77d-935f11d3b8f7.png)

敵の移動　入力するスプライト：敵
![5-4.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/ebbbdbdd-afca-94aa-044d-fdf040299b63.png)

「敵の重力」のブロック作り　入力するスプライト：敵
![5-5.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/fc283801-667a-18c1-aa76-35e51460415b.png)

敵の重力　入力するスプライト：敵
![5-6.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/d2e2d078-8de4-0660-2ab8-4f8542185940.png)

敵のヤラレ判定　入力するスプライト：敵
![5-7.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/53a377ce-2aae-9104-25f1-10ce240a554b.png)

弾が敵に当たった時の消去　入力するスプライト：弾
![5-10.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/3232786f-a7c5-350f-acf7-6fbbec1711fb.png)

主人公の重力調整　入力するスプライト：主人公
[ここ](https://qiita.com/Getabako/items/1d4932a2ffd7b01242f1)で入力したスクリプトを変更する
![5-9.PNG](https://qiita-image-store.s3.amazonaws.com/0/214359/e97b324c-1c4a-a4d8-487f-7f0db8eb7ea7.png)

[解説動画はこちら♪](https://www.youtube.com/watch?v=16X1miLymNg)

[目次に戻る](https://qiita.com/Getabako/items/fbb7d8b9ba7681b7191a)
Resource HintsでpreconnectとDNS-Prefetchを併記

##目的
relプロトコルは併記が可能なはずだが、preconnectとDNS-Prefetchを併記した事例を見かけない。もしや前例がないから誰もやらないのではないか？本当はよくわかってないのではないか？と思ったので試してみる。

##海外事例でprerenderとprefetchを併記した例
http://ipullrank.com/how-i-sped-up-my-site-68-percent-with-one-line-of-code/
GAのデータから次に最も遷移するURLをprerenderに動的に出力する仕組みについての記事。prerenderはFirefoxで動かないので、prefetchを併記しているとのこと。

##Resource Hintsの仕様
https://w3c.github.io/resource-hints/

##Resource Hintsのサポートブラウザ
https://caniuse.com/#search=Resource%20Hints
肝心のiOSのSafariとChromeがDNS-Prefetchに対応しているか不明とのこと。


##実施内容
`<head>` の上部にpreconnectとdns-prefetchのURLを書く。preconnectを優先する形でdns-prefetchと併記する。

`<link rel="preconnect dns-prefetch" href="外部リソースのURL">`
`<link rel="preconnect dns-prefetch" href="外部リソースのURL">`
`<link rel="preconnect dns-prefetch" href="外部リソースのURL">`
`<link rel="preconnect dns-prefetch" href="外部リソースのURL">`
`<link rel="preconnect dns-prefetch" href="外部リソースのURL">`

##結果
Connectingまでが先読みされたので、preconnectがちゃんと効くことがわかった。prerenderやpreloadやpreconnectを使う場合はdns-prefetchも書いておくとよさそう。preconnectが動作しないブラウザでdns-prefetchが動作するテストはしていない。

|前|後|
|---|---|
|![image.png](https://qiita-image-store.s3.amazonaws.com/0/111990/fb8438ed-7539-ea72-3467-1038577a52db.png)|![image.png](https://qiita-image-store.s3.amazonaws.com/0/111990/f614439a-bdc6-7f11-7c44-254631bcff63.png)
Amazon Athenaの料金体系について

## 概要
Athenaを使用するにあたって料金体系がちょっと気になったのでサポートに連絡して確認してみた。

## ドキュメントに記載された料金
> スキャンされたデータ 1 TB あたり 5 USD。
> バイト数はメガバイト単位で切り上げられ、10 MB 未満のクエリは 10 MB と計算されます。
> [料金 - Amazon Athena | AWS](https://aws.amazon.com/jp/athena/pricing/)

## サポートに連絡してわかったこと
10MBのデータをスキャンさせた場合の料金は、10MB分の```0.000005USD```。
10MBに満たない場合でも同額になる。  

ただし、1か月の利用料金の最低単位は```0.01USD```なので、
足りない場合は切り上げて```0.01USD```が請求される。

## ちなみに
BigQueryのようにドライランで料金を確認するようなツールはないらしい。
100万溶かさないようによく考えてからQueryを投げるようにしよう。