OmniAICreator/Qiita-1.07M huggingface dataset:
SHARP Brain に Linux を入れて遊ぶ(3) - スクリーン ショット

[目次](https://qiita.com/nekopro2/items/7eff2eb5e1c4480d3b30)

# 概要
[前回](https://qiita.com/nekopro2/items/5722a2a79f7851cf052c)、フレームバッファ クラスを作成したので、これを使って画面のスクリーン ショットを取りたい。

## 内容
- 基本的には [その2](https://qiita.com/nekopro2/items/379b2894cf9b1ea5d26f) のように BMP ヘッダを頭につければOK
- BMP ファイルは 16bit アライメントで 32bit値があるので気を付ける
  - x86/x64 はアライメントを無視できる
  - ARM の場合はアライメントを跨いた場合、変な値になるので気を付けよう(分かりづらい)

## ソースコード
いつものように gitlab へ
https://gitlab.com/nekodevteam/brainux/-/tree/main/savefb0

## 16bpp Bitmap
Brain は WVGA 16bpp なので、16bpp Bitmap で出力する。
この場合、biCompression に BI_BITFIELDS を指定して、カラーマスクを設定しよう。
また、16bpp bitmap は MS Paint とか真っ当なアプリでないと開けないので注意。

## 結果
このように、まんま撮れるようになりました。
![brain.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821068/df26f2eb-733d-bb5b-99fb-e13c4884ab1e.jpeg)
![tty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821068/113855e3-c115-90ff-e77e-8482643d06cb.png)
ぼくのかんがえたさいきょうのDelphi開発手法・環境 

# なんの記事？
- いろんなショートカットあるけど使い道が分からない🤔

- みんなが使ってるDelphiの開発環境が分からない🤔

- なんかもっと効率の良い開発方法があるのでは🤔

ってな人向けの記事です。
ユースケースベースでお話できたらなと

# キーの割り当てをVisual Studioと似せる
メインの開発言語がC#な人に当設定は非常におススメ！
- モチベーション
  - Visual StudioとRAD Studioで両方のショートカット覚えるの面倒くさい('_')
- ただし、ちょいちょい差異がある...
  - たとえば、コメントアウト
  - コメント解除(Ctrl + K + U)は使えない...

以下、差異の部分を重点的にお話していきます

# ソースコードの検索
コードを分析する際、ソースの検索は欠かせません
効率よく分析するためのショートカットを共有します

## ユニット名をあいまい検索したい(Ctrl + F12)
- プロジェクト内をユニット名で検索できるショートカットです
- 「あのユニット、何となくあんな名前だったけど完全な名前を覚えてない...」そんな時に使えるショートカットです
  - Visual Studio の「Ctrl + ,」に相当

## 開いてる画面のソースを検索したい(Shift + F12)
- クラス名で検索できるショートカットです
  - Visual Studio の「Ctrl + ,」に相当
- 応用技として開いてる画面のソースを検索できます
  - １．Spy++でフォームの画面のクラス名を取得
  - ２．クラス名を入力し検索
  - ３．なぜか最初の「T」の文字を消す必要があるため注意

## プロジェクト内のソースを文字で(全)検索したい(Ctrl + Shift + F)
- Visual Studioでも使える機能なのでみんな知ってるかな(一応の紹介)？
- 開いてるファイルを検索する場合、「Ctrl + F」を使います(あたりまえ)
  - ただし、２つ目以降の検索結果に移動したいとき、Enterを押すと改行されます(使いづらい...)
  - [↓]ボタンを押せばいいんですがマウス操作が面倒くさい
  - そんな時は「F3」or「Shift + F3」で次/前へ移動できます

## 関数の参照関係を確認したい(Ctrl + Shift + Enter)
- 関数の参照元を検索する際に使います
  - Visual Studioの「Shift + F12」に相当
- 逆に、関数の定義を確認したい時は「Ctrl + クリック」 or 「Alt + →」を使います
  - Visual Studioの「F12」に相当
  - 「Alt + ←」で前に戻れます

# ショートカット
コードを書く際のショートカットを紹介します
言わずもがな、エディタ操作のショートカットを覚えることで
開発効率を飛躍的に向上できます

## 行削除したい(Ctrl + Y)
- 説明不要。コード書いてて、行削除はよくしますよね
  - Visual Studioの「Ctrl + X」や「Ctrl + L」に相当

- えっ？じゃあ、やり直しってどうやんのって思いますよね？
  - 「Alt+Shift+Backspace」でできます
  - Visual Studioの(というか、Windows全般の)「Ctrl + Y」に相当
  - やり直したい時に「Ctrl + Y」押すと行が削除されるため、注意！

## フォームとコードをすばやく切り替えたい(F12)
マウス操作で切り替えるの億劫なのでよく使います

## デザイナのコードを見たい(Alt + F12)
直接デザイナをいじってFormを修正したい時に役立つ

## 関数名を変更したい(Ctrl + Shift + E)
- Visual Studioの「Ctrl + ,」に相当

## コードを整形したい(Ctrl + D)
- Visual Studioの「Ctrl + K + C」に相当

## デバッグ中にオブジェクトのプロパティを確認したい(Ctrl + F2)

## その他
- TODOコメントを書きたい(Ctrl + Shift + T)
  - TODOコメントの書き方：
- GUIDを挿入したい(Ctrl + Shift + G)
  - インターフェースを宣言する際にGUIDを書く必要があります

# Delphiならではのショートカット
DelphiはC#とちがい、interface部とimplementation部にわかれています。
この言語仕様に起因するわずらわしさを解消するショートカットを紹介します。

## 関数の可視性をすばやく確認したい(Ctrl + Shift + ↑)
- interface部の定義を確認したい or 修正したい場合に便利です
- 「Ctrl + Shift + ↓」でinterface部からimplementation部へ移動できます

## interface部に書いた関数をimplementation部にも書きたい(Ctrl + Shift + C)
- 同じシグネチャを書かくの、ダルいですよね。。。
- プロパティのフィールド名の補完もできたりします！

# IDEの操作・設定とか
IDE(RAD Studio)を使って開発するうえで
QOL上がったなと感じた内容を紹介します

## 最適な()ソースエディタの設定が知りたい
人による。個人的には以下がオススメ！
- フォントはConsolas
- フォントサイズは「12」くらい

## pasファイル「名」をコピーしたい
- いま開いているユニットのファイル名をコピーしたい
- [プロジェクトマネージャ]のユニットに「F2」押して、「Ctrl + C」すると、フルパスがコピーされます
  - 欲しいのはファイル名だったりするんですよね...
- 「F2」押して、右クリックからの[コピー]でファイル名を取得できます

## ダークモードを適用したい
- Delphi 10.2 Tokyoからデフォで設定可能になりました！
- Delphi XE5でエディタを暗くしたい場合
  - [このサイト](https://github.com/RWarnecke/Delphi-Editor-Theme/blob/master/dark/DXE5.reg)のレジストリを適用すればＯＫ！
  - ちなみに、IDEの設定情報はレジストリに格納されています
  - 他の人の設定情報をインポートできないんですよね...

## 編集中...
PostmanからSalesforceの連携

 ### 要件
Salesforceのオブジェクトは全部のRestApiが対応しているので、RestApiの確認できる方法を検討する
###　案
Postmanで認証して、データの確認、作成を行う
### 参照
・認証のTokenをもらう
・SalesforceのRestApiをコールする

https://trailhead.salesforce.com/ja/content/learn/projects/quick-start-connect-postman-to-salesforce
paizaラーニング レベルアップ問題集 Aランクレベルアップメニュー JavaScript 区間への足し算

区間への足し算 (paizaランク A 相当)

https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_twopointers_step5

クエリについてforループし、クエリの処理でforループをする、for二重ループで解くと、タイムオーバーになります。
```javascript:タイムオーバー
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//要素数 N とクエリの数 M
const [N, M] = lines[0].split(" ").map(Number);
//数列A
const A = lines[1].split(" ").map(num => Number(num));

//クエリについて
for (let i = 1; i <= M; i++) {
    //各クエリの処理に用いる整数 l_i, u_i, a_i (1 ≦ i ≦ M)
    const [l, u, a] = lines[i + 1].split(" ").map(Number);
    
    // 要素番号が、l_i 以上、u_i 以下の全ての A の要素に、a_i を足す。
    for (let j = l; j <= j; j++) {
        A[j] += a;
    }
}
console.log(A.join("\n"));
```


## いもす法(imos法)について

いもす法(imos法)を使います。

要素番号が、l_i 以上、u_i 以下の全ての A の要素に、a_i を足す。

の場合、

例えば、配列add = Array(N+1).fill(0)を用意する。
前処理で、add[l_i]でa_iを足し、add[u_i+1]でa_iを引き、
for(i=0;i<N;i++)add[i+1] += add[i];で、累積和をつくる。
Aの要素に累積和の要素を足す、という流れです。

***

### いもす法のイメージ

前処理で、add[l_i]でa_iを足し、add[u_i+1]でa_iを引き、
for(i=0;i<N;i++)add[i+1] += add[i];で、累積和をつくる、
というのが、いもす法のメインの処理です。

ここのイメージについて解説します。

例えば、
`add = [0, 0, 0, 0, 0, 0, 0]`
を用意して、いもす法でl_i=1からu_i=4までa_iを足すことにします。

add[l_i = 1]でa_iを足すと、
`add = [0, a_i, 0, 0, 0, 0, 0]`
となります。
累積和をつくるとき、add[i+1] += add[i]なので、a_iが次の要素に足され続けていきます。
どこで足すのを止めるか決めないと、最後までa_iが足され、
`add = [0, a_i, a_i, a_i, a_i, a_i, a_i]`
となります。

累積和を作る前に戻ります。
add[l_i = 1]でa_iを足したところです。
`add = [0, a_i, 0, 0, 0, 0, 0]`
a_iを足すのは、u_i=4までとすると、u_i+1=5でa_iを引いておきます。
`add = [0, a_i, 0, 0, 0, -a_i, 0]`
累積和を作ると、a_iが次々足されていきますが、
u_i+1=5の位置でa_i-a_i=0なので、
`add = [0, a_i, a_i, a_i, a_i, 0, 0]`
となります。a_iはu_i=4まで足されたことになります。

まとめると、l_i=1からu_i=4までa_iを足して、
`add = [0, a_i, a_i, a_i, a_i, 0, 0]`
としたい時、
`add = [0, 0, 0, 0, 0, 0, 0]`
を用意して、前処理でl_i=1でa_iを足し、u_i+1=5で-a_iして、
`add = [0, a_i, 0, 0, 0, -a_i, 0]`
累積和をつくれば、a_iが次々足されていって、u_i+1=5で0になり、
`add = [0, a_i, a_i, a_i, a_i, 0, 0]`
l_i=1からu_i=4までa_iを足したaddができます。


前処理で、add[l_i]でa_iを足し、add[u_i+1]でa_iを引き、
for(i=0;i<N;i++)add[i+1] += add[i];で、累積和をつくる
いもす法のイメージについての解説でした。

# 解答例
add配列の長さがN+1なのは、いもす法の前処理で、u_iがNのとき、u=N+1でadd[u] -= aするからです。範囲外にアクセスしないようにしています。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//数列 A の要素数 N と、条件に使う整数 M
const [N, M] = lines[0].split(" ").map(Number);
const A = lines[1].split(" ").map(Number);
//Aに加えるadd
const add = Array(N + 1).fill(0);//N+1範囲外アクセス防ぐ
for (let i = 1; i <= M; i++) {
    const [l, u, a] = lines[1 + i].split(" ").map(Number);
    //いもす法の前処理
    add[l - 1] += a;//l_iでa_iを足し
    add[u] -= a;//u_i+1でa_iを引き
}
//累積和を作る
for (let i = 0; i < N; i++) {
    add[i + 1] += add[i];
}
//addをAに加えて出力
for (let i = 0; i < N; i++) {
    console.log(A[i] + add[i]);
}
```
最後の、累積和を作り、Aに加えて出力するところはまとめることができます。
```javascript
//addをAに加えて出力しながら、累積和をつくる。
for (let i = 0; i < N; i++) {
    //addをAに加える
    console.log(A[i] + add[i]);
    //累積和を作る
    add[i + 1] += add[i];
}
```
サービスに使うアイコンを全部Noto Emojiでやっていくことはできるか

# Noto Emojiとは
https://fonts.google.com/noto/specimen/Noto+Emoji

Google Fontsにて提供されている、Emojiが白黒で表現されたUnicode絵文字。
今回はこれでサービスのアイコンをすべてまかなうことができないかと考えました。

補足：Noto Emojiについての説明は以下の記事に詳しく記載されています
https://forest.watch.impress.co.jp/docs/news/1408856.html


# Noto Emojiをアイコンとして使ったサービス
https://anke.digital/ 

このサービスをNuxt.js+Firebase+Algoliaで個人開発しました。
画面を制作するにあたり、アイコンをSNSのアイコンなどの一部を除きすべてNoto Emojiを使用しています。

## 使い方

emoji用のclassを作って

```css
.emoji {
    font-family: "Noto Emoji",sans-serif;
}
```

こんなかんじで適用するだけ

```haml
<h1><span class="emoji">📣</span>なんらかの見出し</h1>
```


### 使用例

見出しに添えるアイコンにつかったり
![スクリーンショット 2022-09-27 19.28.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7193/64fbe335-158c-e4ec-fbf4-532b9129aef3.png)


空のサムネイル部分の絵の意匠、上矢印、バツボタン、追加の部分のプラスボタン、リストの横のチェックマークなどもnoto emojiを使っています
![スクリーンショット 2022-09-27 19.29.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7193/ca3874a5-38f2-ec6a-a9a5-be8d77f162e2.png)

# 結論
アイコンとしてNoto emojiを使うことは十分に可能 と表現して差し支えないと考えます。
今回使ってみましたが単なる単色の文字なので、色・大きさともに気を使って使う必要がなくかなり楽に取り回しができました。

ただしいくつかの制限や留意すべき事項があったので以下に記載していきます。

# Noto Emojiをアイコンとして使う場合に注意すべき事項

### Firefoxなど一部のブラウザではNoto Emojiが適用されない状態で表示される

Firefoxで[Noto Emoji](https://fonts.google.com/noto/specimen/Noto+Emoji)の画面をみたときのスクショ
![スクリーンショット 2022-09-27 19.49.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7193/be48ce48-802f-4563-f7db-a9aac447968c.png)
なんでこんなことになるの…？？？
申し訳ないことにこの現象が起こる理由がわからなかったのですが、一部のemojiはNoto Emojiが適用されません。上記のスクショ画像を見ていただけるとわかると思うのですが、ハートマークなど意外とメジャーどころのemojiがこの現象を起こすので結構厳しいです。

今回は個人開発なのでFirefoxの[ブラウザのシェア率](https://gs.statcounter.com/browser-market-share)は３％程度という数値を鑑み、Firefoxはサポートしないという判断にしました。とはいえ３％のシェアは単純に考えて１００人のうち3人なのでそれなりにユーザー数がいるようなサービスだと無視はできない数値かなとも思います。


### 丸いフォントとの相性が悪い、かも？

これは実装ではなく見た目のデザイン面の話ですが、Noto Emojiは基本的に線の終端が角状になっていてソリッドな形状になっています。
これにより丸文字フォントと組み合わせると微妙に違和感が出てしまったので、あまりおすすめできません（筆者の使い方センスが悪いだけという可能性は大いに有り得そうです）。


### デザインのトーンに留意

Noto Emojiはアイコンとしての癖は少ないですが、ソリッドな割には可愛らしい印象の絵柄が多いので、Noto Emojiをアイコンに使う場合のデザインのトーンを決めるときはその点に留意すると良いかもしれません。
５種類太さがあるので細いものを選べばクールに、太いものを選べばポップな見た目の用途にも対応できそうですが、読み込みが遅くなるので使用する太さの種類は絞ることが望ましいです。


### 独自機能があるようなサービス・アプリの場合は使わないほうが良いかも

当たり前の話ですが、emojiになるような意匠というのはある程度汎用的なものです（	🎋とか🍣とか月餅とか見てると微妙に懐疑的にはなりますが）
そのため、独自の機能を持つようなアプリやサービスの場合に機能にちゃんと合った意匠のemojiを探すというのは難しいところになります。
UIでよく使うような部分では [シェア](https://www.flaticon.com/free-icons/share) や [コピー](https://www.flaticon.com/search?word=copy&order_by=4) を表すようなemojiというのも執筆時点ではありません。
使ってみると意外と「合うのが無いな〜」ってなるシーンは多かったので、Figmaなどで設計してる段階で採用するかどうかをジャッジすると良いかなと思います。

# まとめ
個人開発やプロトタイピングに採用するなら大いにあり、という感触です。
大規模なものになってくると独自のアイコンを作らざるを得なくなってくることが予想されること、それをNoto emojiのトーンとウェイトを合わせたり、フォントとして取り回すということは面倒になりそうです。
とはいえアイコンを手描きするというのは結構時間がかかる作業なので、Noto Emojiを使って楽をさせてもらうのをデザイン作業の選択肢として持っておくのは良いんじゃないかなと思います
GASでLINEbot（スプレッドシートの内容から返信する）

# はじめに
LINEbotの原型みたいなものはできたので
LINEの部分は割愛して、GASのスクリプト部分だけ残す

# やりたいこと
* GASのスクリプトシートに、想定する応答リストを書いておく
* ユーザからのメッセージを受け取って、応答リストに合致するワードがあれば、それに対応する返事を返す

# GASのスプレッドシートの様子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/c3b12dc7-af99-28c9-4337-b5686293c54b.png)

# スクリプトの中身
トークンは機密情報なので、マスクしました。応答リストにないメッセージを受け取った場合は「こんばんわ」のみ返す。

```
function doPost(e) {
  var event = JSON.parse(e.postData.contents).events[0];
  var replyToken= event.replyToken;

  if (typeof replyToken === 'undefined') {
    return;
  }

  var url = 'https://api.line.me/v2/bot/message/reply';
  var channelToken = '**********';

  if(event.type === "message"){
    var text = event.message.text;

    var res_word = vlookup(text)

    if(!res_word){
      var messages = [{
        'type': 'text',
        'text': 'こんばんわ'
      }];
    } else{
      var messages = [{
        'type': 'text',
        'text': res_word
      }];
    }

  }

  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + channelToken,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': messages,
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);

}

function vlookup(req_word) {
 
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getActiveSheet();
 var rows = sheet.getLastRow()-1;
 var datas = sheet.getRange(2,1,rows,2).getValues();
 
 //連想配列に変換
 var object = {}; //連想配列の箱を用意
 
 for(var i=0; i<datas.length; i++){ //各行のデータを連想配列に格納
   
   var key = datas[i][0];
   var value = datas[i][1];
   object[key] = value;
 
 }

  return object[req_word];
}
```
trioによる並行処理②（Event）

[目次](https://qiita.com/Kyosuke_Ichikawa/items/b7fdffcbfe00773074a6)

## Event
[trio](https://trio.readthedocs.io/en/stable/)には[Event](https://trio.readthedocs.io/en/stable/reference-core.html?highlight=Event#trio.Event)というクラスがあり、次のメソッドがあります。

- ```await wait()```：非同期関数であり```set()```が呼ばれるまで待機します
- ```set()```：```wait()```での待機を終了させます
- ```is_set()```: 既に```set()```されていればTrueを返します

例えば次のように使えます。
```python
import trio


async def func1(event: trio.Event):
    print("func1 start")
    await trio.sleep(1)
    print("set event")
    event.set()
    await trio.sleep(1)
    print("func1 done")


async def main():
    async with trio.open_nursery() as nursery:
        event = trio.Event()
        nursery.start_soon(func1, event)

        print("wait for event")
        await event.wait()
        print("end of nursery")
    print("all end")


trio.run(main)
```
これは必ず次の結果になります。
```
wait for event
func1 start
set event
end of nursery
func1 done
all end
```

- ```await event.wait()```は```event.set()```が呼ばれるまで待機します
- [前記事](https://qiita.com/Kyosuke_Ichikawa/items/60955d36fa4c181c198e)を見て欲しいですが、await時は他の処理が優先され、awaitでない時はその処理が優先されます
  - main関数では```await event.wait()```までawaitしてないので、それまでmain関数の処理が優先されて"wait for event"が最初のメッセージになります
  - ```await event.wait()```時にfunc1の処理が優先されて"func1 start"を出力し、1秒後に```event.set()```されます（"set event"が出力される）
  - ```event.set()```によって```await event.wait()```の待機が終了するため、"end of nursery"が出力されます
  - nurseryのwithブロックは子タスクが終了するまで抜けないため、"func1 done"となってから"all end"になります

## Eventの注意点
既に```set()```されていれば```await wait()```しても待機しません。
よって下記は直ちに"done"となります。
```python
import trio


async def main():
    event = trio.Event()
    event.set()
    await event.wait()
    await event.wait()
    await event.wait()
    print("done")

trio.run(main)
```
EC2インスタンスのキーペアCFnで作れるようになったらしい

## CFnを書いてみる

Resources に書いてみました。
結構簡単ですね。

```:test-key.yaml
---
AWSTemplateFormatVersion: "2010-09-09"
Description: "test"

Resources:
    TestKeyPair:
        Type: AWS::EC2::KeyPair
        Properties:
            KeyName: Test-Key
            KeyType: rsa
```


## CFnを実行してみる

- スタックを作成します

![1CloudFormation - スタック - Google Chrome 2022-09-27 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/fb3032e4-f27d-3a57-4f72-940487d52199.png)


- スタックの名前を記載しました

これ以外はデフォルトで実行しました。

![2CloudFormation - スタック - Google Chrome 2022-09-27 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/7419a848-bd5b-e68e-5dc8-a69cba11e77f.png)


- 実行完了しました

![3CloudFormation - スタック test-key - Google Chrome 202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f2e1f49b-a85e-1041-cde2-c84a156ed64d.png)


- キーペア作れていました

![4キーペア _ EC2 Management Console - Google Chrome 2022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/d8a68929-62bc-4110-2acd-c9c89a0f2102.png)


- 秘密鍵確認

AWS Systems Manager > パラメータストア へ移動します

![5AWS Systems Manager - Parameter Store - Google Chr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/bd12be12-dd2e-d138-4375-b05c2c44b8c8.png)


値の表示をクリックすると値が表示されます。
こちらからコピーして使用します。

![6AWS Systems Manager - Parameter Store - Google Chr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/cac1d199-66b9-f02e-1a99-f3dc85e247ba.png)

## 勉強後イメージ

案外普通にできた・・・今度からはCFnで作ろう！

## 参考

- [[アップデート]EC2のキーペアに新しい管理機能が追加されました。](https://dev.classmethod.jp/articles/update-ec2-keypair-20220429/)
ポケモンの構築を管理できるWebアプリを作りました

https://pokebuild.sasakirione.com

## はじめに
ポケモン対戦をやってて次のような事はありませんか？
 - 構築に入ってるポケモンの努力値ぶりを忘れる
 - 紙やNotion等で構築を管理しているが実数値計算等が怠い
 - 友達と構築をシェアしたいけど公式のレンパ画面だと振り方とかがわからない

そんな人のためのWebアプリを作りました。

## 背景
 - 何か勉強のために1からWebアプリを作ってみたい
 - Notionで構築管理やってたけど怠くなってきた
 - システム化しちゃおう！

## 概要
Webアプリを作って1ヶ月ぐらい弄くり回してやっと最低限の形になった気がするので紹介記事を書いてみます。
今回作ったのはポケモンの構築を管理できるアプリです。
ポケモン対戦をそれなりにやる人であれば自分で構築をあれこれ考えて実際に組んでみる事があると思います。そんな時に構築をメモっておけるようなアプリとなっています。先に書いたように元はNotionで自分がやってた事である意味Notionでよくない？って感じはありますが勉強がてら作ってみました。

## 機能
 - 構築を管理できます
 - 育成済みポケモンを管理できます(育成済みポケモンだけ登録して後でその中からピックアップして構築作ったりできます)
 - S調整機能(任意の努力値で最速〇族まで抜けるっていうのが個体値性格考慮してリアルタイムで出てきます)
 - HP偶数警告(努力値振り画面でHPが偶数だと警告が出ます)
 - 構築の共有機能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861182/8f554156-d00f-e820-cb73-c596eaab2d9b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861182/a33bcf9b-727d-a15c-0ff7-626fd6195b15.png)




## 技術スタック
 - バックエンド：ktor+Exposed
 - フロントエンド：Next.js
 - インフラ：Cloud Run, Cloud SQL(PostgreSQL)
 - その他：Auth0
 
技術スタックについてはやってみたい優先で、そしてバックエンドについては軽めだったのでCloudFunction+Firestoreとかでも全然いい気がしましたが、ちゃんと一から作ってみたいためKotlinで一から作ることを選択しました。
インフラは最初はHerokuを使ってたけどお引っ越しして今に至ります。

### ktor+Exposed
小さいシステム作るならこれで十分(というかSpringが大きすぎる)。ただExposedについてはまだまだこれからを期待って感じですかね(まあv1.0になってないのでしょうがないですかね)。個人的にはマイグレーション機能が欲しいところ。普段はJavaとか書いてるのでKotlin自体は微妙になれてる新しめの言語ということで自分の中で趣味の第一言語になっています。

### Next.js
Reactが触ってみたかったので挑戦してみることに。触ってみた感じは大規模システムならVueより便利そうだなって印象。ただ小規模システムにはちょっと長大すぎるってところはあるかもしれません。あとこれはReact自体というかJavaScriptの話ですが、Decimalがないのはつらみがありました。まあそういうライブラリがあったので良かったんですけど。

### Cloud Run, Cloud SQL, Cloud Build
Cloud SQLはRDSなのに意外と安く借りれてビックリ、ピンチケ開発者なので一つのインスタンスにこれからもどんどんデータベース詰め込む予定です。Cloud BuildとCloud Runについては最初は敷居が高かったですが慣れてみればなんてことないですね、一回覚えちゃえば他の言語でも応用が利くので嬉しい。

### Auth0
ログイン機能をここまで簡単に実装できる事に驚くばかりです。これがなければこのサービスは完成しませんでした。

## 反省
### React初心者
Reactが初めてだったので初期に書いたコードは今見たらどん引きするような内容に、たぶん数ヶ月経ったら今書いてるコードにもどん引きしそう。まあこれはしょうがないですね。具体的な反省を言うとReact QueryかSWR使えば良かったなってことです。

### やっぱりMVC
バックエンドのController-Service-Repository(インターフェースあり)というアーキテクチャはちょっとこの複雑さなら重すぎたなってのを感じています。やっぱりこれぐらいだったらMVCがちょうど良いですね、APIなのでVはありませんが。

### 吹っ飛んだ！
本番環境のDBを吹っ飛ばした話です。スキーマ比較ツール使って本番環境から空っぽの検証環境DBにテーブルを作ってあげようとしたら向きが逆になってることに全てが終わってから気付く。結果、バックアップがあったのでなんとか復旧。DB操作は慎重に。

## 最後に
ここまでお読みくださりありがとうございます。
というわけでここまで説明してきたこのアプリですが現在利用者1人だけです。ちなみに自分です。
自分1人のためであってもしこしこ作るのは楽しいのですが、せっかく作ったんだから一人でも多くの人に使って欲しいです。
なので良かったら使ってくださると幸いです。
phpMyadminのユーザ切り替えでハマった話

## 背景
ポートフォリオを開発している中でエラーではないが実装で少々詰まった。検証がてらphpでログイン機能の実装をすることが今回詰まっているところの問題解決に一番近いと感じログイン機能の実装を選んだ。phpMyadminでDB操作していたらユーザ切り替えに少し手こずったため、メモ程度に残しておこうと思った。

## 開発環境
XAMPP Control Panel v3.3.0を使用
ソフトウェア|バージョン
---|---
OS|Windows 7 Home Premium
WEB|Apache2.4.48(Win64)
DB|mysql Ver.15.1
AP|PHP 8.0.9

## 今回発生した事象
rootでphpMyadminにログイン中にログアウトしようとしてログアウトボタンを押下しても処理がループし、rootで再ログインしてしまう。

## 原因
xamppのインストールディレクトリ内に配置されているconfig.inc.phpファイルの以下の記述がrootになっていた。
※下記に記述している'p@ssw0rd'は本記事のためのダミーのパラメータのため実在しません。
```config.inc.php
<?php 
   // ＝＝＝＝＝＝＝＝＝＝＜省略＞＝＝＝＝＝＝＝＝＝＝
   $cfg['Servers'][$i]['user'] = 'root';
   $cfg['Servers'][$i]['password'] = 'p@ssw0rd';
   // ＝＝＝＝＝＝＝＝＝＝＜省略＞＝＝＝＝＝＝＝＝＝＝
?>
```

## 対策
config.inc.phpファイルの以下の記述をroot以外の任意のユーザ名とパスワードに書き替えることで解決。
```config.inc.php
<?php 
   // ＝＝＝＝＝＝＝＝＝＝＜省略＞＝＝＝＝＝＝＝＝＝＝
   $cfg['Servers'][$i]['user'] = '[任意のユーザ]';
   $cfg['Servers'][$i]['password'] = '[任意のパスワード]';
   // ＝＝＝＝＝＝＝＝＝＝＜省略＞＝＝＝＝＝＝＝＝＝＝
?>
```

## 感想
普段はCLI作業が好きで基本的にはコマンドで何でも処理することが多いのですが、今回に限ってはなぜかGUIで作業を進めていた。まぁ無駄知識が増えてしまったけど、これもこれで良い技術の勉強になったのでよしとしましょうｗ

## 調査で参考にしたサイト
http://hirota2-tech.blogspot.com/2011/11/phpmyadmin.html
tableau Tips ~グラフで実数と%の両方を表示する方法~


# はじめに
業務でtableauを使ってダッシュボードの作成を行っているのですが、
たまに作り方でハマってしまうことがあります。

毎回作成方法を思い出すため過去に作ったものを探すのも大変なので
備忘録として作成しました。

# やりたいこと
![スクリーンショット 2022-09-26 23.57.302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1522066/b179b048-988c-42cc-57e9-7e0236c5d6fd.png)
上図の様なビューを作ります。
具体的には、実数と%(比率)を同一グラフに表示させるビューを作ります。
※データはtableauのサンプルデータのスーパーマーケットを使用
　regionごとにsalesがいくらで、それが全体の何%となるのかを一つのビューで再現します。

# 手順
まずは、regionごとにsalesがいくらになるかの円グラフを作成します。
①マークを円グラフに設定し、「表」のregionをマークの色・ラベルの上にドラッグアンドドロップします。
②「表」の　salesをサイズ・角度・ラベルの上にドラッグアンドドロップします。
アウトプットは以下の通り。
![スクリーンショット 2022-09-27 1.00.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1522066/dc6550dc-c3ae-f6a1-4605-3b6611a06c7d.png)

次にregionごとにsalesが何%になるかのグラフを作成します。
③ラベルの上にドラッグアンドドロップしたsalesを右クリックし、「簡易表計算」→「合計に対する割合」の順に選択。
![スクリーンショット 2022-09-27 1.03.172.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1522066/0ba59a5b-6f52-b5eb-2de8-b9382f8f643e.png)
アウトプットは以下の通り。
![スクリーンショット 2022-09-27 1.09.212.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1522066/53163428-4329-3008-1a4b-1a1610a959c8.png)
④salesを%(比率)に変更したため、再度salesをラベルの上にドラッグアンドドロップします。
![スクリーンショット 2022-09-27 1.19.125.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1522066/36bced8a-08e4-b0a2-36f0-a8852507eb72.png)
以上で完成となります。
一番初めに提示したビューの形となります。

上記の通り実施すれば簡単ですが、下記作成の際の注意点となります。
・salesの実数グラフを作成した後、設定したsalesのカードを%(比率)に変更し、再度salesの実数を設定してください。
※ 今回　salesのラベルを複数個使用しますが、tableauは同一のラベルは設定できないため、実数のままsalesを2つ設定しようとしても
　設定できません。私はそこでハマってしまい、対応に時間を要しました。
　別の対応策としては、salesを複製しsales2などとすれば上記の様に%に一度変更する必要はありません。ただ、カラムが増えてしまうのであまりお勧めできません。

また、今回は円グラフを使用しましたが、別のグラフでもほぼ同様の設定方法で作成可能です。

# おわりに
今回は上記の形を使って作成しました。
他にも方法はありますが、皆さんの解決の方法の一つとなれば幸いです。

今後もこの様な形でtipsを投稿していければと思います。
constで定義したオブジェクトと配列のプロパティは変更が可能

# はじめに
JavaScriptを書いてて、初歩的な箇所を勘違いしていたので、忘れないようにメモ。

# constで定義したオブジェクトと配列のプロパティは変更が可能
```javascript
// constで定義したオブジェクトのプロパティの変更が可能
const val = {
  name: "sasayoshi",
  age: 31
};
val.age = 30;
console.log(val);

// constて定義した配列の中身は変更が可能
const val2 = ["aaa", "bbb"];
val2[0] = "hoge";
val2.push("huga");
console.log(val2);
```
constで定義したオブジェクトと配列のプロパティは変更ができる。
![スクリーンショット 2022-09-27 20.47.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95954/b9de99f6-a279-6092-6987-f6a542ea75bd.png)
AWS Certified Database - Specialty試験の受験記録

https://qiita.com/murapon/items/323734511df840ac845f

に続いて、試験を受けてきました。

## 学習内容

### 1. 公式サイトで確認
https://aws.amazon.com/jp/certification/certified-database-specialty/

デジタルトレーニングを一通りやってみました。

### 2. 書籍で学習
https://www.amazon.co.jp/gp/product/4839975078/

すごくわかりやすいです。発売は1年ほど前ですが、情報が古くなっていることもなく十分使えました。
この本の内容をきちんと理解して覚えていれば、合格できるかと思います。

### 3. 問題を解く
https://www.udemy.com/course/practice-exams-aws-certified-database-specialty-coupon/

今回は問題集としてこれを使いました。50問×3回分で全150問ですが、問題が重複している箇所があり、実質130〜140問くらいかなと・・。
重複していた以外は良い問題が多かったのでおすすめです。
この問題集と、本の問題（65問）を何度か繰り返した後で、公式サイトの模擬試験をやったところ、正答率3割という結果に終わったので、かなり不安になりました・・・。
模擬試験と、公式サイトのサンプル問題も、9割以上解ける状態にしてから試験を受けました。

## 試験振り返り
模擬試験が正答率3割だったので不安でしたが、半分くらいは学習した内容がそのまま出てる感じでした。ただ、試験結果を見ると781点と思ったより間違えていて危なかったです・・。
My Assignment Expert

My Assignment Expert provides a complete assignment solution for students worldwide. To submit your most complex assignments in any subject, you can rely on their assignment writing services![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2879293/db5f58ce-4567-c91f-de69-2d10d5c693d0.png)
<a href="https://myassignmentexpert.co.uk/">Assignment Writing Services</a>
. Their assignment writing services are highly rated among the students in the UK. There are more than 800 PhD experts available for your hassle-free assistance. You can always trust their expert performance approach to submit your challenging assignments. My Assignment Expert is your primary academic partner for any kind of assignment task.
ErrorBoudaryを関数型コンポーネントとして定義したい

## ReactのErrorBoundaryとは？
ErrorBoundaryは、子コンポーネントで何らかのエラーが発生した時にエラー画面をフォールバックUIとして表示してくれるコンポーネントです。

2022年8月時点でも、ErrorBoundaryはクラスコンポーネントとして定義する必要があり、現在主流である関数型コンポーネントとして作成することができません。

ErrorBoundaryコンポーネントはクラスコンポーネントに、ライフサイクルメソッドである `static getDerivedStateFromError()` か `componentDidCatch()` を定義すると、作成する事ができます。


```jsx:公式ドキュメントからの抜粋
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children; 
  }
}
```
また、イベントハンドラでのエラーや、非同期処理のエラー等、以下は処理することができません。

- イベントハンドラ
- setTimeoutなどに代表される非同期コード
- サーバサイドレンダリング
- ErrorBoundary自身がスローしたエラー

これらを関数型コンポーネントでうまく扱える方法がないかなぁと探していたところ、react-error-boundaryというパッケージがあり、クラスコンポーネントでは扱えないエラーも簡単に処理できそうだったので、試してみました。

## react-error-boundaryを試してみる
react-error-boundaryは、レンダー時のエラーを扱いやすくしてくれるラッパーです。
インストールや基本的な使い方は公式ドキュメントを参照してみて下さい。

https://github.com/bvaughn/react-error-boundary


エラー発生時に表示するコンポーネントを追加します。
渡ってきたpropsからエラー情報を取得して表示します。

```jsx:components/ErrorBoundary/index.js
import React from "react";

export const ErrorFallback = ({ error, resetErrorBoundary }) => {
  return (
    <div>
      <h1>エラーが発生しました</h1>
      <p>{error.message}</p>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
};
```
続いて検証のために、一定の確率でエラーを起こすコンポーネントを作成します。

```jsx:components/SamplePage/index.js
import React from "react";

export const SamplePage = () => {
  const random = Math.random();

  if (random <= 0.5) {
    throw new Error("Something went wrong");
  }

  return (
    <div>
      <h2>SamplePage</h2>
    </div>
  );
};
```

最後にフォールバックUIを表示させたいコンポーネントを、react-error-boundaryからimportしたErrorBoundaryでWrapします。

```jsx:src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import { ErrorBoundary } from "react-error-boundary";
import App from "./App";
import { ErrorFallback } from "./components/ErrorBoundary";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <ErrorBoundary FallbackComponent={ErrorFallback}>
    <App />
  </ErrorBoundary>
);
```

これでエラー発生時に代わりのUIを表示する事が出来ました。
gif画像にある「Try againのボタンには、propsの`resetErrorBoundary`に指定されているコールバックを実行することで、少し時間を置いてからリカバリーするという選択肢もユーザーに提供する事ができます。(リカバリーする状況であれば)

![画面収録 2022-09-27 22.57.00.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/385fa18b-4080-d236-8d1d-7cad5ec218a7.gif)

## 最後に
ドキュメントを読むと、イベントハンドラや非同期処理のエラーまで扱えるようになるので、クラスコンポーネントのErrorBoundaryで扱えないものも考慮したい場合、手軽に扱えそうなので、良い選択肢だと思います。
PDOException(code: 0)でつまづいた話

#  PDOException(code: 0)

PHPでサーバーを立て、接続したところInternalServerが発生。
ログを確認するとPDOException(code: 0)とのエラーログ。

どうやら、MySQLとの接続がうまくいってないらしい。


## 環境

- Ubuntu18.04
- php 8.0.23


## 試したこと

### 設定の確認

.envファイルの確認。DB設定が間違っていないか確認。


### Install package

```shell
sudo apt-get install php-mysql
```

### PHP driverの確認
以下のコードを実行して単純にドライバがないのかの切り分け。

```php
<?php
try {
    $pdo = new PDO('mysql:host=localhost;dbname=sample;charset=utf8mb4','admin','P@ssw0rd');
} catch (PDOException $e) {
    exit($e->getMessage().PHP_EOL);
}
echo('ok'.PHP_EOL);
?>
```

```shell
php sample.php
```

以下のメッセージが出力。
```text
could not find driver
```

## 解消

以下の記事を参考に、php-mysqlnd のインストール。

https://www.suzu6.net/posts/198-could-not-find-driver/


```shell
sudo apt-get install php-mysqlnd
```


すると、以下のような出力が。
```shell
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package php-ctype is a virtual package provided by:
  php8.0-mysql 1:8.0.23-1+ubuntu18.04.1+deb.sury.org+1
  php7.4-mysql 7.4.2-6+ubuntu18.04.1+deb.sury.org+1
  php7.3-mysql 7.3.14-6+ubuntu18.04.1+deb.sury.org+1
  php7.2-mysql 7.2.27-5+ubuntu18.04.1+deb.sury.org+2
  php7.1-mysql 7.1.33-9+ubuntu18.04.1+deb.sury.org+1
  php7.0-mysql 7.0.33-20+ubuntu18.04.1+deb.sury.org+1
  php5.6-mysql 5.6.40-21+ubuntu18.04.1+deb.sury.org+1

You should explicitly select one to install.
```
どうやら自分のPHPのバージョンに合わせて明示的にインストールする必要があるらしい。

```shell
sudo apt-get install php8.0-mysql
```

これを実行後、先の`sample.py`がOKと出力され根本のサーバーエラーも解消した。

`sudo apt-get install php-mysql`実行時にバージョンに合わせてインストールしてくれてるように見えたが、ダメだった(?)みたい。


## 参考記事

https://symfoware.blog.fc2.com/blog-entry-2452.html

https://www.suzu6.net/posts/198-could-not-find-driver/
【Swift】$0ってなに？？？

# はじめに
こんな感じで当たり前のように出てくる`$0`はなんなのでしょうか
```swift
answers.map { $0.text }
```
ついさっき理解した(たぶん)ので記事にしときます！

# $0の正体
**結論**
[クロージャ](https://swift.codelly.dev/guide/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3/#%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3%E5%BC%8F%E3%81%AE%E5%AE%9A%E7%BE%A9)の省略記法
$0は引数の1つ目
$1は引数の2つ目
•
•
•

# 例えば？
このようなクロージャがあったとします。
```swift
func test(callback: (Int) -> Void) {
    callback(1)
}
```
通常の場合はこのようになります。
```swift
test { int in
    print(int)
}
```
これを省略記法を使用して書くとこのようになります。
```swift
test {
    print($0)
}
```

かんたん！！

# おわり
この記法がよく使われている`map`, `filter`, `reduce`とかはなんか難しそうで避けてました笑
でも理解したら意外と簡単でびっくり！！
これからは使っていこうと思います！！
素の JavaScript で Google Map 風の拡大縮小機能を作る

# やりたいこと
- google mapのように「スクロールしたとき、マウスの位置を中心に拡大する」機能を作りたい。
- 画像の拡大縮小ライブラリは存在するが、それ以外のDOMでも同様に動くようにしたい

# コード
### html

```html
<!-- boardが枠 / boxが拡大される本体 -->
<div id="board">
    <div id="box" >
        <img id="image" src="image.png">
        <div id="dom"></div>
    </div>
</div>
```
### css
```css
#board {
    width:500px;
    height:500px;
    border:3px solid green;
    overflow: hidden;
}
#box{
    width:500px;
    height: 500px;
    transition-duration: 200ms;
}
#image{
    width: 500px;
    height: 500px;
}
#dom{
    position: absolute;
    top:30px;
    left:30px;
    width: 30px;
    height: 30px;
    background:red;
}
```
この辺は適当に自分の作りたいものに合わせて

### javascript
```javascript
const board=document.getElementById('board')
const box=document.getElementById('box')

let scale=1
let pos={
    x:0,
    y:0,
}

box.style.transformOrigin="0 0"

board.addEventListener('wheel',(event)=>{
    event.preventDefault()

    let mousePos={
        x:event.clientX,
        y:event.clientY,
    }

    if(event.deltaY>0){
        scale*=0.9
        pos.x=pos.x*0.9+mousePos.x*0.1
        pos.y=pos.y*0.9+mousePos.y*0.1

    }else if(event.deltaY<0){
        scale*=1.1
        pos.x=pos.x*1.1-mousePos.x*0.1
        pos.y=pos.y*1.1-mousePos.y*0.1
    }
    
    box.style.transform=`translate(${pos.x}px,${pos.y}px) scale(${scale})`

},{passive:false})
```

# 何をやっているか
## wheelイベント
マウスホイールを動かしたときに発火するイベントが存在する。
```event.clientX```でイベント発火時のマウスの位置（これは拡大率にかかわらず、画面左端からの距離に依存する）が取得できる
```event.deltaY```でページの移動幅(?)のような数値が出る→これが正なら拡大/負なら縮小と判断できる
　
これを利用して、現在の拡大率を保持しておく→イベント発火→deltaYの正負に基づいて拡大率を調整→要素のstyle.transform属性を書き換え　の流れでホイールと同時に要素を拡大できる

## 位置調整
計算のしやすさの観点から、transformOriginを ```(0,0)``` （左上）にして話を進める
純粋に「ホイールの分だけscaleを大きくする」実装をすると、左上を中心に拡大されてしまい、想定と違う動きをする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2878555/334409c7-5985-5932-d5d2-bbb1298b0227.png)

そこで、scaleと同時にtranslateを使ってマウスの位置が拡大の中心になるように（無理やり）調節する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2878555/8795b19a-204a-ba3f-9318-f9045fe0cb4a.png)


### 具体的な計算式について
拡大によって生じるずれは、要素端からのマウスの位置の1.1倍（今回の場合）なので、要素のtranslateXを保持しておき、event.clientXからtranslateXを引いたものに1.1をかけた値を補正値として、translateX分に加算すればよい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2878555/40b2e6b5-8226-1b94-f849-771f3499831b.png)

あとはごにょごにょ計算すると次の式が出てくる。
```
要素のtranslateX = 要素のtranslateX*1.1 - マウスのevent.clientX * 0.1
```

縮小及びyについても同様の考えで式を出せば完成
LINE×GAS｜問い合わせフォームを作成

:::note warn
本記事に記載のコードの中身については、全てを1から私が記載したわけではありません。
こちらの記事は、あくまでも参照元に倣って自分でも作ってみて、つまづいたポイント・自分で追加調査したところ・追加改造を記録した記事です。
:::

# ゴール

GAS、スプレッドシート、LINE公式アカウントを用いて、問い合わせフォームを作る。なお、詳細は引用・参照元に書かれているので、この投稿では自分向けの備忘録とする。

**▼ゴールイメージ**（[引用元](https://specialman9999.github.io/20210511handson/#0/)）
![](https://storage.googleapis.com/zenn-user-upload/b940b62e225b-20220927.png)



# つまづいた部分

ドキュメント通りに作成して「実行」をクリックしたらエラーが発生。

```js:
TypeError: Cannot read property 'postData' of undefined
doPost	@ inquiry.gs:20
```
![](https://storage.googleapis.com/zenn-user-upload/14bd3848e0c9-20220927.png)


# エラーの原因

そもそも「実行」ボタンは今回は押す必要がないらしい。
▶︎[解説](https://www.youtube.com/watch?v=h0Jui-mJHPQ&t=3015s)

エラーの原因は、function doPost(request)はデータを受け取った時に作動するファンクションだから、実行やデバッグ時にはデータを受け取ってなくて、エラーが発生しているらしい。
▶︎[解説](https://www.youtube.com/watch?v=h0Jui-mJHPQ&t=3170s)

ということで、再度デプロイし直したら、無事に動きました！

**▼実際のLINE画面**
![貼り付けた画像_2024_11_09_18_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/338b174b-c6ee-58dc-c78c-82fbfb249bee.png)


**▼実際のスプシ**
![貼り付けた画像_2024_11_09_18_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/d26764e7-de9e-bd31-90bb-f5ce8bcc6537.png)




# 追加改造｜自動でメッセージ応答

## ゴール

「おすすめ」と質問したら、自動で応答するように設定を変更。
![](https://storage.googleapis.com/zenn-user-upload/c3d783414ad3-20220927.png)



## やり方
**①LINE Developersで作成したチャネルを表示**
![](https://storage.googleapis.com/zenn-user-upload/ccc6e8029a22-20220927.png)

**②「応答メッセージ」を編集**
![](https://storage.googleapis.com/zenn-user-upload/64bbab474261-20220927.png)
![](https://storage.googleapis.com/zenn-user-upload/f8cf778727fa-20220927.png)
![](https://storage.googleapis.com/zenn-user-upload/73b679fa87bd-20220927.png)
![](https://storage.googleapis.com/zenn-user-upload/f145190befee-20220927.png)

**③応答メッセージを作成**
詳しい作成方法は画面を見ればわかります。プレビュー画面があるの、めっちゃありがたい！
![](https://storage.googleapis.com/zenn-user-upload/1de8745bb1d5-20220927.png)

**④テスト**
いい感じに動いたけど、もともと設定されているGASが作動してしまって、名前を入力するように求めてしまった。
![](https://storage.googleapis.com/zenn-user-upload/8835e7ae97e1-20220927.png)


## 要改善ポイント｜不要なタイミングでGASを動作させない
そもそもGASでしたかったのは、ユーザから送信されたアドレス・名前などの情報をスプシに記録すること。ユーザへの返事はGASではなく、LINEのメッセージ応答機能を用いた方が改修しやすいし、ユーザから送られてきた内容に応じた返答ができるから、ベターなはず。

ちょっと、現時点では技術力不足なので改善ができたら追記する。

**「スプシの”現状ステータス”が”finish”だったら、GASによるメッセージ応答はしない」**
もしくは
**「スプシの”現状ステータス”が”finish以外”だったら、GASによるメッセージ応答をする」**

っていう条件分岐をつけてあげれば解決しそう。


# やってみた感想

要改善ポイントさえ改善できれば、普通にお店で使えるものになりそう。
なにより、自動メッセージ応答が想像以上に簡単にできて驚き。これはお店をやってる人なら使わない理由はない。
テストではなく、実際に何かに使ってみようかな〜


# 引用・参照
https://specialman9999.github.io/20210511handson/#0

https://youtu.be/h0Jui-mJHPQ
目指せ！第１４回ＵＥＣ杯コンピューター囲碁大会＜本編＞ Step [O11o_3o0] カーネルのインタープリター

目指せ！第１４回ＵＥＣ杯コンピューター囲碁大会＜本編＞ Step [O11o_3o0] カーネルのインタープリター

# 連載の目次

📖 [目指せ！第１４回ＵＥＣ杯コンピューター囲碁大会＜本編＞](https://qiita.com/muzudho1/items/744f6051954525878b84)  

# Step [O11o_3o0] カーネルのインタープリター

👇 以下のファイルを新規作成してほしい  

```plaintext
  	📂 kifuwarabe-uec14
	├── 📂 kernel
	│	├── 📄 go.mod
👉 	│	├── 📄 kernel.go
 	│	└── 📄 logger.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
 	└── 📄 main.go
```

```go
// BOF [O11o_3o0]

package kernel

import "strings"

const geta = 1 // Japanese wooden clogs. Used to convert bases and ordinals.

// Kernel - カーネル
type Kernel struct {
	// Position - 局面
	Position *Position
}

// NewDirtyKernel - カーネルの新規作成
// - 一部のメンバーは、初期化されていないので、別途初期化処理が要る
func NewDirtyKernel(gameRule GameRule, boardWidht int, boardHeight int) *Kernel {
	var k = new(Kernel)
	k.Position = NewDirtyPosition(gameRule, boardWidht, boardHeight)
	return k
}

// Execute - 実行
//
// Returns
// -------
// isHandled : bool
// 処理済なら真
func (k *Kernel) Execute(command string, logg *Logger) bool {

	var tokens = strings.Split(command, " ")
	switch tokens[0] {

	// この下にコマンドを挟んでいく
	// -------------------------

	// この上にコマンドを挟んでいく
	// -------------------------

	default:
	}

	return false
}

// EOF [O11o_3o0]
```

## Step [O11o_3o1o0] 外側のインタープリターから呼び出す

👇 以下の既存ファイルを編集してほしい  

```plaintext
  	📂 kifuwarabe-uec14
	├── 📂 kernel
	│	├── 📄 go.mod
 	│	├── 📄 kernel.go
 	│	└── 📄 logger.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
👉 	└── 📄 main.go
```

👇 がんばって挿入してほしい  

```go
// ...略...

import (
	// ...略...

	"github.com/muzudho/kifuwarabe-uec14/kernel"
)
// ...略...

		// [O12o__11o_4o0] 棋譜の初期化に利用
		var onUnknownTurn = func() kernel.Stone {
			var errMsg = fmt.Sprintf("? unexpected play_first:%s", engineConfig.GetPlayFirst())
			logg.C.Info(errMsg)
			logg.J.Infow("error", "play_first", engineConfig.GetPlayFirst())
			panic(errMsg)
		}

		// [O11o_3o0]
		var gameRule = kernel.NewGameRule(kernel.KomiFloat(engineConfig.GetKomi()), kernel.PositionNumberInt(engineConfig.GetMaxPositionNumber()))
		var kernel1 = kernel.NewDirtyKernel(*gameRule, engineConfig.GetBoardSize(), engineConfig.GetBoardSize())
		// 設定ファイルの内容をカーネルへ反映
		kernel1.Board.Init(engineConfig.GetBoardSize(), engineConfig.GetBoardSize())

		/*
		...以下略...
		// [O11o_1o0] コンソール等からの文字列入力
		var scanner = bufio.NewScanner(os.Stdin)
		for scanner.Scan() {
			var command = scanner.Text()
			logg.C.Infof("# %s", command)             // 人間向けの出力
			logg.J.Infow("input", "command", command) // コンピューター向けの出力
		...以上略...
		*/

			// * これを追加する
			// [O11o_3o0]
			var isHandled = kernel1.Execute(command, logg)
			if isHandled {
				continue
			}

			/*
			...以下略...
			// [O11o_1o0]
			var tokens = strings.Split(command, " ")
			switch tokens[0] {
			*/
```

* カーネルと、自作の部分で コマンドが被ったなら、カーネルの方を優先する
  * これにより カーネルのアップデートにより 自作のコマンドが避けられることから、アップデート時は動作テストしてほしい
ServerlessFrameworkでLambda(Go)を動かしたらファイルが見つからずエラーになる

# はじめに

GoをLambdaにデプロイしたのですが、ファイル読み込みで多くの時間を使ったのでまとめます
ServerlessFrameworkを利用したLambdaでファイル読み込みをする方の参考になればと思います

# 問題

Lambda(go)で以下のコードを実行していました
ここでは`config.ini`という設定ファイルを本番環境では、`main`の実行ファイルと同じ階層にあるものを読み込むようにします

しかし、このコードでは`not found ./config.ini`となってしまいます

```go:config.go
	path := "/go/src/config/config.ini"

	if os.Getenv("ENV") == "production" {
		path = "./config.ini"
	}

 	cfg, err := ini.Load(path)
```

# 解決方法

現在serverless frameworkを利用して`serverless.yml`で`main`と同じフォルダに`config.ini`がアップロードされている状態です

以下のようにファイルパスを変更しました

```go:config.go
	if os.Getenv("ENV") == "production" {
		path = "/var/task/bin/config.ini"
	}
```

Lambdaのファイルパスは`/var/task`いかにアップロードされるようです (serverless framework)

# おわりに

この設定で色々遠回りしてしまいましたが、最後はすっきりと書けました
goのテストの関係で相対パスだとファイルの位置でエラーになってしまうので、絶対パスにしてみました
【Git】GitHub CLIの導入方法

## インストール
Macの場合
```zsh
brew install gh	
```
または
```zsh
sudo port install gh
```

Windowsの場合
```zsh
winget install gh
```

インストールされたか確認する

```zsh
$ gh version
gh version 2.16.0 (2022-09-21)
https://github.com/cli/cli/releases/tag/v2.16.0
```

## ログイン
インストールができたらログインをする

```
gh auth login
```
【Vue3】親<->子間のコンポーネントメソッド発火方法

# はじめに
こんにちは。
今回はVue3で親子間のコンポーネント内メソッドの発火方法を紹介していきます。
子から親のメソッドを発火させる方法はご存知の方多いと思いますが親から子のメソッドを直接発火させる方法も紹介していますので参考になれば幸いです。
<font color="red">#注意：Vue3 composition apiの記法で紹介しています。</font>

# 前提：親と子コンポーネントを作成
まずは親コンポーネントと子コンポーネントを作成していきます。
今回は分かりやすいようシンプルなものにしています。
```Child.vue
<template>
  <button
    @click="emitEvent"
  >
    子コンポーネント
  </button>
</template>

<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api'

export default defineComponent({
  emits: ['childEmit'],
  setup(props, {emit}){
    const emitEvent = () => {
      emit('childEmit')
    }

    const halloFromChild = () => {
      alert('Hello from Child!')
    }

    return {emitEvent, halloFromChild}
  }
})
</script>
```
```Parent.vue
<template>
  <div>
　　　　  <button
    　　@click="halloFromChild"
  　　　　>
    　　親コンポーネント
  　　　　</button>
    <Child
      ref="child"
      @childEmit="helloFromParent"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api'
import Child from './Child.vue'

export default defineComponent({
  components: {
    Child
  },
  setup(props, {emit}){
    const child = ref(null)

    const helloFromParent = () => {
      alert('Hello from Parent!')
    }

    const halloFromChild = () => {
      child.value.halloFromChild()
    }

    return {child, helloFromParent, halloFromChild}
  }
})
</script>
```

# 子→親のメソッドを発火する
`emit`を使用します！
子コンポーネントの方で、 `emitEvent()` というメソッドを叩くと、 `childEmit` というイベントが親コンポーネントで発火するようになっています。
```js
const emitEvent = () => {
  emit('childEmit')
}
```
そして、この発行された `childEmit`イベントを親側で受け取り、実行したいメソッドへと渡してあげます。
今回の例では`helloFromParent`メソッドが実行されます。
```vue
<template>
  <div>
　　　　  <button
    　　@click="halloFromChild"
  　　　　>
    　　親コンポーネント
  　　　　</button>
    <Child
      ref="child"
      @childEmit="helloFromParent"  ← この部分！
    />
  </div>
</template>
```

# 親→子のメソッドを発火する
refのテンプレート参照を使用します！
親コンポーネントのこちらのメソッドに注目してください。
```js
const halloFromChild = () => {
  child.value.halloFromChild()
}
```
`ref`は指定した対象のDOM要素を引っ張ってこれるもの、と捉えている方も多いと思いますが、`ref`をComponentに指定してあげると、Componentインスタンスがまるっと取得できます。
そして取得したコンポーネント内にあるメソッドを発火させることができます。
これだけで親→子のメソッドを発火させることができます。
### Tips ： refの型定義
TypeScriptを使用している場合refに型定義をしたいことがあると思います。
refでコンポーネントを参照した場合にどうやって型定義をするか紹介します。
```ts
const componentRef = ref<InstanceType<typeof HelloWorld>>()
```
上記のように記述することで型定義することができます。これで補完や型チェックも効くようになるので活用してみてください！

# まとめ
今回はコンポーネント間のメソッド発火方法を紹介しました。少しでも参考になれば幸いです！
Linux / Webサーバーの基本

# 概要
初歩的な内容ですが基本が大事なのでアウトプットしていきたいと思います。随時追記していきます。
# Linuxとは
Linuxとは、Mac OSやWindowsと同じ<font color="red">OS</font>の一種です。
<font color="red">OS</font>とは、『オペレーティングシステム』の略でコンピューターを管理しているソフトウェアのことです。パソコンには必ずOSが搭載されています。ExcelやWordなどで作成したテキストなどが正しく記録保存され、保存したデータを読み込んで閲覧できたりするのは、OSが機能しているからです。

Linuxにも種類があります。

・Red Hat EL,CentOS
・Debian,Ubuntu
・SUSE,openSUSE
・その他

この中でもRed Hat EL,SUSE,openSUSEなどは有償のOSになります。無償のものは、サポートが受けられなかったり、保守ポリシーを自分たちでしっかり確認する必要があります。その点、有償のものはこの問題が解決され一定期間のサポート体制が整っています。
Linuxは自由に改良できるオープンソースのOSなので、必要な分だけサーバーを構築できるのが強みです。本来、安全性や速度をキープするためには多くのサーバー構築が必要になり、その分のコストも発生するのですが、Linuxは無料であるため、コストを大幅に削減しサーバーを立てることができます。
# Linuxの種類（ディストリビューション）
上記で上げた通りLinuxにはいくつか種類があります。それを、<font color="red">ディストリビューション</font>といいます。
OSにはカーネルと呼ばれる中心的な機能を持つソフトウェアがあります。メモリやディスクの読み書き、プログラムの起動通信、など本当に基本的な機能しか備わっていません。そこに、外部の命令を実行するプログラムを付け加えることで、はじめてOSとして機能するようになります。

簡単にいうと、OSを一つの組織とみなした場合カーネルさんは中心人物なのですが、カーネルさんだけでは組織の運営が成り立ちません。そこで、シェルさんやデーモンさんといったソフトウェアを使うことで、初めて組織として成り立つようなイメージです。
LinuxはOSの名前ですが厳密にいうとカーネルの名前です。
Linuxが欲しい時にカーネルのLinuxだけをもらっても使えませんし、その他諸々のソフトウェアを自分で集めるのは大変です。
そこで、カーネルやその他諸々のソフトウェアを一緒にした状態で配られています。このようにOSとしてのLinuxなどの配布形態のことを<font color="red">ディストリビューション</font>といいます。

現在、主流のディストリビューションは次の二つです。

①Red Hat系
　Red Had社が配布しているディストリビューションRed hat Enterprice Linuxを中心とした系列です。互換OSが配布されており、 
　それがCent OSです。基本的に両者は同じものですが、Cent OSには、Red Hatの強力なサポートなどはありません。

②Debian系
　Debianというコミュニティでまとめられたディストリビューションを中心とした系列です。Ubuntuはデスクトップ利用でも人気　があります。
　LTSと呼ばれる長期サポートがあり5年間にわたるセキュリティアップデートが提供されるバージョンもあり、サーバー用としても　人気があります。

# サーバーOS
パソコンは買ってきたらすぐに使えるように様々なソフトウェアが既に準備されていますが、サーバーの場合は、自分で揃えていかなければなりません。
サーバーの基本は最小限です。最小限のソフトウェアを入れ、最小限のものだけを動かし、最小限の権限を与えます。これには理由があって、一つは24時間365日稼働させるため、機器への負担を減らすということです。余分なものが動いていれば、その分CPUやメモリに負担がかかってしまいます。
もう一つは、セキュリティ的な問題で、特にインターネット上に設置するサーバーの場合は、サービスが多く動いていたり、余計な権限があったりするとそこから攻撃のとっかかりとされてしまう可能性があります。

これらを防ぐために、最小限としなければならないのです。
新入社員がPJでモブプロに2週間参加してみた

**本記事、新入社員の私がアジャイルのPJでモブプロに参加してみた時の感想となっております。
初めての投稿なので稚拙で読みにくい部分があるとは思いますが何卒。**

> モブプロとは？って方向け
> https://qiita.com/mzmz__02/items/26a34e3e3f2cb870cfa2


# 経緯
フロントエンド未経験の新入社員の私が一人でできそうなタスクが現状なかったため(謝罪)、1つのタスクを3人で取り掛かるモブプロをPJで初めて採用していただいた。


今回実際に使用したモブプロの手法は、**タイピスト1人**、**ナビゲーター2人**の体制で取り組んだ。
タイピストとナビゲーターはキリの良いタイミングで交代しつつ作業していった。

#### モブプロのアクター
| 人物 | 説明 |
|:-:|:-:|
| 私 | 8月から本格的にPJに参加したバリバリ新入社員。  |
| A先輩  | PJ立ち上げ時からいらっしゃる、一番優しい大先輩。 |
| B先輩  | 話やすい場を率先して作ってくれる先輩。|

#### モブプロ開発環境
常にリモートでの作業
通話はSlack
開発はvscode
画面共有はMicrosoft Live Share -> https://visualstudio.microsoft.com/ja/services/live-share/

# 実施してみた感想
実際にリモートで2週間先輩に囲まれながらモブプロを実践してみて、新入社員の私からの感想は・・・・**楽しかった**。
ただ単に楽しかっただけでなく、得られるものが多すぎた。

A先輩がモブプロの時に重要視していたことは、**3人共同じ理解度で進むこと**だった。
そのため、私がタイピストの時に理解できているかを逐一確認してくれていたし、B先輩にも確認していた。
同じ理解度で進むことで、**既存コードの理解や初めてのフロント言語に対しての理解が格段に上がった**と感じた。

B先輩は明るく話しかけてくれて、**話しやすい雰囲気**を作ってくれていたと感じた。(所説)
モブプロ実施前の私は2人の先輩と一緒に作業する時に、迷惑をかけないか。イライラさせてしまわないか。の面で不安だった。
そんな不安と緊張も5分経たずに打ち消してくれたのはB先輩のおかげだと思っている。
これ以来他のメンバーの方々と話す時も、気兼ねなく話せるようになっている気がする。

**総合して、本当にやってよかったなぁ・・・と感じている。**

## メリット
実施してみて、私がかなりよかったと感じているのは十分察していただけていると思う。
じゃあ、実際なにがよかったと感じたか。それがコチラ。

- フルリモートで壁があった先輩に、私自身が打ち解けられた
- 先輩との距離が近づいたため、今後も話しかけやすくなる
- 教えてもらいつつ開発していくため、理解のスピードが速い
- A先輩の知識を新人の私だけでなくB先輩に共有できる(B先輩もしかり)
- 雑談も挟みつつ開発していくため、一人でタスクをこなす時よりも集中力が持続する
- 結果的にそこそこのタスクが遂行できるため、達成感が生まれる
- 3人だとコードレビューをしながらになるので、一石二鳥

## デメリット
デメリットなんてあるの？あります。

- 新人がナビゲーターの場合、もう一人のナビゲーターに考え・指示を任せてしまう
- 新人がタイピストの場合、説明待ちになってしまって自分で考えなくなる
  * ↑ 私さん・B先輩さんはどう思いますか？ってA先輩が逐一聞いてくれていました。
  

- 先輩のタスクの着手状況が止まる
  * モブプロのタスクに付きっ切りだと先輩のタスクが一時停止となりがち。心から感謝しつつ取り組もう
- 集中しすぎて休憩取らなくなりがち
  * モブプロ後半はメンバーの誰かが離席するタイミングで休憩取っていた。
- モブプロに向くタスク・向かないタスクがあるため、着手する前に選別する必要がある

## 後日談
PJのチーム内でモブプロの先駆者となったわけだが、先駆者3名のモブプロに対しての感触がよかったため実施したスプリントのレトロスペクティブで今後もモブプロを実施していく話になった。

その後チーム内でモブプロだけでなく、ペアプロの頻度も増えた。
このような複数人での開発手法を用いるハードルが下がったと感じて、実施してよかったと新人ながら思いました。
これからモブプロを導入しようとしている方に参考になったら幸いです。

## 参考文献
https://qiita.com/mzmz__02/items/26a34e3e3f2cb870cfa2

https://qiita.com/kojimadev/items/5d0e03f3367eddc4fa67
Arduino MegaでATmega328P-AUに書き込みしてみた

## 経緯
今回は手元にArduino unoがなかったのでMegaで書き込みしてみた。
ATMega328P-AUに書き込むにあたりDIP化するため
秋月電子通商のDIP化基板を使用した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/e83c9869-0418-602b-6337-716872951e29.png)
https://akizukidenshi.com/catalog/g/gP-09581/

## 配線
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/ecbce4c2-c012-bdec-550c-af2afb584603.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/b56c1310-32dc-788a-6e04-0ad5357eb3fb.png)

## Arduino Megaを書き込み装置に変更
1、ArduinoISPをArduinoMegaに書き込み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/ed286b42-faeb-f142-00c4-21c18850b6e6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/53853b19-0ceb-5389-a2ce-ab66d204ec15.png)

2、ブートローダーをATmega328P-AUに書き込み
「ブートローダを書き込む」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/d27cc480-fca2-1d77-d2a0-93e4c19561ba.png)

3、スケッチを書き込み
以下のスケッチを書き込んだ。
ピンアサインの考え方にめちゃくちゃ苦労した。。。
このサイトのピンアサインを参考にした。
http://domoticx.com/atmega328-au-programmeren-met-arduino-als-isp/

```c
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(9, OUTPUT);  //13pinが9になるらしい
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(9, HIGH); 
  delay(1000);                       // wait for a second
  digitalWrite(9, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}
```
書き込みは以下の設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/4b856b10-daf4-f2a3-1067-fa623040b805.png)
書き込みは「書込装置を使って書き込む」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/4c1273f4-3993-f9aa-6349-ff48adffd7c3.png)

これでLチカ完了です。
"rails g"コマンドを叩いたらターミナルが固まってしまった時の対処法

はじめに
--
DBテーブルを追加する必要があり、"rails g model"コマンドを叩いたところ、ファイルが作成されずうんともすんとも言わなくなり固まってしまいました。

"ctrl + c"で終了したところ、下記のようにエラー文っぽいものが見当たらない文章が出力されて焦ったので、同じ場面の時に焦らないように備忘録にまとめようと思います。

~~~
~# bundle exec rails generate model ~
※↑ここで固まりうんともすんとも言わなくなる

※↓"ctrl + c"で下記が出力された(エラーっぽい単語が見えなくて焦りました。)
^C/usr/local/bundle/gems/spring-4.0.0/lib/spring/client/run.rb:117:in `gets': Interrupt
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client/run.rb:117:in `verify_server_version'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client/run.rb:62:in `run'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client/run.rb:42:in `warm_run'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client/run.rb:35:in `call'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client/command.rb:7:in `call'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client/rails.rb:24:in `call'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client/command.rb:7:in `call'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/client.rb:30:in `run'
	from /usr/local/bundle/gems/spring-4.0.0/bin/spring:49:in `<top (required)>'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/binstub.rb:11:in `load'
	from /usr/local/bundle/gems/spring-4.0.0/lib/spring/binstub.rb:11:in `<top (required)>'
	from /git-used-to/bin/spring:10:in `require'
	from /git-used-to/bin/spring:10:in `block in <top (required)>'
	from <internal:kernel>:90:in `tap'
	from /git-used-to/bin/spring:7:in `<top (required)>'
	from bin/rails:2:in `load'
	from bin/rails:2:in `<main>'
~~~

原因
--
結論から言うと、"spring"(railsでの開発スピードをアップしてくれるアプリケーションプリローダーというものらしい)が今回コマンドを固まらせた原因のようです。(詳しいことは分かりませんでした)

Gemfileでよく目にするやつですね。
~~~ruby
gem 'spring'
~~~

これが原因でrailsコマンドが固まってしまうことがたまにあるようです。
なので、"rails g"だけ動かなくなるような問題ではないみたいですね。

解決法
--
解決法は、"spring"を一旦止めることです。
下記のコマンドを叩いて"spring"を終了させます。(Spring stopped.が返ってくると思います。)

~~~
~ % spring stop
Spring stopped.
~~~

これを一旦stopしてあげてから、"rails g"コマンドを叩くと、しっかりファイルを作成してくれました。


わけわからん"spring"を止めてしまって良いのか
--
ネットで調べると結構"spring stopを叩こう"という記事が出てきたのですが、よくわかってないspringを止めてしまっていいのか？再起動できるのか?という不安が拭えずにいましたが、"spring stop"後にrailsコマンドを叩くと同時にspringが自動で動き出すそうです。

"spring status"を叩くとspringの状態をみれるので、自分でも確認してみるとしっかり動いていることが確認できました。(安心！)

~~~
~ # spring status
Spring is running:

  916 spring server | アプリ名 | started 1 hour ago
  975 spring app    | アプリ名 | started 2 hours ago | development mode
~ # 
~~~

参考
--
https://b0npu.hatenablog.com/entry/2016/04/11/032826