OmniAICreator/Qiita-1.07M huggingface dataset:
MathJaxで動的な変化を追加するにはTypesetを用いる

# onclickで数式を表示したい

以下で実現できる。

```javascript
    const math = document.getElementByID('math');
    btn.onclick = function() {
      math.textContent = '$x + 1$';
      MathJax.Hub.Typeset(math);
    }
```

`MathJax.Hub.Typeset`がないとただ

x + 1

と表示されるだけ。

`MathJax.Hub.Typeset`を記述すれば

$x + 1$

と表示される。

## 参考記事
https://ja.stackoverflow.com/questions/48544/%E6%95%B0%E5%BC%8F%E3%82%92javascript%E3%81%8B%E3%82%89%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%93%E3%81%A7html%E4%B8%8A%E3%81%AB%E8%A1%A8%E7%A4%BA%E3%81%95%E3%81%9B%E3%81%9F%E3%81%84mathmlmathjax
Vue.js学習記録3日目

20201231

# LocalStorageを使用したデータの保存



Vue.jsを使って一通りメソッドを実装し、画面の表示を変えることはできたがリロードするともとに戻ってしまう。これを解決するためにLocalStorgaeという仕組みを導入する。



LocalStorageをデータが変更されるたびに動かしたいのでwatchという仕組みを使う。jsのコードは以下の通り。

```js
watch: {
      todos: function() {
        localStorage.setItem('todos', JSON.stringify(this.todos));
        alert('Data saved')
      }
    },
```

これでtodosの中身が変更されたときにlocalStorageにtodosというキーで変数todosの中身をJSON形式で保存する。

JSON.stringify(this.todos)をコンソールで表示すると

```
[{"title":"task1","isDone":true},{"title":"task2","isDone":false},{"title":"task3","isDone":true}]
```

このように配列の中にハッシュが複数並んだ構造になっている。これをlocalStorageに保存する。setItemはlocalStorageが使えるメソッドでDBにデータを保存する。



ただしwatchでは配列の要素数の変化には反応するが、ハッシュの中身の変化には反応しない。よってdeep watcherという仕組みを使う。

監視したい変数をキーにとり、中にhandler(実際に動く処理)とdeepオプション(deep watcherにするかどうか)をつける。こうすることで配列の中のハッシュのキーバリューペアの変更にも反応する。

```js
watch: {
      todos:  {
        handler: function() {
          localStorage.setItem('todos', JSON.stringify(this.todos));
          alert('Data saved')
        },
        deep: true
      }
    },
```



ただしこれだけだとリロードするともとに戻ってしまうので、リロード時にlocalStorageからデータを引っ張る処理を加える。

```js
    mounted: function () {
      this.todos = JSON.parse(localStorage.getItem('todos')) || [];
    },
```

JSON.stringifyを使ってjsonを文字列に変換してlocalStorageに保存しているので逆にビューで使用するにはjson.parseしてjson形式に戻す必要がある。getItemはlocalStorageから値を取得する。



ここまでの動きをウェブ上で確認すると以下のようになる。なお、localStorageをブラウザ上で確認するには検証ツールのapplicationタブを使う。

https://gyazo.com/df05e83be746d7afa684cbf1956849e2
AmplifyをLambdaを使って動的に動かす

# Amplifyが動的に動かせると思っていた

Amplifyでは以下のようにpythonファイルを指定しても呼べなかった。

- 修正前

```html

    <script>
        var callAPI = (input)=>{
            var myHeaders = new Headers();
            console.log(input)
            myHeaders.append("Content-Type", "text/html");
            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: input,
                redirect: 'follow'
            };
            fetch("test.py", requestOptions)
            .then(response => response.text())
            .then(result => console.log('success', result))
            .catch(error => console.log('error', error));
        }
    </script>
</head>
<body>
    <form>
        <label>文字を入力してください</label>
        <input type="text" id="input">
        <button type="button" onclick="callAPI(document.getElementById('input').value)">入力</button>
    </form>
</body>
```


htmlから呼び出したいpythonファイルをLambdaにほぼコピペしたら実行したいpythonプログラムを実行できた。
動的にするにはただデプロイするだけでは足りないよう。

- 修正後

```html
<body>
    <form>
        <label for="inhput" class="cl1">文字を入力してください</label>
        <input type="text" id="input">
        <button type="button" onclick="callAPI(document.getElementById('input').value)">入力</button>
    </form>
    <script>
        var callAPI = (input)=>{
            var myHeaders = new Headers();
            myHeaders.append("Content-Type", "application/json");
            var raw = JSON.stringify({"input":input});
            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: raw,
                redirect: 'follow'
            };
            fetch("ここにAPI GatewayのURLを書く", requestOptions)
            .then(response => response.text())
            .then(result => alert(JSON.parse(result).body))
            .catch(error => console.log('error', error));
        }
    </script>
</body>
```


## 参考記事
- 公式チュートリアル  
https://aws.amazon.com/jp/getting-started/hands-on/build-web-app-s3-lambda-api-gateway-dynamodb/module-three/
ローカルスコープとグローバルスコープ

ローカルスコープとグローバルスコープの違いを理解し、
各変数を扱う場合の注意点を整理する。

#ローカルスコープとグローバルスコープとは？
ローカルスコープは定義された関数内を指し、その中で利用できる変数をローカル変数と言う。

```
def sample():
    a = 1 ※ローカルスコープ
```
グローバルスコープは対象のpythonファイル内を指しており、どの関数からでも参照が可能です。

```
b = 2 ※グローバルスコープ
def sample():
    a = 2
```

#グローバルスコープの扱い方
グローバルスコープはローカルスコープ内からでも扱える

```
local = 100
def global():
    a = 100
    print(local + a)
```
importの使い方

```opposite_ai.py
import math
# 反対向けのAI
class Oppai:
    #処理
    pass
```

```hent_ai.py
#つかむ動作のAI
class Hentai:
    #処理
    pass

```

```app.json.py
import hent_ai
from hent_ai import Hentai #Hentai()でインスタンス作成できる
import opposite_ai as oppai #oppaiでopposite_aiが使える。
import opposite_ai.math #oppai.mathと書かなくてよくなる。
try:
    setai=__import__("set_ai")#詳細設定。有無が

except Exception as e:
    print(e)

class classproperty(property):
    pass

class PropertyMeta(type):

    def __new__(cls, name, bases, namespace):
        props = [(k, v) for k, v in namespace.items() if type(v) == classproperty]
        for k, v in props:
            setattr(cls, k, v)
            del namespace[k]
        return type.__new__(cls, name, bases, namespace)

class StartUp(metaclass=PropertyMeta):
    __this = None

    def __init__(self):
        self.hentai = Hentai()
        self.oppai = oppai.Oppai()
        pass
    
    @classproperty
    def value(cls):
        if cls.__this is not None:
            return cls.__this
        cls.__this = StartUp()
        return cls.__this

    @classmethod
    def main(cls):
        cls.value
        print("Hello World")
        cls.__this.input = input("何か入力")
        return

if __name__ == "__main__":
    StartUp.main()
```
正月休みはソシムさんのＡｎａｃｏｎｄａでＰｙｔｈｏｎを学習するぞ

１年間、色々な投稿を参考にし、２回目の投稿となります。
Ａｎｄｒｏｉｄｓｔｕｄｉｏ、エクリプスでAndroidをやってからPythonを始めました。

またもや色々なPythonを活用している方々の意見を参考にしすぎたら（プライベートで）
混乱したんですが、とにかく年末年始の正月休みはそソシム株１式会社の著書のみに専念しましょう。

一挙両得、2頭を追う者は1頭も終えずと相反する慣用句がありますが、

その著書で自然言語処理のサンプルをＡｎａｃｏｎｄａのジュピターノートブックに映して実行させてみるが、

「モデルがありませんよ(´;ω;｀)」って弾かれてます。

本のサンプルでお試しに動かしてみれば、エラーが出るなんてあるあるです。

本に文句を言っちゃーーダメダメです。

現役さんはこれを易々と越えていくんで。

とにかくサンプルでなんとか動いたやつはまた投稿しようと思います。

年末年始でＡｎａｃｏｎｄａを満了することが目的ですから

その次はヴィジュアルスタジオコードでＥｘｃｅｌを操ることが目的です。
「Rubyで回分数の判定」を参考にWolframAlphaでやってみた。

(オリジナルポスト)
https://qiita.com/healthy-ozisan/items/ca5f254a95aae4c2c4b0
(参考)【Python】 プロジェクトオイラー　Problem 4
https://qiita.com/projecteuler/items/3f1bdb3e7d9fd1ff2def

##WolframAlphaで
12321は回文数ですか？
12321は回文数です
https://ja.wolframalpha.com/input/?i=12321%E3%81%AF%E5%9B%9E%E6%96%87%E6%95%B0%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F
Linuxコマンドを使い始めるのに調べたこと

エンジニアスキルを上げるために、ファイル操作からLinuxコマンドにシフトしよう。
基礎知識と基本コマンドを、簡単にまとめてみました。

# Linuxとは
オープンソースのOS。Unix系OSのひとつ。2010年代以降、サーバ向けOSとして広く運用されるようになっている。
# シェルとは
シェルはOSと対話するためのインターフェースを提供するソフトウェア。
![シェル](https://orizuru.io/wp/wp-content/uploads/2019/07/%E3%82%B7%E3%82%A7%E3%83%AB%E7%94%BB%E5%83%8F-1.png)
> 画像引用：CORE CONCEPT TECHNOLOGY INC.ブログ：【10分でわかるかもしれない】シェル（shell）とは？

# シェルの種類
ターミナルから、以下コマンドで確認。

```bash
$ echo $SHELL
```
| シェル |説明 |
|:--|:--|
|sh   |古くからあるシェル。AT&Tベル研究所のSteven Bourne氏によって開発され、開発者の名にちなんでBシェル（Bourneシェル）と呼ばれる。   |
|csh   |C言語に似た構文をもつことから、Cシェルと呼ばれる。Bシェルに比べ、対話的に使用する場面で便利な機能（ヒストリー機能やジョブ制御、エイリアスなど）が実装されている。   |
|bash   |Bシェルを基盤とし、その機能を拡張したもの。   |
|tcsh   |CシェルにTenexの機能を組み込んだもの。Tenexとは、コマンドライン（コマンドの入力部分）の編集機能、ファイル名やコマンドの補間機能があるシステム。   |
|zsh   |bashやtcshなどの他のシェルの機能をいいとこ取りし、さらに独自の拡張機能を実装したもの。  |

# Linuxの基礎コマンド
| コマンド | 説明 |
|:--|:--|
|cd \<path>   |<path>に移動する (current directory)   |
|pwd   |今いるディレクトリを表示 (print working directory)   |
|mkdir \<new folder>   |新しいフォルダ\<new folder>を作成 (make directory)   |
|touch \<new file>   |新しいファイル\<new file>を作成   |
|ls   |カレントディレクトリのファイル、フォルダを一覧表示 (list)   |
|rm \<file>   |\<file>を削除   |
|rm -r \<folder>   |\<folder>を削除   |
SolarisでRedshiftなどのサードパーティのレンダリングエンジンを使っている時でもHoudini GLで素早くViewに表示させる方法。

#はじめに
この記事はHoudini Advent Calendar 2020 9日目の記事です。

12月9日が次女の1歳の誕生日なので記念に投稿してみようと意気込んでいたのですが遅れに遅れてしまいまい申し訳ございません。
Houdiniに関してQiitaに投稿するのは初めてです。
サードパーティのレンダリングエンジンを使っている時でも下記のようにHoudini GLで表示されるためのTipsです。
![ezgif.com-gif-maker (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24726/40b816a7-ff25-4ced-254f-4b942451d57c.gif)



#お題
僕はレンダリングには`Redshift`を使っていますが、下記のように通常のマテリアルの設定では`Solaris`（Stage)のViewで描写の早い`HoudiniGL`を選択しているとテクスチャーなどが張られた状態でプレビューできません。勿論`Redshift`を選択すれば表示されますが、いくらGPUを使って早いとは言えViewを動かしたり、なにか作業するたびに再レンダリングされるので、作業中は`HoudiniGL`で確認したいものです。

#####解決前のView 
![flatview.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24726/5e0914f9-b025-0aed-e454-b5a09a8b51a5.jpeg)

#####Material Libraryの中身
![redshift_material.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24726/9fafd0d9-6618-2f7d-d6ff-58d8dfe4c6be.png)

#####Nodeの全体像
![node.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24726/0cc3823d-9f37-ee40-7368-de4a953fece4.png)


#解決方法
**`Material Library`で`Karma`の設定も行い(今回は`Principled Shader`の追加と各種テクスチャの設定）、`Collectノード`でまとめ上げる**と、`Solaris`のViewを動かしている`USD Hydra`エンジンのの`Render Delegate`という機能を使って、`Karma`のレンダリングが出来るのと同時に`HoudiniGL`による素早い表示が可能となります。`HoudiniGL`の設定をすると`Karma`でのレンダリングも付いてくる！みたいな感じです。(同様に、`Arnold`などのレンダリングエンジンも追加できます）
#####設定後のMaterial Libraryの中身
![collect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24726/ed89d091-fb1f-310d-4e51-d2ad829ccd6d.png)
#####設定後のMaterial Libraryの設定
`Material VOP`には`Collect`ノードを指定します。
![property.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24726/82cfdd9e-55e7-d914-2e8f-79796f824b51.png)

#####`HoudiniGL`でもテクスチャなどが表示されるようになりました
![View.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24726/9402d508-00ee-71e0-4bb1-b68bd256b9f5.png)

#さいごに
`Nvidia`の`Omniverse`の出現をきっかけに`USD`というか`Solaris`を本格的に使おうと勉強中です。今後のSolarisに関する情報を発信していけたらと思っています。
元々Houdiniのカメラやライトの管理方法が嫌いだったので`Solaris`は自分に合っています。
Hipファイル要望があるようでしたら公開しますが、多分この内容に興味がある方は上記のノードの画像でお分かりになるかと思います。
より詳細な内容はこちらをご覧ください。[元ネタ動画](https://www.youtube.com/watch?v=q-vXgQYDUL8&list=PLXNFA1EysfYmy1G5yX570j4vySn769pFg)
サーボモーターの仕様　


https://monoist.atmarkit.co.jp/mn/articles/1605/12/news007_2.html

サーボモータを制御するためには周期を20ミリ秒、周波数でいえば50Hzにします。またパルス幅は1ミリ秒から2ミリ秒の間で変化させます。パルス幅が1ミリ秒の時、サーボモーターの軸の角度が0度となります。また2ミリ秒の時にサーボモーターの軸の角度は180度となります。1.5ミリ秒の時は、ちょうど真ん中の90度となります。この様にパルス幅を微妙に変えることによって、サーボモーターの軸の角度を0度から180度の間で制御することができるのです。
Railsの[validates :~, presence: true]と[null: false]の違い

#Railsの[validates :~, presence: true]と[null: false]の違い

**主に自分用に、初めての投稿です**

##[結論]
2つとも、nilの保存が防ぐことができますが、``[null: false]``の場合、`""(空文字)`を保存することが可能です。

また、`[validates :~, presence: true]`の場合、ブラウザ上からの保存はできませんが、SQLから保存処理を行うことができます。

そのため、カラムに制約をつける際は、マイグレーションファイルに`[null: false]`,モデルに`[validates :~, presence: true]`の、2つの記述を書いておくと安心です。
🎍PHP🎍だけで動くwebパラパラアニメを表現してみた...!!(むりやり)

※PHPアドベントカレンダー大遅刻で申し訳ありません。。。><

## PHPでアニメーション表現できないのかな..?

PHPではサーバーサイドの言語だからアニメーションは無理、どうにかしてjavascriptのようにアニメーションが表現できないか、
ましては、php-cliでコマンドライン上でもなく**ブラウザ上で表現**できないか、完全に誰得なのかわからないものに挑戦してみました。。汗

で完成したものがこれ..



[**▶完成したデモはこちら**](https://matsudapress.com/lab/sandbox/php/red.php?id=0)
※だいぶカクカクですが:upside_down:


javascriptやCSS、HTMLもつかっていません。

gif画像など組み合わせたり、遅延時間を調整すればかなり無理矢理だけどアニメーションっぽいことできそう。
キーボード入力情報をうまく連携させれば、無理やり動きのあるゲームっぽいのも可？

## アニメーションっぽく表現するために色々やった試行錯誤

#### 検証① sleepを使って遅延でアニメーションできないか？

```php:
<?php
sleep(1);
echo "H";
sleep(1);
echo "A";
sleep(2);
echo "P";
```

3秒後に、`HAP`とでる..

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/b2297f74-76a1-6b4d-4552-ea3954f30b46.png)

当たり前だけど、処理結果しかでないから、、どうにか画面クリア的ことができないか。。


#### 検証② `sleep`と`header("Location:〜");`でリダイレクトと組み合わせたら？

画面を再描画する方法がないなら、むりやりリダイレクトや！ということで、
リダイレクト処理と遅延処理でなんとかできないかと挑戦。
そもそも、`header("Location:〜")`前にecho等の出力はNGなので、
html上には表示できないとして、アドレスバー上でパラパラアニメっぽくできないかな〜と妄想。

jsでやっている[→こちら](https://blog.sushi.money/entry/2020/08/13/140742#%F0%9F%8C%94)をイメージw

とりあえず。`http://example.com/#H→#HA→#HAP→#HAPPY`と動いてくれないか、、
検証


```php:
<?php
sleep(1);
$anime = ["H","HA","HAP","HAPP","HAPPY"];
$red = "./red2.php";
if( isset($_GET['id']) ){
        $id = intval($_GET['id']);
        if($id > 4) exit(); 
        $url = $red."?id=".($id+1)."#".$anime[$id];
        header("Location:".$url);
}
exit();
```

結果は.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/14d49499-294e-7948-ed89-10af8f57d7df.png)
↓
🕓 5秒後
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/41ad0cdc-76b0-ef96-7361-c468401668ce.png)

アドレスバーも最終的な結果した出力されない...

また、red2.php等のパスをリダイレクト毎にシンボリックリンクで変更してやってもみましたが、
こちらも結果は最終的な出力しかでずNG..

もうphpアドベントカレンダーのネタないし、php-cliでゲームでも作ろうかなとおもったら、
既に素晴らしすぎるphp-cliで動くテトリスがwwすごい
[→こちら](https://qiita.com/PruneMazui/items/617e1af1a4b4577eed1f)

#### 検証③ `header( "refresh:0.2;url=".$url );`ヘッダーリフレッシュに出会う

```php:
<?php
$anime = ["H","A","P","P","Y"," ","N","E","W","Y","E","A","R",""," ","🎍2021🎍"];
$red = "./red.php";
if( isset($_GET['id']) ){
        $id = intval($_GET['id']);
        $id++;
}
$url = $red."?id=".$id."#".$anime[$id];
header( "refresh:0.2;url=".$url );
for($i=0;$i<$id;$i++){
        echo $anime[$i];
}
exit();
```

お、なんかいけたっぽい。。
というかheaderのrefreshってhtmlな気がするけど、、コードはすべてphpなのでお許しください。

![Dec-31-2020 04-30-49.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/cc171cb0-b2c9-dd5f-91fb-a89b473f8778.gif)


## 🎍2021年も良いPHPライフを🎍

最後まで読んでいただきありがとうございます！良いお年を

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/8b9c5d6e-f764-b065-751a-fd3f81aeb877.png)
【Unity】簡単にビデオ録画ができるアセット NatCorderのメモ

#はじめに
GameSceneの映像をカメラロールに保存する時、プラットフォーム別の対応をしたくなかったので利用しました。
サンプルシーンと公式リファレンスを参考にすれば大体わかりますが、英語読むの大変だったので自分用にまとめておきます。

#NatCorder
> UnityEngine用の軽量ビデオ録画API。
 プッシュアーキテクチャで設計されているため、3つの簡単なステップでビデオを録画できます。

**公式API**
https://docs.natsuite.io/natcorder/
![スクリーンショット 2020-12-30 2.13.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293639/da94e6be-75b3-0f14-c92d-2f80da986748.png)

こちらから購入できます。
https://assetstore.unity.com/packages/tools/integration/natcorder-video-recording-api-102645

##録画開始方法

###Recorderクラス
作成したい形式のRecorderクラスインスタンスを作ります。
ここでサイズやフレーム数を決めます。音声も含めたい場合は引数で渡してあげてください。

```C#
mp4Recorder = new MP4Recorder(Camera.main.pixelWidth, Camera.main.pixelHeight, 30);
```
NatCorderでは下記の形式が用意されています。

- MP4
- GIF
- HEVC
- JPG
- WAV

###RealtimeClock
NatCorderで用意されているTimestampを取得するクラスです。

```C#
clock = new RealtimeClock();
```

###CameraInput
UnityCameraの映像を使って録画したい場合に使うクラスです。
コンストラクターにRecorderクラスとRealtimeClock、撮影で使うUnityCameraを引数に渡してあげます。
この時配列でUnityCameraを渡すことで複数の映像をブレンドしてくれます。

```C#
cameraInput = new CameraInput(mp4recorder, clock, Camera.main);
```
CameraInputのインスタンスを生成した時点で録画が開始されます。

##録画停止方法

###CameraInput.Dispose
録画を停止したい場合に使う関数です。
Recorderクラスで```FinishWriting()```を呼び出す前に必ず行います。

```C#
cameraInput.Dispose();
```

###IMediaRecorder.FinishWriting
フレームのコミットを終了する関数です。
処理が終了すると保存先のpathを返してくれます。

```C#
var path = await recorder.FinishWriting();
```

#サンプルコード
とりあえずこんなんで動きます。

```C#
using UnityEngine;
using NatSuite.Recorders.Clocks;
using NatSuite.Recorders.Inputs;
using MP4Recorder = NatSuite.Recorders.MP4Recorder;

public class MovieGenerater
{
    private static MovieGenerater instance;
    private MP4Recorder mp4recorder;
    private CameraInput cameraInput;

    public static MovieGenerater Instance
    {
        get
        {
            if (instance == null) instance = new MovieGenerater();
            return instance;
        }
    }

    public void StartRecording()
    {
        mp4recorder = new MP4Recorder(Camera.main.pixelWidth, Camera.main.pixelHeight, 30);
        cameraInput = new CameraInput(mp4recorder, new RealtimeClock(), Camera.main);
        Debug.Log("Recording Start");
    }

    public async void StopRecording()
    {
        cameraInput.Dispose();
        var path = await mp4recorder.FinishWriting();
        Debug.Log($"Saved recording to: {path}");
    }
}
```

##使い方
ボタン等のタイミングで```StartRecording();```を呼べば撮影が開始されます。
終了したい場合は```StopRecording();```を使ってください。
正常に保存が成功すると保存先のpathが返ってくるので確認してください。

#まとめ
たったこれだけでプラットフォームを気にせず使えるのでオススメのアセットです！
カメラアプリやARアプリで使ったり、RenderTextureの録画をしたいときに便利そう。。

余談になりますが同じ作者さんの**NatShare**というAssetを使うと、SNS共有まで対応幅が広がるので気になった方は使ってみてください！
~~気が向いたらNatShareの記事もかきます！~~

NatShareの記事投稿しました。
https://qiita.com/Formi/items/de2afa7fab89bbee8259
roman numerals

# はじめに

今回は以下の記事にある，アラビア数字を受け取って，ローマ数字を返す関数to\_romanをrubyで実装する．
-   [roman numerals](https://qiita.com/daddygongon/items/2d0a73a51ddab2d9da1b)

# roman numerals

境界値が沢山あってifだらけになってしまうような場合は，配列に境界値を入れてループで回すという実装テクニックが使える場合がある．今回はこの方法が有効なので使う．

```ruby:roman_numerals.rb
def to_roman(n)
  raise RangeError if n <= 0 or 4000 <= n

  arabic_num = [1000,900,500,400,100,90,50,40,10,9,5,4,1]
  roman_num = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
  ret = ""
  arabic_num.zip(roman_num) do |arabic, roman|
    while n >= arabic do
      n -= arabic
      ret << roman
    end
  end
  return ret
end
```

# 発展課題

この関数をIntegerクラスのメソッドとして追加してみる．

```ruby:roman_numerals.rb
class Integer
  def to_roman
    n = self
    raise RangeError if n <= 0 or 4000 <= n

    arabic_num = [1000,900,500,400,100,90,50,40,10,9,5,4,1]
    roman_num = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
    ret = ""
    arabic_num.zip(roman_num) do |arabic, roman|
      while n >= arabic do
	n -= arabic
	ret << roman
      end
    end
    return ret
  end
end
```

すると以下のように使える．

```ruby:roman_numerals.rb
3999.to_roman # => "MMMCMXCIX"
```

------
 - **source** ~/grad_members_20f/members/ryuta-kikuchi/qiita_articles/roman_numerals.org
Firestore（in Datastore mode）で、Projectionクエリを使って料金を節約する

クリスマスは過ぎてしまいましたが参加してたGCP Advent Calendarに穴が一つだけ空いてたので今更ながら埋めます^^;

# 最初に

Firestore (in Datastore Mode)でクエリを呼び出した場合、通常Query実行の1読み込みオペレーションに加えて、取得したエンティティの数だけ読み込みオペレーションがかかります。

大昔には読み込みオペレーションを節約する為にKey名にプロパティ内容を埋め込んでKeysOnlyクエリで取得するみたいな黒魔術が存在したこともありましたが、現在はProjectionクエリを利用して同様の節約を行うことが出来ます（しかも黒魔術と違ってプロパティ変更が可能です^^）。

Projectionクエリは、一般的なRDBでいうところのカラム指定SELECT（SELECT A, B, C FROM ...）を行うものです。
Firestore(in Datastore mode)内部の動きとしては、インデックス上のプロパティを使って結果を返す為、かかる料金はクエリ実行の1読み込みオペレーションのみで、エンティティ毎の読み込みオペレーションが無料になります。
つまり、例えば1000件読み込んだ場合料金は**1/1001**になります。

# 実装

本記事ではGoのClient Libraryを利用します。

datastore.QueryのProjectメソッドで取得したいプロパティ名を指定するだけです。

```Go
type Book struct {
	Title     string
	Category  string
	Price     int
	CreatedAt time.Time
}

func main() {
	ctx := context.Background()

	q := datastore.NewQuery("Book").Project("Title", "Price", "Category", "CreatedAt").Order("CreatedAt").Limit(1000)

	var books []*Book
	_, err := client.GetAll(ctx, q, &books)
	if err != nil {
		log.Fatal(err)
	}

	for _, b := range books {
		fmt.Printf("%+v\n", b)
	}

	fmt.Println("done")
}
```

複数のプロパティを指定する場合はカスタムインデックスが必要になります。

```yaml
- kind: Book
  properties:
  - name: CreatedAt
  - name: Category
  - name: Price
  - name: Title
```

# まとめ

Projectionクエリは結構マイナーな機能かな、と思っているのですが、うまく使うことで大幅にコストを減らすことが可能です。

旧Datastore時代からあった機能ですがグローバルクエリの場合インデックス遅延により最新のデータを取得しない可能性があるというデメリットもありました。
Firestoreになってクエリも強整合になったのでその弱点もなくなった認識です（ツヨイ！）

現状Datastore modeのみの機能ですが、Native modeにも欲しいところです。

# 参考資料

[Projection queries](https://cloud.google.com/datastore/docs/concepts/queries#projection_queries)
[Pricing and Quota](https://cloud.google.com/datastore/pricing)

それでは、よいお年を〜＼(^o^)／
Go言語でconfigファイルを読み込む！簡単なサンプルを紹介

公式ドキュメント→https://gopkg.in/go-ini/ini.v1

### パッケージをインストール
```
go get gopkg.in/go-ini/ini.v1
```

### ファイル構成

```
.
├── config
│   └── config.go
├── config.ini
└── main.go
```

### iniファイルを作成
```config.ini
[api]
api_key = aaaaaa
api_secret = bbbbbbb

[db]
password = ccccc
etc...
```

上記の[api][db]のようにセクションごとに分けてあげると管理がしやすい。
クォーテーションなどで囲む必要はなし。

### configファイルを作成

```config/config.go
package config

import "gopkg.in/ini.v1"

type ConfigList struct {
	APIKey     string
	APISecret  string
	Password   string
}

var Config ConfigList

func init() {
	cfg, err := ini.Load("config.ini")
	if err != nil {
		//エラー処理
	}

	Config = ConfigList{
		APIKey:     cfg.Section("api").Key("api_key").String(),
		APISecret:  cfg.Section("api").Key("api_secret").String(),
		Password:   cfg.Section("db").Key("password").String(),
	}
}
```

### configの値を取得

```main.go
package main

import "./config"

func main() {
    Println(config.Config.APIKey)
    Println(config.Config.APISecret)
    Println(config.Config.Password)
}
```
こんな感じでconfigの値を取得できます。

今回はiniファイルを作成しましたがTOMLを使った方法もある。
この人の記事がとても分かりやすかったのでおすすめです。
→https://qiita.com/futoase/items/fd697a708fcbcee104de
課題 roman numerals



# 課題

アラビア数字(arabic numerals)を受け取って，ローマ数字(romannumerals)を返すmethodを書きなさい


# ローマ数字で使われる文字

| arabic numerals | roman numerals |
|----------------:|:---------------|
| 1               | I              |
| 5               | V              |
| 10              | X              |
| 50              | L              |
| 100             | C              |
| 500             | D              |
| 1000            | M              |


# 用いたコード

```ruby
# coding: utf-8

def to_roman(num)
# 4000 未満の数値を入力する

#1,000 に関して
thou = num / 1000
a = num % 1000
roman = 'M' * thou

#100 に関して

hun = a / 100
b = a % 100

if (hun == 9)
  roman += 'CM';
elsif (hun >= 5)
  roman += 'D' + 'C' * (hun - 5)
elsif (hun == 4)
  roman += 'CD'
else
  roman += 'C' * hun
end

# 10 の個数を計算
ten = b / 10
c = b % 10

if (ten == 9)
  roman += 'XC'
elsif (ten >= 5)
  roman += 'L' + 'X' * (ten - 5)
elsif (ten == 4)
  roman += 'XL'
else
  roman += 'X' * ten
end

# 1 の個数を計算
if (c == 9)
  roman += 'IX'
elsif (c >= 5)
  roman += 'V' + 'I' * (c - 5)
elsif (c == 4)
  roman += 'IV'
else
  roman += 'I' * c
end
  p "アラビア数字=#{num} ローマ数字=#{roman}"
end


data = [1, 2, 4, 5, 6, 9, 10, 11, 14, 15, 19, 38, 42, 49, 51, 97, 99, 439, 483, 499, 732, 961, 999, 1999]
data.each do |num|
to_roman(num)
end

```


## コード解説

-   roman に変化する関数
    -   それぞれのくらいの数を調べる
-   入力データを用いて、変換し出力


# 出力結果

```
"アラビア数字=1 ローマ数字=I"
"アラビア数字=2 ローマ数字=II"
"アラビア数字=4 ローマ数字=IV"
"アラビア数字=5 ローマ数字=V"
"アラビア数字=6 ローマ数字=VI"
"アラビア数字=9 ローマ数字=IX"
"アラビア数字=10 ローマ数字=X"
"アラビア数字=11 ローマ数字=XI"
"アラビア数字=14 ローマ数字=XIV"
"アラビア数字=15 ローマ数字=XV"
"アラビア数字=19 ローマ数字=XIX"
"アラビア数字=38 ローマ数字=XXXVIII"
"アラビア数字=42 ローマ数字=XLII"
"アラビア数字=49 ローマ数字=XLIX"
"アラビア数字=51 ローマ数字=LI"
"アラビア数字=97 ローマ数字=XCVII"
"アラビア数字=99 ローマ数字=XCIX"
"アラビア数字=439 ローマ数字=CDXXXIX"
"アラビア数字=483 ローマ数字=CDLXXXIII"
"アラビア数字=499 ローマ数字=CDXCIX"
"アラビア数字=732 ローマ数字=DCCXXXII"
"アラビア数字=961 ローマ数字=CMLXI"
"アラビア数字=999 ローマ数字=CMXCIX"
"アラビア数字=1999 ローマ数字=MCMXCIX"
```



------
 - **source** ~/grad_members_20f/members/FumiyaToyoda/roman_numerals.org
課題 roman numerals



# 課題

アラビア数字(arabic numerals)を受け取って，ローマ数字(romannumerals)を返すmethodを書きなさい


# ローマ数字で使われる文字

| arabic numerals | roman numerals |
|----------------:|:---------------|
| 1               | I              |
| 5               | V              |
| 10              | X              |
| 50              | L              |
| 100             | C              |
| 500             | D              |
| 1000            | M              |


# 用いたコード

```ruby
# coding: utf-8

def to_roman(num)
# 4000 未満の数値を入力する

#1,000 に関して
thou = num / 1000
a = num % 1000
roman = 'M' * thou

#100 に関して

hun = a / 100
b = a % 100

if (hun == 9)
  roman += 'CM';
elsif (hun >= 5)
  roman += 'D' + 'C' * (hun - 5)
elsif (hun == 4)
  roman += 'CD'
else
  roman += 'C' * hun
end

# 10 の個数を計算
ten = b / 10
c = b % 10

if (ten == 9)
  roman += 'XC'
elsif (ten >= 5)
  roman += 'L' + 'X' * (ten - 5)
elsif (ten == 4)
  roman += 'XL'
else
  roman += 'X' * ten
end

# 1 の個数を計算
if (c == 9)
  roman += 'IX'
elsif (c >= 5)
  roman += 'V' + 'I' * (c - 5)
elsif (c == 4)
  roman += 'IV'
else
  roman += 'I' * c
end
  p "アラビア数字=#{num} ローマ数字=#{roman}"
end


data = [1, 2, 4, 5, 6, 9, 10, 11, 14, 15, 19, 38, 42, 49, 51, 97, 99, 439, 483, 499, 732, 961, 999, 1999]
data.each do |num|
to_roman(num)
end

```


## コード解説

-   それぞれのくらいの数を調べる
    -


# 出力結果

```
"アラビア数字=1 ローマ数字=I"
"アラビア数字=2 ローマ数字=II"
"アラビア数字=4 ローマ数字=IV"
"アラビア数字=5 ローマ数字=V"
"アラビア数字=6 ローマ数字=VI"
"アラビア数字=9 ローマ数字=IX"
"アラビア数字=10 ローマ数字=X"
"アラビア数字=11 ローマ数字=XI"
"アラビア数字=14 ローマ数字=XIV"
"アラビア数字=15 ローマ数字=XV"
"アラビア数字=19 ローマ数字=XIX"
"アラビア数字=38 ローマ数字=XXXVIII"
"アラビア数字=42 ローマ数字=XLII"
"アラビア数字=49 ローマ数字=XLIX"
"アラビア数字=51 ローマ数字=LI"
"アラビア数字=97 ローマ数字=XCVII"
"アラビア数字=99 ローマ数字=XCIX"
"アラビア数字=439 ローマ数字=CDXXXIX"
"アラビア数字=483 ローマ数字=CDLXXXIII"
"アラビア数字=499 ローマ数字=CDXCIX"
"アラビア数字=732 ローマ数字=DCCXXXII"
"アラビア数字=961 ローマ数字=CMLXI"
"アラビア数字=999 ローマ数字=CMXCIX"
"アラビア数字=1999 ローマ数字=MCMXCIX"
```



------
 - **source** ~/grad_members_20f/members/FumiyaToyoda/roman_numerals.org
Linux(Ubuntu)でFreeCADをインストールしてアイコンを作成してみた

#はじめに
Ubuntuで最高峰の3dCADのFreeCADを入れると，コマンドラインでしか起動出来ないのがちょっともったいない．
なのでアイコンを作ってランチャーから起動してみたって話．
この方法を使えば他のアプリでもアイコン自由に変えたりデフォルトの起動オプション変えたり出来る．
そこまでは話さないけど，出来ると知ってると後々便利よ．

##FreeCADのインストール
apt元のパッケージもあるんだけど，バージョンが古いらしいのでPPAで最新安定版を入れる．

```
sudo add-apt-repository ppa:freecad-maintainers/freecad-stable
sudo apt-get update
sudo apt-get install freecad
```

##FreeCADの.desktopファイルを探す
Linuxアプリのアイコンは.desktopファイルでオプション管理してます．
よってlinuxにある神コマンドlocateを使ってFreeCADの.desktopファイルを探す．
locateを入れてない？
人生の8割損してるので今直ぐ入れて下さい．

```
locate freecad.desktop
```

まあ多分
>/usr/share/app-install/desktop/freecad:freecad.desktop

ってヒットするので別にそこにアクセスしても良いけど．
これをアイコンを管理してるフォルダの ~/.local/share/applicationsにコピー．

```
sudo cp /usr/share/app-install/desktop/freecad:freecad.desktop ~/.local/share/applications/freecad.desktop
```

これでSuperKeyでアプリ検索すると出てくるようになります．

##アイコンを追加
アイコンが真っ白なのでアイコンを設定する．
自分の好きなアイコンをダウンロードして"freecad.png"とかで保存する．
キャッシュされないので消さない場所に保存する．

さっきの.desktopファイルを編集する．

```
sudo gedit ~/.local/share/applications/freecad.desktop
```

ファイル内の"Icon"部分を変更．
フォルダの場所は自分が"freecad.png"を保存した場所．以下はあくまで一例．

```
Icon=/home/"user-name"/Pictures/Icon/freecad.png
```

最後に保存してログアウト→ログインすると反映される．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246335/dcd7579c-0540-d985-ffa8-b55c868c5736.png)

#終わりに
ちょいちょいやったらうまいこと行ったので共有した．
~~この記事が良いと思ったら高評価ボタン・チャンネル登録してくれよな！~~

Ubuntu神で本当に便利なのでみんな使って...Windows使う理由ある？

ではまた．
共有ライブラリを使うのを止めてほしい

以下は共有ライブラリに虐げられ共有ライブラリをもう使いたくないという個人的な愚痴をまとめたものです。特にことわらない場合は Linux の話です。

何故共有ライブラリを使うのか？
--------------------------

前回説明したように共有ライブラリをリンクした実行ファイルは必要な共有ライブラリを実行時にシステムから検索してロードします。この際ライブラリを検索する方法は名前です。先に見つけたものを使います。しかもこの検索パスは環境変数 `LD_LIBRARY_PATH` によって変更できます。また検索する順序に当然依存します。

この機構は何のために存在するのでしょう？いくつかの目的があげられます。

### ディスク容量を節約する

複数の実行バイナリで同じ関数のバイナリを持たなくていいので単純にディスク容量を節約できます。これは現代のように十分大容量なディスクが安価で利用できる時代には特に問題になりません。
 
### 共有ライブラリを更新すればそれを利用している全ての実行ファイルで更新したものを利用できる

例えば利用しているライブラリに脆弱性が見つかったとしましょう。そのライブラリを使用している実行ファイルには全てその脆弱性がある事になります。急いで全ての実行ファイルを更新しなければなりません。この時共有ライブラリの形で提供してあれば、その共有ライブラリを更新すれば全ての実行ファイルを再ビルドせずに済みます。これは使うライブラリが増えれば増えるほど組み合わせ論的に増えます。もし静的にリンクしていたら使っているライブラリが更新される度にビルドをする必要があるでしょう。これはシステムを提供する立場では看過出来ません。

何故共有ライブラリは辛いのか?
-------------------------
はい、共有ライブラリは大事ですね。どうしてこんな記事を書いたのでしょうか？

アプリケーションを書いているときに、あるライブラリを使おうとしたとしましょう。ライブラリを使うのはとても良いことです、多くの処理は既に誰かが上手く解決してライブラリとして提供してくれています。ではこのライブラリを静的にリンクするべきでしょうか？動的にリンクするべきでしょうか？

静的にリンクすることの利点は、そのライブラリをビルド時の状態で固定出きることであり、動的なリンクの利点は実行時にこのライブラリを入れ替えることによって状態を固定しない事です。

動的にシステムからライブラリを取得する事は上に述べたように問題が発生した場合に簡単に置換出来る事が出来る一方、アプリケーションは勝手に共有ライブラリがすげ替えられてもちゃんと動作し続けないといけないことになります。しかも共有ライブラリはアプリケーションの実行バイナリ本体に含まれていないため、正しくシステムにライブラリがインストールされていないとアプリケーションが動きません。こうなるとアプリケーション開発者が実行環境を制御したいと思うことは自然な事でしょう。アプリケーションを安定して動作させる環境を用意しようと考える事でしょう。そうだ実行環境をコンテナで配布すればいいんだ！

はい、コンテナ内の共有ライブラリはシステムから置き換えれませんね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30426/2ed8d180-485d-daee-87bb-c2fb38bd0526.png)
https://www.slideshare.net/Docker/dockercon-eu-day-1-general-session

何を間違えたのでしょう？対立しているのは次の2点ですね

- 共有ライブラリを変更する事で問題に対処できる
- アプリケーションを安定に動作させるために共有ライブラリを更新して欲しくない

共有ライブラリを置き換える事で実現しようとしたセキュリティは上の図でコンロに鍵をかけているのと等しく、コンテナ技術の発達によって共有ライブラリを更新することで脆弱性に対応できる、というのは全く現実的でなくなってしまいました。もうこうなってしまうとわざわざ実行時に共有ライブラリを探す理由がありません。探すまでもなくコンテナで固定されてしまっているのですから。
ガリル（Galil）モーションコントローラーについて

この記事では[ガリル社のモーションコントローラー](https://www.galil.com/)の概要を記載する。

##モーションコントローラーとは？
サーボモータなどのアクチュエータを制御するための機器。モーション（動き）を制御（コントロール）することができる。下図ではPCに接続されたコントローラー（ガリル）がサーボアンプ（サーボドライバー）に指令を出し、サーボアンプがモーターを制御している。エンコーダーはモーターの動き（回転数やトルクなど）を計測し、コントローラーへフィードバックしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318917/21f59001-ee18-0176-dcf1-425f9e0095b5.png)

##ガリルの仕様
- スタンドアロン動作、またはPCからEthernet,USBで制御。
- 最大8軸（型式のDMC-41x3のxが制御可能な軸数。4軸ならDMC-4143）※注１
- プログラムまたはガリル制御ソフトのターミナルから動作。
- プログラムは最大8つまで並列制御（マルチタスク）可能。
- デジタル・アナログI/O制御可能。
- PID制御でゲイン調整が可能。

※注１　モーター一つを1軸と見なす。モーター4つを同時制御したいなら最大4軸用のガリルを使う必要がある。


##ガリルの特徴
- 簡単なプログラムでモーター制御ができるので、PLCに比べるととりあえず動かしたいときに便利。
- 並列処理が簡単にできるので、複雑な多軸制御でも動作検証が楽。
- 動作中にターミナルから回転数やトルクを変えられるので、簡単な動作ならプログラムを書き換えなくても動作検証ができる。
- プログラムは簡単な文法のスクリプト言語なので書きやすいが、古い言語スタイルなので複雑なことはできない。
- 円弧補間など数式の設定をしなくても自動でやってくれる。

##プログラムの作成・転送・実行
PC上でのプログラム作成・プログラムのガリルへの転送・ガリルでのプログラム実行の手順を記載する。
###プログラムの作成
ガリルプログラムのコーディングはGalil Toolsで行える（エディタはついているが入力補完などのIDEとしての機能はない）。なお、静的なエラーは以下のダウンロード実行時にターミナルに表示される。

###プログラムのガリルへの転送
作成したプログラムをガリルへ転送（ダウンロードと呼ばれている）するにはGalil Toolsでプログラムを開いた（プログラムウィンドウがアクティブ）状態でDownLoadボタンを押す。なお、ただダウンロードしただけではガリルの電源を落とした時にダウンロードしたプログラムは消されてしまうので、電源を落とした後でもプログラムを残したい場合は書き込む作業（ターミナルでコマンドBN）が必要になる。LSコマンドを実行するとガリルにダウンロードされたプログラムがターミナルに表示される。

###プログラムの実行
実行させたいプログラムをガリルへダウンロードした状態で、ターミナルにXQ#{実行させたいラベル名}と入力するとプログラムが実行される。
Sublime Text3 でインクリメント/デクリメント

Sublime Text3をずっと使っていて、
以前は`Ctrl + ↑` `Ctrl + ↓`で
数値を1つづつ加算/減算できたんですよね。

で、アップデートがあったのか、いつからかそれが使えなくなってしまって。


for文なんかで、`$i >= 10`みたいな場面で
あと数字を1つ変えたら挙動はどうなるか、
フロントの見た目はどうなるかって時に、
バックスペース2回打って9にしたり、同じように11にしたり。

めんどくさくてしょうがなかった。

かといって数字を1つづつ上下させるのって
一言で表す単語も分からなくて諦めてた。

んで、今日になって別件でVimについて調べてたら
「インクリメント・デクリメント」という単語を見つけまして。

ああ、これだこれだと思いながら
早速Sublime Text君にインストールしたのでここに書き残しておく。


## 手順
Sublime Text3でパッケージコントロールを開く
`基本設定` > `Package Controll` > `Install Package`

`Inc-Dec-Value`をインストールする。

`基本設定` > `キーバインド` で以下をコピペする。

```
{ "keys": ["ctrl+up"], "command": "inc_dec_value", "args": { "action": "inc_min" } },
{ "keys": ["ctrl+down"], "command": "inc_dec_value", "args": { "action": "dec_min" } },
```


## 参考記事
https://mackee.hatenablog.com/entry/2014/05/18/185047
一人システム開発だけど、Azure Boardsを使ってみる③

#概要
前回の記事「[一人システム開発だけど、Azure Boardsを使ってみる②](https://qiita.com/yossihard/items/145eaf497adebc445dda)」では、
Azure BoardsのBoardメニューをいろいろ触ってみました。
今回はその続きでBacklogメニューをいろいろ触ってみます。

#Backlogを触ってみる
Azure DevOpsにログインして、左側メニューからBoards⇒Backlogを選択します。
そうすると、以下のような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/f207a78d-085b-0fb3-be81-bc058b9082b6.png)

登録したUser Storyが表示されていますね。
右側には「Planning」というペインがあり、中にIteration 1～3という項目がありますね。
Agile開発におけるイテレーションのことでしょうね。

User Storyをイテレーションにドラッグ＆ドロップすると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/371b1234-53fc-f3bf-e60c-e84c4c9c9c74.png)

そのUser Storyと紐づくTaskがイテレーションに入れられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/cbc6a7d5-e047-43b4-f297-399efdb26bfb.png)


Taskだけをイテレーションにドラッグ＆ドロップすると、
そのTaskだけがイテレーションに入れられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/4f4470de-1ca5-c66a-465a-d034fdf77fad.png)

ちなみに、イテレーションに入れたUser StoryやTaskを外したいときは、
「XXXX Team Backlog」(ここではAzureBoardsTest Team Backlog)に
ドラッグ＆ドロップすると外れました（笑）。
⇒他にも方法があるかも。

#イテレーションの設定
ところで、このイテレーションって、どこかに設定があるのかと思って
設定画面を眺めていると・・・Project Configurationにありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/41fa7dc1-1612-e3fe-3a07-4f578971ce7e.png)

ここで「New」をクリックすると、以下のような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/cdabb3f3-ba19-5641-f2c0-51cc974896a8.png)

適宜入力して「Save and close」をクリックすると、イテレーションが追加できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/6aac6d2d-9aed-a72b-2e8d-c0468554301f.png)

イテレーションのStart Dateあたりにカーソルを持っていくと、
以下のような表示になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/9f4082a2-c71b-74ea-20b7-c054d6e710d8.png)

ここで、「Set dates」をクリックすると、以下のような画面が表示され、
開始日時と終了日時を設定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/0730858f-f554-eb45-9b80-a74e96ef4ce7.png)

イテレーションの行の「・・・」をクリックして、表示されたメニューから「Edit」を選択しても、
同じ画面が表示され、開始日時や終了日時を設定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/2546e4d2-a1e5-3396-6bff-326c78a32d40.png)

イテレーションに階層も作れます。
イテレーションを選択した状態で、画面内の「New child」をクリックすると、以下のような画面が表示されます。
⇒イテレーションの追加と同じ画面ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/e0d8e22b-7ddc-5753-a6be-e6d62a374051.png)

適宜入力して、「Save and close」をクリックすると、以下の通り。
階層が作れましたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/6360efbe-52ea-1205-a935-867e6da26756.png)

#BacklogのAnalytics
イテレーションに開始日時と終了日時を設定しておいて、
Backlogの「Analytics」をクリックすると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/2bde8440-0797-156f-be49-3154aa40fc0a.png)

以下のような、分析画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/cdec1d8f-ad4c-1500-cfd6-50f499a447b1.png)

・Cumulative Flow Diagram：累積フロー図
・Velocity：ベロシティ（イテレーションで消化したタスクの合計？）

このあたりは、これから実際のプロジェクトに適用して、
どんな風に分析できるか確認してみたいと思います。
ラズパイ4のLibreELECでプライムビデオを観る

自分へのお年玉としてラズパイ4を購入した。
ラズパイのサードパーティOSにはLibreELECと言うメディア専用OSがある。
近頃、Fire TVの調子が悪いし、ラズパイ4ならメディア再生が楽にこなせるはずなので、LibreELECをその代わりにしようと考えた。
実際に試したところ、観たいビデオを探すインターフェースはいまいちだが、再生は安定しているようだ。
以下に作業メモとして参照したサイトの情報を主に記載する。

# 環境

- Raspberry Pi 4B (8GB RAM)
- LibreELEC 9.2.6 (Kodi 18.9)

# 手順

- Raspberry Pi Imagerを使用して、LibreELECをSDカードに焼く  
https://www.raspberrypi.org/software/
- LibreELECを日本語化  
https://pcmanabu.com/pi4-4k-playback/
- LibreELECにAmazon VODビデオプラグインをインストール＆設定  
https://raspida.com/primevideo-libreelec9  
※sambaよりもscp（WinSCPが便利）でファイルを転送する方が良い
(テスト自動化) 自動操作のシナリオを作るにあたって

#背景
社内のシステム開発者向けにテスト自動化システムを構築・運用している。(SikuliX + Testablish)
その中で日常的に出てくる技術課題ややりたいことをメモ書き。

テストに限らず自動化はいろいろと難しい。

#課題
RPAもテスト自動化も『今やっている作業が自動化されたらなんてハッピー』という感じで始めるのだが、実際は『あれ、なんか思ってたのと違う…』と我に帰るタイミングがあるものである。それは、以下のような時に特に強く感じる。

・　作った自動操作が思ったように動かないとき
・　文章で書けばワンセンテンスなのに、自動化させるための工程に直すと10倍以上の量を記述する必要があるとき
・　業務やシステムに仕様変更があって、自動化した操作の多くが動かなくなったとき

いずれも実際遭遇すると『やっぱり止めておこうかな。人類に自動化は早すぎる』と諦めたくなるのだが、諦めてしまっては先がない。
地道に一歩ずつ対策を練りたい。

#対応
操作シナリオの作り方について、使い回しが効いて、メンテナンスが最小となるようなお作法を考える。

#目的
自動化を楽にする。

#内容
自動化にあたってのお作法は色々とあるのだが、今回はその中でもシナリオの区切り方についてメモする。

シナリオの区切り方
次のようなシナリオがあったとする。

>新しい部署および紐づく社員を登録し、対象社員へパスワード変更メールが飛ぶことを確認する。
また、メールからシステムへアクセスし、パスワード変更できることを確認する。
繰り返し実行できるよう登録したデータは最後に消す。

これを単純にシナリオ化すると次のようになる。

>１．担当がシステムへログインし、部署画面へ遷移し、部署データを登録して、社員画面へ遷移し、社員データを登録する。
２．社員がメールを開いて、メール中のLINKからシステムへアクセスし、社員画面へ遷移し、社員データを更新する。
３．担当がシステムへログインし、社員画面へ遷移し、社員データを消して、部署画面へ遷移し、部署データを消す。

ただ、上記のシナリオはできれば以下のように分割したい。

>※以下シナリオの入力データはすべて外部INPUT
システムへログインする
部署画面へ遷移する
部署画面で部署データを登録する
社員画面へ遷移する
社員画面で社員データを登録する
システムをログアウトする
メーラを開く
メールを開く
リンクをクリックする
システムへログインする
社員画面へ遷移する
社員画面で社員データを更新する
システムをログアウトする
システムへログインする
社員画面へ遷移する
社員画面で社員データを削除する
部署画面へ遷移する
部署画面で部署データを削除する
システムをログアウトする

整理すると以下のようになる。

>※以下シナリオの入力データはすべて外部INPUT
ログイン・ログアウト
　システムへログインする
　システムをログアウトする
メニュー
　社員画面へ遷移する
　部署画面へ遷移する
社員画面
　社員データを登録する
　社員データを更新する
　社員データを削除する
部署画面
　部署データを登録する
　部署データを削除する
メーラ
　メーラを開く
　メールを開く
　リンクをクリックする

何が言いたいか。

シナリオは使い回すために以下工夫をしましょう。

・シナリオは一連の操作を一括りで作らず、単操作に切り出す
　(単操作を組み合わせて１シナリオを作成するイメージ)
・データは外部INPUTにする

何が良いか。

・テスト全体で見たときの記述量を減らすことが出来る。(冗長的な記述を省くことができる)
・仕様変更による影響を最小限に出来る。
・単画面テストでの自動シナリオを、シナリオテストでも流用できる

#結果 or 気付いた点
手動テストの場合は、一連の動作で頭からお尻までシナリオを記述するため、自動テストでも同様の記述をしてしまいがちだが、上記のような工夫はやはり不可欠に感じる。

#結論
何事もやり方次第
Rakefile 使い方



# 概要

Rakefile に関する説明


# Rakefile とは

commandラインをまとめたもの。Rakefile を起動させることで、複数のcommand を一気に処理してくれるからすごく助かる。僕の研究室では、texのコンパイルに Omakefile を使ってるがそれに似ている。


# Rakefile 中身

task :default dosystem 'rake -T'exitend

desc 'hello NAME'task :hello doname = ARGV[1]puts "Hello #{name}!"exitend

desc 'git pull'task :pull dop comm = "git pull origin main"system commexitend

require 'colorize'desc 'git push'task :push dop comm = "git add -A"system commcomm = "git commit -m 'hoge'"puts comm.greensystem commp comm = "git pull origin main"system commp comm = "git push origin main"system commexitend

-   git の pull や push を自動で行ってくれる。



------
 - **source** ~/grad_members_20f/members/FumiyaToyoda/rake.org
インスタンスストアとは

## 勉強前イメージ

EC2のインスタンスのなにか・・・？
文字的にスポットインスタンス的なイメージだけど全然違いそう

## 調査

### インスタンスストアとは

EC2で利用できる基本的なブロックストレージの1つ
あともう一つはEBSになります
別名、`エフェメラルディスク` とも呼ばれています。
昔はすべてインスタンスストアのみだったらしいです。

### インスタンスストアの特徴

#### 揮発性

揮発性があり、インスタンスをstop するとデータが消えてしまいます
`※ reboot では消えません`
ですので、データの保存場所というより一時置き場としての使い方になります

#### ネットワークの影響を受けにくい

EC2の物理筐体のローカルディスクを使うので、EBSのようにネットワーク間のやりとりがないためネットワークの影響を受けにくい

#### スナップショットや付け替えについて

EBSにある、スナップショットやインスタンスストアの付け替えはできません

#### インスタンスタイプによりサイズ等が決まっている

インスタンスタイプに `d` がついているものがインスタンスストアのものです。

例に出すと、 `c5d` になります。
以下はEC2インスタンスのインスタンスタイプの選択時の画面ですが、
c5d には EBSのみ ではなく、 SSDと記載されていることがわかります。

![インスタンスウィザードを起動 - EC2 Management Console 2020-12-29 01-16-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/5fdc27d4-1f15-8b1c-0d57-e29a51edd502.png)

### EBSとインスタンスストアの違い

#### EBS

- EC2とはネットワークで接続
- EC2とは別で独立して管理されているので、インスタンスがなくなってもEBSは保持される
- EBSの費用は別に発生する

#### インスタンスストア

- EC2インスタンスの物理サーバの内蔵ディスク
- EC2とは分けることができない
- EC2をstopするとデータが揮発する
- 追加費用は発生しない

### ユースケース

EC2インスタンスに
不揮発なEBSをOSブート用とデータ格納用に使用し、
揮発するインスタンスストアは一時ファイル置き場として利用されることが多いのではないかと思います。

![Untitled Diagram.drawio - diagrams.net 2020-12-29 01-32-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/1137a34e-e929-d483-4c51-800d0816a79f.png)


## 勉強後イメージ

EBS以外にも選択肢があったなんて知らなかった...
まぁただ揮発するのに気をつけないといけない。
たしかに、インスタンス選択する際にEBSしかなかったらそもそも表に書かないよねw

## 参考

- [EC2のストレージどう使う? -Instance Storageを理解して高速IOを上手に活用!-](https://www.slideshare.net/imaifactory/ephemeral-ssd)
- [インスタンスストアボリュームをもつインスタンスタイプにおけるWindows ServerのOSバージョンによる初期設定の違いについて](https://blog.serverworks.co.jp/tech/2020/02/21/diff-instancestore-windows/)
- [EC2の揮発性ストレージ「インスタンスストア」を使ってみよう！](https://dev.classmethod.jp/articles/howto-ec2-volatile-block-storage-instance-store/)
- [【AWS】インスタンスストアとEBSの違いとは？](https://qiita.com/satton6987/items/42a4f8c56aa3851120f9)
2つのPCでGitを利用する

Gitを使っていて、複数のPC（家のPCと職場のPCなど）で作業するときの、PCの設定を自分用にメモしておきます。


※`maste` の部分は`main`になる可能性あり

##1つ目のPCでの作業

```Git:Git
$ git init
$ git remote add origin https://github.com/ユーザー名/.git //URLは自分のものに置き換える
$ git checkout -b hoge //ブランチを作成
$ git fetch origin
$ git merge origin/master
$ git add ○○(作成したディレクトリ) 
$ git commit -m"コミットメッセージ"
$ git push -u origin hoge（ブランチ名）
```


##2つ目のPCでの作業
```Git:Git
$ git init
$ git remote add origin https://github.com/ユーザー名/test.git　//URLは自分のものに置き換える
$ git remote add origin/hoge（ブランチ名）
$ git fetch origin
$ git checkout -b hoge origin/hoge
```

```Git;Git
git add . // カレントディレクトリ以下のすべての変更がaddされる。オプションは色々あるので自分に合ったものを探すとよい。
git commit -m"コミットメッセージ"
git push
```


##2回目以降のPC1,PC2共通の作業
自分の作業ブランチに切り替えた後、masterが更新されている場合があるので、最新データの取り込みを実施します。

```Git:Git
$ git checkout hoge
$ git fetch origin
$ git merge origin/hoge
$ git merge origin/master
```

作業後は

```Git:Git
$ git add ○○(作成・編集したディレクトリ)
$ git commit -m"コミットメッセージ"
$ git push
```



##参考サイト様
[二つのPCでGitを利用するときのメモ](https://takidas.com/archives/168#2PC1PC2)
[【GitHub】端末がクラッシュ→別PCから開発を再開しようとしたらgit push出来なかったので対処した](https://qiita.com/terufumi1122/items/152610a1efae1cbc0a33)
メモ：RaspberryPi上のAzure IoTEdgeランタイムの設定


--- 追記　(2021/5/26) -----

IoT Edgeのバージョンが上がりました。
デバイスの設定ファイルが変更になっています。
[公式ドキュメント](https://docs.microsoft.com/ja-jp/azure/iot-edge/how-to-install-iot-edge?view=iotedge-2020-11)を参照してください。

--- 追記　ここまで ----
 
RaspberryPiにインストールしたAzure IoTEdgeランタイムの設定

[インストール編](https://qiita.com/linyixian/items/f0da0df8f5f9cb034988)の続きです。

詳しくは[公式ドキュメント](https://docs.microsoft.com/ja-jp/azure/iot-edge/how-to-manual-provision-symmetric-key?view=iotedge-2018-06&tabs=azure-portal%2Clinux)を参照してください。

#設定編

IoTHubは作成済みとします。

##・デバイスの登録
ポータルを開き、IoTHubに移動します。
左側ペイン内のIoT Edgeをクリックします。
![iotedge01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/9904f6fc-ffa5-2094-5517-9d54ddab1b25.png)

ポータル左上の「IoT Edgeデバイスを追加する」をクリックします。
![iotedge02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/a3a1f2b8-e4c4-3a7b-c6f8-a254ce035128.png)

デバイスIDにデバイス名を入力してから保存ボタンをクリックします。
![iotedge03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/16b23208-5c9a-e3e1-926a-9a26e80cb723.png)

表示されているデバイスIDをクリックします。
![iotedge4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/4604b698-fa65-279c-1521-fd1fbfce762c.png)

プライマリ接続文字列をコピーします。
![iotedge05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/1065d353-dbf2-e0df-9a5e-98efb847672c.png)

##・RaspberryPiでの設定

ターミナルでRaspberryPiに接続します。
エディタでコンフィグファイルに先ほどコピーしたプライマリ接続文字列をペーストします。

```
sudo nano /etc/iotedge/config.yaml
```
![iotedge06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/fadf41ca-3c32-bd17-4c8b-416845bfc2f7.png)

コンフィグファイルを保存し、IoT Edge ランタイムを再起動します。

```
sudo systemctl restart iotedge
```

しばらくしてからステータスを確認します。

```
systemctl status iotedge
```

次のような画面が表示されたら正常に起動しています。
![iotedge07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/366bb5d8-816f-ce86-80d2-71b95f99afad.png)


以上でIoT Edge ランタイムの設定が完了しました。

次はいよいよカスタムモジュールの作成を行います。
LinuxのRaspberry Pi OS（旧：Raspbian）でマイクが認識されなかった。

皆さん、PulseAudioってご存知でしょうか？
GNOMEやKDEとかいうデスクトップ環境でよく使われているサウンドサーバーです。
結構便利で、音の調整とか、出力先の選択も分かりやすく、とても楽になります。
しかし、私の使っているパソコンのマイクが機能しなくなったことに気が付きまして。そこで、いろいろ原因を探ったところ、このPulseAudioに原因があったので備忘録的に記事を作っておこうと思います。
####僕の環境
カーネルのバージョン：4.19.0-8-amd64
Debian GNU/Linux 10
OSをliveUSBで動かしています。

###１．マイクのカードとデバイス番号の確認
```
pi@raspberrypi:~ $ arecord -l
**** ハードウェアデバイス CAPTURE のリスト ****
カード 0: PCH [HDA Intel PCH], デバイス 0: ALC269VB Analog [ALC269VB Analog]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0
```
まず、マイクのカードとデバイス番号を確認します。
上記のように打てば、このような感じで出てくるはずです。
ハードウェアデバイスで、「カード 0,デバイス 0」と書いてあるので、このデバイスは「hw:0,0」
というふうに認識されています（多分）。
###2.load_module行を追加
そして、つぎに「sudo pcmanfm」と打ってファイルマネージャーをroot権限で開きましょう。そして、「/etc/pulse/default.pa」を開きましょう。するとこのような画面になるはずです。
![2020-12-31-002343_1366x768_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915219/7f59be80-78a5-003d-66a5-3043e15fe5e4.png)
この中のどこでもいいので（後でわかりやすいように一番下がおすすめ）次の行を書き込みます。

```
load-module module-alsa-source device=hw:0,0
#the line above should be somewhere before the line below
.ifexists module-udev-detect.so
```
###3.再起動
参照元には、
>最後に、Pulseaudioを再起動して新しい設定を適用します：

とあるのですが、僕の環境ではうまくいかなかったので、rebootしました。
やっぱり、こういうのを更新したあとにやることといえば、とりあえずrebootみたいなところありますよねｗｗｗ


さて、これで晴れて、マイクが機能するようになりました。
これやってもどうにもならない方は、下に参照元のリンク貼っておくんで見てみてください。



まぁでも、やっぱりこういう作業を自分でしないといけないのはめんどくさい反面、問題が解決したときの快感はたまりませんよね。

では、またどこかで！


参照元：[archlinux(linux版wikiみたいなもの)]
(https://wiki.archlinux.jp/index.php/PulseAudio)
mongo-go-driverでBulkUpdateの実装

## 概要
RDBにはだいたいBulkUpdate（一括更新）の機能があるのですが、MongoDBにおいてもその機能が用意されています。こちらの[ドキュメント](https://docs.mongodb.com/manual/core/bulk-write-operations/)にある通り、更新系のクエリをまとめて実行できます。
今回はGolangでupdateのクエリをBulk形式で実行する例を紹介します。

## 対応
[Golang. MongoDB bulkWrite() to update slice of documents](https://stackoverflow.com/questions/58538657/golang-mongodb-bulkwrite-to-update-slice-of-documents)の記事にある通り、mongo-go-driverのcollectionに`BulkWrite`のメソッドが用意されています。BulkWriteの引数に、`mongo.WriteModel`の配列に定義したクエリを設定して実行します。

## 実装サンプル
例題として、更新対象の`_id`と更新後の`status`を保持したstructの配列をbulk実行します。なお、コレクションオブジェクトを取得するための接続の実装は割愛します。

```go:sampleBulkUpdate.go
func SetStatusPosts(request []postModel.PostStatusUpdateRequest) error {
	var operations []mongo.WriteModel
	// 受け取った配列の数分、updateのクエリオブジェクトを作成
	for _, r := range request {
		operation := mongo.NewUpdateOneModel()
		operation.SetFilter(bson.D{{Key: "_id", Value: r.PostID}})
		operation.SetUpdate(bson.D{{Key: "$set", Value: bson.D{{Key: "status", Value: r.Status}}}})
		operation.SetUpsert(false)
		operations = append(operations, operation)
	}
	bulkOption := options.BulkWriteOptions{}
	bulkOption.SetOrdered(true)
	// BulkUpdateの実行。なお、collectionの取得処理は割愛・・・。
	_, err := collection.BulkWrite(context.Background(), operations, &bulkOption)
	if err != nil {
		return nil, err
	}
	return err
}

```
Plastic SCMを使ってみようと思った

# はじめに
要するにですね、GitとSVNを同時に使えたらいいなーっていうのを、Plastic SCMが叶えてくれそうだなーって思ったんですよ。[1つのリポジトリで分散型と集中型を両方使えるよ！](https://unity.com/ja/products/plastic-scm)なんてウリ文句を見ちゃったもんで。
そんじゃあ試すしかないじゃん！ってことで、せっかくの正月休みを使ってそのへんを試してみようと思うわけです。

思いつきでやってるんで、最終的に失敗だったり飽きて更新やめたらごめんなさい。

# なんでそんなことが必要？

ゲームの開発なんかをすると、どうしてもソースコードとデータアセットを同時にバージョン管理したくなる場面に出くわしたりするわけですが、それがまあどうしてもプログラマーとデザイナーの間で求められる機能が異なるわけです。

プログラマーがソースコードを管理するならそれはもうGitがサイコーですよ。タスク単位でブランチを切ってプルリクでコードレビュー後にマージ、なんて実によくできたワークフローだと思うわけです。

デザイナーがアセット管理をするなら、SVNでデザインアセットの履歴管理とロック機能を利用した編集衝突回避ができればもうそれで十分なわけで。Gitのややこしいワークフローなんか知ったこっちゃないのもわかります。理解してもらいたいとは思うものの、それを強要するのも心苦しいと思うのが正直なところ。

そもそもGitはソースコード管理用のツールで大きなバイナリなんかの扱いが苦手。ただ最近GitLFSなんかも出てきて頑張ってる印象はありつつも、個人的にはなんか微妙なんですよね。（LFSを有効にしたリポジトリで謎のエラーが出たりとかして泣きながらもとに戻したりした記憶のせい）

# とりあえずアカウント作ろう

というわけでまあ、まずは[公式サイトに行ってアカウントを作りましょう](https://www.plasticscm.com/)。

[ここのよくある質問](https://unity.com/ja/products/plastic-scm)とか[ここの情報](https://www.plasticscm.com/pricing)を見る限りでは、とりあえず3ユーザーが5GBまで使うぶんには無料で使えるみたいなんで安心してアカウントを作ろうと思います。

というわけで、サイト右上の[TRY NOWをクリック](https://www.plasticscm.com/download/checkout/confirmcheckout)したら。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294857/939c8333-f25b-0625-ad47-c0a013ea43fc.png)
なんか妙にいっぱい入力するところが出てきた……。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294857/372d7f2d-8f99-5b6a-5478-17efe714528d.png)
なんか会社名とか色々入力しないといけないみたい。いや違うんですよ、私はちょっとアカウントつくってちょっと機能を試したいだけなんですよ、と私の心が入力を拒否。Plastic Cloud settingsってなんやねん。

というわけで、心折れた私がトップページに戻り、なんの気無しにTRY NOWの横のSIGN INのボタンをぽちっ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294857/fae1664b-3964-3777-f705-a720e49816a8.png)
そして遷移先で、Don't have an account?と聞かれたので「いえす！」とばかりにSIGN UPボタンをぽちっ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294857/6898213a-71c5-9d3e-1600-fab6136f8843.png)
おおっ？なんかシンプルな感じの登録画面が。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294857/b773ecfb-69d1-dd55-02c9-f49d1215ddee.png)

これならめんどくさがりの私でもちゃんと入力できそうだわ！というわけで、必要な項目を入力。

Unityに買収された影響かUnityアカウントでのログインもできるみたいですね。私はせっかくなのでチェックを入れて、EmailとPasswardのところにUnityのアカウント情報を入力しました。（最初よくわからなくて新しいパスワードを入力して怒られました）

あと困ったのはCompany。今は完全なる個人でお試ししたいと思ってるんだけど、どうしても会社名を入れないとだめなんですかね？　なのでやむなく会社名を入力。
とはいえ入力した会社が存在するかまではチェックしていないと思うので、サークル名とかでも良いのかな？　だめかな？　確認しないとわかりませんね。

なんやかんや一通り入力してSIGN UPボタンをぽちっ。

そうするとアクティベートのメール送ったから見ろ、的な画面が出ます。（キャプチャ忘れました）
私はUnityアカウントと紐付けたので、Unityで使用しているメアドにメールが届きました。

で、メールを見るとこんなかんじ。
メールの上の方にあるACTIVATE HERE YOUR ACCOUNTのリンクをぽちっと押せばアカウント作成完了です、お疲れさまでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294857/9625e3e8-126c-0be8-ec58-09e41e19e6e3.png)
ダッシュボードが開いて、なんか色々できるようになったみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294857/ed3d2a70-b148-d8db-48a9-f49349edbb39.png)

じゃあ次は実際に使ってみようかなーというところで今日はおしまい。

# おわりに
いやあ、Plastic SCMは日本語の情報少ないんですね。ぐぐったらアカウントつくってみましたーみたいな記事出るかなーと思ったらヒットせずですよ。仕方ないんで備忘録ついでに自分で書きました。
まあないってことは不要なだけかもしれませんけども。

# 参考にさせていただいた記事
* [Unity ファミリーに加わった Plastic SCM ってこんなツール](https://qiita.com/hoboaki/items/2678e60e63e77ac2b502)
    * @hoboakiさんのこの記事を見てPlastic SCMを試そうと思った次第であります。