OmniAICreator/Qiita-1.07M huggingface dataset:
C#でコールバック処理をPromiseる

#javascriptの場合
javascript には `Promise` という、コールバック地獄を緩和する仕組みが（最近は）あります。

例えば、　`setTimeout` はコールバックで指定したfunctionを呼んでくれます。

```javascript
setTimeout( function(){ console.log("Hello");} , 5000); // 5000ミリ秒後に "Hello" と出力される
```

「じゃぁ、5秒後に"Hello"って出力した後、さらに4秒後に"good"って出力して、さらに3秒後に"by"って出したいな」

```javascript
setTimeout(function() {
    console.log("Hello");
    setTimeout(function() {
        console.log("good");
        setTimeout(function() {
            console.log("by");
        },3000); //3000ミリ秒後に "by" と出力される
    },4000); //4000ミリ秒後に "good" と出力される
}, 5000); // 5000ミリ秒後に "Hello" と出力される

```

はい。死ねますね。　これが俗にいう「コールバック地獄」というやつです。

これを、`Proimse` でラップしてあげる（＋最近のJavaScriptならasync~awaitで待ち受けたりすると)

```javascript
function sleep(waitms) {
    return new Promise(function(resolve)
    {
        setTimeout(function() {
            resolve();
        }, waitms);
    });
}

async function Test(){
	await sleep(5000); //中で発火される setTimeout が 5000ms後にPromiseのresolve()を呼ぶ＝終了とみなす
	console.log("Hello");
	await sleep(4000);
	console.log("good");
	await sleep(3000);
	console.log("by");
}
```

はい。めっちゃ見やすくなりましたね。

#C#の場合

非同期の結果通知がコールバックしかないような処理をTaskとして待ち受けられる Promiseクラスを作ってみました。

```cs
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

public class Promise<TResult> : IDisposable
{
    public delegate void PromiseResolve(Action<TResult> resolve);

    public delegate void PromiseResolveReject(Action<TResult> resolve, Action<Exception> reject);

    private readonly TaskCompletionSource<TResult> tcs;
    private readonly PromiseResolve unRegistResolve;

    private readonly PromiseResolveReject unRegistResolveReject;

    public Promise(PromiseResolveReject registCallback, CancellationToken ct = default) : this(registCallback, null, ct)
    {
    }

    public Promise(PromiseResolve registCallback, CancellationToken ct = default) : this(registCallback, null, ct)
    {
    }

    public Promise(PromiseResolveReject registCallback, PromiseResolveReject unRegistCallback,
        CancellationToken ct = default)
    {
        tcs = new TaskCompletionSource<TResult>();
        if (ct != default) ct.Register(() => tcs.TrySetCanceled(ct));
        registCallback(Resolve, Reject);
        unRegistResolveReject = unRegistCallback;
    }

    public Promise(PromiseResolve registCallback, PromiseResolve unRegistCallback, CancellationToken ct = default)
    {
        tcs = new TaskCompletionSource<TResult>();
        if (ct != default) ct.Register(() => tcs.TrySetCanceled(ct));
        registCallback(Resolve);
        unRegistResolve = unRegistCallback;
    }

    public void Dispose()
    {
        if (unRegistResolve != null)
            unRegistResolve(Resolve);
        else
            unRegistResolveReject?.Invoke(Resolve, Reject);
    }

    public TaskAwaiter<TResult> GetAwaiter()
    {
        return tcs.Task.GetAwaiter();
    }

    private void Resolve(TResult result)
    {
        tcs.TrySetResult(result);
    }

    private void Reject(Exception ex)
    {
        tcs.TrySetException(ex);
    }
}
```

イベントの追加と削除のあたりがなんかダメっぽいですね・・・。
bashエラー

シェルやcrontabで標準出力（正常）はファイルに書き出し、標準エラーはターミナルに出力したい場合

```
00 03 * * 1-5 command >> /var/log/cron.log 2>&1
```
http://qiita.com/junp/items/deead60abfe5300224f8
http://qiita.com/laikuaut/items/e1cc312ffc7ec2c872fc
memcached

http://gihyo.jp/dev/feature/01/memcached/0001

- 再起動

```
$ sudo /etc/init.d/memcached restart
```

- memcachedのキャッシュ削除

```
$ telnet localhost xxxxx
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
flush_all
OK

quit
Connection closed by foreign host.
```
SQLコマンドめも

##

## sqlファイル実行
```
cd [sqlのある場所]
mysql -uxxxx -pxxxx
mysql> source [sqlファイル名]
```
## 表示
- 縦表示

```
select * from order where id = 123 \G;
```
- 検索結果を | で区切りたい

```
SELECT
  GROUP_CONCAT(DISTINCT  concat_ws('|', code, name)  ORDER BY code separator '|')
FROM
  ...

# 結果
01|aaa|02|bbb|03|ccc
```
## CSV
- タブ出力

```
into outfile "/tmp/sample1.csv" fields terminated by '\t';
```

## 日時
- 範囲指定

`where`で日時の範囲を指定することがあるが

```
where rd.created_at >= '2015-04-01' and rd.created_at <= '2016-04-01' 
```
betweenでも指定できる

```
rd.created_at between '2015-04-01' and '2016-04-01' 
```

## DB
- トランザクション制御

```
start transaction;
SQL文
正常に終了したことを確認
commit;
```
- ホスト名

```
mysql> show variables like 'hostname';
```
Javascriptで毎秒確率で起動するプログラム

# ソースだけ
使う機会は（おそらく）ない。

```javascript
  // 時間帯の起動数を秒数で割って、確率で起動
  // 60起動なら 60分(60*60秒)の間に60起動だから、毎秒1.6%(60/3600)の確率で起動
  var kidosu = 60;
  var atari = (function (kidosu) {
    var a = random(1, 60*60);
    if (a <= kidosu) {
      return 1;
    }else{
      return 0;
    }
  });

  // 1時間で何回当たるか
  var o = 0;
  for (var count = 0; count < 60*60;){
    count++;
    if(atari(kidosu) == 1){
      o++;
    }
  }
  console.log(o + '回起動');
```
コマンドでmysqlへアクセス

DBへのアクセス

```
/usr/local/mysql/bin/mysql --default-character-set=utf8 -u[ユーザー名] -p[パスワード] -h [DBサーバーのホスト名] [database名]
```
DB情報　だいたいこの辺りに情報が記載されていると思う

```
app/confing/database.yml 
app/confing/app.yml 
```
gormのDelete時の挙動検証

[gormのドキュメント](http://gorm.io/ja_JP/docs/delete.html#Delete-Record)に記載されているWARNINGが怖かったので、サンプルコードを書いて動作の確認をしてみた。

> WARNING When deleting a record, you need to ensure its primary field has value, and GORM will use the primary key to delete the record, if the primary key field is blank, GORM will delete all records for the model

## 検証コード
```
package main

import (
	"github.com/jinzhu/gorm"
	// mysql driver
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

// Animal primary_keyタグなし
type Animal struct {
	ID string
}

// Bird primary_keyタグあり
type Bird struct {
	ID string `gorm:"primary_key"`
}

// Fish IDとは異なる名前 かつ primary_keyタグなし
type Fish struct {
	FishID string
}

// Fruit IDとは異なる名前 かつ primary_keyタグあり
type Fruit struct {
	FruitID string `gorm:"primary_key"`
}

func main() {
	db, _ := gorm.Open("mysql", "root@tcp(127.0.0.1:3306)/example?parseTime=true")
	defer db.Close()
        // 構造体に沿ったテーブルを作成
	db.AutoMigrate(&Animal{}, &Bird{}, &Fish{}, &Fruit{})

        // テストデータの用意
	animal := &Animal{
		ID: "001",
	}
	bird := &Bird{
		ID: "001",
	}
	fish := &Fish{
		FishID: "001",
	}
	fruit := &Fruit{
		FruitID: "001",
	}
	db.Create(&animal)
	db.Create(&bird)
	db.Create(&fish)
	db.Create(&fruit)

        // テストデータの削除
	db.Debug().Delete(&animal)
	db.Debug().Delete(&bird)
	db.Debug().Delete(&fish)
	db.Debug().Delete(&fruit)
}
```

## 出力されるクエリ
```
DELETE FROM `animals`  WHERE `animals`.`id` = '001'
DELETE FROM `birds`  WHERE `birds`.`id` = '001'
DELETE FROM `fish`
DELETE FROM `fruits`  WHERE `fruits`.`fruit_id` = '001'  
```

## まとめ

| カラム名 | プライマリーキータグ | 挙動 |
| :--- | :--- | :--- |
| id | ✕ | 対象IDのレコードが消える |
| id | ◯ | 対象IDのレコードが消える |
| xxx_id | ✕ | <font color="OrangeRed">全件吹っ飛ぶ</font> |
| xxx_id | ◯ | 対象IDのレコードが消える |

`id` という名前のカラムのみ、 `primary_key`タグを書かなくても内部でプライマリーキーとして扱ってくれるもよう。
タグを適切に書くというのはもちろんだけど、記載漏れでテーブル内のレコードが全件消えるリスクを考えると

```
db.Where("id = ?", animal.ID).Delete(&Animal{})
```

とWhere句を明示的に書いたほうが事故防止になって良さそう。
基本的なコマンド

- 移動

```
mv /tmp/exp1/aaa /tmp/exp2/
```
- ファイル作成

```
mkdir xxx
```

- 差分比較

```
diff -r aaa bbb
```

- ファイル削除

```
rm -r [ディレクトリ]
rm -r [ファイル]

# 強制的にディレクトリ削除
rm -rf [ディレクトリ] 
```


- tail

リアルタイムでファイルの中身を表示できる。ログ監視とかで役に立つ

```
tail -f /var/log/httpd/xxxx/error_log
```
access.logで時間帯・ipアドレスごとにしぼる（top5）

```
grep '01/Feb/2017' access_log | cut -d " " -f 1 | sort -r | uniq -c | sort -n -r | head -5 
```

- 検索

```
# 最終更新が2017/4 で、「abc」があるアクセスログ
zgrep "abc" access_log.* | grep Apr | grep 2017
```
Ionic + Angular 勉強方法とか

#勉強方法
バージョンは違っても参考になります
[Ionic 4とFirebaseでチャットアプリ ~事前準備~](https://qiita.com/s_kozake/items/6a8bf2084cf92b49d7b9)
[Ionic 4とFirebaseでチャットアプリ]
(https://qiita.com/s_kozake/items/6c7a0cec75c957606a33)

環境構築でのエラー
[npmでpermission deniedになった時の対処法[mac]]
(https://qiita.com/okohs/items/ced3c3de30af1035242d)

どうしてもバージョンを合わせたいひとはコチラ

```
$ npm install -g ionic@4.0.1 cordova@7.1.0
```
Illustrator使ってみた

##メリット
- ロゴ作成などに向いている
- 基本的に書いた内容全てが保存される
- 文書作成の際にも利用できる
- 編集が楽
- レイヤーが見やすい

---

##デメリット
- データが重い
- 細かい作業に向いていない
- 効果などの編集は作業効率が悪い

編集中
PC近代化改修計画とサブマシン新造（1.計画編）

# 背景

現在使用しているPCは以下の通り。メインマシンが稼働からそろそろ6年くらい経過してパフォーマンス的にも時代遅れになりつつあるので大幅改修を行いたい。
が、しばらく使っていて安定している環境に手を入れるのはいつもながら若干怖く、また色々試してみたいこともあるのでこの際1台新たに新造してしまい、バックアップ環境として立ち上げてからメインマシンの改修に取りかかりたいと検討している。
単なる物欲とか言ってはいけない。

## メインマシン（デスクトップ）

|Model|Main Desktop|
|---|---|
|Case|今は亡きAbeeのチャコールブラウン ミドルタワー |
|CPU|Intel Core i5-4690S "Haswell Refresh" 3.2-3.9GHz/65W|
|CPU Cooler|Noctua NH-C14|
|M/B|ASUS Z97-Pro|
|RAM|4GB|
|電源|忘れた|
|Storage|SSD Plextor 256GB|
|Storage|HDD WD 1TB|
|VGA|ELSA GeForce GTX 1050 2GB S.A.C|
|OS|Windows10 Pro (64bit)|


## サブマシン（モバイル）

|Model|Microsoft Surface Pro4|
|---|---|
|CPU|Intel Core i5-6300U|
|RAM|4GB|
|Storage|SSD 128GB|


# 試してみたいこと・コンセプト
- 純粋なソフト屋さんに戻ったので、家でもいろいろコーディングしたい
- 重めのフレームワークをコンパイルしたりするので、メモリは潤沢に積みたい
- 久しぶりにAMDプラットフォームを使ってみたい
- Mini-ITXで組んだことないので試してみたい
- GPU統合のAPUのパフォーマンスも試してみたい
- 簡易水冷クーラーってどうなのか試してみたい
 - NZXTのインフィニティミラーのやつがかっこいい -> https://www.nzxt.jp/products/detail/newkraken.html
- ケースは後で考えるのでとりあえずバラック
- 電源はSFXにしておく
- 最初はWindows10を入れておくが、将来的にメインマシンの近代化改修が終わったらLinux専用にするか、VMWareのHypervisorでも入れて遊びたい
 - 仮想マシンなどに移動可能な、通常版のWin10ライセンスを買っておく 

# 計画

こんな感じで組んでみたい

|Model|Sub compact Desktop|想定予算|
|---|---|---|
|Case|当面なし|0|
|CPU|Ryzen 5 3400G|22,000|
|CPU Cooler|NZXT KRAKEN X42|15,000|
|M/B|ASUS ROG STRIX B450-I GAMING|17,000|
|RAM|DDR4 2666あたりの適当なメモリ32GB|20,000|
|電源|適当なSFX電源|10,000|
|Storage|適当なM2 SSD PCIE3.0x4 1TBくらい|25,000|
|OS|Windows10 Pro 通常ライセンス|26,000|
|Total||135,000|

# To be continued...
簡易鍵盤アプリ


<p> Tone.jsを使用した簡易楽譜表示付き鍵盤のサンプルです<br>
サンプルgithubURL: https://github.com/NanjoMiyako/toneJSTest1
</p>

<p>内容</p>
 <ol>
   <li>参考サイト</li>
 </ol>
<hr>
<p>1.参考サイト</p>
<p>以下のサイトを参考に作成しました</p>
<br>
<a href="https://paiza.hatenablog.com/entry/2017/03/01/初心者でも音楽アプリが作れる%EF%BC%81Web_Audio_APIを簡略化したJS">
初心者でも音楽アプリが作れる！Web Audio APIを簡略化したJSライブラリ「Tone.js」でピアノ鍵盤を作ってみよう！ - paiza開発日誌
</a>
tableタグの中でtableレイアウトに影響を与えずに::before、::afterを使う

captionタグを使うと影響を与えずにbefore,afterを使える

```html
  <table>
    <caption class="beforeClass"></caption>
    …
  </table>
```

正しい高い方ではないので、ご注意を
https://developer.mozilla.org/ja/docs/Web/HTML/Element/caption
RailsでS3から画像やPDFファイルをダウンロードする方法

## 始めに

Ruby on Railsのアプリケーションでボタンを押すとAmazon S3上にある画像、PDF、動画などをダウンロードする機能実装の仕方の一例です。

ファイル型を指定しないとデフォルトではjpgファイルしかダウンロード出来ない点につまづきました。

regionやbucket、keyなどの情報は自分のS3の設定によって異なってきます。

## コントローラーの設定

コントローラー側でdownloadというメソッドでS3からファイルをダウンロードするメソッドを実装します。コントローラー名はDownloadMaterialsControllerとします。

また今回はCredentials情報も直接コントローラーの中に書いていきます。


```download_materials_controller.rb

# S3から特定のファイルをダウンロードするメソッド
def download
  region='[自分のregion名]'
  bucket='[自分のbucket名]'
  key= params[:file_name]
  credentials=Aws::Credentials.new(
    '[自分のCredentials情報]',
    '[自分のCredentials情報]',
  )
  # send_dataのtypeはtypeで指定
  client=Aws::S3::Client.new(region:region, credentials:credentials)
  data=client.get_object(bucket:bucket, key:key).body
  send_data data.read, filename: params[:file_name], disposition: 'attachment', type: params[:type]
end
```

## Viewファイルの設定

ダウンロードリンクという文字列に:file_name、:typeというパラメータでそれぞれファイル名とファイルの種類をコントローラーに渡すようにします。Slimを使って書くとすると以下のようになります。

```
/ pngファイルの場合
= link_to "ダウンロードリンク", download_materials_download_path(:file_name => "取得したいファイル名.png", :type => 'png')

/ pdfファイルの場合
= link_to "ダウンロードリンク", download_materials_download_path(:file_name => "取得したいファイル名.png", :type => 'pdf')

/ mp4ファイルの場合
= link_to "ダウンロードリンク", download_materials_download_path(:file_name => "取得したいファイル名.mp4", :type => 'mp4')
```

## routeファイルの設定

今回はコントローラ名がDownloadMaterialsControllerなのでrouteファイルに

```routes.rb
get 'download_materials/download'
```
を追記しておきます。


## 最後に
この実装によりリンクをクリックするとDownloadMaterialsControllerのdownloadメソッドからファイルがダウンロードされる仕組みになっています。
またそれぞれのリンクによってパラメータとして渡されるファイル名とファイルの種類の情報によって、それぞれ違うファイルをダウンロード出来るようになっています。
もっと良い実装が出来たら更新したいと思います。少なくとも認証情報は別ファイルに書くべきですね。
【初心者向け】Pythonでの基本的な文法まとめ ①入力編

#概要

最近Djangoばかり触っていて、Pythonの基本的な文法についてすっかり忘れていたので、個人的に最低限覚えておかないと思った範囲を整理する意味も兼ねて記事にしました。

#入力の基本
Pythonではinput()関数を使って入力を受け取ります。
入力された要素は文字列(String)で扱われるため、整数等を数値として扱いたい場合はint関数もしくはfloat関数を使いましょう。
ただし、floatは小数として表示するので、整数を扱いたい場合はintです。

また、実際に以下に記述するコードを試す際には実行後に自身で入力を行なってください。

# 1つの文字列を受け取る

```input.py
# 入力
# ABC

str = input()

print(type())
print(str)

# 出力
# <class 'str'>
# ABC
```

#n個の文字列を受け取る(配列)

```input.py
# 入力
# apple orange banana

str = input().split()

print(type(str))
print(type(str[0]))
print(str)

# 出力
# <class 'list'>
# <class 'str'>
# ['apple', 'orange', 'banana']
```

split()というのは文字列名.split(“ 区切り文字 ”) とすることで、区切り文字で区切られたリストを得る事が出来ます。
区切り文字がスペースや、改行、タブであるときは、特に区切り文字を指定しなくても、区切ることができます。また、半角スペースだけでなく、カンマsplit(',')、スラッシュ('/')の分割も出来ます。




#n個の文字列を受け取る(変数に代入)

```input.py
# 入力
# apple orange banana

str1, str2, str3 = input().split()

print(type(str1))
print(str1)

print(type(str2))
print(str2)

print(type(str3))
print(str3)

# 出力
# <class 'str'>
# apple
# <class 'str'>
# orange
# <class 'str'>
# banana
```
#1つの整数を受け取る

```input.py
# 入力
# 100

num = int(input())

print(type(num))
print(num)

# 出力
# <class 'int'>
# 100
```

入力の基本で書いた通り、input関数を使った際の要素は文字列として扱われるため、整数として扱いたい場合は上記のようにint関数を用いる必要があります。

#n個の整数を受け取る(配列)

```input.py

#入力
# 100 200 300

n,u,m=(int(i) for i in input().split())
print(n)
print(u)
print(m)

# 出力
# 100 
# 200
# 300
```



#n個の整数を受け取る(変数に代入)

```input.py
# 入力
# 100 200 300

num1, num2, num3 = [int(i) for i in input().split()]

print(type(num1))
print(num1)

print(type(num2))
print(num2)

print(type(num3))
print(num3)

# 出力
# <class 'int'>
# 100
# <class 'int'>
# 200
# <class 'int'>
# 300
```

# n行にm個の要素

```input.py

# 要素4つ, 2行の入力と仮定

# 入力
# 最初に要素の列、要素の行数を宣言
# 4 2
# 10 11 12 13 
# 20 21 22 23 

n, m = [int(i) for i in input().split()]
table = [[int(i) for i in input().split()] for m in range(m)]


print(n)
print(m)

print(type(table))
print(table)

# 出力
# 4
# 2
# <class 'list'>
# [[10, 11, 12, 13], [20, 21, 22, 23]]


```


以上がPythonで基本的な入力を受け取る方法です。

ご指摘等ありましたらよろしくお願いします。
Pound経由でLocationヘッダーを返す場合の注意点

テストサーバにPoundを入れていろんなサービスのテストをしているのですが
httpでアクセスした際、httpsにリダイレクトしたいのに、なぜかhttpになってしまう現象があり
具体的には

80portのアクセスはPoundが受け取る
PoundはApacheのVirtualHostの8080に転送する
ApacheはMod_rewriteを利用してURIを保持したままhttpsにRedirectする
Apacheからは”Location: https://hoge.jp/”というヘッダ付きで出力される
Poundがリクエストしてきた端末に返す

単なるリバースプロキシでの処理ですが
Poundがなぜか"Location: https://hoge.jp/" を "Location: http://hoge.jp/" と変更してしまう
のです。

![スクリーンショット 2019-08-09 14.50.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19107/f2648e52-9d43-2549-0a92-1441dca476aa.png)

解決策は RewriteLocation 0 を仕込むことでした。

```
ListenHTTP
    Address 0.0.0.0
    Port    80
    Client  120
    xHTTP   1
    AddHeader "X-Forwarded-Port: 80"
    RewriteLocation 0

    Service
        HeadRequire "Host: hoge.jp"
        BackEnd
            Address 127.0.0.1
            Port    8002
            Priority 1
        End
    End
End
```

man poundでドキュメントを読むと・・

>        RewriteLocation 0|1|2
              If 1 force Pound to change the Location: and Content-location: headers in responses. If they point to the back-end itself or to  the
              listener  (but  with  the wrong protocol) the response will be changed to show the virtual host in the request. Default: 1 (active).
              If the value is set to 2 only the back-end address is compared; this is useful for redirecting a request to an HTTPS listener on the
              same server as the HTTP listener.

どうもまちがってたりしてるのを修正してくれるような機能っぽいのですが・・
いろいろ試してみましたが、同一ホスト名の場合はSchemaは元と同じにしたがる傾向で
別なドメインにリダイレクトする際はそのままだったりします。

Pound + apacheやPHP(Header("Location: https://〜);)でhttp->httpsにリダイレクトさせた場合で
意図しない動きをした場合は見てみるといいとおもいます。
CUIからCyVerse上で公開されたデータをダウンロードする

# CyVerseとは

- データ解析をコモディティ化するための＂サイバーインフラストラクチャー"を提供するプロジェクト。
- アカウントを作るとストレージが貰えたりクラウド環境が使えたりする
- アクティブユーザーが５万人以上いるらしい、が日本ではあまり聞かない気がする
- 日本語の記事はこれぐらい(http://kazumaxneo.hatenablog.com/entry/2018/04/16/224603)

# やりたいこと

- [使いたい論文](https://www.sciencedirect.com/science/article/pii/S0092867419303411)のデータが[iVirus](https://ivirus.readthedocs.io/en/latest/)上にアップされている ([iVirus論文](https://www.nature.com/articles/ismej201689))
- iVirusはCyVerse内のプロジェクト
- それをDLしたい。GUIでぽちぽちやってダウンロードする機能も一応あるっぽかったが、めちゃ遅くてダウンロードできる気がしなかった

# 方針

- CyVerseの中のデータはiCommandsを介してDownLoadするっぽい:[参考](https://cyverse-data-store-guide.readthedocs-hosted.com/en/latest/)
- iCommandsはiRODSに入っているっぽい:[参考](https://irods.org/download/)
- iRODS自体はCyVerseで使っているオープンソースのデータマネジメントツール群で、iRODSからCyVerseのアカウントでログインしデータを落とす

# やったこと

まず http://kazumaxneo.hatenablog.com/entry/2018/04/16/224603 を参考にCyVerseのアカウントを作り、GUI上でアクセス。欲しいデータのパスを確認。
今回は

`/iplant/home/shared/iVirus/GOV2.0/GOV2_viral_populations_larger_than_10KB_or_circular.zip`
`/iplant/home/shared/iVirus/GOV2.0/GOV2_viral_populations_larger_than_5KB_or_circular.zip`

これらが欲しい。


iRODSのインストールはこんな感じ


```shell
wget -qO - https://packages.irods.org/irods-signing-key.asc | sudo apt-key add -
echo "deb [arch=amd64] https://packages.irods.org/apt/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/renci-irods.list
sudo apt-get update
sudo apt-get install irods-server irods-database-plugin-postgres
```

IRODSをインストールしたら、データベースへの接続の初期設定をする。対話型で聞かれるので、[wiki](https://wiki.cyverse.org/wiki/display/DS/Using+iCommands) に従って答えていけばいい。

```shell
vagrant@vagrant:~$ iinit
 ERROR: environment_properties::capture: missing environment file. should be at [/home/vagrant/.irods/irods_environment.json]
One or more fields in your iRODS environment file (irods_environment.json) are
missing; please enter them.
Enter the host name (DNS) of the server to connect to: data.cyverse.org
Enter the port number: 1247
Enter your irods user name: your_user_name
Enter your irods zone: iplant
Those values will be added to your environment file (for use by
other iCommands) if the login succeeds.
```

これでデータにつながるようになったので、wget likeなコマンド `iget`でデータを落とす。

```shell
vagrant@vagrant:~$ iget -K /iplant/home/shared/iVirus/GOV2.0/GOV2_viral_populations_larger_than_10KB_or_circular.zip
vagrant@vagrant:~$ iget -K /iplant/home/shared/iVirus/GOV2.0/GOV2_viral_populations_larger_than_5KB_or_circular.zip
```

# 感想および愚痴

- データダウンロードしたいだけなのに周辺のエコシステムの知識必要なの辛すぎ
- Documentも基本的にCyVerse環境内で閉じた解析を想定しててしんどい
- wget一発で取れるようにしてほしい
GoogleがCoralボード用のEfficientNet-EdgeTPU分類モデルをリリース

Googleは3月に、テンソル処理ユニット（Edge TPU）AIアクセラレータチップを搭載したコンパクトなPCであるCoral Dev Boardと、既存のRaspberry PiおよびLinuxシステムでの機械学習の推論を高速化するために設計されたUSBドングル（Coral USB Accelerator ）。 それ以来、キットのサポートリソースの更新は着実に行われ、本日、Googleは分類モデルの新しいファミリであるEfficientNet-EdgeTPUをリリースしました。Coralボードのシステムオンモジュールでの実行に最適化されています。

![unnamed-_3_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/78465cd4-f2f3-3213-a137-0582a739c955.jpeg)


EfficientNet-EdgeTPUのトレーニングコードと事前トレーニングモデルの両方がGitHubで利用可能です。

機械学習アクセラレータアーキテクトのSuyog GuptaとGoogle Researchのソフトウェアエンジニアは、次のように述べています。 明星タン。 「皮肉なことに、これらのアーキテクチャはデータセンターやエッジコンピューティングプラットフォームで着実に普及していますが、それらで実行される[AIモデル]は、基礎となるハードウェアを活用するためにカスタマイズされることはめったにありません。」

EfficientNet-EdgeTPUプロジェクトの目標は、GoogleのEfficientNetsから派生したモデルを電力効率の良い、オーバーヘッドの少ないEdge TPUチップに合わせることでした。 以前のテストでは、EfficientNetsは既存のAIシステムの特定のカテゴリーよりも高い精度と効率の両方を実証し、パラメーターサイズとFLOPS（浮動小数点計算）を1桁削減しました。

![image1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/32202a8b-0530-9a19-e409-0f526c30ec21.png)
EfficientNet-EdgeTPU-Sは、ResNet-50よりも高い精度を実現しつつ、10倍高速に動作します。

これは、EfficientNetsがグリッド検索を使用して、固定リソース制約の下でベースラインAIモデルのスケーリングディメンション間の関係を識別するためです。 検索により各次元の適切なスケーリング係数が決定され、係数が適用されてベースラインモデルが目的のモデルサイズまたは計算予算にスケールアップされます。

Gupta、Tan、および同僚によると、EfficientNetsを再構築してEdge TPUを活用するには、Googleが開発したAutoML MNASフレームワークを呼び出す必要がありました。 MNASは、ハードウェアの制約（特にオンチップメモリ）を考慮した強化学習を組み込むことにより、候補のリストから理想的なモデルアーキテクチャを特定し、さまざまなモデルを実行し、実物のパフォーマンスを測定してから作物のクリームを選択します。 チームは、Edge TPUでの実行時にアルゴリズムのレイテンシの推定値を提供するレイテンシ予測モジュールでこれを補完しました。

全体論的なアプローチにより、ベースラインモデルEfficientNet-EdgeTPU-Sが作成されました。研究者は、入力画像解像度スケーリング、ネットワーク幅、深度スケーリングの最適な組み合わせを選択することでスケールアップしました。 実験では、結果として得られるより大きなアーキテクチャ-EfficientNet-EdgeTPU-MおよびEfficientNet-EdgeTPU-L-は、Inception-resnet-v2やResnet50のような一般的な画像分類モデルと比較して、レイテンシを増加させてより高い精度を実現し、Edge TPUでより高速に実行しました。

![unnamed-_1_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/3941a509-ede2-0d65-1989-5f6494b3a730.jpeg)

- Google Coral Edge TPU 官方海外代理店： https://store.gravitylink.com/global

EfficientNet-EdgeTPUのリリースは、ハイブリッド量子化、完全整数量子化、プルーニングを含むツールスイートであるGoogleのTensorFlow用Model Optimization Toolkitのデビューの翌日です。 注目すべきは、トレーニング後のfloat16量子化です。これにより、AIモデルのサイズが最大50％削減され、精度はほとんど低下しません。
WSLにRubyをインストるめも

#したいこと
「Windows Subsystem for Linux」のUbuntuにRuby入れる。
先駆者の参考にしてみる。(その通りにやるとはいっていない。)

#が、えらる
終了するまでが長かった。20分以上待った。長い。エラーならもっと早く出てほしい。ぷんすか。ぷん。

```shell
~$ rbenv install 2.6.3
Downloading ruby-2.6.3.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.bz2
Installing ruby-2.6.3...

BUILD FAILED (Ubuntu 18.04 using ruby-build 20190615-7-g0e9094b)

Inspect or clean up the working tree at /tmp/ruby-build.20190809123420.1565
Results logged to /tmp/ruby-build.20190809123420.1565.log

Last 10 log lines:
The Ruby openssl extension was not compiled.
The Ruby readline extension was not compiled.
The Ruby zlib extension was not compiled.
ERROR: Ruby install aborted due to missing extensions
Try running `apt-get install -y libssl-dev libreadline-dev zlib1g-dev` to fetch missing dependencies.

Configure options used:
  --prefix=/home/maple/.rbenv/versions/2.6.3
  LDFLAGS=-L/home/maple/.rbenv/versions/2.6.3/lib
  CPPFLAGS=-I/home/maple/.rbenv/versions/2.6.3/include
```

ぐーぐるさん「拡張機能がないため、Rubyのインストールが中止されました
`apt-get install -y libssl-dev libreadline-dev zlib1g-dev`を実行して、不足している依存関係を取得してください。」
以下入れてみる。

```shell
sudo apt-get install -y libssl-dev libreadline-dev zlib1g-dev
```

![英語わからん.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480221/80f14aee-aac0-b1a7-5ba3-081da98cbbd7.png)
なんか怖いのでた。タスケテー

>`ぐーぐるさんの見解`
特定のライブラリの場合、再起動する必要があるサービスがシステムにインストールされています。 libpam、libc、libsslなどがアップグレードされます。 再起動があると、システムのサービスが中断する可能性があるためです。 プロンプトが表示されないようにします。 代わりに、必要なすべての再起動が自動的に行われるため、ライブラリのアップグレードごとに質問されることを回避できます。
確認せずにパッケージのアップグレード中にサービスを再起動しますか？
<はい> <いいえ>


こっちで勝手にやっとくから、いちいち許可するか聞くの面倒くさいんでやめてイイっすかってことかな。
「Services restarted successfully.」って出てたから大丈夫そう。

もう一度いんすと。長い。また20分以上待った。
エラー出ずに終了。

```shell
~$ ruby -v
rbenv: ruby: command not found

The `ruby' command exists in these Ruby versions:
  2.6.3
```

( ﾟдﾟ)ふぁっ
バージョン指定しないとだめらしい。

```shell
~$ rbenv versions
  2.6.3
~$ rbenv global 2.6.3
~$ ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
```

でけた。

---
##参考
- [WindowsでWSL、Ubuntu、Rubyをインストール](https://qiita.com/tsukamoto/items/6e9a181b6e0defc27a39)
- [Ubuntu on Windows にRubyをインストール]
(https://qiita.com/taokuno/items/3828ee192cfce6add013)
データベースに小数値を格納したい。もちろん正しく計算もしたい。

# はじめに
下記のような小数を使ったクエリを発行したら、結果があるはずなのに結果がないと返ってくる。
データベースから取ってきた小数を使った計算が合わない。

```SQL
SELECT id FROM Products WHERE amount = 59.95
```

そんな現象に遭わないために、遭う人を減らすために、「SQLアンチパターン」第9章から得た知識をまとめておきます。

# データベースで小数値を使用したい
整数型は便利なデータがですが、その名の通り格納できるのは整数のみです。
例えばドルを基準にした金額計算では59.95ドルのように、小数点2位の値が必要になります。このような数値をデータベースに格納し、うまく計算を行うにはどうしたら良いのでしょうか。


## アンチパターン: FLOAT 型の採用
SQLにも実数を表すデータ型があります。FLOATデータ型です。
SQL の FLOAT データ型は実数を **二進数形式** でエンコードします。しかし、「10進数で記述できるすべての値を、2進数で格納できるわけではない」という浮動小数点数の特性を常に意識している人はあまり多くないでしょう。

ここで少し丸めの誤差について話します。
例えば3分の1を小数で表すと0.333333… と無限に続きます。そこで、例えば0.333などの有限精度の値を使って代替します。しかし、計算結果が意図していた値と正確には一致しなくなります。
3分の1を三倍すると1になりますが、0.333を三倍しても0.999です。

二進数形式で無限精度が必要な値は、10進数で表現される値とは異なります。例えば59.95を2進数で正確に表すには無限精度が必要です。FLOATデータ型では無限精度を扱うことはできないため、近似値を使用しています。その近似値を10進数形式で表すと、59.950000762939になります。

これを理解しておけば、計算に誤差が生じることを予測できます。しかし実際のところ、浮動小数点数を使用するたびに計算をするようなことはまずないでしょう。

### FLOAT 型の採用による問題点
意図した値と近似値の差はわずかですし、どうやったところで無限精度を実現することはできないのだからあまり問題ないと考えることもできます。
しかし、計算によっては大きな問題になることもあります。

例えば等価性比較です。

| id | amount |
|----|--------|
|1   | 59.95  |

上記のような Products テーブルがあるとします。`amount` は FLOAT 型です。

```SQL
SELECT id FROM Products WHERE amount = 59.95
```

このクエリを発行した人物は、当然 `1` という結果が返ってくると考えていたはずですが、実際には「一致する行はない」と返ってきます。
これは、 `amount` に格納されている値が59.95よりもわずかに大きいからです。

また、浮動小数点数の誤差は、集約計算を行う場合にも生じます。SUM関数を用いて浮動小数点数を合計する場合、一つ一つの誤差が累積されていきます。
さらに、和ではなく積を計算する場合は誤差がさらに大きくなります。
例えば、1に1.0を掛けると結果は常に1ですが、1に1000回0.999を掛けると結果は約0.3677となります。

## NUMERIC 型、DECIMAL 型を使用する
では、FLOAT の代わりに何を使えば良いのでしょうか。
FLOAT 型の代わりに、NUMERIC または DECIMAL を用いて (NUMERIC と DECIMAL は同一の振る舞いです ) 固定精度の小数点数を表すようにしましょう。

```sql
ALTER TABLE Products MODIFY amount NUMERIC(9,2);
```

このデータ型は、第一引数に「格納可能な **10進数** の桁の総数」を、第二引数に小数点以下に格納できる桁数を指定します。

長所は、10進数で表現できる値を格納するとき、その値が正確に格納されていることを信頼できることです。
無論、このクエリも成功します。

```SQL
SELECT id FROM Products WHERE amount = 59.95
```

NUMERIC や DECIMAL を使用しても、3分の1のような10進数で無限精度が必要な値を格納することはできません。しかし、少なくとも二進数のものよりは10進数の無限小数の扱いに慣れているでしょう。


# まとめ
正確な10進数値が必要なときは、NUMERIC や DECIMAL を使い、FLOAT は避けましょう。
Jmeter サーバ(EC2)からターゲット(EC2)を攻撃する

javaが入ってることを確認する

```
[ec2-user@ip-10-0-0-177 ~]$ java -version
openjdk version "1.8.0_201"
OpenJDK Runtime Environment (build 1.8.0_201-b09)
OpenJDK 64-Bit Server VM (build 25.201-b09, mixed mode)
```

入ってなければここを確認する
https://qiita.com/neko_com/items/ef0409bc85b8054a6004


公式サイトhttps://jmeter.apache.org/download_jmeter.cgiからjmeterをとってくる

```
[ec2-user@ip-10-0-0-177 ~]$ ls
[ec2-user@ip-10-0-0-177 ~]$ wget http://ftp.meisei-u.ac.jp/mirror/apache/dist//jmeter/binaries/apache-jmeter-5.1.1.zip
--2019-08-09 02:20:15--  http://ftp.meisei-u.ac.jp/mirror/apache/dist//jmeter/binaries/apache-jmeter-5.1.1.zip
```


解凍する

```
[ec2-user@ip-10-0-0-177 ~]$ ls
apache-jmeter-5.1.1.zip
[ec2-user@ip-10-0-0-177 ~]$ md5sum apache-jmeter-5.1.1.zip
ffbf958177a9b878346d577868eae4a1  apache-jmeter-5.1.1.zip
[ec2-user@ip-10-0-0-177 ~]$ unzip apache-jmeter-5.1.1.zip
Archive:  apache-jmeter-5.1.1.zip
   creating: apache-jmeter-5.1.1/
   creating: apache-jmeter-5.1.1/bin/
   creating: apache-jmeter-5.1.1/bin/report-template/
   creating: apache-jmeter-5.1.1/bin/report-template/sbadmin2-1.0.7/
   creating: apache-jmeter-5.1.1/bin/report-template/sbadmin2-1.0.7/bower_components/
   creating: apache-jmeter-5.1.1/bin/report-template/sbadmin2-1.0.7/bower_components/bootstrap/
```

ローカルへ移動

```
[ec2-user@ip-10-0-0-148 ~]$ ls
apache-jmeter-5.1.1  apache-jmeter-5.1.1.zip
[ec2-user@ip-10-0-0-148 ~]$ sudo mv apache-jmeter-5.1.1 /usr/local/apache-jmeter-5.1.1
```

ディレクトリを移動して権限付与

```
# cd /usr/local/jmeter-2.9/bin
# chmod 755 jmeter
# chmod 755 jmeter-server
```

jmeter-serverを変更する

```
vim jmeter-server
RMI_HOST_DEF=-Djava.rmi.server.hostname=xxx.xxx.xxx.xxx
```
YTMusicのようなもの(JavaScript)

<p> YouTube Player APIを使用したYoutube動画自動再生のサンプルです<br>

サンプルgitURL:https://github.com/nyake123/LikeyoutubeMusicAPITest1 
</p>
<p>
・ソース修正しました. 2018.10.28<br>
・youtube APIを使ったページを追加しました. 2019.12.17
</p>

<p>内容</p>
 <ol>
   <li>サンプルページ</li>
   <li>参考サイト</li>
 </ol>
<hr>
<p>1.サンプルページ</p>
サンプルページURL: https://nanjomiyako.github.io/youtubeApi2/

<p>2.参考サイト</p>
<p>以下のサイトを参考に作成しました</p>
<br>
<a href="https://www.tam-tam.co.jp/tipsnote/javascript/post6217.html">YouTube Player APIを使って色々やってみる ｜ Tips Note by TAM</a>
<br>
<a href="https://developers.google.com/youtube/iframe_api_reference?hl=ja">iframe 組み込みの YouTube Player API リファレンス  |  YouTube IFrame Player API  |  Google Developers</a>
<br>
<a href="http://www.cgis.biz/others/youtube/">Youtube APIとYoutube Data API (v3) のメモ</a>
<br>
WSL2の仮想ディスクをLinuxでマウントする

Windows 10とLinux(ubuntu 18.04LTS)をデュアルブートするようにインストールした環境でWindows 10側のWSL2環境下にインストールしたUbuntu 18.04LTSのファイルにアクセスする必要があったので、その時の作業の記録です。

## Windows 10のファイルシステムをLinuxファイルシステム用マウントポイントにマウント

まずはWindows 10のファイルシステムをLinuxからアクセスできるようにntfs-3gを使ってWindowsファイルシステム用マウントポイントにマウントします。

### ntfs-3gがインストールされていないならインストール

```shell-session:
$ sudo apt-get install ntfs-3g
```

### 必要なら新たにWindowsファイルシステム用マウントポイントを作成

```shell-session:
$ sudo mkdir -p /volumes/windows_c
```

### Windows 10のファイルシステム(NTFS)をWindowsファイルシステム用マウントポイントにマウント

```shell-session:
$ sudo mount -t ntfs-3g /dev/nvme0n1p3 /volumes/windows_c
```

## nbdとqemu-ndbを使ってWSL2のファイルシステムをLinuxファイルシステム用マウントポイントにマウント

続いてnbd(Network Block Device)とqemu-ndbを使ってWindowsファイルシステム上に構築されたWSL2のファイルシステム(VHDX=WSL2が使用する仮想ディスク)をLinuxファイルシステム用マウントポイントにマウントします。

### qemu-utilsやnbd-clientがインストールされていなければインストール

```shell-session:
$ sudo apt install qemu-utils nbd-client
```

### ndbカーネルモジュールをロード

```shell-session:
$ sudo modprobe nbd
```

<details><summary>仮想ディスク中にパーティションが存在する場合</summary>
<div>
通常はWSL2へのディストリビューションのインストールでは仮想ディスクイメージ中にはパーティションは作られず、ディスク全体が1つのファイルシステムとして扱われるはずなので以下の操作は不要ですが、仮に仮想ディスクイメージ中にパーティションが複数存在する場合には以下の操作を追加で行なってnbdで複数パーティションを扱えるように設定する必要があります。

### nbdが扱えるパーティションの数(デフォルトでは0)を設定するために一旦ndbカーネルモジュールをアンロード

```shell-session:
$ sudo rmmod nbd
```

### nbdが扱えるパーティションの数を16に設定してndbカーネルモジュールをロード

```shell-session:
$ sudo modprobe nbd max_part=16
```
</div>
</details>

### qemu-nbdでWSL2の仮想ディスクイメージをndbに接続

Windowsファイルシステム上のWSL2仮想ディスクイメージは `<ユーザーディレクトリ>¥AppData¥Local¥Packages¥<WSLのディストリビューション識別子>¥LocalState` 以下にVHDX形式の仮想ディスクイメージとして格納されています。
例えば、自分の環境でWSL2へとUbuntu 18.04LTSをインストールした場合にはディスクイメージがWindows 10のファイルシステム上では `C:¥Users¥kazu¥AppData¥Local¥Packages¥CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc¥LocalState¥ext4.vhdx` に格納されていたので、以下のように qemu-nbd への引数としてndbのブロックデバイスとディスクイメージのパスを与えてこれを接続します。
その結果、ndbのブロックデバイスを通してのWSL2仮想ディスクへのアクセスが可能になります。

```shell-session:
# sudo qemu-nbd -c <ndbブロックデバイス> <仮想ディスクイメージのパス>
$ sudo qemu-nbd -c /dev/nbd0 /volumes/windows_c/Users/kazu/AppData/Local/Packages/CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc/LocalState/ext4.vhdx
```

<details><summary>仮想ディスク中にパーティションが存在する場合</summary>
<div>
### WSL2の仮想ディスクイメージ中のパーティション情報を解析
nbdに接続された仮想ディスクイメージ中にパーティションが存在している場合には、それを解析させてそれぞれのパーティションに対応するブロックデバイスを用意する必要があります。

```shell-session:
$ sudo partprobe /dev/nbd0
```
</div>
</details>

### 必要なら新たにLinuxファイルシステム用マウントポイントを作成

```shell-session:
$ sudo mkdir -p /volumes/wsl2_ubuntu
```

### WSL2の仮想ディスクイメージをLinuxファイルシステム用マウントポイントにマウント

```shell-session:
$ sudo mount -o ro,nouser /dev/nbd0 /volumes/wsl2_ubuntu
```
<details><summary>仮想ディスク中にパーティションが存在する場合</summary>nbdに接続された仮想ディスクイメージ中にパーティションが存在している場合には、マウントするndbのブロックデバイスは/dev/ndb0p1のようにパーティション番号を含めたブロックデバイスを指定します。</details>

## アンマウントする

### Linuxファイルシステム用マウントポイントのマウントを解除

```shell-session:
$ sudo umount /volumes/wsl2_ubuntu
```

### qemu-nbdでndbへのWSL2の仮想ディスクイメージの接続を解除

```shell-session:
$ sudo qemu-nbd -d /dev/nbd0
```

### 不要ならカーネルモジュールqemu-nbdとnbdをアンロード

```shell-session:
$ sudo rmmod nbd
```

### Windowsファイルシステム用マウントポイントのマウントを解除

```shell-session:
$ sudo umount /volumes/windows_c
```
LINEの新機能オープンチャットでプログラマのコミュニティを作ってみた

# LINEオープンチャット
いよいよオープンチャットが利用開始になった(^^)
[http://official-blog.line.me/ja/archives/79448193.html](http://official-blog.line.me/ja/archives/79448193.html)

# 早速開設・・・
折角なのでプログラマやエンジニアのみなさんと
コミュニケーションが取れるルームを・・・と思って作ってみました♪♪

目指せ！楽しくて稼げるプログラマー✨
[https://line.me/ti/g2/xN5RGD-_b8b3i5W2g-NN2w](https://line.me/ti/g2/xN5RGD-_b8b3i5W2g-NN2w)
※入り方を最後に書いていますので是非最後までお読みください m(＿＿)m

# 目的
・楽しく働けるプログラマを増やしたい
・稼げるプログラマを増やしたい（搾取されないという意味も含めて）
・何が必要なのかなど、道筋が分かる場所を提供したい
・単純に聞きたいことを聞きたいｗ
・技術的な質問や動向などについても話したりしてみたい
などなど・・・という感じです！(^^)

# なぜ？？
なぜ僕にそういう想いがあるのかというと・・・

元々は現在一部上場企業にまでなっているある会社で
サラリーマンプログラマをやっていたのですが、その時は正直社畜でした・・・💦

通勤途中にぶっ倒れたり、うつ手前まで行きましたし
昇進して結構な立場だったのに給料が手取りで15万円とか
ほんとに最初はかなり苦労しました (^_^;)

何とか転職をして、人生を一変させることができましたが
本当に運が良かっただけで
まだまだ暗黒の時代をお過ごしの方も多いでしょうし
プログラマがどうなっていくとどうなるのかなど
将来のことや今後のことを聞きたかったり・知りたかったりする方もいると思います。

学生さんでこれからプログラマ目指そうとしている方や
目指しているけど「実際のところどうなの？？」とか聞きたい方もいると思います。

何か手助けになれることがあればという想いはずっと持っているので
今回オープンチャットで作ってみた次第です！！✨

あっ・・・もちろん、こちらから聞きたいこととかもあるので
色んなプログラマさん・エンジニアさんが入ってくださると嬉しいです！！

# 入り方（2019/8/22変更）
~~オープンチャットを利用するには以下の手順で進める必要があるとのこと・・・~~
⇒オープンチャットが一般公開されて①～③の手順は要らなくなりました！！
  いきなり④からルームにお入りください！！

~~①LINEアプリを最新バージョンにアップデート~~

~~②OpenChatスタートページを開き、[OpenChatをはじめる]ボタンを押す
[https://w.line.me/openchatactivate/](https://w.line.me/openchatactivate/)~~
​
~~③ボタンが緑色になったら、LINEアプリを一度終了し、再起動~~

④こちらからルームに入る
[目指せ！楽しくて稼げるプログラマ＆エンジニア✨](https://line.me/ti/g2/xN5RGD-_b8b3i5W2g-NN2w)

# 最後に
少しでもお役に立てるならと本気で思っているので
興味のある方は是非お待ちしています！(^^)

「自分の経験も役に立てるなら」と思って入ってくださる方も、もちろん大歓迎ですので
どうぞよろしくお願いします！！
Unityでオンラインマルチプレイなゲームを作りたい その1 ネットワークエンジンの選択

# 経緯
最近購入したゲームのマルチプレイがローカルのみだったのがかなり勿体ないと感じショックを受けたのが始まりです。
無いなら作ってしまおうということで、ついでに今後マルチプレイ有りのゲームを作る方に、オンラインでの実装の検討や開発の参考になるようなものを残せたらいいなと思い、記事を書くことにしました。
ということで、これからゲーム作っていこうと思います。

# オンラインゲーム開発を楽にしてくれるもの
オンラインゲームのネットワークを1から作成するのはかなり敷居が高いです。
調べたところ、ありがたいことにオンラインゲームの開発を簡単にしてくれるエンジンが複数ありました。
開発はやっぱり楽したいのでこれを使わない手はないです。
自分の環境ではUnityを使用しているので、Unityで使用できるものを利用したいと思います。

## Unityで使用できるもの
前述で調べたものを簡単に紹介します。
#### [UNet](https://unity3d.com/jp/unity/features/multiplayer)
Unityに元々あるネットワークAPIです。Unity2019で廃止されました。
デフォルトの機能だけでは実装が難しく、機能を継承してカスタマイズしたりするのがオーソドックスなようです。
#### [Connected games](https://unity3d.com/jp/partners/google/connectedgames)
GoogleがUnityと提携して開発しているUNetに代わるものです。
まだ開発中っぽいです。
#### [Photon Unity Networking(PUN)](https://www.photonengine.com/ja-JP/PUN)
多機能で実装幅が広めです。使用している人が多く、調べれば実装例が結構出ます。
#### [Monobit Unity Networking(MUN)](http://www.monobitengine.com/mun/)
PUNに使用感が近く機能も同じく充実しています。アセット内に含まれているサンプル + 公式のドキュメントを見ながらの開発が進めやすいです。
#### [GameLift](https://aws.amazon.com/jp/gamelift/)
Unityでも利用はできますが、Amazon Lumberyard(アマゾン製のゲームエンジン)向けです。
Unityで使う場合SDKを自身でビルドし、アップロードするといった一手間があるようです。
#### [Strix Unity SDK](https://www.strixengine.com/sdk/strix-unity-sdk/)
機能がシンプルに纏まっていて扱いやすそうです。付属のサンプルが流用しやすくカジュアルなゲームや単純なFPSならサクッとオンライン化できます。
## どれを使おう？
結構数がありました...。使用するのは一つだけでいいので、選んでいきます。
Unity2019を使いたいのでUNetは使えないですね。
Connected gamesも開発中なので使用は見送りです。(そもそもDLするところが見当たらない...まだ出てないんですかね)
GameLift...サンプルや実装例を調べたんですが、それよりもチュートリアルで料金が発生したって記事が...ちょっと怖いので利用は控えます。
残りのPUN/MUN/Strix Unity SDKは普通によさそうです。この3つから使用するものを選びたいと思います。

サンプルとドキュメントを見て比べてみました。

||PUN|MUN|Strix Unity SDK|
|-----------:|:------------:|:------------:|:------------:|
|機能|〇|〇|△|
|導入のしやすさ|〇|〇|〇|
|実装の手軽さ|〇|〇|◎|
|ドキュメント|△|〇|△|
|サンプル|△|〇|△|

Strix Unity SDKは前述通りで簡単なゲームならすごく楽で扱いやすそうなんですが、スクリプト面での実装の情報が少ないのと、ルーム関連(主にパラメータと検索)がちょっと使いづらく感じました。
PUNとMUNは機能に関しては申し分なさそうですが、PUNのドキュメントが個人的には足りない感じがします。
その分MUNは公式のドキュメントと同梱されているサンプルが充実していて、開発が進めやすそうです。

ちょっと凝ったものを作ろうと思っている + 実装法の模索や検索の手間を考えるとMUNがよさそうなので、MUNを使用しようと思います。
<br>
使うネットワークエンジンが決まったので、次回はオンラインゲームを開発する準備を書いていきます。
MAMP ProでXdebug設定してもコマンドラインで有効にならないときの対処法

MAMP ProでXdebugを有効にしてもコマンドラインだと有効にならなくて「おや？」ってなってしまうことがあります（というか毎回バージョンアッアップする度になってます^^;

なんでこんなことになるかというと、MAMP ProはWebアクセス時にはデフォルトとは異なるphp.iniを読みこんでいるから。

![phpinfo__.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9845/2c774b00-a09c-2983-754e-217e0deac6bd.png)

なのでphpinfoを見たときに上記のようだったらシンボリックリンクはってあげれば解決します。

まず既にあるphp.iniをリネーム

```
$ mv /Applications/MAMP/bin/php/php7.2.20/conf/php.ini /Applications/MAMP/bin/php/php7.2.20/conf/php.ini_190809
```

次にシンボリックリンク作成

```
$ ln -s /Library/Application Support/appsolute/MAMP PRO/conf/php7.2.20.ini /Applications/MAMP/bin/php/php7.2.20/conf/php.ini
```

これで解決。

ちなみにmacOSにインストールされてるPHPを使わずにMAMP ProのPHPを使うために direnv 使ってます。

参考 [direnvを使おう - Qiita](https://qiita.com/kompiro/items/5fc46089247a56243a62)

```direnv edit .``` で下記を.envrcに記述しておけば、macOSのPHPよりMAMPのPHPが優先します。

```.envrc
PATH_add /Applications/MAMP/bin/php/php7.2.20/bin/
```

案件によってPHP5.2、7.1, 7.2, 7.3とかってあるので、direnvはだいぶ助かってます^^;
Railsにdeviseを導入する方法

## deviseとは

Rubyのgemで、ログイン機能を簡単に実装出来るようにしてくれます。ログイン機能を実装するためには本来、登録するユーザーのモデルを作って、保存するパスワードを暗号化したり、パスワードを再設定する機能を実装して、ユーザーを記憶するためのトークンを生成したりと様々な要素を実装する必要があります。

devise gemを使えばログインに必要な機能を提供してくれるだけでなく、ユーザーの認証やパスワードの保存というセキュリティ的に問題のある実装が許されない部分でセキュリティの安全性を保証してくれます。

## devise導入の手順

まずGemfileに、

```ruby
gem 'devise'
```

を追加してbundle installを実行してdeviseをインストールします。

```shell
rails g devise:install
```

を実行してdeviseの必要なファイルをインストールします。すると以下のようなメッセージが表示されます。

>=============================================================
Some setup you must do manually if you haven't yet:
1 Ensure you have defined default url options in your environments files. Here
is an example of default_url_options appropriate for a development environment
in config/environments/development.rb:

>config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

>In production, :host should be set to the actual host of your application.

>2 Ensure you have defined root_url to *something* in your config/routes.rb.
For example:

>root to: "home#index"

> 3 Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:

> `<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>`

>4 You can copy Devise views (for customization) to your app by running:
rails g devise:views

>=============================================================

以降、上記のメッセージにしたがってdevise gemの導入を行っていきます。

config/environments/development.rb の末尾に以下を追加します。

```config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```
次にroot to: "home#index"など、任意のルートurlを設定しておいて下さい。

app/views/layouts/application.html.erb ファイルに以下を追加してユーザー登録、ログインのエラーメッセージなどを表示するためのエリアを作ります。

```application.html.erb 
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
```
最後に、

```shell
rails g devise:views
```

のコマンドを実行すると、ユーザー登録やログイン画面、パスワード再設定画面などのユーザー登録やログインに必要な画面のテンプレートが作成されます。

```shell
rails g devise:install
```

を実行した時のセットアップメッセージの手順は全て完了になります。しかしまだdeviseを使用してユーザー登録をするためのモデルが存在しないので作成します。

```shell
rails g devise User
```

というコマンドを実行してUserモデルを作成します。その後rails db:migrateコマンドを実行して`http://localhost:3000/users/sign_up`にアクセスすると、以下のような画面が表示されてdeviseの導入完了になります。
<img width="150" alt="スクリーンショット-2019-07-19-11.56.26-300x231.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479957/05113ef9-94e5-0dce-99c9-31cc23e8195f.png">
EC2上のLaravelキューワーカをSupervisorで永続化

# はじめに
ちゃんとLaravelのキューを触る機会があり、永続化するため公式Docにも載っているSupervisorを使用しました。
Supervisorを使用すること自体初めてだったため間違った情報もあるかもしれません。ご容赦ください。

#### 環境
Amazon Linux 2
Laravel5.8
PHP 7.3.3
Python 2.7.14

# pipのインストール

```shell
$ sudo easy_install pip
```

# Supervisorのインストール

```shell
$ pip install supervisor
```

以下のコマンドでインストールの確認

```shell
$ supervisord -v
```

# コンフィグファイル作成

### デフォルトのコンフィグファイル生成

```sh
$ echo_supervisord_conf > /etc/supervisord.conf
```

### コンフィグファイル修正

[公式Doc](http://supervisord.org/configuration.html)を参考にコンフィグファイルを修正します。
私が修正した内容は以下になります。

```conf:/etc/supervisor.conf
[unix_http_server]
file=/var/run/supervisor.sock

[supervisord]
logfile=/var/log/supervisord.log
logfile_maxbytes=50MB               ;デフォルト
logfile_backups=10                  ;デフォルト
loglevel=info                       ;デフォルト
pidfile=/var/run/supervisord.pid
nodaemon=false                      ;デフォルト
minfds=1024                         ;デフォルト
minprocs=200                        ;デフォルト

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock

[include]
files = /etc/supervisord.d/*.ini
```

私と同じようにsockファイルの設定を変えた場合は新しく作成してください。

```sh
$ sudo touch /var/run/supervisor.sock
$ sudo chmod 777 /var/run/supervisor.sock
```

### program設定

Laravelキューワーカーを起動する設定を作成します。
私はincludeで指定したディレクトリに設定ファイルを配置していますが、supervisor.conf内に直接記述することもできます。

```ini:/etc/supervisord.d/laravel-worker.ini
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=ec2-user
numprocs=8
redirect_stderr=true
stdout_logfile=/tmp/worker.log
```

# サービス登録

`systemctl`を使用してsupervisorの起動、停止等の操作を行えるようにします。
`supervisord`コマンドと`supervisorctl`コマンドを使用して同様の操作は可能なので、不要な方は飛ばしてください。

/etc/systemd/system/supervisord.serviceを作成します。

```conf:supervisord.service
[Unit]
Description=Supervisor process control system for UNIX
Documentation=http://supervisord.org
After=network.target

[Service]
ExecStart=/usr/bin/supervisord -n -c /etc/supervisord.conf
ExecStop=/usr/bin/supervisorctl shutdown
ExecReload=/usr/bin/supervisorctl reload
KillMode=process
Restart=on-failure
RestartSec=50s

[Install]
WantedBy=multi-user.target
```

### 動作確認

```sh
$ systemctl start supervisord
$ systemctl status supervisord
$ systemctl stop supervisord
```

問題なければ自動起動に登録します。

```sh
$ sudo systemctl enable supervisord.service
```

# プロセス一覧確認

```sh
$ sudo supervisorctl status
laravel-worker:laravel-worker_00   RUNNING   pid 17275, uptime 0:00:14
laravel-worker:laravel-worker_01   RUNNING   pid 17276, uptime 0:00:14
laravel-worker:laravel-worker_02   RUNNING   pid 17277, uptime 0:00:14
laravel-worker:laravel-worker_03   RUNNING   pid 17278, uptime 0:00:14
laravel-worker:laravel-worker_04   RUNNING   pid 17279, uptime 0:00:14
laravel-worker:laravel-worker_05   RUNNING   pid 17280, uptime 0:00:14
laravel-worker:laravel-worker_06   RUNNING   pid 17281, uptime 0:00:14
laravel-worker:laravel-worker_07   RUNNING   pid 17282, uptime 0:00:14
```

以上でキューワーカーの永続化が完了しました。

# 参考
[[Laravel5.5]queue:workをsupervisorでデーモン化](https://qiita.com/yosida001/items/9209a293ee6c62b98143)
ブラウザのタブを閉じるときにアラートを出す

```javascript

var isタブを閉じる時にアラートを出す = true;

$(window).bind("beforeunload", function() {
	if (isタブを閉じる時にアラートを出す) {
		return "このページを離れようとしています。";
	}
}
```
「ノーム・カースの最優先条項」は原語では？

TL;DR
====

Retrospective prime directive by Norman Kerth

背景
====

「アート・オブ・アジャイルデベロップメント」の「5.3.3 ステップ１：最優先条項」にて、唐突に

> この目的を達成するために、私はノーム・カースの最優先条項[Kerth]を思い出すことから、ふりかえりを始める

という一文が登場します。
耳慣れない言葉が急に出てきて混乱したので、それが何を指しているのか調べてみました。

ノーム・カース
====

Project Retrospectives: Ahandbook for Team Reviews の著者の Norman L. Kerth を指しているらしい。著書は以下のリンクから。

https://www.amazon.co.jp/exec/obidos/ASIN/0932633447/xpjp-22

Retrospective prime directiveを逐語訳するなら
====

Retrospective: ふりかえり（の）
prime: 最優先（最初の）
directive: 指示・指令

といったところでしょうか。


最優先条項本文（日本語）
====

プロジェクトのふりかえりを行うに当たって、犯人探しではなく建設的に改善策を模索するためにふりかえりの参加者が同意すべきこと、というもののようです。

> 今日見つけたものが何であれ、チームの全員が、その時点でわかっていたことやスキルおよび能力、利用可能なリソースを余すことなく使って、置かれた状況下でベストを尽くした、ということを疑ってはならない

出典：アート・オブ・アジャイルデベロップメント 5.3.3 ステップ１：最優先条項

最優先条項原文
====

以下に原文を引用しておきます。

> Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.

https://retrospectivewiki.org/index.php?title=The_Prime_Directive
コピペで使うFirebase【立ち上げ編】

## 概要
firebaseを使用する際に、コピペで動かしたいと思い設定手順を投稿しようと思いました。

次回：[Firebase【テスト編】](https://qiita.com/ovama-koffee/items/f6569bb45ab51e40c39e)
## プロジェクトを作成してpackage.jsonを生成
```
$ mkdir [project名]
$ cd [project名]
$ npm init
```

## firebaseを設定
firebase-toolsをインストール

```
$ npm install --global firebase-tools
```

Firestore/Functions/Hosting/Storageを設定
基本的に初期設定のままでいいので全部yesを選択しましょう

```bash
$ firebase init
 ...
 ◯ Database: Deploy Firebase Realtime Database Rules
 ◉ Firestore: Deploy rules and create indexes for Firestore
 ◉ Functions: Configure and deploy Cloud Functions
 ◉ Hosting: Configure and deploy Firebase Hosting sites
❯◉ Storage: Deploy Cloud Storage security rules
 ...
 // 使用するプロジェクトを設定。
$ firebase use
```

デプロイ用のnpm-scriptsを追加します。
※　設定しなくても大丈夫ですが、以降npm-scriptで設定したaliasを使用します。

追加するのは、firestore・storageのみデプロイと全てのデプロイ
public/functionsのローカルサーバー起動。

```package.json
...
    "scripts": {
        "deploy": "firebase deploy",
        "deploy-rules": "firebase deploy --only firestore:rules,storage:rules",
        "serve-hosting": "firebase serve --only hosting",
        "serve-functions": "firebase serve --only functions",
        ...
    },
...
```

Functionsのコメントも外しましょう。

```diff:functions/index.js
const functions = require('firebase-functions');

// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions


-// exports.helloWorld = functions.https.onRequest((request, response) => {
-//  response.send("Hello from Firebase!");
-// });
+exports.helloWorld = functions.https.onRequest((request, response) => {
+ response.send("Hello from Firebase!");
+});
```

## 動作確認
```bash
// public
$ npm run serve-hosting
i  hosting: Serving hosting files from: public
✔  hosting: Local server: http://localhost:5000

// functions
✔  functions: Emulator started at http://localhost:5000
i  functions: Watching "/Users/user/[project名]/functions" for Cloud Functions...
✔  functions[helloWorld]: http function initialized (http://localhost:5000/xxxx/us-central1/helloWorld).
```

## デプロイ
デプロイが成功するとそれぞれのURLが表示されます。

```bash
$ npm run deploy
...
Function URL (helloWorld): https://xxxxx // Functions/index.js
Project Console: https://xxxx　// コンソールのURL
Hosting URL: https://xxxxx // public/index.html
```

## エラー集 or ハマったこと

```bash
$ firebase init
> Error: Cloud resource location is not set for this project but the operation you are attempting to perform in Cloud Firestore requires it. Please see this documentation for more details: https://firebase.google.com/docs/projects/locations.

// Firebase Console > Settings > [全般] > Google Cloud Platform（GCP）リソース ロケーション　
// ・ロケーションを選択する

$ npm run deploy-rules
> Error: The Cloud Firestore API is not enabled for the project

// Google Cloud Platform > Firestore
// ・別のデータベースが設定されているため、Firestoreを使用するように変更
```
何かと使えそうな都道府県の定数コード

完全に自分用ですが。
機会があればコピペでご利用ください。

```js:prefecture.js
const PREFECTURE_LIST = [
  { id: 1, name: '北海道' },
  { id: 2, name: '青森県' },
  { id: 3, name: '岩手県' },
  { id: 4, name: '宮城県' },
  { id: 5, name: '秋田県' },
  { id: 6, name: '山形県' },
  { id: 7, name: '福島県' },
  { id: 8, name: '茨城県' },
  { id: 9, name: '栃木県' },
  { id: 10, name: '群馬県' },
  { id: 11, name: '埼玉県' },
  { id: 12, name: '千葉県' },
  { id: 13, name: '東京都' },
  { id: 14, name: '神奈川県' },
  { id: 15, name: '新潟県' },
  { id: 16, name: '富山県' },
  { id: 17, name: '石川県' },
  { id: 18, name: '福井県' },
  { id: 19, name: '山梨県' },
  { id: 20, name: '長野県' },
  { id: 21, name: '岐阜県' },
  { id: 22, name: '静岡県' },
  { id: 23, name: '愛知県' },
  { id: 24, name: '三重県' },
  { id: 25, name: '滋賀県' },
  { id: 26, name: '京都府' },
  { id: 27, name: '大阪府' },
  { id: 28, name: '兵庫県' },
  { id: 29, name: '奈良県' },
  { id: 30, name: '和歌山県' },
  { id: 31, name: '鳥取県' },
  { id: 32, name: '島根県' },
  { id: 33, name: '岡山県' },
  { id: 34, name: '広島県' },
  { id: 35, name: '山口県' },
  { id: 36, name: '徳島県' },
  { id: 37, name: '香川県' },
  { id: 38, name: '愛媛県' },
  { id: 39, name: '高知県' },
  { id: 40, name: '福岡県' },
  { id: 41, name: '佐賀県' },
  { id: 42, name: '長崎県' },
  { id: 43, name: '熊本県' },
  { id: 44, name: '大分県' },
  { id: 45, name: '宮崎県' },
  { id: 46, name: '鹿児島県' },
  { id: 47, name: '沖縄県' },
]

export default {
  data() {
    return {
      PREFECTURE_LIST: PREFECTURE_LIST,
    }
  }
}

```
gitで複数のリモートリポジトリにpushしたい

## きっかけ
とあるファイルをGitLabで管理していたところ、
**「・・・GitHubにも置いておきたい！！！」**

## 複数のリモートリポジトリを登録する
### 現在のリモートリポジトリを確認
```
git remote -v
origin	git@gitlab.com:sample/samplesample.git
origin	git@gitlab.com:sample/samplesample.git
```

### リモートリポジトリを追加
```
git remote add hello https://github.com/nanamicronn/samplesample.git
```

### 再度リモートリポジトリを確認
```
git remote -v
hello	https://github.com/nanamicronn/samplesample.git (fetch)
hello	https://github.com/nanamicronn/samplesample.git (push)
origin	git@gitlab.com:re_build-bootcamp/samplesample.git (fetch)
origin	git@gitlab.com:re_build-bootcamp/samplesample.git (push)
```

`origin`の代わりに`hello`とすることでpushの際に区別することができる！

### それぞれのmasterにpushしてみる
既存のリポジトリ

```
git push origin master
```
新規でつくったリポジトリ

```
git push hello master
```

## さいごに
頭で考えると混乱してしまって「嫌だな〜」
と思っていたけど案外シンプルな作業だった・・・
複数のデータを結合するSQLクエリ

こんにちは。
~~[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)のインターン生です。~~（2020年1月退社）
今回は複数のデータを結合するSQLクエリについて書いていきます。


例として、下の二つの表`Members`、`TestScores`を結合する場合を考えます。

Table: Members

|Name|Sex|Age|          
|:-:|:-:|:-:|             
|Tom|Male|18|             
|Kate|Female|31|
|Susie|Female|43| 
|Sam|Male|22|

Table: TestScores

|Name|English|Math|
|:-:|:-:|:-:|
|Tom|54|76|
|Susie|65|25|
|Sam|48|92|

## データ間で対応している行だけを結合する場合

両データの対応している行（上の例の場合、`Tom`、`Susie`、`Sam`の３行）のみを結合する場合、`INNER JOIN`を用いて、下のようなコードを書きます。

```sql:members.sql
SELECT *
FROM Members
INNER JOIN TestScores
ON Members.Name = TestScores.Name;
```

実行結果は以下のようになります。

|Name|Sex|Age|English|Math| 
|:-:|:-:|:-:|:-:|:-:|
|Tom|Male|18|54|76|
|Susie|Female|43|65|25|
|Sam|Male|22|48|92|

`TestScores`には`Kate`の行がありませんので、`Kate`の行は切り落とされます。

## データ間で対応していない行も結合する場合

`Kate`の行も含めて結合するには、`LEFT JOIN`を使います。



```sql:members.sql
SELECT *
FROM Members
LEFT JOIN TestScores
ON Members.Name = TestScores.Name;
```

上のように書くと、以下の実行結果が得られます。

|Name|Sex|Age|English|Math| 
|:-:|:-:|:-:|:-:|:-:|
|Tom|Male|18|54|76|
|Kate|Female|31|||
|Susie|Female|43|65|25|
|Sam|Male|22|48|92|

`TestScores`の中には`Kate`の行がありませんが、`Kate`の行も結合されました。
このとき、`LEFT JOIN`は、左側の表のすべての行を残し、右側の表の対応する行を結合します。この際、右側の表の中に対応する行がない場合、その部分は空白で埋められます。
`RIGHT JOIN`はその逆です。
`FULL JOIN`は、両側の表にあるすべての行を残して結合します。

## まとめ

今回は、SQLで複数の表を、`JOIN`を用いて結合するクエリについてまとめました。
もし間違いなどがありましたら、訂正しますので、ご指摘のほどよろしくお願いいたします。