OmniAICreator/Qiita-1.07M huggingface dataset:
テストプロセスを一つにまとめたマインドマップテンプレートの展開

#はじめに
この記事は[エムスリーキャリア Advent Calendar 2019 7日目の記事です。](https://qiita.com/advent-calendar/2019/m3c)
はじめまして、エムスリーキャリアでQAを担当しているyu7117です。
今回は普段の業務でソフトウェアテストを行う際に使用しているマインドマップのテンプレートを展開しようと思います。
以下がテンプレートの全容となります。
![タイトル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/3066d109-4cca-1f20-811f-ba0d48341dac.png)

##テンプレートの特徴
 - 一枚のマインドマップでソフトウェアテストのテストプロセスをまとめています。
 - 本テンプレートは案件単位で作成しています。そのため中心のタイトルには案件名を記入します。
 - 使い方として、右上の仕様考察から下に沿って各メインブランチに対してブランチを記述していく形となります。
 - 一般的なマインドマップには記載する際の[ルール](https://www.mindmap-school.jp/mindmap/mindmap-law/)がありますが、私はあまり気にせず直感的に作成しています。
 - マインドマップ作成ツールとしては[XMind](http://jp.xmind.net/)を使用しています。

※本テンプレートではテスト計画、テスト戦略を記述するスペースがありませんが、
これらを作成する際には別のシートとして作成した方が簡潔にまとめることができると考えているため含めていません。

それでは各ブランチの役割について説明します。
##仕様考察
![仕様考察.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/d307ad41-5b4f-0d4e-fe03-5ab1963b9517.jpeg)

仕様考察のブランチでは仕様分析を実施します。
大枠として以下の4項目について考えます。

 - 案件を実施する背景
 - 変更点
 - 変わらない場所
 - 類似施策

ここでは起案された施策に対して実施する目的は何なのか、どのような変更が加えられるのか、類似の機能がある場合はそちらには変更を加えないのかを列挙し、検討します。
この段階では起案者の要求に対して、改修しようとしている内容で妥当なのかを検討します。

##テストスコープ
![テストスコープ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/e9be4926-8564-3400-4dc3-f953368ef048.jpeg)

テストスコープのブランチも役割としては仕様分析となります。
大枠としては以下の２項目となります。

 - 確認するところ
 - 確認しないところ

確認するところでは、主な改修部分やリグレッションテストとして確認すべき影響範囲について記載します。
一方、確認しないところについてはQA環境の制約によって現時点で確認できない部分や関係者との取り決めでテスト範囲が決められている際に記載することで保証範囲を明らかにします。
##仕様の不明点
![仕様の不明点.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/094a96db-c17c-9c10-2c64-f05f919469e8.jpeg)

仕様の不明点には、各テスト工程で発生した自分が理解できていない仕様や各ドキュメントに明記されていない仕様が生じたタイミングで記載します。腹落ちできていない仕様をまとめておくことで開発者に質問する際にも展開しやすかったり、FIXMEのように使うこともでき仕様の抜け漏れを防ぐことに役立ちます。
##テスト設計
![テスト設計.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/3d413d50-91bb-8f28-c1b0-27c4f3049e62.jpeg)

テスト設計ではこれまでに記述した上部のブランチをインプットにテスト設計を作成します。
この際、マインドマップの左半分を確認するようにしています。
![テスト設計補助.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/82db5e26-48cd-581c-e2e0-3bbf4e798796.jpeg)

ここにはOstrandの4つのビューと仕様ベースと要件ベースの考え方を記載しています。普段の業務では案件によってテストの規模がまちまちなこともあるため、個人的には常に最適なアプローチはないと思っています。しかし、どの観点も不具合を漏れなく抽出するためには欠かせないものだと感じているため、常に意識できるよう記載しています。
##業務上使用する際の流れ
![業務上使用する際の流れ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/61e30b09-c00f-ff23-d54e-bdc7bb708333.jpeg)

ここではシステムが改修された状態で、ユーザーが実際に使用した時を記載し、不整合な状況が発生していないか一度書き出してみています。使用考察と何が違うのか、と感じるかもしれませんが、この工程はテスト設計後に行うことによってテスト設計に抜け漏れがないことを確認する意味合いが強いです。ここで問題があれば仕様の考察にフィードバックし、問題がなければテストケースの作成を行います。
##テストケース
![テストケース.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116611/79f61bc7-0508-c325-0356-0d377dc9e5d9.jpeg)

テスト設計を元にテスト実装を行います。
テストケースが一通り作れたらそのままテスト実行に遷移します。
期待通りの結果であれば赤い星のマーカーを付け、期待に反する結果であれば青い星のマーカーを付け実際の動きを記録し、開発者にフィードバックします。
全テストケースが実施完了した段階でマインドマップを画像としてエクスポートし、開発者に展開しています。画像にすることでXmindの導入を伴わずとも内容を確認することができます。

##最後に
以上の要領でテストを進めています。
本テンプレートは随時更新を加え、使いやすさを向上しようとしているので
改修案がある方はぜひお声かけいただければと思います。
Jupyter Notebookでカーネルを増やそう

# はじめに
Jupyter NotebookでPythonを使っているときに、複数の仮想環境を扱う方法の紹介です。
※ コマンドは、macOSのものです。Windowsなどでは、記述方法が変わるのでご注意ください。

# カーネルの仮想環境を追加する

以下では、サンプルとしてPython3.8の仮想環境を追加します。
Python3.8は、`python3.8`コマンドで実行できるとします。未インストールの場合は、 
 https://www.python.org/downloads/ などからダウンロードしてインストールしましょう。

まずは、venv38という仮想環境を作成し、有効化します。別の仮想環境名を使用する場合は、以降のvenv38を適宜読み替えてください。

```
python3.8 -m venv venv38
source venv38/bin/activate
```

`pip install ...`で必要なライブラリーを適宜インストールしてください。

カーネルに仮想環境を追加します。

```
pip install ipykernel
python -m ipykernel install --name venv38
```

# 追加したカーネルの利用

jupyterは非仮想環境下で使うことにしましょう。一旦、`deactivate`で仮想環境を抜けます。

`jupyter-notebook`でJupyter Notebookを起動します。
右上の「New」から「venv38」を選ぶと、venv38の仮想環境で新規に始められます。

# 既存ノートブックのカーネルを変更する

まず、既存のノートブックを開いてください。
Jupyter NotebookのKernelメニューのChange kernelでカーネルを変更できます。
変更できると、右上のカーネルの表示が変わります。

# 追加したカーネルの確認

以降では、追加した仮想環境上での実行とします。

`jupyter kernelspec list`でカーネルとそのパスの一覧を確認できます。

# 追加した仮想環境を削除する

`jupyter kernelspec uninstall venv38`で、追加した仮想環境を削除できます。

# ライブラリを追加する

以降では、追加した仮想環境のJupyter Notebook上での実行とします。

たとえば、venv38に、NumPyのインストールを追加したいとしましょう。
通常ですと、`!pip install numpy`でできますが、このようにするとvenv38ではなく、本体にインストールされます。
Jupyter Notebookから仮想環境にインストールしたい場合は、以下のようにします。パスは上記で確認したパスではなく、最初に作成した仮想環境のパスです。

```
!source /path/to/venv38/bin/activate; pip install numpy
```

以上
#Rails logger  でログ出力されることを #rspec で検証する  ( expect logging in rspec )

expect の中に Rails.logger みたいにメソッドまで書けたんだ...まるで知らずに今まで苦労していた気がする

書き方が推奨かどうかは不明

doubleを繋いだりした方が良いのかもしれない

with で特定のエラーメッセージを期待するが、ゆるい正規表現にしておく

```rb
    it 'logging as fatal' do
      expect(Rails.logger).to receive(:fatal).with(/Some error message/)
      subject
    end
```

[logging - RSpec: how to test Rails logger message expectations? - Stack Overflow](https://stackoverflow.com/questions/10998160/rspec-how-to-test-rails-logger-message-expectations)

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2811








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Firebase consoleで登録したFCM(プッシュ通知)で受け取れるデータメモ

FCM（Firebase Cloud Messaging）は、アプリがForegroundの場合と、Backgroundの場合でデータの受け取り方と形式が異なります。
その辺りを簡潔にまとめました。

#### 公式リファレンスは[「こちら」](https://firebase.google.com/docs/cloud-messaging/android/receive?hl=ja)

## アプリがForegroundの場合
FirebaseMessagingService#onMessageReceived で以下のデータを受信できます。
ちなみに、画面上に通知は表示されません。

```
============================
Class       : RemoteMessage
From        : xxxxxxxxxxxx
To          : null
MessageType : null
MessageId   : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SentTime    : 1575594729695
Priority    : 1
OriginalPriority : 1
Ttl         : xxxxx
CollapseKey : （アプリのパッケージ名）
============================
Class       : Notification　※RemoteMessage.getNotification()
ChannelId   : null
Title       : （設定したタイトル）
Body        : （設定したメッセージ）
ClickAction : null
Tag         : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
============================
Class       : Map<String, String>　※RemoteMessage.getData()
Data :
{
    custom_key1=custom_value1,
    custom_key2=custom_value2,
    ...
}
```

"Data"は、Firebase consoleで入力した"Custom data"の Key / Value Map です。

## アプリがBackgroundの場合
上記onMessageReceivedは呼ばれません。
代わりに、プッシュ通知をタップしてアプリを起動した場合のみ、情報を取得できます。

情報は android.intent.action.MAIN が指定された Activity で取得できます。
onCreate or onNewIntent で Intent.getExtras に Bundle（Key / Value）の形式で入っています。

```
{
    // RemoteMessage
    from=xxxxxxxxxxxx,
    google.message_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    google.sent_time=,
    google.delivered_priority=high,
    google.original_priority=high,
    google.ttl=,
    collapse_key=（アプリのパッケージ名）,

    // Custom data
    custom_key1=custom_value1,
    custom_key2=custom_value2,
}
```
復数のプロジェクトにアクセスする


アプリや管理機能から復数のプロジェクトにアクセスしたい場合がある。
[ここ](https://firebase.google.com/docs/projects/multiprojects?hl=ja)にやり方は書いてあるが、いちおう検証。

## 異なるプロジェクトのFirestoreにアクセセスしてみる

やりかたは難しくない。
ポイントはinitializeAppで、

admin.initializeApp(configInfo, **識別名***);

と、識別子を指定すること。何も書かなければ最初に初期化されるものがdefaultとなるらしい。
識別子が無いと「既にアプリは初期化されてるぞ！」的なエラーが出る。



```js:index.js
const admin = require('firebase-admin');

//鍵の読み込み
const stagingAccount = require('/Users/tamaki/configs/staging-xxxxx.json');
const productionAccount = require('/Users/tamaki/configs/production-xxxxx');

//project1 config
const stagingAppConfig = {
    credential: admin.credential.cert(stagingAccount),
    databaseURL: 'https://staging-xxxxx.firebaseio.com'
}

//project2 config
const productionAppConfig = {
    credential: admin.credential.cert(productionAccount),
    databaseURL: 'https://production-xxxxx.firebaseio.com'
}

//initialize
const staging = admin.initializeApp(stagingAppConfig, 'staging');
const production = admin.initializeApp(productionAppConfig, 'production');

//db
const stagingDB = staging.firestore();
const productionDB = production.firestore();

//insert
stagingDB.collection("members").add({ name: "hoge" })
productionDB.collection("members").add({ name: "foo" })
```

firebase-admin以外（クライアント）でのやり方はそのうち検証する。

>認証とかを考慮すれば。上記を利用してFunctions作ってやるしかないのかな。。。
可変オブジェクト/不変オブジェクト

初学者ですが、個人的な勉強のためまとめました

##可変オブジェクト/不変オブジェクト

・オブジェクトに一度セットしたフィールドの値を、後から変更できるオブジェクトを**可変（mutable）オブジェクト**、変更できないオブジェクトを**不変オブジェクト(immutable)**という

・**java.lang.Stringクラス**や**java.io.Fileクラス**のインスタンスは不変オブジェクトの代表例であり、
値を後から変更することはできない
新しい値を扱いたい場合は新しいインスタンスを作るしかないが、**「変数の値(オブジェクトに対する参照)を変更」**するのであって、**「オブジェクトの状態を変更」**するわけではないで、そこの違いをしっかり理解すべし

・不変なオブジェクトを定義するには以下のようにする 
　①オブジェクトの内部状態を変更可能なメソッドを提供しない(**setterメソッド**など)
　②**クラスをfinalで宣言**し、どのメソッドもオーバーライドされないことを保証する(サブクラスからの状態の変更を防ぐ)
　③**全てのフィールドを"private final"**で定義する("final"の指定は必須ではないが、より明示的に不変クラスであることを宣言できる)
　④内部に可変オブジェクトを保持している場合、そのオブジェクトを外部に提供しない。（**getterメソッド**など）また、該当可変オブジェクトの値を内部的に変更しない
信号処理に関数解析の考え方を導入すると何が嬉しいの？

# はじめに
この記事では「信号空間」について説明します。信号空間とは信号処理を関数解析で表すためのテクニックです。

　二つの信号があるとします。信号は複数の要素から構成されています。
要素どうしに「代数演算構造」を導入します。これは難しそうですが、安心してください。
線形代数でもおなじみの「線形空間の公理」を信号の要素間で満たしていることを保証しているだけです。

![signal_space.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/0cd97103-1d7f-6e09-1f67-96cf69d06681.png)
（tは時間）
　では、信号同士に代数演算構造を導入すると何が嬉しいのでしょうか。この記事では、その代表的な手法として信号の展開表現を説明します。

# 信号の展開表現
「信号の展開表現」とは、信号$f$を基底行列$\phi$と展開係数ベクトル$\bf v$によって
$$f = \phi \bf v$$ 
と表現することです。

このとき、基底の種類によって展開の名前が変わります。
例えば「正規直交基底」で信号$f$を表すと「正規直交展開」といいます。

ポイントとして、
K次元信号空間はK個の線形独立な信号があれば基底を構成できます。
しかし無限次元信号空間においては線形独立な信号であっても基底にならない場合があります。

つまり、信号の展開表現とは信号を基底と展開係数ベクトルで表すことでした。

# まとめ
信号空間を導入すると、信号からノイズを数理的に除去することなどができます。
今回は線形空間で表現しましたが、信号空間というと「ヒルベルト空間」による表現の場合が主流です。

最後にもっと学びたい方は、森北出版からでている[「不規則信号処理」](https://www.morikita.co.jp/books/book/2828)がおすすめです。
Swift Network.framework Study 20191207「Server TCP」その3 receiveメソッド使用 改善

# Study

Network.framework
Study：Server側

## 環境
Client：Java、NetBeans
Server：Swift、Xcode

# Client Source Java

複数回送信する様に修正。

```java
package example.java.network;

import java.io.PrintWriter;
import java.net.Socket;

public class ExampleClientSocket {
    public static void main(String[] args) {
        try(Socket socket = new Socket("localhost", 7777);
            PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);) {
            for(int i = 0; i < 5; i++) {
                printWriter.println("Example Send Data");
                Thread.sleep(5000);
            }
        }
        catch(Exception e) {
            System.out.println(e);
        }
    }
}
```

# Server Source Swift

NWListerを使用する
コネクション確立後のNWConnectionに受信処理登録、開始実施
受信バイト数指定出来るreceiveメソッド使用。
受信したデータ1回分から、maximumLength数分取得しました。
下記の例だと5バイト。
5バイト以上を送信したとしても、6バイト目以降を連続して受信がコールされるわけではない様です。
自ら受信をコールする必要がある。
receiveメソッドを受信完了までコールする。
completionの受信データがnil以外、完了フラグがfalse時にreceiveメソッドをコール。

## main.swift

```swift
import Foundation
import Network

var networkServer = NetworkServer()

networkServer.startListener()

while networkServer.running {
    sleep(1)
}
```

## NetworkServer.swift

```swift
import Foundation
import Network

class NetworkServer {
    public var running = true

    func startListener() {
        let myQueue = DispatchQueue(label: "ExampleNetwork")

        do {
            let nWListener = try NWListener(using: .tcp, on: 7777)
            nWListener.newConnectionHandler = { (newConnection) in
                print("New Connection!!")
                newConnection.start(queue: myQueue)
                self.receive(nWConnection: newConnection)
            }
            nWListener.start(queue: myQueue)
            print("start")
        }
        catch {
            print(error)
        }
    }
    
    func receive(nWConnection:NWConnection) {
        nWConnection.receive(minimumIncompleteLength: 1, maximumLength: 5, completion: { (data, context, flag, error) in
            print("receiveMessage")
            if let data = data {
                let receiveData = [UInt8](data)
                print(receiveData)
                print(flag)
                if(flag == false) {
                    self.receive(nWConnection: nWConnection)
                }
            }
            else {
                print("receiveMessage data nil")
            }
        })
    }
    
}
```
Quest Basicsの紹介

みなさん、Oculus Quest向けコンテンツ開発、してますか！
今回は、Unity初心者の方がQuestのコンテンツ開発の際に役立ちそうな簡単なサンプル集、Quest Basicsを紹介します。

##　誰のために、なぜこんなもの？
そもそもQuestの開発には、Oculusが出している公式のSDK　Oculus Integrationという便利ツールがあります。どう使うか、という公式サンプルもしっかり作ってあって非常に勉強になります。
###　しかしながら！
このOculus Integration、なかなか複雑な作りになっていて、正直初心者の方がこれを参考になにか作ろうと思うと、かなりハードルが高いのでは、と感じてしまいます。
なので、
####　初心者の方が、
####　はじめてQuestのコンテンツ開発をしようとした際にまあ使うだろうとう要素を集めて、
####　簡単なシーン構成で理解しやすくした、
そんなサンプル集をめざして、Quest Basicsを創ることにしました。

##　なにはともあれ
以下のGithubのURLからダウンロードしてみてください。おっと、Starをクリックしていいねするのを忘れずに！
https://github.com/hassydhw/QuestBasic

##　簡単な中身の紹介
たくさんシーンがあるように見えますが、内容によっていくつかのグループに分けています。
_ 01_xx		いろいろなコントローラを表示
_ 02_xx		オブジェクトを操作する例
_ 03_xx		uGUIを操作する例
_ 04_xx		オブジェクト＋uGUIどちらも操作
_ 05_xx		コントローラーのいろいろな入力を取得
_ 06_xx		スティックの入力を利用する例
_ 07_xx		HMD側のセンサーの取得

##　それ以外にも
PrefabsフォルダやScriptsフォルダの中に、参考になりそうなものをあつめてあります。

##　今日はここまで
今日のところは、こんなものがあるよ、という簡単な紹介に留めておきます。
このAdvent Calendar、非常に開いてる場所が多いので（omg）、今後何回かに渡って、具体的な使い方とか、このあたりを参考にするといいよとか、そういった初心者の方向けの使い方を書いていこうと思います。

##　ところで、あなた誰？、って方
宣伝っぽくて恐縮ですが、VRプロフェッショナルアカデミーという、VRコンテンツの作り方を教える学校で、初心者向けコースの講師をやっています。このBasicsも、生徒向けの教材の一環として作ったものなのですが、自分の生徒以外にも初心者の方には広く使っていただきたいとおもっています。
VRコンテンツ作ってみたい！っておもった方はこちらも覗いてみてください。
https://vracademy.jp/vrBeginner.html
micro:bitとWindowsをUSB経由でシリアル通信させる

# Windows側の準備
## ドライバの取得
以下のURLから最新のドライバをダウンロードする。
https://os.mbed.com/handbook/Windows-serial-configuration

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28184/fe400a77-dc12-9802-940f-baf929086451.png)

## ドライバのインストール
ダウンロードしたmbedWinSerial_16466.exeを実行。
![install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28184/f33f12bf-8249-d390-2605-0ce39a06fbc8.png)

インストールに成功すると「The driver was installed successfully」というメッセージダイアログが表示されるので[Finish]釦を押下して終了します。

## COMポートの確認
デバイスマネージャを開いて「ポート(COMとLPT)」のところに「mbed Serial Port(COM4)」のような表示があれば成功です。
※COMポートの番号は環境により変わってきます。
![Device.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28184/0c259c33-7550-2118-c39a-a0b6d492afe3.png)

## 接続テスト
ターミナル（今回はTeraTerm）を起動して、以下のような設定をします。
![com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28184/8449a0d8-2e31-dca9-7cac-ada216b75d22.png)

micro:bit側のスクリプトを作ります。
今回はA釦を押下するとシリアルに"Push A"を書き出し、B釦を押下するとシリアルに"Push B"と書き出すスクリプトとなります。
![microbit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28184/bde151f2-7bb4-998e-9215-261c2e9a0e5c.png)

JavaScriptで見るとこんな感じ。

```javascript

input.onButtonPressed(Button.A, function () {
    serial.writeLine("Push A")
})
input.onButtonPressed(Button.B, function () {
    serial.writeLine("Push B")
})
serial.redirect(
SerialPin.USB_TX,
SerialPin.USB_RX,
BaudRate.BaudRate115200
)
```

作成したプログラムをmicro:bitにダウンロードしてどうさせ、A釦かB釦を押下するとPC上のターミナルに"Push A"や"Pushu B"が表示されます。
![run.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28184/389d9403-c4ff-a9ac-d350-fc73bae4a8aa.png)

## おまけ
温度とか明るさ、加速度センサーは簡単に取得できますが、方角(コンパス)を取得しようとするとmaicro:bitの調整が必要になります。
micro:bitのLEDで「Tilt to fill screen」と評されたら、micro:bitを画面の中心にある点が全体を埋め尽くすまでいろんな方向へ傾けてください。
そのあとに、実際のスクリプトが実行されます。
Reactでwebページを製作、Firebase Hostingで公開した

#フィットネスサービス「UPLIFT」のwebサイトを作った
![upliftlogo_black.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459816/d763ea07-52e1-28e7-099f-71b649805faa.png)
###UPLIFTとは
>自分にあったワークアウトが見つかる
>最新の情報で理想の自分に近づく
>数値記録・目標設定もすべてここで
>※公式HPより引用

###リンク
[UPLIFT](https://upliftfitness.jp/"UPLIFT")

#開発ログ
###経緯
私の友人であるFounderの甲斐がフィットネスサービスを立ち上げるということでwebページの製作を依頼されました。彼はiPhoneアプリ開発に注力しているのでwebは私が担当。

UPLIFTアプリは近日中にApp Storeで公開される予定です。

###技術選定
webページの製作にはWordPressを利用することが多いと思いますが、私自身のReactの練習のためにもReactで製作させていただきました。SPAのUXはとても魅力的ですが、標準的なwebページをSPAで実装するのはかえって手間が増えるのでオススメしません笑。

バックサイドは全部Firebaseにお任せしています。コマンド一行で簡単に運営管理ができるのは気楽でいいですね。

###開発期間
全体で一ヶ月ぐらいかかりました。機能のコーディング自体はすぐにできるのですが、デザイン面が不慣れでしたので結構時間を食いました。CSSって意外にも奥が深いなと。おかげさまでFlexboxにはだいぶ精通しました。

#感想
いまどきのフロントエンドはほとんどデザインだと強く感じました。プログラマというよりはデザイナーですね。バックエンドもFirebase等簡単で便利なサービスがたくさんあるのでwebプログラマという職種はなくなるのではないでしょうか笑。

新しいサービスの黎明期に関わるのはとても楽しいです。私はUPLIFTの運営自体には関わっていないのですが、近い位置でサービスの創設と成長を見ることができるのでワクワクさせてもらっています。運営が友人ということもありますし、成功してbigになってほしいです。成功したらたんまり報酬もらうぞ

#今後の展開
将来的な運営を考えてもWordPressに移行させるのが吉です。一般的なwebページをReactで実装するという非常に非効率な作業をしました。WordPressの勉強をしないといけないですねー。このブログもいつかはWordPressに移行させたいです。

UPLIFTは現在事業拡大中です。大きめの投資を受けてぐんぐん成長させていけたらいいですね。皆さんに良いフィットネスサービスを提供できるように様々な面で努力していきたいと思います。

UPLIFTをよろしくお願いいたします。


※MEMO
この記事は[私のブログ](https://www.imagawahibana.com/"myblog")からの転載です。
[UE4]徐々に石化するシェーダーを作る+5色マスクとかおまけ

### 前書き
- この記事には筆者の性癖が含まれます。予めご了承ください。
- 当記事の中ではこういう概念をマスクと呼称しますが思いっきりfloat値です。
- 実装の垂れ流しなのでバッドプラクティスかもしれないです。

# 目次
- 徐々に変化する関数マスク
- 5色マスク
- おまけ:実装したUE4シェーダー

# 徐々に変化する関数マスク
様々なシチュエーションに対応するために今回複数の関数を用意しました。
1. 全体がフェード
2. まだら模様(ドラゴンズド○マ リスペクト)
3. 下から上がってくるやつ
4. その逆

1. 全体がフェードするやつはこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198123/72a08f39-d4cf-9841-05e1-0e1e3c15b124.png)

2. まだら模様はこんな感じです（意外と絵が微妙だったので修正したい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198123/e5590e9c-aec8-6140-4c6a-00861f35aa36.png)

3.下から上がってくるやつ（意外とry
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198123/a2dd1db0-d71d-497a-c9c4-642b3b4dedbf.png)


ノードと計算式は以下です。
斑に関してはやっぱりUVでやったほうが良いのでは・・・？と思ったりしなくはないです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198123/03a0d082-9a00-8732-f46f-307b8f3ef800.png)

``` c:mask.hlsl
//mask_gen
float outf=0.0f;
float s_mlt=4.0f;
switch(floor(num)){
case 0: outf=in_alpha;break;
//sin波5つを1~0にしてからpowをかけ0~-1にする
case 1:outf=pow((sin(5*s_mlt*local_.x+6)+sin(7*s_mlt*local_.y+1)+sin(13*s_mlt*local_.z+13)
+sin(11*s_mlt*atan2(local_.z,local_.x)*length(float2(local_.z,local_.x))+3)
+sin(17*s_mlt*atan2(local_.z,local_.y)*length(float2(local_.z,local_.y))+23))/10+0.5,3)
+in_alpha*2-1;break;
//localzとの組み合わせでせり上がるとこ+うねうね
case 2:outf=pow(in_alpha*1.02+(1-local_.z)+sin((atan2(local_.y,local_.x))*90)/50,20);break;
case 3:outf=pow(in_alpha*1.02+local_.z+sin((atan2(local_.y,local_.x))*90)/50,20);break;
}
return outf;
```

# 5色マスク
カスタマイズゲー用に5箇所の塗り分けが可能なマスク
RGBA1枚で実装できる（多分）最大色数

#### 挙動
色A,B,C,D,Eがあるとき、
- (0,0,0,0)→色A100%
- (1,0,0,0)→色B100%
- (0,0.5,0,0)→色A50%,色C50%
- (0.7,0.3,0,0)→色B70%,色C30%
- (7,3,0,0)→色B70%,色C30%

#### 計算式
重A=clamp(1-(R+G+B+A),1,0);
重(B,C,D,E)=(R,G,B,A)/clamp(R+G+B+A,999,1);
出力色=色A*重A+色B*重B+...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198123/9d25f053-b36f-0dbd-a4b4-ace1fd66371b.png)

# おまけ:実装したUE4シェーダー
https://qiita.com/vak/items/ced4811350b438104f7d の内容を含みます

4層構造になっております
A層:シェーダーの要件ごとにベース色、パラメーターを準備(この組をマテリアルと呼ぶ)（今回の場合は5色マスクがベース色に）
B層:状態異常番号とベースカラーを受け取り状態異常時のマテリアルを出力
C層:A層とB層を当記事のマスクでマテリアル合成
D層:C層で合成されたマテリアルから色を出力

パラメーターはベース色、アンビエント反映度、スフィアマップ、キューブマップ反映度の4点

### 問題点
UE4のマテリアル関数機能ではサンプラーを出力できない
そのためスフィアマップの計算はモデルに適用するマテリアルであるA層で行う必要がある

上記をまとめたものが以下になります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198123/0d118911-df00-5f30-af40-6311869162cc.png)

## 実装サンプル

https://twitter.com/vak_DJregion/status/1195453585904943104
steamでプレイできるのでよろしくね（ダイマ2）
Gitリポジトリのバックアップとリストア

# 概要
　Git リポジトリの保存と復元方法をメモしたものです。[^1]

# 手順
## バックアップ
```sh
# バックアップをカレントディレクトリ上にデフォルトのフォルダ名で配置する場合
# (下記の場合は repo.git フォルダとして配置される)
git clone --mirror "git@github/path/to/repo/repo.git"

# バックアップを任意のパスに配置する場合
git clone --mirror "git@github/path/to/repo/repo.git" "/path/to/other_name.git"
```
Git Documentation:  [ [git clone](https://git-scm.com/docs/git-clone) ]

## リストア
※リモート側にリポジトリが存在しない場合はリポジトリを作成してから下記を実行する。
※バックアップデータ中のリモートリポジトリの指定を確認する場合は `git remote -v` を実行する。

```sh
# リモートリポジトリがバックアップと同じ場所の場合
cd "/path/to/repo.git"
git push origin

# リモートリポジトリがバックアップと異なる場所の場合
cd "/path/to/repo.git"
git remote rm origin
git remote add --mirror=push origin "git@path.to.repo"
git push origin
```
Git Documentation:  [ [git remote](https://git-scm.com/docs/git-remote), [git push](https://git-scm.com/docs/git-push) ]

## バックアップからローカルへの clone
```sh
# カレントディレクトリ上にデフォルトの名前で配置する場合(下記の場合は /path/to/repo フォルダとして配置される)
git clone "/path/to/repo.git"

# 任意のパスで配置する場合
git clone "/path/to/repo.git" "/path/to/other_name"
```
Git Documentation:  [ [git clone](https://git-scm.com/docs/git-clone) ]

# トラブルシューティング
## 'fatal: remote origin already exists' と表示される場合
```
$ git remote add --mirror=push origin "git@path.to.repo"
fatal: remote origin already exists.
```
既に origin が指定されています。`git remote rm origin` で削除してから実行します。

## 'ERROR: Repository not found' と表示される場合
```
$ git push origin
ERROR: Repository not found.
fatal: Could not read from remote repository.
```
リモート側にリポジトリが存在しないので、リポジトリを作成してから実行します。

## バックアップデータ中のリモートリポジトリ指定を確認したい場合
バックアップデータ(repo.gitフォルダ)内部にて `git remote -v` を実行します。

```
$ git remote -v
origin  git@github.com:youracount/repo.git (fetch)
origin  git@github.com:youracount/repo.git (push)
```

[^1]: GitHub と BitBucket の repository にて backup, restore, transfer(BitBucketで backup して GitHub に restore) を実施しました。
Netlifyでブランチごとにサブドメインでサイトを公開する

<img width="2048" alt="スクリーンショット 2019-12-07 1.49.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386550/40f4ff19-da66-206a-5ee7-34881a637aa1.png">
# 設定するだけ

<img width="2048" alt="スクリーンショット 2019-12-07 1.43.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386550/0e73262c-e16d-dde5-abb0-00615f7913e0.png">

**Build&Deploy**
-> **Deploy contexts**

ここでBranch Deploysの設定をお好みに。

そのあと
**Overview**
->**Domain settings**

でブランチごとにサブドメインの設定をする。

こんな感じ。

基本的にリモートブランチへpushされれば、そのブランチがサブドメインとして勝手に登録される。


# まとめ
いつもやり方を忘れるッ
日本の祝日を判定するPowerShellを書いた件

Advent Calendar 初参加です。
Calendar にかけて、前回書いた記事「[日本の祝日を判定するBashスクリプトを書いた件](https://qiita.com/mindwood/items/d22689d3da61034751bd)」を PowerShell で焼き直してみました。

# 日本の祝日情報をどこから貰うか
Bash版同様、内閣府のホームページから持ってきます。
`Invoke-WebRequest`が`curl`に相当するコマンドレットですが、PowerShellの入出力はすべて **.NET** のクラスオブジェクトなので、画面で確認するなら次のようになります。

```powershell:取得方法
(Invoke-WebRequest https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv).Content
```

```:実行結果
国民の祝日・休日月日,国民の祝日・休日名称
1955/1/1,元日
1955/1/15,成人の日
1955/3/21,春分の日
1955/4/29,天皇誕生日
     :
2020/7/24,スポーツの日
2020/8/10,山の日
2020/9/21,敬老の日
2020/9/22,秋分の日
2020/11/3,文化の日
2020/11/23,勤労感謝の日
```

# PowerShellスクリプト
仕様はBash版を踏襲しています。つまり、祝日ファイルをローカルにキャッシュし、古くなったら内閣府のサーバから取り直します。
確実に祝日と言える場合のみ、終了ステータスに 0 がセットされる点も同様です。
Bash版と比べてみると、言語の特徴が見えて面白いかもしれません。

```powershell:check_holiday.ps1
###############################################################
#   本邦休日判定スクリプト
#   @author  MindWood
#   @param   チェック日付を yyyymmdd で指定。省略すると今日を仮定
#   @return  0       ... 確実に祝日
#            1       ... おそらく平日
#            上記以外 ... エラー
###############################################################

# 引数チェック
Param($DateStr = (Get-Date).ToString('yyyyMMdd'))
try {
    $CheckDate = [DateTime]::ParseExact($DateStr, 'yyyyMMdd', $null)
} catch {
    echo 'Invalid argument'
    exit 255
}
$CachePath = 'C:\tmp'                             # 内閣府提供の祝日ファイルをキャッシュするディレクトリ
$HolidayFile = Join-Path $CachePath holiday.csv   # 祝日登録ファイル名
$Limit = (Get-Date).AddMonths(-3)                 # ３ヶ月以上前は古い祝日登録ファイルとする

# 祝日登録ファイルが無い、もしくは祝日登録ファイルの更新日が古くなった場合、再取得する
if (! (Test-Path $HolidayFile) -or $Limit -gt (Get-ItemProperty $HolidayFile).LastWriteTime) {
    try {
        Invoke-WebRequest https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv -OutFile $HolidayFile
    } catch {
        echo $_.Exception.Message
        exit 250
    }
}

# 祝日として登録されていれば 0 を返却して終了（※祝日情報はyyyy/M/d形式で返る）
if (Select-String -Quiet ((Get-Date $CheckDate).ToString('yyyy/M/d') + ',') $HolidayFile) {
    exit 0
}

# 土日なら 0 を返却して終了
$DayOfWeek = (Get-Date $CheckDate).DayOfWeek
if ($DayOfWeek -in @('Saturday', 'Sunday')) {
    exit 0
}

# 年末年始（12月31日～1月3日）なら 0 を返却して終了
$MMDD = (Get-Date $CheckDate).ToString('MMdd')
if ($MMDD -eq '1231' -or $MMDD -le '0103') {
    exit 0
} 

# 上記いずれでもなければ平日として終了
exit 1
```

このスクリプトで、2019年12月26日から2020年1月16日までの平日を表示させると、次のようになります。

```
for ($date = '20191226'; $date -lt '20200116'; $date = [DateTime]::ParseExact($date, 'yyyyMMdd', $null).AddDays(1).ToString('yyyyMMdd')) {
    .\check_holiday.ps1 $date
    if (! $?) {
        echo "$date は恐らく平日です"
    }
}
20191226 は恐らく平日です
20191227 は恐らく平日です
20191230 は恐らく平日です
20200106 は恐らく平日です
20200107 は恐らく平日です
20200108 は恐らく平日です
20200109 は恐らく平日です
20200110 は恐らく平日です
20200114 は恐らく平日です
20200115 は恐らく平日です
```

なお、PowerShellでも `$?` で直前のコマンド終了ステータスを取得できますが、成功したか（0：True）失敗したか（0以外：False）のブール値で返るので注意が必要。失敗した理由まで知るには`$LastExitCode`を評価すると良いです。

平日に必ず実行させるジョブがある場合、Falseかどうかだけ見れば良いことになります。
pythonでlistをDataFrameに変換する


よく忘れるのでメモ

```python
import pandas as pd

# list
files=['a.txt', 'b.jpg', 'c.cvs', 'd.xls']

print(type(files))

# データフレームに変換
files_df = pd.DataFrame({'files':files})
print(files_df)
print(type(files_df))
```
結果

```bash
<class 'list'>
   files
0  a.txt
1  b.jpg
2  c.cvs
3  d.xls
<class 'pandas.core.frame.DataFrame'>
```
ライフゲームでQRコードつくる

# ライフゲームとは

>ライフゲーム (Conway's Game of Life) は1970年にイギリスの数学者ジョン・ホートン・コンウェイ (John Horton Conway) が考案した生命の誕生、進化、淘汰などのプロセスを簡易的なモデルで再現したシミュレーションゲームである。
(wikipediaより抜粋）

</br>
</br>
つまり、
</br>
こんなことや
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/f3627a98-fbdf-77de-77ee-06da821d83c8.gif">
</br>
こんなことが楽しめます
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/50e794c7-f007-2595-73d3-5b31f7989686.gif">
</br>
(かわいい、、、）

</br>
</br>
# QRコード生成
この形、なにか見覚えありません？
</br>
そう
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/8da7a7ce-20f4-c1cc-ef3e-24b5587e170e.png">※ソースコードに飛びます
</br>
</br>
</br>
なので、つくってみました　→
</br>
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/a44ddf28-fe9d-7716-514f-a4e5d1e3f84c.png">
</br>
</br>
この中には、自由にセルを描くことができるようになってるので、
</br>
こう　→
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/4357e522-6e4f-c580-4731-29d593e3faf1.gif">
</br>
うーむ、、、
</br>
ならば、もっとフレームレート下げて初期値をランダムに、
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/d2b9d031-40e5-ad83-76a3-87dba3508fbe.gif">
</br>
くっそー
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/d9381600-d49a-eed7-3fc5-3e42f103a6a6.gif">
</br>
だめだー
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/e1464810-d273-0114-431e-7ea51b190f77.gif">
</br>
</br>
</br>
</br>
</br>
</br>
</br>
、、、
</br>
</br>
</br>
</br>
</br>
</br>
</br>
ランダムだけでいいそうです
</br>
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318834/d8c299fc-9238-4722-64b1-fce78ac97568.gif">
</br>
</br>
</br>
# おわりに
先月よりプログラミングを始めました。
拙い点が多いかと思います。
なにか誤り等ございましたらぜひご連絡くださいm(_ _)m
</br>

* Twitter　→　https://twitter.com/sakio1535
</br>

プログラミング同志、ほしい、、、

# 参考資料
* [ライフゲームの世界１【複雑系】](https://www.nicovideo.jp/watch/sm19347846)
* [あなたの知らないライフゲームの宇宙 《前編》
](https://note.com/falworks/n/n4971b87a3bf7)
* [Coding Challenge #85: The Game of Life](https://www.youtube.com/watch?v=FWSR_7kZuYg)
Google スプレッドシートで英語論文を翻訳しながら読む

# サマリ
英語論文を日本語に翻訳しつつ Google Spreadsheet 上で管理する方法。
論文PDFからコピペした英語を translate関数で翻訳する。 ただし、そのままだと
うまく動かないので regexreplace で改行削除している。

# 画面
![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102621/ea530904-3be8-e59a-4cd5-865ba887a0cc.jpeg)

# Spread Sheet の中身

|| A       |   B    |    C    |
|--:|:-----------------|:------------------:|:------------------:|
|1|        |     原文  |  訳      |
|2| Title |    ## 英語タイトルの内容コピペ ##   |      =translate(regexreplace(B2,"\n|\r|\r\n"," "),"en","ja")       |
|3| abstract | ## abstractの内容コピペ ##   |  =A3&char(10)&translate(regexreplace(regexreplace(B3,"\n"," "),"\. ","."&char(10)),"en","ja")  |
|4| ## 1章のタイトルコピペ ##| ## 1章の内容コピペ ##   |  =A4&char(10)&translate(regexreplace(regexreplace(B4,"\n"," "),"\. ","."&char(10)),"en","ja")  |

# その他
- なお、IEEE Xplore に掲載されている論文は Web ページの中で論文が読めるので、
ページごとGoogle翻訳するのが一番簡単。
- ACM や arXiv の論文は上記方法で読むのが簡単。
- Spreadsheet 上では読みにくいので C 列(日本語訳)をテキストエディタ等にコピペしてから読むのが吉。
- タブで分けることで複数の論文を一つのSpreadsheetで管理できる。
凄いということはなんとなくわかるけど　全くまだ理解が追い付かない人がdenoを見た場合

遅刻組です。申し訳ありません。
この記事は　[deno  Advent Calendar 2019](https://qiita.com/advent-calendar/2019/deno)　の　6日目です。

このCalenderは denoも　node.jsも一ミリも理解できていない人が
denoを始めた日記です

([第6回deno勉強会に参加しました](https://deno-ja.connpass.com/event/151243/))＠メルカリ

[Denobook 02 【電子版】](https://booth.pm/ja/items/1574063)
を購入して
チュートリアルを実施しました。

```
第2章 Denoで簡単!コマンドラインツール作成 (著: syumai)
 Denoで実用的なコマンドラインツールを作ってみたい方向けの解説を行います。
```

【10/20のoutput】
helloworld　プログラムを作りました。
https://github.com/yamuun/hellodeno

```
第3章 Deno de Bundler 著: keroxp 
JSのモジュールの歴史を紐解き、DenoJSバンドラーの仕組みを解説します。
```


**denoのHP**
https://deno.land/std/


**インストール方法はこちら**
https://github.com/denoland/deno/blob/master/std/manual.md


**Deno実行環境とは何なのか** 
TypeScript を V8 で実行するためのランタイム


**denoの構造**
Typescriptのフロントエンド　（サンドボックス環境のV8エンジン上で実行）
C++のミドルエンド（フロントとバックエンドをつなぐレイヤー　C++製のV8エンジンとやり取りする）
Rust のバックエンド　（ファイルシステム　ネットワーク　環境にアクセスできる）

バックエンドは　go からrustに変わったらしい
https://github.com/denoland/deno/issues/205

rustってGCないらしいけどどうやってメモリの管理してるんだ・・（不勉強）

**Denoが何を解決するのか**
・ Secure Model
・ モジュールシステムのシンプル化
・ カオスなパッケージマネージャーからの脱却
（一例）

制作のoutputがただのハローワールドだけなのですが

denoの3層構造はとても気になりました。
node.jsとの比較をして勉強していきたいと思います。


自分はまだ　**わからないところがわかった** レベルなのですが
ossの序盤立ち上がりを生で見ているいい機会なのでウォッチしていきます。

[Denobook 02 【電子版】](https://booth.pm/ja/items/1574063)
は5章含めて、denoについて詳しい内容が書かれており
AdventCalenderに上記のAuthorが複数名いらっしゃるので
最後まで楽しみにしてます。
vue-facebook-login-componentを使ってみた

## 概要
Nuxt.jsで作成しているサイトにFacebookのログインボタンを配置したいと思って、facebook for developersにある[SDK](https://developers.facebook.com/docs/facebook-login/web?locale=ja_JP)を使おうとしたのですが中々うまく動かせませんでした。。ただ、Vue用に「vue-facebook-login-component」なるものがあり、今回使ってみましたのでメモを残しておきます。

## 事前準備
[Facebookデベロッパーの登録方法を画面入りで解説2019年版](https://wpxaf.com/facebook-developer/)を参考にデベロッパーの登録をします。登録後、Facebook App IDを取得します。

## vue-facebook-login-componentのドキュメント
[VUE FACEBOOK LOGIN](https://adi518.github.io/vue-facebook-login-component/#/?ref=madewithvuejs.com)にあります。

## サンプルソース
今回はFacebookにログイン後、ID・名前・アイコン画像・メールアドレスを取得するサンプルを作成しました。

```FacebookAuthComponent.vue
<template>
  <div>
    <v-facebook-login
      app-id="Facebook App IDを入力"
      version="v5.0"
      :login-options="scope"
      @sdk-init="setSdk"
      @connect="connected"
      @logout="onLogout"
    >
      <span slot="login">Facebookで登録</span>
      <span slot="logout">Facebookからログアウト</span>
    </v-facebook-login>
  </div>
</template>
<script>
import VFacebookLogin from "vue-facebook-login-component";

export default {
  components: {
    VFacebookLogin
  },
  data() {
    return {
      sdkFB: undefined,
      scope: { scope: "public_profile, email" },
      isFacebookAuth: false,
      facebookInfo: undefined
    };
  },
  methods: {
    // sdkの読み込み完了
    setSdk(sdk) {
      this.sdkFB = sdk.FB;
    },
    // 認証が完了したらconnectedが呼ばれる
    connected() {
      this.isFacebookAuth = true;
      // id、名前、写真、メールアドレスを取得
      this.sdkFB.api(
        "/me?fields=id,name,picture,email",
        function(response) {
          // 取得したデータを設定
          this.facebookInfo = {
            id: response.id,
            name: response.name,
            email: response.email,
            pictureUrl: response.picture.data.url
          };
        }.bind(this)
      );
    },
    // ログアウト時は認証フラグをfalse
    onLogout(response) {
      this.isFacebookAuth = false;
    }
  }
};
</script>
```

## ボタンのイメージ
####【ログイン前】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/1dcd5030-53d6-f947-9ca8-28aa6b8539ad.png)
####【認証中】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/0f9ed4c8-e231-b5e7-b46c-46ccb705ed92.png)
####【ログイン後】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/1206e70a-3c6a-7869-48e6-6c330bf9e863.png)
Illustratorでオブジェクトの面積を計算するスクリプト

イラレでオブジェクトの面積を求めようとしたら地味に面倒だったのでスクリプトを作りました。

#概要
面積を測りたいオブジェクトを選択した状態で実行すると、新規テキストを作成して計算結果を表示します。

#注意
- 小数点を丸めているので厳密な計算には使えません。あくまでも目安ということで。
- 複雑なパスの場合、事前にパスの単純化をかけてから実行したほうが良いかもです。
- モニタの解像度によって計算結果が異なるかもなので、単純な四角形などで計算結果を確認してから使用してください。


```javascript:area.jsx
var area = app.selection[0].area; // 選択中のオブジェクトの面積（単位がpt）を取得
var absolute = Math.abs(area); // 負の数字を引っ張ってくる場合があるので、絶対値を取得して正の数に統一
var convert = Math.ceil(absolute * 0.12445216049); // 小数点を切り上げしてptからメートル法に変換
var result = (convert * 0.01 +'㎠');

if (isNaN(area)) {
    alert ("計算できませんでした。単体のオブジェクトを選択して再度実行してください。（グループ化されたものは計算できません）");
    }

else {
    var x = app.activeDocument.selection[0].position[0];
    var y = app.activeDocument.selection[0].position[1]; // 選択中のオブジェクトのXY座標を取得
    docObj = activeDocument;
    textObj = docObj.textFrames.add(); 
    textObj.contents = (result); //テキストフレームにresultを書き込み
    textObj.translate(x,y); //テキストを選択中のオブジェクトのすぐ上に移動
    }
```

#参考
オブジェクトの座標取得
https://stackoverflow.com/questions/4840595/how-do-i-get-the-position-of-the-selected-illustrator-pathitem-in-pixels-using

Illustrator CS自動化作戦
http://www.openspc2.org/book/IllustratorCS/

ILLUSTRATOR SCRIPTING
https://www.adobe.com/devnet/illustrator/scripting.html
mutable, immutableにもやもやしている人が本記事を読むと理解が深まるかもしれない

# Python の mutable immutableって？
Pythonオブジェクトが持っている性質のことです。

例えば、
リスト型はmutable、数値型はimmutable。

---

# Question: なんでそんなこと知らないとダメなん？
# Ans: いや、これを抑えとかないとバグで苦しむことになるんだ。

---

# 具体的には...
関数内で変数を変更したらもとの変数の値までかわちゃった！　なんてことが起ります。

だから、抑えておこう。

---

# まずは大雑把に解説

---

# mutableとは

macの辞書で検索すると...
「変わりやすい」、「移り気の」って出てきます。

mutableなオブジェクトとは、**変更可能**なオブジェクトをさす言葉です。

---

# mutableなオブジェクトの例
リスト型、辞書型、クラスなど。

リスト型はmutable

```lists_is_mutable.py
numbers = [1,2,3,4]
numbers.append(5)
print( "numbers = ", numbers )
# 出力結果 >> numbers =  [1, 2, 3, 4, 5]
```

---

辞書型はmutable

```ditc_is_mutable.py
pokemon = {
    "ピカチュウ": "電気",
    "イーブイ": "ノーマル",
    "コイキング": "ドラゴン"
}
pokemon.pop("コイキング")
# 出力結果 >> pokemon =  {'ピカチュウ': '電気', 'イーブイ': 'ノーマル'}
```

---

# immutableとは
「im」がmuttableの頭について、意味が反転します。「不変の〜」、だとか、「変わらない〜」という意味を持ちます。

immutableなオブジェクトとは、**変更不可能**なオブジェクトをさす言葉です。

例として、int、float、などの数値型、文字列型や、tuple型などが挙げられます。

--- 

# 数値型ってことは......ちょっと待ってよ!

---

### 代入は変更に当たるんじゃないの？

```change.py
a = 10 # aに値を代入している
a = 5  # 10が入っている a に、5を代入。
```

変数 a の値は10に変化した！　→　変更しているのでは？

---

### 代入は変更には当たりません
代入がオブジェクトの変更に当たらないのは、`10`というオブジェクトの**実態**が変化していないからです。

---

### それってどういうこと？
Pythonでは、identityと呼ばれる番号でオブジェクトにアクセスするようになっています。 　

代入で行われるのはidentityの書き換え。
つまり、オブジェクトの実態を変更していることにはなりません。

よって、代入はオブジェクトの変更には当たりません。

---

### 組み込み関数である`id()`でidentityで確認してみよう

```.py
a = 10
print( "id(a) = ", id(a) )
print( "id(10) = ", id(10) )

a = 5
print( "id(a) = ", id(a) )
print( "id(10) = ", id(10) )
```

```
# 実行結果
# id(a) =  4512497008
# id(10) =  4512497008
# id(a) =  4512496848
# id(10) =  4512497008
```

実態のオブジェクトである10は、変数aに5を代入しても変わりません。
→　つまり、代入はオブジェクトの変更には当たりません。
→　**代入は参照先の変更でしかないのです**。

---

# 小まとめ
Pythonでいうmutable、immutableとは、**オブジェクトの実態が変化するか、しないかということで決まります**！

---

# 複雑な例で考えてみよう
以下の二つは、それぞれ、mutableでしょうか、それともimmutableでしょうか。

```problem.py
complex_a = (1,2,3,[4,5])
complex_b = [1,2,3,(4,5)]
```

---

# complex_aはimmutable

`complex_a = (1,2,3,[4,5])`

一番外側の要素がtupleなので、この変数はimmutableです(簡単な見分け方)。
`complex_a[3].pop()`などで操作はできます。が、リストの存在そのものを削除することはできません(tupleの機能でエラーとなります)。

complex_aのidentityが示す１や２、リスト[4,5]のidentityはtupleによって消えたり増えたりするしないことが保証されるので、complex_aはimmutableなのです。

---

# complex_bはmutable

`complex_b = [1,2,3,(4,5)]`

一番外側がリストなので、mutableとなります。

`complex_b.pop()`などをしてやると、中に要素として入っている`(4,5)`自体が削除されます。すると、四つあったidentity番号が三つになります。

こんな風に、complex_bが保持していた直近のオブジェクトのidentityが消えたり増えたりするので、complex_bはmutableです。

---

# 最終まとめ

**mutable、immutableは、一回のみの参照でたどり着けるオブジェクトのidentityが変化するか、変化しないかを表したもの**

と言い換えできるのではではないでしょうか。
[UE4]プレビューメッシュで素早くライティングを確認する

エディタの環境設定にプレビューメッシュというものがあります。
こちらにメッシュを登録することでレベルエディタから素早くメッシュを画面に表示してライティングなどを確認することができます。
デフォルトではカラーキャリブレーターメッシュが登録されています。

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/bd9b7610-16d9-82fc-3e9a-9850d5c5b308.png">


#使ってみよう
使い方は簡単です！
レベルエディタのビューポートにフォーカスがあっている状態で `\` (バックスラッシュ) を押すだけ！
これで押している間カーソル位置にメッシュを表示してくれます。

![PreviewMesh1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/7a2055be-264c-64ed-c306-69d6c41dc5a2.gif)


VolumetricLightMap(VLM)やリフレクションキャプチャーの確認に大活躍です。
**しかもレベルに配置するわけではないのでレベルは汚れません！(重要)**
<font color="lightgray">つい先日までオレオレカラーキャリブレーターをD&Dしてレベルを汚してました</font>


##お好みのメッシュを適用
実はプレビューメッシュは配列であることにお気づきでしょうか？
<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/84e29745-ef01-d367-a0d3-64436c6b700d.png">

プレビューメッシュは複数登録をすることが可能です。
これをどうやって呼び出すかというと
Shiftを押しながら `\` (バックスラッシュ) です！


![PreviewMesh2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/01266f1a-dc77-d0e2-7aeb-190e64292f1a.gif)

#まとめ

タイトル毎のプレイヤーキャラクターや特殊なマテリアルを持ったキャラクターをStaticMesh化して登録しておくとライティングの確認が楽になりそうですね！
AWS re:Invent2019でSecurity Jamに参加してきた

本記事は、[サムザップ Advent Calendar 2019 #2](https://qiita.com/advent-calendar/2019/sumzap2) の12/6の記事です。

AWS re:Invent2019でSecutiry Jamというイベントに参加してきたので紹介します。

## Security Jamとは

<img width="1017" alt="screenshot 2019-12-05 16.44.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540150/bb81acef-6c2c-131e-3a9a-b083638c2fdb.png">


会場で同じテーブルになったイベント参加者４名でチームを組み、
AWS環境上にシミュレートされた復数の問題（セキュリティインシデント）を、
AWSマネジメントコンソールを操作しながら解決していく体験型のイベントです。
問題を解決するごとポイントが付与され、制限時間の4時間が経過した時点のポイント合計で各チームが順位を競います。

###  内容

<img width="1082" alt="screenshot 2019-12-05 12.07.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540150/898abb33-1a6d-5fbd-1d22-78c7b14b1e2f.png">

Security Jamのダッシュボード。
イベント開始までは画像のようにロックされた状態で、
開始と同時にロックが解除されてすべての問題が見られるようになります。

問題内容については詳しく書けませんが権限管理、自動化、ネットワークなど様々な領域の問題が出題され、セキュリティだけでなく、幅広いAWSサービスの知識やトラブルシューティング能力も求められます。

問題にはそれぞれEasy/Middle/Highの３種類の難易度が設定されていて、難易度の高い問題ほど解決時に得られるポイントも高くなります。また、各問題にはヒントがいくつか用意されていて好きなときに使えます。ただし、ヒントを使うと問題解決時に得られるポイントは減らされてしまいます。

### 結果と感想
私のチームは序盤こそ好調だったものの、中盤以降はスコアが伸びず、順位も全チームの中間くらいの平凡な結果に終わってしまいました。自力で問題を解くことに固執せずにヒントをうまく活用すべきだったと反省。

Security Jamは参加するかどうか直前まで迷っていたのですが、自分の現在の知識を確認する良い機会になりましたし、現地のエンジニアと技術で交流する貴重な経験ができたので参加して良かったです。


明日は、@norimatsu_yusuke さんの記事です。
ffmpegで2つのgifファイルを1つにまとめる（左右に配置）

# はじめに
- ffmpegを使って、2つのgifを1つにまとめる．
- この記事では一旦mp4の形式に変換してgifに戻すやり方をする．（gif⇒mp4⇒gif）
- 最終的にはgifの形式で出力する．
- ffmpegのインストールは[前の記事](https://qiita.com/Nahuel/items/dc7f8b0a628c4c68e7c3)で書いたのでそちらを参照

# 実行環境
今回試した環境は以下の通りです．
OS: Ubuntu 18.04 LTS
CPU: i3-4130 3.40GHz
メモリ: 16GB

# 1. gif⇒mp4＜変換＞
以下のコードでgifからmp4に変換することができます．

```
$ ffmpeg -i input.gif -pix_fmt yuv420p output.mp4
```

以下の2つは適宜変更してください．

- input.gif: 入力するgifファイル
- output.mp4: 出力されるmp4ファイル

# 2. 2つのmp4ファイルを左右に配置
以下のコードで2つのmp4ファイルを左右に配置して1つのmp4ファイルとして出力してくれます．

```
$ ffmpeg -i left.mp4 -i right.mp4 -filter_complex hstack output.mp4
```

以下の3つは適宜変更してください．

- left.mp4: 入力するmp4ファイル(こちらが左側になる)
- right.mp4: 入力するmp4ファイル(こちらが右側になる)
- output.mp4: 出力されるmp4ファイル

# 3. mp4⇒gif＜再変換＞
以下のコードでmp4からgifに変換することができます．
※-r：フレームレート（以下のコードでは10と設定）

```
$  ffmpeg -i input.mp4 -r 10 output.gif
```

以下の2つは適宜変更してください．

- input.mp4: 入力するmp4ファイル
- output.gif: 出力されるgifファイル


# まとめ

- ffmpegで2つのgifを1つにまとめた．
- だいたいffmpegで解決できるから本当に助かる．

# 参考文献
[GIF アニメーションを mp4 ファイルへ変換する](https://qz.tsugumi.org/convert_gif_to_mp4.html)
[【ffmpeg】 比較動画の作り方 ](https://looooooooop.blog.fc2.com/blog-entry-990.htm)
[FFmpegで動画をGIFに変換](https://qiita.com/wMETAw/items/fdb754022aec1da88e6e)
さくらサーバーで定期的なPythonスクレイピングをするためcron設定方法。

#はじめに
定期的にスクレイピングするにはcron設定をしなければならないらしく、検索すると古い記事であまりにも分かりにくかったので独自の方法を記載しました。

スクレイピングについては前回書いてますのでスクレイピングをしたい人は下のリンクからみてください
[https://qiita.com/kei_kei_kei/items/730ba09e7830d5c00a1c](https://qiita.com/kei_kei_kei/items/730ba09e7830d5c00a1c)



#では実際に設定しましょう
ターミナルを開き、さくらサーバーにログインします。

下記のコマンドを実行。

```
ssh アカウント名@初期ドメイン(xxx.sakura.ne.jp)
```
パスワードを聞かれるのでドメインIDを打つときに必要なパスワードを入力。
```%```が出てきたらログインできました。
![https___qiita-image-store.s3.amazonaws.com_0_154299_b9ec4b06-666d-51a7-3afe-fa0c3d5b728d.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492078/c03cbf1a-1b49-bc5a-9cd1-0a332ba0510d.jpeg)


##さくらサーバーのpythonのバージョンは古い
pythonのバージョンが古いのでバージョンあげようと皆必死になるのですが、めんどくさいのと
```path```も変えなきゃいけないのでさらにめんどくさいなのでそのままで。

##しかし！そのまま動かすとエラーが、
```
Traceback (most recent call last):
  File "train_mnist.py", line 4, in <module>
    import requests
ImportError: No module named requests
```

##ローカルはPython3。さくらはPython2。
ローカルで

```
pip install (外部モジュール名)
```
をしてインストールして動いたと思います。

さくらにも外部モジュールのインストールが必要。

##さくらのバージョン低くてpip使えません。
気づいた方はpipでインストールしようとすると思いますが、できないのです。

なので必要なモジュールは下記のようにインストールしてください

```
python -m install requests
```
今回は```requests```をインストールしましたが、
Beautiful Soupをインストールしたい方は下記のコマンド

```
python -m install beautifulsoup4
```
こんな感じで必要なモジュールをインストールしていきます。

今回使う外部モジュールをインストールできたらターミナルでの作業は終わり。

#さくらサーバーの設定をしていきます。


##契約中のさくらサーバーにログインします
![スクリーンショット 2019-12-07 0.26.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492078/717ff519-82e8-6d28-504c-d9edd483c7f0.png)

###アプリケーション設定にある⓵のcron設定のリンクをクリックします
![スクリーンショット 2019-12-07 0.27.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492078/5c4d482b-810b-57c4-fd21-a7b08525b54f.png)

⓵を押すと⓶の新規項目の追加リンクが出てくる画面に進みます。
そのまま⓶の新規項目追加を押します。

###cronをどのくらいの頻度動かすのか設定していきます。
![スクリーンショット 2019-12-07 0.31.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492078/9c87aeb3-fabb-527b-94e7-6e1ac0f8f6d1.png)

⓵には
```cd /home/自分のアカウント名/www/ファイルのあるディレクトリ;＜半角スペース＞/usr/local/bin/python＜半角スペース＞対象ファイル.py```

⓶には
説明にある通り何ヶ月の何日の何時、何分毎に動かしたいのか記述します。
画像では2分おきに実行させています。

入力し終わったら⓷の送信ボタンをクリック



###送信を押すとcron設定画面に戻るので環境変数を設定
![スクリーンショット 2019-12-07 0.43.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492078/62a9568d-dd0a-1387-5c43-a51c0b31ea65.png)
ここには

環境変数設定：```PYTHONPATH```
環境変数の値：```home/アカウント名/lib/python```

上記を入力して追加をクリック

###登録完了！！

#実際に動いてるか確認しましょう。
さくらのcron設定で```1> /dev/null```を入力していない方にはメールが届きます。
メールにはエラーがある場合はエラー文が書いてあるので確認。
もし、エラーが出ていればエラー通りに解決していきます。

#最後に要確認
さくらのPythonのデフォルトエンコーディングはasciiです。
なので、日本語を出したい方はデフォルトを変更してください。
デフォルトエンコーディングを確認したい方は最初に戻りさくらをターミナルを開きます。
ログインして```python```と打ち込み下記のコマンドを実行してください。

```
% python


>>>import sys
>>>print sys.getdefaultencoding()

```
デフォルトエンコーディングが確認できます。
今回作成したのはInt型だけが必要だったので変更せずにすみましたが、必要なかたはトライしてみてください。


##cron設定で作ったサイトはこちら
[完成サイト：https://compadre.matrix.jp/aisekiya/](https://compadre.matrix.jp/aisekiya/)
![スクリーンショット 2019-12-05 16.19.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492078/9a5bbedf-d217-c6d2-9311-099d82154a6c.png)
【Rails】ES6が原因でHerokuへのデプロイ失敗 Uglifier::Error: Unexpected token:~

## はじめに
RailsアプリのHerokuへのデプロイにおける`Uglifier::Error: Unexpected token:~`というエラーに対する解決方法を記載します。

## 環境
- macOS Catalina 10.15.1
- zsh: 5.7.1
- Ruby: 2.6.5
- Rails: 5.2.4 
- Docker: 19.03.5
- docker-compose: 1.24.1

## エラー内容
```ruby
 Uglifier::Error: Unexpected token: name (任意の内容). To use ES6 syntax, harmony mode must be enabled with Uglifier.new(:harmony => true).
```
「ES6を使うには`Uglifier.new(:harmony => true)`で`harmony mode`を有効にしてね」とのこと。

**Uglifier**はJavaScriptの圧縮をしてくれるgem。ただES5までしか対応していません。

## 解決策
エラーメッセージの言う通り、本番環境の設定ファイルを編集します。

```ruby:config/environments/production.rb
config.assets.js_compressor = :uglifier
```

↓

```ruby:config/environments/production.rb
config.assets.js_compressor = Uglifier.new(harmony: true)
```

これで無事本番環境へのデプロイが出来るようになりました！

## 発生のきっかけ
これまで自分のRailsアプリ内のJavaScriptではずっと`var`を使っていたのですが、それを`let`(ES6から対応)に変更してみたことで発生しました。

**development環境**では**Uglifier**を使わないため上記エラーは発生せず。
**Chrome**がES6に対応しているので特に問題にならなかったようです。

## ※余談
[uglifierの公式README](https://github.com/lautis/uglifier)にこんなことが書いてありました。

> More stable alternatives for working with ES6 code is to first transpile to ES5 with e.g. babel-transpiler or using Closure Compiler to directly minify ES6 code.

「ES6をより安定して使うには`babel-transpiler`もしくは`Closure Compiler`を使ってES5をトランスパイルすることです。」
とのこと。

後日、下記gemを使って試してみようと思います。
↓
[GitHub - babel/ruby-babel-transpiler: Ruby Babel is a bridge to the JS Babel transpiler.](https://github.com/babel/ruby-babel-transpiler)


## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [Uglifier::Error: Unexpected token: punc ((). To use ES6 syntax, harmony mode must be enabled with Uglifier.new(:harmony => true) · Issue #127 · lautis/uglifier · GitHub](https://github.com/lautis/uglifier/issues/127)
- [GitHub - lautis/uglifier: Ruby wrapper for UglifyJS JavaScript compressor.](https://github.com/lautis/uglifier)
Unityのゲームビューとシーンビューを取り違えたことに気づいたときのミスを取り戻す方法

シーンビューだと思っていじっていたらゲームビューで、いじっていたものすべてパー・・・・というミスをやったんですが、
回避する方法あります？という質問をTechAcademyのメンターさんにぶつけた。



ゲームビューのときにシーンビューだと思って

- インスペクタで設定値を変更してしまったケース  
→エディタ拡張により、ゲームビューで変更した値を外部ファイルに書き出すことでミスを取り戻すことができそう・・・らしい。
https://www.f-sp.com/entry/2016/08/25/194719
- オブジェクトを追加してしまったケース  
→こちらもエディタ拡張により救えるかもしれないが、そもそもゲームビューでの操作は一時的にオブジェクトを追加してみるということが可能ということでもあるので、その利点を潰すことになりかねない。むずかしい。


結論としてぱっと解決できる方法はないみたい。
元も子もないが、単純に**うっかりミスをしない作業フローを考える**、**慣れる**のがよさげ。
【C++】GoogleChromeで指定のURLを開く方法 

#目的
AtCoderの過去問をランダムに開いて勉強できるようにしたい．
#方法
###1. C++を用いて指定のアプリケーションを開く
「C++ URL 開き方」などで検索をすると，ShellExecute関数というものがヒットした．
使い方をいくらか調べたが，Macでの使い方がうまくヒットしなかったため断念した．

```C++:ShellExcute.cpp
ShellExecute( hWnd, "open", "http://www.google.co.jp/", NULL, NULL, SW_SHOWNORMAL );
```
どうやら[ここ](https://tokibito.hatenablog.com/entry/20121020/1350676167)によると
>WindowsだとShellAPI.ShellExecuteを使えばいいんだけど、WindowsAPIなのでこれはMacOSXでは使えない。

らしい．そろそろAPIが何なのかしっかり理解する必要がありそう．

次に関連事項を検索しているとC++で別のプログラムを開く方法がヒットした．

```C++:System.cpp
int system( const char* command );
```

コマンドを書けばそれを実行してくれる関数だった．

###2. 指定のURLを開く方法

コマンドを実行するための関数が見つかったため，あとはコマンドでURLを開く方法を検索すれば良いことがわかった．

どうやら
`open -a '/Applications/Google Chrome.app' <URL>`
を実行すれば指定のURLを開けるようだ．

よって以下のように作成した．

```C++:RandomAtCoder.cpp
#include<iostream>
#include<string>

using namespace std;

// ランダム関数
int RandomNum(){
    return rand()%146+1;
}

int main(){
    srand((unsigned int)time(NULL));
    int problemNum = RandomNum();
    string com = "open -a '/Applications/Google Chrome.app' https://atcoder.jp/contests/abc";

    // 桁が違う場合文字数を合わせるURLだったためif文で分岐している(1→001や15→015など)
    if(problemNum<10){
        com = com + "00" + to_string(problemNum) + "/tasks";  
    }
    else if(problemNum<100){
        com = com + "0" + to_string(problemNum) + "/tasks";
    }
    else{
        com = com + to_string(problemNum) + "/tasks";      
    }
    // コンソールにコマンドを書き込む際，char型である必要があるのでstringから変換
    system(com.c_str());
    return 0;
}
```
#結論
本当は難易度の入力をさせてその難易度の問題をランダムに開くようにしたかったのだが，URLが定性的ではなかったので断念．
ABC問題どARC問題選べるプログラムも書いてみる．
yui.design - UIデザイナーのためのリファレンスサイトをFirebaseで作った話


###はじめに

この記事はSFC Advent Calendar 2019の7日目の記事です。

はじめましてエンジニアの@furuta_katsumiです。デザイナーの[レオ](https://twitter.com/ell_eo)と話す中で日本のアプリのリファレンスサービスがないよね、とのことでサービス開発を始めました。

[yui.design](https://yui.design)

<img width="1185" alt="スクリーンショット 2019-12-21 17.35.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69141/03ad6b80-5b16-8283-c6fe-66e2f7af2c92.png">


### サイトの実装構成

時間的問題と、開発する人間が現状自分一人だったこともあり

・Firebase
・React
・Typescript

の構成で開発を始めました。

##  Firebaseのメリットデメリット

とりあえずFirebaseとは？
今回使った物で感じたメリットデメリットを書いてきます。

### auth
基本的なログイン機能に加え、Authログイン等まで実装してくれるサービスです

・メリット
数行のコードでログイン実装できます。早い。

・デメリット
個人的な感覚ですが、認証リクエストが少し遅いです。1sかかる時があるくらい遅い時があります。

### storage

ファイルなどのストレージサービスです。
画像データ等を上げられます。

・メリット
Authと連携して権限管理できたり、それこそ数行のコードでデータを上げられます。

・デメリット
調べた限り別途CDNを挟むのは難しそうでした。
また体感的に遅いなと感じたので、バケットに直接アクセスするように書き換えてます。


### hosting
サービス自体を公開するホスティングサービアです

・メリット
コンソールアプリケーションもしっかりしていて、簡単にあげられます。使いやすい

・デメリット
特になし

### firestore
データを管理する、NoSQLなサービスです。

・メリット
スケーラビリティ。型がないのでゴリゴリ行ける。速度早い

・デメリット

RDBMSに慣れてるせいかN+1系の対処ができなかったり、検索系の実装が辛かったです。一応where関数のおかげで少しだけquery的なことはできますが、複雑なことはまだまだ難しそうです

### 料金

![90F3C7DE-DE47-425C-B26A-22502D06D40F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69141/b927715c-6efb-916d-b6ae-f9fbe0d6edbc.png)

価格設定が割とユーザーのユースケースに合わせているので、サービスが大きくなるまでは無料で試し、リミッターとして2500円回したりできます。

(個人的には少し高いけど、便利代だと思ってます)


細かい問題はまた別途記事にしたい。

##  StoryBookとAtomicDesign

![スクリーンショット 2019-12-21 17.39.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69141/8b0a66c3-9469-3138-bb2b-d24530540fe7.png)

デザイン系のサービスを作つにあたってデザイナーとの連携と、コンポーネントの区切りに注意して作成して見ました。



デザイナーがいつでもデザイン確認でき、文字を入れて見たり、変数を変更して見ることができます。

Atomic Designは、パーツを5段回に分けてコンポーネントのグループとして開発します。ただ今回は、悩みすぎると時間消費しすぎるので未来の自分に託して悩過ぎたら諦める方針なので、割とぐちゃぐちゃです。いつか公開したいですが、リファクタリング後ですね。

##  TypeScript

静的型って良いですよね。

JavaScriptだと乱暴に書いたコードが動くことがメリットでもありデメリットでもあるんですが...

都度仕様変更があった時に型がちゃんとしてるこで、エラー出てくれるので、実行しないと分からないエラーなど未然に防げます。

あと、過去に製作したものがNaNだらけになったことがあるのですが、その心配が減るだけでもtsは幸せです。



##  まとめ

日本のUIデザイナーがより、本当にユーザーに価値がある仕事に専念できるよう、気軽に検索したり、ナレッジをまとめていく予定です。ぜひ、一緒に開発に関わりたい人がいれば、ぜひコントリビューターになってください！