OmniAICreator/Qiita-1.07M huggingface dataset:
[Unity] Humanoid animation をデフォルメキャラに適用する

![gif_animation_001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/ad65152b-623a-8250-1462-a8b22c200866.gif)

Mechanimに対応したモデルはアニメーションをいろいろ流用できて便利ですが、通常の8等身モデル用アニメーションをデフォルメキャラに適用するとどうしても腕が頭や体に埋まりがちです。
そこで、腕のアニメーションを補正して、頭と体に埋まりにくいようにしてみます。
![2019-12-16_235206.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/37f41811-fb1a-794c-d1a4-02b1aae01365.png)

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Demo
{
    [System.Serializable]
    public class RotationTuner
    {
        public Transform transform = null;
        public Quaternion defaultRotation = Quaternion.identity;
        [Range(0f, 1f)] public float rate = 0.5f;
    }

    public class AnimationTuner : MonoBehaviour
    {
        [SerializeField] RotationTuner[] m_tunerArr = null;
        [SerializeField,Range(0f,1f)] float m_intensity = 1f;

        // Start is called before the first frame update
        void Start()
        {
            for (int i = 0; i < m_tunerArr.Length; ++i)
            {
                m_tunerArr[i].defaultRotation = m_tunerArr[i].transform.localRotation;
            }
        }

        // Update is called once per frame
        void Update()
        {
        }

        void LateUpdate()
        {
            for (int i = 0; i < m_tunerArr.Length; ++i)
            {
                m_tunerArr[i].transform.localRotation = Quaternion.Lerp(m_tunerArr[i].defaultRotation, m_tunerArr[i].transform.localRotation, m_tunerArr[i].rate + (1f- m_tunerArr[i].rate)*(1f-m_intensity));
            }
        }
    }
}
```

上記のスクリプトをアニメーションのついたモデルにアタッチし、腕（およびアニメーションを補正したい）のTransformおよび補正度合いをセットします。

![2019-12-17_011022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5de411ba-35e0-2c4f-fdfb-ddd2da1bd325.png)

![2019-12-17_011500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/7646d562-bf63-74c9-6f1c-93af0e51593b.png)

補正度合いはDefaultRotationと現在のアニメーションのRotationの合成割合です。1に近いほど元のアニメーションに近くなります。
DefaultRotationにはTポーズ等ベースとなるポーズのRotationを入れますが、
入力せず（全て0）にしておけばStart時のポーズを自動的に入力してくれます。

また、Intensityの値をアニメーションに合わせて変更することで、モーションに合わせてさらに細かく制御することも可能です。

[動画](https://youtu.be/Ko0dVeAR-ws)
[関連:アニメーションIKで、（やだ、あの人こっち見てる・・・）にする](https://qiita.com/ELIXIR/items/09c3daf0fbcafe1bec99)

この「特定の関節を後から補正する方法」は個人的に比較的よく使用していて、他にも
・Mechanim以外のアニメーションで自然に特定の方向を向かせる
・多関節やしっぽなどを特定の場所に自然に動かす
等にも応用可能です。
『ディープラーニング G検定（ジェネラリスト）公式テキスト』読書メモ：03

## 知識表現

### 人工無脳

人工無脳は，特定のルール・手順に沿って会話を機械的に処理するコンピュータプログラム．
<font color="Lime">チャットボット</font>や<font color="Lime">おしゃべりボット</font>などと呼ばれている．

最初の人工無脳はジョゼフ・ワイゼンバウムによって1964年から1966年にかけてと開発された<font color="Lime">ELIZA</font>と呼ばれるプログラム．

## エキスパートシステム

専門分野の知識を有し，エキスパートのように振る舞うプログラムをエキスパートシステムと呼ぶ．

初期のエキスパートシステムとして最も影響力が大きかったのが1970年代にスタンフォード大学で開発された<font color="Lime">MYCIN</font>．
血液中のバクテリアの診断支援をするルールベースのプログラムで，69％の確率で正しい処方をすることができており，これは，専門医ではない医師より良いとされる数字．
専門家の知識を扱っていることがわかりやすい医療分野で，医師と対話しているような質問応答機能や説明機能を備えていたことで大きな注目を集めた．
同大学のエドワード・ファイゲンバウムは1960年代に未知の有機化合物を特定する<font color="Lime">DENDRAL</font>を開発していた．

### エキスパートシステムの限界

知識ベースを構築するためには，専門家やドキュメント，事例などから知識を獲得する必要があるが，専門家の持つ知識の多くは経験的なものであったため，専門家からの知識の獲得が困難であった（おそらく，専門家は自分の経験で獲得したものだから，その知識を明示的に体系化して他人に渡すのを嫌がったから，専門家から知識を得ることが出来なかったという意味）．
また，知識の数が増えると，一貫していないものが出てきて，知識ベースを保守することが困難になった．
そのため，別のアプローチに目を向け始めた．

### 意味ネットワーク

意味ネットワークはもともと認知心理学における長期記憶の構造モデルとして考案されたもの．

概念をラベルのついたノードで表現し，概念間の関係をラベルのついたリンクで結んだネットワーク．

![意味ネットワーク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147064/fbdec0fe-83ec-95ca-d435-9bad954fda5b.png)


「is-a」は継承関係を表現しており，この関係が重要．矢印が向いている方が上位概念，つまり内包している．図のように，哺乳類は人間を内包している．また，「part-of」などは属性を表現している．

### オントロジー

**Cycプロジェクト**

知識ベースのシステムが柔軟な能力を持つには膨大な知識が必要になる．
そのため，すべての一般常識をコンピュータに取り込むというCycプロジェクトがダグラス・レナートによって1984年からスタート．
2014年8月で30年に突入したプロジェクトでおそらく現在もなお続いている．

**オントロジー**

知識の記述や共有が難しいことが分かり，知識を体系化する方法論が研究されるようになる．

オントロジーとは，本来哲学用語で<font color="Lime">「存在論（存在に関する体系的理論）」</font>という意味．人工知能の用語としては，一般的に<font color="Lime">「概念化の明示的な使用」</font>という定義で知られる．

エキスパートシステムのための知識ベースの開発と保守にはコストがかかるという問題があるため，それを解決するために<font color="Lime">知識の共有と再利用</font>に貢献する学問として知識工学が注目され，その中の中心的な研究としてオントロジーが特にフォーカスされた．

結局オントロジーが何かと言うと，知識を記述するときに，その言葉の意味や関係性を他の人と共有できるように，明確に定義しておくこと．

![オントロジー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147064/da2f26c8-b1d9-0823-68ea-872463a99556.png)



オントロジーには，<u>ヘビーウェイトオントロジー</u>と<u>ライトウェイトオントロジー</u>という2つの分類がある．

・ヘビーウェイトオントロジー：構成要素や意味的関係の正当性について哲学的な考察が必要になり，人間が関わる部分が多く，時間とコストがかかる．

・ライトウェイトオントロジー：完全に正しくなくても使えれば良いという現実的思想．ウェブマイニングやデータマイニングに適用されている．

実際の活用例として，IBMが開発した「ワトソン」にウィキペディアの情報を元にライトウェイトオントロジーが使用されている．ワトソンはアメリカのクイズ番組に出演し，人間のチャンピオンに勝利したことで有名になった．ワトソンは質問に含まれるキーワードと関連しそうな答えを高速で検索し，一番確率の高い物を解答する．
日本でも「東ロボくん」に使用されている．
継続と反証はカリーハワード対応するか

## 概要

**継続**の概念に対応する論理的な概念として**反証**を想定できるが、対応は限定的になる、というアイデアメモ。

## カリーハワード対応

**カリーハワード対応**というものがある。これは、論理についての概念である**証明**と、計算機についての概念である**式（プログラム）**の間にある緊密な対応を指す。

通常、次のような対応関係が念頭に置かれる。

|論理|計算機|
|---|-----|
|証明|式|
|カノニカル証明|値|
|証明の簡約|式の評価|
|命題|型|
|含意命題(AならばBという意味で$A \to B$)|関数型(AからBの関数という意味で$A \to B$)|

この対応のおかげで、論理/計算機で成り立つことがらを、概念を交換して計算機/論理で成り立つことがらにできる。例えば、「命題の証明を簡約してカノニカル証明にできる」という論理学的な事実を、「型が付いた式を評価して値にできる」という計算機科学的な事実ともみなせる。

## 継続の論理的対応物

ところで、計算機科学には**継続**という概念があるが、これに対応する論理的な概念はないだろうか？

多分自然な候補は**反証**だと思う。

なぜかというと、**継続**には普通$\lnot A \equiv A \to \bot$、継続型をつける。ここで登場する$\bot$は、値が存在しない型。

一方、論理的にも**反証**が示すのは$\lnot A \equiv A \to \bot$、否定の命題である。ここで登場する$\bot$は矛盾を表現し、カノニカル証明が存在しない命題。

よって、さっき紹介した対応を次のように拡張できるように見える。

|論理|計算機|
|---|-----|
|証明|式|
|カノニカル証明|値|
|証明の簡約|式の評価|
|命題|型|
|含意命題(AならばBという意味で$A \to B$)|関数型(AからBの関数という意味で$A \to B$)|
|反証|継続|
|否定命題($\lnot A \equiv A \to \bot$)|継続型($\lnot A \equiv A \to \bot$)|

## 本当にそうか？

上記のように反証と継続を対応させる考え方は一定程度うまくいくのだが、型や命題が表現したいことを考えると、不一致が出てくる。

否定命題$A \to \bot$を示す反証は、「入力は$A$のカノニカル証明、出力は$\bot$のカノニカル証明」であるようなものである。

一方、継続型$A \to \bot$で型が付く継続は、「入力は$A$の値、出力は$\bot$の値」であるようなものである。

ただし$\bot$のカノニカル証明/値などというものは定義上存在しない。だから、$A \to \bot$を示す反証/と型がつく継続があっても、こいつが$A$のカノニカル証明/値を受け取って$\bot$のカノニカル証明/値を返すことはない。ここまでは対応している。

違うのはここから。反証の場合、$A \to \bot$を示す反証があっても、こいつが$A$のカノニカル証明を受け取って$\bot$のカノニカル証明を返すことはない。よって、$A \to \bot$を示す反証があるなら、$A$のカノニカル証明は存在しない、と考える（だからこそ$A$の否定になる)。反証に**カノニカル証明が与えられることはない**。

一方継続の場合はこうなる。$A \to \bot$で型がつく継続があっても、$A$の値を受け取って$\bot$の値を返すことはない。だが$A \to \bot$で型がつく継続に、$A$の値を与えるのはごく普通に発生する事態である。だから継続の場合は、継続に値を与えても、**値が返されることがない**、と考える。

つまり反証と継続は、同じ「入力$A$、出力$\bot$」ではあるが、表現したいことが微妙に異なる。否定命題は**「入力$A$」を排除する**命題として意図され、継続型は**「出力$\bot$」を排除する**型として意図されている。ここにおいて、読み替えは破綻する。

## 結論+α

型や命題が表現したいことを考えると、継続と反証の対応は崩れる。

そもそも論でいうと、継続を扱うプログラミングでは**値を返さず（値を返す以外の作用という意味での）副作用だけを起こす式**が登場するが、論理の世界では**カノニカル証明を返さない証明**が何者か理解しがたい。ただ、論理の世界における副作用として**行為**を考えれば、**行為に帰結する推論**はカノニカル証明を返さない証明なのでは、とか妄想中。
Rails6 ログアウト機能作成中にルーティングに問題ないのにエラーが出た話

# 目的

- ログアウト機能作成中にルーティングに問題は無いのにルーティングエラーが出た時の話をまとめる。

# 結論

- ログアウトボタンを押下した時の設定で`method`を`post`に指定していなかった。

# エラーまでの経緯

- ログアウト機能を作りたかった。
- Bootstrapを用いたheaderにログアウトボタンを作成し、押されるとルーティング経由でコントローラのアクション内で　`session[:user_id]`に`nil`を入れてログアウト処理を行うものだった。
- 下記に各ファイルの一部の抜粋を記載する。
- headerのビュー

    ```
    <li class="navbar-item"><a href="/logout" class="nav-link">ログアウト</a></li>
    ```
- ルーティング

    ```
    post "logout" => "users#logout"
    ```

- コントローラのアクション

    ```
    def logout
      session[:user_id] = nil
      flash[:notice] = "ログアウトしました"
      redirect_to("/login")
    end
    ```
- ビューからの送り先のルーティングの`logout`にスペルミスもない。

# 原因

- ビューからルーティングのpostへ送るときは`method`を`post`にしてあげないといけないのにしてない。
- `post`に送るときは指定してあげないと`post "logout" => "users#logout"`を見つけられない。

# 解決方

- 取り急ぎつまりまくったので`link_to`を使用してログアウトできるかどうかだけ確認した。
- 下記に修正したheaderのビューファイルの内容を記載する。

    ```
    <!--<li class="navbar-item"><a href="/logout" class="nav-link">ログアウト</a></li>-->
    <%= link_to("ログアウト", "/logout", {method: "post"}) %>
    ```

- ログアウトすることができた。

# 残件

- `link_to`を使用したログアウトは行えたものの、Bootstrapのheaderでの`method`を`post`にする方法を知らないのでそこを解決する。
- <a>タグの中で`method="post"`すればいけそうだがうまく行かなかったので解決する。
- 若干体調が悪いため今日はここまでとする。
WWWの歴史について少し調べた

Web関連の本を読んだまとめ

## Webはどのように発展してきたか
### World Wide WebとMosaic
インターネットは50年ほど前の1969年にその原型が生まれた。当初の20年間近くは、大学の研究者などのごく一部の限られた人が利用するものだった。これには2つの理由が考えられる。

* インターネットを利用するためのコンピュータやネットワーク資源が非常に高価だった
* 利用用途が電子メールの交換やファイル共有が中心で、普段コンピュータに縁のない人にはあまり興味の向かいないものだった

#### WWWの誕生
この状況を大きく変えるきっかけとなったのが、「World Wide Web」と、Webブラウザの原型である「NCSA Mosaic」と呼ばれるソフトの誕生。

世界で始めてWWWが提案されたのは1989年で、素粒子物理学の研究所からであり、研究結果を**HTML**と呼ばれる統一された形式で表現することを考えられた。HTMLはその後徐々に仕様が固められていき、現在でもwebサイトの記述に使われている。

ここで最も画期的であったのが、「**Hyper Text**」と呼ばれる仕組みで、Hyper Textでは、文書間の参照が「Hyper Link」というコンピュータで理解することのできる形式で記述されているため、瞬時に参照先の文書を閲覧することができる。

このようなネットワーク上でリンクされたハイパーリンクの繋がりが、蜘蛛の巣のように見えることから、**World Wide Web**と名付けられた。

#### NCSA Mosaic
テキスト中心で表示されていたWebページを、現在のWebブラウザのように、文字と画像を混在させて表示できるようにしたのが、1993年に開発されたNCSA Mosaic。

Mosaicが開発され、無料でだれでも利用できるようになったおかげで、WWWの利用は大きく広がり、一般の人の興味を引くようになった。

### CGIの誕生
Webサーバは本来、元々用意されていたコンテンツ(静的なコンテンツ)をクライアントからのリクエストに応じて返すのが仕事。

動的なコンテンツを生成してWebクライアントに渡すにはWebサーバとコンテンツを生成するプログラムとの連携が必要であり、そこで考え出されたのが、CGI(Common Gateway Interface)という仕組み。

このCGIによって、検索サイトや掲示板システムショッピングサイトといった機能を実現することができるようになった。これがWebアプリケーションの始まり。

#### サーブレットの登場
CGIを使ったアプリケーションが普及するに従って、新たな問題が生じた。

##### 開発言語の問題
当時主に利用されていた言語はPerlであり、アプリケーションに求められる機能が大規模化、複雑化するに従って、プログラムの作成が困難になってきた。

##### 性能の問題
従来はWebブラウザからリクエストが届くたびにCGIを通じてプロセスを起動していた。アクセス数が少ないうちは、これで問題なかったが、アクセスが増えるに従って、処理が追いつかなくなった。

#### Java/サーブレットの誕生
Webアプリケーション開発がこのような問題を抱えていた際に登場したのがJava。

Javaはオブジェクト指向の機能をフルサポートしており大規模なシステム開発が行いやすく、また当時広く利用されていたC言語に似た文法であったため、当時の開発者に受け入れやすかった。

Java自体はWebアプリケーションの開発を行うために作られた言語ではなかったため、JavaEE(Java Enterprise Edition)の一部として「サーブレット」というWebアプリケーション開発をサポートするための機能が提供された。サーブレットとはJavaで作られたHTMLなどのWebコンテンツを生成するプログラムのこと。

Javaには特定のOSやハードウェアに依存せずに動作するという特徴を持つ。

##　まとめ
インターネットの歴史が思った以上に浅くて驚いた(筆者は1995年生まれ)
AtCoder水色を武器に就活した話

#はじめに
~~タイトル一本釣りじゃねえか~~
この記事は[DMMグループ '20卒内定者アドベントカレンダー](https://adventar.org/calendars/4156)17日目の記事です．

こんにちは[@iwakiri_k](https://twitter.com/iwakiri_k)です．

ほぼ競プロしかスキルの無い私がWeb系企業から内定を頂くことができたので，
そのプロセスを書き残しておきたいと思います．

#記事長いから一言でまとめて
まあ何とかなった．
水色程度レベルでのWeb系就活なら，最低限何かモノを作った経験は欲しいかも．

#内定取得時のスペック
・パスナビで前期偏差値45の国公立大学生
・情報工学専攻
・学部4年生
・AtCoder水色
・GPA3.0(上位5%の成績優秀者として表彰された)
・Railsちょっとできる(完全に理解ネタのやつではない)

あとスペックと言えるものか分かりませんが，面接時に話したネタとして
・BMSで旧発狂皆伝を所持
・スピードキューブのシングル自己ベ約9秒
・PSPのチートコード作成経験あり
なんかもあります

#内定取得までの主な流れ
####学部1年 冬
AtCoderを知りました．
ここから気まぐれでコンテストに参加するようになります．

参加するだけでは意味が無いので，
『解けなかった問題1問は解けるようにする』
という目標で続けました．

過去問を何百問も解くような精進はしていません．

####学部3年 春
インターンどこ行けば良いか分からないので，先輩から勧められた合同説明会に行きました．
サポーターズ主催のギークフェスタというイベントです．

私はそこで始めて，
**Web系という業界を初めて知りました**．

ええ，**『知った』**です．
大学のキャリア教育で「プログラミングはSIer下流がやるものだ」と教わっていたので，目が点になりました．

周りの学生のレベルが高くて絶望したのを覚えています．

####学部3年 夏
ギークフェスタで見てきた優秀な人達を押しのけて人気Web系企業の選考を通過できる自信は無かったので，
選考の無い地方Web系企業のインターンに行きました．

そこでRailsを学びました．
競プロ以外の初めてのスキルです．

####学部3年 秋
就活イベントや1dayインターンを通して，エンジニアを募集している業界を一通り見てきました．
SIerとか自動車メーカーとか広告制作とか色々．
体験型の1dayインターンでは，UnityとかElasticsearch+Kibanaとか触れたのを覚えています．

色々見て悩んだ結果，Web系のサーバーサイドエンジニアに学部卒でなることを決めました．

####学部3年 冬
大学がクソ忙しい中，平行して就活をします．

競プロをやっているおかげでコーディングテストは余裕です．満点安定でした．

ですが，1次面接で落ちます．
フィードバックに『Webアプリ周りの知識が足りない』とありました．

とりあえず，Railsチュートリアルに毛が生えた成果物を作りました．

####春休み
サポーターズ1on1面談会やジースタイラスITエンジニア逆求人に参加します．
そこで，多くの企業から高評価を頂きました．

以前の1on1面談会ではそうでは無かったので，
恐らく『水色＋Webアプリの成果物あり』というスキルを評価をしてくれたのだと思います．

また，オンライン面接は苦手だという事に気が付いたので，
現地でスムーズに面接を行えるようにする為，東京にシェアハウスを借りました．

####学部4年 春
イケイケで選考が進んでいきました．

また，面接最初の自己紹介では，AtCoder水色のスキルをより強調する為，
「水色持っているので最適化・高速化が得意です．今はこんな本読んでます」
という感じに，技術書展で買ったC++高速化本を見せたりしていました．

そんなこんなで，5月初頭にDMM.comから内定を頂きました．

#競プロは就活に役立つのか？
役立つか役立たないかで言えば，当然役立ちます．
実際，内定理由のフィードバックではAtCoder水色を高く評価してくれました．

ですが，**就活対策としてのコスパは悪いです**．
普通のWeb系の場合，常人ならば成果物はほぼ必須ですし．
実際，面接中にモダンな技術用語がいっぱい飛んできました．

C++での高速化に特化した企業や，競プロを高く評価している企業ならば別でしょうが，
そういう企業だったとしても，競プロ一本で入るとなると水色では厳しいと思います．

#おわりに
どうせアドカレを書くなら参考になりそうな記事にしたいと思い，このような内容にしました．

同期の皆様，これからよろしくお願い致します．
[Rails]  アクションでレイアウトを出し分ける

段階フォームにて、初期の画面とそれ以降の画面とでは共通レイアウトを出し分けたい。

```ruby:register.rb
class Register
  def screen_1
    layout 'register/login'
  end

  def screen_2
    layout 'register/profile'
  end

  def screen_3
    layout 'register/experience'
    # もし条件式がfalseだったらscreen_2にレンダリングする時はrenderに複数渡せる
    if false
      render :screen_2, {:layout => 'register/experience'}
    end  
  end
```
AWS C#環境構築挑戦

ASP.NETまで挑戦したかったけど、無理だったので.NET実行環境構築まで。

参考URL
ファイルの転送方法
https://qiita.com/3naU/items/b5c5875b557bc55f96df

ASP.NET
https://www.aruse.net/entry/2018/09/09/095522

.NET環境構築
https://docs.microsoft.com/en-us/dotnet/core/install/linux-package-manager-centos7

VPC作成
<img width="1440" alt="スクリーンショット 2019-12-17 0.23.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514262/ecb239c7-ad16-987e-e574-90564877946f.png">

サブネット作成
<img width="1440" alt="スクリーンショット 2019-12-17 0.27.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514262/6b30f134-923b-340e-42dc-382df24f64a2.png">

インターネットゲートウェイの作成
<img width="1440" alt="スクリーンショット 2019-12-17 0.33.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514262/de444f91-bf8a-a714-5885-e2e7d80f24ea.png">

インターネットゲートウェイをVPCにアタッチ
<img width="1440" alt="スクリーンショット 2019-12-17 0.35.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514262/7642fa1c-4a70-5303-6be8-82edaeb1e663.png">

サブネットからルートテーブルの編集
<img width="1440" alt="スクリーンショット 2019-12-17 0.40.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514262/2da3897f-39f1-7be5-23cc-5806095ffccd.png">

EC2インスタンス作成する。ipアドレスは有効にする。

作成した後、下記コマンドで接続
```
ssh -i wwwww.pem.txt ec2-user@xxx.yyy.vvv.zzz
```

参考URLよりdotnet-sdkをインストール

```
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm

sudo yum install dotnet-sdk-3.1
```

コンソールアプリ作成

```
dotnet new console
```

コンソールアプリ実行

```
dotnet run
```
ナレッジ管理のオープンソースをインストールしてみた

# 概要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/0cc1be86-f151-02ba-a31c-3ac795e53e46.png)

ナレッジ管理オープンソースBookStackを
Mampのローカルサーバーにインストールする手順

[BookStack](https://www.bookstackapp.com/)

#手順

## 1.GitHub リポジトリをクローン

```
git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch
```

## 2.composerインストール

```
cd BookStack
composer install
```

## 3. .envファイル設定

「.env.example」をファイル名「.env」に変更

**.envファイル内のデータベース情報を記入**

```terminal
# Database details
DB_HOST=localhost
DB_DATABASE=[データベース名]
DB_USERNAME=[データベースユーザー名]
DB_PASSWORD=[データベースパスワード]
```

**.envファイル内に言語指定追加**

```terminal
APP_LANG=ja
```

## 4.パーミッションの確認

下記のフォルダのパーミッションが書き込み可能か確認

- storage,
- bootstrap/cache
- public/uploads

## 5.アプリケーションキー作成

```terminal
php artisan key:generate
```

## 6. Mampの設定

**/Applications/MAMP/conf/apache/extra/httpd-vhosts.confの変更**

localhostのURLは「knowledge.bookstack.com」にしています。

```
<VirtualHost *:80>
    ServerName knowledge.bookstack.com
    DocumentRoot "[webルートのパス]"
    <Directory "[webルートのパス]">
        AllowOverride All
    </Directory>
    ErrorLog "logs/bookstack.local-error_log"
    CustomLog "logs/bookstack.local-access_log" common
</VirtualHost>
```

**/private/etc/hostsの変更**

```
127.0.0.1   knowledge.bookstack.com
::1         knowledge.bookstack.com
fe80::1%lo0 knowledge.bookstack.com
```

## 7.データベース更新

Mampだとmigrateがうまくいかないので「database.php」を下記の内容に変更

```php
'unix_socket' => '/Applications/MAMP/tmp/mysql/mysql.sock',
```

変更後に下記のコマンド実行

```
php artisan migrate
```

インストール完了

## 8.サイトにアクセス

**ログイン画面**

```
knowledge.bookstack.com
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/71fd9bf3-d35d-cd17-419b-f1e36051205d.png)

下記のメールアドレス・パスワードでログイン

```
メールアドレス ： admin@admin.com
パスワード : password
```

**ログイントップ**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/ae0e5e98-03a3-6a80-76a6-bee6df42474b.png)

## 9.エディタをMarkdownに変更

デフォルトではエディタがWYSIWYGなのでMarkdownに変更

**WYSIWYG**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/9040f8c0-6170-38fd-26f1-6a872bd2e767.png)

右上の「設定」リンクからページエディタを「Markdown」選択して設定を保存

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/4dbb2af6-a444-33a7-dc33-5c9ad11f8276.png)

**Markdownエディタ**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43894/27f1f2b4-f7b5-911b-becb-2f459b3f3e34.png)

#最後に

今回はMampで構築しましたが、Dockerで構築できるようにしたい。
あと、BookStackはlaravelで出来てるんですね。
rbenvからRubyまでのInstall

#備忘録
こんにちは！はじめまして！
完全なる備忘録として投稿致します。
ご覧になられた方の参考になれば幸いです。

##環境
- Windows10
- vagrant (boxはbento/centos-6.8)
- virtulbox
- centos

##インストール
rubyをインストールするために必要なツール各種。
流れとしては、
git→rbenv→rubyという手順。
バージョンなどこだわりがないのであれば、ドットインストール様の開発環境を整えようの講座で全て整う。
1からやりたい方は↓
https://github.com/rbenv/rbenv
##いよいよ！
rbenvがインストールできたら、
いよいよ、
```ruby
sudo yum install ruby
```
これで、何とかvagrantでRubyが使える。

##後記
バージョンにこだわらないのであれば、これで十分に使える。
まずは、rbenvでRubyの開発環境を構築してから、Rubyをインストールする流れ。
(ですます調が揃っていないのはご愛敬。。。あくまで備忘録です)
VSCodeのファイルエクスプローラーから不要ファイルを非表示にする方法

# 目障りなファイルを非表示に
VSCodeでUnityプロジェクトを開く際、ファイルエクスプローラー上に表示される `.meta`ファイルが目障りだったので非表示にした。

言語やプラットフォームに限らず使える設定なので、やり方をメモしておく。

## エクスプローラーの非表示ファイル設定
VSCodeのメニューから [Preference] - [Settings] を選択し、設定画面を開く。
<img width="482" alt="スクリーンショット 2019-12-16 22.57.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/a95acca5-d733-98c8-cd16-df328a3ebbb0.png">

検索バーに「Files: Exclude」を入力。
<img width="1110" alt="スクリーンショット 2019-12-16 22.56.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/e81cc1a0-1b06-ecce-0d53-3c54f9b0ec17.png">

「Add Pattern」で `**/*.meta`を追加。
<img width="562" alt="スクリーンショット 2019-12-16 22.56.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/77aa67b7-2521-5655-7ef8-dbdd85814414.png">

これで`.meta`ファイルがエクスプローラー上の表示から除外される。
<img width="215" alt="スクリーンショット 2019-12-16 22.56.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/dd7d0787-1635-5081-e053-9216f992e7cb.png">

同様に`.unity`や`.asset`、`.prefab`など、VSCodeで開く意味のないファイルを非表示にすると、エクスプローラーがスッキリする。

ユーザー設定／ワークスペース設定と分かれているので、必要に応じて使い分けるのが良いかと。

globパターンの詳細はドキュメントを参考に。
[Basic Editing in Visual Studio Code](https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options)
【rails】他のモデルのDBにimageを保存する方法

##記事投稿の理由
保存時に他のモデルに対してデータを保存する方法がわからず苦労したので、備忘録として残します。
今回はcarrierwaveを使用します。


###環境
rails 5.0.7
carrierwave

carrierwaveの導入に関しては参考になる記事を記載しておきますので、こちらを参照ください。
https://qiita.com/STHEXA/items/05a492bd9cf4cf31ba98


###方法

今回はproductのコントローラーとモデル。
imageのモデルを使用いたします。

###実装
バリデーションをかけると保存できなくなるようなので、presence:trueは記載しないで下さい。

```models/image.rb
class Image < ApplicationRecord
 belongs_to :product
  # モデルを保存できなくなるのでpresence: trueは記載しない

end
```

```models/product.rb
class Product < ApplicationRecord
  has_many :images
  accepts_nested_attributes_for :images
 #イメージをDB登録するために記載
```

fields_forを使うことで入れ子のモデル(Image)を表示させることができます。

```new.html.haml
 = f.fields_for :images do |image_field|
   = image_field.file_field :image　,class: "upload-image", type: "file"
```

コントローラーでnewアクションでAddressをbuild（newのリレーション版）をするようにします。
これにより、fields_for内の内容が表示されます。
また、StrongParameterも許可するようにします。fields_forは[引数に与えた名前]_attributesというname属性でフォームを作成するので、images_attributesを許可する必要があります。


```Products_controller.rb
class productsController < ApplicationController
  def new
    @product = Product.new
    @product.image.build
  end

  def create
    @item = Item.new(create_params)
      if @item.save
     else
      render= 'new'
  end

  private
  def create_params
    params.require(:item).permit( images_attributes: [:image, :id])
end
```

##参考
下記の記事は非常に丁寧に書かれており、わかりやすかったです。
是非ご一読下さい。

Railsでaccepts_nested_attributes_forとfields_forを使ってhas_many関連の子レコードを作成/更新するフォームを作成
https://ruby-rails.hatenadiary.com/entry/20141208/1418018874
Redmine チケットを書く側の視点と見る側の視点

# はじめに
なぜこの記事を書いたのかというと、以下のようなお誘いがあり、
自分のこれまでを振り返ることも含めて記事にしてみようと思ったからです。

★[Redmine Advent Calendar 2019](https://adventar.org/calendars/4221)

# なぜこの題目なのか？
なぜこの題目を選んだかというと、かれこれ組み込みソフトウェア開発者として前職含めて
10年になろうとしています。その中で、Redmineを活用しようとして挫折し、転職を経て、
再度挑戦してやっと形になってきました。
これまでの軌跡を観点の違う視点でまとめることでそれぞれの立場の方の参考になればと
思い、とりあえずまとめてみようと思います。
(自分の備忘録に近いところがあるのであまりためにならないかもしれないです。)

# チケットを書く側の視点
まずは書く側の視点。これは前職での経験です。
時系列順にどういう心境の変化がどういうタイミングで起こったかを書きます。

## 1.面倒くさい
まずはここ。これを超えないと廃れる。実際に前職では一時期廃れました。
だって、使い方がわからないし、なんで導入するか説明もないもんだもの。

面倒くさい理由は以下

1.何を書いていいかわからない。
2.何故導入すかわからない。
3.書いたことによるメリットがわからない。
**4.そもそもチケットを書くのが面倒くさい。**

まぁ、これです。大体の人が当てはまるのではないでしょうか。
前職で声が出てたのは3が多かったかな？
遠い昔なので忘れつつありますが…。

**とにかく説明がない！！！**

これに尽きるのではないでしょうか。ここの観点って結構大事だったと私は思っています。
裏を返せばこれを明確にしていけばRedmineの活用が見えてくるはずなので…。

## 2.面倒くさい→使える？
次の段階。まだ半信半疑です。
少しでいいのでメリットが見えるとここに行き着くと思います。
私が記憶している限り…
私が経験したのは
**「過去対策した部分のチケットが残っていて、困ったときに調べて経緯がわかった」**
これです。これを発見したとき、あれ？Redmineって案外使えるんじゃない？っと思いました。
今もここの考え方は凄く私の中では根強く残っています。

**ナレッジベースとしてどんな情報も残せるRedmineって便利!!!**

## 3.使える？→使える!!!
最終段階。確信に変わったときですね。
これは実は転職してから実感しました。
何故なら…

1.過去の情報がどこにあるかわからない。
2.過去の情報がなくなってしまっている。

上記のような問題点を抱えていたから。
過去の情報って案外馬鹿にできないことを痛感しました…。
経緯がわからないと手を出したときに痛い目見るんですよね…。ソフトあるあるです…。

# チケットを見る側の視点
さて、ここから、私が「書く側」から「見る側」に移り変わります。
書く側の視点から変化して何を対処してきたかを書きます。

## 1.慣れてもらう
まずは、ここから。書くことに慣れてもらう。書く内容は問わない。
ただし、お題は絞りました。まずはバグ管理から。
決めたルールはこれだけ。
ここから書きやすさを追求するためにヒアリングを定期的に行うようにしていました。
**ヒアリング。これ大事!!!**
うちの会社はそこまで大きくないからできるのかもしれませんが、
私は前職でも「現地・現物」にはこだわって、不具合が出たら即品質テスト場に
向かっていましたね。棟が離れていましたが走って行ってたなぁ…。
とりあえず、現場の人の声を聞いて、即日カイゼンを実施する。
これが最近できなくなってきているので初心に帰らないとと思う次第です…。

## 2.慣れた→活用してもらう
慣れて来たら活用してもらうように仕向ける!!!
そのためにはプラグインもちょこちょこ入れ始めました。
とりあえずは…

**「Redmine Issue Templates」**
↓あえてブログを紹介させて頂きます。
★[日々是精進。(はてな館)](https://daily-postit.hatenablog.com/entry/2019/03/22/105354)

実はうちの会社で今も無料で活用されているのこれだけだったりします。
後は有料のRedmine Lychee。
色々プラグインは入れよう計画はあるのですが手が回っていません…。

そして、私が見る側の視点で活用し始めたのはバグ件数の推移。
とりあえず上がっているバグの件数と解決数とを週毎に集計して…
最終的な報告のときに推移が減っていってますという報告をして活用していました。
今は別の人にその辺りは移管。
おそらくですが**活用方法は無限大**だと思うのですよね。

## 3.活用できた→一緒に考える
正直、私も業務が忙しくなってきて、片手間で管理が一人で出来なくなってきています。
色々と一人で悶々とする日々が続いて来ていたのですが、やっと仲間が増えはじめてきて
どうやって活用するかを一緒に考え始めました。
私はRedmineTokyoやらに参加して、色々な方と話をすることで違った見方ができるように
少しでもなってきたのかなぁっと考えておりますが、まだまだ…

★[Redmine.Tokyo](https://redmine.tokyo/projects/shinared)

しかし、言えることは一つ…
**一緒に考える仲間は大切!!!**

# 終わりに
以上になります。ざっくりとしていますが何かの足しになったでしょうか？
正直、ただの備忘録に近いです。

## あなたがRedmineを無理やり使っている「書く側」
もし、面倒くさいなと考えているのであれば、何か活用出来る方法がないかを
少し考えて見てください。それで世界が少し変わります。
私が活用方法の行き着いた先は**「ナレッジベース」**です。
答えはそれぞれだと思います。
イヤイヤではなく、少しでも前向きに捉えると色々と世界が変わると思います。

## あなたがRedmineを無理やり使っている「見る側」
管理は大変だと思います。でも、ヒアリングして、ドンドン改善すれば、
自ずと色々と環境が変わると思います。
滅気ずに頑張りましょう。**外に出れば仲間はたくさんいます。**
私はそれに勉強会に参加することで気づくことができました。
是非とも社内に籠もらずにたまには気晴らしに外にでるのもいかがでしょうか。

節操ない文章ですが、これにて終わります。
オンライン実行環境まとめ

# はじめに

[ゆるゆる新卒1年生 Advent Calendar 2019のアドベントカレンダー](https://qiita.com/advent-calendar/2019/yuruyuru-freshman)17日目の記事です。

## 背景

さまざまな事情でご自身のパソコンにプログラム実行環境がない、もしくは環境構築ができない方がいるかと思います。@daikikatsuragawa もその一人でした。今回はそのような状況でもプログラムを書きたい、実行したいと思っていた自分がお世話になっていた「オンライン実行環境」をいくつか紹介します。

## オンライン実行環境とは

「ブラウザ上でプログラムを作成して実行が可能な環境」です。プログラミング初学者や、プログラムをすぐに試してみたい人にとって、簡単で素晴らしいツールです。

# オンライン実行環境まとめ

## paiza.IO

URL: https://paiza.io/ja

### 概要

日本語のウェブサイトです。24以上のプログラミング言語をサポートします。コンパイルや実行が可能です。外部ファイルのアップロードも可能です。ユーザ登録の必要がなくすぐに使用可能です。Ideone.comと比較して、複数ファイルの実行も可能であるという利点があります。

### コメント

軽くコードを試すとき、主にこれを利用していました。簡単です。

## Ideone.com

URL: https://ideone.com/

### 概要

60以上のプログラミング言語をサポートします。コンパイルや実行が可能です。短縮URLでの共有が可能です。ユーザ登録の必要がなくすぐに使用可能です。

### コメント

paiza.IOで対応していない言語を試したいとき、役に立ちました。日本語に対応していないため、とっかかり難いかと思いますが、豊富な言語への対応が魅力的です。

## Google Colaboratory

URL: https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja

### 概要

Googleのアカウントをお持ちの場合、利用が可能なPythonの実行が可能な無料のツールです。Jupyter Notebook形式です。GPUの利用も可能です。 matplotlibを使用してグラフを描画できます。機械学習を扱う方にオススメです。

### コメント

機械学習に取り組むときにもってこいです。Jupyter Notebook形式だとグラフの出力もできます。GPUを使いこなすことでいろんなことが出来そうです。（類似しているものとしてKaggleのNotebookもあります。）

# おわりに

「オンライン実行環境」をいくつか紹介しました。さまざまな事情でご自身のパソコンにプログラム実行環境がない、もしくは環境構築ができない方々はぜひお試しください！
Could not find generator 'factory_bot:model'. でファクトリが作成できないとき

## ファクトリが作成できない

コマンドが見つからないようで、実行できない。。

```console
$ rails g factory_bot:model user
Running via Spring preloader in process 81847
Could not find generator 'factory_bot:model'. 
Run `rails generate --help` for more options.
```

## 解決策

古いプロセスに接続していることが原因でした。
下記で停止して、

```console
$ spring stop
``` 

もう一回ファクトリを作成すると、

```console
$ rails g factory_bot:model user
Running via Spring preloader in process 89115
      create  spec/factories/users.rb
```

成功しました！

## おまけ：springはアプリケーションプリローダー

>Springとは、Rails4.1から標準で付属するようになったアプリケーションプリローダーです。
Rails内では様々なライブラリのロードなどの前処理が行われるので、コマンドを実行するための待ち時間がかかってしまいます。
事前にバックグラウンドでライブラリをロードしておくことで、その待ち時間を短くするものがアプリケーションプリローダーです。

railsコマンドを素早く実行するためのライブラリだったんですね。

## 参考

[Rails 4 + react-rails gem: Could not find generator 'react:install'](https://stackoverflow.com/questions/33600745/rails-4-react-rails-gem-could-not-find-generator-reactinstall)



[Railsの開発効率をあげる - Springを使ってRailsのコンソールコマンドの実行を早くする](https://ruby-rails.hatenadiary.com/entry/20141026/1414289421)
エフェクト取り扱い説明書

# はじめに
この記事はC++を学び始めたくらいの人を対象にした、ゲーム制作でのエフェクトの取り扱いをまとめたものです。  

# エフェクトとは
ここで扱うエフェクトは、ある時発生して一定時間動いたあと消えるものを指す。  
(例 : あるキーを押したら自機周辺に白い円が現れ、時間経過で膨張し、一定時間経過後消えるもの)

# やりたいこと
毎フレーム各エフェクトの処理(円の半径を増やすなど)を実行し、一定時間が経過したかの判定を行い、経過していたらそのエフェクトを削除する必要がある。  
各エフェクトで更新内容が違うので、仮想関数を利用して解決する。  

# 基底クラス
そうと決まればさっさと基底クラスを作成してしまおう。  
すべての要素に必要な変数は、消えるまでの時間(定数)と発生してからの時間である。  
関数は、毎フレーム一度だけ呼ぶ更新用の関数(update関数)と、描画を行う関数である。  
エフェクトの削除はupdate関数の返り値でbool型を返してきて行うことにする。  
時間の更新のため、基底クラスのupdate関数の中身を作成してそれを実行するようにした。  
これらを実装する。  

```cpp
class Effect {
protected:
    Effect(unsigned int deleteFrame) : 
        mDeleteFrame(deleteFrame),
        mFrame(0)
    {
    }
public:
    virtual ~Effect() = default;
private:
    //発生からのフレーム数
    unsigned int mFrame;

protected:
    //発生からのフレーム数
    unsigned int frame() {
        return mFrame;
    }

    //削除までのフレーム数
    const unsigned int mDeleteFrame;

public:
    //削除する時にtrueを返す
    virtual bool update() {
        mFrame++;
        return false;
    }

    virtual void draw() const = 0;
};
```

# エフェクト管理クラス

この方式でエフェクトを作成すると、各エフェクトのupdate関数に加えて基底クラスのupdate関数も呼ぶ必要がある。  
また、各エフェクトをvectorなどの何かしらの方法で管理する必要がある。  
これらを管理するクラスを作成する。  

```cpp
class EffectManager {
public:
    EffectManager() {
        
    }

    ~EffectManager() {
        clear(); //下で定義
    }

private:
    std::vector<Effect*> mEffect;

public:
    void update() {
        auto itr = std::remove_if(mEffect.begin(), mEffect.end(),
            [](Effect *t){
                t->Effect::udpate();
                bool flag = t->update();
                if(flag) delete t;
                return flag;
            }
        );
        mEffect.erase(itr, mEffect.end());
    }

    void draw() const {
        for(const auto &i : mEffect) {
            i->draw();
        }
    }

    //要素を追加
    void add(Effect *effect) {
        mEffect.emplace_back(effect);
    }

    //エフェクト全消去
    void clear() {
        for(const auto &i : mEffect) {
            delete i;
        }
        mEffect.clear();
    }
};
```

あとは、このクラスのインスタンスを作成して毎フレームupdateとdraw関数を呼べばいい。  
エフェクトを追加したいときにadd関数に生成したインスタンスのポインタを渡すと自動的に更新削除までやってくれる。  

# 作成例

DxLibを用いて白い円が20フレーム膨張して消えるだけのエフェクトを作成する。  

```cpp
class WhiteCircle : public Effect {
public:
    WhiteCircle(int x, int y) : 
        Effect(20),
        x(x),
        y(y),
        r(0)
    {}

    virtual ~WhiteCircle() = default;

    virtual void update() override {
        r++;
    }
    virtual void draw() const override {
        DrawCircle(x, y, r, 0xffffff, FALSE);
    }

private:
    int x;
    int y;
    int r;
}
```

# おわりに

仮想関数を用いてエフェクトを簡単に取り扱えるようにやってみました。  
実際各エフェクトクラスの実装が簡単に書けて管理も考えなくていいので割と扱いやすいのかなと思います。  
改善点が多いコードなので是非考えてみてください。
FlaskとTensorFlowを利用した、顔画像の推論

# はじめに
- `TensorFlow` の `MNIST CNN` のチュートリアルを改造して、顔画像の学習と推論を実施しました。
- 今回は、`Flask` から推論を実施して、結果を表示してみます。
- ソース一式は [ここ](https://github.com/maedamikio/public/tree/master/abe_or_ishihara/learning) です。


# 概要
- 設定ファイルで指定しているクラス毎に、テスト画像による推論を実施しています。
- 各画像の結果は、青は正解、赤は間違いという意味です。
- それぞれ、どのクラスに分類されたかが、分かる様にしました。

![40q6c-l084k.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/3aee35ce-5f0b-6135-9837-257356f05a13.gif)

# Flask

## 学習モデルのインポート
- 前回作成した `face_deep.py` をインポートします。

```
import face_deep
```

## 推論
- 学習画像とテスト画像で推論を出来る様にしています。
- フォルダ内の `.jpeg` 全てを推論対象にしています。

```
@app.route('/predict/<folder>/<item>')
def predict(folder, item):
    """画像の推論."""

    if folder not in ['train', 'test']:
        abort(404)

    filename_list = sorted(glob.glob(os.path.join(DATA_PATH, folder, item, '*.jpeg')))
```

- 各画像は、`Pillow` で読み込み、リサイズ、グレースケール、値を `0-255` から `0-1` に変更します。

```
    image_list = []
    for filename in filename_list:

        face = Image.open(filename)
        face = face.resize((IMG_ROWS, IMG_COLS), Image.LANCZOS)
        face = face.convert('L')
        face = np.array(face, dtype=np.float32) / 255.0
        face = np.ravel(face)
        image_list.append(face)
```

- 各画像をまとめて、`face_deep.py` の `predict` に入力します。
- 推論結果は、`[ 99   0   0   0   0   0   0   0   0   0]` の様な確率を含む配列が画像分返却されます。

```
    percent_list = face_deep.predict(image_list, dtype='int')
```

- テンプレート用の修正を実施します。
- `color` は、対象の画像の推論結果が、正しければ、`True` 間違っていれば `False` で与えられます。
- `filename` で、テンプレートからは、画像のリンクを作成出来る様にしています。
- `percent` で、テンプレートで、画像のクラス別確率が表示される様にしています。

```
    rows = []
    for filename, percent in zip(filename_list, percent_list):
        color = CLASSES.index(item) in [index for index, value in enumerate(percent) if value == max(percent)]
        row = {'filename': os.path.basename(filename), 'percent': percent, 'color': color}
        rows.append(row)

    return render_template('predict.html', folder=folder, item=item, headers=CLASSES, rows=rows)
```

## テンプレート
- 上記の `color` によって、正解の場合は青色の `table-primary` 間違いの場合は赤色の `table-danger` を設定しています。

```
          {% if row.color %}
          <tr class="table-primary">
          {% else %}
          <tr class="table-danger">
          {% endif %}
```

- ファイル名等を元に、顔画像のリンクを作成しています。
- 保存されている画像は、大小様々なので、`size` で動的に変更しています。

```
            <td>
                <figure class="figure">
                  <img src="/data/{{ folder }}/{{ item }}/{{ row.filename }}?size=100" />
                  <figcaption class="figure-caption">{{ row.filename }}</figcaption>
                </figure>
            </td>
```

- 各画像のクラス毎の確率を表示しています。

```
            {% for percent in row.percent %}
            <td scope="row">{{ percent }}%</td>

```


# おわりに
- `Flask` を利用して、顔画像の推論結果を表示しました。
- 推論結果の一覧、クラス毎の確率が表示できるので、不適切な画像などの確認などがしやすくなりました。
- 次回は、様々な画像をアップロード出来るWebアプリケーションを作成したいと思います。
関数データ分析について雑にまとめました

# はじめにとおわり
今までQiitaで記事を書いていましたが、Hatenaブログに鞍替えします。

Hatenaブログ１本目は関数データ分析について雑にまとめました。
関数データを用いた回帰分析や主成分分析の方法を紹介しています。

https://saltcooky.hatenablog.com/entry/2019/12/16/010000
【メモ】オンプレミス環境IPv4におけるネットワークのルーティング設計（ポリシー）でやってたこと。

このエントリーは[#ssmjp Advent Calendar 2019](https://adventar.org/calendars/3948)の12/16に割り込みました（笑）

インターネットに携わったのはいまから約20年ちょっと前で、そこからイントラネット（LAN）設計や構築も経験して、運用もやってきていましたが、経験してきた中でおそらくいまでもさほど自分の中では変わっていない考えについてまとめてみました。

ただし、この考えは将来オンプレミス環境でしか通じないかもしれません。

#ルーティングポリシー
- ノード間は基本どのノードもつながる（pingレベルで届く）ことが前提
- インターネットとイントラネット間はNATを利用して接続。
- デフォルトゲートウェイは必ずInternetへ出る方向に記載。2つ以上ある場合は必ずメインで利用する回線に近いほうへ設定。
- 明らかにInternetに接続しないところだけnullを設定。nullを設定する箇所はL3スイッチなどルーティング機能をもつところで記載。
- ノード間をつなげない場合はファイアウォール(FW)機能でブロック
- 行きと帰りのルートは同じ経路を通る。同じ経路を通らないところにはFWを置かない。
- ルーティングプロトコル(RIP,OSPF,BGPなど)は同じ宛先に管理上経路が2通り以上ある場合に初めて利用する。

#上記ポリシーを実行した結果がもたらすもの
- ネットワーク構成図からルーティングがすぐに想像できる。

#上記ポリシーを曲げて／曲げられて妥協した結果やらかした失敗
- 新たにネットワークを作ろうとして、本来書いておくべきルーティング設定がなかったためにルーティング管理が煩雑になった。
- 本番環境のリリースにおいて通信ができないトラブルを何回か起こした。

#おわりに
セキュリティ上の理由でノード側にルーティングを書かないことで担保するというやり方をやってだいたいトラブルに陥ってきたので書いてみました。
あと、フィルタリングは責任分界点で記載するってのもありますが、又追々。

#参考サイト
ルーティングを設定するうえで必要なIPv4のアドレス体系は以下を参照。
[IANA IPv4 Address Space Registry](https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xml)
railsのログにタグ付けをしてログ種別を識別する

# railsのログにタグ付けをしてログ種別を識別する
`logger.tagged`を使用する事で、ログにタグを付ける事が可能です。
例えば、サブドメインやリクエストIDなどを指定してデバックに役立てます。

```ruby
$ logger.tagged("BCX", "Jason") { logger.info "Stuff" }
#=> [BCX] [Jason] Stuff
```
Python学習ノート_005

サンプルのコードを読む前に自分の考えで書いたコードです。

- ポイント
 - 文字列を比較する場合は下記の方法があります。
     - 完全一致（等価）: ==, !=
     - 部分一致: in, not in
     - 前方一致・後方一致（先頭・末尾）: startswith(), endswith()
 - if条件に複数条件（and orなど）ある場合、バックスラッシュ（\）を使えば何度改行してもいい。同じく、括弧()内であれば何度改行してもいい。インデントの制限もない。

```python:sample03.py
import random

#じゃんけんの定義
choices = ['グー', 'パー', 'チョキ']

str_gu = "グー"
str_pa = "パー"
str_chyoki = "チョキ"

icon_gu = "✊"
icon_pa = "✋"
icon_chyoki = "✌️"

people_win = "人の勝ち"
computer_win = "パソンコンの勝ち"

#パソコンの選択を作る
computer_choice = random.choice(choices)

#人の選択を聞く
people_choice = input("あなたの選択はなんですか。「グー、パー、チョキ」から１つを選択してください。 ")

#人が一部のみ入力する場合：
if (people_choice.startswith("g") or
    people_choice.startswith("ぐ") or
    people_choice.startswith("グ") ) :
    people_choice = str_gu

if (people_choice.startswith("p") or
    people_choice.startswith("ぱ") or
    people_choice.startswith("パ") ) :
    people_choice = str_pa

if (people_choice.startswith("c") or
    people_choice.startswith("ち") or
    people_choice.startswith("チ")) :
    people_choice = str_chyoki
    

#アイコンを設定する
computer_icon = ""
people_icon = ""
if computer_choice == str_gu :
    computer_icon = icon_gu
elif computer_choice == str_pa :
    computer_icon = icon_pa
elif computer_choice == str_chyoki :
    computer_icon = icon_chyoki

if people_choice == str_gu :
    people_icon = icon_gu
elif people_choice == str_pa :
    people_icon = icon_pa
elif people_choice == str_chyoki :
    people_icon = icon_chyoki

#パソコンの選択を出力する
if people_icon == "" :
    print("入力は間違いました。再度さいしょからやり直してください。")
    
#パソコンの選択を出力する
print("パソコンの選択は",
      computer_choice,
      computer_icon)
print("人の選択は",
      people_choice,
      people_icon)

#判断
# 1.一致する場合、
if computer_choice == people_choice :
    print("再度じゃんけんしてください。")
elif computer_choice == str_gu and people_choice == str_pa :
    print(people_win)
elif computer_choice == str_pa and people_choice == str_chyoki :
    print(people_win)
elif computer_choice == str_chyoki and people_choice == str_gu :
    print(people_win)
else :
    print(computer_win)
```
- 実行結果  
残念ですが、パソコンに負けました。  
![じゃんけんの結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/33b4a843-99a4-e080-da91-daef387d77d7.png)
ブランチごとに内容をわけたい

# 経緯
僕はそこそこの規模の開発をするとき必ず今後の開発予定などを未来の自分向けにメモしておくmemo.txtを作成する。  
この内容はリモートで管理する必要はなく、gitignoreしてもいい。  
しかし、僕は複数のPCで作業することがあり、リモートを介して内容の同期を行うため、gitignoreしてしまうとmemo.txtの内容を共有できない。  
一方で、ほかの開発者などがいる場合や不特定多数に公開している場合、masterブランチに自分向けのメモが転がっているのはよくない。  
そこで、ブランチごとにmemo.txtの内容を別々にする方法を調べてみた。  

# 使う機能
ブランチをマージするときに無視してもらえればいいので、競合が起きた時に自動的にどちらか一方のものを選択するGitの機能を使う。  
以下、その設定方法を記した。  

# config
gitで管理しているフォルダ(以下作業フォルダ)には隠しフォルダ.gitがあり、その中にconfigファイルがある。  
この中に以下の内容を追加する。  
```[merge "ours"]
    name = "Keep ours merge"
    driver = true
```

# .gitattributes
次に、.gitattributesファイルを作成する。  
作成する場所はとりあえず作業フォルダにしておく。  
(たぶん深いフォルダに入れるとgitignoreとかと同じ感じになるとおもう)  
ここに以下の内容を書く。  
```memo.txt merge=ours
```
ここでのmemo.txtは作業フォルダに直に置かれている場合で、例えばTestフォルダにあるmemo.txtを扱いたかったら  
```Test/memo.txt merge=ours
```
とすればいい。  

ここまでで設定は完了だ。  

# 意図的に競合を起こす
設定しただけではmasterブランチにメモの内容が公開されてしまうので意図的に競合を起こす必要がある。  
memo.txtを作成したときにそれぞれのブランチでブランチ名などを書いてコミットして置くといいだろう。  

# マージしてみる
マージしたときに  
```Auto-merging memo.txt
Merge made by the 'recursive' strategy.
```
のようなメッセージが出たら成功だ。  

# 注意点

最初に競合を起こすことを忘れがち。  
.gitattributesのファイル指定するときに./などをつけるとうまくいかない。  
configの内容はgit管理されないため個々のPCで行う必要がある。  
GitHubでプルリクエストが来た時にGitHub上でマージしてしまうとオートマージが機能しないので、プルしてマージしてプッシュする必要がある。  
(もしかしたらGitHub上のマージも設定できるかも……？？)  

# 参考
https://qiita.com/matsuoshi/items/f40d60a5c0a1a169a73b
railsでカスタムログ({Rails.env}.log以外のログ)を出力する方法

# railsでカスタムログ({Rails.env}.log以外のログ)を出力する方法

## カスタムロガーを追加したい場合

`config/application.rb`もしくは、`config/environments/`配下の各環境設定ファイル内で以下を指定

```ruby
config.sample_logger = Logger.new(Rails.root.join('log/sample.log'))
```

# ログフォーマット

## 日時のフォーマットを変更
Logger#datetime_format= を用いてログに記録する時の日時のフォーマッ トを変更することもできます。

```ruby
logger.datetime_format = '%Y-%m-%d %H:%M:%S'
# e.g. "2004-01-03 00:54:26"
```

コンストラクタでも同様にできます。

```ruby
require 'logger'
Logger.new(logdev, datetime_format: '%Y-%m-%d %H:%M:%S')
```

## フォーマットを変更

Logger#formatter= を用いてフォーマットを変更することもできます。
4つの引数 (severity, time, program name, message) を受け取る call メソッドを 持つオブジェクトを指定します。call メソッドの返り値は文字列にしてください。

### Procオブジェクトを指定する場合

```ruby
logger.formatter = proc do |severity, datetime, progname, msg|
  "#{datetime}: #{msg}\n"
end
# => "2005-09-22 08:51:08 +0900: hello world"
```

### 独自で作成したclassのオブジェクトを指定する場合

```ruby
logger.formatter = SampleLoggerFormatter.new

class SampleLoggerFormatter
  def call(severity, timestamp, progname, msg)
    "#{datetime}: #{msg}\n"
  end
end
```

## コンストラクタでも同様にできます。

```ruby
require 'logger'

Logger.new(logdev, formatter: proc {|severity, datetime, progname, msg|
  "#{datetime}: #{msg}\n"
})
```

# Rubyリファレンスマニュアル
https://docs.ruby-lang.org/ja/2.6.0/library/logger.html
High Sierra へのVMware Fusion 11.5VM起動時のエラー

##こまったこと
https://communities.vmware.com/thread/598474

これが起きました。
上記のサイトでは解決していますが、実際にやってみると"Allow"ボタンは表示されますが押しても文章は消えず何も起きません・・・。

色々探すとScreen Sharing系のアプリがあると押せない、とかもあるようなのですが、System Preferenceでは共有は何も有効にしていない・・・はて

##これで解決
Chromeを終了した。どうやらこいつ自身がChrome Remote Desktop系の何かをしているようだ・・・。
プログラミング初心者が次の壁を超えるためのポイント

@ug23 といいます。Twitterは [@ug23_](https://twitter.com/ug23_)です。よろしくお願いします。
TechTrainではサーバサイドをメインでメンタリングしています。

本記事は[【Mentor Ver.】TechTrain Advent Calendar 2019](https://qiita.com/advent-calendar/2019/techtrain-mentor)の16日目の記事です。

昨日は @kohey18 さんの[Nuxt.jsとcontentfulとNetlifyで作るWebサイト](https://qiita.com/kohey18/items/e1da7076437268dd650f)でした。

## TL;DR
ここから始まる一連のツイートを読んでください。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">1からプログラミングはじめた学生によく教えてるんだけど、1人開発だけどもこれらを口酸っぱく言ってた気がする<br><br>・自分が扱っているものが想定通りか確かめる<br>・少なくとも明日の自分が読めるように意味のある名前をつける<br>・自分が知っている方法に持ちこめるように問題を分割したり加工したりする</p>&mdash; ゆーじ / Yuji Imagawa (@ug23_) <a href="https://twitter.com/ug23_/status/1167241246928060417?ref_src=twsrc%5Etfw">August 30, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 背景
これをツイートした当時、ちょうど勤務先でインターンに来ていた学生のメンターをやっていました。

プログラミング経験はUdemyをちょっとやった、ということでHello, worldを書いたり、かんたんな文法は覚えているようでした。

彼が統計や分析のためにWebスクレイピングをやるということで、Pythonのライブラリを用いながらコードを書いていましたが、プログラミング初心者が躓くであろうポイントにたくさん引っかかっていました。

ただ、「自分もそうだったなぁ…」と思いながら教えていたり、「ただコードが動くようにするだけでなく、なにか1つ覚えて帰ってもらおう」という気持ちでメンタリングしていたのでその後のTechTrainのメンタリングに役に立っている気がします。

今回はそうしたポイントについて説明します。

## 変数や関数の戻り値が自分の想定通りか確かめながら進めよう
自分のやりたいことを実現するためにQiitaや技術ブログでのコードをコピペして動かす、というケースはよくあると思います。
私もよく知らない技術や初めて触るライブラリなどはそういう雑なやり方をしがちです。

問題になるのはそれを自分の書いているコードにそれを生かす場合です。
慣れていれば「この人は最初に○○クラスなのをそのままxxメソッド使ってるから自分のコードならyyyかな？」と想像できますが、コピペしたらとりあえず動くだろう、写経して動かそうという気持ちだと動きません。

そうでなくてもよくわからないライブラリを使っていたりすると自分がなにをやっているのかわからなくなりがちです。

- Rails文脈なら`ActiveRecord::Relation`なのかmodelのインスタンスなのか？
- PythonのBeautifulSoupではTagインスタンス（中のTagも走査可能）なのか、Stringの値なのか？
- ほかにも日付型なのか、日付を格納したただの文字列なのか？

いろんな場合があります。コードをコピペしたり、メソッドチェーンしながら自分のほしい値を取りたい場合**自分が扱っているものが想定通りか？**を考えてみましょう。

乗り越え方としてはこまめに（愚直に）printデバッグをしたり、型を確認するメソッドを使ったりするとよいかもしれません。

興味があればテスト駆動開発を実践するのもアリですね。

## 少なくとも明日の自分が読めるように意味のある名前をつけよう

「これって可能なのかな？」
「とりあえず動かしてみてから考えてみよう」
「動かない、こっちで試してみよう」

などとガチャガチャしてると自分で何をやってたかわからなくなりがちです。
変数名が `a` とか `aaa` とかになってると**どこまでうまくいっていたのか？もややこしくなりがちです。
ちょっと時間があいたり、明日出社したときに自分がなにをやっていたかわからなくなって最初からやり直す羽目になりがちです。

今のうちから変数名やメソッド名、クラス名にわかりやすい名前をつけるよう努力しましょう。特に、焦っているときほど。
もし、これからエンジニアを職業としてやっていきたい人は絶対名前をつける力が必要になるのでサボらずに鍛えましょう。
鍛え方としては以下の方法が考えられます。

- みんな大好き[リーダブルコード](https://www.amazon.co.jp/dp/4873115655/)を読んでみる
- 社内のコードを読んでみる: 名付けについて良いと思ったところ・意図がわからなかったものを書いた人に聞ければ聞いてみる
- 自分のコードを読んでもらってフィードバックをもらう

あとから思い出しやすくなっていると「調子どう？」と聞きにきた先輩に質問するとき楽だし、明日の自分も楽です。
質問される側としてはいちいち説明されるより、名前が読みやすい形になっている方がとてもありがたいです。

## 問題を分割したり変形したりして自分が使い慣れている形に持ち込もう
「このデータからこれを抜き出すにはこれをxxxしてyyyしないといけない。yyyの方法がわからない」
「yyyって○○ってことだからこないだのあそこでやったのをちょっと変えれば一緒だよ」
「あっ」

仕事って完全に同じ仕事は極めてまれですが、同じ**ような**仕事はよくあります。
直面している問題を少し変形したり、データの形をちょっと変えたりすれば自分が書いてきたコードや他で読んだコードと同じような処理で済むよ、ということはよくあります。現状の状況をうまく使ったり、問題をよりかんたんな変形できないか考えてみましょう。

こういう問題の組み換えみたいな脳、自分はどこで鍛えたんだって思いますが今思うと**高校数学**と大学1年生のときの数学だろうなと思いました。

もちろん、その形は実はあんまりよくないんだという話は後々出てくるかもしれませんが、一旦はスムーズにかける方で、レビューでより良い方法をもらえたら勉強がてらそっちに直すという動きはできると思います。

逆に言えばそういう得意なもの・慣れているものをある程度色々持っているとスムーズに実装できるし、自分のカンペみたいなのも作れて効率が上がるかもしれません。

## 最後に
こうしたポイントを考えながらプログラミングできると成長をより加速できるかもしれません。
それでもわからないことはTechTrainに登録して、私、あるいは他のメンターに聞いてみましょう。
everyday rspec メモ


### newとcreateの違い

- newだとvalidatioに基本は引っかからない
  - valid?でerrorsインスタンスを作成する
- createだとひっかる

### before

- 重複の処理は、beforeで定義する。（rubyのattr_accessor見たい。）

```
RSpec.describe User, type: :model do 


  before do 
    @user = User.new(first_name: "ee",last_name:"tets",email:"test1@aa.aaee",password:"aaaaaaaa")
  end

  it "姓、名、メール、パスワードがあれば有効な状態であること" do
    
    @user.valid?

    expect(@user).to be_valid
  end
  it "姓、名、メール、パスワードがあれば有効な状態であること" do
    
    @user.valid?

    expect(@user).to be_valid
  end

```

### メソッド

- to not_to
- be_valid
- include

### よくわからんメソッド

- validate_uniqueness_of
- scoped_to


### subject

無理やりsubject使った

- conetextをsubject使うときはよく使う見たい

```ruby

   before do 
    @user = User.create(first_name: "first",last_name:"last",email:"aaa@aa.aa",password:"aaaaaaaa")
   end
   subject {@user.name}
   it "ユーザーのフルネームを文字列として返すこと" do 
    
    is_expected.to eq "first last"
   end

```

### p32 アソシエーション的な

- belongs_to（単数形） Project.new(name:"aaaa", owner: user)
- has_many （複数系） Project.new(name:"aaaa", notes: note)

```ruby
    it "" do 
     user = User.create(first_name: "ee",last_name:"tets",email:"test1@aa.aaee",password:"aaaaaaaa")
     project = Project.new(name:"aaaa", owner: user)
     project.notes.build(message:"ssss",user:user)
     project.save!
     expect(project.notes.length).to eq 1
    end
```
コピペで使えるLFTPスクリプト

# LFTPとは

コマンドでファイルの転送操作をできるプログラム。
FFFTPやFileZillaといったFTPクライアントソフトを介さずに転送できる。
サーバからローカルへのダウンロードも、ローカルからサーバへのアップロードも可能。

この記事ではコマンドひとつで一定のファイル転送を行うスクリプトを作成します。

## 事前準備

まずはLFTPをインストールします。homebrewを使っている場合は下記でOKです。

```shell
brew install lftp
```

任意のディレクトリ内で、スクリプトを書くファイルを作成します。

```shell

touch lftp-script.sh
```
※ファイル名は良しなに変えて大丈夫です。

作成したら、`chmod a+x ./lftp-script.sh`で実行権限を付与しておきましょう。

## コピペで使えるスクリプト

作成した`lftp-script.sh`に以下を貼り付けます。

```shell
#! /bin/sh

HOST=サーバのホスト名
USERNAME=サーバのユーザー名
PASSWORD=サーバのパスワード
REMOTE="サーバのディレクトリまたはファイルまでのパス"
LOCAL="ローカルのディレクトリまたはファイルまでのパス"
```

ダウンロードでもアップロードでも共通で使える変数です。
値をサーバ接続に必要な情報やサーバ・ローカルのパスに書き換え、変数に格納します。

### 以降は用途に合わせて使ってください

目的に沿うものを、先ほどの変数に続けて記載してください。

```shell
# サーバからローカルへデータをダウンロードさせたい場合
FROM="$REMOTE"
TO="$LOCAL"
lftp <<EOF
open -u $USERNAME,$PASSWORD $HOST
set ssl:check-hostname false
mirror \
--dry-run \
$FROM \
$TO \
exit \
EOF
```

```shell
# ローカルからサーバへデータをアップロードさせたい場合
FROM="$LOCAL"
TO="$REMOTE"
lftp <<EOF
open -u $USERNAME,$PASSWORD $HOST
set ssl:check-hostname false
mirror \
--dry-run \
--reverse \
$FROM \
$TO \
exit \
EOF
```

※ダウンロード・アップロードどちらのスクリプトも揃えたい場合は、ファイルを分けてお使いください。
※誤操作に備えてファイル転送処理を実行させない`--dry-run`オプションを付けています。実際にファイルの転送を行いたい段階で`--dry-run`の行を削除してください。
※実現したいのは単純なダウンロード・アップロードではない？後述の[使う機会がありそうなmirrorのオプションまとめ](#使う機会がありそうなmirrorのオプションまとめ)でお目当ての結果が得られそうかチェックしてみてください。

## スクリプトを実行します

下記で実行。

```
./lftp-script.sh
```

### スクリプトを実行して起きたエラー

#### SSL証明書のホスト名とサーバのホスト名が一致していないとのエラー

```shell
mirror: Fatal error: Certificate verification: subjectAltName does not match ‘ホスト名’
```

SSL証明書のsubjectAltNameとサーバのホスト名が違っているようです。
※subjectAltName...ホスト名をいくつも登録しておけるものらしい

mirrorコマンドの手前に下記を付ければOK。

```shell
set ssl:check-hostname false
```

これは「ホスト名のチェックはしない」という指示です。
SSL証明書とサーバのホスト名が一致していないケースはよくあるので、遭遇しやすいエラーかと思います。

※このエラーを検索すると以下のような対処がヒットしますが、ホスト名相違のエラーを下記で解決するのは誤りだと思いますので、ご注意ください。

`set ssl:verify-certificate no`
→ 「SSL証明書が有効な証明書かどうかを確認しない」という設定のようです。SSL証明書の確認自体をやめたい訳ではないので、正しくないと思います。

`set ftp:ssl-allow false`
→ 「SSL接続をしない」という設定のようです。SSLで接続してほしいので、この指定はよくなさそうです。

## 使う機会がありそうなmirrorのオプションまとめ
`mirror`コマンドの後ろに記述します。

| オプション | 短縮形 | 指定内容 |
|:--|:--|:--|
| --dry-run | なし | ファイル転送自体は行わず<br>ログのみを出力する |
| --reverse | -R | ローカルからサーバへ<br>データをアップロードする |
| --delete | -e | 転送元に存在しない<br>ファイルが転送先にある場合、<br>転送先からそのファイルを<br>削除する |
| --only-newer | -n | 転送元のデータのうち、<br>更新日時が転送先より新しい<br>ファイルのみを転送先へ<br>転送する |
| --only-missing | なし | 転送元にしか存在しない<br>ファイルのみを転送先へ<br>転送する |
| --exclude-glob 拡張子 | -X | \*.zip のように指定する。<br>転送対象から特定の拡張子の<br>ファイルを除外する<br>※複数回指定できる |
| --parallel=数字 | -P | 転送処理を並列に行う。<br>いくつを並列処理するかを<br>指定する<br>※処理速度を速める為の機能 |
| --verbose | -v | 処理したファイルの<br>処理結果を表示する |

## 参考にしたページ
[LFTP公式マニュアル - http://lftp.yar.ru/lftp-man.html](http://lftp.yar.ru/lftp-man.html)
[lftp で "Certificate verification: certificate common name doesn't match requested host name" というエラー - https://qiita.com/yuki12/items/b0a9e7efa79a80309c0b](https://qiita.com/yuki12/items/b0a9e7efa79a80309c0b)

## あとがき
ファイルの転送操作にはLFTPの他にLinuxコマンドのrsyncやSSHやGit hooksといったものも活用できそうです（そちらの方がメジャーかも...？）
今回は使う機会があったのでまとめてみました。誰かの役に立つと良いなあ。
React Native で世界地図を表示する

# はじめに
仕事で React Native を使って開発をしており、知見が溜まってきたのですが、記事に起こそうと悩んでる間にかなり経ってしましました。

今回は、画面上に世界地図を表示する方法についてです。
イメージは下記の感じです。

![Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-16 at 22.37.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/501b6501-ce56-4156-e703-df783fc1cf83.png)

# 使用しているライブラリ

- `d3-geo`
- `i18n-iso-countries`
- `react-native-svg`
- `topojson-client`
- `world-countries`

# 実装方法
まずはマップデータ必要です。
日本地図はちょっと骨が折れるのですが、世界地図は[このデータ](https://github.com/vega/vega/blob/master/docs/data/world-110m.json)を使えば簡単に対応できます。

```javascript

import worldData from 'src/assets/data/world-110m.json'
import { feature } from 'topojson-client';

const WorldMapPage: React.FunctionComponent = () => {
  const mapData = feature(worldData, worldData.objects.countries).features;
  ...
```

画面上にスポット（赤い丸）や、国を塗りつぶしたい場合は下記のように実装します。

### スポット
```javascript
import countries from 'world-countries';
...
const WorldMapPage: React.FunctionComponent = () => {
  ...
  const spotGeos = [
    { code: 'JPN', volume: 15 },
    { code: 'USA', volume: 30 },
  ];
  spotGeos.reduce((acc, sg) => {
      const country = countries.find((c) => c.cca3 === sg.code);
      if (!country || !country.latlng) return acc;

      acc.push({
        coordinates: country.latlng.slice().reverse(),
        volume: sg.volume,
      });
      return acc;
    }, [] as any);
```

### 国のカラーリング
```javascript
import isoCountries from 'i18n-iso-countries';
...
const WorldMapPage: React.FunctionComponent = () => {
  ...
  const paintCountry = [
    { id: 'CHN' },
    { id: 'HKG' },
    { id: 'GBR' },
    { id: 'FRA' },
    { id: 'ITA' },
    { id: 'KOR' },
  ];
  const getColor = (numericId: string) => {
    const alpha3 = isoCountries.numericToAlpha3(numericId);
    return paintCountry.find((c) => c.id === alpha3)
      ? `rgba(38,50,56,0.5)`
      : `rgba(255,255,255,1)`;
  };
```

メルカトル図法上にプロットできるように、マッピング関数を定義します。

```javascript
const viewWidth = 800;
const viewHeight = 450;

const projectMercator = () =>
  geoMercator()
    .scale(viewWidth / ((2 * Math.PI * (360 - 0)) / 360))
    .center([0, 0])
    .translate([viewWidth / 2, viewHeight / 2])
```

これで準備は完了です。
あとは `react-native-svg` を用いて、画面上に描写します。

```jsx
<Svg
  width={size}
  height={size * (viewHeight / viewWidth)}
  viewBox={`0 0 ${viewWidth} ${viewHeight}`}
>
  <G>
    {mapData.map((d, i) => {
      return (
        <Path
          key={`path-${i}`}
          d={geoPath().projection(projectMercator())(d)}
          fill={`${getColor(d.id)}`}
          stroke="#000000"
          strokeWidth={0.5}
        />
      );
    })}
  </G>
  <G>
    {spots &&
      spots.length > 0 &&
      spots.map((sg, i) => (
        <Circle
          key={`circle-${i}`}
          cx={projectMercator()(sg.coordinates)[0]}
          cy={projectMercator()(sg.coordinates)[1]}
          r={sg.volume}
          fill={`rgba(233,30,99,0.5)`}
        />
      ))}
  </G>
</Svg>
```

`size` はここでは画面幅を取得して設定しています。
上記の手順で、国の塗りつぶしと、地図上に円をプロットすることができました。

日本地図を描きたい場合は、日本地図用のデータを取得する必要があります。
また、世界地図と比べて縮尺が異なるので微調整が必要です。
データさえ用意できれば、描写は同様の手法で実現可能となります。

# おわりに
今回は、半年間、投稿が遠のいてしまいました。
ニッチな知見は整理して、言語化して少しずつ記事にできればと思います。