OmniAICreator/Qiita-1.07M huggingface dataset:
ReactアプリケーションをFirebase Hostingで公開する

個人的に学習した内容と詰まったところを記述していこうと思います。また、本記事はReactで作成したアプリケーションを前提に記載しています。所々怪しい部分もあるかもしれませんが、その際はコメントいただけるとありがたいです。


基本的には以下の流れで簡単にデプロイすることができます。

# Firebaseの準備
1. Firebaseに登録[Firebase](https://firebase.google.com/)

2. CLIをインストール

```
npm install -g firebase
```

3.　Firebaseへログイン

```
firebase login
```
これでFirebaseを利用できる環境になりました。
ただ、上記の手順だとログインしただけなので、firebaseの機能を利用することはできません。
プロジェクトの作成も合わせて行いましょう！
[Firebaseプロジェクトの作成（外部サイト）](https://docs.kii.com/ja/samples/push-notifications/push-notifications-android-fcm/create-project/)

# Firebaseでデプロイ
Firebaseの準備が整ったら早速デプロイです。
FirebaseのHostingを利用したデプロイはかなりお手軽で簡単にできます。
また、Firebaseのコンソール上からデプロイ履歴もみることができるので管理もしやすいです。

以下、デプロイ手順になります。

1. デプロイしたいアプリケーションのディレクトリまで移動して以下のコマンドを実行

```
firebase init
```
このコマンドを打つといろんな質問が飛んできます。今回はHostingのみの利用を前提としているので、以下のように答えてもらえれば問題ないです。

`` Which Firebase CLI features do you want to setup for this folder ?``
→ *Hosting: Configure and deploy Firebase Hosting sites* をスペースキーで選択してリターン
  スペースキーで選択してからでないとエラーになります。

```Select a default Firebase project for this directory```
→ Firebaseコンソールで作成したprojectを選択

```What do you want to use as your public directory?```
→ public (何も入力せずリターン)

```Configure as a single-page app (rewrite all urls to /index.html)```
→ Y(SPA設定されていることの確認、Reactアプリケーション前提なので問題なし)

```File public/index.html already exists. Overwrite```
→ アプリケーションにあるものを上書きしますか？という質問。基本的にNOと答える。
　（筆者は上書きしてしまい、Firebaseの初期画面がずっと出ていた。上書きされてReactのroot要素がなくなってしまったため）

以上です！
質問途中でGithubとの連携を聞かれますがその質問もNOと答えていただければOKです。


２. アプリケーションをビルド
ビルドする前に必ず確認して欲しいのが、**firebase init** したときに生成される`firebase.json`というファイルがあるのですがそこの設定を確認して欲しいです。自分はこれがわからずに結構詰まってました。

```
　　　"hosting": {
    　　　　"public": "public",

　　　　　以下略
```

ここの設定が```public```のままだとデプロイしたあと何も表示されない白い画面しか出てこなくなります。なので、ここの設定が

```
　　　"hosting": {
    　　　　"public": "build", //  ここが"build"になっていることを確認する

　　　　　以下略
```

以上を確認してから、

```
npm run build
```

を実行してください。

３. デプロイ
ここまで来ればほとんど作業は終わったと言っても良いです。あとは以下のコマンドを打てばあなたのアプリケーションはデプロイされ公開されます。

```
firebase deploy
```
デプロイが完了すると、


```
=== Deploying to '*****'...
略
✔  Deploy complete!
Project Console: https://console.firebase.google.com/project/*****/overview
Hosting URL: https://*****.firebaseapp.com
```

と表示されるので、```Hosting URL```に記載されているURLで公開されたアプリケーションをみることができます。

かなり簡単にデプロイすることができます。Firebaseは無料で使い始めることができるのでいいですね。
アルファベットと数字をそのまま読みに変換【python】

#概要
MeCabのユーザー辞書を作っているときに、アルファベットや数字をそのまま読ませたいことがあったので、コピペ用の変換表を作りました。
#コード

```Python
surface = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
yomi = "エー・ビー・シー・ディー・イー・エフ・ジー・エイチ・アイ・ジェー・ケー・エル・エム・エヌ・オー・ピー・キュー・アール・エス・ティー・ユー・ブイ・ダブリュー・エックス・ワイ・ゼット・ゼロ・イチ・ニ・サン・ヨン・ゴ・ロク・ナナ・ハチ・キュウ・ジュウ".split("・")
pronunciation = "エー・ビー・シー・ディー・イー・エフ・ジー・エイチ・アイ・ジェー・ケー・エル・エム・エヌ・オー・ピー・キュー・アール・エス・ティー・ユー・ブイ・ダブリュー・エックス・ワイ・ゼット・ゼロ・イチ・ニ・サン・ヨン・ゴ・ロク・ナナ・ハチ・キュー".split("・")

#変換辞書を作りたいとき
surface2yomi = {s:y for s,y in zip(surface,yomi)}
surface2pronunciation = {s:p for s,p in zip(surface, pronounciation)}

#mecabの辞書に登録したいとき
dic = []
for s,y,p in zip(surface, yomi, pronunciation):
  text = "{},,,1,名詞,一般,*,*,*,*,{},{},{}".format(s,s,y,p)
  dic.append(text)

print("\n".join(dic))

```
Ubuntu22.04にAndroid Studio Chipmunk | 2021.2.1をインストールし日本語化してみた

# はじめに
Android Studio4.1からはIntelliJ2020.1ベースになったため日本語化の仕方が変わります。
4.0以前のバージョンをお使いの方は、以下を参照ください。
https://qiita.com/maccadoo/items/4ce153af005df3f48e8d

|Soft          |Ver    |
|:-:           |:-:    |
|Ubuntu        |22.04|
|Android Studio|2021.2.1|


# Ubuntu日本語化
[Ubuntu 20.04.1 LTS 日本語 Remix](https://www.ubuntulinux.jp/News/ubuntu2004-ja-remix)がリリースされたため、リンク先のisoを使えば以下のレポジトリ追加は不要。

他のフェレーバーを使用した場合は、Ubuntu Japanese Teamによる20.04(focal)用追加パッケージが利用できるようになっているため、レポジトリを追加し環境を整える

```
wget -q https://www.ubuntulinux.jp/ubuntu-ja-archive-keyring.gpg -O- | sudo apt-key add -
wget -q https://www.ubuntulinux.jp/ubuntu-jp-ppa-keyring.gpg -O- | sudo apt-key add -
sudo wget https://www.ubuntulinux.jp/sources.list.d/focal.list -O /etc/apt/sources.list.d/ubuntu-ja.list
sudo apt update
sudo apt -y full-upgrade
sudo apt -y install ubuntu-defaults-ja
```

# Android Studioのインストール前準備
AVDを有効にするためにはKVMが必要とのことでインストールと権限付与を行う。ついでにadbもインストールする。

```
sudo apt -y install qemu-kvm default-jdk adb git
sudo gpasswd -a "${USER}" kvm
reboot
```

# Android Studioのインストール&日本語化
ubuntu-makeも利用可能だが、ここではubuntu標準のsnappyでインストールする。

```
sudo snap refresh
sudo snap install android-studio --classic
cd ~/.local/share/Google/AndroidStudio2021.2
wget -qO- https://plugins.jetbrains.com/files/13964/141385/ja.212.324.zip | jar xvf /dev/stdin
```

snappyは新しいバージョンがリリースされるとオートでバージョンアップされてしまう。
バージョンを固定して使いたい場合は、ubuntu-makeを使うか、Intellijを使ったほうが良い。
Intellijの場合は、channelを指定することにより、バージョンを固定できる。

```
sudo snap install intellij-idea-community --channel=2021.1/stable --classic
```
# 日本語化プラグインのインストール(GUIで日本語化)
コマンドラインで日本語化した方は飛ばしてください
ここからの手順はWindowsもmacOSも同じです。なんで、わかりにくい場合は他のサイトを参照してもらっても構いません。正し、4.0以前の記事は参考にならないので注意です。

Welcaome画面のConfigure > Pluginsから「Japanese Language Pack」をインストール。
プラグインをインストールするとIDEAの再起動をかける必要があるため、他のプラグインもインストールしたい場合は、ここで追加する。
![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253664/d2994fcd-09da-8f08-fa71-4c6798be611a.png)
![Screenshot from 2020-04-24 21-57-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253664/9102bf22-ce61-8708-a6e4-b6550bee9389.png)

これで、Welcaome画面の「Create New Project(プロジェクト画面から新規作成)」からAndroidのプロジェクトを作りビルドすることができるようになる。

# (おまけ)オレはFultterでアプリが作りたいんじゃい
Flutterもsnapでインストールできるから便利ですね(6/30にedgeチャネルから晴れてstableになりました)
##Fultter SDKインストール

```
sudo snap install flutter --classic
flutter precache
flutter upgrade
```

## IntelliJにFlutter/Dartプラグインをインストール
Welcaome画面のConfigure > Pluginsから「Flutter」をインストール。
Dartプラグインも入れるか聞いてくるのでInstallをクリック。
![Screenshot from 2020-04-24 23-00-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253664/a7393d18-cae3-c1d9-1bd6-91db8d382b53.png)


## プロジェクト画面から新規作成から
これで、Welcaome画面の「Create New Project(プロジェクト画面から新規作成)」からFlutterのプロジェクトを作りビルドすることができるようになる。
Flutter SDK pathは~/snap/flutter/common/flutterを指定。
![Screenshot from 2020-04-24 22-42-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253664/7d7a8350-0920-4ec4-be4f-77ee12ce4343.png)
javascriptで複利計算プログラム

```html

 <script type="text/javascript">
      function Calculator() {
        var rate, amount, period;
        rate = parseInt(document.myform.rate.value, 10);
        amount = parseInt(document.myform.amount.value, 10);
        period = parseInt(document.myform.period.value, 10);
        document.myform.receipt.value = fukuri(rate, amount, period);
      }

      function fukuri(rate, amount, period) {
        var receipt;
        receipt = amount;

        var str = "";
        str += "<table class=’test’>";
        str += "<tr><th>預入期間</th><th>受取金額</th></tr>";

        //預入金額＝元金×(1＋金利)/100
        //Math.round：小数点以下を四捨五入
        for (var i = 1; i <= period; i++) {
          receipt = Math.round(receipt * (1 + rate / 100));
          str += "<tr><td>" + i + "年</td><td>" + receipt + "円</td></tr>";
        }

        str += "</table>";
        document.getElementById("result").innerHTML = str;
        return receipt;
      }

      function TableClear() {
        document.getElementById("result").innerHTML = "";
      }
    </script>

  <body>
    <h1>複利計算</h1>
    <p>金利・金額・預入期間(年)を入力してください。</p>
    <form name="myform">
      <table>
        <tr>
          <th>金利</th>
          <td><input type="text" name="rate" size="22" value="4" />％</td>
        </tr>
        <tr>
          <th>金額</th>
          <td><input type="text" name="amount" size="22" value="10000" />円</td>
        </tr>
        <tr>
          <th>預入期間</th>
          <td><input type="text" name="period" size="22" value="10" />年</td>
        </tr>
        <tr>
          <td colspan="2" class="btn">
            <input type="button" onclick="Calculator()" value="計算" />
            <input type="reset" onclick="TableClear()" value="クリア" />
          </td>
        </tr>
        <tr>
          <th>受取金額</th>
          <td><input type="text" name="receipt" size="22" />円</td>
        </tr>
      </table>
    </form>
    <hr />
    <div id="result"></div>
  </body>

```
curlでXML-RPCサービスの死活監視(XMLファイル読み込みでなくコマンドラインで完結したい)

XML-RPCサーバの死活監視が必要になり、例のごとく`curl`を使ってシンプルに実現したい。

ググるとXMLファイルを読み込む方法が散見されるが、このためにファイルを追加するのは避けたいし、死活監視用に作成したメソッド(`alive`)は引数を持たないシンプルな実装。

以下のようにシンプルなXMLなのでコマンドラインに直接書きたい。
(一目瞭然ですが、メソッド名は<methodName>要素内の値で指定できます)

```xml
<?xml version='1.0'?>
<methodCall>
  <methodName>alive</methodName>
  <params></params>
</methodCall>
```

結果として、以下でいけた。以下はExampleServiceのliveメソッドを実行している。

```
curl -X POST -d '<?xml version='\''1.0'\''?><methodCall><methodName>alive</methodName><params></params></methodCall>' http(s)://<domain>:<port>/ExampleService.php
```

ポイントは以下の2つ

- `-X POST`・・・XML-RPCはPOSTメソッドなのでPOSTを指定
- `'\''`・・・シングルクォートのエスケープ   ★後で気づいたけどダブルクォートだとエスケープ不要

あとは、指定しないでも問題ありませんでしたが、プロトコルがHTTP/XMLであることを明示しておきたい場合は、ヘッダーオプションで`text/xml`を指定するとよいかもしれません。

```bash
-H 'Content-type: text/xml'
```
Xcode12の実機起動時、"no code signature found."で失敗する問題の一時対処

## 事象

XCode12にアップグレードしてから、ビルドやシミュレータ起動は出来ても実機起動時に以下のコードを吐いて失敗する問題に悩まされていました。

```
No code signature found.
Domain: com.apple.dt.MobileDeviceErrorDomain
Code: -402620388
……
```

外部ライブラリ_SwiftyTesseract_を_SwiftPackageManager_から導入した場合に発生しており、調べてみると、_Firebase_ライブラリなどでも同様の事象が発生しているらしい。

## 原因と解決方法

どうやら、導入している外部ライブラリがstaticの場合でも実機に転送し、そのバイナリのsignatureをチェックして失敗しているらしい。

[参考URL](https://github.com/firebase/firebase-ios-sdk/issues/6472#issuecomment-694449182)

基本的にはXCode12のバグのようだが、上記参考URLの通り_Edit Schema_→_Build_→_Post-actions_に、以下の_Run Script_を追加することで一時対処可能。

__なお、除去する_Frameworks_は導入しているライブラリにあわせてください__

- Shell
  - `/bin/sh`
- Provide build settings from
  - 対象のアプリ
- 内容

```
# Type a script or drag a script file from your workspace to insert its path.
rm -rf "${TARGET_BUILD_DIR}/${TARGET_NAME}.app/Frameworks/libtesseract.framework"
rm -rf "${TARGET_BUILD_DIR}/${TARGET_NAME}.app/Frameworks/SwiftyTesseract.framework"
```


XCode12が修正されるまでの一時対処として、参考まで。
vistaでquartus その45

#概要

vistaでquartusやってみた。
cpuを書いてみた。
命令を拡張する。構想編。

#dup

スタックトップをコピーする。

```
			7: //dup
			begin
				qtop2dbus <= 1;
				dbus2qtop <= 1;
				push <= 1;
			end
```

#load

スタックトップをアドレスとして、読み込む。
間接アドレッシングの実現。

```
			8: //ld
			begin
				qtop2dbus <= 1;
				cont <= 1;
			end
			begin
				ram2dbus <= 1;
				dbus2qtop <= 1;
				push <= 1;
			end
```
#store

スタックトップをアドレスとして、書き込む。
間接アドレッシングの実現。

```
			9: //st
			begin
				qtop2abus <= 1;
				cont <= 1;
				pop <= 1;
			end
			begin
				qtop2dbus <= 1;
				dbus2ram <= 1;
				pop <= 1;
			end
```
#call

スタックトップに、戻りアドレスを積む。
サブルーチンコールの実現

```
			10: //call
			begin
				qtop2dbus <= 1;
				dbus2qtop <= 1;
				push <= 1;
			end
```
#ret

スタックトップをアドレスとして、ジャンプ
サブルーチンコールの実現

```
			11: //ret
			begin
				qtop2dbus <= 1;
				dbus2pc <= 1;
				pop <= 1;
			end
```

以上。
論文まとめ：MOTS: Multi-Object Tracking and Segmentation

# はじめに
CVPR2019 main conference から以下の論文
[1] P. Voigtlaender, et. al."MOTS: Multi-Object Tracking and Segmentation", CVPR2019
のまとめ

論文へのリンク:
https://www.vision.rwth-aachen.de/media/papers/mots-multi-object-tracking-and-segmentation/MOTS.pdf

projectのサイト:
https://www.vision.rwth-aachen.de/page/mots

Githubの公式コード:
https://github.com/VisualComputingInstitute/TrackR-CNN
MIT license。Tensorflow1系。

デモ動画:
https://www.vision.rwth-aachen.de/media/papers/178/MOTS_video.mp4

# 概要
1. multi-object trackingと同時にsegmenatationも行う新たなタスク multi-object tracking and segmentation（<b>MOTS</b>）を定義した
2. そのタスクのため、KITTI dataset や MOTCallenge dataset に segmentation のアノテーションを加えることで、新たな datasetを生み出した
3. これの評価のため、新たなメトリクス（sMOTSA）を提案した
4. multi-object tracking and segmentation のベースラインとなるモデルを提案した

# MOTS用のdataset を作成
これまでMOTS用のdatasetがほとんどないため、bounding box に対してsegmentを加える形で新たに作成した。

具体的には、bounding boxで切り取った画像を事前学習したDeepLab等に入れ、segmentを予測させる。これを人出でrefineするような手順。

# MOTS用の評価手法を作成

略

# 提案モデル TrackR-CNN

以下が提案モデル TrackR-CNN 概要

![trackr-cnn_img00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/2d81678c-b0bb-4ffb-c062-6f4720e889fa.png)

TrackR-CNNという名前からも想像つくように、Mask R-CNNをベースとしている。

それとの違いで見ると、

1. 左側入力が複数フレームに渡るsequentialな画像である。それをCNNで特徴量化する。
2. これにより出力される各frameの特徴量に対し、3D Convで畳み込む。
3. これにより出力される時空間な特徴量に対し、Region Proposal Networkで物体候補領域を推定する。
4. 各物体候補領域に対し、Mask R-CNNと同様にbounding box回帰、クラス分類、セグメントを行うが、これに加えてAssociation embeddingも出力する

## Association Head
各物体候補領域に対しAssociation embeddingを出力する部分。

![trackr-cnn_img00_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/6db654c5-4ffd-e03a-6f99-f04ec7e739f6.png)

### 同一物体の判定

ここでは候補領域の物体 $d \in \mathcal{D}$ ごとにベクトル $a\_d$  を出力する。

異なるframeにおける任意の物体 $v$、$w$ における距離はユークリッド距離とする。

```math
d ( v, w) := \| v-w \|
```

この距離の近さで同一物体か否かを判定する。

### id 一致に関するloss

物体 d の ground truthの id を $id\_e$ とし、以下のtriplet losssを用いる。

```math
Loss_{id} = \frac{1}{| D |} \sum_{d \in \mathcal{D}} \max \left( \max_{e \in \mathcal{D}:id_e = id_d} \| a_e - e_d \| - \min_{e \in \mathcal{D}:id_e \neq id_d} \| a_e - e_d \| + \alpha , 0 \right)
```

まず、括弧内の１項目は同じidの場合であり、フレーム間に渡って距離が最大となるものとしている。よってこの項が最小化することを期待する。

括弧内の２項目は異なるidの場合であり、フレーム間に渡って距離が最小となるものとしている。これにマイナスをかけるので、この項が最大化することを期待する。

この両者にマージン $\alpha$ を加え、それと０との最大値を採用する。

それを全ての物体に渡って平均化する。

これにより、同じ物体間ではベクトルが近くなり、異なる物体間ではベクトルが遠くなることを期待する。

## mask propagation
評価対象としてのMask R-CNNをMOTSタスクに応用するとき、トラッキングのアルゴリズムが必要である。本論文ではマスク・ベースでの類似性を利用している。

t-1時の物体 d におけるマスクとt時の物体 e におけるマスクとの類似度（maskprop）は

```math
{\rm{maskprop}} (mask_d, mask_e) = {\rm IoU}(\mathcal{W} (mask_d), mask_e)
```

とする。ここで$\mathcal{W}$ はoptical flowによるwarping。

# 実験と結果
## 定量的評価 
KITTI dataset を使った他のモデルとの MOTS値の比較は以下。

![trackr-cnn_img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/4adf6661-89b5-6159-8437-31c241696e5e.png)

+MGはTrack R-CNN自体はmaskのheadなしヴァージョンであり、後処理でmaskを推定する。

## 定性的評価
以下がKITTI datasetのvalidation dataにおける推論例。

![trackr-cnn_img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/1219bdf6-c529-4ddf-372b-18f080a92be5.png)

+MGに比べてmask headがある(a), (c)はidswが減っている。
Accessing array elements 配列の要素へのアクセスの方法 

```c

int main()
{
    double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
    double salary = balance[4]; //0から4番目 50.0にアクセス
}
```

```c

double *p1;

p1 = array;
printf("%f", *p1); // 1000.0
printf("%f", *(balance + 2)); //3.4
```
・arrayのみだと配列の先頭のアドレスを返す

・要素へのアクセス
１、＊をつけると先頭の要素を返す
２、[]でインデックスを指定することで、インデックスに相当する要素を返す

```c
//どちらも1000.0を返す
*balance
balance[0]

balance + 2 
/* 
balanceの先頭を指すアドレスが、
2つのインデックス分後ろにずれる。（2番目になる//balanceだと3.4のアドレスを指す）
*/

```

その要素にアクセスするには

```C
*(balance + 2) // 3.4
```
停まれ標識検知　可視化部分の開発part2 物体を検知した時にソケット通信で別システムに知らせる

## 前回までの記録
前々回から停まれの標識を検知するプログラムを作成しています.前回はその停まれ標識を検知した時に可視化する為のプログラムとしてとりあえず家にある椅子を検知した時にそれをいつ検知したかを記録するプログラムを作成しました.
今回は検知した時に別プログラムへソケット通信をするプログラムを作成していきます.
## 実現するべき機能
・椅子が検知した時にソケット通信を行う.
※socket通信に関しては以下の記事を参考にさせていただきました.
とりあえず即興で作ったのでserver.pyは丸々同じです.
※一応これらの機能は既存のyolov5のdetect.pyに実装しています.
## 実装したコード
※前回のコードにほんの少し手を加えただけです.

クライアント側

```detect.py
                    if label1=="chair":
                     print("椅子を検知しました.")
                     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s2:
                         s2.connect(('127.0.0.1', 50007))
                         s2.sendall(b'isukenti')
                         data = s2.recv(1024)
```
server側

```server.py
# socket サーバを作成
import socket

# AF = IPv4 という意味
# TCP/IP の場合は、SOCK_STREAM を使う
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # IPアドレスとポートを指定
    s.bind(('127.0.0.1', 50007))
    # 1 接続
    s.listen(1)
    # connection するまで待つ
    while True:
        # 誰かがアクセスしてきたら、コネクションとアドレスを入れる
        conn, addr = s.accept()
        with conn:
            while True:
                # データを受け取る
                data = conn.recv(1024)
                if not data:
                    break
                print('data : {}, addr: {}'.format(data, addr))
                # クライアントにデータを返す(b -> byte でないといけない)
                conn.sendall(b'Received: ' + data)
```
##次回へ
次は本格的に可視化する部分を作っていきたいと思います.具体的にはまだ停まれの標識は使いませんが,椅子を検出したときに音声合成を使って「椅子を検知しました」ってしゃべるようなプログラムを考えています.
後,できれば目で見てわかる可視化部分も考えていきたいなと考えています.
##おまけ
一応,今は椅子でやっていて停まれの標識を使ったことをやってないじゃないかと思う人もいるかもしれないので一応！
停まれの標識でも今やっていることは実現できますが,家の中に停まれの標識はないので実験ができません.
なので,外に持っていく前に必要な機能を備えたいのでとりあえず座っている椅子を検知させています.
必要な機能が実装できるまで停まれ看板検知はお待ちください.なお,モデルのできについてなどは前記事に書いてあります.
一応最終的な目標地点は,地図とこのプログラムを連携させてなんかやりたいなとか思っています.
以上です.
vistaでquartus その44

#概要

vistaでquartusやってみた。
cpuを書いてみた。
機械語モニタを作る。トリック編。

#俺cpuには、間接アドレッシングが無い。

メモリー関係の命令は、setとgetで、直接アドレシングでオペコードに、アドレスを埋め込んでいる。
0x2000 + アドレスがset
0x3000 + アドレスがget
setは、メモリーに、スタックトップを書き込む命令
getは、メモリーから、スタックトップへ読み込む命令
機械語モニタは、メモリーに書いたり、読む、コマンドがある。

#トリック

オペコードを生成してメモリーに書き込み、そこへジャンプ。


#メモリー読み込み

0x100から、読み取る場合

```
push  0x100
get  a
+
set  b
jmp  b

a:
  0x2000
b:
  0x0000
c:
  0x5000
```

スタックに、0x100を積む。
アドレスaから、0x2000をスタックに積む。
0x2000 + 0x100を実行。
アドレスbに書き込む
アドレスbに、ジャンプ。
アドレス0x100から、読み取る。

#メモリー書き込み

0x100に0xffffを、書き込む場合

```
push  0x100
get  d
+
set  f
get  e
jmp  f

d:
  0x3000
e:
  0xffff
f:
  0x0000
g:
  0x5000
```

アドレスeに、0xffffを入れておく。
スタックに、0x100を積む。
アドレスdから、0x3000をスタックに積む。
0x3000 + 0x100を実行。
アドレスfに書き込む
アドレスeから、読み込む
アドレスfに、ジャンプ
アドレス0x100に、書き込む。

# アドレス0x100に、ジャンプ

```
push  0x100
get  j
+
set  k
jmp  k
j:
  0x5000
k:
  0x0000
```

スタックに、0x100を積む。
アドレスjから、0x5000をスタックに積む。
0x5000 + 0x100を実行。
アドレスkに書き込む
アドレスkに、ジャンプ
アドレス0x100に、ジャンプ

以上。
汎用ポインタ（void型ポインタ）について

汎用ポインタは
void *型（void型は、ポインタ型でのみ使用可能）
通常の変数にはvoid型は存在しない。

これは、名前からわかるように
ありとあらゆるポインタ型に変換できるポインタ型。

つまり、どのような値でも受け取れる関数を作成するために使われる。

汎用ポインタを使用すれば、どのような型でも受け取れる。

void型のポインタを逆参照するには必ず型キャストします。

キャストはc言語では任意ですが、C++では必ず必要になる。

例）

```
void outString(void *buf);
```
UnityにMixamoから取り込んだキャラクターのアニメーションを別のキャラクターに割り当てて動かす方法

なんで動かないのかな、と無駄に時間を消費してしまっていて理由がやっとわかったので、同じミスをまたしてしまう可能性があるのでここにまとめておきました。
結論から言うと、RigをHumanoidに変更していなくて別のキャラクターに割り当てられなかった、と言うのが答えです。
流れを見ていきましょう


1:mixamoでアニメーションを割り当てたUnity用のfbxファイルをダウンロードする
<1>
![スクリーンショット 2020-10-13 3.33.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/279a787a-cd84-df26-56b3-a87bd31e891c.png)

.
.
.
.

Assets > import New Assetからダウンロードファイルにダウンロードした先ほどのファイルを取り込む
<2>
![スクリーンショット 2020-10-13 3.34.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/87351123-fcf7-eb0e-443e-35a5b3189585.png)

.
.
.
.


取り込んだばかりのファイルはRigがGenericになっており、他のオブジェクトに対してもアニメーションを割り当てたい時に使えるようにHumanoidに切り替える
<3-1>
![スクリーンショット 2020-10-13 3.35.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/74bf48f7-8498-5c52-5144-9a4c797689bd.png)

.
.
.
.


これに切り替える。applyボタンを押して完了
<3-2>
![スクリーンショット 2020-10-13 3.35.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/e19b4733-8f23-38bd-615a-f3ca00566631.png)

.
.
.
.


そうすると、存在しなかったアバターファイルがfbxファイルの子要素として生成されてるのを確認する
<4>
![スクリーンショット 2020-10-13 3.35.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/fbd79b5d-f530-3140-e20e-9da2992679c0.png)

.
.
.
.


他のキャラクターに対してもmixamoから取り込んだキャラクターに割り当てたアニメーションを使用できるようにAnimator Controllerを新規作成する
<5>
![スクリーンショット 2020-10-13 3.36.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/b9c9fbbf-7c79-5f26-0b3f-2336af8d1ba0.png)

.
.
.
.


Animator Controllerのタブから新規にアニメーションを割り当てて作成する
<6>
![スクリーンショット 2020-10-13 3.37.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/d2c61f1c-816c-891e-ae38-d3e058cda2a4.png)

.
.
.
.


startから矢印を引っ張ってアニメーションのルートを作る
<7>
![スクリーンショット 2020-10-13 3.37.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/fc6390ec-3371-bb0f-f242-4d606bd98930.png)

.
.
.
.


InspectorのMotionにmixamoからとりこんだキャラクターのアニメーションを割り当てる
<8>
![スクリーンショット 2020-10-13 3.38.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/6ef0a5d5-3762-53f9-1a81-57802bfdcf57.png)

.
.
.
.


ループ再生にするためにアニメーションを割り当てたstateに対してMake Transitonで同じStateをクリックし、TransitionのSoloにチェックを入れる
<9>
![スクリーンショット 2020-10-13 3.38.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/b6887d65-528f-4418-8d74-f5c8b5172d97.png)


.
.
.
.


![スクリーンショット 2020-10-13 3.39.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/5da7ed44-2fd2-7775-9bcb-9dad01310d0a.png)

.
.
.
.


完成して取り込んだfbxファイルと違うキャラクターに割り当てたIdleのアニメーションがこんな感じです
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/789a715e-6ba7-578f-e131-89e070ff1683.gif)
C++構造体メンバに対しC#クラスのプロパティでマーシャリングする

# メンバではなくプロパティでやる理由
C++の構造体に対しマーシャリングする時、通常ならメンバで充分対応出来るのですが
XMLやjsonへのシリアライズや、PropertyGridクラスへの対応が簡単に出来るようになるので
クラスのプロパティを使用します
（MSDNにプロパティとマーシャリングの関連について記述が見当たらなかったのでメモした具合です）

# 一例
睡眠限界状態なので色々省いてるかもです

### C++側実装

```C++:C++
// 構造体定義
struct TestStruct
{
	int numA;
	int numB;
	wchar_t txt[20];
};

// 関数定義
extern "C" __declspec(dllexport) void CppDll(TestStruct test);
```

### C＃側実装

```C#:C#
// マーシャリング用クラス定義
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class TestStruct
{
	// メンバでやる方法
	int numA;

	// 公開プロパティにする
	// このプロパティはマーシャリングに影響しない
	public int numAProperty
	{
		get { return numA; }
		set { numA = value; }
	}

	/* ============================================ */

	// プロパティでやる方法
	// 自動プロパティで適用可
	public int numB { get; set; }

	/* ============================================ */

	// 文字列の場合
	// 自動プロパティは不可（後述）
	[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
	string txt;

	public string txtProperty
	{
		get { return txt; }
		set { txt = value; }
	}
}

// C++関数定義
[DllImport("hoge.dll")]
public static extern void CppDll(TestStruct test);

static void Main(string[] args)
{
	// 使用例
	var hoge = new TestStruct()
	{
		numAProperty = 1,
		numB = 2,
		txtProperty = "piyo",
	};
	CppDll(hoge);
}
```

## MarshalAs属性が必要な場合は自動プロパティで対応出来ない

```C#:C#
// 以下エラーとなる
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string txt { get; set; }
```

MarshalAs属性が必要となるメンバに対しては指定不可なので
自動プロパティ以外の方法で実装する必要があります


# 最後に

寝る時間惜しんで書くもんでもなかった
C#でWM_COPYDATAを大量に使う事になるのが悪い
conda環境（Anacondaによる仮想環境）を利用する

#はじめに
SEIYA（@SeiyaSunapro7th）です.
Anacondaを用いた仮想環境（conda環境）を利用する方法についてまとめてみました.

###実行確認ができた環境
macOS Catalina ver.10.17.7
conda ver.4.8.5

#1. condaの確認
###1-1. condaがインストールされていること,バージョンを確認する.

```
$ conda info
```


###1-2. condaを最新バージョンにアップデートする.

```
$ conda update conda
```


#2. Anacondaで仮想環境を構築する
###2-1. 仮想環境を構築
conda環境を構築するためのコマンド.
conda環境を構築する際に加えるパッケージを指定する.
バージョンの指定をしなければ最新バージョンがインストールされる.


```
$ conda create -n 環境名 加えるパッケージ
```


ex. conda環境にpython3.7とnumpyをインストールする場合

```
$ conda create -n環境名 python=3.7 numpy
```

###2-2. ライブラリをインストール/アンインストール,アップデート
構築したconda環境にcondaが対応しているライブラリをインストールする.

```
$ conda install ライブラリ名
```


逆にアンインストールをするコマンド.

```
$ conda uninstall ライブラリ名
```


指定したライブラリをアップデートする.

```
$ conda update ライブラリ名
```


#3. conda環境の起動/終了,削除
###3-1. conda環境の起動と終了

```
$ conda activate 環境名
$ conda deactivate
```


###3-2. conda環境を削除する.

```
$ conda remove -n 環境名 –-all
```


#4. 環境内の検索
###4-1. 既存の仮想環境を出力
Anaconda内にある全ての環境（ベース環境も含めて）を出力する.

```
$ conda info -e
```

###4-2. 環境内の既存ライブラリを出力
指定した環境にインストールされているライブラリを出力する.
指定したければ,作業中の環境の情報を出力する.

```
$ conda list -n 環境名
```


#5. インストールしたいライブラリ検索, 非対応ライブラリをインストール
###5-1. condaに対応しているかの確認
condaに対応しているライブラリを出力する.
ライブラリとそれに対応するpythonのバージョンも出力する.

```
$ conda search (--full-name) ライブラリ名
```

###5-2.conda非対応ライブラリをインストールする
conda対応していない場合,以下の手順を踏むと,condaでインストールができる.
何個か存在するライブラリがある場合に,インストールしたいライブラリ出力し,使用するもの決定する.

```
$ anaconda search -t conda ライブラリ名
```


インストールしたいパッケージの詳細を調べ,インストールに用いるURLを調べる.

```
$ anaconda show パッケージ名
```


ex. mecab-python3をインストールしたい場合

```
$ anaconda show temporary-receipes/mecab-python3
```


指定したURLからパッケージをインストールする.

```
$ conda install -c 調べたURL パッケージ名
```


#おわりに
Anacondaは便利なパッケージですが,利用しないライブラリも多く同時にインストールされます.
pipでインストールされたライブラリとAnacondaによってインストールされたライブラリを共存させると,不具合が生じることがあります.
また,容量が圧迫されることが困る方はpyenvなどを利用することがオススメです.

#参考記事
[-【初心者向け】Anacondaで仮想環境を作ってみる](https://qiita.com/ozaki_physics/items/985188feb92570e5b82d)
[- condaとpipでのパッケージ管理について](https://qiita.com/ynakayama/items/29efebeb38604d10acef)
#関連記事
[- pyenvが必要かどうかのフローチャート](https://qiita.com/shibukawa/items/0daab479a2fd2cb8a0e7)
[- pyenvとvenvで仮想環境を構築する](https://qiita.com/sychocola1/items/93c4e043e4c8dbc60cad)
CentOS 6へのDockerインストール

古い情報がかなり多くはまらされた。。。
```yum install docker```だと全く関係ない紛らわしいのが入っちゃう
（```service docker start```でエラー発生）

epelインストールして
```yum install docker-io　--enablerepo=epel```
でいけるという情報多いが
リポジトリ消えてるみたい

で今度はrpmで
```wget https://yum.dockerproject.org/repo/main/centos/6/Packages/docker-engine-1.7.1-1.el6.x86_64.rpm```
でいけるという情報もあったが
これも```yum.dockerproject.org```のリンク切れてるっぽい

これならいけた

```bash
yum install https://get.docker.com/rpm/1.7.1/centos-6/RPMS/x86_64/docker-engine-1.7.1-1.el6.x86_64.rpm
```


参考
---
[stack overflow - Installing Docker on CentOS 6 after removal of docker-io](https://stackoverflow.com/questions/55134196/installing-docker-on-centos-6-after-removal-of-docker-io)
ARグラスで必須になる3Dムービー形式作りたい

3Dムービー形式は以下のようなものが入っている
./3Dmovie.hero1
(zip){
./index.md #htmlを入れたい時に使う
./app.json.py #立体音源に変換するAI
 #↑特定の動きを付ける、3Dオーディオの場所によって動的な音源、文字を入れる等の仕事をする
./app.json #上のスクリプトの設定
./Andio
{
./AudioBacePos.json #オーディオの場所のマトリックスとベクタ情報
./Audio001.mp4 #音のみ保存
./Audio001.mp3 #音を格納
}
./3DBace
{
 #webpとapngのみ対応
./3Dbace.json #json情報
./3dbace001.webp #webp対応
./3dbace001.apng #apng対応
./3Dbace.bin #バイナリー
}
./ArLib
{
 #ショートカットファイルxmlで記述されている
./ArKit.refwrap #ArKitの参照(なければ利用しない)
./ArCore.refwrap #ArCoreの参照(なければ利用しない)
./Vulkan.refwrap #Vulkanの参照(なければ利用しない)
./Metal.refwrap #Metalの参照(なければ利用しない)
./D3DX11.refwrap #DirectXの参照(なければ利用しない)
}
}(/zip)

この形式を世界標準(ISO標準)にしたい。VR/ARの標準動画形式にしたい。
初心者のプログラミング

# 勉強の記録
## 勉強した内容
- letの使い方。
- ツイッターなどでよくある診断ツールの作成。

## 何をベースに勉強してるか
- [N予備校 プログラミング入門](https://www.nnn.ed.nico/home)

## 内容の詳細
### わかったことについて
- 影響される範囲を絞れるので、別の場所で同じ引数を使ってエラーが出にくくなるってスゲーって思いました。
ただ、まだどういう状況でそれが役立つのかよくわかりません。
- 文字にはcharaCodeがあり、それによって同名なら同じ結果がでるようにできるって知りました。
- for(let i = 0; i < userName.length; i++){　のようにプロパティ全体を式に組み込めるのが面白い！

### むずかしかったよ
- 正直全体的に難しい…。
なるほどねって思える部分があるだけマシなのかなって思えるけど。
もう一度同じ内容をやらないと同じことを出来る気がしない。

## 次回やる予定のこと
- というわけもう一度同じところはやるつもりです。
次回からはテキストを先に読み、予習してから取り掛かろうと思います。

## 今回書いたコード

```js
'use strict';
const answers = [
    '{userName}のいいところは声です。{userName}の特徴的な声は皆を惹きつけ、心に残ります。',
    '{userName}のいいところはまなざしです。{userName}に見つめられた人は、気になって仕方がないでしょう。',
    '{userName}のいいところは情熱です。{userName}の情熱に周りの人は感化されます。',
    '{userName}のいいところは厳しさです。{userName}の厳しさがものごとをいつも成功に導きます。',
    '{userName}のいいところは知識です。博識な{userName}を多くの人が頼りにしています。',
    '{userName}のいいところはユニークさです。{userName}だけのその特徴が皆を楽しくさせます。',
    '{userName}のいいところは用心深さです。{userName}の洞察に、多くの人が助けられます。',
    '{userName}のいいところは見た目です。内側から溢れ出る{userName}の良さに皆が気を惹かれます。',
    '{userName}のいいところは決断力です。{userName}がする決断にいつも助けられる人がいます。',
    '{userName}のいいところは思いやりです。{userName}に気をかけてもらった多くの人が感謝しています。',
    '{userName}のいいところは感受性です。{userName}が感じたことに皆が共感し、わかりあうことができます。',
    '{userName}のいいところは節度です。強引すぎない{userName}の考えに皆が感謝しています。',
    '{userName}のいいところは好奇心です。新しいことに向かっていく{userName}の心構えが多くの人に魅力的に映ります。',
    '{userName}のいいところは気配りです。{userName}の配慮が多くの人を救っています。',
    '{userName}のいいところはその全てです。ありのままの{userName}自身がいいところなのです。',
    '{userName}のいいところは自制心です。やばいと思ったときにしっかりと衝動を抑えられる{userName}が皆から評価されています。',
];
/**
 * 　名前の文字列を渡すと診断結果を返す関数
 * 　@param {string} userName ユーザーの名前
 * 　@return {string}　診断結果
 */

 function assessment(userName){ 
     //userName(文字列) を数値に変換
     //全ての文字を足し算する
     var userNameNumber = 0;
     for(let i = 0; i < userName.length; i++){
         userNameNumber += userName.charCodeAt(i);

     }
     //5桁の数値を回答結果の範囲（0～15）に返還
     var answerNumber = userNameNumber % answers.length;
     //診断結果
     var result = answers[answerNumber];
     return result.replace(/\{userName\}/g, userName);
 }

 console.log(assessment('太郎'));
 console.log(assessment('次郎'));
 console.log(assessment('太郎'));
```
ウォーターフォール開発＆アジャイル開発

今回はウォーターフォール開発とアジャイル開発について
メリットデメリット、違いについてリサーチした事を共有しようと思います。
##ウォーターフォール開発とは
####中長期的且つ、最初の設計が肝心になる場合（機械の製造、造船業など）に用いられる手法
     -主な流れ-
    1. 全体の機能設計
    2. 計画を決定
    3. 計画にしたがい開発を実装
各工程ごとに成果物を作り、各工程の品質をしっかり確保します。

####メリット
　1. 全体的な計画を立てやすい
　2. 進捗状況の把握がしやすい
　3. 大規模開発に向いている
####デメリット
　1. トラブルが起きた時の差し戻し工数が発生する
　2. 仕様変更を行う時の時間、金銭的コストが大きい
　3. ユーザーからの意見を取り入れにくい

##アジャイル開発とは
####短期間で開発を見直し、開発期間を大幅に短縮できる手法（ウォーターフォール開発より短期間）
    -主な流れ-
    1. 大枠のリリース計画を立てる
    2. 設計⇨実装⇨テスト
    3. ①②サイクルを繰り返す（イテレーションと言う）

####メリット
　1. ユーザーの要望に対応しやすい（途中の変更にも臨機応変に対応しやすい）
　2. トラブル起きても差し戻し工数が少ない
　3. 仕様変更に対応しやすい（途中変更の多いサービスに対して進めやすい）

####デメリット
　1. 開発の方向性がブレやすい（厳密性優先　＜　柔軟性優先　である為）
　2. スケジュール、進捗管理が難しい

##選択方法例
####アジャイル開発
    * ユーザーの意見を重視したアプリケーションを作る場合
    * 機能変更が多いWebサービスなどに対応する場合

####ウォーターフォール開発
    決まった仕様通りに進むプロジェクトの場合

ご覧いただきありがとうございます。
以上でウォーターフォール開発とアジャイル開発です。
どっちがいいと言うわけではなく、目的などによって使い分けるんだなと理解できました。
少しでも役に立つ共有ができたら嬉しいです。
またご意見や、付け足しなどした方がいいと思う事があれば、教えていただけると
大変勉強になるのでぜひよろしくお願い致します。
鬼滅の刃、tohoを滅する

## はじめに
toho様を貶める意図はないです。（くそ雑タイトルごめんなさい）
混雑は予想されていたはずなので、人員の配備等しかるべき準備が行われているであろうこと、
異常な高負荷に備えることは容易ではないことは重々承知の上です。

## 問題
10/16(金)         　←　「鬼滅の刃　無限列車編」の公開日
10/13(火) 00:00:00　←　前売り券の座席指定・新規鑑賞券購入受付開始

サイトへのアクセスは順番待ち、サイトへアクセスできても１つ１つの遷移がもの凄く遅い状態。
私も鬼滅の刃ファンの１人で、前売り券を購入し、座席指定を行った。
その時に　`高負荷時の「上映スケジュール」の挙動について`　思うところがあった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616737/33042c50-dc45-feeb-7bbd-0886daf21090.png)
↑上映スケジュールの見た目(正常時)
※後述のエラー発生時は、スクリーンと時間の欄が表示されない。

「上映スケジュール」は、下記の手順で新規鑑賞券の購入まで流れていく。
1. 上映スケジュール内に表示されている利用したい日付をクリックorタップする
2. 指定した日付の上映スケジュールが表示される
3. そこから希望の映画の鑑賞券購入・座席の指定

普段は問題ないが、今回は高負荷であったため、
利用したい日付を選択した際のリクエストが503エラーとなる事象が発生していた。

この時に私が気になった点が下記。
1. 利用したい日付選択時、リクエストが失敗しても「見た目的には分からない」
2. 失敗したリクエストの「再送信は自動では行われない」
上記によって「一般的なユーザ」が、リクエストが失敗として「終わっている」のに気づけず、
リクエストの再送信を行わず待ち続ける状態が発生したことが予想される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616737/1a0e83e8-ae0d-7cdc-f0d9-a677e2a50057.png)
↑何度も成功するまで送ったリクエスト

## 対応方法
対応方法としては、`開発者ツールのネットワークタブで、日付タップ時のリクエストの終了コードを確認し、
成功するまで日付のタップを繰り返す。`ことでたまに成功するのを待つしかないのだが、

## 思ったこと
前述のとおり、一般ユーザは「サーバ重いし待ってれば表示されるかぁ」となっていたのではないかと予想している。
そしてしょうがない面も多分にあるが、不親切なUIだと思ってしまった。
（私も開発者ツール見ないとリクエストが失敗してることに気づけなかった。）

## じゃあどうしてほしかったの？
遷移ではなくクライアントで描画内容を変えるなら、
リクエストが失敗した際に、ユーザにリクエストの再送信を促すようなUIを作るべきでは？
と思いましたまる
私はもう気合で買えたので、文句を言いたいわけではないけど、
似たようなものを作っている1人のポンコツエンジニアとして思うところがあった。

## まとめ
高負荷に備える設備拡充は容易じゃないのは分かってる。その話はしないする意味あまりない。でも、
障害時（※この件が障害かどうかは怪しいけど）にうまくユーザを誘導できるようなUIを心掛けたいと自戒。

備考
qiita使い慣れていないのと、浅学のため、タグとかおかしいかもしれないです。
間違っている箇所ありましたら、申し訳ありませんでした。
気が向いたらご指摘いただけるとありがたいです。
goのgqlgenでgqlgenコマンドが効かない

# 事象

- goでGraphQLを実装するのにgqlgenを使っていた
- https://github.com/99designs/gqlgen
- READMEに書いてあるコマンド `go run github.com/99designs/gqlgen [args]`が実行できたり、できなかったりした

# 発生条件
- go.modファイルに書いてあるgoのバージョンが1.12以下の人はおそらくREADME通りにやっても動作する
- go.modファイルに書いてあるgoのバージョンが1.13以上の人は`go mod vendor`後に実行するとおそらくエラーになる

# 対処方法
- `go get github.com/99designs/gqlgen`した段階でおそらく`$GOPATH/bin/gqlgen`が生成されているはず
- `gqlgen [args]`で実行できる。（`$GOPATH/bin`にパスが通っているはず）

# 最後に
- go run [package]は、実行する場所($GOPATH内かそうではないか）、go.modのバージョン、./vendorが存在するか否か、によって参照しにいく場所が変わるのでややこしい
- goのmoduleは1.12前と1.13以降で挙動が違うので、さっさとバージョンをあげてしまった方がよさそう
dlタグを初めて利用する機会があったので、調べてみた！備忘録

こんばんは、昨日、初めてdlタグを利用した記念すべき1日となりました。笑
ということで、dlタグとは何なのか、調べてみました！
...っていう備忘録です。
セットで、dtタグ、ddタグについても記述していきます。

# dlタグ
dl -> description list（説明リスト）
言葉や用語の<b>定義をする場合や、説明をする場合</b>に利用します。
リスト表示のliタグと同じように、定義や説明を文章ではなく、リストアップするから、description <b>list</b>なんだと考えられます。
次項から説明するdtタグとddタグとセットで使われます。

# dtタグ
dt -> description term（説明される言葉）
<b>定義や説明したい言葉や用語</b>を記述する際に利用します。

# ddタグ
dd -> description, definition（説明や定義）
説明の本文を記述する際に利用します。

# 使い方
ざっと、意味を説明したので、使い方をみてみましょう。

```sample.html
<!--省略-->
<dl>
    <dt>フレームワーク：</dt>
    <dd>Vue.js</dd>
</dl>
<dl>
    <dt>ライブラリ：</dt>
    <dd>React.js</dd>
</dl>
<!--省略-->
```

以下の画像が上記コードの実行結果です。↓

![スクリーンショット 2020-10-13 1.28.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619752/6dba3d25-de86-e8a2-2170-616d062fa872.png)

こんな感じで、dtタグで囲まれた、フレームワークやライブラリといった言葉に対して、ddタグで囲まれた、Vue.jsやReact.jsといった説明のような記述が可能になります。
1つのdtタグに対して、<b>複数のddタグ、つまり、複数の説明文を記述することが可能です</b>。

本当に簡単にですが、まとめてみました！
不備等あれば、コメントをお願い致します。

# 参考資料
<a href="http://www.htmq.com/html5/dl.shtml">★HTML5タグリファレンス</a>
AWS DynamoDBにCSVファイルをインポートする方法

# DynamoDBへのCSVファイルインポートはコンソールからは出来ないので、DQLを使った簡単な方法を明記します。

環境

Mac OSX

```
$ pip --version
pip 20.1.1 from /usr/local/var/pyenv/versions/3.7.7/lib/python3.7/site- packages/pip
(python 3.7)
$ python --version
3.7.7
```


まずPC内に以下のコマンド仮想環境を作ります。

```
$  python -m venv venv
```

次に、その仮想環境に入ります。（ ドット[ . ]のあとは半角スペース区切ってください。

```
$ . venv/bin/activate
```

次にDQLをインストールします。

```
$ pip3 install dql
```

環境変数を設定
以下のコマンドで AWS 認証情報のプロファイル (saml) とリージョン (東京) を環境変数に設定できます：

```
export AWS_PROFILE=saml
export AWS_REGION=ap-northeast-1
```

Windows の場合は代わりに以下のコマンドを使ってください：

```
set AWS_PROFILE=saml
set AWS_REGION=ap-northeast-1
```

dql ツールを利用

以上の設定が終われば、dql コマンドを叩いてコマンドラインインターフェイスを開きます

```
$ dql
ap-northeast-1>
```

あとは、SQL文を入力していくんですが、
### その前に
```
opt allow_select_scan true
```
を入力して、全件スキャンできるようにしておきます。それ以降は自由にSQL文を実行してください。
例としては、`SELECT * FROM test_teble SAVE test.csv` といった感じですね。

```
SELECT * FROM {テーブル名} SAVE {ファイル名}
```

にすると指定したテーブルから全件、指定したファイル名でローカル（コマンド実行ディレクトリ）にファイルが保存されます。
【超初心者向け】autofocus: trueの使用法


# autofocus属性
「autofocus: true」とはページを読み込んだらすぐにautofocus属性を記述している部分にカーソルが移動して入力状態になる、というものです。
# 具体例
一覧ページからマイページへ移動し名前を変更しようとする場合。
　
一覧ページからマイページボタンをクリックしてマイページに行くと自ら名前のフォーム部分を選択しなくてもカーソルが移動した状態でマイページが表示されます。そのためすぐに編集をすることができます！
![カーソルが移動して入力状態になる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764198/67109899-be13-7402-3fcf-105416cff1fe.png)
***
⚠️autofocus:trueは1つのhtmlファイルに1つまでということを押さえておきましょう。
# 記述の仕方
ここでは上記画像のコードをそのままご紹介します。
全体の中で「autofocus: ture」がどのように使用されているのかを把握しましょう。
環境：rails 6.0.0、VScode 1.46、macOS Catalina 10.15

```app/views/users/show.html.erb
<div class="account-page">
  <div class="account-page-title">
    <h1>マイページ</h1>
  </div>
  <div class="account-info">
    <h2>ユーザー情報</h2>
  </div>
  <div class="account-page-form">
    <%= form_for(current_user) do |f| %>
      <div class="form-field">
        <div class="form-field-name">
          <%= f.label :name %>
        </div>
        <div class="form-field-name">
          <%= f.text_field :name, autofocus: true %>
        </div>
      </div> 
      <div class="form-field">   
        <div class="form-field-email">
          <%= f.label :email %>
        </div>
        <div class="form-field-email">
          <%= f.email_field :email %>
        </div>
        <br>
      </div>
      <%= f.submit "更新する" %>
      <br>
      <%= link_to "ログアウト", destroy_user_session_path, method: :delete%>
    <% end %>
  </div>
</div>
```
# おわりに
参考サイトURL→[Uhyohyoweb](http://uhyohyo.sakura.tv/index.html)
「autofocus: trueの使用法」に関する記事はいかがでしたか？
autofocus自体はとっても簡単ですが知らないと「何それ？」ってなりますよね。
簡単なことすぎてピックアップされないので今回記事にしてみました！
少しでも理解のお役に立てたら幸いです。
また、いたらない点がございましたらご指摘ください。（初投稿かつ初学者なので皆さんのご指摘がとっても学びにつながります！）
皆さん、最後までご覧いただきありがとうございます。それではまた別の記事でお会いしましょう〜〜！
【小ネタ】sshdで特定のグループのみパスワード認証にする

# 経緯
公開鍵認証方式でサーバに接続する以外に、「特定のアカウントのみパスワード認証したい」というリクエストがあったので設定内容のメモ。。(今までそういう設定したことなかったわ)

ちなみにsshd_configのMatchディレクティブを使えば実現可能だが、アカウントが大量にあると個別指定が面倒いのでグループ単位で指定したほうが運用面で楽になります。

# 設定内容
グループ単位でパスワード認証を許可するなら、sshd_configの終盤に以下のように記載

```vim
Match Group グループ名
　PasswordAuthentication　yes
```

Matchディレクティブで条件を記載すればOK。
ちなみにMatchディレクティブで指定できる条件は・・・

- User
- Group
- Host
- Address

接続元のAddress指定もできるので端末が特定されている際は便利そう。

[sshd_coinfig(5)](https://linux.die.net/man/5/sshd_config)
[Processing] Bluetooth で接続されているデバイス名とポート名を対応付ける (Windows)

## 要約

- レジストリ `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM` にデバイスの情報が含まれている
    - コマンド `REG QUERY ～` でレジストリを読み込める
        - `/s` オプションでツリー以下をすべて表示
        - `/v` オプションで特定の値を抽出
            - `FriendlyName` にデバイス名が含まれているキーがある
            - `PortName` にポート名が含まれているキーがある
    - `Runtime.getRuntime().exec()` でコマンド実行できる

```powershell
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM" /s /v FriendlyName
```

を実行すると

```
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM\Dev_XXXXXXXXXXXX\x&xxxxxxx&x&BluetoothDevice_XXXXXXXXXXXX
    FriendlyName    REG_SZ    【デバイス名】
```

のようなリストが得られる。

```powershell
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM" /s /v PortName
```

を実行すると

```
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}_LOCALMFG&XXXX\x&xxxxxxxx&x&XXXXXXXXXXXX_XXXXXXXXX\Device Parameters
    PortName    REG_SZ    【ポート名】
```

のようなリストが得られる。

これらの `XXXXXXXXXXXX` の部分が MAC アドレスになっていて一致しているので、結果を混ぜ合わせると対応が得られる。

## コード

```java
import java.io.InputStreamReader;
import java.util.Map;

class BluetoothDevice {
  String address;
  String name;
  String port;
  
  BluetoothDevice(String address, String name, String port) {
    this.address = address;
    this.name = name;
    this.port = port;
  }
  
  String toString() {
    return "BluetoothDevice(address: " + address + ", name: " + name + ", port: " + port + ")";
  }
}

ArrayList<BluetoothDevice> discoverBluetoothDevicesForWindows() {
  ArrayList<BluetoothDevice> devices = new ArrayList();
  try {
    Runtime r = Runtime.getRuntime();
    Process p;
    BufferedReader br;
    HashMap<String, String> hm = new HashMap();
    p = r.exec("REG QUERY HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\BTHENUM /s /v FriendlyName");
    br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while (true) {
      String s = br.readLine();
      if (s == null) break;
      String key = "BluetoothDevice_";
      int idx = s.indexOf(key);
      if (idx != -1) {
        String address = s.substring(idx + key.length());
        s = br.readLine();
        String name = s.substring("    FriendlyName    REG_SZ    ".length());
        hm.put(address, name);
      }
    }
    p = r.exec("REG QUERY HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\BTHENUM /s /v PortName");
    br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while (true) {
      String s = br.readLine();
      if (s == null) break;
      for (Map.Entry<String, String> entry : hm.entrySet()) {
        String address = entry.getKey();
        String name = entry.getValue();
        if (s.contains(address)) {
          s = br.readLine();
          String port = s.substring("    PortName    REG_SZ    ".length());
          devices.add(new BluetoothDevice(address, name, port));
        }
      }
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
  return devices;
}
```
【執筆途中_0.25版】JSFにおけるアーキテクチャを理解する_2020.11時点

今まで利用したことのあるフレームワークといえば、[WACs](https://www.mtioutput.com/entry/2018/07/27/161509)、[Struts2](https://qiita.com/tarosa0001/items/889faa2ab5853005f26b)、[TERASOLUNA(5.x)](https://terasolunaorg.github.io/guideline/5.0.0.RELEASE/ja/Overview/FrameworkStack.html#o-r-mapper)でした。
JSF(JavaServer Faces)は初めて触るので、学習のため、記事にしようと思います。
目標はアーキを理解しつつ、画面-ロジック-DBまでの連携を実装できる事にしたいな。
記事のリンクだけでも参照したい為、執筆途中で公開する事をお許しくださいませ。

##用語の理解(整理未済)　

 ***Java EE(Java Platform, Enterprise Edition)***
　　● Java EEとはJava SEの拡張機能で、Javaで実装されたアプリケーションサーバーの標準規格及びそのAPIを定めたものだそうです。歴史が複雑なので自分なりの理解を図にしました。ちなみにJSF(JavaServer Faces)はJava EEの仕様として定義されており、JavaEE5から登場します。
![JavaEE.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/27258c98-fc26-55c5-a5de-b1fcb18c2ba5.jpeg)


 ***NetBeans***  [:flag_jp:NetBeans 日本語サイト](https://ja.netbeans.org/index.html)　(8.2～メンテなし) 
　　● NetBeansはSun Microsystemsと契約(1999)し、Java Beansコンポーネント開発用のIDEとして開発されていたが、SunがOracleが買収され(2010/1)、JDeveloperの競合製品の立場になってしまってます。その後Apacheソフトウェア財団に寄贈され(2016)当初はApache Incubatorであったが、ようやくApache Software Foundationとして開発されるようになってます(2019)。JavaEEとともにOracleに属していた時は不遇な状況を過ごしてきたみたいです。

 ***[JavaServer Faces(JSF)](http://www.dcom-web.co.jp/technology/jsf1/)***
　　● JSFとはMVCモデルをベースに作られたコンポーネントベース型のJavaEE純正のWebアプリケーションフレームワークです。JSF2.0(JSR314)がメジャーリリースされ(2009.6)、JavaEE6のAPI仕様として包含されるようになっています。そのあとJSF2.2(JSR344)がJavaEE7のAPI仕様、JSF2.3(JSR372)がJavaEE8のAPI仕様として構成されるようになりました。Seasar2やStrutsなどのアクションベースとJSFのコンポーネントベースのFWでは処理の流れが違うので慣れが必要です。コンポーネントベースというと今どきのVue.js,React.jsのように流行ってもよさそうなのですが、先にStruts,Springが流行ったのであまり日の目を見なかったのでしょうか(~~メガドライブみたいなものかしら~~)。


 ***[EclipseLink(ORM)](https://www.eclipse.org/eclipselink/)***
　　● ORM(O/R マッピング)とはオブジェクト指向プログラミング言語がリレーショナルデータベースのデータをオブジェクトとして自動変換する手法である。Java Persistence API(JPA)はJavaにおけるO/Rマッピングの仕様であり、JPA 2.0(JSR317)がJavaEE6と同日にリリース(2009.12)、JPA 2.1(JSR 338)がその後リリースされ(2013.4)今に至ります。なお、このJSRのリファレンス実装がeclopselinkやGlassFish v3(JSR317のみ)です。

- ***[WildFly](https://ponsuke-tarou.hatenablog.com/entry/2018/05/29/002359)***

##JSFにおけるライフサイクル概要図
- ***別記事の予定***

##初めの一歩
①NetBeansのインストールについて
　　　

　こちらが分かりやすいです。
　　-***[【手順】NetBeans8.2のダウンロード・インストール手順を解説【Windows編】](https://shimapuku.com/programming/environment/environment-netbeans-8)***
　　　　[:file:日本語版IDE_Ver8.2_Last updated September 23, 2016 ](https://netbeans.org/downloads/old/8.2/)
　　　　[:file:英語版IDE_Ver12.1_released on September 1, 2020](https://netbeans.apache.org/download/nb121/nb121.html)
　　
　 

##簡単なサンプル画面
- ***別記事の予定***

##検証項目
- ***別記事の予定　サーブレットやStrutsとの違い***

---

 こちらの記事を参考にさせていただきました。有難うございました。
[・【もうハマらない！】JSFをきちんと理解しよう。]
(https://qiita.com/3san-yamagami3/items/1b9d7d98c6476d5b1508)
[・JSF2.0の考え方] 
(https://yoshio3.com/2012/08/24/detail-of-jsf20/)
[・Javaを使うなら知っておきたい技術、フレームワーク、ライブラリ、ツールまとめ]
(https://qiita.com/disc99/items/727b51dbe737602a5c91)
[・JavaServer Faces入門]
(http://dream.mods.jp/wp/2016/11/01/jsf2-2%E5%85%A5%E9%96%80-%E7%AC%AC1%E5%9B%9Ejsf%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B/)
[・JavaEE使い方メモ（基本＋環境構築）](https://qiita.com/opengl-8080/items/aeda0d8bad42af3113bd)
[・Java EEとは？](https://style.potepan.com/articles/16062.html)
デフォルトアプリでファイルを開く

コマンドライン環境だと、カレントディレトリにあるファイルをプラットフォームのデフォルトアプリで開きたくなることがあります。各プラットフォームでの方法を調べてみました。

# Linux

```
$ xdg-open ファイル名
```

# Windowsのコマンドプロンプト

```
> start ファイル名
```

# cygwin

```
$ cygstart ファイル名
```
LINEボットでゲームブック、回想シーンを追加


前回の投稿（ [LINEボットでゲームブックを作った、ついでにシナリオエディタ作ったので完成](https://qiita.com/poruruba/items/c8673d4a57b9c77ed6d3) ）の続きです。

LINEボットでゲームブックを作りましたが、かのTyranoScriptを参考に、回想シーンを付けてみました。
気に入った画像があるページで、「記憶」 と言うと、その時の画像や音声を覚えておいてくれるので、いつでも見返せるようになります。
今回も、GitHubに上げています。

poruruba/LinebotGamebook
　https://github.com/poruruba/LinebotGamebook

回想シーンを思い出すために、LIFFアプリを追加します。
こんな感じの画面が、LINEアプリ内に表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/a6853df4-6d54-9aef-1bee-5dc55f1dcc9d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/8f2f82c2-9fc9-d6ff-cc91-f27b2944a37f.png)
 
#LIFFアプリの登録

LIFFアプリは、スマホのLINEアプリの中で起動できるWebページです。
ユーザにログインを気にさせずにWebページを表示させられるのがよいです。

LINE Developersより、LINEログインチャネルを作成し、LIFFタブを選択して、LIFFアプリの「追加」ボタンを押下すれば登録できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/e7424112-a985-9e38-eb62-7e03d02527ce.png)

LIFFアプリ名には適当な名前を入力し、エンドポイントURLには、立ち上げたサーバのURLを以下のようにして入力します。

　https://【サーバのURL】/gamebook/liff/index.html

そうすると、LIFF IDが払い出されます。これを覚えておきます。ついでに、このチャネルのチャネルIDも覚えておきます。

※ちなみに、以前はMessaging APIでLIFFが登録できていたのですが、最近はだめになったようです。（その影響で、liff.sendMessages()が呼び出せなくなっているような。。。）

あとは、上記のURLに表示させたいWebページを作ればよいです。
このページにユーザに飛んでもらうためには、チャットで「"https://liff.line.me/" + LIFF_ID」という感じのURLをクリックしてもらえばよいです。

#LIFFアプリとサーバの連携

LIFFアプリは通常のSPAのWebページです。
以下のjavascriptライブラリを取り込みます。

```html:public/gamebook/liff/index.html
  <script charset="utf-8" src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>
```

LIFFアプリのJavascriptでは、Webページが起動した直後に、以下を呼び出します。

```js:public/gamebook/liff/js/start.js
                await liff.init({
                    liffId: LIFF_ID
                });
                this.id_token = liff.getIDToken();
```

LIFF_IDは先ほど取得したものです。
そして、このid_tokenを立ち上げたサーバに渡します。

```js:public/gamebook/liff/js/start.js
                var param = {
                    id_token: this.id_token,
                    cmd: 'get'
                };
                var json = await do_post(status_url, param );
```

(参考) liff.init()、liff.getIDToken()
https://developers.line.biz/ja/reference/liff/#initialize-liff-app
https://developers.line.biz/ja/reference/liff/#get-id-token

サーバ側では、IDトークンを検証してLINEユーザIDを判別して、シナリオの状態を取り出し、jsonとして戻してくれるようにサーバ側を実装しました。

#サーバ側の処理

サーバ側ではIDトークンをLINEサーバに渡して正しさを確認すると、ユーザの情報が取得できます。ブラウザから取得したIDトークンと、先ほどメモっておいたチャネルIDを使います。

```js:api/controllers/linebot/index.js
      var json = await do_post_urlencoded('https://api.line.me/oauth2/v2.1/verify', { id_token: body.id_token, client_id: LINE_CHANNEL_ID } );
      var userId = json.sub;
```

(参考) LIFFアプリおよびサーバーでユーザー情報を使用する
　https://developers.line.biz/ja/docs/liff/using-user-profile/

userIdがわかったので、DBまたはファイルから状態を取得し、以降の処理でクライアントに返してあげています。

あとは、ソースコードを見ていただければ！！

#補足

LIFFアプリは、ChromeではなくLINEアプリの中で起動するのでJavascriptのデバッグがつらいです。
その場合には、以下の部分のコメントアウトを解除してください。consoleが見れます。

```js:public/gamebook/liff/js/start.js
//var vConsole = new VConsole();
```

Tencent/vConsole
　https://github.com/Tencent/vConsole

以上
RailsでCSVインポートする時、nkfコマンドを使ったらめっちゃ楽だった

RailsでCSVファイルをインポートするとき、こんな感じに実装してた。

```ruby
def read_csv
  begin
    rows = CSV.read(file, encoding: 'UTF-8')
  rescue CSV::MalformedCSVError
    begin
      # csvファイルがUTF-8でない場合はShift_JISで読む
      rows = CSV.read(file, encoding: 'Shift_JIS')
    rescue CSV::MalformedCSVError, Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError
        # csvファイルがUTF-8・Shift_JISでもない場合
        @error = 'ファイルのエンコードはUTF-8かShift_JISではありません。'
    end
  end
  rows&.shift # ヘッダーを削除する
  rows
end
```

## 問題点
例外処理が多くて面倒だし、そもそもインポートできる文字コード２つしかないとか…

## 解決策
どうやら`nkf`とかいうモジュールを使うとなんでも変換できそうだ…
https://docs.ruby-lang.org/ja/latest/class/NKF.html

- nkfをPCにインストール

```console
brew install nkf
```

```console
nkf -w --overwrite 変換したいファイルのpath
```
このコマンドを使えばいい感じに変換できそう。

- Railsの中にこのコマンドを組み込んでみる。

```ruby
def read_csv(file)
  system("nkf -w --overwrite #{file.path}")
  rows = CSV.read(file)
  rows&.shift # 1行目のヘッダーを削除する
  rows
end
```

すっきりとしたコードになりました。

## 注意点
あらかじめ`brew install nkf`コマンド等でnkfをインストールしておかないと、`nkf`コマンドが使えないので気をつけてください。
今回使ったlink_toのいろいろ、まとめてみた

#はじめに
今回のカリキュラムで一番躓いたのが、`link_toメソッド`だった。もちろん基本的な使い方は理解しているつもりだが、どうもpathの引数がしっくりときていない。

今回の投稿は何かを説明する目的ではなく、自分がコードを読むための記録である。
以下、今回作成したアプリの全link_toを余計な記述はカットして引数の読み方とともに載せる。

###全link_toメソッド

#####①

```ruby:application.html.erb

<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
<%= link_to "新規投稿", new_prototype_path %>
```
サインイン状態で表示させている「ログアウト」と「新規投稿」どちらも誰もが共通するページや処理のため、（　）で引数を渡す必要がない。
ユーザーによってログアウトページが違うことはないし、ユーザーによって新規投稿ページが違うことはない。
`link_toメソッド`はデフォルトでHTTPメソッドがGETのため、ログアウトのときは、第三引数にメソッドを指定する。

#####②

```ruby:application.html.erb

<%= link_to "ログイン", new_user_session_path %>
<%= link_to "新規登録", new_user_registration_path %>
```
①と考え方は同じ。今度は非ログイン状態のときの表示。ログイン画面も新規登録もユーザーによって変わることはないから、引数がなくてよい。

#####③

```ruby:application.html.erb
<%= link_to image_tag("logo.png"), root_path %>
```
root_pathは引数がなくてもいける！

#####④

```ruby:prototypes/show.html.erb
<%= link_to "編集する", edit_prototype_path(@prototype) %>
<%= link_to "削除する", prototype_path(@prototype), method: :delete %>
```
投稿したものの詳細ページから、編集したり、削除したりする部分。
showアクションの中で、`@prototype = Prototype.find(params[:id])`と一つのレコードを選び出しているため、どのprototypeを編集・削除するか判断ができる。

#####⑤

```ruby:prototypes/_prototype.html.erb
<%= link_to prototype.title, prototype_path(prototype.id) %>
<%= link_to image_tag(prototype.image), prototype_path(prototype.id) %>
```




#####user_pathシリーズ

user_pathはユーザーのマイページに飛ぶ。誰のマイページなのか明らかにするため、引数が必要になる。

```ruby:prototypes/index.html.erb
<%= link_to current_user.name + "さん", user_path(current_user) %>
```
ログイン中のユーザー名をクリックするとそのユーザーのマイページに飛ぶ。
deviseのGemを用いることによって使える`current_user`。

```ruby:prototypes/_prototype.html.erb

<%= link_to "by " + prototype.user.name, user_path(prototype.user.id) %>
```
prototypeとアソシエーションしているuserのidを取得。

```ruby:prototypes/show.html.erb

<%= link_to "by " + @prototype.user.name, user_path(@prototype.user.id) %>
```
誰による投稿か、名前が表示されている部分のコード。
showアクションの中で、`@prototype = Prototype.find(params[:id])`と一つのレコードを選び出しているため、prototypeとアソシエーションしているuserのidを取得できる。


```ruby:prototypes/show.html.erb
<%= link_to comment.user.name, user_path(comment.user.id) %>
```
誰のコメントか表示されているところのコード。each文で|ブロックパラメーター（変数）に`comment`|が入り、commentとアソシエーションしているuserのidを取得。
Power Apps キャンバスアプリでフォントの指定が可能になりました

タイトルのままです。

これまではPower Appsのフォントは用意されたいくつかのフォントから選択するほかありませんでした。
英語のアプリを作っている分には特に問題なくおおよそ使いそうなフォントはそろっていたわけですが、日本語を表示するときには表現力がいまいちでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/4436591b-1903-9279-244c-ca9ab3be8458.png)

今回、各種コントロールの"Font"プロパティに選択肢以外のフォントを指定できることを発見しました。

サンプルは以下の画像をご覧ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/4454db5f-b076-eb2c-0681-9ccefd329b40.png)

もちろんラベルだけでなく、ほかのコントロールでも対応しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/24004036-905e-a860-f7ef-b536c84fae46.png)

設定する箇所は、各コントロールの「詳細」にある"Font"プロパティで、指定の方法はダブルクォーテーションで囲めばOKです。
もしフォント名にスペースを含む場合には、シングルクォーテーションでフォント名を囲んでください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/f628616e-eee9-7b1d-92d3-673ef45badee.png)

また、OS対応などの意味合いで複数フォントを指定する場合には、カンマ区切りで以下のように指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/3092b006-f72a-ea66-e941-6b4e8ec314c9.png)

これで日本語のUIも少しいい感じにできるかもしれません。

対応しているフォントはすべて調べ切れていないので、必要なフォントが適用されるかどうか、みなさん試してみてください。