OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】kaminariを使ってページネーションを実装する方法

ページネーションを作るのに、kaminariというgemを使ったのですが久しぶりで忘れてしまっていました。

 

そこで備忘録として

- kaminariの導入方法
- kaminariのカスタマイズ方法

についてまとめてみました。

 

よかったら参考にしてみてください。


##【Rails】kaminariを使ってページネーションを実装する方法
kaminariによるページネーションの実装は、大きく分けて6つのステップでできます。


###ステップ1：Gemgileに記述
Gemfileに以下のように記述してください。

```
gem 'kaminari'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266250/ad12fefc-3f54-f470-15a6-3e015ae45290.png)


###ステップ2：bundle installする
Gemfileにkaminariを記述したら、ターミナルを開いてbundle installしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266250/7bd8f71b-f7fe-ac36-be03-b6bbe8b89402.png)


###ステップ3：kaminariの設定ファイルを生成する
次にkanimariの設定ファイルを作ります。

以下のコマンドをターミナルに打ち込んでください。

```
rails g kaminari:config
```

以下のように表示されたら成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266250/858dae76-a855-2f05-3a23-992e4f9170f2.png)


###ステップ4：kaminariのviewファイルの生成
次にviewファイルを作ります。
今回はbootstrap4で見た目を整えるので、以下のようなコマンドを打ちました。


```
rails g kaminari:views bootstrap4
```

以下のように表示されたら成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266250/c6b461b1-5651-553b-55c7-496b49855153.png)


ちなみにBootstrap4を使わない場合は、以下のように打ち込んでください。

 
```
rails g kaminari:views default
```


###ステップ5：controllerにpageメソッドを追加
ページネーションを実装したいアクションを持つcontrollerにpageメソッドを追加しましょう。

```
.page(params[:page])
```

例えば、indexアクションに表示される記事一覧（@articles）にページネーションを使いたい場合は、こんな感じで書けばOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266250/074cc31b-28b4-5542-8f2d-130cf79e6665.png)


pageメソッドを呼び出すことにより、引数に指定したページに表示するデータだけを取得できます。

デフォルトの設定では、1ページに25件のデータが取得されます。


###ステップ6：viewファイルの修正
次にviewファイルを修正していきましょう。

ページネーションを表示したい箇所に以下のコードを書いてください。


```
<%= paginate @articles %>
```

以下のように表示されたら成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266250/e7acf1af-7639-0440-2f92-2a4fa951db76.png)


##まとめ
kaminari便利！
【初心者向け】コメント機能作成追加

##前提
・記事投稿一覧ページがすでに作成されている状態であること
・記事投稿一覧ページにコメント機能を追加する
・コメントはUserと紐づいてはいない仕様にしています
（説明が少なくて恐縮ですがお許しください）

##コメント機能作成
###コメントモデルを作成する
作成するカラムは
user_id
content
topic_id
を用意します。


```ターミナル
$ rails g model comment user_id:integer content:text topic_id:integer
```
```
rails db:migrate
```


###アソシエーションの追加（モデルの関連付け）
コメントと投稿の関係は以下のようになります。
・Commentは１つのTopicを持っている
・Commentは１つのUserを持っている
・Topicは複数のCommentを持っている
という関連を持っています。

ですので、Commentモデルに「belongs_to」、Topicモデルに「has_many」を以下のように追加します。

```app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :topic
  belongs_to :user
  
  validates :content, presence: true
end
```

```models/topic.rb
  has_many :comments, dependent: :destroy
  has_many :comment_users, through: :comments, source: 'user'
```

###コントローラを作成しルーティングを設定する
```
$rails g controller comments
```

```config/routes.rb
  get 'comment/new'
  #中略

resources :topics do
  resources :comments
  #/topics/:topic_id/comment/newのパスが使用できる
end
```

```controllers/comments_controller.rb
class CommentsController < ApplicationController
  def new
    @comment = Comment.new
    @topic_id = params[:topic_id]
  end
  
  def create #コメントを登録する
    @comment = Comment.new #コメントのインスタンスを作成
    @comment.topic_id = params[:topic_id] #記事番号をパラメータから受け取る
    @comment.content = params[:content] #コメントの内容をパラメータから受け取る
   
    if @comment.save #コメント登録の条件分岐
      redirect_to topics_path, success: 'コメントに成功しました' 
    else
      flash.now[:danger] = "コメントに失敗しました"
      render :new
    end
  end
end
```



###リンクの追加
今回は投稿一覧ページの投稿からコメントページへと遷移できるようにします。コメントアイコンを用意してリンクを貼ります。

```erb:topics/index.html.erb
<%= link_to new_topic_comment_path(topic_id: topic.id), method: :get do %>
　<%= image_tag 'icons/comment.png', class: 'topic-index-icon' %>
<% end %>
```

###コメント投稿のページ作成
```erb:views/comments/new.html.erb
<div class="topic-new-wrapper" >
  <div class="container">
    <div class="row">
      <div class="col-md-6 col-md-offset-3">
        <h1 class="text-center">Add Comment</h1>
        <%= form_with url: '/topics/' + @topic_id.to_s + '/comments' ,local: true do |f| %>
          <div class="form-group">
            <%= f.label :content %>
            <%= f.text_area :content, class: 'form-control' %>
          </div>

          <% if logged_in? %>
            <%= f.submit 'コメント送信', class: 'btn btn-black btn-block' %>
          <% end %>
        <% end %>
      </div>
    </div>
  </div>
</div>
```

##作成結果
コメント追加ページ
![スクリーンショット 2019-09-29 23.31.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404519/b975c263-9678-3ca0-6f00-9947f26bf48c.png)

記事投稿一覧ページ
![comment_function.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404519/307f6db2-5103-a83f-3e30-a5c0021a3679.png)

拙い記事で恐縮ですが、何かの参考になればと思います。
間違いや認識違い等ございましたらご指摘くださればと思います。
RaspberryPIにてFlatのテンプレート設定【OSJS編】

#■Flatのadminログイン
まだRaspberryPiにFlatがインストールされてない方は下記の記事からインストールしてみてください。
https://qiita.com/xiger78/items/cd6b204b6b7c8b6313ea

>Flatのログインアドレス

http://[raspberrypi ip address:9000]
例)http://xiger.ipdisk.co.kr:9000
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/22445be7-9f75-a3fe-3401-8c26ec2d4caa.png)

>ログイン後の初期ページ

私の場合は、RaspberrｙPiの公式OSではなくDietPiのOS環境からインストールしましたので、
NameがDietPiと表示されてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/a6f5576f-f3c8-881b-6cc5-2bbd1461b156.png)

>App Templatesメニューの表示

ここで使ってみたいテンプレートを選んで必要な必須情報を設定するとすぐ使えます。
まだ細かく設定することになっていますが、いつか改善されると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/ee392e0d-5846-5405-4e54-342c2a863b37.png)
下記の情報を入力します。
IPアドレスはRPIのIPアドレスを入力してください。
本来は未入力でもデフォルトでRPIのIPアドレスに設定されると聞きましたが、
以前できなかったので、一応入れるようにしました。

※IPアドレスを未入力で進んでみてください。それで問題ないならここの入力は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/52107d98-0fec-b405-974a-220388d3bbe7.png)

Createボタンをクリックしてください。

>OSJSへアクセス

下記のURLより確認できます。
http://xiger.ipdisk.co.kr:8000

実行された画面のイメージです。
各アプリはこちらで実行してみた結果です。
面白いですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/0658da32-1658-3ea9-9dc9-dbc686a8d571.png)

>一言

Flatより提供されているテンプレートでこんなイメージもありましたね。
ブラウザから起動されるOS!!!
RPIより起動も早いです。でも使う道が。。。＞。＜
今度はRPIに直接TVを繋げておいてKODIを実行して確認してみましょう。
すでにFlatをインストールしている方なら試してみてください。
これも面白いです。W

>公式サイト
http://flat.wednus.com/home
試し割り法による素因数分解

## 概要
素因数（prime factor）とは、ある自然数の約数となる素数のことです。また素因数分解 (prime factorization) とは、自然数を素因数の積の形で表すことを指します。例えば360を素因数分解すると、$2^3$ × $3^2$ × $5^1$と表すことができます。本記事では2以上の自然数の素因数を試し割り法で列挙する手法を紹介します。

## 方針
基本的な考え方としては、与えられた2以上の自然数nに対して、nより小さい数で割り切れるかどうかを順番に確かめることで素因数判定を行っていきます。nを割り切る素因数を見つけた際、その素因数の累乗でも割り切れるかどうかも同時に確認しておくと効率的です。素因数候補として確かめるべき値の範囲は、2以上$\sqrt{n}$以下で十分です。



## 実装例
```python:
# Return a list of the prime factors for a natural number bigger than 1
def trial_division(n):
    if n < 2:
        return []
    
    prime_factors = []
    
    for i in range(2, int(n**0.5)+1):
        # nがi（の累乗）で割り切れるかを調べる
        while n % i == 0:
            # nがiで割り切れる場合、iを素因数としてリストに追加する
            prime_factors.append(i)
            # nをiで割った商で更新しておく
            n //= i
    # nの平方根より大きい素因数が存在する場合
    if n > 1:
        prime_factors.append(n)
    
    return prime_factors

n = int(input())
print(trial_division(n))
```

## 実行結果

```
# 入力
12
# 出力
[2, 2, 3]

# 入力
100
# 出力
[2, 2, 5, 5]

# 入力
600851475143
# 出力
[71, 839, 1471, 6857]
```

## 約数の列挙
約数はある整数を割り切ることのできる整数です。整数Nの約数とは、整数Nの素因数またはそれらを掛け合わせたものになるため、上記の素因数分解を利用して、整数Nの約数を列挙することもできます。
※この方法以外にも、単に1以上√N以下の整数で割り切れるか調べることで約数を列挙することもできます

### 実装例
```python
import itertools

# nの約数のSetを返す
def get_divisors(n):
    # nの素因数のリストを得る
    prime_factors = trial_division(n)
    divisors = set()

    for i in range(1, len(prime_factors)+1):
        # 素因数をi個選んだ時の組み合わせ
        combinations = list(itertools.combinations(prime_factors, i))

        # 素因数を掛け合わせて約数を得る
        for comb in combinations:
            divisor = 1
            for num in comb:
                divisor *= num
            divisors.add(divisor)

    # 1を約数として加える
    divisors.add(1)
    return divisors
```



## 参考
[試し割り法(Wikipedia)](https://ja.wikipedia.org/wiki/%E8%A9%A6%E3%81%97%E5%89%B2%E3%82%8A%E6%B3%95)
[Pythonで素因数分解（試し割り法）](https://note.nkmk.me/python-prime-factorization/)
[Pythonで競技プログラミング 〜基本的なアルゴリズム 〜](https://qiita.com/knakajima3027/items/b871631b8997a6d67223#%E7%B4%A0%E5%9B%A0%E6%95%B0%E5%88%86%E8%A7%A3)
[[Python]試し割法で素因数分解する](https://qiita.com/kageyasai2/items/48ef81f39b4e31c6d396)
[git] submoduleの削除、再追加について

# はじめに
gitのsubmoduleを使う機会があったのですが、間違えて追加して再追加するときに、いろいろ戸惑ったので、まとめました。

# submoduleの追加
```zsh
$ git submodule add サブモジュール化したいリポジトリ パス/名前指定
```
submoduleの追加は上記のコマンドで行えます。
パス/名前指定を空白にすると、現在のディレクトリにリポジトリ名のままで作成されます。

# submoduleの削除
```zsh
$ git submodule deinit -f 追加したサブモジュール
$ git rm -f 追加したサブモジュール
$ rm -rf .git/modules/追加したサブモジュール 
```
submoduleの削除は上記のコマンドで行えます。
忘れがちなのが、`.git/modules/追加したサブモジュール`ですね。これを消し忘れると、ローカルに存在すると言われ再追加ができなくなります。

# submoduleの再追加
```zsh
$ git submodule add サブモジュール化したいリポジトリ パス/名前指定
```
再追加はsubmoduleの追加と同じコマンドです。
これがうまくいかない場合正しく削除できていないので、確認しなおしましょう。

# まとめ
再追加できないときは、`.git/modules/追加したサブモジュール`の消し忘れの可能性があります。
vscodeではここの差分がでないので注意です。
VScodeで一括インデント(windows)

#下のコマンドを打ちましょう#

`shift+Alt+f`

これを打てば終わりです.
何回も調べるの面倒なのでメモしました.
無駄な時間は減らしたいものですね.

#参考#
[https://www.ksakae1216.com/entry/2016/11/22/063000](https://www.ksakae1216.com/entry/2016/11/22/063000)
Unite Tokyo 2019行って個人開発で役立てたいなと思ったこと

# 前置き
- Unite Tokyo 2019に会社のお金で行かせていただきました
- 業務の話は社内にシェアするとして
- 本記事は個人開発（超小規模）ゲームに関しての話
- 業務ではUnity3年くらい離れていたので、今更かよ……という内容が一部含まれてるかも……

# 個人的に役に立てたいと思ったお話（上から優先度高）
## UnityTestRunner
### 役に立ったと思ったポイント
- 個人開発だからこそ効率良くテストしないと……と単純に思った
- 導入不要。menuからすぐ始められそう
- Editorモードだと実行早そう
- テストコードは保守が大変になるので、ある程度粒度は落とす
- *テストコードはガラスのように壊れやすいものではなく、竹のようにしなやかで柔軟性の高いものを目指すべき*

### 講演資料
[Unity Test Runnerを活用して内部品質を向上しよう](https://learning.unity3d.jp/3300/)

### 参考資料
[Unity使いは全員Unity Test Runnerを使え！爆速のトライ＆エラー環境だぞ！](https://qiita.com/su10/items/67a4a90c648b1ef68ab9)

## サーバサイドサービス（BaaS）
大きく二つ紹介されていたので、お話聞きました。

- [PlayFab](https://azure.microsoft.com/ja-jp/services/playfab/)
- [Game Server Serives(GS2)](https://gs2.io/)

### 役に立ったと思ったポイント
- どちらもサーバサイド側のゲームに必要な処理群（ログイン処理/PlayerData管理 等々）を用意してくださってるので、UnityからはAPI叩くだけ楽々導入できそう
- PlayFab側は機能制限ありの完全無料プランもあるとのことで、使うとしたらまずはそちらを使ってみたい
- GS2は1APIリクエストごとに0.02円（でもHPみるとFreeプランありそう……？）

### 講演資料
- [Unity + PlayFab ではじめる新しいゲーム運用　～LiveOpsの始め方～](https://learning.unity3d.jp/3296/)
- [Game Server Services ではじめる サーバー開発運用しないゲーム開発](https://learning.unity3d.jp/3241/)

## Visual Effect Graph

### 役に立ったと思ったポイント
- GPUで実行されるので早いとのこと
- ノードベースで定義できるようになり、作りやすそう

### 講演資料
[パーティクルエフェクトが超進化する！ Visual Effect Graph の基礎と応用](https://learning.unity3d.jp/3276/)

## ハイパーカジュアルゲームのお話
### 役に立ったと思ったポイント
- パッと見てそれが何をするものかを容易に想像できるように、アフォーダンスを意識
- 子ども心をくすぐるようなものを意識（むずかしいぃ……）
- とりあえずリリースしたものでも、後から化けるケース（思いつきによる機能改修）もあるから諦めないこと
- [SAY GAMES](https://saygames.by/)さんのゲームはめっちゃ参考にされたとのこと

### 講演資料
[データよりも面白さ？ 芸者東京に学ぶ！グローバルでヒットするハイパーカジュアルゲームの作り方](https://learning.unity3d.jp/3336/)

## Unity Servicesの話
### 役に立ったと思ったポイント
- Cloud Diagnostics（クラッシュレポート＆ユーザの任意のレポート管理）が講演の中で唯一フリーで手軽に使えそうだった。（ただしフリーの範囲だと、25件のレポートしか保存できない）

### 講演資料
[開発から運用まで、デベロッパーをサポートするUnity Services](https://learning.unity3d.jp/3272/)


## その他
- Game Developers Meeting
    - 最新の技術や情報をシェアするDeNAさん主催のゲームクリエイター向け勉強会というものを定期的に開催されているとのこと（渋谷じゃなかったら行きたかったという話）
- [IRIAMさん](https://iriam.com/)のデモアプリ
    - 画像一枚から、機械学習を用いて、瞬き/口パクの差分を生成して、カメラで自分の表情をsyncする技術がめっさ感動しました。アプリ的にはVtuberとのコミュニケーションツールとのことでした。自分でも１枚絵から自動でLive2Dのごとく動くものが生成できるものを作りたいという願望だけが生まれた

# 感想
- 色々進化していてびっくりした
- 個人開発におけるテストについても考えさせられた  
（まだ未公開のゲーム開発において、依頼主にほぼテスト丸投げしてしまった経緯もあり、すみませんでしかなかった）
- サーバサイドはもはや趣味で開発しない世界がありそうで、個人開発的にはすごく嬉しいお話
[Android]常にフルスクリーンにしておきたい時のTIPS

# 目的
- ナビゲーションバーが邪魔で基本常に非表示にしておきたい

# 方法
 
以下の処理を実装する。

```MainActivity.kt
override fun onStart() {
     super.onStart()
     hideSystemUI()    
}

fun hideSystemUI() {
     window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            or View.SYSTEM_UI_FLAG_FULLSCREEN
            or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
}

override fun onWindowFocusChanged(hasFocus: Boolean) {
    super.onWindowFocusChanged(hasFocus)
    if (hasFocus) hideSystemUI()
}
```

## View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
「外部からスワイプしないとナビゲーションバーが出てこない上に、出てきたナビゲーションは半透明になる」というモードを指す。
なお、ナビゲーションバーは普通がいいという場合はSYSTEM_UI_FLAG_IMMERSIVEを使う。

## View.SYSTEM_UI_FLAG_FULLSCREEN
ステータスバーを非表示にする。

## View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
ナビゲーションバーを非表示にする

## View.SYSTEM_UI_FLAG_LAYOUT_STABLE
ナビゲーションバーが非表示になった時にレイアウトが崩れないようにする。

## View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
ステータスバーが非表示になった時にレイアウトが崩れないようにする。

# onWindowFocusChangedでhideSystemUIする理由
これがないとDialogを表示するタイミングで再度ナビゲーションバーが表示されてしまう。

# それでもDialogFragment表示時にナビゲーションが表示されてしまう場合
私は表示されしまったので以下の実装を行い対処した。
このためにBaseDialogFragmentができてしまったのであまり良い方法ではないかも。

 ```BaseDialogFragment.kt
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        hideSystemUI()
    }

    // ソフトウェアキーの非表示
    private fun hideSystemUI() {
        dialog?.window?.setFlags(
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        )
        activity?.window?.decorView?.systemUiVisibility?.let {
            dialog?.window?.decorView?.setSystemUiVisibility(it)
        }
        dialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
    }
```


# 参考

全画面モードを有効にする
https://developer.android.com/training/system-ui/immersive
Nuxt.jsでloadingにプログレスバーを使う

Nuxt.jsで構築したサイトで、ページ読み込み時にプログレスバーを表示させたかったが、詰まったのでメモ。
https://ja.nuxtjs.org/api/configuration-loading/

## 1. modeをspaにする

自分の場合、ここで詰まっていた。`nuxt.config.js`で、modeを「spa」にしておく必要がある。

```js:nuxt.config.js
export default {
  mode: 'spa',
  /* 省略 */
```

## 2. $loadingメソッドを呼び出す

あとは、公式サイトと同じように、$loadingメソッドを呼び出す。

```vue:index.vue
<template>
  <!-- 省略 -->
</template>

<script>
  export default {mounted() {
    this.$nextTick(() => {
      this.$nuxt.$loading.start()
      setTimeout(() => this.$nuxt.$loading.finish(), 1000)
      })
    }
  }
</script>
```

## 3. カスタマイズ

プログレスバーの色や高さなどを調整したければ、それも`nuxt.config.js`上で行う。

```js:nuxt.config.js
export default {
  mode: 'spa',
  /* 省略 */
  /*
  ** Customize the progress-bar color
  */
  loading: { color: 'red' },
```
[Unity] Project Tinyでのミニゲーム作成 - UI

# はじめに
Project Tinyでミニゲームを作成時に使用した機能やトラブルを説明していきます。
今回はUIについてです。
リポジトリは[こちら](https://github.com/chocolate-ice-cream/TinyRun)。

### UIの作成方法

uGUIと基本的には同じです。
RootとなるEntityにUICanvasとRectTransformを設定し、
その子としてスプライトやテキストを配置していきます。
![UI.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490737/cf586521-50de-086e-a5aa-a40d7c0dc4e8.jpeg)

### ボタン

ボタンを作成するために下記のコンポーネントが必要になります。

- Sprite2DRenderer
- RectTransform
- Button
- PointerInteraction
- Sprite2DRendererOption
- ColorTintTransition

![BUtton_Inspector.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490737/8174934c-3b29-6e34-417f-0b72ba5c986c.jpeg)

#### ボタンの実装

HierarchyでEntityに上記の必要なコンポーネントを設定し、
BUttonのsprite2DRendererにボタン画像のSprite2DRnedererのEntity、
transitionにColorTintTransitionのEntityを設定すればいいだけです。
必要に応じてColorTintTransitionの各色を変更してください。
あとはシステム内でPointerInteractionのclickedからクリックしたかどうか判定します。

今回の場合だと、ゲームオーバー時のリトライボタンで使用しています。

```C#:GameOverSystem.cs
// リトライボタンのクリック
Entities.WithAll<RetryButton>().ForEach((Entity entity, ref PointerInteraction pointerInteraction) =>
{
    // クリックされたらリトライを行う
    retry = pointerInteraction.clicked;
    pointerInteraction.clicked = false;
});
```
![GameOver_Modified.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490737/54f13c56-7658-eb80-b38e-922699536efd.jpeg)

### テキスト

テキストを作成するために必要なコンポーネントです。

- RectTransform
- Text2DStyleBitmapFont
- Text2DRenderer
- Text2DStyle
- TextString
- LayerSorting

![Text.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490737/d19b4928-ddc9-ed7c-95ba-8bcca02e1a7d.jpeg)

#### テキストの実装

Entityに上記の必要なコンポーネントを設定します。
各コンポーネントのフィールドを下記のように設定してください。

**Text2DStyleBitmapFont**
font : Text Mesh Proのフォントアセット

**Text2DRenderer**
style : Text2DStyleのEntity

**Text2DStyle**
color : フォントカラー
size : フォントサイズ

**TextString**
Value : 描画する文字列

**LayerSorting**
layer : レイヤー
order : レイヤー内での描画順(大きいほど手前になる)

タイトル画面、スコア表示、ゲームオーバー表記はこの方法で実装しています。
![Title.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490737/71d954ec-87b3-1666-0762-2219ff572a98.jpeg)
SwiftUIにおけるscaledToFill()とかscaledToFit()とかaspectRatio(_:contentMode:)等の使い分け

主にImageのリサイズの時に、FillとかFitとかaspectRatioとか色々あって何を使えばよかったんだっけ？となるので備忘録としてまとめました。

そもそも…
##Fillとは？
枠内いっぱいに表示されるように拡大縮小されるので、はみ出した分の左右もしくは上下は切り取られる。

##Fitとは？
枠内からハミ出さないように拡大縮小されるので、左右もしくは上下に空白ができる可能性がある。

##SwiftUIにおけるメソッドの違いは？
###scaledToFill()
```swift:使用例
Image("SampleImage")
    .resizable()
    .scaledToFill()
```
[scaledToFill()の公式ドキュメント]
(https://developer.apple.com/documentation/swiftui/tupleview/3277975-scaledtofill)
アスペクト比を維持しながら、親に合わせてこのビューをスケーリング
枠全体を覆うように拡大縮小されるので、はみ出した分の左右もしくは上下が切り取られる可能性がある。
`aspectRatio(nil, contentMode: .fill)` と同一効果。

###scaledToFit()
```swift:使用例
Image("SampleImage")
    .resizable()
    .scaledToFit()
```
[scaledToFit()の公式ドキュメント](https://developer.apple.com/documentation/swiftui/tupleview/3277977-scaledtofit)
アスペクト比を維持しながら、親に合わせてこのビューをスケーリング
全体が表示されるように拡大縮小されるので、左右もしくは上下に空白ができる可能性がある。
`aspectRatio(nil, contentMode: .fit)` と同一効果。

###aspectRatio(_:contentMode:)
```swift:使用例
Image("SampleImage")
    .resizable()
    .aspectRatio(0.5, contentMode: .fit)
```
[aspectRatio(_:contentMode:)の公式ドキュメント](https://developer.apple.com/documentation/swiftui/image/3269594-aspectratio)
第一引数で、幅と高さの比率を指定する。 (e.g. 0.75)
`contentMode` では、`fit` or `fill` を選択する。

以上、他にまた類似の指定方法があって迷いそうだったら追加したいです。

間違い等あれば教えていただければ嬉しいです！
【Lambda】zipファイルの圧縮解凍サンプル【nodejs】

# やること
Lambdaで
・圧縮:S3バケットにzipファイルを作成する
・解凍:S3バケットに格納されている、zipファイルから中身を取り出す

# 手順概要
+ node-zip が動くようにLayerファイル（zip)を作る
+ LambdaにLayerファイルをアップロードする
+ Layerを使って関数を作る

## Layerファイルを作ります
クライアントで作業します。
クライアントnodejsが動くようにして、外部モジュールを入れたものをzipしてaws管理コンソールから入れるだけ

例えば、amazon linux2で作業する場合は…

```bash
curl --silent --location https://rpm.nodesource.com/setup_12.x | sudo bash -
yum install -y nodejs 
mkdir nodejs
cd nodejs
npm init -y
npm install -y node-zip
cd ..
zip -r layer.zip nodejs/.
```

## zipをLambdaに登録します
AWS管理コンソールで作業します。
![スクリーンショット 2019-09-29 21.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/f53fd022-5afb-598f-2bb1-a643a61a9296.png)
「レイヤーの作成」で、先ほど作ったLayer.zipファイルを入れれば終わりです。

## 関数の準備
Layersを選択して
![スクリーンショット 2019-09-29 21.48.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/0d9c5d96-74ea-a17e-5444-71e7f9708b5a.png)
「レイヤーの追加」押下で先ほど作ったレイヤーが出てきますので、選択。
![スクリーンショット 2019-09-29 21.48.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/15aff369-8503-a6fd-aad2-6a8fb8e48d0d.png)

## 関数の作成
下のコードを先頭あたりに入れて、実行してみます。エラーが出なければレイヤーが効いています。

```javascript
const node_zip = require('node-zip');
```

ちなみに、Layerを外すと、上記コードはエラーになります。

### 解凍
S3に置いてあるzipファイルを解凍します。
IAMで、s3:GetObject が必要です

```javascript:抜粋
const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01' });
const node_zip = require('node-zip');

s3.getObject({Bucket:s3bucket, Key:s3object},function(err,data) {
    if (err) {
       return;
    } else {
       var zip = new node_zip(data.Body, {base64: false, checkCRC32: true});
       for (var fileinzip in zip.files) {
           let pKey="";
           let pBody="";
           for (var para in zip.files[fileinzip]) {
               if(para=="name")   pKey = zip.files[fileinzip][para];
               if(para=="_data") pBody = zip.files[fileinzip][para];
           }
           // pKey にファイル名、pBodyにファイル内容が入っている
           // putObjectするとか。。
        }  // 次のファイル
    });
```


### 圧縮
圧縮対象のファイルはあらかじめ準備する必要はないです。
ファイル名とファイル内容があれば良いです。

IAMで、s3:PutObject が必要です

```javascript
const node_zip = require('node-zip');
const zip = new node_zip();
            
zip.file("ファイル名１", "内容文字列１");
zip.file("ファイル名2", "内容文字列２");
zip.file("ファイル名3", "内容文字列３");
	        
let zipContent = zip.generate({base64: false,compression:'DEFLATE'});
var buf = Buffer.from(zipContent, 'binary');
	
let param ={ Bucket:bucket, Key : "hoge.zip", Body: buf, ContentType: 'application/zip'};
s3.putObjct(param);

```
paizaの超初級問題で挫折したが、なんとか問題が解けるようになった方法

###簡単な紹介

2019年5月からRubyの勉強を始めた初心者です。
処理や出力はできるのですが、最初の受け取りにかなり苦戦したので
初心者が受け取りで躓かないように、そして挫折しないように書いておきます。

###今回挫折しかけた問題

足し算
半角スペースで区切られた２つの正の整数を足し算して出力する問題です。


###解くためにやったこと

・受け取り方法をGoogle検索で調べる
・メソッドの意味や使い方をGoogle検索で調べる
・メソッドを使うことでどのような処理をされているのか調べた

検索は『やりたい処理　メソッド　Ruby』などで検索をかけて地道にコードに
埋め込んで、実行してみて思い通りの動きをするのか？また、書き方はあっているのかなど、まずは色々試してなんとか動くように必死で検索してトライしてみました。

---

練習問題は公開OKとのことなので、初心者の方の参考に残しておきます。
もっと良い書き方や処理の早い方法などあると思いますが、動くことを第一優先に下記のメソッドとコードを書いて通過することができました。


使用したメソッド
gets 
"文字\n"
文字列と改行文字を受け取り

chomp
\n(改行)を取り除く

split("")
文字列を分割して配列にする

map(&:to_i)
要素を一括で数値に変換

sum
配列の要素を合計

```
n = gets.chomp.split(" ").map(&:to_i).sum

p n
```
---
最後に、私は検索しまくってなんとか自力で解けたのですが、基礎知識がなくてだいぶ苦しみました。しかし、調べていく中で徐々に知識がついていき解けるようになりました。この記事を参考にコピペではなく、実際に手を動かして色々やってみるといつの間にか成長することができるのだと実感しました。参考になれば嬉しいです。
z/Db2のCOPYユーティリティでハマった話

#z/Db2のCOPYユーティリティでハマった話
メインフレームの現場から離れて４か月。少しずつメインフレームの知識を忘れていると感じたため、自分自身の備忘録として書きます。
結構忘れてきてるから、コードに自信がない・・・

ある朝のことz/Db2のCOPYユーティリティを使用して実行している定期バックアップジョブがabendしてた・・・orz
でも、原因が分からない。それまで普通に動いてたのに・・・
バックアップ容量も見積もって余裕を持たせてるし、バックアップジョブの実行時間にも問題ない。
なのにどうして!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


######原因はz/Db2ユーティリティのTEMPLATEだった
-TEMPLATEユーティリティは各テンプレートに関して、テンプレート名、データ・セットの命名規則、必要な割り振りパラメーターを指定できる。
-なんのこっちゃと思った？例を挙げよう。

以下のような名前のDBとテーブルスペースたちがあったとしよう。
1つ目
DB名：DBTEST1
TS名：TSTEST1
2つ目
DB名：DBTEST2
TS名：TSTEST2

こうしたDB、TSたちに対していちいちデータセット名JCLにべた書きしてを割り振るのは面倒すぎる。それにデータセット名は一意でないといけないから、被りは絶対NG!
そんなこ定期バックアップでいちいち考慮してられっか（怒）
って時にこのTEMPLATEが超便利なんです。

TEMPLATEにはあらかじめDB名やTS名のほかに日付や時間にデータセット名を一意にするためのがある。それらを組み合わせると、

```
TEMPLATE COPYDS DSN &DB..&TS..IC.D&DATE..&UN
         LOCALDDN UNIT SYSDA DSN(COPY001F.IFDY01) SPACE(15,1) CYL 
         DISP(NEW,CATLG,CATLG) 
LISTDEF  LIST1 INCLIUDE DB.ONLDB.*
COPY TABLESPACE LIST1 COPYDDN(COPYDS)
```

こんな感じ。実際に使ってたのはVTLだけどそこは許して・・・。
じゃあ何が悪かったのかというと。

```
TEMPLATE COPYDS DSN &DB..&TS..IC.D&DATE..*&UN*
```
「&UN」の部分。これは、英数字からなるランダムな８文字で、DB2 はこの文字をシステム・クロックから組み込んでくれる。
この数字が当時、偶然GDG(世代管理)データセットの絶対バージョンGxxxxVxxxのランダムな数字を生成してしまった。
ただ、実態はGDGではないからz/OS君が異常を検知してabendしちゃってた。

結局ダサいけど、↓みたいな感じで直した。

```
TEMPLATE COPYDS DSN &DB..&TS...&UN..IC.D&DATE.
```

そこまで考えてバックアップ設計をしないといけないのねって痛感した。
Vue.jsをTypeScriptと使うメモ  -設定-(@vue/cliは使わずに)

# 設定
## 必要なpackageを取得
```
npm install vue-property-decorator
npm install --save-dev typescript webpack webpack-merge
```
## tsconfig(基本的に推奨構成より)
```json
{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "strict": true,
    "moduleResolution": "node",
    "noImplicitAny": true,  // 暗黙のany
    "strictNullChecks": true,  //nullやundefinedを明示するように
    "noImplicitThis": true,
    "moduleResolution": "node",
    // importのpathを./src/...から@src/...に
    "paths": {
      "@src/*": ["src/*"]
    }, 
    "include": [
      "./src/**/*.ts"
    ]
  }
}
```
*includeなどは自分の設定に合わせて…*

## webpack設定
```js:webpack.common.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const webpack = require('webpack')

module.exports = {
  entry: {
    app: ["./src/index.ts"]
  },
  output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "public/js")
  },
  resolve: {
    extensions: [".js", ".ts", ".vue", ".json", ".css"],
    alias: {
      vue$: "vue/dist/vue.esm.js",
      // importのpathを./src/...から@src/...に
      '@src': path.resolve(__dirname, './src')
    },
    modules: ["node_modules"]
  },
  plugins: [
    new VueLoaderPlugin(),
  ]
}
```
### 開発用のビルドと本番用のビルドで分けたりする。(sourcemap出力したり)
```js:webpack.dev.js
// 開発ビルド用
const merge = require('webpack-merge')
const common = require('./webpack.common.js')

module.exports = merge(common, {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        loader: 'vue-loader',
        options: {
          cssModules: {
            camelCase: true
          }
        }
      },
      {
        test: /\.ts$/,
        exclude: '/node_modules/',
        use: [
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [/\.vue$/]
            }
          }
        ]
      },
    ]
  }
})


```
REST APIとHTTPメソッドについてまとめてみた

REST APIは理解しないで使っていそうなので調べてみようと思います。

# [参考：IT用語辞典 e-Words](http://e-words.jp/w/REST.html)

> ・RESTful API(REST API)とは、Webシステムを外部から利用するためのプログラムの呼び出し規約(API)の種類の一つで、RESTと呼ばれる設計原則に従って策定されたもの。RESTそのものは適用範囲の広い抽象的なモデルだが、一般的にはRESTの考え方をWeb APIに適用したものをRESTful APIと呼んでいる。
> ・RESTful APIでは、URL/URIですべてのリソースを一意に識別し、セッション管理や状態管理などを行わない(ステートレス)。同じURLに対する呼び出しには常に同じ結果が返されることが期待される。
> ・また、リソースの操作はHTTPメソッドによって指定(取得ならGETメソッド、書き込みならPOSTメソッド)され、結果はXMLやHTML、JSONなどで返される。また、処理結果はHTTPステータスコードで通知するという原則が含まれることもある。

らしい、、、、
難しいのでゆっくり噛み砕いていく。

# RESTってなに？
Representational State Transfer => REST
って呼ぶらしい。
これってなんなのかというと、
> 分散型システムにおける複数のソフトウェアを連携させるのに適した設計原則の集合、考え方のこと。

だそうです。

# APIってどういうもの？
> 個々のソフトウェアの開発者が毎回すべての機能をゼロから開発するのは困難で無駄なため、多くのソフトウェアが共通して利用する機能は、OSやミドルウェアなどの形でまとめて提供されている。
> そのような汎用的な機能を呼び出して利用するための手続きを定めたもの

共通して利用する機能は呼び出すだけで使えるようにしておけば開発者は楽だよねってものらしい。

つまり、
複数のソフトウェアを連携させる上で共通して利用する機能は、まとめて用意しとけば開発者はらくだよねってことか。

# ステートレスってなに？

> システムが現在の状態を表すデータなどを保持せず、入力の内容によってのみ出力が決定される方式。同じ入力に対する出力は常に同じになる。

作成・取得・更新・削除の処理があったとして、
各処理ごとURLを変えるんじゃなくてHTTPメソッドで分けて１つのURLでやったほうががいいよねってことかな。

利用者の負荷が減るのかとおもいます。

# HTTPメソッドってどんなものがあるの？

HTTPメソッドの種類は以下のようなものがある。

| メソッド  | 意味 |
|:--|:--|
| GET  | URIで指定した情報を要求。URIがファイル名のときはそのファイルの中身を、プログラム名のときはそのプログラムの出力を返す |
| POST  | 　クライアントからデータを（名前と値）のセットで渡す。フォームデータを送るときなどに使用 |
| PUT  | URIで指定したサーバ上のファイルを置き換える |
| DELETE  | URIで指定したサーバ上のファイルを削除する |
| HEAD  | GETと同じだがHTTPヘッダのみを返す|
| OPTIONS  | リソースがサポートしているメソッドの取得 |
| TRACE  | サーバが受け取った要求行とヘッダ行をそのまま送り返す |
| CONNECT  | プロキシ動作のトンネル接続への変更 |

REST APIで使われるのはGET、POST、PUT、DELETEなんですって。
作成・取得・更新・削除するシステムがあったとして
各処理をHTTPメソッドを使用し、取得なら「GET」、作成なら「POST」、更新なら「PUT」、削除なら「DELETE」のようにHTTPの一般的なリクエストメソッドを使用するそうです。



#参考サイト
RESTful APIにおける基本的な考え方
https://developer.ntt.com/ja/blog/92ae9651-557e-482c-8f53-59cbce049c02

0からREST APIについて調べてみた
https://qiita.com/masato44gm/items/dffb8281536ad321fb08

REST APIとは？ – API設計のポイント！
https://wp.tech-style.info/archives/683#toc12

RESTful APIとは何なのか
https://qiita.com/NagaokaKenichi/items/0647c30ef596cedf4bf2

APIとは
http://e-words.jp/w/API.html

HTTPメソッド(CRUD)についてまとめた
https://qiita.com/r_fukuma/items/a9e8d18467fe3e04068e
Error解析&Node.js&google-home-notifierでGoogle Homeに喋らせよう

Node.jsを使って、Google Homeに喋らせました。
その際詰まったところなどを解説します。

こちらのサイトを参考にnode.js作成
https://qiita.com/SatoTakumi/items/c9de7ff27e5b70508066


###0.node.jsのバージョン

```
$ npm -v
  6.9.0
$ node -v
  v10.16.0
```

###1.google-home-notifierをインストール

```
$ npm init
$ npm install google-home-notifier
```
※npm initはデフォルトでいい場合は全てEnterする。

###2.node.jsでサンプルコードを書く
```node.js:sample.js
   //ライブラリ参照
   var googlehome = require('./node_modules/google-home-notifier');
   // 言語設定
   var language = 'ja';
   // GoogleHomeのIPアドレスに書き換えてくださいね
   googlehome.ip('0.0.0.0',language);
   // 第一引数を自分のもっているGoogleHomeの名前に書き換えてくださいね
   //googlehome.device('googlehome', language);
   // Google Homeにしゃべって欲しい文章をここに記入してくださいね
   var text = 'こんにちは';
   // メイン処理
   try {
       googlehome.notify(text, function(notifyRes) {
           console.log(notifyRes);
       });
   } catch(err) {
       console.log(err);
   };
```
###3.実行
```
$ node sample.js
```

これでいけるはず...

```
Error: get key failed from google
```
###はまりました...orz

色々調べてこちらの対策を発見:[pull request](https://github.com/zlargon/google-tts/pull/14/commits/b5d1b8561fc1a34fac1e66bb280cd153d1a31044"pull request")
修正するも、動かない...。
調べても解決に至らずだったので、

※現在はnode_modules/google-home-notifier/package.jsonの
google-tts-apiのバージョンを上げる事で対応可能なようです。
詳細は下記コメント参照。
sienoriさんありがとうございました。
仕組み的な意味で意味で記事はそのまま残します。

###google-home-notifierのソースコードを確認してみる事にしました。

気になるところを発見！

```node.js:node_modules/google-tts-api/lib/key.js
var match = html.match("TKK='(\\d+.\\d+)';");
if(!match) throw new Error('get key failed from google');
```

htmlが何かのhtmlを読んでmatchさせているが失敗している。
そして、恐らく、それが、

```node.js:node_modules/google-tts-api/lib/key.js
var host = 'https://translate.google.com';
```

というわけで、
https://translate.google.com/

のhtmlを解析していきます。
![スクリーンショット 2019-09-29 22.09.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105573/f9f1c0d9-ff46-d7df-1b7c-8aedef7343a0.png)

1.右クリックで**「ページのソースを表示」**
2.command+fで「TKK」検索
3.気になる内容が引っかかる。

```:view-source:https://translate.google.com/
tkk:'436044.375069185'
TKK = mobileWebapp.tkk
```

そして、ソースコードと照らし合わせてみると、

```node.js:node_modules/google-tts-api/lib/key.js
var match = html.match("TKK='(\\d+.\\d+)';");
```

恐らく以前は、
TKK='(\\d+.\\d+)'; //つまり、TKK=436044.375069185;数字は任意

と書いてあったけど、
今は、
https://translate.google.com/　
のhtmlコードが変わってしまい

```:view-source:https://translate.google.com/
tkk:'436044.375069185',
TKK = mobileWebapp.tkk
```

となり、TKK='(\\d+.\\d+)';にmatchしなくなった。
そのため、tkk:'436044.375069185',にmatchするように修正。

```node.js:node_modules/google-tts-api/lib/key.js

//var match = html.match("TKK='(\\d+.\\d+)';");
var match = html.match("tkk:'(\\d+.\\d+)',");
```

動きました！

ちなみにソースコードは[こちら](https://github.com/CoffCookie/googlehome.git "こちら")にupしています。

###これで喋らせる事ができましたが...
日本語を喋るけど、発音が英語っぽい日本語になる問題が発生。
修正方法：https://qiita.com/sohsatoh/items/69bcad398ffae11359f0

この部分を

```node.js:google-home-notifier.js
var ip = function(ip) {
    deviceAddress = ip;
    return this;
}
```

こう直すと直るようです。

```node.js:google-home-notifier.js
var ip = function(ip, lang = 'ja') {
    deviceAddress = ip;
    language = lang;
    return this;
}
```

完成！
PythonとOpenCVでリアルタイム顔検出する（Windows10）

#環境
Windows 10 Pro
Python 3.7.4（Anaconda）
OpneCV 4.1.1

#行程
1. Anacondaをインストール
2. Anaconda Navigatorで仮想環境を作成
3. 作成した仮想環境にOpenCVをインストール
4. 作業ディレクトリの作成
5. 顔のカスケードファイルをダウンロード
6. ページを参考にコードをコピペ
7. カスケードファイルの場所を指定する（必須ではない）

##1.Anacondaをインストール
適当にググってやりました。

##2.Anaconda Navigatorで仮想環境を作成
コチラの記事を参照のこと。
[Anaconda navigatorで仮想環境を作ってターミナルを開く(Windows10)](https://qiita.com/Noebgmo/items/28c346309a3e3c2f0ab2) 

##3.作成した仮想環境にOpenCVをインストール
コチラのページを参考にさせていただいた。
[pip で OpenCV のインストール](https://qiita.com/fiftystorm36/items/1a285b5fbf99f8ac82eb) 

Anaconda Navigatorで仮想環境のターミナルを開く（緑の▶をクリック）。

```python:うまくいかなかった

pip install opencv-python
```
でインストールしてみる。

~~ソースコードを実行したら 「import cv2 できません。」と言われた。~~

***追記 2019/10/15***
***上のコードでエラー出なかった。仮想環境が悪かったのかな？***

以下のコードでインストールしなおした。
（気分で仮想環境から作りなおした）

```python:うまくいった
python -m pip install opencv-contrib-python
```

##4. 作業ディレクトリの作成
適当に作成する。

##5.顔のカスケードファイルをダウンロード

[GitHubのOpenCVのページ](https://github.com/opencv/opencv) からダウンロードできる。

適当な場所に保存する。

必要なカスケードファイルを作業ディレクトリの中のフォルダにコピーして使用する。
（私はこの方が管理がしやすい。必須ではない）
（これをしない場合は作業7も不要かと思う）

##6.ページを参考にコードをコピペ
このページ( [Python, OpenCVで顔検出と瞳検出（顔認識、瞳認識）](https://note.nkmk.me/python-opencv-face-detection-haar-cascade/) )の下の方にある、
「カメラを使ってリアルタイムで顔検出と瞳検出」を参考にさせていただいた。

##7. カスケードファイルの場所を指定
ソースコード3,4行目に記載してあるカスケードファイルの場所を、
実際の保存場所と一致させる。


#結果

カメラ画像の顔にリアルタイムで四角形を表示することができた。

（動作画像はすっぴんなので載せません）
Nuxtから利用したChart.jsでイベントを発行する

# はじめに
以前書いた[NuxtでChart.jsを利用する](https://qiita.com/kattoon/items/a76caa684261956c900b)で実装した`doughnut-chart`にて、hover時とレンダリング完了時にそれぞれイベントが発行されるよう改修しました。

# hoverイベントを発行
`doughnut-chart`はChart.jsの`Doughnut Chart`を利用しており、hover時に処理を実行するためには`options.onHover`にコールバック関数を渡すことで可能となります。
https://www.chartjs.org/docs/latest/general/interactions/events.html

そのため、`doughnut-chart`ではコールバック関数をコンポーネントのメソッドとして実装し、renderChart時にonHoverプロパティの値として定義することとしました。

```javascript:plugins/vue-chartjs.js
  // ・・・省略
  mounted() {
    this.renderChart(this.chartData, { onHover: this.hover, ...this.options });
  },
  methods: {
    hover: function(point, event) {
      const element = event[0] || null;
      if (element === null) {
        return;
      }
      this.$emit('hover', element._index);
    },
  },
});
```

実装した`hover`メソッドでは2つの引数`point`と`event`を受け取り、これらにはそれぞれ`MouseEvent`と`ChartElement`が渡されます。
`ChartElement`にはlabelやvalueをはじめとするChart情報が含まれており、今回はその中の`index`情報を利用することとしました。
`this.$emit`にてカスタムイベントを発行することが可能なため、hoverイベントを発行し`index`を返却しております。

```vue:plugins/vue-chartjs.js
<template>
  <v-container fluid>
    <doughnut-chart :chart-data="chartData" :options="chartOptions" @hover="hover"/>
    // ・・・省略
  </v-container>
</template>

<script>
  // ・・・省略
  methods: {
    // ・・・省略
    hover: function(index) {
      console.log(index);
    },
  },
};
</script>
```
`doughnut-chart`にてhoverイベントを発行するよう実装したため、呼び出し側からは上記のようにevent handlerをメソッドにて実装し、`@hover="event handler名"`にてイベントを受け取ることが可能となります。

# renderedイベントを発行
次にレンダリングが完了した際にイベントを発行するよう`doughnut-chart`を改修します。
Chart.jsの`Doughnut Chart`では、`options.animation.onComplete`にコールバック関数を渡すことでレンダリング完了時に処理を実行することが可能です。
https://www.chartjs.org/docs/latest/configuration/animations.html

そこでhoverイベントの発行時と同様に`options`プロパティにコールバック関数をdefault値として渡すことで実装しようと試みたのですが、`onComplete`は`animation`オブジェクトのプロパティであり一つネストした階層に定義する必要があるため、新たに算出プロパティ`optionsMergedDefaultEvents`を実装し、そこでdefaultのイベントをpropsで渡された`options`にmergeするようにしました。

```javascript:plugins/vue-chartjs.js
  // ・・・省略
  computed: {
    optionsMergedDefaultEvents: function() {
      let options = this.options;
      const animation = this.options.animation || {};
      options.animation = {
        onComplete: this.rendered,
        ...animation,
      };

      options = {
        onHover: this.hover,
        ...options,
      };

      return options;
    },
  },
  mounted() {
    this.renderChart(this.chartData, this.optionsMergedDefaultEvents);
  },
  methods: {
    // ・・・省略
    rendered: function() {
      this.$emit('rendered');
    },
  },
  // ・・・省略
```

上記により、レンダリング完了時もhoverイベントと同様に呼び出し側から`@rendered="event handler名"`にてイベントを受け取ることが可能となりました。

```vue:plugins/vue-chartjs.js
<template>
  <v-container fluid>
    <doughnut-chart :chart-data="chartData" :options="chartOptions" @hover="hover" @rendered="rendered"/>
    // ・・・省略
  </v-container>
</template>

<script>
  // ・・・省略
  methods: {
    // ・・・省略
    rendered: function() {
      console.log('rendered');
    },
  },
};
</script>
```
【メモ】CSSのhover処理をスマートフォンでも適用させる

## はじめに
ポートフォリオ作成時、画像の上にカーソルを置いた時に文字を浮かび上がらせる処理をしていました。
その処理をスマホでも適用させるための実装のメモを残します。

##結論
HTMLに以下を追加するのみです！

```
<div class='top' ontouchstart="">
```

ontouchstart=""　という属性を追加することでスマホ（タッチデバイス）でも画像をタップした際にhover時の動きをしてくれます。
ontouchstartとは、その名の通り「指先が触れた時に発生する」イベントです。

この属性を追加しないと、スマホ時にhoverが反応しない事を本番環境にアップしてから気づいたので、スマホ時でのテストも大事ですね。（当たり前）

CSSに関しては何も追加しなくても適用されます。

##終わる
以上、ただのメモでした。
VirtualBoxにおけるホストOS側のBIOS設定

## BIOS設定

![BIOS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/2e7d9e5f-9af7-b92d-12c2-09dfcd9337e3.jpeg)

- `BIOS` とは、パソコンに接続された周辺機器を制御するためのソフトウェアであれる。
- `Virtualbox` で `64bit` を動かすには、ハードウェアレベルでの「`仮想化支援技術`」が必須である。
- `BIOS` はパソコンメーカーによって様々で、「`advanced`」や「`CPU`」の項目に「`Virtualization Technology`」などのメニューがあり、これが `OFF` になっていると `VirtualBox` では `32bit` しか表示されない。
- `BIOS` の設定を変更する場合は「`BIOS　PCメーカー名　仮想化`」などで `検索` すると方法が出てくる。
Drupal 8 で ログインロックされたアカウントを管理画面から解除する

Drupal8 では、５回ログインに失敗すると、標準でアカウントがロックされてしまいます。

```
There have been more than 5 failed login attempts for this account. It is temporarily blocked. Try again later or request a new password.
```

しばらく待つか（何分だったかな？）、パスワードの再設定をすればよいのですが、納品後にクレームの温床になってしまいがちです。

そんな声が多々あるのか、Drupalには flood_unblock というモジュールが用意されています。昨日確認したところ、16,571 のサイトで利用されているとのことなので、みんな考えることは一緒ですね。

※標準にいれりゃいいのに。。

使い方は簡単で、

```
drush en flood_unblock 
```

などでモジュールをいれると、「環境設定」> 「システム」のなかに、flood unblock が表示されようになるので、アカウントロックされたユーザを選んで、「Clear Flood」ボタンを押下すればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225890/d836e1a7-a61f-6744-45cf-31bda932a8b1.png)
【SwiftUI】画面いっぱいにViewを広げる

# 問題を感じたView

このViewを横いっぱい広げたいなんとかしたい。

<img width="200" alt="スクリーンショット 2019-09-29 21.29.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114709/d33b4ef0-81e9-c41d-b9fc-11678220e4c1.png">


```swift:
struct DailyCaloriesSummaryView: View {
    
    var body: some View {
        VStack(alignment: .leading, spacing: 5) {
            Text("9月11日")
                .font(.headline)
            
            VStack(alignment: .leading, spacing: 5) {
                Text("摂取カロリー: 1800kcal")
                Text("消費カロリー: 600kcal")
                Text("差分: 1200kcal")
            }
            .font(.body)
            .padding(.leading, 15)
        }
        .background(Color(.secondarySystemFill))
    }
}

struct DailyCaloriesSummaryView_Previews: PreviewProvider {
    static var previews: some View {
        DailyCaloriesSummaryView()
    }
}

```

# 画面いっぱい広げる
`.background` の手前に以下のコードを差し込む

```swift:
.frame(maxWidth: .infinity)
```

<img width="200" alt="スクリーンショット 2019-09-29 21.30.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114709/3f969a49-18a1-00bf-7aee-876888ebfbfa.png">

# 画面いっぱいまで広げたうえで、左寄せする

```swift:
.frame(maxWidth: .infinity, alignment: .leading)
```

<img width="200" alt="スクリーンショット 2019-09-29 21.32.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114709/e900659a-4fcd-aa21-592d-7bfbf3e6bf36.png">

# 見た目を整えて最終形
カードUIの出来上がり！
<img width="200" alt="スクリーンショット 2019-09-29 21.34.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114709/bfe47c5b-a6a6-5b69-54d1-92be008e2c22.png">


```swift:
struct DailyCaloriesSummaryView: View {
    
    var body: some View {
        VStack(alignment: .leading, spacing: 5) {
            Text("9月11日")
                .font(.headline)
            
            VStack(alignment: .leading, spacing: 5) {
                Text("摂取カロリー: 1800kcal")
                Text("消費カロリー: 600kcal")
                Text("差分: 1200kcal")
            }
            .font(.body)
            .padding(.leading, 15)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(15)
        .background(Color(.secondarySystemFill))
        .cornerRadius(15)
    }
    
}

struct DailyCaloriesSummaryView_Previews: PreviewProvider {
    static var previews: some View {
        DailyCaloriesSummaryView()
            .padding(15)
        
    }
}

```
Anaconda navigatorで仮想環境を作ってターミナルを開く(Windows10)

#仮想環境を作成する

左下の[Create]をクリック。

新しい仮想環境の名前を入力し、Pythonのバージョンを選択する。

![コメント 2019-09-29 212040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499476/2dc13cfb-1cde-3776-6923-d6fc2aeafbce.png)

すると、仮想環境が作成される。

#作成した仮想環境でターミナルを開く

動かしたい仮想環境の名前の横の[▶]をクリック。

[Open Terminal]をクリック。

![コメント 2019-09-29 212220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499476/8d7a6de6-e8d0-06f4-9225-935e185da709.png)
[Ubuntu18.04] Tilixの設定

現在使用しているTilixというTerminalの設定です。
（Hyperも試してみたけど、emacs起動するとひっちゃかめっちゃかになるので撤退しました...）

## 設定

### 外観

スクショで...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233666/b9d2bd8a-533c-350a-9d3a-05d2a406b09a.png)


### ショートカット

下記のように変更する

|アクション|ショートカットキー|
|---|---|
|Open a new session|Shift + Ctrl + N|
|Add terminal right|Shift + Ctrl + T|
|Switch to next terminal|Ctrl + T|
|Switch to next session|Ctrl + Left|
|Switch to previous session|Ctrl + Right|




### Quake

画面上部からほぼフルサイズで表示したいのでこのような設定にしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233666/7610ea4c-69d6-b505-4e24-926fcd4dbbec.png)


※quakeでの起動設定

- gnome-control-center
    - デバイス
        - キーボード

ショートカットを追加で下記のように設定

- 名前: `tilix-quake` お好みで。
- コマンド: `tilix --quake`
- ショートカット: `Super + Space` お好みで。

![Screenshot from 2019-10-10 00-07-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233666/42e5e7ed-35da-6a01-a223-a6dfebe30d16.png)


これで `Super + Space` を押せば画面トップからターミナルが現れます。
シェル実行ツールfairy support runで既存のシェル資産を整理してみる

# fairy support runって？
複数のサーバー上で
手元にあるシェルの実行
ファイルのダウンロード、アップロードができるツールです
サーバーの構成管理にも使えます

[ドキュメント](https://doc.fairysupport.com/run/ja/apache_install.html)を見れば使い方は簡単にわかります
この手のツールでよくあるLAMP環境の構築は[こちら](https://doc.fairysupport.com/run/ja/sample_web.html)で一発でできます

#### 使うのに向いてる人
手元にシェル資産がある人
#### 使うのに向かない人
シェルと聞くと脊髄反射で拒絶反応を起こす人

# とりあえず動かしてみる
Java上で動くのであらかじめJavaをインストールしておきます
fairy support runをダウンロードをします。
[fairy support runダウンロード](https://github.com/fairysupport/run/raw/master/build/libs/com_fairysupport_run.jar)
シェルを実行するサーバーへのアクセス情報ファイルを作成します

```server.properties
server1.address=127.0.0.1
server1.port=2222
server1.user=vagrant
server1.password=vagrant
```
実行するシェル作成します
testフォルダ作成してその中にmain.shを作成します

```main.sh
#!/bin/bash

echo "Hello world"
```

ファイルの構成は全部で下記のようになりました

```
|-- com_fairysupport_run.jar
|-- server.properties
`-- test
    `-- main.sh
```

jarファイルなのでjavaコマンドで実行できます
引数に与えているtestというのはmain.shの入っているフォルダ名です

```
java -jar com_fairysupport_run.jar test
```

これでmain.shが127.0.0.1:2222上で実行されました

シェルはキックに使うだけにして本処理は得意な言語にしてみる

testフォルダの中にhello_world.plを作成します

```hello_world.pl
print "hello world\n";
```

main.shを修正します

```main.sh
#!/bin/bash

perl hello_world.pl
```

ファイルの構成は全部で下記のようになりました

```
|-- com_fairysupport_run.jar
|-- server.properties
`-- test
    |-- hello_world.pl
    `-- main.sh
```

実行してみます

```
java -jar com_fairysupport_run.jar test
```

main.shからhello_world.plが実行されました

# 既存のシェル資産を整理する
とりあえず動かせたので既存のシェル資産をfairy support runで実行できるようにまとめてみる

MySQLへのデータの初期データインポートを整理します

mysqlimportフォルダ作成してその中にmain.shを作成します

```main.sh
#!/bin/bash

data_dir=$(cd ./data; pwd)
for file in `ls -1 ${data_dir}`
do
  mysqlimport -uroot -ppassword --local my_db ${data_dir}/${file}
done
```

mysqlimportフォルダ内にdataフォルダを作成します
dataフォルダ内にテーブル名.txtという名前のタブ区切りファイルを作成します

ファイルの構成は全部で下記のようになりました

```
|-- com_fairysupport_run.jar
|-- server.properties
`-- mysqlimport
    |-- data
    |   |-- group.txt
    |   |-- schedule.txt
    |   `-- user.txt
    `-- main.sh
```

実行してみます

```
java -jar com_fairysupport_run.jar mysqlimport
```

my_dbデータベース内のgroupテーブル、scheduleテーブル、userテーブルへ初期データ投入ができました

今回MySQLへの初期データ投入を整理してみました
ruby nkf メモ

Rubyのnkf のオプションを理解するためのメモ

```ruby
require 'nkf'
str = "あアぁｱヴバパｳﾞ01０１abABａｂＡＢ"

# -w はUTF-8(BOMなし)で出力するオプション nkfはデフォルトで半角カナを全角カナ変換する
NKF.nkf("-w", str)
=> "あアぁアヴバパヴ01０１abABａｂＡＢ"

# -x をつけると半角カナはそのまま出力される
NKF.nkf("-xw", str)
# => "あアぁｱヴバパｳﾞ01０１abABａｂＡＢ"

# ひらがなをカタカナに変換
NKF.nkf("-h1 -w", str)
# => "ああぁあゔばぱゔ01０１abABａｂＡＢ"

# カタカナをひらがなに
NKF.nkf("-h2 -w", str)
# => "アアァアヴバパヴ01０１abABａｂＡＢ"

# 全角空白を半角空白に変換
str1 = "育ち盛り　弁当"
NKF.nkf("-Z1 -w", str1)
# => "育ち盛り 弁当"

# 変換元の文字コードをsjisへ変換
NKF.nkf('-s', str)
# => "\x{82A0}\x{8341}\x{829F}\x{8341}\x{8394}\x{836F}\x{8370}\x{8394}01\x{824F}\x{8250}abAB\x{8281}\x{8282}\x{8260}\x{8261}"

# icが入力の文字コード、ocが出力の文字コード、変換できなければ下駄線に置き換える
kbf = "〜鎌倉幕府〜"
sub = NKF.nkf("--ic=UTF-8 --oc=CP932 --fb-subchar=0x3013", kbf)
# => "\x{81AC}\x{8A99}\x{9171}\x{968B}\x{957B}\x{81AC}"

# sjisからUTF8に変換
sub.encode("UTF-8", "Shift_JIS")
# => "〓鎌倉幕府〓"

# UTF8からsjisへ変換
str.encode("Shift_JIS", "UTF-8")
# => "\x{8160}\x{8A99}\x{9171}\x{968B}\x{957B}\x{8160}"
```


```ruby
str2 = "てすと😓"

sub2 = NKF.nkf("--ic=UTF-8 --oc=CP932 --fb-subchar=0x3013", str2)
sub2.encode("UTF-8", "Shift_JIS")
# => "てすと〓"
```
PhpStormで入力中に出てくるポップアップを非表示にする

PhpStormを使い始めて、入力中に出てくるポップアップが邪魔だったので、非表示にする方法を記録しておきます。
<img width="1336" alt="Screen Shot 2019-09-29 at 20.56.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287391/1b430ab7-101b-98cb-f77d-6a33ed3ef163.png">
1.PhpStorm->Preference
2.Editor->General->Code Completion
3.Parameter infoの中にあるShow the parameter info popup in 1000ms のチェックボックスをOFF
<img width="1012" alt="Screen Shot 2019-09-29 at 20.54.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287391/10677690-183c-250b-f928-900acf71f237.png">
ツールが英語なので、ググってもなかなか非表示にするやり方が分かりませんでした。
以下のページを参考にしました。
https://intellij-support.jetbrains.com/hc/en-us/community/posts/360000037590-Disable-pop-up-that-prevents-typing-
最近よく使っているDocker構成の備忘録 (NodeJS+Redis+MySQL)

# はじめに
この記事は最近Dockerをよく使うようになってきて、
開発環境を作っては捨て作っては捨てを繰り返しつつ、いろいろ試しているうちに
個人的によく使いそうな構成が見えてきたので、それをメモとして残しておく目的で記載しています。

# アーキテクチャ
NodeJS + Redis + MySQLによる構成で作っていきます。
主な内訳は以下の通りです。

|  | 利用目的 | 
|---|---|
|NodeJS  |webアプリケーション  |
|MySQL | ユーザー等の主なデータ  |
|Redis | セッション,キャッシュ  |

今回セッションとキャッシュをどちらもRedisで管理してしまっていますが、
分けるソリューションもあると思います。
一例としては、キャッシュとかはDynamoDBでセッション管理はRedisに保存みたいな感じですかね。
自分が作る程度の環境だとそこまで分ける必要性を感じなかったので、すべてRedisで管理してました。

# ディレクトリ構成
このあとdocker-compose.ymlを記載しますが、
今回は以下のディレクトリ構成を前提で進めています。

```terminal
├── data
│   ├── mysql
│   └── redis
├── docker-compose.yml
├── mysql
│   └── Dockerfile
├── app
│   ├── Dockerfile
│   ├── app.js
│   ├── bin
│   │   └── www
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   ├── public
│   │   ├── images
│   │   ├── javascripts
│   │   └── stylesheets
│   │       └── style.css
│   ├── routes
│   │   ├── index.js
│   │   └── users.js
│   └── views
│       ├── error.jade
│       ├── index.jade
│       └── layout.jade
└── redis
    └── Dockerfile
```


# docker-compose.yml
今回は、Docker-Composeを使ってNodeJS、MySQL、Redisのそれぞれでコンテナ立ち上げていく形にしていきます。
docker-composeの内容は以下の通りです。

```docker-compose.yml
version: '3'

services:
  app:
    build:
      context: .
      dockerfile: ./app/Dockerfile
    depends_on:
      - mysql
      - redis
    ports:
      - '3000:3000'
    tty: true
    container_name: node_app

  mysql:
    build:
      context: .
      dockerfile: ./mysql/Dockerfile
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: user
      MYSQL_PASSWORD: hogehoge
      MYSQL_DATABASE: testdb
    volumes:
      - ./data/mysql:/var/lib/mysql
    container_name: mysql

  redis:
    build:
      context: .
      dockerfile: ./redis/Dockerfile
    restart: always
    volumes:
      - ./data/redis:/data
    container_name: redis
```

servicesに対してwebアプリケーションや他のミドルウェアのDockerイメージに関する設定内容を記載しています。
appのところにはdepends_onがありますが、これは記載されている他のイメージとの依存関係を示すものになっています。依存関係のあるものが解決してからappの内容が動作します。
それぞれbuildのところで、どのDockerfileを使用してDockerイメージをbuildするかを設定しているのがわかると思うので、Dockerfileも記載しましょう。


## ./app/Dockerfile

```Dockerfile:./app/Dockerfile
FROM node:latest

WORKDIR /home/app

COPY ./app/package*.json ./

RUN npm install

COPY ./app ./

EXPOSE 3000
```

## ./mysql/Dockerfile
```Dockerfile:./mysql/Dockerfile
FROM mysql:5.7

# ADD ./mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf

EXPOSE 3306
```

## ./redis/Dockerfile
```Dockerfile:./redis/Dockerfile
FROM redis

# COPY redis.conf /usr/local/etc/redis/redis.conf

EXPOSE 6379
```

## 実行
docker-compose.ymlのあるディレクトリで実行します。
### build
```
$ docker-compose build
```

### 起動
```
$ docker-compose up -d
```

### exec
```
# nodeのコンテナ
$ docker-compose exec app bash

# redisのコンテナ
$ docker-compose exec redis bash

# mysqlのコンテナ
$ docker-compose exec mysql bash
```

ここに記載していないコマンドはこちらの方の記事が参考になります。
[docker-compose コマンドまとめ](https://qiita.com/wasanx25/items/d47caf37b79e855af95f)


# おわりに
個人的に利用することの多そうな環境をメモがてら書いていきましたが、
間違いやよりよい方法があればぜひ教えてください🙇‍♀️
PythonでEither実装してみた

これまでPythonをメインに書いてきたのですが、最近Haskellを学んでいて、EitherはPythonでどう実装するんだろう、と思い自分で実装してみました。
# 実装
PythonによるEitherの実装を示します。
Functorとして扱えるように、fmapを実装しています。
※Monadとして扱うようにするためには、さらなる関数の実装が必要ですが、今後の課題としたいと思います。

```pither.py
from typing import Any, Callable

class Either:
    pass


class Right(Either):
    def __init__(self, v: Any):
        self.__v = v

    def value(self) -> Any:
        return self.__v


class Left(Either):
    def __init__(self, v: Any):
        self.__v = v

    def value(self) -> Any:
        return self.__v


def fmap(f: Callable[[Any], Any], x: Either) -> Either:
    '''
    >>> fmap(lambda x: x + 1, Right(2)).value()
    3
    >>> fmap(lambda x: x + 1, Left('string')).value()
    'string'
    >>> fmap(lambda x: x + 1, Right('string')).value()
    'must be str, not int'
    '''
    if not isinstance(f, Callable):
        raise TypeError('f should be Callable instance')
    if not isinstance(x, Either):
        raise TypeError('x should be Either instance')

    if isinstance(x, Right):
        try:
            return Right(f(x.value()))
        except Exception as e:
            return Left(str(e))
    if isinstance(x, Left):
        return x


if __name__ == '__main__':
    import doctest
    doctest.testmod()
```
構造としていたってシンプルです。
Eitherという親クラスを継承したRightクラスとLeftクラスを実装しています。
そして、Right、Leftクラスともに1つの値をコンストラクタの引数に渡し、その値を参照するvalueメソッドが実装されているのみです。
fmapでは第2引数がRightインスタンスのときはラップされた値に関数を適用し、結果をRightインスタンスで返す一方、Leftインスタンスの場合は、そのまま返すような実装となっています。
また、Pythonは動的型付け言語であるため、型チェックを自前で実装しています。
fはCallableであることをチェックしていますが、fの引数の型まではチェックできないため、不完全です。
もう少しいいやり方があるか考えてみようと思っています。
（いざ静的型付け言語を学んでみると動的型付け言語は機能不足に感じてきてしまいますね…）

# まとめ
PythonでEitherの実装をしてみました。
先に述べた通り、Monadとして扱うようにするためには、さらなる関数の実装が必要なので、今後残りの関数の実装をしていきたいと思います。