OmniAICreator/Qiita-1.07M huggingface dataset:
[ruby] Google Firebase Storageの簡単な使い方

# Spark プラン 無料枠 Storage

https://firebase.google.com/pricing
![Firebase_Pricing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/9eb039d7-680a-0c35-ca7d-d3a11213b910.png)

# プロジェクトID
![clouds_–_Project_settings_–_Firebase_console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/cc3cd796-c89b-26ac-8dd2-d458ef45f351.png)


# バケットID
複数のバケットは持てないので、ここに表示されるドメイン名がそれ(`gs://`以下)

![clouds_–_Storage_–_Firebase_console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/d651aa68-1f54-0fc6-9d12-eb7830b3c773.png)


## コードサンプル等
![オブジェクトの命名ガイドライン_ _ _Cloud_Storage_ _ _Google_Cloud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/7bc68732-e3c4-e846-a45d-13abe4f2d8f5.png)

- [リンク][1]
- [リンク][2]
- [リンク][3]


```rb:storage
storage = Google::Cloud::Storage.new(project_id: ENV["FIREBASE_PROJECT_ID"])
```

```rb:bucket
bucket = storage.bucket ENV["FIREBASE_STORAGE_BUCKET_ID"]
```


```rb:ファイルの追加
bucket.create_file "/path/to/file" # バケットのルートに置く
bucket.create_file "/path/to/file", "folder/name/file" # バケットのサブフォルダに置く

# metadataを付けて置く（後で説明するpublic_urlで必要になる）
# tokenはぶつからない、推測されにくいものであれば何でも良さそう
require "active_support/all"
bucket.create_file "/path/to/file", metadata: { firebaseStorageDownloadTokens: SecureRandom.uuid }
```

```rb:ファイルの参照
files = bucket.files # 全部

# Signature: find_files(prefix:?, delimiter:?, token:?, max:?, versions:?)
# 例 a/b/c_d_e.jpg というファイルがあった場合、
# bucket.find_files prefix: "a/b/c_" で見つけられる path.start_with? 的な
files = bucket.find_files prefix: "folder/sub/prefix"

file = bucket.file("path/to/file") # 直接ファイル1つ
```

```rb:更新
bucket.create_file "/path/to/file1", "folder/sub/file" 
bucket.create_file "/path/to/file2", "folder/sub/file"  # 同じところに同じ名前で置く
```


```rb:削除
file.delete
```


```rb:誰でもアクセスできるURL
file.signed_url # => デフォルトで5分間の公開が可能
file.signed_url expires: 1.hour.to_i # => 1時間の公開が可能、最大で7日間
```

[Signed URL example][3]
> X-Goog-Expires: The length of time the signed URL remained valid, measured in seconds from the value in X-Goog-Date. In this example the Signed URL expires in 15 minutes. The longest expiration value is 604800 seconds (7 days).


```rb:誰でもアクセスできるURL（永続的）
def public_url(file)
  # more like permanent
  URI(
    "https://firebasestorage.googleapis.com/v0/b/#{CGI.escape file.bucket}/o/#{CGI.escape file.name}",
  ).tap do |uri|

    uri.query = {
      token: file.metadata["firebaseStorageDownloadTokens"],
      alt: :media,
    }.to_query
  end
end
```
`firebaseStorageDownloadTokens`がここで必要になるので、ファイルを置く時に`metadata`の指定が必要になる。
（javascriptからだとアップロードしたファイルの`downloadUrl`がメソッドとして提供されているが、rubyだとまだない？）

[Qiita][4]
[How to Access and Download Files in Cloud Storage][5]

[1]: https://googleapis.dev/ruby/google-cloud-storage/latest/Google/Cloud/Storage.html
[2]: https://cloud.google.com/storage/docs/how-to?hl=ja
[3]: https://cloud.google.com/storage/docs/access-control/signed-urls#example

[4]: https://qiita.com/HorikawaTokiya/items/8d0a9075bc49ea3e74e1
[5]: https://medium.com/firebase-developers/firebase-how-to-access-and-download-files-in-cloud-storage-b8f2cf49aa13
Firebaseのタイムスタンプ型をSwiftでDate型にキャスト

まずはFirebaseのデータを配列？リスト？として取得するクラスを作成
もともとFirebaseにはdateという名前のタイムスタンプ型のフィールドが登録されている前提

```swift

import Foundation
import CodableFirebase 
import Firebase

struct Info : Decodable {
    
    //Firebaseから取得するフィールドを格納する変数を定義
    var id : String?
    var messageId : String?
    var roomid : String?
    var senderid : String?
    var created_date : Date?
    
    static func decode(_ data : [String:Any]) -> Info? {
        do {
            var item = try FirestoreDecoder().decode(Info.self, from: data)
            if let timestamp : Timestamp = data["date"] as? Timestamp {
                item.created_date = timestamp.dateValue()
            }
            return item
        }catch {
            return nil
        }
    }
}


```
呼び出す時はこんな感じ。

```swift
import Foundation
import UIKit
import Firebase


    var Sample_Array: [Info] = []
    var firestore = Firestore.firestore()
  

    override func viewDidLoad() {
        super.viewDidLoad()

        self.firestore.collection("info_data").getDocuments { (snaps, error) in
            guard let documents = snaps?.documents else { return }
            self.Sample_Array = []
            for document in documents {                  
                guard let item = Info.decode(document.data()) else{
                    continue
                }
                self.Sample_Array.append(item)
            }
            print(self.Sample_Array)
        }
    }

```

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
転職のために開発を始めたい方へのアンチパターン

## 結論
* 自分の作りたいアプリは作るな
    * サンプルアプリを作れ
* １ヶ月かけて作ろう
    * 土日で作れ

### なんでなん？
* アプリを作るのは大変
* githubに成果物入れたほうが転職とかで都合がいい
* やりたいことを増やすと凝りすぎて終わらない
* サンプルアプリなら思想入れずに、やりたいことをミニマムで完了できる
* 刹那的なモチベーションは続かない
 
### まとめ
エンジニアならきちんとコミットするべきです。
githubにリポジトリがあると転職などの際に武器になります。
コミットしやすい単位にし、最小の努力でアウトカムを最大化しましょう。

以上です。


## 前ふり（予定だったけどやめた）
どうも、八流エンジニアです。
本記事は、個人開発をやりたいなーと思っている方に向けるものです。
そして、僕みたいに
`半端に作ったものしかなく、世に出すものがない！という人間をこれ以上増やしたくない`
という思いだけでかきました。

実は自分も今まで個人開発というものを少なからずやっていました。


* htaのjsonパーサアプリから始まり（もはやhtaは需要ない、10年以上前だししゃーない）
* Androidのポケモン図鑑（githubに公開するのにポケモンの画像仕込むのはまずい）
    * いい感じに画像を抽出するshell（もうやばい）
    * 特定のurlから画像漁るpython（これもあんまり）
* Flutterの離婚助長アプリ
    * こんなもん作ってるやつ人として信用できん！もうヤバいって・・
        * 離婚している人多いらしいから気軽に思ってもいいんじゃない？ってマインドあったの
    * かなり作りかけ
* Flutterのアロマアプリ（かなり作りかけ）
    * 無駄に画像課金（123rf）した挙げ句頓挫しました。
    * 半端すぎてgithubに公開していいかわからない
    * fireStoreからデータ引っ張ってこれるおもろーってなったり
    * twitterとinstagram連携させてui引っ張ってこようとした
    * デザイン書いてproviderで遊んでた
    * 詰め込みすぎて飽きた
    * かなり作りかけ

と、色々作りかけていましたが
最近githubに公開できる状態のものがないことに気が付きました！
「転職用にPUBLICにしたいけど、人に見せられるものがない！！！！！！！」

自分みたいな人をこれ以上作りたくないと思いまして筆を執りました。

#### 解決策はシンプルです
だいたい企業が見たいソースなんてものは、
基礎的な文法とアーキとテスト作ってるのをみて、まぁまぁいいんじゃない？程度に見るためのものです（偏見）
そのため、サンプルで十分なんですよ。リポジトリがあるだけで謎の安心感あるんですよ。

サンプル作る際に、次から次へとやってみたいことを盛り込みすぎる人は出てくると思います。
やめとけ・・・その先は地獄だぞ

転職用にモノなんてつくりたくないじゃぁー！！！って僕は思います。
個人開発なんてできっこないグループは絶対います。
それでもライブラリやFWを試したくなる気持ちはわかります。
その際は、物を作ろう！ではなく、サンプルを作ろう！を意識しましょう。


2021/03/16追記
サンプル土日に作ってみました。こんな感じでもいいんじゃない？

https://qiita.com/tomotakasg/items/19be0038b8933fbf751b
BigQueryに関する技術情報リンク集

順次追加

# パフォーマンスチューニング
- [BigQuery におけるコスト最適化の ベスト プラクティス](https://cloud.google.com/blog/ja/products/data-analytics/cost-optimization-best-practices-for-bigquery)
- [クエリ パフォーマンスの最適化の概要](https://cloud.google.com/bigquery/docs/best-practices-performance-overview?hl=ja)
- [Cloud Storage のパフォーマンスを最適化する](https://cloud.google.com/blog/ja/products/gcp/optimizing-your-cloud-storage-performance-google-cloud-performance-atlas)
    - gsutilでデータアップロード転送する場合の最適な方法、など書いてある 

# DMLのベストプラクティス
[BigQuery 特集: データ操作（DML）](https://cloud.google.com/blog/ja/products/data-analytics/bigquery-explained-data-manipulation-dml)

# DWHのBigQueryへの移行
[データ ウェアハウスの BigQuery への移行](https://cloud.google.com/solutions/migration/dw2bq/dw-bq-migration-overview?hl=ja)
- 導入と概要/スキーマとデータ転送の概要/データ ガバナンス/データ パイプライン/レポートと分析/パフォーマンスの最適化とそれぞれにトピックごとに書かれている
- また、移行元DWHとして、Netezza/Oracle/Amazon Redshift/Teradata それぞれについてガイドもある

# クエリのインメモリ実行について
[In-memory query execution in Google BigQuery](https://cloud.google.com/blog/products/gcp/in-memory-query-execution-in-google-bigquery)
Pythonでsocket通信 (HTTPプロトコル)

socket通信でHTTPプロトコルを再現してみた話。フレームワークの便利さを実感したのと、フレームワークの下でどんな動作が行われているかを知る良い機会となりました。

ローカルサーバ(127.0.0.1:8080)を立てたのち、ブラウザでそのサーバにアクセスしてHTML表示したあとに以下プログラムを走らせると、body部分やHTTPヘッダーの情報をGETしてファイルに出力されます。ブラウザでアクセス前に以下プログラムを走らせてもHTML関連のレスポンスデータは得られないので注意！もちろん、サーバ側はクライアントからのGET要求に対しデータを返すという前提がある。
pythonのsocketドキュメントはこちら→ https://docs.python.org/ja/3/library/socket.html

```python:client.py
import socket
import os.path
import datetime

#接続先サーバの指定
server =('127.0.0.1',8080)
#socketの設置
soc =socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#serverにコネクション接続！！
soc.connect(server)

#サーバ(localhost:8080/test)から取得した情報を整理して表示
msg  ='GET /test HTTP/1.1\r\n'
msg +='Host: localhost:8080\r\n'
msg +='\r\n'
#HTMLはutf-8しか対応していないのでエンコードしてサーバに送信する必要がある
soc.send(msg.encode('utf-8'))
#1回の通信で受信するデータ量を指定(大体2048の倍数)したのち、
#サーバから受信したメッセージをデコード
data =soc.recv(4096).decode('utf-8')

#ファイルを開いて、取得した情報を"response.txt"として出力
f =open('response.txt',mode='a')　#mode = w:上書き / a:追記
#出力ファイルの場所と名前指定
filepath ='./response.txt'
#今回は追記するので前回分との境目が分かるようにラインを引いた
lines ="\r\n#############################\r\n"
#タイムスタンプ関連の表示設定
p  =os.stat(os.path.abspath(filepath))
dt =datetime.datetime.fromtimestamp(p.st_mtime)
#複数の引数を指定したい場合↓は「.writelines」を用いる
f.writelines((data,"\r\nSave Date:",dt.strftime("%Y-%m-%d %H:%M:%S"),lines))
#ファイル閉じる
f.close()

print('Completed writing response to response.txt in the current dir.\r\n' + str(data))
#socketを閉じる
soc.close()
print("Client Stopped...")
```
client側にはconnectionという概念がないので、socketを開通したり、閉じたりだけでOK。
HTTPプロトコルが1回1回の通信でセッションを切るのに対し、socket通信は指定するまで通信をどこで切るか(どこまでが1回の通信なのか不明)判断してくれないので、こちらで事前に指定する必要がある。
Goで月(Month)をint型にしたい

Goでは月を取得するとint型ではなく、`March`みたいな値が出力される。
JavaScriptでは月を取得すると、number型（Goでいうint型）になるので少し驚いたのでメモ。
（しかも、JSは0から始まるから厄介...）

## そのまま月(Month)を取得しようとすると
```go
package main

import (
	"fmt"
	"time"
)

func main()  {
	t := time.Now()
	month := t.Month()
	fmt.Printf("type=%T value=%v\n", month, month)
}
```

```terminal:結果
type=time.Month value=March
```
結果として、`time.Month型`という型の`March`が返される。


## 月(Month)をint型にするには
これをint型で扱うにはどうすれば良いか？
今回の例の場合は`March`を`3`と扱うにはどうすれば良いか？

これは簡単で、`time.Now().Month()`を`int()`で「`time.Month型` => `int型`」に型変換してあげればOK！

```go
package main

import (
	"fmt"
	"time"
)

func main()  {
	t := time.Now()
	month := t.Month()
	// 型変換でint型へ
	monthToInt := int(month)
	fmt.Printf("type=%T value=%v\n", monthToInt, monthToInt)
}
```

```terminal:結果
type=int value=3
```
これで`March`ではなく`3`というint型で扱える。
以上。
Laravelのmigration classでchangeメソッドが使用できない

##現象
ある既存のカラムでNULL値を許可orDEFAULT値を設定するようにしたく、
migrationを実行したところ以下のエラーに遭遇。

```
RuntimeException:Changing columns for table "テーブル名" requires Doctrine DBAL.
Please install the doctrine/dbal package.
```

##対処法
素直にdoctrine/dbal packageをcomposerでinstallする。

```
composer require doctrine/dbal
Using version ^3.0 for doctrine/dbal
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
  - Installing composer/package-versions-deprecated (1.11.99.1): Downloading (100%)         
  - Installing doctrine/event-manager (1.1.1): Downloading (100%)         
  - Installing doctrine/cache (1.10.2): Downloading (100%)         
  - Installing doctrine/dbal (3.0.0): Downloading (100%) 
  ...
```

よし、これでOK。
再度migrationを実行してみます。

```
Migrating : 2021_03_01_001211_modify_employees_table_20210301

Symfony\Component\Debug\Exception\FatalThrowableError  
: Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
```

Driverがないだと。。。
こういう時こそ落ち着いて、エラー文で示してくれているディレクトリの中を覗くと原因が判明する。
vendor/doctrine/dbal/src/Driver/
↑
こちらのパスにPDOMySqlが存在しなかった。

###他にも同様の現象に出くわしている方がいると期待し検索
[[laravel] doctrine/dbalを入れたのに「Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found」と言われる](https://qiita.com/snbk/items/803aea10773052629a45)

こちらの方が仰られている通り、
ver3.x系(先程installしたversion)とver2.x系とではディレクトリ構成が変わっていました。
気を取り直し、バージョンを指定しinstallし直す。

```
composer require "doctrine/dbal:2.*"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
  - Downgrading doctrine/dbal (3.0.0 => 2.12.1): Downloading (100%)  
 ...
```

最後に以下を実行し無事解決に至る。（多謝）

```
php artisan migrate:refresh --seed
```

```php:該当のmigrationファイル
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class ModifyEmployeesTable20210301 extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table->string('first_name')->nullable()->change();
            $table->string('last_name')->nullable()->change();
            $table->tinyInteger('email_verified')->default(0)->after('email_verified_at');
            $table->string('email_verify_token')->nullable()->after('email_verified');
            $table->tinyInteger('status')->default(0)->after('email_verify_token');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('employees', function (Blueprint $table) {
            $table->string('first_name')->nullable(false)->change();
            $table->string('last_name')->nullable(false)->change();
            $table->dropColumn('email_verified');
            $table->dropColumn('email_verify_token');
            $table->dropColumn('status');
        });
    }
}
```

まだまだ未熟者ですが、
経験を蓄積していく為に記事にして残すことを決意した次第です。
今後とも先輩方、宜しくお願い致します。
【Rails】link_toのxxx_pathが長い時はpolymorphic_pathを使うと綺麗に書けるお話

Railsにはよく使うものとして`link_to`や`button_to`があります。これらはリンクやボタンを生成するヘルパーです。

更に、遷移先のURLやpathを指定することが出来て、以下のように書けます。

```erb
<%= link_to '詳細へ', user_path(user.id) %>
```

では、URLのネストをした場合、`xxx_path`はどうなるでしょうか？

例えば、ユーザーは記事を投稿でき、その記事たちをお気に入りに追加できる機能があったとします。

ルーティングはこちら

```ruby:routes.rb
Rails.application.routes.draw do
  # ユーザーは記事を投稿できる
  resources :users do
    resources :articles do
      # 記事をお気に入りすることができる
      resources :favorites
    end
  end
end
```

rails routesを叩いて`xxx_path`の部分を見てみましょう。

お気に入りの新規保存に使えるであろうfavorites#createは`user_article_favorites`になってます。
これはまだマシですが、もっとネストされたら長くなり、`xxx_path`の部分が分かり辛くなるでしょう。

```shell
$ rails routes

user_article_favorites     GET    /users/:user_id/articles/:article_id/favorites(.:format)          favorites#index
                           POST   /users/:user_id/articles/:article_id/favorites(.:format)          favorites#create
new_user_article_favorite  GET    /users/:user_id/articles/:article_id/favorites/new(.:format)      favorites#new
edit_user_article_favorite GET    /users/:user_id/articles/:article_id/favorites/:id/edit(.:format) favorites#edit
user_article_favorite      GET    /users/:user_id/articles/:article_id/favorites/:id(.:format)      favorites#show
                           PATCH  /users/:user_id/articles/:article_id/favorites/:id(.:format)      favorites#update
                           PUT    /users/:user_id/articles/:article_id/favorites/:id(.:format)       favorites#update
                           DELETE /users/:user_id/articles/:article_id/favorites/:id(.:format)       favorites#destroy

```


# 本題（polymophic_path)を使おう！

Railsにはモデルから生成されたインスタンスに対して、ルーティングをスマートに書ける方法が提供されています。

公式ドキュメントは[こちら](https://api.rubyonrails.org/v6.1.0/classes/ActionDispatch/Routing/PolymorphicRoutes.html)

結論から言うと、こう書いていたものが、

```erb
# user    = User.find(1)
# article = Article.find(1)

<%= button_to 'お気に入りする', user_article_favorites_path(user.id, article.id), method: :post %>
```

こう書けます

```erb
<%= link_to 'お気に入りする', polymorphic_path([user, article, :favorites]), method: :post %>
```

何をしているかと言うと、polymorphic_pathの引数においたモデルインスタンスを元にリンクを生成してくれています。
今回の場合 `users/1/articles/1/favorites`が生成されています。

ポイントは以下の3つです。

* 基本的に引数にはModelのインスタンスを置く
* 引数を複数置きたい場合は配列で囲む
* インスタンスの生成が行われていない場合は、`:favorites`のようにシンボル型で引数に置く

今回の例よりさらに複雑になったpathであれば可読性はさらに向上すると思います。
（逆にusers_pathといった短いものにpolymorphic_pathを使うと変に見えるかもしれません。）

## polymorphic_pathの応用

先ほどとは別にnewアクションやeditアクションへのリンクを生成したい場合は以下のように書くこともできます。

```erb
# user    = User.find(1)
# article = Article.find(1)

<%= link_to '編集へ', edit_polymorphic_path([user, article ]) %>

<%= link_to '新規作成へ', new_polymorphic_path([user, article ]) %>
```
`edit_polymorphic_path([user, article ])` の場合、`users/1/articles/1/edit`のようなリンクが生成されます。

# まとめ

RailsにはDRYの法則に則ったヘルパーやメソッドがたくさん用意されています。
今回扱ったpolymorphic_pathは長くなりがちなpathの記述を簡潔に書くことができます。
ぜひお試しください！
if文なしでじゃんけん javascript

[if文なしでじゃんけん - Qiita](https://qiita.com/tadsan/items/65d91ba6b50535fc8815) を読んで、自分ならどうするか考えてみた。

### 解答
```javascript
const battle = {
    "グー": {
        "グー": "あいこ",
        "チョキ": "あなたの勝ち",
        "パー": "あなたの負け",
    },
    "チョキ": {
        "グー": "あなたの負け",
        "チョキ": "あいこ",
        "パー": "あなたの勝ち",
    },
    "パー": {
        "グー": "あなたの勝ち",
        "チョキ": "あなたの負け",
        "パー": "あいこ",
    },
}

const battleResult = (myHand, yourHand) =>
    `[${myHand}] vs [${yourHand}] => ${battle[myHand][yourHand]}`

console.log(battleResult("グー", "チョキ"))
console.log(battleResult("グー", "グー"))
console.log(battleResult("グー", "パー"))
```

可読性 MAX !!

### 結果
```
[グー] vs [チョキ] => あなたの勝ち
[グー] vs [グー] => あいこ
[グー] vs [パー] => あなたの負け
```
useStateの使い方

#概要
先日、React Hooksの学習を行いました。
今回は、useStateの使い方を紹介します。

##目次
- 事前知識
- Hookを使用するメリット
- useStateの使い方
- useStateの実用例
- 最後に...

##事前知識
>Reactには、関数コンポーネント(関数型で定義されたコンポーネント)とクラスコンポーネント(クラス型で定義されたコンポーネント)があります。
クラスコンポーネントでは、関数コンポーネントとは異なり、state(状態管理)やライフサイクルメソッドを使用する事が出来ます。

##Hookを使用するメリット
Hookを使用する事で、クラス機能(stateやライフサイクルメソッド)を関数コンポーネントでも使える様になります。
これにより、コードを簡潔に書け、可視性が上がりました。
>補足
・旧Reactの記述方法で開発を進めており、途中にReact Hooksを使用しても、これまでの記述に悪影響を出さないというのもメリットの一つです。

##useStateの使い方
まずは、useState関数をインポートします。

```React:useState関数をインポート
import React, { useState } form 'react';
```

次に、下記のコードでuseState関数を定義します。

```React:useState関数を定義
const [stateの変数名, stateを変更させる関数名] = useState(stateの初期値);
```

最後に、stateを変更させる関数名をJSX内でアロー関数を用いて呼び出します。

```React:useState関数を呼び出す
const App = () => {
 stateを変更させる関数名(変更したstateの値)
};
```

##useStateの実用例
useStateを使ったカウントアップ関数の例を紹介します。

```React:useStateの使用例
import React, { useState } from 'react';

const App = () => {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <div>
        <p>{count}</p>
        <button onClick={() => setCount(count + 1)}>
          Click
        </button>
      </div>
    </div>
  );
};

export default App;
```

###最後に...
今回は、useStateの使い方を紹介しました。

最後まで、読んでいただきありがとうございました。
if文なしでじゃんけん Javascript版

[if文なしでじゃんけん](https://qiita.com/tadsan/items/65d91ba6b50535fc8815) を見ました。

事前に勝敗を定義するのは反則な気がしたので作ってみました。
勝敗は自分と相手の手の差に mod(3) を取ればわかります。

### コード
```js
const hands = ['✊', '✌', '✋'];
const results = ['あいこ', 'あなたの負け', 'あなたの勝ち'];

hands.forEach((myHand, myVal) => {
  hands.forEach((yourHand, yourVal) => {
    console.log(
      `[${myHand} vs ${yourHand}] ${results[(myVal - yourVal + 3) % 3]}`
    );
  });
});
```

### 表

<table>
  <tr>
    <th colspan="2" rowspan="2">(myVal - yourVal + 3) % 3</th>
    <th colspan="3">yourVal</th>
  </tr>
  <tr>
    <th>✊0</th>
    <th>✌1</th>
    <th>✋2</th>
  </tr>
  <tr>
    <th rowspan="3">myVal</th>
    <th>✊0</th>
    <td>0 <font color=green>draw</font></td>
    <td>2 <font color=red>win</font></td>
    <td>1 <font color=blue>lose</font></td>
  </tr>
  <tr>
    <th>✌1</th>
    <td>1 <font color=blue>lose</font></td>
    <td>0 <font color=green>draw</font></td>
    <td>2 <font color=red>win</font></td>
  </tr>
  <tr>
    <th>✋2</th>
    <td>2 <font color=red>win</font></td>
    <td>1 <font color=blue>lose</font></td>
    <td>0 <font color=green>draw</font></td>
  </tr>    
</table>


### 結果

```
[✊ vs ✊] あいこ
[✊ vs ✌] あなたの勝ち
[✊ vs ✋] あなたの負け
[✌ vs ✊] あなたの負け
[✌ vs ✌] あいこ
[✌ vs ✋] あなたの勝ち
[✋ vs ✊] あなたの勝ち
[✋ vs ✌] あなたの負け
[✋ vs ✋] あいこ
```

### 応用
手の種類が奇数なら、じゃんけんの拡張も可能
例えば五行に見立てて

<table>
  <tr>
    <th colspan="2" rowspan="2">(myVal - yourVal + 5) % 5</th>
    <th colspan="5">yourVal</th>
  </tr>
  <tr>
    <th>木0</th>
    <th>火1</th>
    <th>土2</th>
    <th>金3</th>
    <th>水4</th>
  </tr>
  <tr>
    <th rowspan="5">myVal</th>
    <th>木0</th>
    <td>0 <font color=green>draw</font></td>
    <td>4 <font color=blue>lose</font></td>
    <td>3 <font color=red>win</font></td>
    <td>2 <font color=blue>lose</font></td>
    <td>1 <font color=red>win</font></td>
  </tr>
  <tr>
    <th>火1</th>
    <td>1 <font color=red>win</font></td>
    <td>0 <font color=green>draw</font></td>
    <td>4 <font color=blue>lose</font></td>
    <td>3 <font color=red>win</font></td>
    <td>2 <font color=blue>lose</font></td>
  </tr>
  <tr>
    <th>土2</th>
    <td>2 <font color=blue>lose</font></td>
    <td>1 <font color=red>win</font></td>
    <td>0 <font color=green>draw</font></td>
    <td>4 <font color=blue>lose</font></td>
    <td>3 <font color=red>win</font></td>
  </tr>
  <tr>
    <th>金3</th>
    <td>3 <font color=red>win</font></td>
    <td>2 <font color=blue>lose</font></td>
    <td>1 <font color=red>win</font></td>
    <td>0 <font color=green>draw</font></td>
    <td>4 <font color=blue>lose</font></td>
  </tr>
  <tr>
    <th>水4</th>
    <td>4 <font color=blue>lose</font></td>
    <td>3 <font color=red>win</font></td>
    <td>2 <font color=blue>lose</font></td>
    <td>1 <font color=red>win</font></td>
    <td>0 <font color=green>draw</font></td>
  </tr>  
</table>

手が増えれば増えるほど、事前にすべての勝敗を定義するのが困難になりますよね。



### 感想
法則性はないかと表を作ってみて気づきました
が、調べてみると一般的なアルゴリズムのようですね。
Fargate PV 1.4.0 では空文字のコマンド引数が無視されるから気を付けた方がいい

# tl; dr

- Fargate プラットフォームバージョン 1.4.0 では、コンテナで実行するコマンドの引数に空文字を渡すと無視される。
- Fargate プラットフォームバージョン 1.4.0 を使用する限り、この挙動は回避できない模様。
- 現時点で引数に空文字を使うには Fargate プラットフォームバージョン 1.3.0 を利用するしかない模様。

# 検証

## Dockerfile

```Dockerfile
FROM alpine:3.13.2
RUN echo 'echo "\$0（script_name）: $0"; \
    echo "\$1（first_args）: $1"; \
    echo "\$2（second_args）: $2"; \
    echo "\$3（third_args）: $3"; \
    echo "\$4（4th_args）: $4"; \
    echo "\$5（5th_args）: $5"; \
    echo "\$#（number_of_args）: $#"; \
    echo "\"\$*\": \"$*\""; \
    echo "\"\$@\": \"$@\""' > /args_test.sh
CMD ["/bin/sh", "/args_test.sh", "first", "", "third", "", "5th"]
```

## Fargate PV 1.3.0 での実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36663/792248f9-c436-3600-7312-0378b7318401.png)

## Fargate PV 1.4.0 での実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36663/4034af47-938f-895f-5591-188a72c9798a.png)

# どうすべきか

- LATEST が 1.4.0 に変更されるにあたって、検証を行う際はネットワーク周りの確認だけでなく、コンテナの最終的な実行結果まで確認を行った方が良さそう。
- その確認が難しいようであれば、現時点では 1.3.0 に固定するのが無難そう。
- また、タスク定義やタスク実行時の CMD 上書きでも再現するため、動的に引数を設定している様なタスクでは、さらに検証で注意が必要である。
TypeScriptで文字列配列からCSVダウンロード

- IE対応。
- コンマや改行を含むセルは " で囲む。

```ts
declare global {
  interface Navigator {
    msSaveBlob?: (blob: any, defaultName?: string) => boolean;
  }
}

function downloadCsvBlob (data: string[][], fileName: string) {
  const bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
  const re = /[,\r\n"]/;
  const csv = data.map(record => record.map(value => re.test(value)
    ? `"${value.replace(/"/g, '""')}"` : value).join(',')).join('\r\n');
  const blob = new Blob([bom, csv], { type: 'text/csv' });

  if (window.navigator.msSaveBlob) { // for IE,Edge
    window.navigator.msSaveBlob(blob, fileName);
  } else {
    const url = URL.createObjectURL(blob);
    const el = document.createElement('a');
    el.href = url;
    el.setAttribute('download', fileName);
    document.body.appendChild(el);
    el.click();
    URL.revokeObjectURL(url);
    if (el.parentNode) {
      el.parentNode.removeChild(el);
    }
  }
}
```
PythonでHDF5 fileの読み込み&書き出し

この記事は備忘録です。

Python可視化の記事:
・[応用編1](https://qiita.com/coffiego/items/dfabde5f8588723b32d6)
・[基礎編](https://qiita.com/coffiego/items/52315ea45fcc6d83b5b9)


#この記事でできること
#####・HDF5ファイルの読み込み、書き出し

#使うライブラリー
この記事で使うライブラリーは以下になります。ひとまず以下のコードをコピペしてコードの上に貼っておけば問題ないです。

```python
import matplotlib.pyplot as plt #実際にプロットする
import numpy as np #データの整理
import pandas as pd #データフレームのライブラリ
import h5py #HDF5のライブラリ
```



# HDF5ファイルの読み出し&書き出し

```python

#読み出し
filename = "your HDF5 file name" #ここに読み込みたいfile name
h5file = h5py.File(filename,"r")
read_value = h5file["dir_1/dir_2/dir_3/input"].value #ファイルの階層構造をここに書く

# 書き出し
h5file = h5py.File(filename,'w') #書き出しfilename
group = h5file.create_group('group1') #一番上の階層グループ
group.create_dataset('subgroup1', data=val1) #一つ下の階層
group.create_dataset('subgroup2', data=val2) #一つ下の階層
group.create_dataset('subgroup2', data=val3) #一つ下の階層
h5file.flush()
h5file.close()
```

# CSV読み込み&書き出し

```python

#読み込み
#headerあり
data = pd.read_csv("filename.csv",delimiter=',')
value = data['column_name'] #columnを取り出す
#value = np.array(value,dtype=np.float) #数値として取り出す時

#headerなし
data = pd.read_csv("filename.csv",delimiter=',',header=None)
col1 = data[1]
col2 = data[2]
#etc

#書き出し
output = pandas_dataframe #書き出したいdataを入れる
output.to_csv("output_filename.csv",header=False)#ある場合はheader=True
```
index.d.tsで起きたPrismaPromiseの「Type error: Type expected.」で、vercelにデプロイできない時に確認すべきこと

先日、`TypeScript+Next.js`のアプリをvercelにデプロイしようとしていたのですが、GitHubリポジトリとvercelを連携して、deployボタンを押したところ以下のエラーが起きて失敗しました。

```console
17:15:42.281  	Failed to compile.
17:15:42.284  	./node_modules/.prisma/client/index.d.ts:10:33
17:15:42.284  	Type error: Type expected.
17:15:42.285  	   8 | export type PrismaPromise<A> = Promise<A> & {[prisma]: true}
17:15:42.285  	   9 | type UnwrapTuple<Tuple extends readonly unknown[]> = {
17:15:42.285  	> 10 |   [K in keyof Tuple]: K extends `${number}` ? Tuple[K] extends PrismaPromise<infer X> ? X : never : never
17:15:42.285  	     |                                 ^
17:15:42.285  	  11 | };
```

どうやら`PrismaPromise`の型定義が間違えているっぽい(?)けど、`index.d.ts`は一回もいじってないし、と思いつつググっていると、以下のgithub issueを発見。

[Bug: Prisma 2.17.0: Type errors in generated client for `UnwrapTuple` #5726](https://github.com/prisma/prisma/issues/5726)


ここに全てが書いてありました。

どうやら、**prismaのバージョンが2.14以降だと、TypeScript 4.1以上が必要**らしいです。

自分の使っていたTypeScriptとprismaのバージョンをみてみると、`prisma`が**2.17.0**、`TypeScript `が**3.9.4**。これが原因っぽいです。

そこで、以下を実行します。

```console
$ npm update -g typescript
```

これで、`TypeScript`のバージョンは**4.2.2**になりました。
これで、エディタをみてみると、型のエラーが消えました！
ROSの勉強　第17弾：キーボード操作（シミュレーション）

# #プログラミング ROS< キーボード操作（シミュレーション） >

## はじめに
1つの参考書に沿って，ROS(Robot Operating System)を難なく扱えるようになることが目的である．その第17弾として，キーボード操作（シミュレーション）を扱う．


## 環境
##### 仮想環境
|||
|:-:|:--|
|ソフト|VMware Workstation 15|
|実装RAM|2 GB|
|OS|Ubuntu 64 ビット|
|isoファイル|ubuntu-mate-20.04.1-desktop-amd64.iso|

##### コンピュータ
|||
|:-:|:--|
|デバイス|MSI|
|プロセッサ|Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 2.50GHz|
|実装RAM|8.00 GB (7.89 GB 使用可能)|
|OS|Windows (Windows 10 Home, バージョン：1909)|

##### ROS
|||
|:-:|:--|
|Distribution|noetic|
|プログラミング言語|Python 3.8.5|
|シミュレーション|gazebo|

## 実装
[前回](https://qiita.com/Yuya-Shimizu/items/6bd15d2a0253e72bbe24)のプログラムをシミュレーションGazeboを起動させた状態で，turtlebotを動かしてみる．

以下にそのときの実行様子を示す．
![ezgif-7-147c8d124f5b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/c4ac82ea-a4f6-606d-69a9-2e6e48daa12b.gif)

確かに，キーボードの入力に対して，プログラムしたとおりに動いていることが分かる．

## 感想
今回は動かすだけであったため，非常に簡単であった．しかしながら，実際にシミュレーション上で動かせたということで，ようやくここまできたかという感じである．基本中の基本ではあるかもしれないが，コントローラを使った操作ということになればこのあたりの知識が大いに役立つことだと思う．次回はrvizの基本的な使い方を学ぶ．いよいよ地図生成の準備といったところである．

## 参考文献
プログラミングROS Pythonによるロボットアプリケーション開発
　　　　　　　　Morgan Quigley, Brian Gerkey, William D.Smart 著
　　　　　　　　　　　　　　　　　　　　　　　河田　卓志　監訳
　　　　　　　　　　  　松田　晃一，福地　正樹，由谷　哲夫　訳
　　　　　　　　　　　　　　　　　　オイラリー・ジャパン　発行
EC2にvalheim鯖建てる作業メモ

## インストール
```zsh
$ sudo dpkg --add-architecture i386; sudo apt update; sudo apt install curl wget file tar bzip2 gzip unzip bsdmainutils python util-linux ca-certificates binutils bc jq tmux netcat lib32gcc1 lib32stdc++6 steamcmd
$ sudo dpkg --add-architecture i386; sudo apt update; sudo apt install libsdl2-2.0-0:i386
$ wget -O linuxgsm.sh https://linuxgsm.sh && chmod +x linuxgsm.sh && bash linuxgsm.sh vhserver
$ ./vhserver install
$ vim lgsm/config-lgsm/vhserver/vhserver.cfg
```

## 設定

```zsh
$ vim lgsm/config-lgsm/vhserver/vhserver.cfg
```

```vhserver.cfg
servername="hoge"
serverpassword="fuga"
gameworld="hogefuga"
```

## 起動、停止
```
$ ./vhserver start
$ ./vhserver stop
```

## 容量足りない時
ストレージの空き容量足りなくてエラー出るのでEBSを8GBから20GBに拡張する

```
$ df -h
$ lsblk
$ sudo growpart /dev/xvda 1
$ sudo resize2fs /dev/xvda1
```
terraformでapply後にtfstate削除してもう一回applyしたらどうなるか試してみた

terraformをapplyした時に作成されるtfstateには、現在の状態が記録されているみたいです。それを削除してapplyしたらどうなるか気になったのでやってみました。

# 前提
* コードは、EC2を作成するだけ
* 一度terraformでapplyした後に、作成されたtfstateを削除、その後再びapplyを実施してみる

# 検証

1度apply実行後に、tfstateを削除せずplanしてみる

```
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_instance.example: Refreshing state... [id=i-034f0504ef1224dd5]

------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
```

もちろん差分無しで表示される

次にtfstateを削除してplanしてみる

```
 terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      + ami                          = "ami-0c3fd0f5d33134a76"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known afte

<省略>

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

```

差分が出てきた
ということは新しく作成されるかな？applyを実施


```
$ terraform apply

<省略>

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.example: Creating...
aws_instance.example: Still creating... [10s elapsed]
aws_instance.example: Creation complete after 13s [id=i-03f96833d40e268eb]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

作成されたっぽい
AWSコンソール画面で確認しても、もう一台EC2が作成されていた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321507/7cd4a275-61d8-b639-c16e-fc56d8987673.png)

上部が1回目に作成したもので、下にあるのが、今回のapply実行時に作成されたもの

# 結論
1度実行した時のtfstateを削除すれば、terraformの管理から外れる。もう一度実行すると、別でEC2を立ち上げる
【Rails】acts_as_listを使った並べ替え機能を同期/非同期それぞれで実装

## 導入
```rb:Gemfile
gem 'acts_as_list'
```
```bash
$ bundle install
```
```rb:app/models/task.rb
class Task < ApplicationRecord
  acts_as_list
end
```
```bash
rails g migration AddPositionToTask position:integer
```
```rb
class AddPositionToTask < ActiveRecord::Migration[6.0]
  def change
    add_column :tasks, :position, :integer #カラム名はpositionじゃなきゃいけない
  end
end
```
```bash
$ rails db:migrate
```
```config/routes.rb
resources :tasks do
  member do
    get :move_higher
    get :move_lower
  end
end
```

## 同期処理で動かす
```rb:app/contollers/tasks_controller.rb
def index
  @tasks = Task.all.order(:position) # positionカラムに従いソート
end

def move_higher
  Task.find(params[:id]).move_higher #move_higherメソッドでpositionを上に
  redirect_to action: :index
end

def move_lower
  Task.find(params[:id]).move_lower #move_lowerメソッドでpositionを下に
  redirect_to action: :index
end
```
```erb:app/views/tasks/index.html.erb
<h2>タスク一覧</h2>
<table>
  <% @tasks.each do |task| %>
    <tr>
      <td><%= task.name %></td>
      <td><%= link_to '詳細', user %></td>
      <td><%= link_to "↑", move_higher_task_path(task) %></td>
      <td><%= link_to "↓", move_lower_task_path(task) %></td>
    </tr>
  <% end %>
</table>
```

## 非同期処理で動かす
```rb:app/contollers/tasks_controller.rb
def index
  @tasks = Task.all.order(:position)
end

def move_higher
  @task = Task.find(params[:id])
  @task.move_higher
  @tasks = Task.all.order(:position)
end

def move_lower
  @task = Task.find(params[:id])
  @task.move_lower
  @tasks = Task.all.order(:position)
end
```
```erb:app/views/tasks/index.html.erb
<div id='task-list'>
  <table>
    <% @tasks.each do |task| %>
      <tr class='body-row'>
        <td><%= task.name %></td>
        <td><%= link_to '詳細', task %></td>
        <td><%= link_to '↑', tasks_path(task), remote: true %></td>
        <td><%= link_to '↓', tasks_path(task), remote: true %></td>
      </tr>
    <% end %>
  </table>
</div>
```
```erb:app/views/_tasks.html.erb
<table>
  <% tasks.each do |task| %>
    <tr class='body-row'>
      <td><%= task.name %></td>
      <td><%= link_to '詳細', task %></td>
      <td><%= link_to '↑', tasks_path(task), remote: true %></td>
      <td><%= link_to '↓', tasks_path(task), remote: true %></td>
    </tr>
  <% end %>
</table>
```
```erb:app/views/move_higher.js.erb
$('#task-list').html("<%= j(render 'tasks/tasks', tasks: @tasks) %>");
```
```erb:app/views/move_lower.js.erb
$('#task-list').html("<%= j(render 'tasks/tasks', tasks: @tasks) %>");
```

## scope
taskテーブルのkindカラムの中で並び替えをしたい場合(kindで絞り込みをした状態でもうまく動くようにしたい場合)、以下のように書く。

```app/models/task.rb
class Task < ApplicationRecord
  acts_as_list scope: [:kind]
end
```

## 注意点
positionカラムのデータがnullだと動かない。
既存のテーブルに後からpositionカラムを追加した際には、なんらかの方法で全てのデータのpositionカラムに数値を入力する必要がある。

## 参考
- [brendon/acts_as_list](https://github.com/brendon/acts_as_list)
- [Ruby on Rails gem acts_as_list を使用した項目の並び替え実装 - てきとうコンプリート](https://teki-com.hateblo.jp/entry/2019/05/07/115758)
- [【Rails5】acts_as_listでデータの並び替え機能を実装 - Railsからはじめるプログラミング日記](https://oe526.hatenablog.com/entry/acts_as_list)
python（pandas）にて省略せずに表示させる対応策メモ【初心者】

Python初心者の私が躓いたポイントを備忘録としてまとめていきます。

Pandasライブラリを使ってcsvを読み込み・表示させる場合がよくありますが、
長すぎると表示が省略されてしまいます。

これだとデータの中身をチェックできないので、省略を解除しすべて表示させることが
重要です。

この方法は以下の通り。


行方向にて省略させずにすべて表示するには以下のコードでOK。



```python:python
pd.set_option("display.max_columns",99999)
```


同様に行方向にて省略させずにすべて表示するには以下のコード。

```python:python
pd.set_option("display.max_rows",99999)
```

この時元のデータよりも上で入力した数の方が
大きくないと解除されなかったので注意が必要


参考サイト

https://life-freedom888.com/pandas-shouryaku-none/
RailsでCustom Validatorの実装例


## 最初に
みなさん、Custom Validator使ってますか？

[rails guide](https://railsguides.jp/active_record_validations.html)の[ここ](https://railsguides.jp/active_record_validations.html#カスタムバリデーションを実行する)にも記載されていますが`ActiveModel::Validator`や`ActiveModel::EachValidator`を使って自作のvalidatorを作成することができます。

異なるmodelで同じようなvalidationを実行する場合は以下のようなメリットがあるので是非使っていきましょう。
・modelのコードを減らせる
・specの行数を減らせる
(Validator Classへspecを書けば良いので同じようなspecを減らせます)

## 実装例
よくあるパターンだと思うのですが異なるmodelでメールアドレスカラムを持っており、同じようなvalidationを実装する場合の実装例を記載します。

- 以下のようなEmailのValidator Classを作成します。


```app/validators/email_validator.rb
# frozen_string_literal: true

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value.match(/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i)
      record.errors.add(attribute, options[:message] || "の形式が不正です")
    end
  end
end
```

- deviseを使っていてdeviseと同じEmailのvalidationを使いたい場合は以下のような書き方もできます。

```ruby
unless value.match(/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i)
↓
unless value.match(Devise.email_regexp)
```

- modelでの使い方は以下になります。

```ruby
class Person < ApplicationRecord
  validates :email, presence: true, email: true
end
```

- エラーメッセージは以下のような感じになると思います。

```
メールアドレスの形式が不正です
```

- エラーメッセージを変えたい場合もあると思います。
- その場合は以下のようにメッセージを個別で設定することができます。

```ruby

class User < ApplicationRecord
	validates :email, allow_nil: true, email: { message: "正しいメールアドレスの形式で入力してください" }
end
```

- 次にspecの書き方のサンプルを記載します。

```ruby
# frozen_string_literal: true

require "rails_helper"

describe EmailValidator do
  let(:model_class) do
    Struct.new(:mail_address) do
      include ActiveModel::Validations

      def self.name
        "DummyModel"
      end

      validates :mail_address, allow_nil: true, email: true
    end
  end

  describe "#validate" do
    subject { model_class.new(email) }

    describe "登録可能な形式" do
      context "nil は登録できる" do
        let(:email) { nil }
        it { is_expected.to be_valid }
      end

      context "「abc@example.com」は登録できる" do
        let(:email) { "abc@example.com" }
        it { is_expected.to be_valid }
      end
    end

    describe "登録不可能な形式" do
      context "「abc」は登録できない" do
        let(:email) { "abc" }
        it { is_expected.not_to be_valid }
      end

      context "「abcd.@example.com」は登録できない" do
        let(:email) { "abcd.@example.com" }
        it { is_expected.not_to be_valid }
      end
    end
  end
end
```

## 最後に

email以外にも画像やURLのvalidationなど使えるところは色々あるのでお試し下さい！
pugの使い方、dotenvの扱い

 今日やること
・pugについての学習
・

#PugでHTMLコーディングを効率化

>pugとは
>>pugとはhtmlを効率的に描くために開発されたテンプレートエンジン。使い方はcssでいうsassみたいなもの。通常は`.pug`のように書くが今回は`.vue`ファイルの中に`lang=pug`を埋め込んでいこうと思う。

###pugの記法

Rubyのようにインデントのみで階層化を行い書いていくのが基本。

```vue:
ul.btns
  li
    a.btn(href="/") ボタン
```

↓

```vue:
<ul class="btns">
    <li>
        <a href="/"></a>
    </li>
</ul>
```
今使っている`FBButton.vue`だと次のようになる

```vue:FBButton
<template>
    <div class="btn">
        <v
    </div>
</template>
```

```vue:FBButton.vue
<template lang="pug">
  .btn
    v-btn.indigo.accent-3.white--text(depressed='depressed' @click='open')
      i.fa.fa-facebook
      | Login with Facebook
</template>
```

#dotenvについて

Vue.jsで環境変数を利用する方法
とりあえず１人情シスでの開発なので.envと.env.localで十分。

`.env`だがこれは開発、テスト、本番環境全てで使う環境設定がある場合に利用する。また、`.env`は優先順位的には下位になるので`.env.development`などモードが指定されてる方が優先順位は強い。
`.local`は各自のローカル環境でだけ使いたい環境変数があった場合にのみ利用することになる。

###補足：環境設定ファイルの書き方

```vue:.env
VUE_APP_HOST=localhost
```
上のように`VUE_APP`をプレフィックス（変数の頭につける）にする必要がある。そうしないと読み込みさせない。

読み込み時では
```process.env.VUE_APP_HOST```
とすることで読み込めるようになる.`process.env`を忘れないようにすること。

今回の場合だと次のようになる。

###環境変数の定義
```vue:.env
VUE_APP_FB_REDIRECT_URL = https://example.herokuapp.com/fb_user_info/
VUE_APP_IG_REDIRECT_URL = https://example.herokuapp.com/insta/
```

```vue:.env.local
VUE_APP_FB_REDIRECT_URL = https://localhost:8080/fb_user_info/
VUE_APP_IG_REDIRECT_URL = https://localhost:8080/insta/
```
これで環境変数を定義することができた。

次に読み込み時に使うコードを書いていく。

```vue:FBButton.vue
export default {
    name: 'FBButton',
    methods: {
        open() {
            document.location.href = `https://www.facebook.com/v9.0/dialog/oauth?client_id={app_id}redirect_uri=${process.env.VUE_APP_FB_REDIRECT_URL}`
    //${``}：このような形にする。
        }
   }
}
</script>
```

#今日の課題

・vue.js上で投稿を表示する。（写真やテキストなど）
・ログアウトボタンを作る。（ヒント：localStorage上の情報を消してaxiosの情報も空にする）
・ナビゲーションバーを作る
Ubuntu 20.10 に TigerVNC をインストールする

こちらと同じことを、Ubuntu 20.10 で行いました。
[Ubuntu 20.04にVNCサーバーをインストールする方法](https://tutorialcrawler.com/ubuntu-debian/ubuntu-20-04%E3%81%ABvnc%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)

デスクトップ環境のインストール

```bash
sudo apt install tasksel -y
```

tasksel で、ubuntu desktop をインストール

```bash
tasksel
```

システムブートをグラフィカルターゲットに設定

```bash
sudo systemctl set-default graphical.target
```

再起動

```bash
sudo shutdown -r now
```

TigerVNCサーバーをインストールする

```bash
sudo apt install tigervnc-standalone-server -y
```

VNCパスワードを設定

```bash
vncpasswd
```

VNCサーバーを起動

```bash
vncserver -localhost no
```

起動した時の様子

```text
$ vncserver -localhost no

New 'violet:1 (uchida)' desktop at :1 on machine violet

Starting applications specified in /etc/X11/Xvnc-session
Log file is /home/uchida/.vnc/violet:1.log

Use xtigervncviewer -SecurityTypes VncAuth,TLSVnc -passwd /home/uchida/.vnc/passwd violet:1 to connect to the VNC server.
```

起動していることの確認

```text
$ vncserver -list

TigerVNC server sessions:

X DISPLAY #	RFB PORT #	PROCESS ID
:1		5901		3510
```

他の Ubuntu 端末でクライアントのインストール方法

ダウンロード

```bash
wget https://www.realvnc.com/download/file/viewer.files/VNC-Viewer-6.22.515-Linux-x64.deb
```

インストール

```bash
sudo dpkg -i VNC-Viewer-6.22.515-Linux-x64.deb
```

起動

```bash
vncviewer
```

パスワードの入力
![authenticate_mar01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/bf10fb7a-7ea5-3b7a-4e2a-396985622ed5.png)
enumの使い方について簡単にまとめる


スキル不足だった僕はそれぞれの場所で宣言すればいいじゃんなんて思っていたわけなのだが、企業とかで使われるアプリを案件を通して行ったときにいろんな場所で宣言しまくるのはあまりよくないななんて思った。

確かに楽なんだけど、あれ、、、、○○○○って何番だっけみたいな感じであまり使わないやつとかだとマジでわからなくなる

そんな時にenumの使い方と実際の使われ方を見てこっちの方が間違いなく便利なんて思ったので自分が見返せるようにするためにも残しておく

例えばenumの使い方はこんな感じ

商品の状態を数字で管理している場合

0が販売

1が在庫

2がなんちゃらみたいな

そんな感じの場合

enum 商品: Int {
    case 販売           = 0
    case 在庫           = 1
    case なんちゃら      = 2
}

こんな感じで配置しておけば関数とか作成した場合でも販売を呼び出したり在庫を呼び出したりすればいいだけなので、ある程度スキルが身に付けばこっちの方が楽だななんて思えるようになる

これからプログラミングを始めるとかそういう方は「なんだこれ、、、」みたいな感じになるだろうけど、理解して実際に現場で経験すればこっちの方が楽かもみたいになると思います。

enumの使い方は未経験とか個人で小さくアプリを作成している方からするとあまり使う機会は多くないかもですが、割と便利なので頑張って覚えてください。

当時の僕に向けたメッセージでした。
[Azure] Azure Logic Apps で Azure Functions を繰り返し実行する

## はじめに
Azure Functions の従量課金プランでは最大で 10 分のタイムアウト制限があり、実行に長時間かかる関数はそのままでは実行できません。
もし、ループ処理によって実行に時間がかかる場合は、そのループを Azure Logic Apps に任せることで 1 実行あたりの実行時間を抑えることができるかもしれません。
今回は、Azure Logic Apps を利用して、Azure Functions を繰り返し実行するロジックを実装してみます。

## 関数の作成
Azure Functions で `Double` という http トリガー関数を作成しました。
実行コードは以下の通り。
リクエストボディから渡された `parameter` を 2 倍して返す単純な関数です。

~~~js:Double/index.js
module.exports = async function (context, req) {

    let param = parseInt(req.body.parameter);
    const result = param * 2;

    context.res = {
        body: result
    };
}
~~~

##ロジックアプリの作成
### 空のロジックアプリの作成
続いて、ロジックアプリを作成しテンプレートから `空のロジック アプリ` を選択します。
初めてロジックアプリを作成する方は、以下の公式ドキュメント クイックスタートをご参照ください。
https://docs.microsoft.com/ja-jp/azure/logic-apps/quickstart-create-first-logic-app-workflow#create-your-logic-app

### トリガーの作成
ロジックアプリの中身を作成していきます。
トリガーは `HTTP 要求の受信時` にしておきます。
![2021-02-27_13h34_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/19f8103b-f2dc-dc5a-d055-8a2a5f187ac5.png)
### 変数の作成
次のステップは `変数を初期化する` です。
今回は、繰り返し 2 倍する `parameter` 変数を作成し、初期値を 1 に設定します。
![2021-02-26_18h45_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/28545bcd-bf17-279e-49da-f015ec07892b.png)
![2021-02-26_18h46_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/021e02ee-951d-7097-6d0e-aa1acdf46b60.png)

### 繰り返し処理の作成
繰り返し処理を作成します。`制御` の `まで` を選択します。
![2021-02-26_18h46_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/3d2ae119-757e-9690-5f6a-068c60cf522e.png)
今回は `parameter` が 1000 以上になるまで値を 2 倍し続けたいと思います。
繰り返しの制限 (回数上限、タイムアウト) も別途設定することができます。
![2021-02-26_18h47_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/1fbaeb72-cb0e-c189-35b7-6f77f1bc1f3c.png)
アクションは先ほど作成した Azure Functions 関数 `Double` を設定し、要求本文 (ボディ) に JSON 形式で `parameter` を設定します。
![2021-02-26_18h48_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/4352e84c-39eb-6492-ed03-9bde71388190.png)
最後にレスポンスとして返ってきた値を `parameter` に設定します。
返り値を `Int()` を使って整数値に parse して　`parameter` 変数に設定するようにします。
![2021-02-26_18h50_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/8e0650dd-9a70-4bce-76c0-0e4b525dc139.png)
以上でロジックアプリの作成は完了です。ロジックアプリを保存します。

## ロジックアプリを実行してみる
画面上部の `実行` を押して、結果を確認してみます。
すると、繰り返し処理が 10 回転して、`parameter` の値が 1024 になるまで関数が実行されていることが確認できました！
![2021-02-26_18h51_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423135/9c39312e-79ed-4302-8f49-ebf83985b8ab.png)


## さいごに
Azure Logic Apps を利用して、Azure Functions を繰り返し実行するロジックを実装してみました。
関数の実行時間が長くタイムアウト制限に引っかかる場合、解消法の一つとして検討してみてはいかがでしょうか。

## 参考文献
- Azure Functions のホスティング オプション - サービスの制限：https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-scale#service-limits
- クイックスタート: 初めての Logic Apps ワークフローを作成する - Azure portal：https://docs.microsoft.com/ja-jp/azure/logic-apps/quickstart-create-first-logic-app-workflow#create-your-logic-app
GitHub ブランチ関連のコマンド

#概要
先日、GitHubを使用して、アプリケーション開発を行ったところ、様々なコマンドを実行しました。
その中でも、今回は、実際に使用したブランチ関連のコマンドを紹介したいと思います。

##目次
- 事前知識
- ブランチの一覧を表示する
- 新しくブランチを作成する
- 作業ブランチの移動
- 新しくブランチを作成して、そのブランチに移動する
- ブランチ名を変更する
- ブランチを削除する
- 最後に...

##事前知識
>ブランチとは、作業履歴を分岐して、記録していく為のものです。
分岐したブランチは他のブランチの影響を受けないため、同じリポジトリ中で複数の変更を同時に進めていくことができます。
また、分岐したブランチは他のブランチと統合(マージ)することで、一つのブランチにまとめ直すことが出来ます。

##ブランチの一覧を表示する
下記のコマンド実行する事により、ローカルブランチの一覧が表示されます。

```
$ git branch
```

>補足
・ブランチ名の頭に「＊」がついているブランチ名が、現在自身がいるブランチ。
・リモートブランチの一覧を表示する : $ git branch -r
・リモートブランチを含んだ、ブランチの一覧を表示する : $ git branch -a

##新しくブランチを作成する
下記のコマンド実行する事により、新しくブランチを作成する事が出来ます。

```
$ git branch 作成するブランチ名
```

##作業ブランチの移動
下記のコマンド実行する事により、作業ブランチを移動する事が出来ます。

```
$ git checkout 移動したい先のブランチ名
```

##新しくブランチを作成して、そのブランチに移動する
下記のコマンド実行する事により、新しくブランチを作成して、移動する事が出来ます。

```
$ git checkout -b 作成するブランチ名
```

##ブランチ名を変更する
下記のコマンド実行する事により、ブランチ名の変更を行う事が出来ます。

```
$ git branch -m 古いブランチ名 新しいブランチ名
```

>補足
・現在いるブランチのブランチ名を変更する : $ git branch -m 新しいブランチ名 

##ブランチを削除する
下記のコマンド実行する事により、マージの状態に関わらず、指定したブランチを削除する事が出来ます。

```
$ git branch -D ブランチ名
```


###最後に...
今回は、実際に使用したブランチ関連のコマンドを紹介しました。

最後まで、読んでいただきありがとうございました。
[JavaScript]クリックした要素の取得

クリックした要素を取得したくて、格闘したので、備忘録。
調べたら案外簡単に出てきました。

###構文
```
event.target.innerHTML
```

```event.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="event.js"></script>
    <title>Document</title>
</head>
<body>
    <p onclick="getText()">イベント１</p>
    <p onclick="getText()">イベント２</p>
    <p onclick="getText()">イベント３</p>
</body>
</html>
```
```event.js
function getText() {
    var eventText = event.target.innerHTML;
    alert(eventText);
}
```

これで問題なく動くのですが、エディタの方では、~~event~~の表記がなされ、「eventは非推奨です」と出ちゃいます。動くのでよしとしてますが、なんか気持ち悪い、、

あと、タグすべてにonclickイベント書かないといけないのもめんどくさい。
なんとかならないですかね、、
LED点滅

### 概要

LEDの点灯と似ているが，ここではLEDの点滅をやってみる．一般的なArduinoIDEを用いた開発では，LED点灯と同様にHello World的な扱いとなるが，一定時間待って点灯と消灯を繰り返す点滅は，ちょっとめんどくさい．点滅ができると，シリアルによるデータ送信以外でデバッグがしやすくなる(あるパスを通ったら点灯/消灯とか．シリアル通信自身のデバッグとかに使える)．少しハマったので，まとめておく．なお，この記事は[LED点灯](https://qiita.com/hiro4669/items/56099dd9adfd9e7b5a39)の知識を前提としている

### LEDを消す
LEDを消すために，以下のように`turnoff`をアセンブリ言語で追加する．
なお，`turnon`は点灯する関数

```nasm:led.s
        .globl turnon
        .type  turnon, @function
turnon:
        push r16
        ldi r16, 0b00100000
        out 0x5, r16
        pop r16
        ret

        .globl turnoff
        .type  turnoff, @function
turnoff:
        push r16
        ldi r16, 0b00000000
        out 0x5, r16
        pop r16
        ret
```

そして，これらの関数を`main`から呼び出せば良い

```c:main.c
void setout();
void turnon();
void turnoff();

int flg = 1;

/* 遅延するための関数 */
int wait(int seed) { 
    int i;
    for (i = seed; i < seed+32000; ++i) {
    }
    return i;
}


int main(void) {
        setout();
        turnoff();
        int flg = 1;
        int v = 1;
        while(1) {
            if (flg == 0) {
                turnon();
                flg = 1;
            } else if (flg == 1) {
                turnoff();
                flg = 0;
            }
            wait(v);
            wait(v);
            wait(v);
            v++;
        }
        return 0;
}
```
やることは実に単純だが，点滅が早すぎると人間が目視で確認できない．ArduinoIDEを使うと，`delay(millisec)`を使うことで遅延させることができるが，そんな関数は今無いので無理やり時間がかかる処理を追加して(`wait`)代用する.
`wait`で

```c:wait
for (i = seed; i < seed+32000; ++i) {
```
としているのは，ArduinoUnoは16ビットなため，intの大きさも2バイトで，32767以上の生の数を表せないため．仕方ないので，この関数を3回呼び出して適当に遅延させている．

さらに，この`wait`自身は何も影響を与えないため，最適化オプションを使って(`-Ox`)コンパイルすると，このループが削除されるか，`wait`の呼び出しが削除されて遅延しない(気づくまでに時間がかかった)ので注意すること．
このコードで，1秒間に3回くらいの点滅を目視で確認できる．


LED点滅プログラムは以下のコマンドで実行することができる

```
>git clone https://github.com/hiro4669/iosv.git
>cd iosv/led_onoff
>make
>make write
```
OSI基本参照モデル覚え方

# この記事について

- 個人メモなのであまり気にしないでください。いいと思ったらどんどんパクってください。

# 語呂合わせ

- 「アプリのプライドを窃盗、ネズミデート人物」

# 簡単な解説と経緯

1. 「アプリケーション層」「プレゼンテーション層」「セッション層」「ネットワーク層」「データリンク層」「物理層」の順番が覚えられない。変な語呂合わせで覚えてみることにした。
1. 「アプリのプライドを窃盗」の「アプリ」はアプリケーション層を指している。
1. 「アプリのプライドを窃盗」の「プライド」の「プ」はプレゼンテーション層を指している。
1. 「アプリのプライドを窃盗」の「窃盗」の「せ」はセッション層を指している。
1. 「ネズミデート人物」の「ネズミ」の「ネ」はネットワーク層を指している。
1. 「ネズミデート人物」の「デート」の「デ」はデータリンク層を指している。
1. 「ネズミデート人物」の「人物」の「物」は物理層を指している。
direnvを使っている時にcreate-react-appの環境変数がうまく出力されない

## 症状

`create-react-app`で作成したプロジェクト + `direnv`を使っている時に、

`.env` に下のように環境変数を書いても、undfinedしか返ってこず、困った。

```
export REACT_APP_API_URL='xxxxxxxx'
```

## 解決
ファイル名を、`.env`から`.envrc`に修正すると正しく動作した。

知ってると当たり前かもしれないが、意外と詰まった。


## その他
一般的な原因の場合は [create-react-appのプロジェクトで環境変数を.envから読み込めない原因と解決策](https://qiita.com/wakeupsloth/items/ec19b9fbfddfb1cd58bb)が参考になりそう。