OmniAICreator/Qiita-1.07M huggingface dataset:
validationのカスタマイズ

# 概要
個人アプリを作成していく中で、グループ登録が突如できなくなった事象が発生しました:scream:

原因は、usersモデルに追加したバリデーションでした:persevere:
（原因探るために、また一からアプリ作成し述べ4日間も費やしました。。。。）

備忘録として残します！

# エラー状況
### グループ登録画面
<img width="1394" alt="スクリーンショット 2020-06-08 17.43.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634091/4566f1d0-ecf1-54fe-35c5-14879e6bbec1.png">
今までできていたグループ登録ができなくなる事象が発生:zap:

### ログ
<img width="1440" alt="スクリーンショット 2020-06-08 17.44.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634091/7227f624-d05a-aa25-5525-5174f374156f.png">

ログを見ると、paramsはきちんとデータ取得されているのに、ROLLBACKされています:rolling_eyes:
エラーの内容は**invalid**。

### 原因
悪さしているコードは、usersモデルに追記したバリデーションでした:angry:

```Ruby:app/models/user.rb
  validates :password, presence: true, length: {minimum: 8 }
```
パスワード7文字以下はエラーにする記述です。

恐らく、userモデルに追加したバリデーションによって、group登録時にpasswordデータも取得させる必要性が出てきた？？のかな？？
もし、わかる方がいれば教えてください:bow_tone1:

# 解決方法
usersモデルに追加したバリデーションにオプションをつけて解決しました！

```Ruby:app/models/user.rb
  validates :password, presence: true, length: {minimum: 8 },on: :create
```
user登録時のみにバリデーションが使用される！という意味合いです。

# 感想
まず、急に登録できなくなり、原因もわからない状況で、一からアプリを作成し直し原因を突き止めた事象です。。。
本当に辛かった:sob:
たった11文字のコードを追加するだけで解決しましたが、ある意味得たものは大きかったと考えています:laughing:

# 参考
●passwordバリデーションの解決の糸口がわかりました。
https://qiita.com/noriya1217/items/f0e887f3a7b2c7f83722

●バリデーションのオプションについて参考にしました。
https://qiita.com/Shantti-Y/items/19ea23b81f3421063fc5
Jenkinsジョブで "git clone <url>" した後と同じ状態にするには

- ソースコード管理
    - Git
        - リポジトリ
            - リポジトリURL : https://~~.git
            - 認証情報 : free
            - 名称 : null
            - Refspec : null
        - ビルドするブランチ
            - ブランチ指定子 (空欄はすべてを指定) : refs/heads/master
        - リポジトリ・ブラウザ : (自動)
- ビルド開始前にワークスペースを削除する : on
- ビルド
    - シェルの実行
        - シェルスクリプト :

```
git checkout master
git remote set-head origin master
```

---

### 追記

シェルスクリプトの内容と、`Check out to specific local branch` がイコールであることを後で知りました

- ソースコード管理
    - Git
        - 追加処理 : Check out to specific local branch
            - ブランチ名 : **

<details><summary>Check out to specific local branch のヒント</summary><div>

```
リビジョンをチェックアウトして、このブランチのヘッドとしてビルドします。
空文字や"**"を設定すると、ブランチ名はoriginを含まないリモートのブランチから算出します。その場合、 リモートブランチorigin/masterは、ローカルブランチmasterにチェックアウトされ、 リモートブランチorigin/develop/new-featureは、 ローカルブランチdevelop/new-featureにチェックアウトされます。

サブモジュールではテストされていないことに注意してください。
```
</div></details>
Akashic EngineゲームをTypeScriptで書くための改造版ボイラープレート作りました

初めまして。初投稿です。

突然ですがドワンゴが作っているTypeScript製ゲームエンジンのAkashic EngineをTypeScriptで書く為のボイラープレートを作りました。

リポジトリはこちらです。
https://github.com/KoutaKawase/akashic_boiler

git cloneするだけで簡単に使えるので良かったら使ってみてください。＼(^o^)／

# どういうものか
公式ボイラープレートを元に色々弄ったボイラープレートです。
もともとこのエンジンでゲームを作るためのプロジェクト作成は公式が用意してくれています。
```
akashic init -t typescript-shin-ichiba-ranking
```
というコマンドを入力するだけでニコ生で動くゲームをTypeScriptで書くためのファイル群が自動生成されます。

じゃあ何でこんなボイラープレートを作ったかというと、依存ライブラリが少し古いためです。

公式ボイラープレートはリンターにTSLintが採用されていますが、TSLintはTSLint公式がdeprecatedを勧告しています。あとTypeScriptのバージョンが2.9と少しだけ古いです。

あと個人的にjestをTypeScriptで使いたいのでts-jestを入れたかったのもあります。

TypeScriptを3.9に上げ、TSLintの代わりにESLintを採用し、prettierでフォーマットできるようにしてlint-stagedでgit commit時に自動でリンターが走る仕様になってます。

大した事してないですがよかったら使ってくれると嬉しいです！
OSI参照モデル

# OSI参照モデル



# 層 (Layer)

L7	アプリケーション層

​　**アプリケーションごとの固有の規定**

L6　プレゼンテーション層

　**文字コードなどのデータの表現形式**

L5　セッション層

　**通信プログラム間の通信の確立、維持、終了**

L4　トランスポート層

　**データ転送の信頼性**

L3 　ネットワーク層

　**異なるネットワーク間の通信**

L2 　データリンク層

　**同じネットワークの中でどのように通信するか？**

L1 　物理層

　**ビット列と電気信号を変換するための規定**



# 概要

## 用語

- パケット

  **ネットワークを流れるひとかたまりのデータ**のこと。パケットはヘッダとデータ（ペイロード）に分かれる。

- ヘッダ

  データや文書の本体の先頭に付け加えられる、**そのデータについての情報を記述した部分**のこと。

- パケットヘッダ

  パケットヘッダとは、ネットワークを流れる一塊のデータの先頭に付け加える、**そのデータについての情報を記述した部分**のこと。



## OSI参照モデルとTCP/IPモデルの関係

## TCP/IPモデル

L4　アプリケーション層

　OSI参照モデルのL7,L6,L5に対応

L3 　トランスポート層

　OSI参照モデルのL4に対応

L2 　インターネット層

　OSI参照モデルのL3に対応

L1 　ネットワーク・インターフェース層

　OSI参照モデルのL2,L1に対応



### 共通点

**異機種間の通信**を目的としています。

OSI参照モデルの策定される以前では、コンピュータネットワークは、単一のベンダー（メーカー）の

製品だけで構成されており、異なるベンダーのコンピュータ同士の通信を行うことは難しい状況でした。

ネットワークが普及するにつれ、特定のベンダーに依存することなく異なるベンダーの機器との接続

の要望が増えたため、異機種間の通信を実現するための設計方針（OSI）が1984年に策定されました。



### 団体

OSI参照モデル : 国際標準化機構 (**ISO**)

TCP/IPモデル : 米国国防高等研究計画局 (**DARPA**)



### 立ち位置

TCP/IPモデルが、私たちが使っている「事実上の」標準である。

OSI参照モデルは国際標準化機構（ISO）が作った「名目上の」標準である。



# L1　物理層

**ビット列と電気信号を変換するための規定**



L1 (物理的接続) は電気信号をビット列に変換する

L1以外 (論理的接続) は、ビット列のまま扱う規定



# L2　データリンク層

**同じネットワークの中でどのように通信するか？**



## Mac アドレス

**上位24ビットをベンダー識別子という。**IEEEが製品ベンダーに重複しないように割り当てられる。Macアドレスの**下位24ビットをベンダー内識別子という。**ベンダーが独自に割り当てる。



## ネットワーク機器

- リピータハブ (L1)

  繋がっている端末すべてに対して、データを送信する。Macアドレスを使う必要がなく、電気信号を扱うので第一層の処理になる。

- スイッチングハブ (L2)

  繋がる複数の端末内の必要としているものだけにデータを渡す。**該当の端末はMacアドレスで識別する。**OSI参照モデルの第二層の処理である。

- ルーター (L3)

  異なるネットワーク間を中継する。よって、第三層の処理である。

  

## 用語

- コリジョン

  有線ならデータが同じ線の中でぶつかって壊れること。無線ならアクセスポイントで波が重なってしまうこと。

- ALOHA

  **無線通信用の通信プロトコルである。**ノードでの検出なしで、パケット通信が可能になったときにすぐにパケットを送信する。パケット通信が可能になったら、通信相手の状況を考慮せずに通信するので、コリジョンが起きやすい。

- CSMA

  データリンク層の通信プロトコルである。**ALOHAと異なり、コリジョンを回避できる。**CSMA/CDは送信中に衝突を検出し、もし検出したら即座に通信を中止する。ランダムな待ち時間を挿入するCSMA/CAは送信の前に待ち時間を毎回挿入する。

- SSID

  **アクセスポイントの識別子である。**混線防止のために名付けている。無線LANの親器になれるものにつく。無線LANで使用されている帯域は、2.4GHz帯(多くの機器が対応)と5GHz帯がある。



# L3　ネットワーク層

**異なるネットワーク間の通信**



## IPアドレス

**ネットワーク部**は、各ホストが所属するネットワークを示す。

**ホスト部**はネットワークに所属する各ホストを表す。

**プレフィックス長**とは先頭何ビットまでがネットワーク部かを示すものである。



## ルーティングテーブル

**ルーティングテーブルとは、事前に登録されたルートのネットワーク情報のデータベースのことである。**基本的なルーティングテーブルの構成は、宛先ルート、パケット転送先、出力インターフェースである。**ダイナミックルーティング**はそれぞれのルータが作ったルーティングテーブルを交換し合って、更新していく。**スタティックルーティング**は、手動でルーティングテーブルを決定する。



## DNS

DNSサーバは、ドメイン名とIPアドレスの対応付けを行うための仕組みを提供するサーバである。



## ARP

**ARPはIPアドレスとMACアドレスを対応付けること。**

ブロードキャストで**ARPリクエスト**を送る。

**ARPリプライ**はユニキャストでMACアドレスを送り返す。



# L4　トランスポート層

**データ転送の信頼性**



## TCP/UDP

**TCP**は高速性よりも正確性を重視するサービスに利用される。

**UDP**は、リアルタイム性を重視するサービスに利用される。

**3ウェイハンドシェイク**とは、TCPにおいて使用される接続を確立する方法である。

**TCPコネクション**は、ハーフクローズという方法で終了される。片方ずつコネクションを切断する。コネクションを切断したい方がFIN bitをセットする。

**輻輳制御**は、adv window sizeとcongestion window sizeの小さいほうに合わせることを指す。



## セグメンテーション

アプリケーション内で使われるデータの単位はファイルである。

その大きさは、MBからGB程度である。

**TCPセグメントの大きさは1500B程度である。**

**データを1500Bずつの単位に区切って送信すること**をセグメンテーションという。



## ポート番号

**ポート番号とは、TCP/UDP通信において、コンピュータが通信に使用するプログラムを識別するための番号である。**

インターネットに接続されているコンピュータでは、数多くの通信プログラムが動いており、データがどのサービスに向けたものかを明らかにする必要がある。

宛先ポート番号は、アプリケーションプロトコルごとに決まっている。送信元ポート番号はOSが空いている番号を適当に割り振る。
AndroidStudio(kotlin)ボタン押下でテキストビューの書体フォントを変更する。

# やりたいこと

 * フォントファイルをアプリのアセットに取り込む。
 * ボタンを押下すると、テキストビューの書体が変わる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/4db6d3e6-a72a-c77b-4fc5-4e15f154de45.png)

# フォントファイルの取り込み

## フォントファイルの入手方法（自分のPCから）

Windows10の場合、

```
コントロールパネル ＞ デスクトップのカスタマイズ ＞ フォント
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/60c98d8e-b3b7-5ffe-9922-6400622bb4f4.png)


でフォントファイルが表示されるので、
任意のファイルをコピペしてアプリのアセットに保存する。

## アセットフォルダの作成方法

AndroidStudioにて

```
File > New > Folder > Asset Folder
```

を実行する。
すると、app配下に `assets` フォルダが作成される。
このフォルダにフォントファイルをコピペする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/4509161a-f88f-c44f-945c-798e844d1422.png)



# 実装


## 画面側

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/1982e7dd-45c3-aade-4ce2-7519179d8e7e.png)


```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="あいうえお"
        android:textSize="36sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

## メイン処理

assetsフォルダ内に hoge.ttc がある場合、下記のように指定できる。

```kotlin
package com.example.yamato200608a

import android.graphics.Typeface
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btn.setOnClickListener {
            val typeface = Typeface.createFromAsset(assets, "hoge.ttc")
            textView.typeface = typeface
        }
    }
}
```
Git基礎的コマンドメモ


##init
gitの環境作り

```
git init
```

##status
状況の確認

```
git status
```

## log
ログの確認

```
git log
```

##add
インデックスに登録

```
git add static/style.css  #ファイル指定
git add .   #全てのファイル
```

##reset
取り消し

```
git reset HEAD   #addの取り消し
git reset HEAD index.html　 #ファイル指定
```

##commit
コミット

```
git commit -m "Message"
```

##checkout

```
git checkout HEAD^   #一個前に戻る
git checkout "HEAD^"  #windowsはダブルクォーテーションで囲む
git checkout -b ブランチ名　 #ブランチを作成及び切り替え
git checkout ブランチ名  #ブランチの切り替え
git checkout -f　ブランチ名　#強制的にブランチを切り替える（保存していなくても）
```

##branch

```terminal
git branch　 #ブランチを確認
git branch -d ブランチ名　#ブランチの削除
```

##remote

```
git remote add origin URL #リモートリポジトリと紐づけ
git remote　#リモートリポジトリの確認
git remote -v #リモートリポジトリのURL確認
git remote set-url origin http://zzzzz/wwww.git #URL変更
```

##push

```
git push origin ブランチ名　　#リモートリポジトリにプッシュする
```

##pull

```
git pull origin ブランチ名　 #リモートリポジトリをローカルに反映
```

##clone

```
git clone "リポジトリURL"
git clone -b <指定したいブランチ名name> "リポジトリURL" #ブランチを指定してcloneする
```

## revert 
特定のcommitを打ち消す

```
git revert <commit>
```

## ユーザー名とemailの設定

###現在のユーザー名とemailを確認する

```
git config --global user.name
git config --global user.email
git config --local user.name
git config --local user.email
```
### ユーザー名とemailを変更する

```
git config --global user.name "ユーザー名"
git config --global user.email メールアドレス
git config --local user.name "ユーザー名"
git config --local user.email　メールアドレス
```
受験者のスキルセット・バックボーンと受験動機

色々とG検定関連のブログを見ると、簡単・難しい等意見が別れていると思います。
各自のスキルセット・バックボーンがそれぞれ異なるので、意見が分かれるのは当然かと思います。

私自身のスキルセットと受験動機を簡単に記載します。

# スキルセット

* 2000年前後に、MARCH相当の文系学部を卒業。中堅SIerに就職、その後同じ業界の中で転職を2回
* VB6.0 + Oracle8のクライアント・サーバシステム開発が最初、その後も基本的にはクラサバシステムの開発に従事。
歳を重ねる毎に主な業務がコーディング→設計→管理・手配に遷移。いわゆるWeb界隈の人ではありません。
* 業務ではほぼ利用はありませんが、AWSはSA ProやDveOps Pro、GCPのAssociate Cloud Engineer、SFDC関連も保持。ただし、明らかにペーパードライバー。IPAも高度（DBとセキスペ）を保持。資格試験勉強は嫌いではない。
* AIは一切知識なし。数学も不得手。高校時代、私立文系コースに在籍していたため、微積はやっていない。Pythonも業務では利用経験なし。入門書やWebサイトをななめ読みしたことが程度。でも、PyconJPには参加したことあります。
* エンタープライズ領域の昔ながらのシステム開発に従事しているが、Web界隈・クラウド界隈に憧れを持っている。ただ、そちらの世界に飛び込むには、スキル・年齢等の面から躊躇。

# 受験動機

* 2020#2の受験料が半額のため。←きっかけはかなりこれです。
* クラウドについては、広く浅くではあるがある程度触りは覚えた。次はAIだろう、という考え。
* 諸般の事情から、しばらくの間、勉強する時間を取ることが可能になった。
Unity-DOTSで作る2D弾幕シューティングの例 - ②ステージキューの管理について

[Unity-DOTSで作る2D弾幕シューティングの例](https://qiita.com/inukai_anubis/items/21e96a59941adab96670)の二回目です。

# ステージキューの管理について

まだDotsと関係ないところの話です。
ここで作っているのはシューティングゲームなので、ステージは時間と共にスクロールしていき、
一定の地点に来ると敵が出てきたり背景が変わったりするわけですが、
それを表現するデータ構造としてどういう方法がいいのかいろいろ検討した結果、
結局全部同じ構造のデータとしてまとめればいいんじゃねということになり、下記のような形になりました。

<img width="568" alt="スクリーンショット 2020-06-08 14.22.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651558/b3f9a687-1aaa-50ad-5913-be3c4e572b1a.png">

これをステージキューと呼んでいます。
ここで言う`type`というカラムが、それがどういう種類のイベントなのかを指定しているものです。
`path`で何か使いたい文字列のパラメータを、`param1〜5`で何か使いたい数値のパラメータを設定しておきます。
例えば`type`が`Spawn`の場合、敵の出現を表すイベントになります。

このゲームでは、基本的にフレームが進行するごとにカウンタを加算していき、
カウンタの値が`queue_id`の値と一致したら、そのイベントを実行するというような形式でステージを進行させていきます。
`Spawn`を例にとると、イベントが実行される際に、`param1〜5`の値を下記のような形でマッピングしなおした敵スポーンを表現する構造体に変換して利用します。

```cs
public struct QSpawn {
    public int entryId;
    public int enemyId;
    public int verseId;
    public int x;
    public int y;
}
```

敵スポーンの場合、DB上でparam4に出現時X座標を、param5にY座標を書いておき、それがQSpawnのxとyに割り当てられるようにしています。
敵スポーンに関しては今のところ文字列パラメータは必要なく、
極力可変長データは持たせないようにしたいため、`path`のデータは捨てます。

Q：無駄なデータ領域が多すぎでは？
A：はい

でもどうやったって最終的には複雑になるんだからこの程度の取り決めだけしておけばよくない？ということになり、現在の形になりました。

現在のところステージキューのイベントには下記のような種類があります。

* タイルマップ背景の切り替え
* パーティクル背景の切り替え
* 敵のスポーン
* 敵の武装契機（攻撃情報の設定）
* 敵の移動契機（直線移動、円形移動、バネ等の挙動タイプごとに移動）
* BGMの切り替え
* バース（独自機能）の切り替え、名前の設定

シューティングゲームの作成にあたってはけっこう当たり前に使われているやり方なのかもしれませんが、
いざ自分で作ろうと思って検索してみても意外と情報が見つからなかったので、一例として記載しておきます。
デバッグ用Gemのインストールが失敗する時の対応

Macbook Pro 13インチ（2020年モデル）にruby環境を構築していた時に、デバッグ用Gemのインストールにつまずきました。

#今回実行した環境

Catalina 10.15.4

デバッグ用Gem導入
-
デバッグ用のgemをbundler経由で導入します。

```ruby:
$ gem install bundler
$ bundle init
$ gem install debase
$ gem install ruby-debug-ide
```

エラーを吐きます。

```ruby:
uilding native extensions. This could take a while...
ERROR:  Error installing debase:
        ERROR: Failed to build gem native extension.

    current directory: /Library/Ruby/Gems/2.6.0/gems/debase-0.2.4.1/ext
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby -I /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0 -r ./siteconf20200608-81290-fde397.rb extconf.rb
checking for vm_core.h... no
checking for vm_core.h... no
**************************************************************************
No source for ruby-2.6.3-p62 (revision 67580) provided with
debase-ruby_core_source gem. Falling back to ruby-2.6.0-p0.
**************************************************************************
checking for vm_core.h... yes
checking for iseq.h... no
Makefile creation failed
*************************************************************

  NOTE: If your headers were not found, try passing
        --with-ruby-include=PATH_TO_HEADERS      

*************************************************************

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/$(RUBY_BASE_NAME)
        --with-ruby-dir
        --without-ruby-dir
        --with-ruby-include
        --without-ruby-include=${ruby-dir}/include
        --with-ruby-lib
        --without-ruby-lib=${ruby-dir}/lib

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-19/2.6.0/debase-0.2.4.1/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Library/Ruby/Gems/2.6.0/gems/debase-0.2.4.1 for inspection.
Results logged to /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-19/2.6.0/debase-0.2.4.1/gem_make.out
```

調べてみると、debase-ruby_core_sourceとrubyのバージョン2.6.3が不整合のようです。
そのため、rubyのバージョンを変更しました。

```ruby:
$ brew update
$ brew install rbenv
$ rbenv --version
  rbenv 1.1.2
$ rbenv install 2.6.6
$ rbenv global 2.6.6
```

無事、デバッグ用Gemをインストールできるようになりました。
【Thymeleaf】Session中のキーの存在有無で表示非表示の制御

# ×公式リファレンス通りだと制御できないので注意
`session.containsKey`では一律trueが返却されてしまうので、
下記のようなコードでは、セッション中のキー`foo`の有無に関わらず常にhogeが表示されてしまう。

```html
<span th:if="${session.containsKey('foo')}">hoge</span>
```

# ◎Session中のキーの存在有無で表示非表示の制御方法
下記のように`session.keySet().contains`を利用する。

```html
<span th:if="${session.keySet().contains('foo')}">hoge</span>
```

上記のコードのようにすることで、セッション中に`foo`というキーが存在する場合のみtrueが返却される。
よって、セッション中に`foo`というキーが存在する場合のみhogeと表示することができる。
vbsでyyyymmddを手軽に使おうとする

自身のリファレンスとして使用させていただきます

とりあえず、扱いやすい関数として記述するよう別ファイル化。コピーしてソースを書いていく形にする。

```
Option Explicit
Include("C:\hoge\vbs\yyyymmdd.vbs")'読み込みたいvbsファイルのフルパス
'=====================
'ソースコード
msgbox yyyymmdd(now())

'=====================
'読み込んだvbsのクイックリファレンス

'mm(date)	//放り込んだdateの日付をmmで戻す
'dd(date)	//放り込んだdateの日付をmmで戻す
'yyyymmdd(date)	//放り込んだdateの日付をyyyymmddで戻す

'=====================
Function Include(full_path)
	Dim objFso, objWsh
	Set objFso = Wscript.CreateObject("Scripting.FileSystemObject")
	Set objWsh = objFso.OpenTextFile(full_path)
	ExecuteGlobal objWsh.ReadAll()
	objWsh.Close
	Set objWsh = nothing
	Set objFso = nothing 
End Function
```

そしたら、中身を適当に書いていく。

```
function dd(date)
	dd = mid(date,9,2)
end function

function mm(date)
	mm = mid(date,6,2)
end function

function yyyymmdd(date)
	yyyymmdd = year(date) & mm(date) & dd(date)
end function
```

この一手間だけでソースの可読性がかなり変わるので、個人的にオススメ。

オブジェクトを呼び出して、色々やって、戻ってくるという動作をする関数なんかも

```
function exist(path)
	Set objFso = CreateObject("Scripting.FileSystemObject")
	exist = objFso.FileExists(path) or objFso.FolderExists(path)
	'パスに書かれたファイルかフォルダがあるならtrue
	Set objFso = nothing
end function
```

みたいにすれば、かなり適当に分かりやすく欲しい機能だけ取り出せるようになります。

※VBSを読み込む ExecuteGlobal は、暴走すると危ないので、使用は自己責任でお願いします。
俺的リーダブルコードチートシート

- 他人から見て理解しやすいコードを作れ。場合によっては、簡潔/少ないコメントはマイナスに働くことに注意(条件分岐などを過度に短略化すると後で分かり辛い)
- 変数名に情報を詰め込め。例えば何か情報を取ってくるget関数なども、どこからなんの情報を取ってくるかで名付け方をgetFrom()/fetchFrom()などに変更した方が良い
- 変数名に値の単位/暗号化の有無などの情報を追記するのは◎
- ローカルな変数であればあるほど良い。また、その方が変数名の省略をしても問題が起きづらくなる
- 限界値はmin/max，以上以下はfirst/last,以上未満はbegin/end
- bool値を持つ変数は，先頭にis/should/has/canをつける&肯定系で名付けるのが吉
- 空行を使ってコードを段落分けしろ
- 重複処理はclassや関数を用いて簡潔に
- すぐに分かること/関数名や変数名の意味を補うコメントはしない
- コードの欠陥，定数やアルゴリズムの設計背景，コードの全体像はコメントすべし
- やばいと思ったこと，疑問に思ったことはガンガンコメントすべし
- 関数の入出力は実例を書くと◎
- インラインコメントで不明な引数は説明を付け加える
- コメントに代名詞は避ける
- `if 10 < width`よりも`if width > 10`(調査対象>比較対象)
- 条件分岐では「目立つもの」「単純なもの」を先に書く。また、条件は肯定で書く
- 三項演算子は「複数の条件の中から1つを選ぶ」際に用いる
- ネストは出来るだけ浅く(失敗を先に出す等/早めにreturn/gaurd節を用いて正常系と異常系を分ける)
- 式の意味を表す説明変数/要約変数を導入する
- ド・モルガンの法則 `not (a and b and c) ⇄ (not a) or (not b) or (not c)`または`not (a or b or c) ⇄ (not a) and (not b) and (not c)`
- 複雑な式を分割していない/理解を促進しない/中間結果に過ぎない変数は使わない
- 変数は出来るだけローカルに(1度しか宣言しないレベルで)
- 関数は出来るだけstaticに．大きなクラスは小さなクラスに
- プログラムの目的に無関係なコードは分離すべし
- 汎用コード化しよう
- プログラムで行うタスクを列挙し、1度に1つのタスクをする
- ディディベアに話しかけるようにコードのロジックの流れを説明できるようになれ
- 出来るだけライブラリに頼ってコード量を少なくするべし
- 単一責任原則:変更する理由が同じものは集める/違うものは分ける
【Laravel】バリデーションで任意のフィールドに任意のメッセージを設定する。

メモとして残します。

バリデーションで任意のフィールドに任意のメッセージを設定する方法をメモ。
Laravelのバリデーション便利ですが、たまにくどいエラーメッセージになってしまうことがあるため、
任意のメッセージを設定してあげましょう。
ルールごとに設定できるようです。
今回は、個人的に少しくどいエラーメッセージである`required_if`のメッセージをいじります。

#■やり方
messageメソッドをオーバライドしてあげることで、任意のフィールドに任意のメッセージを設定できる。

```php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class HogeRequest extends FormRequest
{
//・・・・・・・・・省略 

    /**
     * 定義済みバリデーションルールのエラーメッセージ取得
     *
     * @return array
     */
    public function messages()
    {
        return [
            'description.required_if' => trans('validation.required'),// この場合は必須の時のメッセージを表示します。
        ];
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $rule = [
            'is_public'  => 'required|in:1,0',
            'description'  => 'required_if:is_public,1|max:500',
        ];

        return $rule;
    }
}
```

#■余談
上記の例だと
description属性のルールでrequired_ifを定義しているため、
「is_publicが1なら、descriptionは入力必須です」
みたいなメッセージで、くどいなと思ったため、設定しました。
動画のAVAssetから音声データのみを抽出し再生

###元動画のAVAssetから音声データ(Audio track)のみ抽出
  

```
let asset = AVURLAsset(url: url)
let track = asset.tracks(withMediaType: .audio)[0]
```

###新しいAVAssetを生成し、そのAudio trackも生成

```
let newAsset = AVMutableComposition()
guard let audioTrack = newAsset.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) else { return }
```


###newAsset(音声のみのAVAsset)に動画から抽出したAudio trackを挿入

```
do {
      try audioTrack.insertTimeRange(track.timeRange, of: track, at: .zero)
    } catch let error {
        print(error)
    }
```

###AVPlayerで再生

```
let player = AVPlayer(playerItem: AVPlayerItem(asset: newAsset))
playerLayer.player = player
playerLayer.player?.play()
```


###コード全体

```
let asset = AVURLAsset(url: url)
let track = asset.tracks(withMediaType: .audio)[0]

let newAsset = AVMutableComposition()
guard let audioTrack = newAsset.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) else { return }

do {
      try audioTrack.insertTimeRange(track.timeRange, of: track, at: .zero)
    } catch let error {
        print(error)
    }

let player = AVPlayer(playerItem: AVPlayerItem(asset: newAsset))
playerLayer.player = player
playerLayer.player?.play()
```

###参考にした記事
https://qiita.com/croquette0212/items/8912053e616e575a4d4a
LaravelのRoutingについて prefixとgroupを使ってみる

laravelのルーティングについて簡単にまとめました。

## 基本の書き方

```php
Route::get('/main/list','MainController@list')->name('main.list');
Route::get('/main/edit','MainController@edit')->name('main.edit');
Route::get('/main/search','MainController@search')->name('main.search');
```

## prefixを使って省略した書き方

プレフィックスの意味は、頭に付く文字列のことです。
[プレフィックス (prefix)とは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word1208.html)

上記では`/main/`というプレフィックス部分が重複しているため、まとめて書くことで可読性の高いコードにします。prefixは通常、group関数とセットで使用されます。

```php
Route::prefix('main')->group(function () {
    Route::get('list','MainController@list')->name('main.list');
    Route::get('edit','MainController@edit')->name('main.edit');
    Route::get('search','MainController@search')->name('main.search');
});
```

## 名前付きルート name

`name('main.list');`の`main.`の部分も共通しているので、name()を使ってまとめて記載します。

```php
Route::prefix('main')->name('main.')->group(function () {
    Route::get('list','MainController@list')->name('list');
    Route::get('edit','MainController@edit')->name('edit');
    Route::get('search','MainController@search')->name('search');
});
```
textlintをtypescriptのコメントに適用する。

自然言語に対してlintをかけることができるtextlintというのがあるらしいです。
とりあえずこれをtypescriptのコメントに対して適用できるプラグインを書いてみました。
※ まだやってみた程度なので、どの程度うまく動くかわからないです。```tsconfig.json```も全く参照していません。

ソースはこちら。
https://github.com/ktkn304/textlint-plugin-typescript

# 使い方
とりあえず作ってみた程度のものなのでnpmには登録していません。
以下のようにgithubから直接インストールしてください。

``` shell
yarn install https://github.com/ktkn304/textlint-plugin-typescript.git
```


つぎにtextlintの設定ファイル(.textlintrc)を以下のように書き換えます。
※ ルールはお好みで追加してください。

``` json:.textlintrc
{
    "plugins": [
        "typescript"
    ]
}
```


あとはtextlintを実行すればts, tsxファイルのコメントもチェックしてくれます。

出力例:

``` shell
$ yarn lint
yarn run v1.22.4
$ textlint src/**

textlint-test/src/sample.ts
  20:11  ✓ error  原則として、全角文字と半角文字の間にスペースを入れません。  ja-spacing/ja-space-between-half-and-full-width

✖ 1 problem (1 error, 0 warnings)
✓ 1 fixable problem.
Try to run: $ textlint --fix [file]

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

# 参照
textlintについて
- [Qiitaやはてブロに投稿するようなユーザーはみんなtextlintを使うと捗るぞ！](https://qiita.com/fruitriin/items/de0e3d4c2205b734bdc5)
【Laravel7でユーザー認証_1】基本のき

# はじめに
Laravel7を使って、ユーザー認証が必要なサイトを構築する方法をまとめます。

#環境
XAMPP環境でLaravelが使えるように設定してあります。

- Windows10 Pro 64bit
- PHP 7.3.18
- Laravel 7.12.0
- MariaDB 10.1.32

# ユーザー認証の設定
## Laravelのプロジェクト作成
任意の名称でプロジェクトを作成します。
ここでは、「laravel_auth」という名前でプロジェクトを作成しました。

```
$ composer create-project --prefer-dist laravel/laravel laravel_auth
$ cd laravel_auth
$ php artisan -v
Laravel Framework 7.12.0
```
※Laravelのバージョンを指定してインストールしたい場合、laravel/laravelの部分にバージョン情報を追加する。


```
$ composer create-project --prefer-dist "laravel/laravel=7.*" laravel_auth
```

## 認証機能の追加
```php artisan ui vue --auth``` で認証機能を追加します。
Laravel5では、```php artisan make:auth``` で認証機能が追加できましたが、Laravel7はLaravel/uiに組み込まれたため、先にLaravel/uiの追加（composer require laravel/ui）が必要です。

```:Laravel/uiの追加
$ composer require laravel/ui
Using version ^2.0 for laravel/ui
```
※Laravel/uiのバージョンを指定したい場合、バージョン情報を最後に追加する。

```
$ composer require laravel/ui 2.*
```

```:認証機能の追加
$ php artisan ui vue --auth
Vue scaffolding installed successfully.
Please run "npm install && npm run dev" to compile your fresh scaffolding.
Authentication scaffolding generated successfully.
```

```Could not open input file: artisan``` というエラーが出た場合、Laravelのプロジェクトディレクトリ外でコマンドを打っている可能性が高いので、```cd``` コマンドで作成したディレクトリの中に移動します。

## パッケージのインストール・ビルド
Laravel/ui に必要なCSSやJavascriptを入れます。

```
$ npm install
$ npm run dev
```

## データベースの設定
### データベースの作成
phpMyAdminで、新規データベースの作成をします。
ここでは、以下内容でデータベースを作成しました。

- データベース名：laravel_auth_db
- ユーザ名：laravel_auth_user
- ユーザパスワード：laravel_auth_password


### .envファイルの設定
laravel_multi_auth フォルダの中の .env について、データベース接続に関わる以下の項目を書き換えます。

```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_auth_db
DB_USERNAME=laravel_auth_user
DB_PASSWORD=laravel_auth_password
```

### テーブルの作成

```php artisan migrate``` で認証に必要なテーブルを作成します。

```
$ php artisan migrate
```

``SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))`` というエラーが発生する場合、 app\Providers\AppServiceProvider.php に、以下の内容を追加し、最大長未指定カラムのデフォルト最大長を191に変更します。

```app\Providers\AppServiceProvider.php
+   use Illuminate\Support\Facades\Schema;

    public function boot()
    {
+       Schema::defaultStringLength(191);
    }
```

途中でmigrateが止まってしまった場合、中途半端にテーブルが作られてしまった状態なので、一旦すべてのテーブルを削除して作り直します。

```
$ php artisan migrate:fresh
Dropped all tables successfully.
Migration table created successfully.
```

## 開発サーバの起動
```
$ php artisan serve
Laravel development server started: http://127.0.0.1:8000
```

サーバが起動すると、URLが表示されるので、ブラウザでアクセスして確認します。

|![Laravel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/723f0acf-9b47-ce71-c5b8-0ca08609b94e.png)|
|:-:|


以上で、ユーザー認証の基本的な操作が可能になります。

◆次の記事 [【Laravel7でユーザー認証_2】ユーザー認証を日本語化](https://qiita.com/crosawassant/items/d1f4c5c93f30afa9eb65)

#参考サイト
- [更新！ Laravel6/7「make:Auth」が無くなった 〜Laravel6/7でのLogin機能の実装方法〜MyMemo - Qiita](https://qiita.com/daisu_yamazaki/items/a914a16ca1640334d7a5)
- [Laravel5.4以上、MySQL5.7.7未満 でusersテーブルのマイグレーションを実行すると Syntax error が発生する - Qiita](https://qiita.com/beer_geek/items/6e4264db142745ea666f)
Unity-DOTSで作る2D弾幕シューティングの例 - 概要

# 何？
個人でDotsを使って趣味で作っていたシューティングゲームについて、
作るにあたって調査が必要だった部分などをまとめていきます。

ECS、Dotsが何かという点については下記がオススメです。
[たのしいDOTS 〜初級から上級まで〜](https://learning.unity3d.jp/3252/)

このDotsというのは作っていておもしろく、パフォーマンスも良いものができ、勉強にもなるので、
最初のとっつきにくさを突破してしまえば学んで損はないものだと思います。
Dotsを使った制作の一例として、何かの参考になれば幸いです。

ここで話すゲームは下記のような感じです。
![01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651558/9d61b60b-b268-991c-6fec-d5fd76e9e664.gif)

# 環境

|名前  |バージョン  |
|---|---|
|Unity  |2019.3.05f  |
|Entities  |0.6.0  |
|Burst|1.3.0|
|Jobs|0.2.5|
|Addressable|1.1.10|

# お章立て

1. [データの管理について](https://qiita.com/inukai_anubis/items/1db866e99e5d04e516de)
2. [ステージキューの管理について](https://qiita.com/inukai_anubis/items/261a9e37ec9eef79c2cf)
3. [敵/弾/銃のデータ構造について](https://qiita.com/inukai_anubis/items/cf9ed47060332bc903cf)
4. [Entityの管理について](https://qiita.com/inukai_anubis/items/cf120d58ab16d25db47a)
5. [自作描画システムについて](https://qiita.com/inukai_anubis/items/3d4998471aec023e6b05)
おすすめショートカットキー OneNote 編

#おすすめショートカット OneNote 編
こんにちは、今回は Microsoft のOfiice 製品である OneNote の作業効率アップ系ショートカットキーを紹介したいと思います。
OneNote は2種類存在してますが、今回は **OneNote for Windows 10** と呼ばれているものでのお話になります。
![2020-06-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539633/e78a44cb-d6c3-1390-85b0-4acde5503f0d.png)

## OneNote 固有のショートカットキー
- Ctrl + . → 箇条書き（点）
- Ctrl + / → 箇条書き（数字）
- Ctrl + N → ページの追加
- なにも記入してない行で Tab → インデント
 - Shift 押しながらすると戻る
- 何か入力したところで Tab → 表の生成、右に枠が増える

## ここから先は Office でも共通
全く同じでなくても似た機能はあると思います。

- Ctrl + T → セクションの追加
- Ctrl + B → 太字
- Ctrl + U → 下線
- Ctrl + Shift + , → フォントサイズの変更、小さくなる
- Ctrl + Shift + . → フォントサイズの変更、大きくなる
- Ctrl + F → 検索
- Shift + Enter → 箇条書きとかで新しく点とかつけずに改行

録音機能と組み合わせると作業効率はさらに爆上がりです！

![コメント 2020-06-08 164503_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539633/a0c5441c-e624-ec44-4692-c96fb337bd07.jpeg)

丸で囲ったところをクリックするとメニュバーが消えるの最近知りました...
PostgresqlをUbuntu20.04に入れてみる。

Postgresをインストールするなら、公式が良さそう。

https://wiki.postgresql.org/wiki/Apt

コレに従って入れていく。


```bash
# 必要なパッケージをインストールする
sudo apt-get install curl ca-certificates gnupg

# 鍵を入れる。
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

# リポジトリの参照リストに追記する。20.04のコードネームはfocal fossaなので。
# deb http://apt.postgresql.org/pub/repos/apt focal-pgdg main

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

# リポジトリを更新する。Postgresをインストールする
sudo apt update
sudo apt install postgresql-11 pgadmin4

# インストールすると、受付ポートが立ち上がる
netstat -nlpt
↓
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      654/systemd-resolve 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      753/sshd: /usr/sbin 
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      6371/postgres       
tcp6       0      0 :::22                   :::*                    LISTEN      753/sshd: /usr/sbin 

# psqlのバージョン確認
root@kuntama-db:/etc/netplan# su - postgres
postgres@kuntama-db:~$ psql -V
psql (PostgreSQL) 11.8 (Ubuntu 11.8-1.pgdg20.04+1)
postgres@kuntama-db:~$ 

```

接続確認

```
root@kuntama-db:/etc/netplan# su - postgres
postgres@kuntama-db:~$ psql -V
psql (PostgreSQL) 11.8 (Ubuntu 11.8-1.pgdg20.04+1)
postgres@kuntama-db:~$ psql -d postgres -U postgres
psql (11.8 (Ubuntu 11.8-1.pgdg20.04+1))
Type "help" for help.

postgres=# 
postgres=# 
postgres=# 
postgres=# \d
Did not find any relations.
postgres=# 
postgres=# 
postgres=# \q
postgres@kuntama-db:~$ 

```

パスワードなしでいけるみたいですね。
NuxtでボタンをクリックしたときにToastが出てURLをコピーする機能の実装

# 概要

調べてみたら思ったより簡単に実装できたるモジュールがあったので共有します。
ソースは[ここ](https://github.com/Kuehar/nuxt-django)。

# こんな感じのを作るよ！！

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412789/d1dd84e1-fa35-a6cb-5d8f-f5e77750684e.gif)


# 導入

[nuxt-clipboard2](https://www.npmjs.com/package/nuxt-clipboard2)

まずはインストール。

```
$ npm install --save nuxt-clipboard2
```

そしてmoduleに追加。

```javascript:nuxt.config.js
modules: [
    'nuxt-clipboard2',//追加
  ],
```


これで

```Javascript
<v-btn class="ma-2" text icon color="green lighten-2" @click="onCopy(`http://localhost:3000/hoge/${hoge.id}/`)">
        <v-icon>mdi-share-variant</v-icon>
</v-btn>

..............

<script>
export default {
  methods: {
    onCopy(url) {
      this.$copyText(url)
    }
  }
}
```


これをfor文で動的にidを取得すれば自動的にurlが割り当てられます。
基本的なものとしてはこれで十分です。

しかし、ちゃんとコピーされたかどうかをtoastで表示した方がユーザーにとってみやすくなるので、もう少しだけいじってみましょう。

[@nuxtjs/toast](https://www.npmjs.com/package/@nuxtjs/toast)を使います。

```
$ npm install @nuxtjs/toast
```

```javascript:nuxt.config.js
modules: [
    'nuxt-clipboard2',//追加
    '@nuxtjs/toast' //追加
]

// Toastの設定
toast: {
    position: 'top-center',
    theme: 'bubble'
  },
```

```javascript
<script>
export default {
  props: ['item', 'onDelete'],
  methods: {
    onCopy(url) {
        this.$copyText(url)
        this.$toast.success('URLがコピーされました!!')
      }
    }
  }
</script>
```

これで冒頭のような処理が行われます。

toast機能は色々と応用が効くと思ったので書いておきました。
誰かの役に立つと幸いです。

お疲れ様でした。
マイグレーションとシーディングについて理解したいときに読むメモ

#マイグレーションとシーディングについて
データベースの内容を自動生成するために用意されているのがマイグレーションとシーディングである．これらを理解することでデータベースを効率的に管理することができるようになる．

##マイグレーションとは
データベースを扱うときに，最も注意しなければいけないのが「データベースの構造」である．例えば，データベースを移行したり，環境を移行したりする場合，データベースを一から構造しなければいけない．このとき，全てのデータベースを全く同じ構造で作らなければ，データベース関係は正しく動作しなくなる（何度エラーを吐かれたことか...）

現在，使っているデータベースの構造を確認し，それと全く同じものを再現する仕組みがあれば，データベースの管理はとても楽になる．そのために提供されているのが「マイグレーション」という機能．

マイグレーションは，データベースのバージョン管理機能（だから日時などがファイル名に入るのか！！）である．データベースのテーブルを作成したり，削除したりする機能を持っており，PHP のスクリプトを使ってテーブルの作成処理などを用意している，
このマイグレーション機能を使用して，使用するテーブルなどの作成処理を用意しておけば，環境が変わった場合もコマンド一つでデータベースのテーブルなどを生成することができる，また，テーブルの構造が途中で変わった場合でも古いテーブルを全て削除して最新のテーブルに更新するような作業が簡単に行うことができる．

##シーディングとは
テーブルの用意については，マイグレーションを用いてできるようになる．ただ，これだけでは，テーブルに何もレコードは入っていない．初期状態でダミーのレコードがあると便利だよね．これをしてくれるのが「シーディング」機能である．これはシード（最初から用意しておいたレコード）を作成する機能である．


#手順について
マイグレーションとシーディングの手順についてのメモ
##マイグレーションの手順
⒈ 専用のスクリプトファイルの作成
まず最初に，マイグレーションを記録するためのスクリプトファイルを作成する．これはコマンドを使って，作成できる．

```php artisan make:migration ファイル名
```


⒉ スクリプトの記述
作成されたスクリプトファイルに，データベース管理の処理を記述する．これは，テーブルの生成や削除などの処理を PHP で書くことになる，

```php:xxx_filename.php
public function up(){
    Scheme::create('', function(BluePrint $table){
        テーブル作成処理
    });
}
```

⒊ マイグレーションの実行
マイグレーションを行う場合，コマンドを使って実行する．コマンドにより，用意されたマイグレーション用のスクリプトファイルを実行してテーブルの生成や削除などが行える．

```php artisan migrate
```


##シーディングの手順
⒈ シーディングのためのスクリプトファイルを作成する．これはコマンドで用意できる．

```php artisan make:seeder シーダーファイル名
```

⒉ スクリプトファイルを編集してシードに追加する．
run メソッド内にシードを作成する処理を記述．
DB::insertを用いて，レコードを作成するだけである．


⒊ シーダーファイルの登録
DatabaseSeeder.php というファイルがデフォルトで用意されているので，これを以下のように編集する．

```php:DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(){
        $this->call(シーダーファイル名::class);
    }
}

```

⒋ コマンドでシーディングを実行
```php artisan db::seed
```



#マイグレーションとシーディングについて
あまり理解してないと，何度かつまづく部分なきがする（僕がそうでした）ので，まとめてみました．今後も色々アップできたらと思います．
[GCF+Python]ExcelをGCSにアップしてBigQueryに新規テーブルを作成する方法


#目的
非エンジニアの企画職やマーケ職などが自身でBigQueryにデータアップロードできるツールを提供したい & 自分自身が普段エクセルのデータをBigQUeryにアップロードするのが面倒だったりするので、GUIで操作できるように作りました。

#想定する挙動
1. **Cloud Storageにエクセル(.xlsxもしくは.csv)をアップロードする。**  
※GCSのディレクトリ名がBigQueryのデータセット名となり、ファイル名がテーブル名になるようにpathを作る  
.xlsx `GS://バケット名（任意）/dataset名/table名.xlsx`  
.csv `GS://バケット名（任意）/dataset名/table名.csv`

2.**GCSのアップロードがトリガーとなり、GCFが動く。**
3.**BigQueryに新規テーブルが作成される。**
（※既に同じテーブル名がある場合、上書きされる）

#準備
- ### Google Cloud Storage  
データアップロード対象のバケットを作成する

- ### Google Cloud Functions  
以下の設定を行う（詳細は割愛）
Python 3.7
トリガーのタイプ : `Cloud Storage`
バケット : `上記で作成したGCSのバケット`


#GCF
```requestments.txt
pandas
pandas-gbq
google-cloud-storage
google-cloud-bigquery
xlrd
```

```main.py
from google.cloud import storage
from google.cloud import bigquery
import pandas as pd
import re


def gsc_to_bigquery_createtable(data, context):
    # log
    print(data)
    print(context)
    print('Folder Name : {}'.format(data['name']))
    GETPATH = data['name']
    m = re.match(
        r'(?P<getDatasetId>.*)/(?P<getFileId>.*)\.(?P<getFileType>.*)',
        GETPATH)
    # バケット名とプロジェクト名を指定する
    BUCKET = 'バケット名'
    PROJECT_ID = 'プロジェクト名'
    # データセット名を取得
    DATASET_ID = m.group('getDatasetId')
    # ファイル名を取得
    FILE_ID = m.group('getFileId')
    # 識別子を取得
    FILE_TYPE = m.group('getFileType')

    TMP_PATH = '/tmp/' + FILE_ID + '.' + FILE_TYPE
    # GSCからpythonへデータインポート
    gcs = storage.Client(PROJECT_ID)
    bucket = gcs.get_bucket(BUCKET)
    blob = bucket.get_blob(GETPATH)
    blob.download_to_filename(TMP_PATH)

    # 識別子の条件分岐
    if FILE_TYPE == 'xlsx':
        df = pd.read_excel(TMP_PATH)
    elif FILE_TYPE == 'csv':
        df = pd.read_csv(TMP_PATH)

    # pythonからBigQueryへテーブル作成
    full_table_id = DATASET_ID + '.' + FILE_ID
    df.to_gbq(full_table_id, project_id=PROJECT_ID, if_exists='replace')
　　# log
    print('Folder Name : {}'.format(data['name']))
```
Macbook proのBluetoothでaptXを有効にする

手持ちのイヤホンがaptXに対応しているので、折角だから高音質にしようと思って調べてみました。

実行環境
Macbook pro 13(2018)
macOS 10.14.6 Mojave

**bluetoothをオフにして**以下のコマンドを実行するとaptXを有効にできます。
`sudo defaults write bluetoothaudiod "Enable AptX codec" -bool true`

optionを推しながらbluetoothアイコンをクリックし、コーデックを確認します。
aptXになっていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262234/59019da8-4164-5694-a3a8-39fee8dab97a.png)


元に戻すときは再度**bluetoothをオフにして**以下のコマンドを実行します
`sudo defaults delete bluetoothaudiod`
ARC 036 D 偶数メートル

##問題
https://atcoder.jp/contests/arc036/tasks/arc036_d
##見た感じ
まず距離が偶数の道でつながれた町は偶数の距離で到達できて、あと距離が奇数の道で町aと町bがつながっていて、距離が奇数の道で町cと町dがつながっていた時、bとdが偶数の距離で到達できればaとcも偶数の距離で到達できる。
ここで、aとbが偶数の距離で到達できて、cとbが偶数の距離で到達できればaとcも偶数の距離で到達できるのでこのような到達可能関係はunion-find木で管理すれば便利そうなので、そうする方針で進めた。
まず、距離偶数で到達できる街をまとめたuftreeをtreeとする。こうするとaとbを結ぶ新しい道で長さが偶数のものが来たときすら、以下のような入力があるかもしれないので、めっちゃ計算しないといけない。
1 1 2 3
1 3 4 3
1 2 3 2
この時、1 2 3 2 の道のおかげでもともとなかった偶数長の道がで来ている。これができたかできてないかを判定するのに素直に書くと$O(n^2)$かかり間に合わない。
ここで、奇数長の道と偶数長の道を別々に考えるから、計算量が増えるので、ひとつのuftreeでまとめて考えることにする。
treeを以下の要領でmergeしていく。
1 a b x に対して
x%2==0の時　tree.merge(a,b);tree.merge(a+n,b+n);
x%2==1の時  tree.merge(a,b+n);tree.merge(a+n,b);
このようにすると、奇数長の道を含む偶数長の道はnから2*n-1の仮想的な街を通らないと形成できなくて、また逆にnから2*n-1の仮想的な街を経由する道は奇数長の道を含む偶数長の道になっている。つまり、奇数長の場合を分けて計算する代わりにuftreeの中で分離した形で管理していくことで、頂点数は2倍なったがそれだけだすんだのだ。
これで、行けば単純に
2 a b 1に対して、
tree.same(a,b)ですむ。
##解法
uftree上で到達可能性を上の要領で管理していく。
##ソースコード
```c++
struct uftree{
    int n;
    int cou;
    vector<int> parent;
    vector<int> rank;
    vector<int> _size;
    uftree(int n):n(n){
        parent=vector<int>(n);
        rank=vector<int>(n,0);
        _size=vector<int>(n,1);
        cou=n;
        rep(i,n){
            parent[i]=i;
        }
    }
    int root(int i){
        return parent[i]==i?i:parent[i]=root(parent[i]);
    } 
    bool same(int i,int j){
        return root(i)==root(j);
    }
    void merge(int i,int j){
        i=root(i);j=root(j);
        if(i==j)return;
        cou--;
        if(rank[i]>=rank[j]){
            parent[j]=i;
            _size[i]+=_size[j];
        }else{
            parent[i]=j;
            _size[j]+=_size[i];
        }
        if(rank[i]==rank[j])rank[i]++;
        return;
    }
    int count(){
        return cou;
    }
    int unitsize(int i){
        return _size[root(i)];
    }
};
const int N_MAX=0;
int n,q;
vector<pint> mem;

int main(){
    int a,x,y,z;
    //入力
    cin >> n>> q ;
    uftree tree(2*n);
    vector<string> ans;
    rep(i,q){
        cin>>a>>x>>y>>z;
        if(a==1){
            z=z%2;
            if(z==0){
                tree.merge(x-1+n,y-1+n);
                tree.merge(x-1,y-1);
            }else{
                tree.merge(x-1,y-1+n);
                tree.merge(y-1,x-1+n);
            }
        }else{
            tree.same(x-1,y-1)?ans.pb("YES"):ans.pb("NO");
        }
    }
    //処理
    //出力
    for(auto b: ans){
        cout << b <<endl;
    }
}
```

##振り返り
uftreeって同値関係を代表元を定めることで管理するデータ構造だと気づいた。
IE6 対応の wysiwyg エディタ

* [Supported Editors Matrix | Drupal 7 guide on Drupal.org](https://www.drupal.org/docs/7/modules/wysiwyg/supported-editors-matrix)

CKEditor と TinyMCE が２大エディタ

## CKEditor3

* CKEditor は FCKeditor の後継。
* [3系](http://svn.ckeditor.com/CKEditor/) : IE6対応
    * [4.1.3](https://github.com/ckeditor/ckeditor4/archive/4.1.3.tar.gz) : IE7対応最終バージョン
    * [4系](https://github.com/ckeditor/ckeditor4/releases) : IE8対応。4.14.0 が最新 (2020/6/9現在)
    * [5系](https://ckeditor.com/docs/ckeditor5/latest/builds/guides/support/browser-compatibility.html) : IE非対応(11も)
* https://docs-old.ckeditor.com/ckeditor_api/symbols/CKEDITOR.config.html

```sh
git clone https://github.com/dehy/ckeditor3
cd ckeditor3/
php -S 0.0.0.0:8000
```

* http://localhost:8000/_samples/


```html
<script type="text/javascript" src="ckeditor.js"></script>

<textarea cols="80" id="editor1" name="editor1" rows="10">
    <div id="editor2">aaa</div>
</textarea>

<script> 
// 非表示にしたいボタンを列挙
CKEDITOR.config.removePlugins = 'newpage,flash,save,templates';
// Enterキーで<br /> (デフォルトは<p></p>)
CKEDITOR.config.enterMode = CKEDITOR.ENTER_BR;

// Editor表示
CKEDITOR.replace('editor1', {
    height: 500
});
</script>
```


```js
// editor1 の値を取得する方法 (公式)
var src = CKEDITOR.instances.editor1.getData();

// iframe の中身を取得する方法
var iframe = document.getElementById('cke_editor1').getElementsByTagName('iframe')[0];
var src = iframe.contentWindow.document.body.innerHTML;
```

----

## ckeditor4 (IE9以降対応)

* [Builder | CKEditor.com](https://ckeditor.com/cke4/builder)
* [build-config.js](https://github.com/ckeditor/ckeditor4-presets/tree/master/presets)

### 注意点

* CKEditor3 では問題なかったが、CKEditor4では入力できるタグの制限がある。

全てのタグを許可するには

```js
CKEDITOR.config.allowedContent = true;
```

* 日本語化 UTF-8 を SJIS化

```sh:sjis化
nkf -s --overwrite `find | grep ja.js`
```



----

## TinyMCE v3

ソースコードエディターがポップアップ表示するのがちょっと気に入った。

![editor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/108ca315-d558-90d0-15f2-12489ff607a7.png)


* [v3](https://www.tiny.cloud/docs-3x/extras/TinyMCE3x@Browser_compatiblity/) : IE6対応
* https://www.tiny.cloud/docs-3x/
    * https://www.tiny.cloud/docs-3x/TinyMCE3x@Installation/

```sh
# version 3.4.8+dfsg0-2 が入った。
apt install -y tinymce

cp -a /usr/share/tinymce/www/ ~/Documents/
cd www
# 一部修正
sed -e 's@/tinymce/tiny_mce.js@tiny_mce.js@' example.html > index.html
python3 -m http.server
```

### サンプル

```html
<script language="javascript" type="text/javascript" src="tiny_mce.js"></script>
<script language="javascript" type="text/javascript">
tinyMCE.init({
    mode : "textareas",
    // HTMLプレビューボタンも表示
    theme : "advanced",
    apply_source_formatting : false,
    theme_advanced_buttons3_add : "fullpage"
});
</script>

<body>
<h1>TinyMCE Debian Test</h1>

<form method="post">
    <textarea name="content" cols="50" rows="15">sample</textarea>
</form>
```

### HTMLが自動で整形されるのを防ぐ

* [TinyMCE | apply_source_formatting](https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@apply_source_formatting/)

```js
tinyMCE.init({
    ...
    apply_source_formatting : false
});
```
TypeScriptでmapNotNull関数を実現したい

# TypeScriptでmapNotNull関数を実現したい
kotlinのmapNotNull関数をTypeScriptでも実現したい、そういう記事です。
[mapNotNull()](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map-not-null.html)
## KotlinのmapNotNull関数
Kotlinのmap関数は、コレクションの各要素に与えられた関数を適用して、その結果を新しいコレクションに集約します。mapNotNull関数は結果がnullの場合は、その要素はスキップします。

```
val list = listOf(
    listOf(79, 80, 75, 87),
    listOf(60, 55, 45, 63),
    listOf(69, 90, 74, 88)
)
println(
    list.mapNotNull { if (it >= 80) it else null }.filter { it.isNotEmpty() }
) // [[80, 87], [90, 88]
```
## TypeScriptで同じことを実現しようとすると・・・

```
let list = [
    [79, 80, 75, 87],
    [60, 55, 45, 63],
    [69, 90, 74, 88]
]
console.log(
    list.map(p => p.filter(q => q >= 80))
) // [[80, 87], [], [90, 88]]
```
空配列が混じってしまいます。
## やはりさらにfilterで空配列を取り除くしかないのか

```
let list = [
    [79, 80, 75, 87],
    [60, 55, 45, 63],
    [69, 90, 74, 88]
]
console.log(
    list.map(p => p.filter(q => q >= 80))
        .filter(r => r.length != 0) 
) // [[80, 87], [90, 88]]
```
## 追記
コメントで指摘していただいた通り、Kotlinでもfilterで空配列を除去しないとだめでした。
mapNotNullOrEmpty的なものはないのでしょうか。。
【UiPath】逆引き


# フォルダ内のファイル一覧取得
アクティビティ無し。`System.IO.Directory.GetFiles` を使う。
参考：[Directory.GetFiles メソッド (System.IO) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.directory.getfiles?view=netframework-4.8)

```vb:サンプル
System.IO.Directory.GetFiles("C:\test")

' フィルタ指定。*と?が使用できる
System.IO.Directory.GetFiles("C:\test", "*.xlsx")

' サブフォルダを含めるかどうかの指定
System.IO.Directory.GetFiles("C:\test", "*.xlsx", System.IO.SearchOption.AllDirectories)
```

# パスワード付きzipファイルの解凍
.NET、UiPathに用意されている機能では扱えないので、ほかのツール(7zip)を使う。

PCに7zipをインストールする。
(コマンドラインが使用できて、パスワード付きの解凍ができるツールであればなんでも良い)

コマンド実行して解凍する。実行方法は後述の「コマンドを実行して終了を待つ」参照。

↓ `C:\test\test.zip`をパスワード`123456`を使って`C:\test`へ解凍する例。

```:コマンド例
"C:\Program Files\7-Zip\7z.exe" x C:\test\test.zip -oC:\test -p123456
```

# コマンドを実行して終了を待つ
「プロセスの開始」(StartProcess)は非同期なので、コマンド実行中でも後続のフローがさっさと進んでしまう。
代わりに「PowerShellを呼び出し」を使い、PowerShell内で`Start-Process -Wait`を使う。

参考：[UIPathでPowerShellを実行する方法 - Qiita](https://qiita.com/mima_ita/items/7ab32e085b1eba0f422d)

まず実行するps1ファイルを用意して、プロジェクトフォルダ内に保存する。

```powershell:7zip実行.ps1
Param(
     [string]$zipPath
    ,[string]$destDir
    ,[string]$password
)

$exePath = "`"C:\Program Files\7-Zip\7z.exe`""

$args = @("x", "`"${zipPath}`"", "-o`"${destDir}`"", "-p${password}")

Start-Process -FilePath $exePath -ArgumentList $args -Wait
```

UiPath側でps1ファイルを読み込み、「PowerShellを呼び出し」で実行する。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/04590ebb-4b97-a884-9d57-6bb6a848cc9d.png)

「PowerShellを呼び出し」アクティビティのプロパティのうち、「スクリプト入力」にチェックを入れ、スクリプトに渡すパラメータは「パラメーター」に指定する。

# DataTable の DataType を変更する
## 現象
「CSVを読み込み(ReadCsvFile)」で読み込んだ DataTable は、列の DataType が全て String 型になる。
Excel の「範囲を読み込み(ExcelReadRange)」で読み込んだ DataTable は、列の DataType が全て Object 型になる。

同じ名前の列名が両者に存在し、DataTypeが異なる場合、「データテーブルをマージ」で合体させようとしても、DataType の不一致でエラーになる。

↓エラーメッセージ
> データ テーブルをマージ: <target>.列名 と <source>.列名 は競合するプロパティがあります : DataType プロパティの不一致

DataType を揃えれば良いのだが、データがある DataTable に対して DataType の変更はできない。

## 解決策1
UiPath Connect で公開されているコンポーネントを利用する。
[Datatable - Change Column Datatype - RPA コンポーネント | UiPath Connect](https://connect.uipath.com/ja/marketplace/components/datatable-change-column-datatype)

## 解決策2
元の DataTable のスキーマを元に新しい DataTable を作成し、DataType を変更してから元データをインポートする。
…という処理を「コードを呼び出し」に実装する。

```vb:DataTypeをObjectへ変える例
out_table = in_table.Clone()

For Each column As DataColumn In out_table.Columns
    column.DataType = GetType(Object)
Next

For Each row As DataRow In in_table.Rows
    out_table.ImportRow(row)
Next
```
↓引数の設定

|名前|方向|型|値|
|---|---|---|---|
|in_table|入力|DataTable|DataTable型の変数を指定|
|out_table|出力|DataTable|上記と同じ変数を指定|

# Json を扱う
参照設定に`UiPath.Web.Activities`が必要。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/1c93477a-cecc-c489-54d1-0934abc49791.png)
Json.NETが使われている。
【MySQL】GROUP BYとORDER BYが併用できない件

##経緯
一番新しく更新されたデータを取得したいと思い、こんな感じのSQLを書いたところ想定通りの値が取れない

#####サンプルテーブル

| id | name | type | created_date | update_date |
|:--:|:----:|:----:|:------------:|:-----------:|
| 1  | entry | 1 | 2020-01-08 12:04:56|2020-01-08 12:04:56|
| 2  |  introduce | 1 |2020-01-11 14:24:31|2020-01-11 14:24:31|
| 3  |  introduce | 1 |2020-01-12 13:29:01|2020-01-08 15:42:21|
| 4  |  recommend | 2 |2020-01-15 11:16:30|2020-01-15 11:16:30|
| 5  | make | 3 |2020-01-16 14:54:16|2020-01-16 14:54:16|
| 6  | read | 3 |2020-01-18 13:12:06|2020-01-19 12:02:24|


#####SQL

~~~SQL
select updated_date from tables group by type order by updated_date desc
~~~

##原因
SQLの命令を処理する順番として、GROUP BYが優先されるため
つまり、一旦GROUP BYでグループされた後に昇順・降順を決定するため、意図しない値が取得されていたという訳。

##対処方法
SELECTで取得する項目が一つの場合、MAX関数を使用する

~~~SQL
select MAX(updated_date) from tables group by type;
~~~

SELECTで取得する項目が複数の場合、サブクエリを構築する

~~~SQL
select * from tables where updated_date in (select MAX(updated_date) from tables group by type);
~~~
Amazon Linux Spring Boot Jarファイルをサービスとして登録

今回試した環境は以下

- Spring Boot
- Kotlin
- Gradle
- EC2(Amazon Linux)


##### 1.jarをサービスとして登録できるようにbuild.gradleに以下を追加

```gradle:build.gradle.kts
tasks.getByName<BootJar>("bootJar") {
  launchScript()
}
```
#####2.jarファイル生成

```terminal
gradle bootJar
```

##### 3.jarファイルをサーバーにアップロード

```terminal
# 手順2の実行後jarファイルが生成されていることを確認
# xxx.jarが生成されていればOK
ls -la ./build/libs/

# 対象のサーバにjarファイルアップロード(ipやpemは各環境に合わせて書き換える)
# ユーザはEC2を使っているので今回はec2-userを利用しています
sftp -i ~/.ssh/xxx.pem ec2-user@xx.xx.xx.xx
put ./build/libs/xxx.jar
```
#####4. jarファイルが実行可能か確認

```terminal
# サーバにssh接続
ssh -i ~/.ssh/xxx.pem ec2-user@xx.xx.xx.xx

# 実行してみる
# 問題なく起動できればプロセスレベルで起動できるところまで確認OK
java -jar  xxx.jar
```

#####5.実行時に渡すパラメータを記載したファイルを作成

ファイル名はjarファイルと同じにし拡張子をconfにする。
以下は実行時のプロファイルを指定する例


```conf:xxx.conf
RUN_ARGS="--spring.profiles.active=prod"
```

#####5.サービス登録するためのファイルを作成

```terminal
# xxxはservice名
sudo vi /usr/lib/systemd/system/xxx.service
```

```terminal:xxx.service
[Unit]
# xxxはサービス名
Description=xxx
After=syslog.target
 
[Service]
Type=simple
User=ec2-user
Group =ec2-user
# xxxは設置したjarのファイルパス
ExecStart=/home/ec2-user/xxx.jar
SuccessExitStatus=143
 
[Install]
WantedBy=multi-user.target
```

#####6.サービスを開始

```terminal
# 変更を読み込む
systemctl daemon-reload

# サービスとして登録されていることを確認
systemctl status xxx.service

# サービス開始
sudo systemctl start xxx.service

# 確認
systemctl status xxx.service 
ps aux | grep java

# 上記手順でうまくいかない時はログをみる
# /var/log/messageを確認する
# permissionエラーが出てしまっている時は、 xxx.jarの権限を確認する 744とかで実行権限がついていればOK。
お前らの四捨五入は間違っている~0.5を足している人へ~

四捨五入をしていてふと詰まったことがあったので共有する。

結論だけ言うとちゃんとどこの言語にでもありそうなroundを使おうと言う話。(これも正確な四捨五入ではなく銀行丸めと言うものな場合もある)


私はC言語で四捨五入する時に以下のようなコードを書いていた。

```C
float x=1.6;
int round_x = x + 0.5;
```

int型へのキャストでは少数部分が切り捨てられるのでさきに0.5を足しておくことで切り捨てが四捨五入に早変わりすると言うもの。
1.51の場合
1.51+0.5=2.01なので2.01の小数点以下を切り捨てるとちゃんと1.51の四捨五入である2になっている。
1.49の場合
1.49+0.5=1.99なので1.99の小数点以下を切り捨てるとちゃんと1.49の四捨五入にである1なっている。

今までこのコードに疑問など抱いたことはなかった。(intやfloatの精度が足りる限り)
しかし、このコードには問題がある。

# 負の数の時には0.5を足してはいけない
先ほどのコードで-2.3を四捨五入することを考えてみよう。
答えは-2になるべきであるが。
-2.3+0.5=-1.8
小数点を切り捨てると-1となってしまうのである。

知っている人にとっては当たり前の話かもしれないがこれに気づかずに1時間ほど詰まってしまった

# ならばどうする？
四捨五入する対象が負の時には+0.5ではなく-0.5しなければならない。
少しめんどくさいので諦めてround関数を使ったほうが早いだろう。