OmniAICreator/Qiita-1.07M huggingface dataset:
JavaでのスレッドとCallableの基本【初心者】

## JavaでのThreadの基本
マルチスレッドを使えば複数処理を並列に走らせたりできる。
こういう処理の一つ一つをスレッドと呼ぶ。
Javaにおいてスレッド処理をするには継承（`extends`）を使う方法とインターフェイスを実装（`implements`）して使う方法がある。
前者の場合は`Thread`クラスを継承して`start()`メソッドを呼び出す。
後者の場合は`Runnable`インターフェイスを実装して`run()`メソッドを呼び出す。
Javaでは多重継承ができないため、`Thread`を使う方法だと他のクラスを継承できないが、インターフェイスを使った方法であれば可能。
後者の場合は`Callable`インターフェイスを実装して`call()`メソッドを呼び出す方法もある。

## RunnableとCallableの違い

`Runnable`の場合は返り値の指定ができず、例外も飛ばせない。

```Java:Runnable_interface
public interface Runnable {
    public abstract void run();
}
```
こんな感じで実装する。`run()`メソッドをoverrideする。

```Java:Runnable_implements
static class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnableだよ");
    }
}
```
`Callable`の場合は返り値の指定ができ、例外を飛ばせる。

```Java:Callable_interface
public interface Callable<V> {
    V call() throws Exception;
}
```
こんな感じで実装する。`call()`メソッドをoverrideする。
<>の部分がジェネリクスと呼ばれる部分で、返り値の型を指定できる。（以下ではString）

```Java:Callable_implements
static class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        String result = "Callableだよ";
        return result;
    }
}
```




## Callableの呼び出し

オブジェクトを作って`Callable`を使ってみたい。

```Java:main
MyCallable myCallable = new MyCallable();
```
ここで`Future`と`ExecutorService`を使うと便利。

```Java:main
// ExecutorServiceインスタンスを生成
ExecutorService executorService = Executors.newSingleThreadExecutor();
// Executorにスレッドの実行を依頼
Future<String> future = executorService.submit(myCallable); 
//結果を取り出すにはget()メソッドを使う
String result = future.get(100, TimeUnit.MILLISECONDS);

```
`ExecutorService`経由で`myCallable`を実行し、結果を`Future`型の変数に格納している。
返り値の型はジェネリクスで指定。上では`String`にしている。
結果は`Future`の`get()`メソッドを使って取り出す。
また、上のように引数を指定することで、0.1秒以上かかった場合に例外を発生させたりできる。

よくわかってない僕からすると、
**「Runnableの時みたいに`myCallable.call()`を直接呼び出すのじゃだめなの？」**
とか思ったりしたのだけど、
`myCallable`の処理は別スレッドで行われるため、処理が終わってから返り値が返ってくるのを待ってなきゃいけないのよね。
`ExucutorService`を使えばちゃんと処理が終わるまで待った上で、返り値を`future`オブジェクト経由で取得可能ということだと思う。（多分）
`Future`っていう名前も未来っぽいし。

## ThreadLocalを使った方法

classのstaticメンバは共有リソースとして管理されるために、別のスレッドから書き換え可能になってしまう。
スレット内で完結させるには`ThreadLocal`を使うと便利。

```Java:main
// ThreadLocalのインスタンスを作成
private final ThreadLocal<ExecutorService> executorServicePool = new ThreadLocal<>();
// SingleThreadExecutorをセットする
executorServicePool.set(Executors.newSingleThreadExecutor());
//結果を取り出すにはget()メソッドを使う
ExecutorService executorService = executorServicePool.get();
```
これでよりスレッドセーフになる。



## 参考にしたページ

- https://blog.toyo999.com/entry/java-thread-callable-future
OWASP ZAP（Mac版）で脆弱性診断してみた

## はじめに
みなさまこんにちは！daimyo404です！
セキュリティ問題が色んなところで起こっている昨今、脆弱性の見直しをしている方も多いのではないでしょうか。

その際、よく脆弱性診断なるものをやっているかと思います。具体的にどんなことをしているのか知りたかったのでやってみたのですが、参考にしたサイトからはGUIが変わってたり、ちょっと手間取ったところもあったのでメモ。

## OWASP ZAPとは
オープンソースのWeb向けのセキュリティスキャナーで、OWASPというコミュニティが提供しています。今回はこれを使って脆弱性診断をやってみます。

## 手順
1. OWASP ZAPをインストール
1. OWASP ZAPの起動、設定
1. FireFoxの設定（プラグイン導入）
1. 診断！！

## 手順１：OWASP ZAPをインストール
[ここ](https://www.zaproxy.org/download/)よりダウンロード（あんまり躓く人も少ないと思うのでサクッとインストール）

## 手順２：OWAPS ZAPの起動、設定
インストールが完了したら、OWASP ZAPを起動します。そして、他のアプリケーションとポートが競合するのを防ぐため、ポートの設定を変更してあげます。

左上のメニューの「ZAP」->「Preference」を押下、オプションの画面が開いたら、左ペインの「ローカル・プロキシ」を押下、ポートを適当に変更して、「OK」を押します。
![スクリーンショット 2021-01-03 3.07.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/f816d016-d173-4aae-f691-b09dc5a110d1.png)

## 手順３：FireFoxの設定（プラグイン導入）
診断にあたり、WebブラウザはFireFox、また、FoxyProxyというプラグインを導入すると、2クリックでプロキシを切り替えできるので、今回はその方法でやります。

まずFireFoxを起動。（インストール未済の方はダウンロードから）右上のハンバーガーマークよりアドオンを押下する。

検索窓があるので、「FoxyProxy Standard」と検索してアドオンを導入。
![スクリーンショット 2021-01-03 3.20.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/619ea529-2429-78e0-5faf-b7b195974d82.png)

アドオンの設定を開く。
![スクリーンショット 2021-01-03 3.21.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/6106f709-465b-3d2c-31cc-23fc707ab105.png)

Addを押す。
![スクリーンショット 2021-01-03 3.24.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/812f628a-ef05-9740-d69a-d999a2c12cb6.png)

タイトルと★マークの箇所を入力してSave（ProxyTypeはHTTP、Usernameとか他のoptionalは空白でOK）
![スクリーンショット 2021-01-03 3.26.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/3e358f7c-b046-a477-729e-aabd7ab03f93.png)

これでサクッとプロキシの変更ができます。
![スクリーンショット 2021-01-03 3.29.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/e3b34932-2a97-9060-de5c-4a87d7b9805e.png)

## 手順４：診断！！
まず初めにモードを**プロテクトモード**にしましょう。
※診断対象以外に影響をさせないために必ず！

![スクリーンショット 2021-01-03 3.34.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/dce93a4f-0808-e57f-7175-f69cecc012aa.png)

ここでおそらく左ペインの「サイト」配下にFireFoxで開いているWebページ（診断対象）が出ていると思うので、対象のサイトを右クリック -> 「コンテキストに含める」->「既定コンテキスト」をクリック。

![スクリーンショット 2021-01-03 3.37.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/d0f3f22e-78b8-8e9f-baf4-cc9e6fb468b0.png)

左ペインの「コンテキストに含める」を押下、診断対象のURLを1クリックして、OKを押下する。

![スクリーンショット 2021-01-03 3.39.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/b99b7a6a-8784-8a29-1082-0e80dcb3301e.png)

またも右クリックして、「攻撃」を押下！！（今回は動的スキャンを実施）
![スクリーンショット 2021-01-03 3.41.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/3b893cf8-92e4-907e-8d19-52b5e66cb0cd.png)

即席のHTMLしか置いてないサイトだったのですが、X-Frameオプションについての診断結果が出てました。
![スクリーンショット 2021-01-03 3.43.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393049/64fc88f7-398e-f9a1-3a03-fff28975ce4c.png)

## 最後に
スクショいっぱい貼り付けたのでやってみてね！

## 参考サイト
[Mac版のOWASP ZAPで脆弱性チェックの設定](https://doruby.jp/users/r357_on_rails/entries/Mac_OWASP_ZAP)
[OWASP ZAPというWebアプリの脆弱性診断ツールの使い方（入門編）](https://kama3.jp/archives/214)
JUCEでAudioプラグインがスタンドアロン起動しているのかどうか確認する方法

自分がプラグインとして動いているのか、スタンドアロン起動しているのか確認したいことがあります。例えば、スタンドアロン時のみAudioのバッファサイズを変更するUIを出すとか。

##前提##
ProjucerでAudioアプリを作っている。

##確認方法##

下記のファイルをincludeする。

```sample.cpp
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
```

下記のようにStandalonePluginHolderのインスタンスを取得し、nullptrでなかったらスタンドアロン。

```sample.cpp
juce::StandalonePluginHolder* holder = juce::StandalonePluginHolder::getInstance();
if (holder != nullptr)
{
    //  スタンドアロン起動
}
```
puppeteerでclick遷移後に例外が発生する場合 Execution context was destroyed, most likely because of a navigation.

puppeteerで`page.click`を実行して画面遷移後に`page.evalute`等を実行すると`UnhandledPromiseRejectionWarning: Error: Execution context was destroyed, most likely because of a navigation.`のような例外が起こる場合がある。

これは`page.click`をawaitしてもページ遷移までは待っていないため、ページ遷移前に遷移前ページの要素にアクセスしてその最中にページ遷移が起こりアクセス中の要素が破壊されてしまい例外となっている。

そのため、`page.click`をawaitするだけでなく、ページ遷移イベントもawaitしなければならない。

```js
    await Promise.all([
        page.waitForNavigation({waitUntil: ['load', 'networkidle2']}),
        page.click('a.user-name')
    ]);
```

参考: https://qiita.com/hnw/items/a07e6b88d95d1656e02f
Ubuntu18.04にNVIDIAドライバをインストールする方法 (備忘録)

NVIDIAからダウンロードしてきた`GeForceドライバ(Ubuntu上でのNVIDIA Driver)`、もしくは`CUDA Toolkit(NVIDIAドライバ含む)`を`runファイル`からインストールする場合、まずカーネルモジュール[nvidia-drm]をアンロードしてXserverを止めろと言ってきてエラーになり必要なNVIDIA Driverがインストールできない。例として`NVIDIA CUDA`(デフォルト設定ではNVIDIA Driverが自動でインストールされるようになっている)のインストール手順を備忘録として書き残します。

CUDA Toolkitからでなく、`GeForceドライバ(Ubuntu上でのNVIDIA Driver)`単体でインストールする場合は次のページがとても参考になります。

[**[ UEFI のセキュアブート機にNVIDIAのドライバを入れる話 ]**](https://qiita.com/arc279/items/99f08b549c95881007b9)
***
OS : Ubuntu 18.04
CUDAバージョン : 11.2
CUDAファイル名(※) : cuda_11.2.0_460.27.04_linux.run

(※)ファイル命名規則 : cuda _ [CUDAバージョン] _ [NVIDIAドライババージョン] _ [OS種別].run

***
手順１ : [NVIDIAのサイト](https://developer.nvidia.com/cuda-downloads)からCUDA Toolkitをダウンロードしておく。

ここでは~/Downloads/ディレクトリにダウンロードしたものとして手順を書きます。

***

手順２ : CUI(マルチユーザー)モードで起動するための前準備１

**<font color="#FF0000">設定を失敗するとログイン画面が表示されなくなる可能性があるため、注意しながら設定してください。</font>**

```bash:bash
$ cd /lib/systemd/system
$ sudo unlink default.target
$ sudo ln -s multi-user.target default.target
```

***
手順３ : CUI(マルチユーザー)モードで起動するための前準備２

```bash:bash
$ ls -l
(↓のようになっていればOK)
lrwxrwxrwx 1 root root 16  1月  3 01:46 default.target -> multi-user.target
```

***
手順４ : 再起動

```bash:bash
$ reboot
```

うまくいっていればCUIモードで起動するので、ユーザー名とパスワードを入力しログインする。
***
手順５ : CUDA Toolkitのインストール

```bash:bash
$ cd ~/Downloads
$ sudo sh cuda_11.2.0_460.27.04_linux.run
```

インストール画面についてはメニュー形式で表示されるため省略します。
(オプションもあるので、必要に応じて選択してください)

ちなみにインストール中、画面が固まったように見えることがありますが、Toolkitのファイルサイズが大きいため、処理に時間がかかっているだけです。放っておけば通常は処理が完了します。
***
手順６ : GUIモードで起動するための前準備１

**<font color="#FF0000">設定を失敗するとログイン画面が表示されなくなる可能性があるため、注意しながら設定してください。</font>**

```bash:bash
$ cd /lib/systemd/system
$ sudo unlink default.target
$ sudo ln -s graphical.target default.target
```

***
手順７ : GUIモードで起動するための前準備２

```bash:bash
$ ls -l
(↓のようになっていればOK)
lrwxrwxrwx 1 root root 16  1月  3 01:46 default.target -> graphical.target
```

***
手順８ : 再起動

```bash:bash
$ reboot
```

***
手順９ : CUDA Toolkitのパスを通す

インストール完了画面に次の２つのディレクトリにパスを通すよう書かれています。
/usr/local/cuda-11.2/lib64
/usr/local/cuda-11.2/bin

ディレクトリに`cuda-11.2`と書くように指定されていますが、`cuda-11.2`ディレクトリに`cuda`というシンボリックリンクが作られているので、以下のexport文のように`~/.bashrc`ファイルに記述すればOKです。

```
export LD_LIBRARY_PATH=/usr/local/cuda/lib64
export PATH=/usr/local/cuda/bin:$PATH
```

さいごに、sourceコマンドで`.bashrc`を読み込み直せば作業は完了です。

```bash:bash
$ source ~/.bashrc
```

***
自分の備忘録なのでざっくりしか書いていませんが、この手順がわからずにNVIDIA DriverやCUDA Toolkitのインストールを諦めている人もいるかもしれないので、少しでも参考になれば幸いです。

***
参考にしたサイト
[CentOS7、Ubuntu 18.04 でGUIログインを無効にするには](https://www.hiro345.net/blogs/hiro345/archives/19697.html)
[UEFI のセキュアブート機にNVIDIAのドライバを入れる話](https://qiita.com/arc279/items/99f08b549c95881007b9)
Floating IP とは

## 勉強前イメージ

EC2インスタンスのIPがどうとかってイメージだけど
なにするかはわからん。

## 調査

### Floating IP とは

AWSのEC2を使ったデザインパターンの一種で、
何らかの理由でEC2インスタンスを停止させたい場合でも停止時間を短くサーバの切り替えができるパターン

### 構成

サーバを落としたいとき、ElasticIPを付け替えることによってEC2インスタンスへのアクセスをなくす。
似たようなやり方でDNSの向き先を変更する方法があるが、TTL値を気にしないといけないしアクセスが0になることはあまりない(TTL値の関係)
ElasticIPを付け替えることでTTL値を気にせずとも別のEC2インスタンスに任せることができる
また、ElasticIPは `AZ(アベイラビリティゾーン)を超えて設定することができる` ので、AZの障害があっても対処することができる

![Untitled Diagram.drawio - diagrams.net 2020-12-29 16-19-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f6e7a7ec-34fc-0f78-a1bd-85eca6c5c380.png)


### 特徴

上でも書いたことがかぶるが・・・

- ElasticIPを付け替えるだけなので、DNSのTTL値に影響されない
- ElasticIPはAZを超えて設定ができる

## 勉強後イメージ

これを機に、デザインパターンというのがあるのを知った。(言葉は知ってたけど)
ちゃんと見てみたらFloating IPだけじゃなくて他にも、こういうときはこういう構成の仕方があるよーって書いてあってすごい勉強になったので他のデザインパターンも見てみます。

## 参考

- [CDP:Floating IPパターン](http://aws.clouddesignpattern.org/index.php/CDP:Floating_IP%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)
- [「クラウドデザインパターン」をAmazonが公開。システム冗長化、突発的トラフィック対応、動的コンテンツ処理など45種類](https://www.publickey1.jp/blog/12/amazon45.html)
- [[AWS SAA対策] ELBなしでEC2のFailover構成 (Floating IPパターン)](https://infraya.work/exam/awssaa_ec2_failover_without_elb/)
- [【AWS】クラウドデザインパターン実践編／仮想IPアドレスによるFloating IPパターン](https://dev.classmethod.jp/articles/aws-cdp-floating-ip-pattern/)
- [【AWS】クラウドデザインパターン -可用性向上](https://qiita.com/AtsushiUemura/items/12d47243c948f1760a2d)
【VR空間サービス Spatial.io】 #2 VRヘッドセットとの紐づけ

#サマリ
VR空間サービスSpatialのアカウントとVRヘッドセットの紐づけ方法をまとめました。
Spatialの対応しているVRヘッドセットはOculusQuest(2)となっているため、本記事はOculusQuestを対象にしています。
VRヘッドセットとの紐づけはブラウザとVRゴーグルを使って行います。

アカウントをまだ作成していない場合は以下のリンクの手順でアカウントを作成しておきましょう。

[【VR空間サービス Spatial.io】 #1アカウントの作り方](https://qiita.com/mayochan32/items/8b6550d7b5005ecba492)

##環境
- Windows 10
- Chrome
- Oculus Quest2
- Spatial 1.9

##目次
1. ブラウザでの操作
1. VRヘッドセットの操作
1. ペアリング

##ブラウザでの操作

- ブラウザでSpatialのページを開きSIGN UPし、ホーム画面の右上にあるVRヘッドセットをかけるアニメーションをしているボタンをクリックする。

![ゴーグル紐づけボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/eed0cb3f-5805-9323-3d35-961c232d33aa.png)

- ヘッドセットのペアリング番号を入力する画面で待機する。

![ヘッドセットペアリング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/8e0f203f-5524-9574-a91d-855044be6dcc.png)

##VRヘッドセットの操作

- Spatialアプリを起動し「New User」をポイントしてトリガーボタンを押す。

![newuser.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/79038148-3bc5-427f-caec-19900e32bafb.png)

- 表示されるペアリング番号を覚える。

![number.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/12d3c712-8031-c178-aee0-9aa12b477d3f.png)

##ペアリング

- ブラウザでペアリング番号を入力する。

![input_number.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/10a16bc9-4cbe-84e0-c18c-9fd44fe263f2.png)

- VRヘッドセットがSpatialアカウントと紐づけられ作成した Room が見えるようになりました。

![room_select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/36ceb2d4-6b03-4e1c-5096-51cb9f3ccf68.png)

#　
チームハイエナ <img width="120" alt="hyaeninae_tomei.png"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/99b448d3-7ff0-58f3-302b-8528cf339b8d.png">
(OutSystems) ローコードでも大丈夫、BATCH処理 !! vol.2

#背景
ローコードプラットフォーム『OutSystems』を社内へ導入・開発サポートしている。
JavaやPythonも楽しいけど、これからの時代はローコード!!

#課題
OutSystemsはWEBは良いけどBATCHがなぁ…という声を度々耳にするが『そんなとこはない、BATCHもローコードで大丈夫』と言いたい。本稿では、OutSystemsでBATCH処理を実現する上での工夫ポイントを紹介する。

想定
・ 数千～数百万レコード単位の処理
・ スケジューラはOutSystemsとは別の何か(Zabbix, Windowsタスクスケジューラ, JP1など)

ポイント
① BATCHアーキテクチャ
　※定時起動, 常時実行, オンデマンドのタイプがあるが、本稿では"定時起動"について記す
② タイムアウト対応
③ コミット制御
④ レスポンス改善
　a) TextDitionaryを活用
　b) コア部分のみ外を活用 (Extention, PL/SQL, Powershell)

#対応
今回は以下について記述する。
② タイムアウト対応
※定時起動, 常時実行, オンデマンドのタイプがあるが、本稿では"定時起動"について記す

#目的
OutSystemsでBATCHを実現する上での一例を紹介し、ローコードに対する懸念をやわらげ、もっと普及させたい。

#内容
タイムアウトは複数考慮する箇所がある点に注意。
(1) IISのコネクションタイムアウト
(2) リバプロを置いている場合は、リバプロサーバのタイムアウト
(3) OutSystems上のAggregate/AdvancedSQLのタイムアウト

------------
(1) IISのリクエストタイムアウト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563944/110c71f8-0c63-3930-ad2d-4e89c5ee0e2c.png)
デフォルトが120sとなっており、120sを超えた時点でREST APIへの通信が遮断される。
バッチ処理として掛かりそうな時間分だけ延ばして置く。
※ただし、WEBのリクエストへ対しても効いてしまうので、注意

------------
(2) リバプロサーバのタイムアウト
システムやデータを社内NETでプロテクトしたい場合は、DMZにリバプロを配置した構成も考えられる。
その場合はリバプロサーバのミドルウェアにおけるタイムアウトも考慮すること。

Apache(参考サイト LinuxMaster.JP様)
https://www.linuxmaster.jp/linux_skill/2013/08/apache-6.html

IIS
本稿(1)参考

------------
(3) OutSystems上のAggregate/AdvancedSQLのタイムアウト
DBアクセス時のSQL処理のタイムアウト時間にも注意を払う必要がある。
BATCH処理では得てして長時間を要するSQLを発行することが多々ある。(大量選択/更新, PL/SQLなど)
その場合は以下DBアクセスWidgetのTimeoutを要件に合せて編集しておくこと。(defaultは120s? Configuration toolでdefaultの変更が可能かも)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563944/37b3119a-5676-1488-d38f-f31ed4f07bc8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563944/4f9dd787-ec3e-6c8f-1ec0-d8e36676a026.png)

#結果 or 気付いた点
タイムアウト時間を考慮することで、処理時間の長いBATCH処理も実現可能になる。
ただし、どちらかといえばなが～いBATCH処理を作るよりも、機能ごとにSTEPで区切り、１つずつSTEPをRESTでコールする作りの方が、運用・メンテナンス面からやりやすいように感じる。

#結論
今回はOutSystems上でBATCH処理を実現するために必要となるTimeout時間の考慮部分を共有した。
まだ続く。
Teradataの起動・停止

#目的
TeradataDBの起動と停止方法

#コマンド
| 内容 | コマンド | 実行例・補足 |
|:-:|:-:|:-:|
| Teradata停止  | tpareset -x [コメント]  | tpareset -x comment  |
| Teradata起動  | service tpa start  |   |
|   |   |   |
#実行例

###Teradata停止
```
TDExpress1620_Sles11:~ # tpareset -x comment

        You are about to shutdown the database
                 on the system
                    'localhost'
        Do you wish to continue (default: n) [y,n] y
```
####状態確認
```
TDExpress1620_Sles11:~ # pdestate -a
PDE state: DOWN/HARDSTOP
```

###Teradata起動
```
TDExpress1620_Sles11:~ # service tpa start
Teradata Database Initiator service is starting...
Teradata Database Initiator service started successfully.
```
####状態確認
```
TDExpress1620_Sles11:~ # pdestate -a
PDE state is RUN/STARTED.
DBS state is 1/4: DBS Startup - Starting PE Partitions
TDExpress1620_Sles11:~ # pdestate -a
PDE state is RUN/STARTED.
DBS state is 5: Logons are enabled - The system is quiescent
```

#参考
[TPA Reset(tpareset) • Teradata Vantage™ - データベース ユーティリティ • リーダー • Teradataドキュメント](https://docs.teradata.com/r/gjXRKe910A9hOE8O2C3Ufw/_VQ7akXHliTTAKx0pqT39w)
[How To Start and Stop Teradata Database - Database Tutorials](https://dbtut.com/index.php/2018/10/27/how-to-start-and-stop-teradata-database/)
[]()
UbuntuにJetBrainsをいれる

# Download Toolbox App
https://www.jetbrains.com/ja-jp/toolbox-app/

ここでダウンロードします。


# jetbrains-toolbox

```
cd ~/Downloads/
sudo tar -xzf jetbrains-toolbox-1.19.7784.tar.gz -C /opt
```

```
cd /opt/jetbrains-toolbox-1.19.7784
nautilus .
```

![Screenshot from 2021-01-03 02-03-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/109aa804-2de7-8d69-5676-6626db62493d.png)

`jetbrains-toolbox`を右クリックして`Run`する。

![Screenshot from 2021-01-03 02-07-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117099/6466ee5f-b207-5e1f-fb27-2ee2e05be8ee.png)

ここで目的のIDEをインストールする。
【3分で終わります】Ubuntu18.04にVS Codeをインストールしようとしたら、思いの外、簡単だった話。

<p>〜本記事を読んで分かること〜<br><br>

Ubuntu18.04（Verは特に関係ないかも？）で<br>
Visual Studio Codeをインストールする方法。<br>
【結論】3分で終わります。<br><br>

今回もいつものごとく、備忘録です。<br>
他にも優良サイトがたくさんあると<br>
思いますので、要チェック。</p>


<h1>手順</h1>
<h3>(1) VS Codeのダウンロード</h3>
<p>まず、はじめにブラウザ（私はChrome）で<br>
「vs code」と検索。<br><br>
おそらく検索２位（2021年1月時点）に出てくる<br>
「Visual Studio Code - Code Editing. Redefined」の<br>
サイトにアクセスします。<br><br>

赤枠で囲っている「.deb」をクリック。<br>
ダウンロードが始まります。</p>


![vscode_install_site.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553432/e3f3867d-4d66-efea-9172-713a42aeac2a.png)


<p>「ヒットしないんだがっ！」って人は<br>
<a href="https://code.visualstudio.com/docs/?dv=linux64_deb">こちら</a>から直接ダウンロードできます。<br><br>
クリックすると、すぐダウンロードが<br>
始まりますのであしからず。</p><br>


<h3>(2) そして、インストール</h3>
<p>ターミナルを開いて、まずダウンロードした<br>
ディレクトリに移動します。<br>
私の場合は、以下のコードを入力。</p>
```
$ cd Downloads/
```

<p><br>
そして、先程ダウンロードしたファイルを<br>
インストールします。<br>
私は「code_1.52.1-1608136922_amd64.deb」<br>
というファイル名でした。<br><br>
なお、続いてパスワードも入力します。</p>
```
$ sudo dpkg -i code_1.52.1-1608136922_amd64.deb
```

<p><br>
インストールが完了しましたら、起動します。</p>
```
$ code
```
<p><br>
以下のような画面が出力されたら、<br>
ちゃんとインストールできています。<br>
やりましたねっ！！<br></p>

![vscode_start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553432/bed26547-3975-c8df-a03f-b341266bcd99.png)


<h1>まとめ</h1>
<p>いかがでしたか？<br>
ちゃんと3分で終わったでしょう？<br>
思いの外、すぐ終わったので軽く<br>
拍子抜けしてしまいました。<br><br>

今回、この記事を書いた理由は、<br>
以前、プログラミングの勉強会に参加したとき<br>
私のチームメンバー全員が<br>
「VS Code使い」だったことがきっかけです。<br><br>

「何のエディタ使えばいいかわからない」<br>
っていう方は、是非使ってみて下さい。<br><br>

以上。最後まで読んでいただき<br>
ありがとうございました！</p>
React(typescript)で外部scriptを遅延ロードする方法


#今回陥った内容の概要

React(typescript)で外部scriptを使用する**だけ**なのだがかなりの時間と調査を要して解決したのでのでナレッジの共有をしたいと思います。
ただベストプラクティスではないと思っており、実装内容も少しレガシーの方法となっております。
今回は外部scriptになるが古いライブラリを使用する場合、React(typescript)ですが、`＠type`に対応していないものを使用する内容となっております。

#今回の用件
- 実装はReactでのSPA
- 外部scriptはbody内に任意の箇所
- headerにはプロパティを追加する外部scriptなし
- innerHtmlはサニタイズを考慮して使用不可
- 外部script内に`document.write`が使用されている()
- 外部script内にさらなる外部scriptが使用されている

#試したアプローチ

##1.scriptタグの生成

`useEffect`で以下のコードを実装

```typescript:logic.tsx
const script = document.createElement("script");
script.asyc = true;
script.src = "url";

const currentElem = document.getElementById("current");
currentElem?.appendChild(script);
```

build結果としては

```html
<div id="current">
    <scirpt async src="url"></script>
</div>
```

っとなってしまいました。

望む結果としては外部scriptの実行結果(`document.write`)が行われDOM要素を生成して欲しいのでこちらでは望む結果とはなりませんでした。


#解決したアプローチ

`postscribe`を使用しました。

```
npm i postscribe
```


ただこちらのライブラリは`@type`が作成されていなさそうなので、

```typescript
import postscribe from "postscribe";
```

ではエディタ上ではErrorとなってしまいます。

そのため、ベストプラクティスではないと思いつつ以下のような実装で対応しました。

```typescript:logic.tsx
// eslint-disable-next-line @typescript-eslint/no-var-requires
const postscribe = require("postscribe");
postscribe(
  "#current",
  "<script src='url'></script>"
);
```

上記実装でbuildを実行しますと

```html

<div id="current">
    <!-- ここに上記外部scriptのdocument.writeで追加されたDOMが追加 -->
</div>

```

となり、任意のコンテンツが表示されました。


#まとめ
今回に関してはこのような対応で実現させました。
実現できた時は安堵の方がかなり多かったですが、個人的には満足いく実装が出来なかったです。
自分以外にも似たような内容で困っている方がいれば一度試してみてはいかがでしょうか？
また、他にもっと良い実装があるよって方は残していただければ試してみようかと思います。
世界一雑な箱根駅伝予想 #1 -箱根駅伝2021往路：予実差-

#1. はじめに

年も明けたということで、お正月の話をしましょう。
お正月といえばそう、箱根駅伝！
今日は箱根駅伝の往路の日でした。1区白鳥くんの粘り、2区レン・タザワの粘り、3区小林くんの粘り、
4区酒井くんの粘り、5区鈴木芽吹くんの粘り…熱いものを感じました。（ただの駒澤ファン）

というわけで、箱根駅伝の予想をデータ分析（と呼ばれるなにか）によって試行、色々試行錯誤してみようという企画になっております。
今回は昨日思い立って、箱根駅伝2021往路の予想をしてみましたので、実績と共にご報告させて頂きます。

#2. 分析方法
後ほど（別記事）詳述させていただければと思いますが、
Kerasによって分析を行っています。


>Kerasは、オープンソースの 深層学習（ディープラーニング） のライブラリです。「ケラス」と読みます。Kerasは、>TensorFlowやCNTK、Theanoといった他の深層学習（ディープラーニング）のライブラリの上部で動くような作りになっており、それらのライブラリよりも、より簡単にモデル（深層学習のネットワーク）を作ることができるよう設計されています。
>-「深層学習のライブラリ！Kerasの使い方【初心者向け】」

#3. 往路結果発表

まずはいきなりの、箱根駅伝2021往路の予想と実績の「結果発表〜！！！」をさせて頂きます。
果たして、創価大の往路優勝、青山学院の失速…を予想できていたのでしょうか。


##1区：結構外した

明治17位、専修20位的中！汗
法政・東海・城西は過小評価、中央・国士舘・山梨学院は過大評価という結果に。
![1区.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/dca6a1cb-f1d3-ab19-23a5-20379d8dba74.png)

##2区：かなり外した

東海8位的中！汗
日体・東洋・創価・順天堂は過小評価、帝京・中央・山梨学院・法政・専修は過大評価という結果に。
中央＆山梨学院の選手、すみません。
![2区.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/48a5c7d0-b3e8-0d67-18b8-ec0e68291e23.png)

##3区：めちゃくちゃ外した

的中なし！涙
順天堂・東京国際は過小評価、城西・学生連合・専修は過大評価という結果に。

![スクリーンショット 2021-01-03 0.39.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/aa2bbe69-d753-0b6f-f363-504752665bb3.png)
##4区：当たる気がせん

的中なし。
創価・早稲田・東洋は過小評価、城西・東海・専修は過大評価という結果に。
![4区.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/cc73b935-5988-eb02-14aa-420289e24ca7.png)
##5区：当たるかぁ！

的中なし。
創価・拓殖・城西は過小評価、早稲田は過大評価という結果に。
![5区.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/91461c7d-341b-d0cc-3d97-45d109897639.png)

##往路総合：創価大おめでとう、駒澤復路も応援してます

![スクリーンショット 2021-01-03 1.11.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/ac566963-09e1-01c3-80e8-79553c8b59c6.png)

#4. つづく
さて、今回は予実の結果のみをご報告させていただきましたが、
つづきものとして、箱根駅伝2021が終わった後も、
箱根駅伝2022の完璧な予測・予想に向けて記事を書いていこうと思います。
どのように予測を行ったのかについては、別記事でご紹介させていただければと思います。（もちろんとんでもなくラフなので、皆様の忌憚のない意見を都度頂ければ幸いです。）

皆様、温かい目で見守っていただければと思います。
明日の復路も是非応援しましょう！
アドベントカレンダー28日目：SREを読んでみた「時系列データからの実践的なアラート」編③

Borgmanは、Borgのモニタリングを行うシステムです。
Borgmanでは、データフォーマットを統一していました。これにより、システム間のオーバーヘッドをなくし、大量のデータを捌くことができるようになりました。
今日からデータの扱い方について、学んでいきます。

## ルールの評価
BorgmanにはBorgmanルールと呼ばれるプログラムコードがあります。それは、単一の時系列データからの履歴に対してクエリを行ったり、多くの時系列データからさまざまなラベルに対して一度にクエリを実行したりできます。

分散環境におけるルールの評価の要は集計です。集計を行うということは、ジョブを全体として扱うために、そのジョブが持つタスク群の時系列データを収集し、その合計を取るということです。
それらの合計から全体のレートを計算することができます。

## アラート
アラートのルールを評価する際に、Borgmanではその結果を真か偽で返します。そして、真の場合、アラートが発行されます。アラートは、真偽の状態が頻繁に切り替わる状態になることがあります。
そのため、ルールにはアラートを発行するまで真であり続けなければならない期間が設定されています。そして、通常ルールの評価を2回行うことで誤りのアラートが発行されることを防ぎます。

## モニタリングのトポロジーのシャーディング
Borgmanは、時系列データを他のBorgmanからインポートすることができます。
一つのBorgmanだけで全社のサービスのデータを収集することもできますが、これはすぐにボトルネックとなります。
なので、ストリーミングプロトコルを用いて、データ転送を行うグローバルなBorgmanがトップレベルに2つ以上置かれます。
また、さらに複雑な環境では、スクレイピングを行うだけのBorgmanやルール評価、ダッシュボードの役割のレイヤーに分けていくこともできます。

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　116-120
E: The repository 'http://ppa.launchpad.net/daniel.pavel/solaar/ubuntu focal Release' does not have a Release file.


```
E: The repository 'http://ppa.launchpad.net/daniel.pavel/solaar/ubuntu focal Release' does not have a Release file.

```

# a recovering method
```
sudo apt-add-repository -r ppa:daniel.pavel/solaar
sudo apt update -q
```

ref: https://askubuntu.com/questions/1054252/the-repository-http-ppa-launchpad-net-armagetronad-dev-ppa-ubuntu-bionic-rele?newreg=a7920fedb49145f2b9577c5f3febc21b
cronをGUIで操作したいのでDkronを入れてみる

# やりたいこと
自分用の便利ツールをcronで実行するケースが増えてきた。
cronでもいいんだけど、WEBでJOBを確認したり、止めたりしたい。
自前のサーバで動作するため、Dockerで動かせたい。
クラスタとか、マルチ構成はやらない。

# Dkronとは
簡単で信頼性の高いCronジョブらしい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81968/07e91bfc-45ce-89ea-64be-ac405c963c6a.png)


[公式TOPページ](https://dkron.io/)

# Install
公式イメージがあるためDockerコマンドで一発起動。
オプションについて
　Webのポートを8080でそのままフォワード
　ジョブ情報は外だししたいのでdkron.dataボリュームをマウント
　マウントしたボリュームをdkronの起動オプション（--data-dir)に設定
　クラスタ構成にしないのでbootstrap-expectは1
　ノード名を付けないとランダム名になりdocker rm dkron → docker run っとすると前回の情報をうまく引き継げないので適当につける(node-name)

```
docker run --name dkron -p 8080:8080 -d -v dkron.data:/dkron.data dkron/dkron agent --server --bootstrap-expect=1  --data-dir=/dkron.data --node-name=node1
```

[公式ガイド](https://dkron.io/basics/installation/)

# Job登録
以下のURLよりダッシュボードへ遷移してJOBを登録する。
昔のdkronは/dashboard がパスだったらしく迷ったのでメモ

http://localhost:8080/ui

もちろんHTTPからAPIつついてもJOB登録可能

```
curl localhost:8080/v1/jobs -XPOST -d '{
  "name": "job1",
  "schedule": "@every 10s",
  "timezone": "Europe/Berlin",
  "owner": "Platform Team",
  "owner_email": "platform@example.com",
  "disabled": false,
  "tags": {
    "server": "true:1"
  },
  "metadata": {
    "user": "12345"
  },
  "concurrency": "allow",
  "executor": "shell",
  "executor_config": {
    "command": "date"
  }
}'

```

# Jobの動作確認
以下のURLより確認する。
先ほどAPIで登録したjob1が10秒ごとに動いてるっぽい。

http://localhost:8080/ui/#/jobs/job1/show/executions

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81968/1af28845-3afc-6dd2-e44a-787c81c534e0.png)

# タイムゾーンの設定
cron起動する場合、タイムゾーンがUTCになっていたので「Asia/Tokyo」にしたい。

## 🙅 だめなやり方
Dockerのrunオプション（ -e TZ=Asia/Tokyo ）ではだめだった

## 🙆 正しいやり方
ホストのlocaltimeをコピってあげればよかった
```
docker cp /etc/localtime dkron:/etc/
```
Windows 10 Insider Preview で Dev channel にすると Dev channel でしかアップデートは得られないので注意

## 背景

2020 年夏あたりに, WSL2 GPU を試したくて, 開発もしつつ普通に業務(e.g. フォトショップとか Office とか使ったりする)で利用している Windows 機で Insider Preview で Dev channel を選んでしまった.

しかし致命的ではないがやはりちょっと不安定なので Dev channel をやめたくなった. 時期製品版リリースに移行できるとあったので beta or release preview channel にした.

数カ月たってもアップデートが降ってこないし, 20H2 の案内も来ない... :cry:

## 安易に Dev channel を選んではいけない
 

https://docs.microsoft.com/en-us/answers/questions/53587/is-there-a-way-to-change-from-the-dev-channel-to-t.html

時期製品リリースへ移行できるのは beta or release preview channel のみになります. :cry:
切り替え自体は UI でできるのでハマってしまいますが,  **Dev channel を選んで Dev channel のビルドをインストールしてしまった場合, その後他の channel へと移行はできません!**

また, **Dev channel で Insider preview をやめる場合は clean install しか手がありません.**

再インストールだとインストールしたアプリやらが消えてしまいますのでためらってしまいます.
(Windows だと, macOS のようにバックアップから移行しなおしというはできるのかしらん?)

したがって, Dev channel を選んでしまったら, dev channel でのみ生きていくしかありません.
時期メジャーリリースへアップデートできる場合も, 製品版ではなくて時期メジャーリリースの dev channel へとしか移行できません.

Insider Preview で Dev channel を選択する場合は注意しましょう.

開発用に Windows 機を分けて運用しようね...
Mac用アプリをpy2appとPython3を使って作ろう！！

#始めに
今回は[前回の記事](https://qiita.com/lot-uni/items/8a9c439eed0a69c6eed8)で作成したpythonのプログラムがあるのですが、風の噂でPythonのアプリ化がpy2appを使うと簡単に出来ると言う事で実際にアプリ化してやろうと言う魂胆です。是非最後までお楽しみ下さいm(_ _)m
✳︎この記事はPython3,Tkinter,pip3がインストールされている前提で話を進めます

#アプリ化するメリットとは？
プログラムを実行するのは簡単なのに何故アプリ化をする必要があるのかと思った人もいるのでは無いでしょうか？僕が考える理由は二つです。その1:アプリ化する事で共有が簡単になる.その2:配布する事が簡単になります。

#アプリ化の手順

##ステップ1
アプリ化するにはプログラムが無いとお話になりません。なのでTkinterを使ったPythonのコードを用意しましょう。よければこれをお使い下さい。ですが、[前回の記事](https://qiita.com/lot-uni/items/8a9c439eed0a69c6eed8)のコメントの方で自分より綺麗なコードを載せてくれている人が居たのでそちらの方が書いた物を参考にすると良いと思います。

```
import tkinter as tk
import random

# ボタンが押された時の処理
def dice(event):
    # ランダムな整数を生成して、labelの内容を書き換える
    value["text"] = random.randint(1,6)


root = tk.Tk()
root.title("Dice.app")
root.geometry('200x150')

value = tk.Label(text="0",font=("",80))
value.pack(fill = 'x', padx=20, side = 'top')

Btn = tk.Button(text='サイコロをふる',width=10)
Btn.bind("<Button-1>", dice)
Btn.pack(fill = 'x', padx=20, side = 'top')


root.mainloop()
```
##ステップ２
appというフォルダを作成して、先ほどプログラムファイルをappの中に入れて下さい。次にterminalを出して次のコマンドを打って下さい

```
pip3 install py2app
```
これでpy2appのインストールは完了です。
次にターミナルでappのフォルダ内に移動して、次のコマンドを打って下さい(diceの部分は自分の保存したファイルの名前にして下さい)

```
py2applet --make-setup dice.py
```
このコマンドでsetup.pyを生成します。

##ステップ３
次にicnsイメージを用意します。このイメージがアプリのアイコンになります。まずは適当な画像を用意します。僕はこの[サイト](https://illust-imt.jp/archives/008620/)の写真を使わせて貰いました。次に[Image2icon](https://apps.apple.com/jp/app/image2icon-%E7%8B%AC%E8%87%AA%E3%81%AE%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86/id992115977?mt=12)と言うアプリをダウンロードして下さい。このアプリでicnsイメージを作成します。
インストールできたらアプリを起動してアイコンにしたい画像をドラックアンドドロップします。その後書き出すのボタンからICNSを選択したら保存場所をappに指定して、ICNSが出来るのを待ちましょう。![スクリーンショット 2021-01-03 0.26.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/ceee0b51-5259-1b15-676c-fb5af91f9f34.png)

##ステップ4
setup.pyを開いて次のように変更して下さい(APPの所は自分の作ったプログラムの名前を、OPTIONSの所はdice.icnsのところは自分のicnsファイルの名前に変更)

```
"""
This is a setup.py script generated by py2applet

Usage:
    python setup.py py2app
"""

from setuptools import setup

APP = ['dice.py']
DATA_FILES = []
OPTIONS = {'iconfile': 'dice.icns'}

setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)
```

最後にterminalでこのコマンドを叩いで終わりです。

```
python3 setup.py py2app
```
これでアプリは完成です。実際のアプリはappフォルダのdistに保存されています！

#最後に
自分はXcodeでのアプリ開発しかやった事しか無かったのでこんなに一瞬でアプリが作れてびっくりしました。
みなさんもぜひアプリを作ってみて下さい！！

✳︎この記事を書いているのはプログラム初心者なので気軽にコメントして下さい

参考サイト:[https://ebi-works.com/python-desktop-app/](https://ebi-works.com/python-desktop-app/)
How to Install Elixir and Phoenix Framework on Ubuntu 21.04 LTS

## Node.js

### check latest
https://github.com/nvm-sh/nvm/releases
2021/7は`v0.38.0`が最新なので`v0.38.0`をインストールする。

### Install nvm

```
export NVM_DIR="$HOME/.nvm" && (
  git clone https://github.com/nvm-sh/nvm.git "$NVM_DIR"
  cd "$NVM_DIR"
  git checkout `git describe --abbrev=0 --tags --match "v[0-9]*" $(git rev-list --tags --max-count=1)`
) && \. "$NVM_DIR/nvm.sh"

```

Now add these lines to your ~/.bashrc, ~/.profile, or ~/.zshrc file to have it automatically sourced upon login: (you may have to add to more than one of the above files)

```
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
```


推奨版を確認する。
https://nodejs.org/ja/

(2021/7時点で推奨版は14.17.3LTS）

```
nvm install 14.17.3
```

## Various installations
### Required for Erlang
https://computingforgeeks.com/how-to-install-latest-erlang-on-ubuntu-linux/

```
sudo apt-get update
sudo apt-get install automake autoconf libreadline-dev libncurses-dev \
libssl-dev libyaml-dev libxslt1-dev libffi-dev libtool unixodbc-dev \
libwxgtk3.0-gtk3-dev libgl1-mesa-dev  libglu1-mesa-dev libssh-dev xsltproc fop \
libxml2-utils

sudo apt-get -y install build-essential libncurses5-dev openssl
sudo apt-get install curl git-core

sudo apt-get install openjdk-15-jdk default-jdk
```

### Required for Phoenix

```
sudo apt-get -y install inotify-tools
```

### Install kerl

```
cd /tmp
sudo curl -O https://raw.githubusercontent.com/kerl/kerl/master/kerl
sudo chmod a+x kerl
sudo mv kerl /usr/local/bin
```

### Install Erlang/OTP

```
kerl list releases
```

```
kerl build 23.3.4.4 23.3.4.4

kerl install 23.3.4.4 ~/erlang/23.3.4.4
```

### Activate Erlang/OTP

```
. ~/erlang/23.3.4.4/activate
echo 'export PATH="$HOME/erlang/23.3.4.4/bin:$PATH"' >> ~/.bashrc
```

### Install kiex

```
cd /tmp
git clone https://github.com/taylor/kiex.git
cd kiex
echo 'export PATH="$HOME/.kiex:$PATH"' >> ~/.bashrc
source ~/.bashrc
./install
source $HOME/.kiex/scripts/kiex
```

```
vi ~/.bashrc
```

```~/.bashrc
source $HOME/.kiex/scripts/kiex
```

を追記します。

### Install elixir

```
kiex list known
kiex install 1.11.4
kiex use 1.11.4 --default
```

## Install Hex and Rebar

```
mix local.hex --force
mix local.rebar --force
```

## Install Phoenix

```
mix archive.install hex phx_new 1.5.7
mix phx.new -v
```



参考:Elixir/Phoenix 初級① 第3版: はじめの一歩 (OIAX BOOKS)
https://www.amazon.co.jp/exec/obidos/ASIN/B01N2K6UBZ/oiax-22/ref=nosim
Rの備忘録(Twitter分析に関すること)

```
//plot()で作図する時に文字化けしにくくなる
par(family= "HiraKakuProN-W3")
```

```
#書籍やブログのコードを参考にするときは、変数名に注意。　
#自分が使っている変数と異なる時があるので

#パイプの変更を変数に代入する
file <- file %>% distinct()

#エラー文で[???でエラー:　オブジェクト'!!!!'がありません]と出てきた時
<- か %>%　に対応していないオブジェクトが含まれているので、
<-　を使用しエラー出たら　%>%　を、
%>%　を使用してエラー出たら　<-　使うと解消する可能性があります。

#特定のX列をカウント
file %>% count(X) %>% arrange(n) %>% tail(999999)

#ファイルの保存方法(csvのところをxlsxにすればxlsxファイルとして保存可能)
#XXXXのところには変数名（データフレイム名）が入ります。
save(XXXX, file="ファイル名.csv")
#列名も残したまま保存できる。（ただし、他の列もそのまま保存する)
write.csv(XXXX, file = "ファイル名.csv", row.names = TRUE)

#行ごと消す方法（今回の例の場合は1,3,6行目を削除）
file <- file[c(-1,-3,-6),]
#連続した行の削除方法(10行目から50行目を削除)
file <- file[-10:-50,]
#連続した列の削除方法(1列目から5列目を削除)
file <- file[,-1:-5]

#列名も残したまま保存できる。（ただし、他の列もそのまま保存する)
write.csv(file, file = "ファイル名3.csv", row.names = TRUE)


```
pyenv + virtualenv + Anaconda を解除

先人の記事からインストールして使うことは出来ましたが、数か月して環境の元に戻し方が分からなくなってしまったので備忘録です。

https://qiita.com/ysdyt/items/5008e607343b940b3480

あれっ、`deactivate`じゃなかったっけ。

**結論**

```
$ pyenv global system
```

## そもそもそれぞれ何だっけ
<dl>
<dt>pyenv</dt><dd>pythonのバージョン毎に環境(pip install)を作成できる。</dd>
<dt>virtualenv</dt><dd>pyenvの拡張。名前を付けた環境（他の環境と同じpythonバージョンでも可）を作成できる。</dd>
</dl>
**pyenv-virtualenv**でセットと考えていいでしょう。

<dl>
<dt>Anaconda</dt><dd>上記セットと同じ（ただし、conda install）</dd>
</dl>

この２つの仮想環境を共存させるのが目的でした。

## その他の仮想環境
<dl>
<dt>venv</dt><dd>Pythonの標準機能</dd>
<dt>pipenv</dt><dd>pip + venv みたいです。</dd>
</dl>
**docker**で環境を分けている人も多いようです。
google検索のトレンドを取得して可視化する

```python


from pytrends.request import TrendReq
import plotly.graph_objects as go
import pandas as pd

pytrend = TrendReq(hl='ja-jp',tz=540)

kw_list = ['ナイキ','アディダス','アシックス','ヒュンメル']

pytrend.build_payload(kw_list=kw_list, timeframe='2020-1-1 2020-12-31', geo="JP")

df = pytrend.interest_over_time()

df.to_csv("./brand.csv")

df = pd.read_csv("./brand.csv", engine="python")

go.Figure(
    [
        go.Scatter(x=df["date"], y=df["ナイキ"], name="ナイキ"),
        go.Scatter(x=df["date"], y=df["アディダス"], name="アディダス"),
        go.Scatter(x=df["date"], y=df["アシックス"], name="アシックス"),
        go.Scatter(x=df["date"], y=df["ヒュンメル"], name="ヒュンメル"),
    ]
)
Firestoreでフォロー機能を作るにはどのようなdb設計をすればいいのか

今回は、`Firestore`を使ってフォロー機能を作る際にどんなdb設計にすればいいのかを紹介します。

Railsなどでフォロー機能を作る方法はいい記事が多く、それらを見ればいいのですが、`NoSQL`でのフォロー機能に関してそんなに記事がなかったので今回記事を書こうと思いました。

ちなみに普通のdbでのフォロー機能の設計でとても参考になる記事を紹介するなら以下の記事です。めちゃくちゃわかりやすいです。

[【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】🎸](https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1)

## フォロー機能の使い道
まず、今回僕が作成したアプリは各ユーザーが記事を投稿できるもので、フォローしたユーザーの投稿が一覧に表示されます。(Twitterみたいな感じです)

## db設計
まず、フォロー機能を作るにしてもユーザーがいないと始まらないので、`users`コレクションがあります。

それから、記事を管理する`posts`コレクションがあります。
ここまでは普通ですね。

ここから本題のフォロー機能なのですが、Firestoreの場合、中間テーブルを作ってリレーションのようなことができません。

そこで、`follows`コレクションをルートの階層(postsやusersと同じ階層)に作成します。

### なぜルートの階層？
ルートの階層に作ると、後々色々なデータのやりとりやがしやすくなったり、`読み取り回数が抑えられたりします。` userのデータのサブコレクションに保存するという方法もありますが、Firestoreではusersコレクションを読み取るたびにそのサブコレクションまで読み取ってしまいます。つまり、フォローの情報が全く関係ない読み取り(例えばuserの名前を表示するだけとか、userのidを取得するだけとか)を行いたいだけなのに、サブコレクションまで取得してしまい、読み取り回数up→コストがかかるということになります。

そこで、ルートの階層に`follows`コレクションを作ることで、`フォローしている`、`フォローされている`といった情報を持たせ、**必要な時に必要な分だけ**データを取得しようといった意図があります。

### dbの中身はどうなっているのか
`follows`コレクションの各ドキュメントの中身は以下のようになります。

| フィールド名| | 
|---|---|
| following_uid |(任意のidなど) |
|  followed_uid|(任意のidなど) |
|id|(任意のidなど)|

- following_uid：フォロー**している人**のuid
- followed_uid：フォロー**されている人**のuid
- id：ドキュメントのidを保存

こんな感じです。これだけではわかりにくいので、例を挙げます。

例えば、`uidが1の人がuid2の人をフォローする`というアクションをするとするなら、followsコレクションに保存されるデータは以下のようになります。

| フィールド名| | 
|---|---|
| following_uid |1|
|  followed_uid|2 |
|id|(任意のidなど)|

`uidが2の人がuid1の人をフォローする`であれば、

| フィールド名| | 
|---|---|
| following_uid |2|
|  followed_uid|1|
|id|(任意のidなど)|

となります。

`フォローするという一つの行動`に対して1つのドキュメントが作成されます。「これって、フォローが起きるたびにデータ増えていくけどどうなの?」と初めは思いましたが、NoSQLはこれが正解っぽい(?)です。

firestoreでの多対多については、以下の記事でわかりやすくメリットデメリットを紹介されています。

[Cloud Firestoreを実践投入するにあたって考えたこと](https://qiita.com/1amageek/items/d606dcee9fbcf21eeec6)

ここまで説明してきたように、rootの階層にfollowsコレクションを作ることで、タイムライン(フォローしてるユーザーの記事が表示される)を作るのであれば、`follows`コレクションからログインしているユーザーのuidを`following_uid`に持つデータを

```javascript 
db.collection("follows")
.where("following_uid", "==", ログインしてるユーザのuid)
```

で取得しておいて、そのfollowed_uidとマッチする投稿を検索して表示するといった感じでできます。(投稿一つ一つにuidを持たせる必要がありますが)

以上です。

## 参考
[【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】🎸](https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1)

[Cloud Firestoreを実践投入するにあたって考えたこと](https://qiita.com/1amageek/items/d606dcee9fbcf21eeec6)

[【Firebase】Cloud Firestoreのデータ構造の決め方をFirebaseの動画から学ぶ](https://qiita.com/shiz/items/5f4c8ae19083ccdd46b2)
[Rails] 1つのフォームから複数のテーブルに情報を保存する

# はじめに

「ユーザー情報」「本」「ジャンル」、の３つの情報を1つのフォームから送信して、
別々のテーブルに保存する機能を**Formオブジェクト**を使って実装する。

具体的に言うと、自分で定義したクラスに、form_withメソッドに対応する機能とバリデーションを行う機能を持たせ、そのクラスのインスタンスメソッドで複数のテーブルへの保存の処理などを行う。

# Formオブジェクト
Formオブジェクトとは、Railsのデザインパターンの１つです。

このデザインパターンは、「1つのフォーム送信で複数のモデルを操作したい場合」や、
「テーブルに保存しない情報に対するバリデーションを行いたい場合」に使います。
元々modelにバリデーション等様々な処理が書かれているものを、form層に切り出すことで多くのmodelで同一の処理を使えるということです。

---
#実装
form層に切り出すモデルファイル
にinclude 「ActiveModel::Model」 と 「attr_accessor」 を設定する

```user_book.rb
class UserBook
  include ActiveModel::Model
  attr_accessor :nickname, :age, :gender, :book_title, :genre

end
```

# ○ActiveModel::Model
あるクラスにActiveModel::Modelをincludeすると、そのクラスのインスタンスはActiveRecordを継承したクラスのインスタンスと同様に form_with や render などのヘルパーメソッドの引数として扱えたり、バリデーションの機能が使えるようになります。
Formオブジェクトパターンを実装するためにActiveModel::Modelをincludeしたクラスのことを「Formオブジェクト」と呼ぶこともあります。

# ○attr_accessor
記述したクラスに、ゲッターとセッターを定義してくれるメソッドです。与えられた引数をもとに属性を設定し、これを取得するメソッド（ゲッター）と更新するメソッド（セッター）を定義してくれます。

・値の取得ができるメソッドの定義（ゲッター）
・値の更新ができるメソッドの定義（セッター）

今回のフォームで利用する全ての属性(つまり、保存したい各テーブルのカラム名全て)についてゲッターとセッターを定義することで、このFormオブジェクトのインスタンスを生成した際にform_withの引数として利用できるようになります。

# ○切り出す処理を記述

```user_book.rb
class UserBook
  include ActiveModel::Model
  attr_accessor :nickname, :age, :gender, :book_title, :genre

  with_options presence: true do
    validates :nickname
    validates :age
    validates :genre
  end

  def save
    user = User.create(nickname: nickname, age: age, gender: gender)
    Book.create(book_title: book_title, user_id: user.id)
    Genre.create(genre: genre, user_id: user.id)
  end
end
```
設定したいバリデーション全てと、
def save ~ end 内では
フォームからパラメーターとして送られてきた情報をテーブルに保存する処理を書いています。
※Book・Genreオブジェクトでどのユーザーと結びついているのかを保存したいので、
ユーザー情報をuserに代入して、user_idカラムにuser.idで取得した１人のユーザー情報を保存させています。

# ○Formオブジェクトのインスタンスを生成
フォームから送られてきた全ての情報をハッシュ形式に整形するbook_paramsを定義し、
createアクションでこれを呼び出してUserBookクラスのインスタンスを作成することに利用しています。



```books_controller.rb
class BooksController < ApplicationController
  def index
  end

  def new
    @user_book = UserBook.new
  end

  def create
    @user_book = UserBook.new(book_params)
      if @user_book.valid?
        @user_book.save
        redirect_to action: :index
      else
        render action: :new
      end
  end

  private
  
  def book_params
    params.require(:user_book).permit(:nickname, :age, :gender, :book_title, :genre)
  end
end
```

# ○Formオブジェクトのインスタンスを引数として渡す
new.html.erbのform_withメソッドに、作成したFormオブジェクトのインスタンスを引数として渡し、入力した情報がMVCを通って処理されるようにします。

```ruby:app/views/books/new.html.erb
<%= form_with(model: @user_book, url: donations_path, local: true) do |form| %>
  <%= render 'error_messages', model: @user_book %>

  # フォーム内容

<% end %>
```
---
この記事は下記を参考させていただいております。
https://product-development.io/posts/rails-design-pattern-form-objects
FactoryBotで外部キーを使用する場合のやり方　〜別解

#はじめに
　先日、外部キーの値をFactoryBotで使い場合の投稿をしました。その後も調べていると、別の方法もあったので、紹介します。なんなら、こっちの方が簡単です。
[FactoryBot、外部キーバリデーションで弾かれたときの解決方法](https://qiita.com/TerToEer_sho/items/a2973d05c1de6eba2b6a)

##前回の方法
```ruby
FactoryBot.define do
  factory :user do
    Faker::Config.locale = :ja
    room { FactoryBot.create(:room) } #ポイントはここ
    email { Faker::Internet.free_email }
    nickname { Faker::Name.last_name }
    password = Faker::Internet.password(min_length: 6)
    password { password }
    password_confirmation { password }
  end
end
```

##アソシエーションを使った方法

```ruby
FactoryBot.define do
  factory :user do
    Faker::Config.locale = :ja
    #roomのFakerを削除
    email { Faker::Internet.free_email }
    nickname { Faker::Name.last_name }
    password = Faker::Internet.password(min_length: 6)
    password { password }
    password_confirmation { password }
    
    association :room #←追記

  end
end
```

モデルにアソシエーションを記述するときのように
`association :外部キーのモデル名`
とするだけです。

##まとめ
外部キーをFactoryBotを使用する場合は、素直に`association :外部キーのモデル名`とすると、勝手に外部キーと紐付けてテスト用の情報を生成してくれます。
Linuxコマンド入門 ~LS-DYNA編~

自分がLinuxクラスターでLS-DYNAのファイルを編集・実行するときによく使用するコマンドをまとめました。

##目次
1. [更新ファイルの確認](#1-更新ファイルの確認)
2. [過去のコマンドの再利用](#2-過去のコマンドの再利用)
3. [LS-DYNAのエラーの検索](https://qiita.com/hiroshi6318/items/028eb1b44d5941b13e00#3-ls-dyna%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AE%E6%A4%9C%E7%B4%A2)
4. [ある単語がどのファイルに含まれているかの検索](#4-contactという単語がどのkeyファイルに含まれるかの検索)
5. [Linuxキーバインド(ショートカットキー)](https://qiita.com/hiroshi6318/items/028eb1b44d5941b13e00#5-linux%E3%82%AD%E3%83%BC%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89)
6. [その他 (chmod/touch/mkdir/cp/mv/vi)](#6-他のよく使用するコマンド)

##1. 更新ファイルの確認

```console
ls -trl  
```

- ファイルの更新履歴を一行ごとにlong formatで、**下側が最新の履歴**となるように表示します。
- LS_DYNAを回すとき、このコマンドでglstat, binout, d3plotファイルが更新有無を確認して、解析が回りだしたかを確認しています。


>[補足]
> `-l` : long formatで一行ごとにファイルを表示
> `-r` : 表示を逆順に
> `-t` : 更新順にファイルを表示(リストの一番上が最新-> -rで一番下を最新ファイルに)  

- `alias lt='ls -trl'`を.bashrcに登録しておくと便利です。`lt`で`ls -trl`と同じことができます  
    - エイリアスについては@_ydahさんの記事を参照しました。[【Linux】エイリアスの設定方法](https://qiita.com/_ydah/items/18d242b632e5486fe912)

### (おまけ)よく使うlsコマンドのオプション
- `-F`: ファイル種別の表示
    - ファイル・ディレクトリが`dir/` `run@` `exe*`のように、ディレクトリの後に記号がついた状態で表示される。
 
|記号|意味|
|:-:|---|
|/|ディレクトリ|
|@|シンボリックリンク|
|*|実行可能ファイル<br>(実行可能パーミッションがあるファイル)|
|記号無し|通常ファイル|

- `-a`: 隠しファイルを含めたすべてのファイルを表示



##2. 過去のコマンドの再利用
```console
history | grep hogehoge
```
- 上記は*hogehoge*を含む過去のコマンドの履歴一覧を表示する
- 自分が使用しているクラスターは、`qsub -W denendancy=any:hogehoge`のように長いコマンドがあって思い出せないことがあるので、よく使用します。

上記のコマンド後、history一覧で

```console
>594: qsub -W hogehoge
```

のように表示されます。
その後、下記のようにコマンドを打てばそのコマンドを実行できます。

```console
!594
```


##3. LS-DYNAのエラーの検索

```console
grep -i error mes* log
```  
 - mes*とlogファイル内に"error"(大文字小文字の区別なし)という言葉が含まれている場合、そのファイル名を表示。  
 
> `-i`: 大文字小文字の区別なし  
`*`: ワイルドカード

```console
tail -n 15 mes* log d3hsp| less
```
- *mes\* log d3hps*ファイルの最後の15行を見て、それをlessに表示


##4. contactという単語がどのkeyファイルに含まれるかの検索
```none
find . -name ".key"
grep -i *contact '!!'
```
1つ目のコマンドで、現在のディレクトリ**以下**の*.key*ファイルの一覧を取得する。
2つ目のコマンドは1つ目で得たファイル一覧の中から、"contact"という単語を含む部分を返します。
`'!!'`はひとつ前のコマンドを指します。

多分、下記のコマンドで同じことができる。

```none
find . -name "*.key" | xargs grep -l -i 'contact'
```

## 5. Linuxキーバインド
- `ctrl + a`: 現在のコマンドの最初にカーソルを移動
- `ctrl + k`: 現在のカーソル位置(点滅している個所)から後を削除
    - ctrl + a -> ctrl + kで現在書いているコマンドを全消去
- `ctrl + d`: 現在のカーソル位置の文字の削除
- `ctrl + l`: ターミナルの表示を整頓
    - 現在のコマンドラインがターミナルの一番上に移動。

## 6. 他のよく使用するコマンド
####パーミッション
- `chmod 777 MPP.sh` : MPP.shにパーミッションを付与(実行・書込・読込)  

#### ファイル作成　　
- `touch d3kil` : 空ファイル`d3kil`をカレントディレクトリ(cd)に作成
- `mkdir TEST`: TESTディレクトリをcdに作成
- `cp -r hogedir hogedir2`　: hogedirをhogedir2としてディレクトリの中身ごとコピー  

#### ファイル編集
- `mv log log_old` : logファイル(拡張子無)の名前をlog_oldに変更
- `vi fugafuga.key` : vimで`fugafuga.key`を開く
    - vimのコマンドについては、[こちらの記事 ~vimコマンド覚書き~](https://qiita.com/hiroshi6318/items/bc453c991958ffd3762f)にまとめました。
CodeIgniter4でREST APIを実装する

CodeIgniterに入門した。CodeIgniter4の公式Tutorialをやった後、REST APIの実装を試みた。調べてみると、CodeIgniteでREST APIを実装するなら、Rest_Controllerらしい。composerでインストールしてみたが、動かず。

結論、RestControllerはCodeIgntier3用。CodeIgniter4はサポートしていない。

CodeIgniter4にはResourceControllerなるREST API用のControllerが標準で用意されているので、そっちを使うべしということだと思われる。

詳しい説明を書いてくださっている[サイト](http://blog.a-way-out.net/blog/2020/12/20/codeigniter4-rest-api/)を発見。

# 参考にしたサイト
 - [CodeIgniter4の公式Tutorial](./https://codeigniter.com/user_guide/tutorial/index.html)
 - [CodeIgniter RestServer](https://github.com/chriskacerguis/codeigniter-restserver)
 - [CodeIgniter4の公式マニュアル RESTful Resource Handling](https://codeigniter.com/user_guide/incoming/restful.html)
 - [CodeIgniter4でREST APIを作成する](http://blog.a-way-out.net/blog/2020/12/20/codeigniter4-rest-api/)

# CodeIgniter3 + Rest_Controllerのメモ
## インストール方法
CodeIgntier3でRest_Controllerを使ったREST API実装を試す場合、下記の手順が最短。
application/controllers/Example.phpにREST APIのサンプル実装コードがインストールされるので、このコードをベースに機能を追加してみるのが良い。

```
$ composer create-project kenjis/codeigniter-composer-installer codeigniter
$ cd codeigniter
$ php bin/install.php restserver 2.7.2
$ ./bin/server.sh
$ curl http://localhost:8000/api/example/users
```

# REST_Controllerがしてくれること
REST_Controllerを使うと、route.phpにHTTP Method x URLの組み合わせ分のルーティングを書かなくてもよくなる。ルールに従った名前でメソッドを用意すれば、自動的にルーティングしてくれる。
例えば、Api.phpというファイルにApiクラスを実装。Apiクラスにnews_post()メソッドを実装しておく。すると、POST /api/newsでアクセスされた時にはそのメソッドが実行されるようになる。news_get()メソッドを用意しておくと、GET /api/newsおよび、GET /api/news/id/{id}で実行されるようになる。news_get()メソッドには前者用に全てのレコードを応答する処理を、後者用に指定されたidのレコードを応答する処理を実装しておく。
リソースのURLとして、/api/news/id/{id}ではなく、/api/news/id/{id}を使いたい場合の方が多いかもしれない。そのときは、route.phpにルールを追加しておく。

```
$route['api/news/(:newsid)'] = 'api/users/$1'; 
```
リモートデスクトップで音が出なくなった時

## 概要

リモートデスクトップ接続で最初はremoteの音が出ていたのに、
クライアントがsleep後などに音が出なくなった時の対処法

## 環境

client : windows10 1909
remote : windows10 1909

## 対処法

1. remote側のwindowsの検索で「service」と入力
1. 「サービス」アプリをダブルクリック
1. 「Windows Audio」を選択し、サービスの再起動

## 参考

https://superuser.com/questions/1213547/windows-10-remote-desktop-sound-drive-redirection-not-working
[JavaScript] trim()メソッドは文字列両端の改行文字 \n や \r を削除する。

String.trim()メソッドは文字列両端の`空白`を削除する。

この`空白`は、文字通りの空白であるスペースやタブだけでなく、改行文字`\r`, `\n`, `\r\n`も含む。

```JavaScript

const memo = 'とんこつラーメンか、\r\n醤油とんこつラーメンで';


const array1 = memo.split('\r')
console.log(array1);
// [ 'とんこつラーメンか、', '\n醤油とんこつラーメンで' ]


const array2 = memo.split('\n').map(m => m.trim())
console.log(array2);
// [ 'とんこつラーメンか、', '醤油とんこつラーメンで' ]


const array3 = memo.split('\r').map(m => m.trim())
console.log(array3);
// [ 'とんこつラーメンか、', '醤油とんこつラーメンで' ]


const array4 = memo.split('、').map(m => m.trim())
console.log(array4);
// [ 'とんこつラーメンか', '醤油とんこつラーメンで' ]  

```
[Node.js] macで環境構築をしよう

#環境
macOS Catalina バージョン　10.15.7

#nodebrewをインストール

```
$ curl -L git.io/nodebrew | perl - setup
```

上記のコマンドを実行するとターミナル上に以下のように表示されます。

```
========================================
Export a path to nodebrew:

export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================
```

ターミナル上の `export PATH=$HOME/.nodebrew/current/bin:$PATH` のコマンドをコピーして、もう一度貼り付けてエンターキーで実行してください。

```
$ export PATH=$HOME/.nodebrew/current/bin:$PATH
```

インストールに成功しているかを確認しましょう。

```
$ nodebrew -v
```

`nodebrew use [バージョン名]` と表示されたら成功です。


#Node.jsのインストール

```
$ node -v
```

コマンドを実行し、バージョンが表示された場合はすでにNode.jsがインストールされています。
`command not found: node` と表示された場合はまだNode.jsがインストールされていませんのでインストールしていきます。

インストールする際のコマンドはいくつかありますが、今回は　`もっとも新しいバージョンかつ安定版` を意味する　`stable`　のバージョンをインストールしていきます。

```
$ nodebrew install-binary stable
```

次にインストールしたバージョンを使えるようにするコマンドを実行します。
`nodebrew use 任意のバージョン名` を実行します。今回は`stable`　のバージョンが `v14.15.3` なので以下のようになります。

```
$ nodebrew use v14.15.3
```

インストールに成功しているかを確認しましょう。

```
$ nodebrew ls
```

コマンドを実行して以下のように使いたいバージョンが `current: 任意のバージョン名` と表示されていれば成功です。

```
v14.15.3
v15.5.0

current: v14.15.3
```


Node.jsで新規アプリケーションの製作方法は以下で詳しく説明しています。
https://qiita.com/momo1010/items/5430668b7eb1ac47d2e0
SVGをPDFとPNGへ変換する方法【Python】

はじめまして、ますみです！

[![自己紹介.png](https://www.umi-mori.jp/wp-content/uploads/2023/02/introduction_banner_2-2048x533.png)](https://bit.ly/banner_intro_masumi_creator_qiita)


本記事では、SVGをPNGに変換する方法を紹介します。
[`CairoSVG`](https://cairosvg.org/)を試してみたのですが、[`svglib`](https://pypi.org/project/svglib/)の方が簡単に変換できることに気づいたため、その手法を紹介します。

# 実行環境 / Requirement
- macOS Catalina (v10.15.7)
- Python v3.6.5
- pip 20.3.3

# 実行手法 / Usage
## 1. svglibのインストール
まず`pip install svglib`を実行して、svglibをインストールしましょう。

## 2. Pythonファイルの作成
次に、以下のようなPythonファイルを作成しましょう。

```python:svg2png.py
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF, renderPM
import sys
import os

args = sys.argv
filename = args[1]
filename_without_ext = os.path.splitext(os.path.basename(filename))[0]

drawing = svg2rlg(filename)
renderPDF.drawToFile(drawing, filename_without_ext + ".pdf")
drawing = svg2rlg(filename)
renderPM.drawToFile(drawing, filename_without_ext + ".png", fmt="PNG")
```

## 3. コマンドの実行
Terminalやコマンドプロンプトなどを開き、以下のようにSVGファイルを指定して、実行します。

```shell:
python svg2png.py sample.svg
```

以下のようにPNGとPDFファイルが生成されれば、変換成功です！
![shell_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240280/fa849e7e-2084-fca8-98b7-6535bc37d946.png)

# GitHubリポジトリの紹介
Githubにもレポジトリを作成したため、もし良ければこちらもご利用くださいm(_ _)m
https://github.com/Masumi-M/svg2png

# 最後に
最後まで読んでくださり、ありがとうございました！
いかがだったでしょうか？

この記事を通して、少しでもあなたの学びに役立てば幸いです！

:::note info
【仕事の相談はこちら】
お仕事の相談のある方は、下記のフォームよりお気軽にご相談ください。

[問い合わせフォームはこちら](https://forms.gle/G5g1SJ7BBZw7oXYA7)

もしもメールでの問い合わせの方がよろしければ、下記のメールアドレスへご連絡ください。

info*galirage.com（*を@に変えてご送付ください）

🎁 「生成AI活用の無料相談券」もしくは「生成AIの社内ガイドライン（無料PDF）」を『公式LINE』で配布中 🎁
『生成AIを業務に活用したいけど、どうしたらいいかわからない』といった声を多くいただきます。

Galirageでは公式LINEにて、チャットやオンライン会議で「完全個別の生成AI活用無料相談会」を実施しております！
（期間限定で実施しているため、ご興味ある方はお早めに以下のLINE公式アカウントをご登録ください^^）
https://lin.ee/rvz6lMN

※ 予告なく、キャンペーンを終了する可能性がございますが、ご了承ください。

【業務内容】
具体的には、以下のお仕事を中心に受け付けております！（[詳しくはこちら](https://galirage.notion.site/Galirage-AI-c2f3945fafb0433d8d2fd03e56927fd8)）
1. 受託開発（例：生成AIを使った社内システムの開発）
2. コンサルティング（例：技術戦略のアドバイス）
3. 講演（例：社内研修、イベント登壇）

※ 特に「生成AIを使ったシステム開発のご依頼」が多く、ご好評いただいております。

【これまでの相談事例】
以下のようなご相談が多くあります。

🔑 機密情報を漏洩させないための、生成AIのシステム構築をお願いしたい。
🤖 自社データを用いたFAQチャットボットの作り方を知りたい。
💡 ChatGPTを、自分たちの事業にどのように活かせるか、アドバイスやアイデアが欲しい。
:::
# おまけ
エンジニアの仲間（データサイエンティストも含む）を増やしたいため、公式LINEを始めました🎉

「**一緒に仕事をしてくれる方**」「**友だちとして仲良くしてくれる方**」は、友だち追加をしていただけますと嬉しいです！（仲良くなった人たちを集めて、「ボードゲーム会」や「ハッカソン」や「もくもく会」もやりたいなと考えています😆）

とはいえ、みなさんにもメリットがないと申し訳ないので、特典を用意しました！

友だち追加後に、アンケートに回答してくれた方へ「**エンジニア図鑑（職種20選）**」のPDFをお送りします◎

https://lin.ee/hFUN4TL

[![](https://www.umi-mori.jp/wp-content/uploads/2023/10/line_banner_v2.png)](https://lin.ee/hFUN4TL)