OmniAICreator/Qiita-1.07M huggingface dataset:
[Heroku Postgres] Herokuを使って無料でデータベースを利用する

# はじめに🎄
メリークリスマス！！！！🎄🎄
クリスマスいかがお過ごしでしょうか？？🎅
ふっけです。今回はNitKitアドベントカレンダーということで、高専祭のクラス展示で入退場システムを作成したときにHerokuのPostgresSQLを使用したので、その方法について書きます。

# 環境🎄
Node.js v12.8.0

# データベースの導入🎄
Herokuでのプロジェクトの作成は省略します。
Herokuでプロジェクトを作成したあとResourcesのAdd-onsからHeroku Postgresを追加します。
![スクリーンショット 2019-12-24 15.20.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/7eee5910-3f63-781d-e4c1-3ae104a7d376.png)
追加後 Heroku Postgresのリンクから管理画面に飛ぶことができます。
![スクリーンショット 2019-12-24 15.28.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/64adfb0d-2062-c12c-e54d-b68897a9d913.png)

# データベースへのアクセス🎄
先程作成したデータベースにターミナルから接続します。
データベースの管理画面の Settings > Database Credentials > View Credentials のHeroku CLIをコピーして実行します。
すると以下のように接続することができます。接続ができればテーブルの作成等を行えます。
![スクリーンショット 2019-12-24 20.58.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/54025e36-f2c0-2071-80b3-d44aea5c46fe.png)

> PostgreSQLの基本的なコマンド
> https://qiita.com/H-A-L/items/fe8cb0e0ee0041ff3ceb

# プログラムの作成🎄
PostgresSQLへの接続のために使用するモジュールを追加します。

```zsh
yarn add pg
```

接続用クラスファイルを作成します。

```database.js
import Pool from 'pg'
module.exports = class DB {
  constructor() {
    this.pool = new Pool({
      connectionString: DATABASE_URI,
      ssl: true,
    )}
  }
  async query(param) {
    const client = await this.pool.connect()
    const { row } = await client.query(param)
    client.release()
    return row
  }
}
```

Expressでサーバを立てます。

```zsh
yarn add express
```

```index.js
import express from 'express'
import database from './database'
const app = express()
const PORT = process.env.PORT || 3000
app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
    next()
})

// jsonを扱えるようにする
app.use(express.json())
app.use(express.urlencoded({
    extended: true
}))

const db = new database
// メイン処理
api.get('/', async (req, res) => {
  const result = await db.query(SQL)
  return res.status(200).send(result).end()
})

app.listen(PORT)
console.log(`Server running at ${PORT}`)
```

このような感じでqueryにSQL文を渡すと結果が帰ってくるAPIサーバを作ることができます。

# デプロイ🎄
GitHubのリポジトリと連携させると簡単にデプロイすることができます。
またデータベースのURIなどをHerokuの環境変数にしましょう。

> heroku 初級編 - GitHub から deploy してみよう -
> https://qiita.com/sho7650/items/ebd87c5dc2c4c7abb8f0

# 監視🎄
Heroku PostgresではDataclipsという機能でデータベースの中身を見ることができます。この機能とても便利です。
![スクリーンショット 2019-12-24 21.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/5573036c-0ad6-d058-e15f-22b00da4758d.png)

# 最後に🎄
Herokuを使うと無料でデプロイからデータベースの利用までできるのでおすすめです。
ぜひ使ってみてください。

> 実際に使用したリポジトリ
> https://github.com/FukeKazki/3i-entry-exit-server
> 入退場システムについてのブログ 
> https://bit.ly/35RHPDm
VMware Hands On Lab でPKS環境をさわってみました

今年の夏にVMworldに行った時に、会場でHands On Lab（以下HOL）環境での研修を受けてみたのですが、そのときに教官からPKS（kubernetes）の教材も近日中にアップされると聞きました。

今回の改めて見てみたらHOLにPKSの教材がアップされていましたので、どんな感じなのかお試しで見てみました。

因みにHOL環境には事務所から問題なく接続できます。実際の環境や動作を確認したいときは大変便利ですね。
（私がVMwareをさわりまくっていたときにはこういうの無かったです。。。ローカルにせっせと環境つくってました。）

# 検証コース：VMware Enterprise PKS - Getting Started

さて、まずHOLに接続します。

https://labs.hol.vmware.com/

(VMwareアカウントの作成等々事前準備あります）

![PKS000003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/2f81b817-37ac-f634-caa6-bad4a9954bf0.jpeg)



このPKSのHOLはまだ英語と中国語のみ対応してました。英語の勉強を兼ねて読み進めます。

### PKSの構成イメージ
![PKS000027.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/bc04d35b-0fc8-089e-d745-7bc5aaf8a1ce.jpeg)

検証環境に接続すると、自動でこの環境がデプロイされ検証用の疑似仮想クライアントが提供されます。

![PKS000015.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/025af1f9-790b-de52-176c-73be3376d33a.jpeg)

![PKS000017.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/647cf9a0-4430-c7c0-a547-050ce4a56c63.jpeg)

ネットワーク設定やクラスタは作成済みで提供されるので、すぐにいろいろとさわってみることが可能。

そしてネットワーク設定のところもシミュレーションが用意されていて確認することができます。

![PKS000028.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/6c1615a1-7c56-552c-a9d3-009c92b8c157.jpeg)

![PKS000029.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/c26ebf6e-00a2-294d-01c1-37461ef789df.jpeg)


画面左のところのオレンジでマークされていることころをクリックしてたどっていくと、シミュレーションが進んでいきます。

### PKSとBOSH
BOSHの１つのHealth monitoring の機能を見てみます。

下記コマンドでBOSHで管理されているコンテナの状況を見ることができて、
![PKS000062.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/361c194f-265d-2fe2-0865-5ebe64fe50c0.jpeg)

VMwareのvCenterでそのコンテナを確認すると、クラスタやノードとして見えるんですねー。

![PKS000064-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/32d629c1-fa80-aacf-27a9-f592020eefc8.jpeg)

vCenter上でそのノードをPower-oFFすると、BOSH上でも落ちていることがわかります。
（しばらくすると自動回復機能で復活してました）



![PKS000069.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540126/023f34b0-5b70-8fac-b8f4-1a8035976591.jpeg)



だいぶはしょりましたが、

このあと、
VMware NSX-T、HARBOR・・・と各機能の研修がつづきます。結構ボリューミーです。（英語だからかも）
また他のコースではアプリ配備のところも含めたものがありそうなので、次回チャレンジしてみたいと思います。

# 所感

初期設定のネットワーク仮想化のところは統合された管理ツールはない。NSX-TやPKSなどの各管理ツールでのそれぞれ設計、設定していくのが複雑。特に設計が大変そう。

基盤の運用管理ツールが、仮想基盤のvCenter、PKS、NSX-T、Kubernetesと分かれていて運用管理も大変そうです。
コンテナの運用機能をもっとさわってみたいと思いました。

非常に簡単にVMwareの高額な各機能を検証できる環境ですので、試してみる価値ありと思います。
C# と SQL Server の DateTime を Assert.Equals する

C# と Database ではそれぞれミリ秒の保持の仕方が異なります。上手く Assert するには比較用のクラスを作って、 Assert の Parameter に渡してあげれば OK です。

## 使っているもの

- xUnit
- SQL Server

## なぜ起きるのか

C# の DateTime ではミリ秒を正しく保持しています。

C#: `2013-05-01 23:59:59.991`

しかし、これを SQL Server の datetime に入れるとこうなります。

SQL Server: `2013-05-01 23:59:59.990`

これには理由があって、ミリ秒の精度が .000、.003、.007 であるためです。よって、このまま Assert.Equals すると Fail してしまいます。

## 解決方法

比較用のクラスをパラメーターで渡してあげて、多少の時間を許容するようにします。

```csharp
Assert.Equal(expected, actual, new SqlServerDateTimeComparer());
```

### 比較用のクラス

いくつか用意してあるので合ったものを使ってください。また、このクラスでは 10 秒までの差は許容しているので、この設定値は Constructor で受け取れるようにするなどすれば、別の比較 (e.g. DateTime が DI 出来なくて死ぬ Unit Test など) にも使えると思います。

```csharp
public class SqlServerNullableDateTimeComparer : IEqualityComparer<DateTime?>
{
    public bool Equals(DateTime? x, DateTime? y)
    {
        if (x == null && y == null)
        {
            return true;
        }
        if (x == null || y == null)
        {
            return false;
        }
        return (x.Value - y.Value).Duration() < TimeSpan.FromSeconds(10);
    }
    public int GetHashCode(DateTime? obj)
    {
        return obj.GetHashCode();
    }
}

public class SqlServerDateTimeComparer : IEqualityComparer<DateTime>
{
    public bool Equals(DateTime x, DateTime y)
    {
        return (x - y).Duration() < TimeSpan.FromSeconds(10);
    }
    public int GetHashCode(DateTime obj)
    {
        return obj.GetHashCode();
    }
}

public class SqlServerNullableDateTimeOffsetComparer : IEqualityComparer<DateTimeOffset?>
{
    public bool Equals(DateTimeOffset? x, DateTimeOffset? y)
    {
        if (x == null && y == null)
        {
            return true;
        }
        if (x == null || y == null)
        {
            return false;
        }
        return (x.Value - y.Value).Duration() < TimeSpan.FromSeconds(10);
    }
    public int GetHashCode(DateTimeOffset? obj)
    {
        return obj.GetHashCode();
    }
}

public class SqlServerDateTimeOffsetComparer : IEqualityComparer<DateTimeOffset>
{
    public bool Equals(DateTimeOffset x, DateTimeOffset y)
    {
        return (x - y).Duration() < TimeSpan.FromSeconds(10);
    }
    public int GetHashCode(DateTimeOffset obj)
    {
        return obj.GetHashCode();
    }
}
```

## Note

[DATETIME データ型のミリ秒に関する注意事項 – Microsoft SQL Server Japan Support Team Blog](https://blogs.msdn.microsoft.com/jpsql/2013/04/23/datetime/)
PHP htmlspecialcharsについて

## [htmlspecialcharsについて](https://www.php.net/manual/ja/function.htmlspecialchars.php)


```php

htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = TRUE ]]] ) : string
```

・特殊文字を HTML エンティティに変換する。
・第二引数は、フラグ定数でクォートや無効な符号単位シーケンス、そして文書型の扱いを指定する。 デフォルトは ENT_COMPAT | ENT_HTML401 

|フラグ定数名 |説明
|:--|:--|
| ENT_COMPAT | ダブルクオートはエスケープするが、シングルクオートはしない |
| ENT_QUOTES | ダブルクオートもシングルクオートも両方エスケープする |
| ENT_NOQUOTES | ダブルクオートもシングルクオートもエスケープしない |
| ENT_HTML401 | HTML 4.01 として処理 |
| ENT_HTML5 | HTML 5 として処理 |

### 変換前と変換後
- `<` → **`&lt;`**
- `>` → **`&gt;`**
- `&` → **`&amp;`**
- `"` → **`&quot;`**

・第二引数に ENT_QUOTES を指定すると、下記の変換も行う。

- `'` → **`&#039;` or  `&apos`;**

・第三引数は、文字エンコーディングを定義。


## 変換する理由
- XSSを防ぐため。
- テキストで入力されたものを正しくHTMLに出力するため。

## 使用例
```php
//次の様なラッパー関数を準備する
function h($str) {
  return htmlspecialchars($str, ENT_QUOTES|ENT_HTML5, "UTF-8");
}
// HTMLに出力する際
echo h('<hoge>');
```
enebularを使ってフィリピンのクリスマス飾りをピカッとさせてみた


##フィリピンのクリスマス飾りをいただきました
皆さん、**メリークリマスマス！**

今日はクリスマスイブですね🌟

そして、かつ自分にとっては彼女さんの誕生日でもあるんです。。
そこで、今回はenebularで彼女さんへのプレゼントをゴニョゴニョしてみました！

実は、彼女さんはフィリピン出身なんです。
そして、とても自分の国のことを愛しています。
この前も、一緒にこうゆうイベントに行きました。

![S__268296196.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/e8b57598-1015-22ab-9516-0e09fc3329dc.jpeg)
こちら、フィリピンフェスティバルという日本で1番大きいフィリピンのお祭りだそうです。

そこで、出展者の方からこのような飾りをいただきました。

[![Image from Gyazo](https://i.gyazo.com/c8ca715e6d065bcd79976ed4fd11c85a.png)](https://gyazo.com/c8ca715e6d065bcd79976ed4fd11c85a)
こちら、フィリピンのクリスマスツリー的な飾りだそうです。

そして、先日この飾りを使ってLチカして彼女さんにプレゼントしました。
その時の記事はこちらです↓

**「フィリピンのクリスマス飾りをLEDで光らせてみた」┐**
https://qiita.com/aki_suga/items/edca18d3a22f777eab09

↑の記事ではArduinoで光らせた飾りを今回はenebularとRaspberry Piを使ってピカピカさせたいと思います！
飾り付けで格闘している様は上の記事から確認してください笑


##フローを作ってく上での格闘

さぁ、それではenebularを使って飾りを制御していきます！

ラズパイを動かせるノードを用意します。

![スクリーンショット 2019-12-24 17.18.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/72dbead0-14d6-82f8-1d8d-f0402fc86cfb.png)
↑こちらはingectとgpioノードです。

しかし、

![IMG_5237.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/14d5eddc-7d80-6f44-da6e-b3d96f6f3d64.jpeg)

あれ？光る様子がない、、、なぜだ、、、

もしかしたらRaspberry Piの中でgpioのコマンドをインストールしてないからかな、、と思いapt getでgpioコマンド打てるようにしてみました。

![IMG_3778.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/04e2d418-c150-50cd-2426-d5ffaccf79a0.jpeg)


がしかし、、、、

![IMG_5237.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/14d5eddc-7d80-6f44-da6e-b3d96f6f3d64.jpeg)


まだ動かない、、

##解決策は力技

なぜだ、コマンドからLチカさせる分にはできるのでLEDや抵抗とかの位置や繋ぎ方には問題ないはず、、
でも、光らない、、

うんともすんともいかないので諦めかけてたんですが、、、

**あ、enebularでコマンド打てばいいじゃん！**
と閃きました笑

たぶん他のenebularやNode-REDを愛してる方々からはお叱りをうけそうですが、まずは形になるモノを！との思いで無理やりやらせていただきました、、

やり方は簡単！

まずは、ラズパイ上で出力させたいピンのモードを変更します。


```
gpio readall
```
で現在の状態を把握します。

僕の場合は使いたかった17ピンがINの0になってました。
ですので


```
gpio mode -g 17 in
```
でgpioのモードをoutに変換しときます。
そして、enebularで

![スクリーンショット 2019-12-24 18.19.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/55446acb-e10c-5364-849e-804d66a46bc8.png)

このようにexecノードを使い、中身に下のようなコマンドをセットしました！

```
gpio -g write 17 1
```

さっそく動かしてきましょう！

![IMG_9411.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/8ed67cd2-d0f3-5036-5b51-bb83e39ce9cc.jpeg)

おお、動いた！！

なかなか、力技でしたが目標達成することできました、、

よかった、、、

みなさん、素敵なクリスマスを！
Moment.jsを使って年齢計算

# サンプル
```sample.js
import moment from "moment";

function calcAge() {
  dateOfBirth = moment(new Date("1994-01-01")); // 生年月日
  today = moment(new Date("2019-12-24")); // 今日の日付

  // 西暦を比較して年齢を算出
  let baseAge = today.year() - dateOfBirth.year(); // >> 2019 - 1994 = 25（歳）

  // 誕生日を作成 >> 2019-01-01
  let birthday = moment(
    new Date(
      today.year() + "-" + (dateOfBirth.month() + 1) + "-" + dateOfBirth.date()
    )
  );
  console.log(birthday) // >> 2019-01-01

  // 今日が誕生日より前の日付である場合、算出した年齢から-1した値を返す
  if (today.isBefore(birthday)) {
    return baseAge - 1; // 24（歳）が返却される
  }

  // 今日が誕生日 または 誕生日を過ぎている場合は算出した年齢をそのまま返す
  return baseAge; // 25（歳）が返却される
}
```
　
他にも。

```js
moment1.isAfter(moment2) // moment1がmoment2より未来の日付かどうか
```

```js
moment1.isSame(moment2, "day")・・・moment1とmoment2が同じ日付かどうか。
// "month"を指定した場合は、年月が同じかどうか
// "year"を指定した場合は、西暦が同じかどうか
```
　

# 正しい日付かどうか
```sample.js
import moment from "moment";

/**
 * 年齢計算
 *
 * @param {Date} baseday
 * @param {Date} birthday
 */
function calcAge(baseday, birthday) {
  console.log(moment(baseday).isValid()); // 正しい日付ならtrue, 不正な日付はfalse
  console.log(moment(birthday).isValid());
}
```
goでたくさんの画像のサイズを小さくしたい!!!!

# はじめに
こんにちはRIN1208です。
本日はクリスマスイブですね!!自分は特に予定がなく部屋で過ごしてチキンを食べました！悲しい....
この記事は画像のサイズ圧縮をかなりの量をしなくてはいけなくなったのでその制作の途中経過です（深刻なアドベントカレンダーのネタ不足....）

またこの記事は[ITRCアドベントカレンダー](https://adventar.org/calendars/4759)の24日目の記事になります。


# 開発環境
- mac
- goの実行環境

# 今回使用したパッケージ

- github.com/google/uuid  
  uuidを使うために使用しました  
  [GitHub](https://github.com/google/uuid)
- github.com/nfnt/resize  
  画像のサイズを変更するのに使用しました  
  [GitHub](https://github.com/nfnt/resize)

###インストール
```
$ go get github.com/google/uuid
$ go get github.com/nfnt/resize
```


# 今回のコード（下で順々に解説します）

```go
package main

import (
	"image"
	"image/jpeg"
	"image/png"
	"io/ioutil"
	"log"
	"os"

	"github.com/google/uuid"
	"github.com/nfnt/resize"
)

func main() {

	files, _ := ioutil.ReadDir("./image")
	for _, f := range files {
		save_image("./image/" + f.Name())
	}

}

func save_image(filename string) {

	path := "./datas/"  //保存先のディレクトリ名になります。現時点のコードでは既に作成していないとエラーが出ます


	uuid := create_uuid() //こちらの部分は後ほど解説します

	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	img, data, err := image.Decode(file)
	if err != nil {
		log.Fatal(err)
	}
	file.Close()
	m := resize.Resize(1000, 0, img, resize.Lanczos3)

	if data == "png" {
		out, err := os.Create(path + uuid + ".png")
		if err != nil {
			log.Fatal(err)
		}
		defer out.Close()
		png.Encode(out, m)
	} else if data == "jpeg" {
		out, err := os.Create(path + uuid + ".jpeg")
		if err != nil {
			log.Fatal(err)
		}
		defer out.Close()
		jpeg.Encode(out, m, nil)
	}

}

func create_uuid() string {
	u, _ := uuid.NewRandom()
	uuid := u.String()
	return uuid
}

```

特に難しいことはしてないでです

# コードの解説

##main()の部分
```go

    files, _ := ioutil.ReadDir("./image")
    for _, f := range files {
        save_image("./image/" + f.Name())
    }
```
ここではimageディレクト下の画像のファイル名を取得しsave_image()関数に画像ファイルのパスを渡しています。

save_image()の部分は下で説明します。

# save_image()の部分

画像のリサイズは以下の部分でしています。数値を変更するとサイズも変更されます。

```go
m := resize.Resize(1000, 0, img, resize.Lanczos3)
```
こちらの部分は取得した画像がpngならpng、jpegならjpegで保存するようにしています

```go
    if data == "png" {
        out, err := os.Create(path + uuid + ".png")
        if err != nil {
            log.Fatal(err)
        }
        defer out.Close()
        png.Encode(out, m)
    } else if data == "jpeg" {
        out, err := os.Create(path + uuid + ".jpeg")
        if err != nil {
            log.Fatal(err)
        }
        defer out.Close()
        jpeg.Encode(out, m, nil)
    }

```

# create_uuid()の部分
ここに関しては特に説明するとがないですが今回使用した理由としては大量の画像のためファイル名がかぶらないようにしたかったので使用しました。（名前は適当でよかったので）



#終わりに
ここまで読んでいただきありがとうございます。今回ここに書いてあるのは制作途中にの物でありこれから並列処理を使用して大量の画像を処理していく予定です。
運営中のモバイルゲームをPCで出すときのQA

#はじめに
運営中のモバイルゲームをマルチプラットフォーム対応する
（PCで遊べるようにする）話を賜って対応しているのですが、
その時に困った点（現在進行形含む）を備忘録的にまとめてみようと思います。

**※現在絶賛QA中なので、リリース後にまた追記するかもですが、予めご了承ください。**
#PC版QAの流れ
PC版を新しく追加する際の基本的なQAの流れです。
ここは本題でないのでさっくり行きます。
##前提
- モバイル版が基本プレイ無料のアイテム課金制アプリとして先行リリースされている
- PC版もモバイル版と同じ運用サイクルでリリースする
- モバイル版とPC版の機能差はデータダウンロード処理や操作方法のみ
    - ※注意事項あり（後述）

##事前準備

- 検証用PCを用意する
    - 動作下限の端末と推奨スペックの端末は必須
- PC用ビルドを作成してもらう
    - デバッグ機能が使える開発用ビルドと、本番環境につながるビルドが必要
- QA範囲を設定する
    - アプリの挙動から運営周りまで、どの範囲をQAで検証するか決める
        - アプリ挙動、パフォーマンステスト
            - モバイル版と同等に動くか
        - PC機能差分テスト
            - キーボード操作やデータのダウンロード方式、モバイル版からの引継ぎ
            - **※モバイル⇔PCの機能差分はQA範囲設定時に明確にしておくこと**
                - **差分は必ずQA範囲に入れるように関係者と合意形成する必要があるため**
        - 運営系テスト
            - PC版アプリ配信ページの確認、事前登録設定の確認
        - 本番テスト
            - 課金のテストや摸擬リリースなど
##検証実施
事前定義したQA範囲に沿って検証を進めます。
基本的には次のように進んでいくかと思います。

    1. アプリ挙動テスト（動くかどうかのチェック）
    2. PC機能差分テスト
    3. 運営系テスト
    4. プレイスルーテスト（パフォーマンス、挙動チェック）
    5. 本番テスト

##リリース

各工程で問題がない（もしくは許容値以下）であればリリースです。
リリースの流れは事前に開発とすり合わせておきましょう。

- リリース時にメンテに入れるか？
    - 入れない場合はどのようにリリース時の障害をケアするか？
- リリース時のエスカレーションフローはどのようになるか？
- リリース後は誰がどこをどのようにチェックするか？

##運用
リリース後の運用フェイズの話も進めておきましょう。

- PC版のQAはモバイル版と差分は出るか？
    - 作業工数や費用の問題

#PC版QAで困った点
本編です。

##動作環境の選定
どのプラットフォームどの課金形態でも生じる問題とは思いますが、
動作端末と書いていたのにアプリが動かない場合、返金につながる恐れがあるので、
推奨/要求スペックはしっかり決めておく必要があります。

モバイルでもAndroidは無数に機種が存在していて、CPUやRAMの性能が同等でも、
メーカーや機種ごとに動作に違いが生じたりしますが…
PCの場合はメーカー製の完成品だけでなく、
自分でパーツを選んでキッティングできてしまうのでパターンが実質無限です。
**すべてのパターンを試すことは当然できないので、**
最低限どこまで担保したいかをしっかりと握る必要があります。

###★検証端末選定の例
- CPU
    - core i3 7世代で検証
        - ※同じシリーズでも世代ごとに性能が全然違うので注意
- RAM
    - メモリ4GBで検証
        - ※メモリも世代で性能差があるのでどこまで見るか要検討
- GPU
    - ノートPCの内臓グラフィックで検証
        - ※描画性能を要求する場合は単体GPUのグレードまで検討する必要あり
- OS
    - windows 8.1(64bit)で検証
        - ※OSの動作bitも決めておいたほうが良い
- ストレージ
    - Cドライブに10GB以上空きがあるPC
        - ※どのくらいストレージを確保しておけばいいかの基準
- プリインストールアプリ等のメーカー固有環境は一部考慮する
    - 検証PCとしてMacBookProとVAIOを使用する
        - ※PCメーカーがプリインストールしているアプリが思わぬ影響を及ぼす可能性があるので、どこまで考慮するかを要調整

##プラットフォームごとに違う設定をする機能
モバイル版とPC版で全く同じ機能を実装してリリースすると決めていた場合でも、
プラットフォームごとに異なる設定をする必要が出てくることがあります。
エンジニアさんやプランナーさんが忘れたままでリリース直前を迎えるととても焦るので、
QA側でこれなくて大丈夫かな？と聞いてあげるとみんな幸せになれるかもです。
以下にその例を記します。

- プラットフォーム別のガチャやアイテム配布
    - モバイルもPCも同じデータを入れると言っていても、リリース記念ガチャや事前登録報酬をPCだけやる！という話が出ることがあるので、直前で焦らないようにここら辺の要件を整理するのが吉。
- お知らせ/規約等
    - プラットフォームによって規約が違う場合や、PC版のみガチャや報酬を配るときにお知らせを出し分けることがあるので、ここも要確認。
- プラットフォームごとのメンテ機能
    - リリース時や障害発生時に、一つのプラットフォームをメンテ入りさせると全部メンテに入ってしまう設定だと困る場合この機能が必要。

##クラッキング対策
PC版はデータを触りやすいので、クラッキングのリスクも高くなります。
暗号化処理やクラック対策ソフトの適用など、忘れたままテスト終盤に行くと…、
ギリギリでプレイスルーテストのやり直しに繋がったりするので要注意です。
これも何もやってなくて大丈夫かなー？とか思ったら念のため聞いておくと吉です。

#最後に
PC版対応で困ったことをとにかく書き連ねてみました。
まだリリースしていないので、リリース後にまた所感を追記してみようかと思います。
それでは皆さん、よいクリスマスを！
UbuntuServer18.04 + Apache2でPythonCGIを動かすまで

## 経緯
- デスクトップのWindows10がぶっとんだ
- Djangoが使えなかった
- でもでもWebアプリっぽいの作りたい！

___そうだ！CGIにしよう！___
というなんとも情けない経緯で始めることになりました。
実際にやってみると微妙なところで結構詰まったりしたので___この通りにすればとりあえずは動くはず___と言うのを紹介していきます。

## 前準備
- サーバに固定IPアドレスを割り当てる
    - 自宅であればルーター設定から割り当てられるはず
    - 携帯とか会社はわかんない
- ネットワークをDDNSと紐付ける([MyDNS.JPの説明](https://nw.myds.me/synology/setup-domain/))
    - 117.125.xxx.xxxとかでアクセスするのダサい
    - グローバルIPアドレスを晒すことになり非常に危険
    - なんかそれっぽくなる
- Python3をインストール済み

## Apache2の準備
### インストール
```
sudo apt install apache2
```
これ一行で問題なし。
UbuntuServerの導入時に「LAMP Server」を選択していればインストールはすでに終わっているので無視して構わない。

### cgiモジュールの有効化

```
user@hostname:~# sudo a2enmod cgid
Enabling module cgid.
To activate the new configuration, you need to run:
  systemctl restart apache2
user@hostname:~# sudo systemctl restart apache2
```
有効化が正常に完了していれば`/usr/lib/cgi-bin`がドCGIのドキュメントルートとして認識されます。
このままでは通常のドキュメントルート`/var/www/html`と場所が違いすぎて面倒なのでドキュメントルートの変更を行う。

### ドキュメントルートの変更 #任意
新規ファイルを作成する。

```
user@hostname:~# sudo vi /etc/apache2/conf-available/cgi-bin.conf
```

内容は

```/etc/apache2/conf-available/cgi-bin.conf
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

<Directory "/var/www/cgi-bin">
    Options +ExecCGI
    AddHandler cgi-script .cgi .py
</Directory>
```

作成できたら設定ファイルをApache2に認識させる必要がある。

```
user@hostname:~# mkdir /var/www/cgi-bin
user@hostname:~# sudo a2enconf cgi-bin
Enabling conf cgi-bin.
To activate the new configuration, you need to run:
  service apache2 reload
user@hostname:~# sudo systemctl restart apache2
```

##コーディングの注意点
- Shebangの記入は必須
    - ないと正常に認識されない
- 開発環境とサーバで環境が変わる場合はShebangの変更を忘れない

## もしもエラーが出たら
### 403 Forbidden(権限エラー)
該当のファイルの権限が間違っている可能性がある。
ターミナルでファイルの場所を開き権限を設定する。

```
user@hostname:~# sudo chmod 755 xxx.cgi
```

### 500 Internal Server Error(スクリプトエラー)
多分一番わかりにくいエラーコード。
エラーログを見るのが一番だけどありがちなのを2つ紹介する。
#### 1. Pythonモジュールがインストールされていない
`ModuleNotFoundError: No module named 'hoge'`が表示されたらとりあえず`pip install hoge`でOK。
pipコマンドでインストールできなければGithubから探してくるのも一つの手段。

#### 2. 日本語が入るとエラーになる
実際に遭遇した例だと半角文字のみの場合は問題なく表示されるが全角文字が含まれるとエラーになったことがあった。
どんな手を使ってもファイルを読み出す時点で文字化けしていたのではさすがにスクリプト内で対処するのは難しい。
そこでApache2の設定を変更する。

```/etc/apache2/conf-available/charset.conf
# 一行追記
AddDefaultCharset UTF-8
```
筆者の場合はこれで解消された。

### 502 Bad Gateway(応答なし)
- ルーターのポート開放はできているか
- ファイアーウォールの設定を解除できているか
    - `sudo ufw allow 80`
- Apacheは起動しているか

これらの可能性をもう一度洗い直してみよう。
JMeter の Master/Slave 構成のコンフィグレーションと実行

JMeterのコンフィグレーションファイルである、`jmeter.properties` を変更する必要がある。特に Distributed Testing を実現するためには、SlaveのIPアドレスをMaster側に渡す`remote_hosts`というプロパティの変更は必須だ。どれがベストプラクティスなのかよくわからなかったので、調べてみた。

# コンフィグレーションの上書き

## jmeter.properties を上書きする

`JMETER_HOME/bin` に `jmeter.properties` が存在し、それがデフォルトで参照されるので、これを変更するのはどうだろうか？公式の[Configuring JMeter](https://jmeter.apache.org/usermanual/get-started.html#configuring_jmeter)によるとお勧めしないらしい。もしやりたい場合は、`JMETER_HOME/bin/user.properties` を編集するか、もしくは、自分用に`jmeter.properties` を作成して、JMeterの実行時に指定することがお勧めらしい。その場合は次のオプションを使う。

```bash
-p, --propfile <argument>
  the jmeter property file to use
```

## コマンドラインパラメータで上書きする

他の方法では、コマンドラインパラメータで上書きする方法がある。[1.4.6 Overriding Properties Via The Command Line](https://jmeter.apache.org/usermanual/get-started.html#override) によると、いくつかのオーバーライドのオプションがある。`-J`オプションを使えば良さげ。また、Masterだけでなく、Slaveにも設定を転送したい場合は、`-G` を使えば良さげ。

```bash
Java system properties and JMeter properties can be overridden directly on the command lin (instead of modifying jmeter.properties). To do so, use the following options:

-D[prop_name]=[value]
defines a java system property value.
-J[prop_name]=[value]
defines a local JMeter property.
-G[prop_name]=[value]
defines a JMeter property to be sent to all remote servers.
-G[propertyfile]
defines a file containing JMeter properties to be sent to all remote servers.
-L[category]=[priority]
overrides a logging setting, setting a particular category to the given priority level.
The -L flag can also be used without the category name to set the root logging level.

Examples:

jmeter -Duser.dir=/home/mstover/jmeter_stuff \
    -Jremote_hosts=127.0.0.1 -Ljmeter.engine=DEBUG
jmeter -LDEBUG
```

# JMeter 実行で使うオプション

今回のプロジェクトで必要になってくるオプションを整理してみたい。

* `-n`: ヘッドレスモード
* `-t`: jmxファイルのパス
* `-l`: ログのパス
* `-e`: レポートの出力
* `-o`: レポート出力のパス
* `-J`: `jmeter.properties`の上書き
* `-r`: リモートサーバをスタートする (`remote_hosts` で定義されたもの)
* `-R <argument>`: リモートサーバをスタートする。`argument` で remote_hosts を上書きする
* `-X`: リモートサーバーをテスト実行後終了させる

## Distributed Testing を実行する

次のオプションを使ってテストを起動してみた。要件は下記の通り

* ヘッドレスモードにしたい
* jmx ファイルを指定したい
* レポートを出力したい
* リモートサーバーを指定して実行したい
* ログファイルを出力したい
* リモートサーバーは実行後終了はしてほしくない

Slave で`nohup jmeter-server &` を実行後に、Master で次のコマンドを実行する。 

```bash
$ jmeter -n -t ./DocumentApi.jmx -l exec.log -e -o report -R 10.0.0.5
```
これで無事上記の要件が実現する。ちなみに、この例だと Slave は１台だが、複数ある場合は、`10.0.0.5,10.0.0.6` みたいにすると良い。

## csv ファイルの転送

衝撃的なことだが、jmxファイル内でつかわれる、cvsファイルは、Slave 側のサーバーに自動で転送されない。つまり、csvファイルを使っている場合は、Slave のパスが通っているディレクトリに csvファイルを転送してから、テストを実行しなくてはいけない。実際に私の環境でも、これがないためにテストが失敗していた。現在は最新5.2を使っている。
* [Issue with Reading CSV file when doing Distributed testing in Jmeter](https://sqa.stackexchange.com/questions/14648/issue-with-reading-csv-file-when-doing-distributed-testing-in-jmeter)

#　まとめ
このセッティングで、無事 Distributed Testing を実行することができた。尚、この他にもJVMのチューニングなどを行う必要がありそう（ヒープの設定など）それはまた別のブログで。
モブプロに加わって半年たちました

初めまして、にゃまと言います。
本記事はモブプログラミングAdvent Calender2019 23日目の投稿になります（1日遅れましたすみません🙇‍♂️）。
https://qiita.com/advent-calendar/2019/mobprogramming

私は今年の5月から新しいチームにジョインし、それから今までモブプロによる開発を続けてきています。
この記事では、自チームにおけるモブプロのやり方について話そうと思います。

## 弊チームのモブのやり方
弊チームは**すべての開発をモブプロ**で行っています。1日の流れはこんな感じ。

| 時間 | 内容 |
| :-: | :-: |
| 10:00 ~ 10:30 | カンバンをみて今日やることと進め方を整理 |
| 10:30 ~ 12:00 | モブを1~2セッション実施 (50min/session) |
| 12:00 ~ 12:15 | 昼会、チーム全体で今やっていることを共有 |
| 12:15 ~ 13:15 | お昼休憩 |
| 13:15 ~ 19:00 | モブを4~6セッション実施 (50min/session) |

バックログやスプリントレビュー、振り返りは週に1回入れて調整しています。
開発で行き詰まったとき、方針転換が必要になったときは、セッションを中断して議論を開始します。案を出し合い、出尽くしたところで一つに決めます。開発メンバーだけで結論を出せないときは、悩み過ぎずプロダクトオーナーや利害関係者に相談して決断します。これを実現するために、スプリント計画の際はバックログアイテムの完了の定義とともに、悩んだとき**誰にどうやって相談したら良いか**まで確認します。
ジョインした頃は家に帰るとすぐベットに入って寝てしまうほど疲れ切ってしまいましたが、最近はこの開発にも慣れて帰宅後にリングフィットアドベンチャーをプレイできるほどになりました。

![mob.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553924/55e40216-b108-be10-6170-121ec717c147.jpeg)


これは内定者アルバイトを迎え入れたときのモブの風景です。新しいメンバーがジョインしても変わらず、アプリケーション構成を**議論しながら開発**をしています。私たちのメンバーは共有PCを活用して1台のPCで開発をしているので、新メンバーがジョインしても環境セットアップの必要がないのです！
画面脇に黄色の付箋が貼られていますが、ここには不定期に行われる振り返りで決めたモブでのTryを書き留めています。画像中の指示棒も、この振り返りであげられた「（ナビゲーターが）何を指摘しているのかわかりにくい」というProblemに対する「指示棒を買う」というTryで購入したものです。こう言った些細な業務改善をみんなでこなせることもモブの醍醐味なのかもしれません。

ここからは、モブプロのよかったこと、改善したいことを話していきたいと思います。

## よかったこと
5月にジョインしてからの半年を振り返ると、何よりも**開発が楽しい**です。自身の得意な領域は強みを生かしてメンバーをリードしていけば良いです。知らない領域・苦手な領域は他メンバーから学べます。他にも次のようなことを感じました。

### タスクを完了させるまでの時間が早い
より正確にいうと、ユーザに価値を届けるまでの時間が短い、いわゆる**フロー効率が高い**です。
基本みんなでコードを書いているので、レビューを必要としません。コードを知る関係者は全員その場にいるので、わからないことがあってもすぐその場で確認できます（裏を返せば、誰もわからないことは失われた知識になります…）。このように一人で開発していると発生する非同期的なコミュニケーションを排除できるので、その分タスクを短い時間でこなすことができます。
また、**多角的な視点で課題に望むことができる**こともタスクを早く完了させることに寄与しています。課題にぶち当たったとき、一人で解決しようとするとその人のスキルセットによった課題解決になりがちですが、複数人のときは複数のアイディアを複合した無駄のない課題解決ができることもあります。

### 失敗を共有できる
モブプロをしていても、ときにはバグを埋め込んでしまったり、障害を起こしてしまうことがあります。これ自体は避けようがありませんが、モブプロではその**失敗からみんなで学ぶ**ことができます。全員が同じ失敗をしているので、次同じようなタスクに直面しても同じ失敗をする確率が少なくなります。また、メンバーが入れ替わったとしても全員が同じ失敗を共有しているので、失敗経験を失うリスクも少なくできます。

## 課題に感じていること
私たちのモブプロはよく機能していると感じていますが、課題となる点もいくつかあります。いちばんの問題は**開発完了からリリースまでの時間が長い**ことです。私たちのCD (Continuous Deploy) は古くから利用されていることもあって、開発完了からリリース完了までに30分かかってしまいます。この間私たちの手を完全に止めてしまい、次のタスクへ着手する足かせとなっています。
私たちはこの課題に対して、できるところから**少しずつ改善**を行っています。とはいえ、古くから運用されているCDなので、改善の見通しが立つときも立たないときもあります。見通しが立つか立たないかで、私たちは次のようなアプローチをとります。

### 改善の見通しが立つとき
見通しのたった部分をタスクに切り出します。複数ある場合は、開発体験が悪く、かつ短時間で解決できることから優先度を高くします。このタスクを、他の開発タスクと優先度を擦り合わせてから着手します。
開発体験が悪いかどうかは、開発メンバーによる主観で判断しています。

### 改善の見通しが立たないとき
あらかじめ調査タスクを設定します。調査タスクには時間の区切りを入れます。調査タスクに着手したら、設定された時間内で、改善の見通しを立ててタスクに切り出す作業を行います。切り出すことに成功したら、見通しが立った時と同様、他の開発タスクと優先度を擦り合わせてから着手をします。

## おわりに
振り返ってみると、自分にとってはコミュニケーションコストやコンテキストスイッチに対するストレスが大きく改善されたように思えます。正直もっと多くの恩恵を受けているように感じますが、言語化できていないので今回はここまで。
私たちのやり方が、ビジネスの成功まで繋がるよう今後もモブプロを改善していきます！
データベース--メモ

# DBでよく使う型

string 文字列型
text テキスト（不定長文字列）型
integer 整数型
float 浮動小数点数型
decimal 固定長整数型
datetime 日時型
timestamp タイムスタンプ型
time 時刻型
date 日付型
binary バイナリ文字列型
boolean 真偽値型
references 他のテーブルへの外部キーの定義、_id が付いた整数

## 電話番号の型を設定するとき

integer型だと10桁まで。電話番号は11桁の時もある。なのでDBに登録できないことがある。
また、09012345678の場合、最初の0が消えることがある。
なので string型をおすすめします。
string型の文字列だとハイフン（ー）もDBに保存ができる
 
``` sample.rb
def change
    create_table :addresses do |t|
      t.references :user, foreign_key: true, null: false
      t.string  :post_code,          null: false
      t.string  :prefectures,        null: false
      t.string  :city,               null: false
      t.string  :address,            null: false
      t.string  :building_name
      t.string  :tel_no
      t.timestamps
    end
  end
```

#参考記事
https://qiita.com/Yinaura/items/cede8324d08993d2065c
https://chinatz.hatenablog.com/entry/2018/07/20/210000
初心者によるプログラミング学習ログ 193日目

#100日チャレンジの193日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

193日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>193日目<br><br>udemyでjqueryをさらっと<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a><a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1209200943377473536?ref_src=twsrc%5Etfw">December 23, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ディープラーニングと機械学習

技術の世界は非常に速く進歩しています。人工知能、機械学習、深層学習が話題になりつつあります。今日は、機械学習と深層学習の違いについて説明します。
このディスカッションでは、定義を確認してから、いくつかの例を見てみましょう。それではまず、機械学習の定義を見てみましょう。機械学習は、コンピューターがデータから学習して予測を行う機能を提供するアルゴリズムです。次に、ディープラーニングとは何ですか？ディープラーニングは機械学習のサブセットであり、脳の構造と機能に触発されたアルゴリズムに関するものです。
![machineai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542616/4e58efc6-928e-b4bb-006d-bd7786d141d4.png)

それでは、簡単な例を見てみましょう。たとえば、入力として画像を受け取り、それが車であるかどうかを判断するアルゴリズムを設計する必要があります。
したがって、機械学習の場合、自動車の特性（フィーチャー）を定義する必要があります。たとえば、車の特徴は、下に車輪があります。機械学習の場合、アルゴリズムは画像を入力として受け取り、画像内のオブジェクトに丸い車輪があるかどうかをチェックしようとします。丸い車輪を見つけることができる場合、オブジェクトを車として分類する場合があり、そうでない場合は拒否されます。
問題は、車輪に穴が開いて、もはや丸くないことかもしれません。そうなると、通常の機械学習アルゴリズムはそれを車として検出しなくなります。そして、ここでディープラーニングが役立ちます。ディープラーニングでは膨大な数の画像を取得し、それらを使用してトレーニングを行います。もう先に進む前に、子供の頃から、自動車を人間として検出する方法をどのように学びましたか？「底に丸い車輪があるもの、それが車だ」と誰かが言ったとは思いません。むしろ、あなたの両親が「見て、それは車だ」と言ったのではないかと思います。あなたの脳はそのデータを入力として受け取りました。それを自己訓練しました。そして、十分な入力を取得した後、あなたの脳が、車かどうかを簡単に検出できるかもしれません。
同様に、深層学習では、アルゴリズムは入力として多くの画像を受け取ります。単独で分析して機能を抽出します。機能自体を定義します。適切にトレーニングされると、正しい出力が得られます。
さて、どのように選択できますか、どちらを使用する必要がありますか？通常の機械学習アルゴリズムまたは深層学習アルゴリズム？答えはとても簡単です。
1）多くのラベル付きデータ　2）高性能GPUの　3）高度なアルゴリズム。したがって、3つすべてを持っている場合、ディープラーニングが最良の選択です。それ以外の場合は、通常の機械学習アルゴリズムを使用する必要があります。
最後に、ディープラーニングと機械学習の概要を把握するために、表を見てみましょう。
![Screen Shot 2019-12-24 at 20.45.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542616/4f30f226-846d-c49a-81e0-f5e14b062b5e.png)
そして最後に、私の悪い日本語をもし訳ございます。
Dockerで使い捨てのMySQL環境を用意する



ローカルで使い捨てのデータベースが立てられると個人で何かと試したいときなどに便利なので、DockerのMySQLイメージを使ったやり方を残しておきます。

## 1.MySQLのDockerコンテナを起動

Dockerの[公式イメージ](https://hub.docker.com/_/mysql)に記載の通り、コンテナを起動します。

```
docker run --name {適当なコンテナ名} -e MYSQL_ROOT_PASSWORD={適当なパスワード} -d -p 3307:3306 mysql:5.7
```
* ここではホスト（Mac）側 port 3307とコンテナのport 3306をマッピングしています。


## 2.アプリケーションから接続

* CakePHP2.9から接続しています。
* "localhost"ではなく127.0.0.1で繋いでください。

```app/Config/database.php
    public $default = array(
        'datasource'=>'Database/Mysql',
        'persistent'=>false,
        'host'=>'127.0.0.1:3307', //ホスト側のportを記載
        'login'=>'root',
        'password'=>'{パスワード}',
        'database'=>'{データベース名}',
        'prefix'=>'',
        'encoding'=>'utf8',
    );
```

## 3.SequelProからつなぐ

* GUIツールからも普通に繋げます。ここでもホスト名は127.0.0.1です。

<img width="429" alt="スクリーンショット 2019-12-24 20.47.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/e2147a68-c569-c74e-56f4-fc335f8716ab.png">
p5jsでPokémon GOっぽいUIを作る(4)

前回までに地図、人、ボタンを雑に表示しましたが、今回は少し趣向を変えて現在地を取得することにします。

まず、地図から。位置情報をURLで渡すとYahoo地図の情報を取得して表示するスクリプトを用意します。

```php
<?php
$appid = "YOUR_APP_ID";
$lat = @$_GET["lat"] ?: "35.66521320007564";
$lon = @$_GET["lon"] ?: "139.7300114513391";
$query = http_build_query([
    'lat' => $lat,
    'lon' => $lon,
    'z' => '16',
    'appid' => $appid,
'base:red|off:address,landmark,line_name,station_name,symbol,area_name',
    'style' => 'off:address,landmark,line_name,station_name,symbol,area_name',
]);
$url = 'https://map.yahooapis.jp/map/V1/static?' . $query;
header('Content-Type: image/png');
readfile( $url );
```

次に、これを呼び出すわけですが、素のgeolocation APIは非同期なのでp5jsのスタイルと合いません。p5jsっぽく位置情報取得できるp5.geolocation.jsというライブラリがあるので、これを使ってみます。

```js
<script src="p5.min.js"></script>
<script src="p5.geolocation.js"></script>
<script>

let img;
let locationData;
function preload() {
  locationData =  getCurrentPosition();
}

function setup() {
  let lat = locationData.latitude;
  let lon = locationData.longitude;
  let url = 'https://example.com/getmap.php'
  img = loadImage(url +'?lat='+lat+'&lon='+lon);

  createCanvas(600, 600, WEBGL);
}

function draw() {
  background(0);
  rotateX(1);

  push();
  texture(img);
  plane(1000, 1000);
  pop();

}
</script>
```

ちゃんと動きますね。今回は自宅の周辺を表示しちゃうので画面キャプチャは省略です。
Ubuntu最高

#昔はインフラエンジニアでした
##LinuxよりUnixのほうが多かったかな
昔はインフラエンジニアでした。
実はHP-UX・AIX・Solaris・DegitalUnixなんて使ってました。
殆どがSparkStationとHPの端末からでしたけど。
その頃はある携帯キャリアの決済システムやWebシステム・メールシステム・メールストアの管理だったんですが。
色んな事やってました。
監視室の設営とかもやってましたね。
若い会社だったので楽しかったですよ。
そのころはLinux使ってみようかなと思ってましたがパーティション壊すのが怖くて使ってませんでした。
##Linuxを組むようになったのは２９歳頃から
Linuxでシステム組むようになったのは２９歳ぐらいのときから組んでました。
それまではFD起動で遊んでました。
遊びが好して仕事になってました。
でも困ったことが一つなぜか知らないけどサーバ管理以外の仕事も引き受けさせられ地獄でした。
##Linux系の通販のバックオフィスの会社に入りました。
その時もLinuxを楽しんでました。
どんな組み方できるか日々VMを潰しながら研究したりLinuxインストールしたりして勉強と研究に没頭してました。
たまには東京にサーバ設置という名の出張もしていましたね。
あのときも楽しかったんですがクラッカーにやられたことがあって大変な目にあったことがあります。
夜半になっても原因がわからず最終的には◯国系クラッカーが攻撃していたとのこと怖かったです。
##その会社をやめた理由は実はプログラマーになりたかった。
プログラマーにはなりたかったんですがインフラが楽しすぎたんですね。
そろそろプログラミングがしたいなと思い楽しかったのですがその会社をやめ通販会社に行きました。
ですが、Access使ったシステムだったのです。
何も教えていただけませんでした。
それからというものLinuxは遊びで使うものと考えていました。
CentOSばかり使ってましたね。
そのころ。
##岐阜県のスマホ人材育成生になりました。
それぐらいからですかね。
ちょっとWindowsが嫌になってきたのはついに師匠からMacBookWhiteを譲っていただきました。
それからというものWindowsよりMacOSやLinuxのほうがいいやと思っていました。
##ついにであってしまった。
Ubuntuに出会いました。
CentOSって意外と設定がめんどいのとチューニングがめんどくさいのでいいのないかなと探していたら見つけちゃいました。
Ubuntuくんを。
それからと言っていいものAspireOneにUbuntu突っ込んだりMacにVirtualbox入れてUbuntu入れたりしています。
WSLも実はUbuntuです。
それだけUbuntuが好きなのにはやはりチューニングのしやすさにありました。
それだし起動は早いし。
最速インストールが必要でない限りはUbuntuですね。
やっぱ新しいものも早く手に入るし楽しいもん。

Ubuntu談義になってしまいすいませんでした。

みなさんもLinuxライフ楽しんでください。
基本情報技術者試験の勉強計画　第10週（12/23週）

## 目標と結果
### 目標
・体調管理に気を付ける
・部屋の掃除をして勉強がしやすい環境づくり
・過去問道場平成30年度を繰り返し解く
### 結果
・勉強がしやすくなりました
・平成30年度であれば解けるようになった
## 振り返り
### Keep
・繰り返し解くこと
・意識
### Problem
・ついつい寝てしまう
### Try
・次は違う年度の問題も解く
toioコミュニティのこれまでとこれから。

これは[「toio™(ロボットトイ | toio（トイオ）) Advent Calendar 2019」](https://qiita.com/advent-calendar/2019/toiotomo)最終日の記事になります。

## まずはじめに
toio™(ロボットトイ | toio（トイオ）) Advent Calendar 2019の投稿が、全て埋まった事に感激です。
執筆者の皆さん本当にお疲れ様でした。最初は運営の勢いで、立ち上げてしまったのですが、みなさんの熱意が本当に頼もしかったです。これからtoioを使ってものづくりを始める方、中級から上級に進んでいく方、などなど非常に多くの方へ価値の高いまとめが完成した!!! と思っております。

## toio™で作ってみた！友の会（非公式）についての紹介
”（非公式）”と書いてある通り、完全に趣味のメンバーで構成され…構成されっ…?うん。構成されており（笑）toioの可能性にチャレンジしていく集まりでございます。コミュニティルールを守り、toioに興味がある方であれば、どなたでも参加が可能です。投稿をずっと見る参加スタイルも全然構いません。

toio™で作ってみた！友の会（非公式）
https://www.facebook.com/groups/toiotomo/

## "ゆるい"運営体制
”ゆるい”という言葉は人によって誤解も生みそうなので、少し補足すると、”作りかけ”、”役に立たない”みたいなものづくりを当たり前に推奨してます。ものづくり界隈の皆さんにあえて言うまでもないですが（笑）何かしらやりたいことにチャレンジしたり、思いついた事をやってみて共有しよう！みたいな場所で、オンラインでもリアルでも細々と続けていければと思っております。LT会を過去2度行ってきまして、参加した方であればその居心地は分かってくれると思うのですが、どなたでも、そんなにハードルを感じず楽しめるような運営体制です。たまに運営で至らない点（バグ）が起きますが、温かい心で見逃してもらえると助かります。（反省）

過去のLT会の様子
【第1回】
 -  イベントページ ⇒ [toio™で作ってみた！友の会（非公式）第1回LT会 : ATND](https://atnd.org/events/107886)
 - ツイートまとめ ⇒ [つぶやきのまとめ](https://togetter.com/li/1402490) 
【第2回】
 - イベントページ ⇒ [toio™で作ってみた！友の会（非公式）第2回LT会 - connpass](https://toiotomo.connpass.com/event/153101/)
 - ツイートまとめ ⇒ [つぶやきのまとめ](https://togetter.com/li/1433654)

## 次回のイベントについて

次回についてはこれまでの参加アンケートから意見をまとめ、希望の多かった、家族と一緒にゆるく参加できる
イベントを管理者の1人でもある[@youtoy](https://twitter.com/youtoy)さんが立ち上げてくれました。
第３回目のイベントは2020/01/19(日)にLODGE（Yahoo! JAPAN）イベントスペースで行います。ぜひご興味のある方はご参加くださいませ。
[toioで作ってみた！友の会（非公式）第3回もくもく＆交流会](https://toiotomo.connpass.com/event/157360/)

## イベント出展について

そしてこちらも作ってみた物をアウトプットしたいという意見があり、色々アウトプットできるイベントを探り
吉報がとどきました。

2020年2月15日(土)・16日(日)につくばカピオ（茨城県つくば市竹園1-10-1）で開催される
[Tsukuba Mini Maker Faire 2020](https://tmmf.jp/2020/)の出展が承認されました。
展示の規模は机1つ椅子2つという形ではありますが、多くの方へ作ってみた物が触れられる機会となると思いますので
ぜひイベントへもご来場頂ければ幸いです。

来年はいよいよ2020年。toioも新タイトルの発売も予定されておりますので、楽しみですね。
我々もハックしながら面白い仕掛けを1つでも、2つでも多く出せていければと思います。

来年もよろしくお願いいたします。それではよいお年を!!!
Firebase Cloud Messaging API をPHPで叩いてみた

# Firebase Cloud Messaging API をPHPで叩いてみた
仕事でFirebaseを使ってモバイルアプリのプッシュ通知機能を実装することになったため、０から一人でネットの海を彷徨いながら調べたことをつらつらと書いていきます。

## とりあえずAPI叩くには
自分の環境にcurlコマンドをインストールし、それぞれ必要な値を入力した下記コマンドをターミナルで叩いてみてください。

```
curl -X POST --header "Authorization: key={SERVER_KEY}" \
--Header "Content-Type: application/json" \
https://fcm.googleapis.com/fcm/send \
-d @- << EOF
{
    "registration_ids": ["{DEVICE_TOKEN}"],
    "notification": {
        "title": "{TITLE}",
        "body": "{MESSAGE}"
    },
    "priority": 10
}
EOF
```

{SERVER_KEY} = Firebaseコンソールを開き、プロジェクトの設定>クラウド メッセージング>プロジェクト認証情報 に記載されているサーバーキーの値を入力してください。

{DEVICE_TOKEN} = 対象のアプリから取得したデバイストークの値を入力してください。

{TITLE} = プッシュ通知に表示するタイトルを文字列で入力してください。

{MESSAGE} = プッシュ通知に表示するボディ部分のメッセージを文字列で入力してください。

コマンドを叩くと下記のようにmessage_idが返ってくれば成功です。

```
$ curl -X POST --header "Authorization: key=**********" \
> --Header "Content-Type: application/json" \
> https://fcm.googleapis.com/fcm/send \
> -d @- << EOF
> {
>     "registration_ids": ["**********"],
>     "notification": {
>         "title": "TEST",
>         "body": "This is test push."
>     },
>     "priority": "high"
> }
> EOF
{"multicast_id":**********,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"**********"}]}
```

## PHPで書いてみた
curlコマンドだけではシステムに組み込む際に面倒だと思うので、続いてPHPで上記一連の処理を下記のように実装してみました。

```
<?php
define( 'FCM_API_SEVER_KEY', '{SEVER_KEY}');
define( 'FCM_API_URL', 'https://fcm.googleapis.com/fcm/send' );
$data = [
        "registration_ids" => ["{DEVICE_TOKEN}"],
        "notification" => [
                "title" => "{TITLE}",
                "body" => "{MESSAGE}"
        ],
        "priority" => "high"
];

$header = [
        'Authorization: key=' . FCM_API_SEVER_KEY,
        'Content-Type: application/json',
];
$context = stream_context_create(array(
        'http' => array(
                'method' => 'POST',
                'header' => implode(PHP_EOL,$header),
                'content'=>  json_encode($data),
                'ignore_errors' => true
        )
));

$response = file_get_contents(
        FCM_API_URL,
        false,
        $context
);

$result = json_decode($response,true);

// 返却値を確認
var_dump($result);
```

このファイルを下記のように実行すれば先ほどのcurlコマンドと同じようにプッシュ通知を送信できます。

```
$ php fcmReq.php
array(5) {
  ["multicast_id"]=>
  int(**********)
  ["success"]=>
  int(1)
  ["failure"]=>
  int(0)
  ["canonical_ids"]=>
  int(0)
  ["results"]=>
  array(1) {
    [0]=>
    array(1) {
      ["message_id"]=>
      string(16) "**********"
    }
  }
}
```

## 参考記事
https://qiita.com/nkmrh/items/e964d916f9a2620a1b80
https://qiita.com/re-24/items/542f39220a606e319fa1
Dispose three.js objects with Nuxt

Nuxt のページ遷移時に three で作ったオブジェクトを破棄したいとき、メモリリークをケアするための tips です。

少し前にちょうどアドベカレンダーで次の three x Nuxt な記事が書かれていました。

* [three.js with Nuxt.js - Qiita](https://qiita.com/misaki_mofu/items/145ac26d600b429a6f8a)

この内容で Nuxt で three をやっていくのはつかめると思うので、破棄部分のみ書いていきます。先述の記事には EventBus で Vue コンポーネント側から three の描画スクリプトのメソッドを発火させていましたが、Vue から剥がしやすくしておくために、今回は data にインスタンスを格納して取り回していくことを想定しています。

パフォーマンス考えるならやはり Vue に依存しない自前の EventBus で実装するとか Three の `EventDispatcher` を使うのがよいかなと思います。もしくは [Non-reactive data](https://qiita.com/miyaoka/items/5183c143e195455ae65e#8-non-reactive-data)  とか。(場合によりけりですね、Vue 縛りなら先述の記事のように対応するのが一番簡単でスマートかと … また追記します)

Page/xxx.vue の `beforeDestroy` で破棄メソッドを実行します。このときcanvas が消えるので、UX を考えると、先に loader の展開を待ってから実行するなど考慮しておくとよいですね。

```pages/xxx.js
import { NiceThreeScene } from '~/assets/js/NiceThreeScene'

export default {
  data() {
    return {
      canvas: null,
      frameId: 0,
    }
  },
  mounted() {
    this.init()
  },
  beforeDestroy() {
    this.canvas.finish()
    cancelAnimationFrame(this.frameID)
  },
  methods: {
    init() {
      const { canvas } = this.$refs
      this.canvas = new NiceThreeScene({ canvas })
      //
      this.update()
    },
    update() {
      this.frameId = requestAnimationFrame(this.update)
      this.canvas.update()
    },
  },
}
```

```assets/NiceThreeScene.js
export class NiceThreeScene {
  constructor({ canvas }) {
    // ... init ...
  }

  /**
   * called by raf
   */
  update() {
    if (!this.needsStopUpdate) {
      const time = 0.001 * performance.now()
      this.animationObjects.update(time)
      //
      this.renderer.render(this.scene, this.camera)
    }
  }

  /**
   * called by beforeDestroy
   */
  finish() {
    this.needsStopUpdate = true // stop update method
    //
    this.disposeThreeObjects(this.scene, this.renderer) // dispose 
    //
    this.canvas.width = 1 // resize canvas
    this.canvas.height = 1 // resize canvas
  }

  disposeThreeObjects(scene, renderer) {
    scene.children.forEach(obj => {
      obj.traverse(obj3D => dispose(obj3D))
      scene.remove(obj)
    })

    renderer.dispose()
    renderer.forceContextLoss()
    renderer.domElement = null
  }
}

function dispose(obj) {
  if (obj.geometry) {
    obj.geometry.dispose()
    obj.geometry = null
  }
  if (!!obj.material && obj.material instanceof Array) {
    obj.material.forEach(material => disposeMaterial(material))
  } else if (obj.material) {
    disposeMaterial(obj.material)
  }
}

function disposeMaterial(material) {
  if (material.map) {
    material.map.dispose()
    material.map = null
  }
  material.dispose()
  material = null
}
```

ざっくりまとめると update の処理をスキップ、 three のオブジェクトを破棄して canvas をリサイズする流れです。

こちら Three.js Advent Calendar 2019 12.24 でした。

* [Three.js Advent Calendar 2019 - Qiita](https://qiita.com/advent-calendar/2019/threejs)

おわります。
メリークリスマス🎅🏻
Nuxtで「vue-clickaway」のディレクティブをグローバルに登録する

# vue-clickaway
https://github.com/simplesmiler/vue-clickaway
要素の外側をクリックしたときにイベントを起こせるライブラリ

# コード
pluginsの中で、

```js
import Vue from 'vue'
import { directive as onClickaway } from 'vue-clickaway';
Vue.directive('onClickaway', onClickaway);
```

インポートしたディレクティブのグローバル登録がよくわからなかったのでメモ
[備忘録]Next.jsプロジェクト導入方法

個人の備忘録です。

#Next.jsの導入方法

##前提条件
Node.jsは導入済みとする。

##方法
プロジェクトフォルダにpackage.jsonファイルを作成する。
内容は以下の通り

```"package.json"
{
   "scripts": {
      "dev": "next",
      "build": "next build",
      "start": "next start",
      "export": "next export"
  }
}
```

フォルダ内で以下のコマンドを実行する。

```
npm install --save next react react-dom
```

##ページ作成
プロジェクトフォルダにpagesフォルダを作成する.
このフォルダがWebページを配置しておくための場所になる。

このフォルダ内にindex.jsファイルを作成する。
内容は下記の通り

```index.js
export default () =>
  <div>
    <h1>Next.js</h1>
    <p>新しいプロジェクトです！</p>
  </div>
```

##プロジェクトの実行

プロジェクトフォルダ内で下記のコマンドを実行

```
npm run dev
```

ブラウザで確認する。
<img width="509" alt="スクリーンショット 2019-12-24 20.13.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360790/48de5bb5-f098-ad94-833a-75d79f14ae3b.png">


以上
Microsoftが試験配信ミス？AZ-103 合格したが異様に点数が低くひょっとしたら...

#トラブルか仕様か？
AZ-103試験配信トラブルでネット検索していたところ、実機試験なしで46問で試験終了になったのはテスト配信の不具合ではないかという受験者が他にいた。確かに7割程度の問題を解いた後に実機があり実機試験後に3割の問題が「表示される可能性がある」との試験開始前注意事項があったので不自然と言えば不自然。逆に言うともしそうだとしてもそこまでの回答が良ければ他を捨てても合格ラインに達することは私が証明したことになる。ちなみに私の点数は760点だった。自信を持って回答したものが多かったのでえらい低いなあとは思ったが。

合格ラインに達せず意図しない形で不合格になると再試験の可能性があるので落ち着くまで受験は待った方が良いのではないか...調査や疑問がある場合はexam challengeというフォームをMCPフォーラムに提出すると再試験ができることがあるらしい。まずはフォーラムでマイクロソフトMCP担当に聞くことから始めないといけないようだ。

#トラブル報告：
https://trainingsupport.microsoft.com/en-us/mcp/forum/all/az103-exam-issue-no-lab-questions-at-all/c2e027df-5046-47c3-adff-a8bfd1141690
https://trainingsupport.microsoft.com/en-us/mcp/forum/all/az-103-test-with-no-lab/15b199dd-c1be-41e2-8745-c10acf8d818e

#前回の投稿：
https://qiita.com/mnoda/items/7738d39a040c7f5f8f25

#日本のMCPサポートに連絡はしておきました
https://trainingsupport.microsoft.com/ja-jp/mcp/forum/all/az-103-azure-administrator/098d98db-a0f8-4a37-9bc9-d0093ceb2a5f
【初心者向け】Tableauのデータ接続についてざっくり独自解説！

はじめに
-----

はじめに、こちらは初心者向け記事となります。
Tableauの使い方を教えていく上で初心者の方がはじめに躓くポイントかなと思い記事を作成いたしました。
書籍とかを参照するとあまり説明がなく、用語を多用する場合もあるので、参考にしていただければ。

Qiitaで普段記事を書いている皆様には既知な内容かもしれませんが生暖かい目で見てくださると幸いです。

本当に初歩の初歩です！！！

前提として　(データベースとテーブルを理解されている方はスルーください)
-----
基本的には、Tableauはファイルや、サーバーへ接続して可視化をしていくかと思いますが、
接続する前にデータベースとテーブルのイメージを理解いただきたいと思います。


Excelに置き換えるとイメージがしやすいと思います。

まずは、データベースは、Excelの1ファイルと思ってください。
1ファイルの中にタブを複数展開できるかと思いますが、そのタブが【テーブル】です。

ざっくりですが、データベースの中にテーブルがいっぱいあるぞー！と思ってください。

各データ接続オプションについてざっくり解説
-----

恐らく文字にすると混乱することも多いので、画像にしました。


###■結合
![結合.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87028/68d3832d-300c-8e19-7390-2d9a4105e7a7.jpeg)

**使用用途："単一"データベース内に分析したい2つ以上のテーブルがある場合に使用**

とても基本的な結合の仕方です。
結合は、テーブル同士が横にくっつくイメージです。

###■ブレンド
![ブレンド.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87028/65ac2539-8ce9-2064-a9e4-0edd93d83239.jpeg)


**使用用途："複数"データベース内に分析したい2つ以上のテーブルがある場合に使用**

データベースが別々になっただけで、基本は結合と変わらないです。

###■ユニオン
![ユニオン.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87028/9d601c64-c663-f32f-64f6-48d8d0483329.jpeg)


**使用用途：列名が一緒で参照したい表が別データベースやテーブルにある場合**

結合とブレンドと違いテーブル同士は縦に繋がります。
また、画像は"単一"データベースですが、複数でも問題はございません。

最後に
----------------------
1から勉強したため独自の解釈が多いかもしれません。
私の解釈が異なっている場合は、ご指摘いただけますと幸いです。

また、「内部結合」「左・右結合」「完全外部」は別途追記させていただきます。
Stay Hungry Stay Foolish in Code Chrysalis ~ Hakobot ~

この記事は [CodeChrysalis Advent Calendar 2019](https://qiita.com/advent-calendar/2019/codechrysalis) の記事です。

# はじめに

先日、Code Chrysalis Immersive 9期卒業生が数人集まって、[Hakobot](https://hakobot.com/)を興味津々に触っていました。彼らは特にIoTに興味があって卒業日にIoT関係でなにか作りたいと言っていたのは聞いていたのですが、さっそく行動に移しているようです。

![IMG_20191122_192018.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141607/9d65e8ae-55f5-a74b-0d8b-7266c844554e.jpeg)

[Hakobot](https://hakobot.com/)は自動輸送を実現するために開発されているプロダクトです。例えば今自動車産業もTESLAが代表されるようにソフトウェアを中心として業界を席巻する会社が出て生きていますが、自動運転によって輸送業界も大きな変化が起こる可能性は十分に秘めており（というか遠からずそうなるであろう）、物流にもこの波は起きることを見越して開発されています。

面白い話を伺ったのは、ハードウェアエンジニアとソフトウェアエンジニアの考えるプロセスは異なるということです。まさにIoTは両方必要とされる分野であり、上手く両者の知見が活かせれば面白いプロダクトが生まれるということで、Code Chrysalisの卒業生で興味を持った有志が触らせてもらっています。

## おもしろい！やってみたい！からプロダクトは生まれる

このようにやってみたい！と思えるメンバーが集まってガチャガチャ遊んでみることで、面白いアイディアやその実現は生まれていきます。

なにせ私たちCode Chrysalisの卒業生はフルスタックソフトウェアエンジニアです。「こうすればいいんじゃない？」と思ったらソフトウェアであれば自分たちで作ることができます。

まるでガレージですよね。WindowsもGoogleもガレージからだったわけです。

## Stay Hungry

そして卒業したらそれで終わりではありません。じゃあこれ次学んでみたいとかこれ試してみたいとかどんどん好奇心の範囲を広げて試してみる。

そうやっていつの間にかできることも増えていくし、そのときにできなくても素早く学んで実行に移せる。このサイクルを生み出す人間になります。

## Stay Foolish

大事なことは自分の仕事には関係ないことでも、興味があったら触ってみれば良いじゃないかということです。ソフトウェアエンジニアだからといってエンジンアリングだけ知っていればよいわけではない。代表のKaniは自然が大好きで千葉県の海にたまに行っているし、そういった遊びだって大事。

もしくは真面目な話でもファイナンス、マーケティング、デザインなどなど、自分の幅を広げられることはなんでもあります。自分がやってみたいと思えるものに手を出してみれば良い。まずはTryです。Tryする前に向いているのか向いていないのかを気づくことはできません。

たとえば「あなたは過去にこうだったのだからそれは向いていない」とか「あれもだめだったからこれもだめ」といくら推論したって、実は好きになれるかもしれません。他人に言われたからと言って本当にそうなるかはわからないじゃないですか。

## 今後のHakobotに乞うご期待

今後も卒業生がHakobotで”遊ぶ”のを定期的にチェックして、どんな動きがあるのかを見てみようと思います！

![IMG_20191122_180323.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141607/a5e4db54-7a0d-4015-b6a6-f4b2f8d7f73e.jpeg)
スター乞食にスター爆撃をするためのCLTを作ったよ

[Swift/Kotlin愛好会 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/love_swift_kotlin)の空き枠を埋めに来ました。

# 作ったもの
https://github.com/417-72KI/SSGH

# インストール

Homebrew対応させました

```sh
$ brew tap 417-72KI/SSGH
$ brew install ssgh
```

# 使い方
## GitHubトークンが必要なのではじめに作ります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135304/8c407631-dfc4-664c-42d1-accf878b3198.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135304/cf684f87-d932-01f2-7835-cfe7f8f0ed1c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135304/af70b4d8-66cb-dce9-a6b9-5f72879426b1.png)

## できたトークンを環境変数にセットします

```sh:.bashrc
export SSGH_TOKEN='{コピってきたトークン}'
```

## 後はGitHubのアカウントを指定してコマンドを叩くだけ！

```sh
ssgh 417-72KI
```

# 仕組み
やっていることは非常に単純ですが、GitHub APIの仕様に癖があって微妙に苦戦しました。

- ユーザ情報取得 ([`GET /users/:username`](https://developer.github.com/v3/users/#get-a-single-user))
- リポジトリリスト取得 ([`GET /users/:username/repos`](https://developer.github.com/v3/repos/#list-user-repositories))
- 各リポジトリごとにスター済みか確認 ([`GET /user/starred/:owner/:repo`](https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository))
- スターしていないリポジトリにスターを付ける([`PUT /user/starred/:owner/:repo`](https://developer.github.com/v3/activity/starring/#star-a-repository))

リポジトリリストから取得できたエンティティにはスター済みかのフラグが無いため、各リポジトリに対してスター済みか確認するAPIを叩く必要があります。
このスター済み確認API、なんとレスポンスは空っぽで、

- スター済みならステータス204
- 未スターならステータス404

という不思議な仕様になっています。
そのため、レスポンスのステータスコードを見て404なら正常系として扱うようにエラーハンドリングをゴニョゴニョする必要がありました。
奮闘の結果は[こちら](https://github.com/417-72KI/SSGH/blob/master/Sources/GitHubAPI/Starred.swift)を御覧ください(

## 使ったもの
- [APIKit](https://github.com/ishkawa/APIKit)
- [Commander](https://github.com/kylef/Commander)

# TODO
- ターゲット複数指定爆撃
- フォロワー全員に爆撃

# 余談
名前の由来ですが、7年くらい前に流行った[ShootingStar](https://octoba.net/archives/20120514-android-app-4.html)というTwitterクライアントをリスペクトしています。
当時のTwitterは「いいね」ではなく「お気に入り(ふぁぼ)」があり、そのアイコンが☆でした。
また、[ふぁぼ爆撃](https://www.weblio.jp/content/%E3%81%B5%E3%81%81%E3%81%BC%E7%88%86%E6%92%83)という文化もあり爆撃専用に作られたのがShootingStarというクライアントでした。

# 終わりに
誰かから「スターください」って言われたらこのツールを使って爆撃していってください。

そしてこの記事を見たそこのあなた、後は分かるね？(
【Veevalidate】 まとめ(v3対応)

# 【Veevalidate】 まとめ

```vue:example.vue
<ValidationObserver ref="obs1" v-slot="{ errors, invalid, touched }">
...
</ValidationObserver>
```
## バリデーション初期化
```js
methods: {
  test () {
    this.$refs.obs1.reset()
  }
}
```

## 特定のflags(ex. touched)にアクセス
```js
methods: {
  test () {
    this.$refs.obs1.flags.touched
  }
}
```