OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScript勉強日記#2

①条件式を三択以上で使用したい

```
 const answer = window.prompt('ヘルプを見ますか？');
  if(answer === 'yes') {
    window.alert('タップでジャンプ、障害物をよけます。');
  } else if(answer === 'no') {
    window.alert('ゲームを起動中...');
  } else {
    window.alert('yesかnoでお答えください。');
  }
```
基本的にelseとifを組み合わせるだけで何択でも大丈夫そうです。

②数当てゲーム

```
const number = Math.floor(Math.random() * 6);
const answer = parseInt(window.prompt('数当てゲームです。0~5の数字を入力してください。'));
let message;
if(answer === number) {
  message = '当たり！'
} else if(answer < number) {
  message = '残念でした！もっと大きい';
} else if(answer > number) {
  message = '残念でした！もっと小さい';
} else {
  message = '0~5の数字を入力してね。';
}
window.alert(message);
```

使用したのは`Math.floor(Math.random() * x)`と`parseInt(window.prompt())`
前者は0~(x-1)の整数をランダムに代入する為のコードで、後者は文字列(window~)を数値に変換する為のコードです。
条件式で変数messageに代入する値を決めて最後に表示するといった流れになります。

③時間毎に異なるメッセージを表示

```
const hour = new Date().getHours();

if(hour >= 19 && hour < 21) {
  window.alert('お弁当30%OFF！');
} else if(hour === 9 || hour ===15) {
  window.alert('お弁当一個買ったら一個おまけ！');
} else {
  window.alert('お弁当はいかがですか');
}
```

使用したのは`new Date().getHours()`、`演算子&&と||`です。
現段階では`.getHours()はページを開いた時刻を24時間時計で取得する`くらいに捉えています。
演算子&&はドモルガンの法則のA∩Bで、`複数の条件全てに当てはまった時True`になります。
演算子||はA∪Bで、`複数の条件のうち一つ以上当てはまった時True`になります。
FortiGate の非対称ルーティング

# FortiGate の非対称ルーティング

## 非対称ルーティングとは


``行きのパケット``と``帰りのパケット``が異なる経路（L3機器）を通る通信のこと。
Firewall は通信のセッション管理を行っており、``非対称ルーティング``とは相性が悪い。
例えば行きのパケットが無いのに、帰りのパケットだけ来ても通信の整合性が合わなくなり許可すべき通信か判断できない。また通信の内容を見てセキュリティチェックを行うUTM機能も不能となる。
場合によっては、PINGは通るがTCP通信ができないこともある。これはTCPのほうがステートフルな通信を行っていることからチェックが厳しくなるためである。よって疎通確認はPINGだけに頼らず、できる限りTCPによる確認も行うべきである。

## NG なケース

下図のように、「行き」はLANインターフェースからDMZインターフェースを通ってサーバーに到着するが、「帰り」はサーバーから直接LAN側のPCと通信をしてFortiGateを通らないパターン。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/6967120d-f93f-3b4e-55c6-e9f261099ee7.png)

このようにFortiGateで異なるインターフェース間を通る通信で、「行き」または「帰り」のいずれかの通信がFortiGateを通らないとFortiGateは次に続くパケットをブロックし通信ができなくなります。

### 回避策

- FortiGateのポリシーで LAN -> DMZ の通信をNATにする。送信元IPがFortiGateとなり、帰りのパケットもFortiGateに向かう。
- Webサーバーへの通信はLAN側のIP宛で行う。
- FortiGateで非対称ルーティングを許可する。（非推奨）<a href="">set asymroute enable</a>


## OK なケース

非対称ルーティングでも通信ができる場合があります。
それはFortiGateのインターフェース間通信が発生しない場合です。
下図はLANインターフェースで受けたパケットが、同じLANインターフェースから出ていくだけなので、FortiGateとしてはセッション管理をする必要がないため、OK となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/fe9bbde8-a31c-4ed6-5115-c864240a3627.png)


### ICMP Redirectについて

FortiGateはデフォルトでICMP Redirectが有効になっており、本ケースでは最初のパケットのみFortiGateを経由し、以降のパケットは直接ルータを通るため、``非対称ルーティングは最初のパケットのみ``となります。
もしかするとICMP Redirectによって非対称ルーティングでもたまたま通信できているだけかもしれないので、FortiGateのICMP Redirectを無効にして検証してみました。
結果は変わらずTCPでも通信できていたので、``ICMP Redirectの影響``はないことがわかりました。
Python3: Google Cloud Translation API の使い方 (Advanced)

次のページを参考にしました。
[テキストの翻訳（Advanced）](https://cloud.google.com/translate/docs/advanced/translating-text-v3)

```py:ex02.py
#! /usr/bin/python
#
#	ex02.py
#
#						Nov/25/2020
#
# ------------------------------------------------------------------
import sys
from google.cloud import translate

# ------------------------------------------------------------------
def translate_text(text,project_id):
	"""Translating Text."""

	client = translate.TranslationServiceClient()
	location = "global"

	parent = "projects/" + project_id + "/locations/" + location

	response = client.translate_text(
			parent=parent,
			contents=[text],
			mime_type='text/plain',
			source_language_code='de',
			target_language_code='ja')

	for translation in response.translations:
		print("Translated text: {}".format(translation.translated_text))

#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
project_id = "project-translation"
text="Es war einmal ein kleines Mädchen."
translate_text(text, project_id)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

 実行方法

```bash
export GOOGLE_APPLICATION_CREDENTIALS=./***.json
#
./ex02.py
```

実行結果

```text
*** 開始 ***
Translated text: 昔々、小さな女の子がいました。
*** 終了 ***
```

GOOGLE_APPLICATION_CREDENTIALS の作成方法
>認証情報 --> サービスアカウントを管理 --> サービスアカウントを作成
![service_account_feb13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/318b82d5-d23c-2bcc-8e7a-cc0771d5e973.png)
FlutterのImagePickerでapp storeにリジェクトされた件。

#ストアから以下のリジェクトをくらいました。
Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage


We noticed that your app requests the user’s consent to access the camera and photos, but doesn’t sufficiently explain the use of the camera and photos in the purpose string.

To help users make informed decisions about how their data is used, all permission request alerts need to specify how your app will use the requested information.

Next Steps

Please revise the relevant purpose string in your app’s Info.plist file to specify why your app needs access to the user's camera and photos. Make sure the purpose string includes an example of how the user's data will be used.

You can modify your app's Info.plist file using the property list editor in Xcode.


#原因と対策
下記ページを参考にImagePickerを導入してたのですが、
https://makulogsleep.com/flutter-image-store

下の部分をそのままInfo.plistに貼り付けてたら、「簡単すぎてわからんわ！」とお叱りを受けました。
![スクリーンショット 2020-11-25 13.09.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/947355e1-3076-8499-ab9c-9ec1a278f4d6.png)

<string>タグの中身を、具体的に「画像データをどう使うのか」と書き直したらOKでした。

#ちなみに、どこで使われるのか。
以下のように、「カメラへのアクセスを求めています」の下に使われます。
![スクリーンショット 2020-11-25 13.14.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/ba13cf80-f2a0-24ea-fba1-f3674e09e6e8.png)
ServiceNow - JavaオブジェクトとJavaScriptオブジェクト

#概要
ServiceNow本体はJavaで書かれている。そのためにJavaオブジェクトを戻すサーバ側ユーティリティメソッドもある。それらのJavaオブジェクトをJavaScriptで扱おうとするとundefinedになる。

#課題
ServiceNowのGlideRecordUtilドキュメントのgetTables()メソッドのスクリプトサンプルを実行するとundefinedになる。

```
var tables = new GlideRecordUtil().getTables("cmdb_ci_linux_server");
gs.log(tables.join(","));  
// The result would be "cmdb_ci, cmdb_ci_computer, cmdb_ci_server, cmdb_ci_linux_server".
```

https://developer.servicenow.com/dev.do#!/reference/api/paris/server_legacy/c_GlideRecordUtilAPI#r_GRU-getTables_S?navFilter=gettable

#原因
原因はこのメソッドの戻り値の型である。説明に書かれている通りに**Java** ArrayListを返すので直接.join(",")は出来ない。

```
Returns a Java ArrayList of the ancestors of the given table name.
```

#対策
Java ArrayListをJavaScriptのArrayListに変換すると問題は解決する。
ServiceNowはJavaオブジェクトをJavaScriptオブジェクトに変換するために**j2js**と提供している。
https://developer.servicenow.com/dev.do#!/reference/api/orlando/server_legacy/c_J2jsAPI

次のようにサンプルコードを修正すると正しくテーブル名一覧は表示される。

```
var tables = new GlideRecordUtil().getTables("cmdb_ci_linux_server");
var tablejs = j2js(tables);
gs.log(tablejs.join(","));
```
実行結果

```
*** Script: cmdb_ci_linux_server,cmdb_ci_server,cmdb_ci_computer,cmdb_ci_hardware,cmdb_ci,cmdb
```

以上
C#　PowerPointファイルのプロパティを設定・読み込む

<p><strong>PowerPointファイルのプロパティは　ファイルの内容を示し、そのファイルを特定するためのものです。 ドキュメントのプロパティには、タイトル、作成者名、件名などのほかに、ドキュメントのトピックや内容を特定するキーワードがあります。<br>
この記事では　Spire. Presentationを通じてPowerPointファイルのプロパティを設定・読み込む方法をご紹介していきます。<br></strong></p>
<h3><strong>下準備</strong></h3>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/download-presentation-for-net-free.html" target="_self">Free Spire. Presentation</a>無料版をダウンロードしてください。<br></strong></p>
<p><strong><img src="//public.muragon.com/9qx7s4rm/4trfrnbf.png?dummy=1606276472391" width="525" height="222"></strong></p>
<p><br></p>
<p><strong>2.Visual Studioを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire. Presentation.dllを参照に追加してください。<br>
<span style="color:#ff0000;">（Net 4.0を例としたら、デフォルトパスは“Bin→NET4.0→Presentation.dll”というようになります。）</span></strong></p>
<p><br></p>
<p> </p>
<p><img src="//public.muragon.com/9qx7s4rm/35tgm8yl.png?dummy=1606276472391" width="250" height="216"></p>
<h3><strong>プロパティの設定</strong></h3>
<p><br></p>
```c#
using Spire.Presentation;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{

//PPTを作成します。
Presentation ppt = new Presentation();

//プロパティを設定します。
ppt.DocumentProperty.Title = "パンダについて";
ppt.DocumentProperty.Subject = "パンダの竹";
ppt.DocumentProperty.Author = "パンダンさん";
ppt.DocumentProperty.Manager = "パンダのマネジャー";
ppt.DocumentProperty.Company = "パンダ会社";
ppt.DocumentProperty.Category = "動物";
ppt.DocumentProperty.Keywords = "パンダ";
ppt.DocumentProperty.Comments = "パンダさんのお嫁さんってだれ？";

//保存します。
ppt.SaveToFile("プロパティ.pptx", FileFormat.Pptx2013);
}
 } 
  }
```



<p><img src="//public.muragon.com/9qx7s4rm/aj042r0u.png?dummy=1606276472391" width="422" height="520"></p>
<h3><strong>プロパティを読みこむ</strong></h3>
<p><br></p>

```c#
using Spire.Presentation;
using System;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
  
//PPTをロードします。
Presentation ppt = new Presentation();
ppt.LoadFromFile("プロパティ.pptx");

//プロパティを読み込みます。
Console.WriteLine("タイトル: " + ppt.DocumentProperty.Title);  
Console.WriteLine("サブタイトル: " + ppt.DocumentProperty.Subject);
Console.WriteLine("作成者: " + ppt.DocumentProperty.Author);
Console.WriteLine("管理者: " + ppt.DocumentProperty.Manager);
Console.WriteLine("会社名: " + ppt.DocumentProperty.Company);
Console.WriteLine("分類: " + ppt.DocumentProperty.Category);
Console.WriteLine("キーワード: " + ppt.DocumentProperty.Keywords);
Console.WriteLine("コメント: " + ppt.DocumentProperty.Comments);

Console.ReadKey();
}
　}
　　}
```


<p><img src="//public.muragon.com/9qx7s4rm/j5xmd664.png?dummy=1606276472391" width="432" height="231"></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
ruby 演習メモ IV (assert_equal)



# 目的

ruby のコードを実際に書いてみよう.今回は第 IV 弾.


# お題:assert\_equal

assert equal とは, equal かどうかを確かめる (assert) 関数.
これを実際に書いてみる.
(参考資料は[これ](https://qiita.com/daddygongon/items/f6cea87314ee26e130ea))


# code 例

実際に書いた code はこんな感じ.

```ruby
def assert_equal(expected, result)
  return expected == result
end

print "#{assert_equal(1, 1)}\n"
print "#{assert_equal(1, 2)}\n"
```

関数 assert\_equal の説明はこんな感じ. (見たまんま)

-   関数名 : assert\_equal
-   入力 : expected, result
-   出力 : true or false
-   概要 : expected と result が一致するなら true, そうでないなら false を返す


# 他の code からこの関数を呼び出したい時

この関数を他の ruby code から呼び出したい時は, 

```ruby
require './assert_equal'

assert_equal(2, 1*2)
```

こんな感じで使える.

でも, このままだと

```ruby
print "#{assert_equal(1, 1)}\n"
print "#{assert_equal(1, 2)}\n"
```

ここも実行される.

そんな時, この部分 (関数のテスト部分) を実行しないようにするために, 以下の記述が使える

```ruby
if $PROGRAM_NAME == __FILE__
  print "#{assert_equal(1, 1)}\n"
  print "#{assert_equal(1, 2)}\n"
end
```

これは, 実行してるファイル名と, code が実際に記述されているファイル名が同じなら, if - end を実行するという意味.
この書き方はとりあえず覚えよう.


# colorize で色をつける

colorize で文字列に色をつけることが出来る.

```ruby
require 'colorize'

print "#{assert_equal(1, 1)}\n".green
print "#{assert_equal(1, 2)}\n".red
```

こんな感じ.

どういう色があるかを見る時は,

    > irb
    irb(main):001:0> require 'colorize'
    => true
    irb(main):002:0> String.colors
    => [:black, :light_black, :red, :light_red, :green, :light_green, :yellow, :light_yellow, :blue, :light_blue, :magenta, :light_magenta, :cyan, :light_cyan, :white, :light_white, :default]

こうやって見れる.

ちなみに colorize がない時は, 

    > gem install colorize

これで install.(gem は ruby の library を管理するシステム)


# 今回書いた code の全体

最終的にこうなった. ファイル名は "assert\_equal\_final.rb".
ちなみに自身の関数名を取得したい時は,  `__method__` で良いらしい. ([ここ](https://qiita.com/syasin/items/b8f318edf21b1e5abbc7)参照)

```ruby

require 'colorize'

def print_expected_and_result(expected, result)
  print "expected: #{expected}\n"
  print "result:   #{result}\n"
end

def assert_equal(expected, result)
  print_expected_and_result(expected, result)
  is_equal = (expected == result)
  if is_equal
    print "succeeded in #{__method__}.\n".green
  else
    print "failed in #{__method__}.\n".red
  end
  return is_equal # 何となく返したいから返してる
end

def assert_not_equal(expected, result)
  print_expected_and_result(expected, result)
  is_not_equal = (expected != result)
  if is_not_equal
    print "succeeded in #{__method__}.\n".green
  else
    print "failed in #{__method__}.\n".red
  end
  return is_not_equal # 何となく返したいから返してる
end

if $PROGRAM_NAME == __FILE__
  array_expected	= [1, 1, 2, 2]
  array_result		= [1, 2, 1, 2]

  array_expected.zip(array_result) do |expected, result|
    assert_equal(expected, result)
    assert_not_equal(expected, result)
  end
end

```


# 参考資料

-   [チャート式ruby-IV(assert\_equal)](https://qiita.com/daddygongon/items/f6cea87314ee26e130ea)
-   [マルチスケール特論 第9回](https://qiita.com/syasin/items/b8f318edf21b1e5abbc7)



------
 - **source** ~/Lecture/multiscale_simulation/grad_members_20f/members/gagagagazelle/docs/c4_assert_equal.org
NUXTJS環境でmicroCMSで日付取得した際の省略方法

自分用メモかねて。
公式ドキュメントにはなかったので、どちらかというとNUXT.JSの処理ですね。

microCMSをで投稿日とかを取得するには、

```
        "createdAt": "2020-09-24T11:27:31.580Z"
        "updatedAt": "2020-11-24T01:17:52.754Z"
        "publishedAt": "2020-09-24T11:27:31.580Z"
```
のように作成日、更新日、公開日を取得可能です。

ですが、例えば後ろの時刻まではいらないなーと思ったときには
処理が必要になります。
通常だと

```
      {{ publishedAt }}
```
（構成にもよりますが）
で出力ですが

```
      {{ new Date(publishedAt).toLocaleDateString() }}
```
と打つことで日付だけ取得可能でした。
![スクリーンショット 2020-11-24 15.52.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546003/80b2afc6-2f12-2ee7-681b-ad2462d8db77.png)
下が通常取得。上が処理後の取得。
【AWS】Auroraオートスケール：②オートスケール設定

#はじめに
Auroraのオートスケールを記事にしたいと思います、長いのでシリーズ記事とします

1. [【AWS】Auroraオートスケール：①オートスケール概要](https://qiita.com/y-okuhira/items/1277ba6012b72280d75d)
2. [【AWS】Auroraオートスケール：②オートスケール設定](https://qiita.com/y-okuhira/items/a1b2b41e105f36daa3be)　<b>※現在の記事</b>
3. 【AWS】Auroraオートスケール：③Cron式スケジュール設定 
4. 【AWS】Auroraオートスケール：④Cron式スケジュール変更
5. 【AWS】Auroraオートスケール：⑤カスタムメトリクスでリードレプリカ数経過観察
6. 【AWS】Auroraオートスケール：⑥チューニング・ブラッシュアップ等

#Aurora Auto Scaling設定内容
Auroraの構築は済んでいて　下記図のような最小限の簡単な環境が出来ている前提で進めていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682071/9eecac18-c28b-ee78-bd5b-bc8b45bf21f5.png)

①作成したAuroraクラスタ　＞　ログとイベント　＞　「Auto Scalingポリシーの追加」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682071/03a12ee1-8b57-f52d-8a9a-1d3c7c3f256a.png)


②Auto Scalingポリシーの設定を行います
・ポリシー名（任意）：test-aurora-policy
・ターゲットメトリクス：Auroraレプリカの平均CPU使用率
・ターゲット値：80%
・スケールインクールダウン期間
・スケールアウトクールダウン期間
・最小キャパシティー：2　※現在リードレプリカが1台ですが、最小の2台へ増えます
・最大キャパシティー：3　※どんなに負荷が増えても、リードレプリカは3台以上へは増えません

※デフォルトの設定値は下記の内容となりました
・AuroraのCPU使用率が80%以上になると、オートスケールによってリードレプリカが1台増える
・AuroraのCPU使用率が72%以下になると、オートスケールによってリードレプリカが1台減る![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682071/7f02962c-72c5-b59c-858d-e333d8562da7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682071/9515d7ce-d74c-219d-9cfa-0b8d9eacc113.png)

③Aurora Auto Scaling設定後の動作
リードレプリカが最小2台に設定しましたので、Auto オートスケール設定直後にリードレプリカが1台作成されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682071/58866463-64b6-a1f2-9a49-0cd118d2e093.png)

また、下記のようにスケールイン・スケールアウト用のCloudWatchのアラートが作成されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682071/e18614d7-95b4-a380-9b53-2bb8aacfcd8b.png)
上記アラート既定値は運用によって調整・設定していきます。

以上でAuroraオートスケールの設定は完了です。

#次回
３. 【AWS】Auroraオートスケール：③Cron式スケジュール設定
【AWS】Auroraオートスケール：①オートスケール概要


#はじめに
Auroraのオートスケールを記事にしたいと思います、長いのでシリーズ記事とします

1. [【AWS】Auroraオートスケール：①オートスケール概要](https://qiita.com/y-okuhira/items/1277ba6012b72280d75d)　<b>※現在の記事</b>
2. [【AWS】Auroraオートスケール：②オートスケール設定](https://qiita.com/y-okuhira/items/a1b2b41e105f36daa3be)
3. 【AWS】Auroraオートスケール：③Cron式スケジュール設定 
4. 【AWS】Auroraオートスケール：④Cron式スケジュール変更
5. 【AWS】Auroraオートスケール：⑤カスタムメトリクスでリードレプリカ数経過観察
6. 【AWS】Auroraオートスケール：⑥チューニング・ブラッシュアップ等



#背景
ユーザ数が増えてリードレプリカの負荷が上がり、
緊急対応としてリードレプリカを増やす対応を2～3回ほど行い、結構な工数を要しました
上記の対策としてAuroraオートスケールを実装し、リードレプリカの負荷によって自動でスケールアップする仕組みを取り入れました
Auroraオートスケールは便利なのですが、あまり記事を見かけない為、ナレッジを残したいと思います
※Cron式スケジュール設定の記事が少なくて数時間苦戦しました・・・

#Auroraオートスケール概要説明
リードレプリカの平均CPU使用率、平均接続数の負荷に応じて自動でリードレプリカ台数をオートスケールします
上記により可用性、運用・課金コスト削減等のメリットを得る事が出来ます
急激に負荷が上がってしまった場合を想定して、障害を未然に防ぐ為にも標準で取り入れた方が良いと考えています

リードレプリカへの負荷が高まるとオートスケール処理が開始され、自動でスケールアップ（増大）を行う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536501/63d067a2-2311-ec14-e78b-7051d419484e.png)

読込処理も分散されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536501/3f844235-0a71-bc69-5f52-888e1567a2ac.png)


###Cron式スケジュール
負荷が高まる時間帯を事前に分かる場合は、Cron式スケジュールでリードレプリカを増やす事が出来ます
※12時負荷が高まる場合、事前に11時にリードレプリカ台数を増やす、下記は3台から5台に増えた図です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536501/ef3f7e6f-2c4d-fb0d-a4b4-abd8d9f970d1.png)

#次回
[2.【AWS】Auroraオートスケール：②オートスケール設定](https://qiita.com/y-okuhira/items/a1b2b41e105f36daa3be)

#参考
[[AWS] Amazon Auroraについて](https://qiita.com/oudon722/items/db43a9e5a1a5bcc02f23)
[Amazon Aurora](https://qiita.com/leomaro7/items/bc64709558180f70453f)
【AWS】Aurora説明（Aurora、RDS、オンプレミスとの比較）

#はじめに
AWSサービスAuroraについて説明致します
個人的見解もあるのですが、私はAWSでDBを使用するのでしたらAuroraをお勧めしています
障害対応や運用、可用性の恩恵が大きく、品質がとても良いと考えています

また、RDSとAuroraの区別がよく分からないという人を時折見受けられます
本記事はあくまで参考として閲覧頂きたいのですが、
Auroraがよく分からないという人もこれを機にAuroraに携わって頂けたら嬉しいと思います

#１．Auroraとは
AuroraはMySQL/Postgres互換ではありますがアーキテクチャはAWS独自にカスタマイズされており、パフォーマンスと可用性について商用DBに匹敵する品質を謳っています

特徴的な点としてはコンピュートとストレージが分離されているためそれぞれが別々にスケールする事が出来、3Azに6コピーを持って高可用性を担保しています
※AWS様からAuroraアピールポイントの回答を頂いており、少し拝借しております

私が携わっている業務でも推奨しているAWSデータベースサービスとなります

【2020年SummitOnline】
[Amazon Aurora はこう使え！貴方にだけ便利な使い方教えます！](https://resources.awscloud.com/vidyard-all-players/aws-25-aws-summit-online-japan-2020-720p)

※上記、運用やアーキテクチャを簡素化するための様々な方法が紹介されております

#２．Aurora、RDS、オンプレミスとの比較
下記のように比較表を作成しました
Auroraにデメリットがあるとすれば、Auroraが「MySQL8.0」にまだ対応していない事かなと思います（※2020年12月時点、PostgreSQLも同様の内容）

|  | メリット | デメリット |
|:-:|:--|:--|
|     Aurora<br>（MySQL5.7）     	| ・パフォーマンス、高可用性、運用を楽にする豊富な機能（オートスケール、リードレプリカ、PerformanceInsigtなど）     <br><br>・マネージドサービスなので運用コストのメリットが大きい     <br><br>・Aurora(5.7)とMySQLを比較して、5倍のパフォーマンスを示したというベンチマーク結果があります　※AWS事例 	| ・MySQL8.0最新機能が使えない、単純比較するとインスタンス費用が割高（パフォーマンス向上によってサイズや数を減らせばAuroraのほうが安くなるケースもあり）                                                                   	|
|        RDS<br>（MySQL8）       	| ・MySQL8系の最新機能が使える     <br><br>・他DBエンジンが使用可能（ORACLE、SQLServer、MariaDB等）                                                                                                                                                                	| ・Auroraならではの機能が使えない<br>     　－　障害復旧（フェールオーバー）の時間が長い<br>     　－　リードレプリカ、オートスケール使用が出来ない<br>     　－　容易にストレージのスケールアップが出来ない、等・・・ 	|
| オンプレミス構築<br>（MySQL8） 	| ・ある意味ですべて自分でコントロール可能     <br><br>・MySQL8系の最新機能が使える     <br><br>・MySQL8.0を使用した場合、MySQL5.7より最大2倍高速　※MySQLの公式見解                                                                                                    	| ・運用コストが高い                                                                                                                                                                                                       	|

多少のデメリットがあると言えど、やはりメリットは大きく、そしてまだまだAurora技術の急速成長の勢いが止まりません
便利な機能もどんどん増えていくので、もっと使いこなせるようになりたいです

#次回
次記事でAurora作成を行いたいと思います
【AWS】Aurora作成


また、Auroraオートスケールについても下記シリーズ記事として記載していきます
[1. 【AWS】Auroraオートスケール：①オートスケール概要](https://qiita.com/y-okuhira/items/1277ba6012b72280d75d)
[2. 【AWS】Auroraオートスケール：②オートスケール設定](https://qiita.com/y-okuhira/items/a1b2b41e105f36daa3be)
3. 【AWS】Auroraオートスケール：③Cron式スケジュール設定 
4. 【AWS】Auroraオートスケール：④Cron式スケジュール変更
5. 【AWS】Auroraオートスケール：⑤カスタムメトリクスでリードレプリカ数経過観察
6. 【AWS】Auroraオートスケール：⑥チューニング・ブラッシュアップ等

#参考サイト
[AWS-25：Amazon Aurora はこう使え！貴方にだけ便利な使い方教えます！](https://resources.awscloud.com/vidyard-all-players/aws-25-aws-summit-online-japan-2020-720p)
[AuroraかRDSどちらを選ぶべきか比較する話をDevelopers.IO 2019 in OSAKAでしました #cmdevio](https://dev.classmethod.jp/articles/developers-io-2019-in-osaka-aurora-or-rds/#aurora-features)

以上です、ありがとうございました
macのルーティングを変更する route add route change route delete


VPNを通したくない通信があるときとかに使う

interface指定

```ruby
$ sudo route add -host <dest-IP> -interface en0
Password:
add host <dest-IP>: gateway en0
```

ルータを指定する版

```ruby
# route add
$ sudo route -n add -net <dest-IP>/32 192.168.0.1
```

デフォゲを全部変えたい版
全部VPN通したいときとか

```ruby
sudo route change default 10.10.20.30
```

このIPはVPN tunnel用のgw的なIPを。

消す時

```
$ sudo route delete -host $IP -interface en0
delete host $IP: gateway en0
```
CLIをインストールできてるのに、command not found: quasar　とかになる場合。

```
sudo npm install -g @quasar/cli
```

でモジュールをインストールして

```
+ @quasar/cli@1.1.2
added 376 packages from 294 contributors in 9.001s
```

ッて感じでインストールできたのに、いざコマンドしてみると
「ありません」みたいになるやつ

```
 quasar create quasar-weather
zsh: command not found: quasar
```
こんなかんじでハマる。


こういうのは単純に反映がされてないだけなので、


```
% source ~/.bash_profile
```
これで反映させてから、
もう一回コマンドを実行させるとうまくいきますた

```
Mac desktop % source ~/.bash_profile
Mac desktop % quasar create quasar-weather

  ___                             
 / _ \ _   _  __ _ ___  __ _ _ __ 
| | | | | | |/ _` / __|/ _` | '__|
| |_| | |_| | (_| \__ \ (_| | |   
 \__\_\\__,_|\__,_|___/\__,_|_|
```


しょっちゅう忘れるのでメモ
あと、VSコードターミナルでも同様なのでメモ
UnityでTOMLファイルを扱う

# 概要
Unityの趣味プロジェクトでTOMLファイルの読み込みをしたくなったので、TOMLファイルを取り扱えるライブラリをインポートしたときの作業ログです。
Unityや.NET周りの開発は完全に素人で、手探りで進めているため、不必要にまわりくどい方法をとっていたりもするかと思います。
そのような点を見つけましたら、指摘して貰えると喜びます。

## バージョン
- Unity 2019.4.15f1

## ログ
### ライブラリのインポート
NettというTOMLファイルをパースできるライブラリがあるので、これをUnityから使えるようにしたい。
https://github.com/paiden/Nett
.NETのライブラリなので.NET用のパッケージマネージャであるNuGetでインストールする。
https://www.nuget.org/
NuGetにはUnity用の実装があるのでこれを使う。
https://github.com/GlitchEnzo/NuGetForUnity
README上のリンク
https://github.com/GlitchEnzo/NuGetForUnity/releases
から最新のリリースのunitypackageファイルをダウンロードしてきて、Unityの`Assets>Import Package>Custom Package...`からインポートする。
UnityのツールバーにNuGetが追加されるので、`NuGet>Manage NuGet Pakages`からNettを探してインストール。

```
Disabling WSA platform on asset settings for ThisProjectPath\Assets\packages.config
```
なるWarningが出たが現状問題ないのでとりあえず無視。

### ファイル読み込み
NettのリポジトリのREADMEの[Documentation]
(http://paiden.github.io/Nett/)が工事中で情報がないので、APIの情報を探す。
[ここ](http://paiden.github.io/Nett/api/Nett.html)にまとまっていたので、参考にしつつファイルを読み込む。
プロジェクトのルートディレクトリに`input/test_input.toml`を作成。中身は下記

```toml:test_input.toml
title = "Input file example"
```

```C#:Test.cs
using UnityEngine;
using System.Collections;
using Nett;

public class Test : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // read input file
        string input_file_path = Application.dataPath + "/../input/test_input.toml";
        TomlTable root = Toml.ReadFile(input_file_path);
        string title = root.Get<string>("title");
        Debug.Log("The input file title is " + title);
    }
}
```
Unityで実行してコンソールに適切に出力されていることを確認。

```
The input file title is Input file example
UnityEngine.Debug:Log(Object)
Test:Start() (at Assets/Test.cs:8)
```


## 他に参考にした記事
- https://qiita.com/Kosen-amai/items/107f74cd29faa6b5002b
- https://cgworld.jp/regular/201909-codelight-unity11-2.html
Sourcetree SSHキーの設定

<br>
原因はわかりませんが、突然git push ができなくなって、手動でSourcetreeでのSSHキーの作成からGithubへの再登録を行った。<br>
その忘備録。

## 問題
Sourcetreeでいつもの通りにコミットした内容をリモートリポジトリにプッシュしたら以下のようなエラーが出た。
念のためターミナルソフト(CUI画面)で再度プッシュしても以下のエラーが出た。

```
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

## 解決策
結論、元々Sourcetreeによって作成されていたファイルを削除して(sshディレクトリ内のconfigファイルのSourcetreeによる記述箇所とSourcetreeによって作成されたsshキー)、SSHキーを再度作成して、GitHubに登録したら直った。

以下に手順を示す。


## sshディレクトリ内のconfigファイルの修正及び、公開鍵、秘密鍵の削除

### configファイルの修正
~/.sshディレクトリ内のconfigファイルをvimでも何でも良いので開くと以下のような記述を見つけることができると思います。
この`Host ~GitHub`から`AddKeysToAgent ~`までの行を全て削除します。その後configファイルを保存します。

￼

### 公開鍵、秘密鍵の削除
新しくキーを生成するので、Sourcetreeによって生成されたキーを削除します。
Sourcetreeによって生成される鍵はおそらく、”[your-github-username]-GitHub.pub” と “[your-github-username]-GitHub”になってると思います。
(今回はGitHubを使用していることを想定していますが、Bitbucketでも同じようなファイル名になっていると思います。)
これを削除します。

### Sourcetreeでのキーの作成

* Sourcetreeを開いて、(macなら)歯車マークをクリックして「アカウント」をクリックします。
* 問題のアカウントをクリックして、左下の「編集」タブをクリックします。
* キーを削除したので、SSHキーの欄が「キーがありません」などの表示になっていますので、「キーの生成」をクリックして新たに作成します。
* 作成後「クリップボードにコピー」をクリック
* Githubのアカウントで「SSH and GPG keys」の欄を開く
* SSH keysにある問題のSSHを「Delete」する。
* 「New SSH key」をクリック
* Titleは任意に決めてください。Keyに先ほどクリップボードにコピーしたものをペーストして保存して終了です。

以上で終了です。おそらくSourcetreeからプッシュできるようになっていると思います。
それかターミナルで

```
$ ssh -T git@github.com
```

でアクセス可能か確認できます。
PHPでの基本的なこと (1)

#最初に
普段Pythonをつかっているため、そこと完全に一致しているものは省略しているかも

###メモ
プログラムの最後には；をつけること

#コメントアウト
### 1行のコメントアウト

```php
// これでコメントアウトされる
```

### 複数行のコメントアウト
```php
/*
echo "/*と* /で挟むと";
echo "その間の行は";
echo "実行されない";
echo "上のやつで空白が入っているのはコメントアウト解除を防ぐため"
*/
```


#標準出力
###文字列
文字列の場合は""で挟む

```php
echo "ABC";
// 出力 ABC
```

###数字
数字の場合はそのままでおｋ
特に形式などを指定する必要もなさそう

```php
echo 15;
// 出力　15
echo 10.5;
// 出力　10.5
```

###論理型
論理型の場合はechoでtrueを出力すると1、falseは何も出力されない

```php
echo true;
// 1
echo false;
// 出力されない
```

###複数行出力
\nをつけるとその位置で改行

```php
echo "ABC\nDEF";
/*
ABC
DEF
*/
```

###エスケープシーケンス
""を入れたい場合は\"をつける

```php
echo "\"Hello\"";
// "Hello"
```


##変数
頭に$をつけることで変数であると宣言できる

###演算

```php
//和
$number1 = 4 + 8;
echo $number1;
// 12

//差
$number2 = 9 - 5;
echo $number2;
// 4

//積
$number3 = 6 * 5;
echo $number3;
// 30

//商
$number4 = 6 / 3;
echo $number4;
// 2

//余り
$number5 = 7 % 4;
echo $number5;
// 3
```

もちろん複合演算子(+=など)も使用可能


なお、以下のように直接演算をして出力することも可能

```php
echo 3 + 8;
// 11
```

###定数
代入などによって変化することのない値

```php
define("Pi", "3.14");
echo Pi;
// 3.14
```

###連結
.でつなぐことで連結して出力することができる

```php
echo "ABC"."DEF";
// ABCDEF
```

###文字列と変数・定数の連結
.でつなぐことで変数や定数も接続することができる

```php
$number = 12345;
echo "number".$number;
// number12345
```


# 型
### 配列
まとめる要素をarray(と)で挟む

```php
array("要素1","要素2","要素3");
```

###連想配列
配列同様にarray(と)で挟む
さらに=>で2つの要素をつなぐ

```php
array("商品名"=>"コーラ", "種類"=>"飲料");
```
S3のサーバーサイド暗号化とダウンロード経路

## TL;DR
以下の組み合わせのダウンロード可否を調査する機会があったのでまとめます。

- サーバーサイド暗号化の種類
  - なし
  - SSE-S3
  - SSE-KMS
- ダウンロード経路
  - 静的ホスティング
  - Get Object URL
  - Presigned URL
  - CloudFront

結果だけ気になる人は[結論](#結論)へ飛んでください。

## サーバーサイド暗号化
S3にはサーバーサイド暗号化(Server Side Encryption、SSE)という機能があります。
保存時に暗号化が行われ、取得時に復号されるので、利用者はあまり意識せずにオブジェクトを暗号化することができます。
[公式ドキュメント](https://docs.aws.amazon.com/AmazonS3/latest/dev/serv-side-encryption.html)

### サーバーサイド暗号化の種類
サーバーサイド暗号化には現在3つの暗号化の方法があります。

**SSE-Cを利用するシーンは（個人的に）あまりないため、今回は「暗号化なし」「SSE-S3」「SSE-KMS」を対象に調査を行うことにします。**

#### SSE-S3
AWSが用意したS3用の暗号鍵を用いて暗号化を行います。
[公式ドキュメント](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html)

#### SSE-KMS
ユーザーがAWS KMSで作成した鍵を用いて暗号化を行います。
[公式ドキュメント](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html)

#### SSE-C
ユーザーが作成した鍵を用いて暗号化を行います。
オブジェクトをS3にアップロードする際とダウンロードする際に暗号鍵を指定します。
AWS上に暗号鍵をアップロードすることなく、手元で管理することが可能です。
[公式ドキュメント](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html)


## S3上のオブジェクトのダウンロード経路
さて、S3上のオブジェクトをアプリケーションから取得する方法はいくつか存在します。

- S3の静的サイトホスティング機能
- S3のGet Object URL
- S3のPresigned URL([SigV4](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html))
- CloudFrontのOriginに指定
- アプリケーション上でAWS SDKで取得

アプリケーション上でAWS SDKで取得に関しては、当然どのようなサーバーサイド暗号化であろうと取得可能なので、今回の調査では対象外とします。

## 実装
Terraformでサクッと調査対象のS3バケットやCloudFrontなどを実装しました。
<a href="https://github.com/reireias/s3-encryptions"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/reireias/s3-encryptions.png" width="460px"></a>

## 結論
結果は以下のようになりました。

| | SSEなし | SSE-S3 | SSE-KMS|
|:--|:--:|:--:|:--:|
|静的ホスティング|◯|◯|×|
|Get Object URL|◯|◯|×|
|Presigned URL|◯|◯|◯|
|CloudFront|◯|◯|×|

要件次第ですが、SSE-S3が無難かなと。

## おまけ
SSE-KMS + CloudFrontはLambda Edgeで署名を付与することで復号できるようになるようです。
https://aws.amazon.com/jp/blogs/networking-and-content-delivery/serving-sse-kms-encrypted-content-from-s3-using-cloudfront/
HDDをフォーマットしようとしたら、{} is mounted; will not make a filesystem here!のエラー

HDDをマウントする過程でフォーマットしようとしたところ、エラーが出たのでメモ。

#HDDをフォーマットしようとしたらエラー

```
$ sudo mkfs.ext4 /dev/sdb1
/dev/sdb1 is mounted; will not make a filesystem here!
```

#アンマウントしてから再実行で解決
```
$ sudo umount /dev/sdb1
$ sudo mkfs.ext4 /dev/sdb1
```
gigafile便に上がっているファイルをwgetする

#gigafile便のファイルをwgetでダウンロードしたい
gigafileで100GB近い動画ファイルを送られ、クラウドで再エンコードしてからダウンロードしようとしたところ、cookie関連を知らなくて調べるのにちょっと時間かかったのでメモ

gigafile便のダウンロードボタンのPHPはcookieを使っているみたいで、こうして一旦ダウンロードページのcookieを保存しておく必要があるようです

```
$ wget --keep-session-cookies --save-cookies=cookies.txt 【ダウンロードページのリンク】
$ wget --load-cookies cookies.txt -r -k -E 【ダウンロードボタンのリンク】
```
この二行でDLが始まります

時間帯によるけど観測した中では最高80MB/sくらいでダウンロードできてました、いいですねぇ
【Laravel】指定の文字数以上の文字列を表示するとき、「...」としたい場合

# はじめに
現在、社内向け質問アプリケーションを制作中です。
日々こつこつと機能を追加したり、改善したりしています。
こちらに開発からデプロイまでについてまとめているので、よろしければ是非見てみてください。
[【未経験・独学】Laravelでアプリケーションの開発からAWSを用いたデプロイまで](https://qiita.com/sasao3/items/5311d442699dba198bb0)

今回は、長い文章に対して指定の文字数を超えた場合は、「...」と表示させたいと思い調べたことをここに記録します。

# 現状
現状はこのように、コメント文が全部表示されています。そのため、コメント欄の箇所のみバランスが悪くなっている。

![コメント欄.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/08632380-378a-2165-cfe1-efa6e8e7b870.png)

そこで、100文字以上は...と表示させてコメント欄のサイズをある程度一定にしたいと思う。
調べてみたところ、ヘルパ関数の`Str::limit()`を使用することで解決ができると分かった。

# Str::limit()とは？
Str::limit()とは、Laravelで用意されているグローバルヘルパ関数の一つである。
こちらの関数を使うことで指定した長さへ文字列を切り詰めることが出来る。

使い方としては、第一引数に対象の文字列、第二引数に指定の文字数、第三引数に最長文字数を超えた場合に末尾へ追加する文字列を指定する。
参考：[Laravel 7.x ヘルパ](https://readouble.com/laravel/7.x/ja/helpers.html#method-str-limit)

Str::limit()を使う前は、`{{$reply->body}}`と記載している。
Str::limit()を用いると、このようになる。

```php
{{\Illuminate\Support\Str::limit($reply->body, 100, '...')}}
```

このようにStr::limit()を用いることで、コメントの文字数を一定にすることが出来ました。
![コメント欄２.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/4c0196e5-58bd-00e8-5720-bec212686b57.png)

※注意点としては、指定する数字はマルチバイトを考慮しなければいけないということ。
日本語は、マルチバイト文字（2バイト以上のデータ量で表すもの）なため以下のようになってしまう。

```php
Str::limit('確認用', '3', '...') //確...となる
```

参考
・[マルチバイト文字  【 多バイト文字 】](http://e-words.jp/w/%E3%83%9E%E3%83%AB%E3%83%81%E3%83%90%E3%82%A4%E3%83%88%E6%96%87%E5%AD%97.html#:~:text=%E3%83%9E%E3%83%AB%E3%83%81%E3%83%90%E3%82%A4%E3%83%88%E6%96%87%E5%AD%97%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%A7%E6%96%87%E5%AD%97%E3%82%92%E6%89%B1%E3%81%88%E3%82%8B,%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E8%A1%A8%E3%81%95%E3%82%8C%E3%82%8B%E6%96%87%E5%AD%97%E3%80%82)
・[全142種類！Laravelヘルパー関数実例](https://blog.capilano-fw.com/?p=837#Strlimit)

# まとめ
今回は、Laravelで指定の文字数以上の時、...としたい場合についてまとめました。
公式ドキュメントを見てみると、他にも沢山のヘルパ関数があったので色々見てみようと思います。
ServiceNow - Personal Developer Instanceのデモユーザも無効にする

#概要
ServiceNowのPersonal Developer Instanceを作成した後にデモデータを削除しないとデモユーザが有効になる。すべてのインスタンスで同じユーザになるためセキュリティ上ではそれらのユーザを無効にした方がよい。

#手順
##管理ユーザの作成
1. ServiceNowでは最低でも管理者が2人必要です。そのために先ずは管理者をもう一人作成します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/3c575d02-fc7a-b0fc-b2fb-31a7d3cd6e0f.png)
2. 「新規」ボタンを押下![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/8fc3deb6-52e7-4540-fa29-db8ada9e2836.png)
3. 「ユーザーID」と「パスワード」を入力![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/d3732ba4-3ead-f507-fc75-79b200d6a044.png)
4. ヘッダを右クリックして「保存」を選択![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/621f8145-0ffa-5a26-cd18-668d8f6f57b9.png)
5. ページ下の「ロール」タブを選択して「編集」ボタンを押下![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/f0dfbe05-f048-dbd1-5ea5-9781c447b401.png)
6. 「admin」を選択して「>」ボタンを押下![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/b9eef06b-d61c-a08b-e2f9-98f40f9004c4.png)
7. 「保存」ボタンを押下![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/37d773fc-f8ef-3ffb-cd83-886b46636471.png)

##既存ユーザの無効化
1. アプリケーションナビゲータから「バック」を検索して「スクリプト-バックグラウンド」を選択![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/b48d102c-d7a9-2c3b-a27d-c4a8627b1fca.png)
2. 次のスクリプトを実行<br/><pre>var grUser = new GlideRecord('sys_user');grUser.addActiveQuery();
grUser.query();
gs.print('rows:' + grUser.getRowCount());
var j = 0;
while(grUser.next()) {
  if (grUser.user_name != 'admin' && grUser.user_name != 'ozawa_h') { // 作成した管理ユーザ名に置き換える
    //grUser.setValue('active', false);
    //grUser.update();
    j++;
  }
}
gs.print("active:" + j);</pre>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/6dc8fabf-4332-d32a-49b9-4012911f3db8.png)

3. 実行結果は「*** Script: rows:」の値が「*** Script: active:」よりも2つ多いはず。そうでない場合はスクリプトで管理者指定を見直す
4. コメントアウトした行の先頭の「//」を削除して再び実行する。<pre>var grUser = new GlideRecord('sys_user');
grUser.addActiveQuery();
grUser.query();
gs.print('rows:' + grUser.getRowCount());
var j = 0;
while(grUser.next()) {
  if (grUser.user_name != 'admin' && grUser.user_name != 'ozawa_h') { // 
    grUser.setValue('active', false);
    grUser.update();
    j++;
  }
}
gs.print("active:" + j);</pre>
5. 再びユーザ一覧を表示して「アクティブ」欄が「false」に変更されていることを確認![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/5f65eae5-8dc0-8b4e-a2e6-f2b77ca2e63b.png)

以上
コミットコメントにプレフィックスを含めると分かりやすくなる


## プレフィックス

[angular.jsのDEVELOPERS.mdを参考](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#type)

- feature: 機能追加
- fix: バグ修正
- docs: ドキュメント修正
- style: コードスタイル修正（フォーマッター適用など）
- refactor: リファクタリング。機能追加やバグ修正など、動作を変更するものは入れないこと！！
- performance: パフォーマンス向上目的の修正
- test: テスト系のみの修正

参考のほうは、略称を使ったりしていたがブランチ名にも使いたいため、略さずにつけることにした。

あと、ライブラリ修正とか細かすぎるかなぁと思うところは消した。

## ブランチ名も合わせる

- feature/converter
- fix/converter
- refactor/converter

などなど

## 感想

職場でもコミットコメントのプレフィックス付ける部分のみやってみたが、リリース時の今回修正分確認が分かりやすくなり、非常に良かった。

ブランチ名を合わせるところまでやると、ブランチ一覧で大体の進行度合いが分かり、良さそうではある。

featureのコードレビュー時に、規模の大きいリファクタリングが入っていると、かなり辛くなるので、上記意識するとそういうのが無くなるかも？的な期待もある。

とりあえず、コミットコメントの先頭プレフィックスだけでもやってみるのが、コスパも良いしおすすめ。
bqコマンドでプロジェクト指定してコマンドを実行

bqコマンドを使って別プロジェクトにCSVファイルをインポートする時に調べた時のメモ。

# 結論
- `--project_id` オプションを使ってプロジェクトIDを指定する

# 環境
- GCP
- Ubuntu 18.04.03 LTS (Bionic Beaver)
- BigQuery CLI 2.0.62

# コマンド
## プロジェクト一覧の表示
```
bq ls -p
```

## プロジェクトを指定して、CSVファイルをBigQueryにインポート
```
bq load \
--project_id=project-b \      # プロジェクト名
--autodetect \                # スキーマ自動生成
--source_format CSV \         # インポートファイルフォーマット
<DataSetName>>.<TableName>> \ # インポートするBQのテーブル
./import.csv                  # インポートファイル
```

# 参考
- [まかあそてっく](https://makaaso-tech.com/bq-command-project-id/)
レスポンシブデザインの小技（PCとスマホ用に改行を調整する）

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ cssの基礎知識が増える
・ レスポンシブデザインについて

## 例

レスポンシブデザインを整えていて、文字を改行しなければいけない時

![スクリーンショット 2020-11-25 11.45.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/a116f1e2-973d-e078-ffa8-e992d18c4621.png)

## 手順

① レスポンシブデザインで対応する都度、`br`タグに適切なクラス名を付けて

```haml:index.haml
中略

    %p.inline iSaraでは、基礎知識学習は
    %br.brsp
    %span<>
      事前課題
    %p.inline と
    %span<>
      チャットサポート
    %p.inline のみ。

中略
```

② cssで隠しておきます

```scss:index.scss
// 中略

br.brsp {
  display: none;
}

// 中略
```

③ 表示を`display:block`で切り替えると

```scss:index.scss

@media screen and (max-width: 768px) {

// 中略

  br.brsp {
    display: block;
  }

// 中略
```

無事スマホ用の画面で改行できました。コードを汚さず、編集も軽く、使い回せます

![スクリーンショット 2020-11-25 12.00.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/a6f0bba6-7859-43fd-39d3-9bd0de83e68a.png)
メモ：Dockerイメージをまるっと削除したい

Dockerコンテナ乱立してるなー
Dockerイメージ使ってないやつ多いなー
って時にやる3コマンド

```
# コンテナ停止
docker ps -q | xargs docker stop
# コンテナ削除
docker ps -qa | xargs docker rm
# イメージ削除
docker images -q | xargs docker rmi
```
【Angular】ドラッグ＆ドロップで画像を読み込み表示する

前回:[画像を読み込んで表示する](https://qiita.com/frtklog/items/55ea3ab56e7474494368)

今回はドラッグ＆ドロップでエリアにドラッグして持ってきた画像を読み込んで表示するサンプルを作っていきます
未記載のclassはブートストラップを参照してください

####html
```html
<div class="container-md text-center">
  <div 
    class="dragarea w-100 border bg-light d-flex align-items-center"
    (dragover)="dragOver($event)" (drop)="drop($event)"
  >
    <span class="mx-auto">ドラッグエリア</span>
  </div>
  <input type="file" id="dragareaInput" style="display:none" (change)="onChangeDragAreaInput($event)">
  <label class="mt-3 btn btn-secondary" for="dragareaInput">参照</label>
  <div class="row">
    <img *ngFor="let i of img" [src]="i" class="col-6">
  </div>
</div>
```
####css
```css
.dragarea {
  height: 300px;
}
```
####typescript
```typescript
  onChangeDragAreaInput(event){
    // ファイルの情報はevent.target.filesにある
    let reader = new FileReader();
    const file = event.target.files[0];
    reader.readAsDataURL(file);
    reader.onload = () => {
      this.img.push(reader.result);
    };
  }

  dragOver(event:DragEvent){
    // ブラウザで画像を開かないようにする
    event.preventDefault();
  }
  drop(event:DragEvent){
    // ブラウザで画像を開かないようにする
    event.preventDefault();

    const file = event.dataTransfer.files;
    const fileList = Object.entries(file).map(f=>f[1]);
    console.log(fileList);

    fileList.forEach(f=>{
      let reader = new FileReader();
      reader.readAsDataURL(f);
      reader.onload = () => {
        this.img.push(reader.result);
      };
    });
  }
```

![スクリーンショット 2020-11-25 11.54.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607742/cbd3bb07-21f7-a94b-aa3a-28dbf0ab097b.png)

preventDefaultを動作させないとブラウザで画像開いちゃう、覚えた。
UWSCでコピペを自動化


# UWSCで自動化

ちょっとしたコピペ作業が発生したので、UWSCで自動化して代わりにやってもらいました。

いつかはPythonも使いたいけど、おそらくこの作業はPython引っ張り出すほどじゃないと思うのよね。
 
## コード
```
x = GETID("Sublime Text")
y = GETID("新規ファイル.xml")

for i = 1 to 100

SCKEY(x,VK_CTRL,L)
SLEEP(0.2)
SCKEY(x,VK_CTRL,C)
SLEEP(0.2)
KBD(VK_RIGHT,CLICK,40)
SLEEP(0.2)

SCKEY(y,VK_CTRL,V)
SLEEP(0.2)

KBD(VK_DOWN,CLICK,40)
SLEEP(0.2)

next
```


## 解説

### GETID("")
まず変数 x と y に、操作したいウィンドウを代入します。

`GETID("")`がウィンドウを取得するコマンドです。

操作したいウィンドウタイトルなどをダブルコーテーション内に書くと判定してくれます。
<br>


### for ~ next
for と next で挟んだ処理を繰り返し実行してくれます。

for の後に変数 i を用意し、1 to 100 の部分で繰り返す回数を設定します。

この場合、処理を100回繰り返してくれます。
<br>


#### SCKEY($window, $key_1, $key_2)

`SCKEY` は、キーボードの同時押しを実行してくれるコマンドです。


`$window`の部分に操作したいウィンドウを設定する必要があります。

この場合、上で設定した x,y を入れることで、指定したウィンドウを操作してくれます。


`$key_1`と`$key_2`の部分には、同時押ししたいキーを入力します。

例えばコピーなら [Ctrl+C]、ペーストなら [Ctrl+V] なので、

`SCKEY(x,VK_CTRL,C)` //コピー

`SCKEY(x,VK_CTRL,V)` //ペースト

のようになります。
<br>

#### SLEEP()
設定した秒数の間、次の処理を待ってくれるコマンドです。

`SLEEP(1)` とした場合、次の処理を1秒待ってくれます。
<br>

#### KBD()
キーボードを1つ押すときのコマンドです。

`KBD(VK_DOWN,CLICK,40)`とは、「↓ボタンを40ミリ秒だけ押す」という処理になります。

エクセルで次の行を参照したい時などによく使います。

## おわり

こんだけ書いておけば、未来の自分でもすぐ使える気がします。
C#でテキストファイル読み込み

テキストファイルの読み込み

```.cs
using(var st = new System.IO.StreamReader("test.txt"))
{
    string line;
    while(null != (line = st.ReadLine())
    {
        //line に一行ずつ入る （改行コードは入っていない）
    }
}
```

.Net2.0 くらいからこの方法で読んでいる。
その頃、var はなかったけどね。
while の中がごちゃっとしてて入門者には説明が面倒なのと、
line のスコープが微妙に広いのが難点だけど、これが一番シンプル。

昔からあるファイル関係のクラスは、テキスト、ストリーム、staticメソッド、抽象クラス、継承とか
ごちゃごちゃしてるから「テキスト読み込みならこう書く」と決めておくのがいいと思う。
QNAP NAS で MyDNS ddns サービスを登録する

ddns サービスとして　MyDNS.jp　が使い勝手が良いので利用中。
MS-Windows10 PC に　DiCE をインストールし自動更新をしていたが、ときどき動作しなくなり数か月ごとに再設定する必要があった。

今まで MS-Windows10 の PC だけしかない環境だったが、QNAP NAS を導入したのでそれを使って　MyDNS　の更新ができるように設定した。

# 環境

- QNAP TS-673
- QTS バージョン 4.5.1.1480

# 設定画面

QTS　にログオン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/aeb217ca-3802-5277-0539-c7f4e7a43ccf.png)

「コントロールパネル」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1bcb1303-5f6f-84eb-0332-5696d5b8d4e0.png)

「ネットワークとファイルサービス」-「ネットワークと仮想スイッチ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2200a909-eee2-08c4-ca66-62b4473e2563.png)

「DDNS」-「追加」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/01ceda9f-6c91-9ccd-fd86-832abf2465c7.png)

「Customized」を選ぶ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/28769de6-48b1-981d-f1ae-e7567ec4fe15.png)

# 設定内容


MyDNS　サイトの「HOW TO USE」
https://www.mydns.jp/?MENU=030
の
「STEP 4. Send  IP ADDRESS」
によると、以下の通知方法が使えるらしい。

- POP3 ... メールソフトなど
- IMAP4 ... メールソフトなど
- FTP ... WEBカメラやスクリプトなど
- HTTP-BASIC ... DiCEやスクリプトなど
- HTTP-DIRECT ... 任意のIPアドレスを直接通知

このうち、


> HTTP-DIRECTの場合
>  
> 通知URL : http(s)://www.mydns.jp/directip.html
> 通知方法 : POST or GET
> 
> 必須パラメータ
> MID : マスターID
> PWD : パスワード
> IPV4ADDR : IPv4アドレス(※)
> IPV6ADDR : IPv6アドレス(※)
> ※どちらか一方があればOK、どちらもないとNGとなります
> 
> 通知例 : http(s)://www.mydns.jp/directip.html?MID=MasterID&PWD=Password&IPV4ADDR=IPv4Address&IPV6ADDR=IPv6Address

この方法が使えそうです。

自分の情報が

- Master ID mydns999999999
- パスワード　fugafuga

であったとすると、以下のように設定します。

```

https://www.mydns.jp/directip.html?MID=%USER%&PWD=%PASS%&IPV4ADDR=%IP%
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/371d77b5-25dd-6ebc-27db-346cfaae2480.png)

ホスト名は必要ないのですが、何か入れておかないと登録できませんでした。

これで「適用」を押すと設定されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/01533850-4d28-e9b4-1689-3ef670408795.png)
ImportError: libGL.so.1: cannot open shared object file: No such file or directory への対策

# やりたいこと

* python で import cv2 をやりたい。

# 現象

.pyを実行すると下記エラー。

```
ImportError: libGL.so.1: cannot open shared object file: No such file or directory
```

# 環境

tensorflowのDockerイメージを利用。下記手順で構築した。
https://qiita.com/kenichiro-yamato/items/ec944220321a58310f1f


# 対策

下記を実行したらエラーが出なくなった。

```
pip install opencv-python
```

```
pip install opencv-contrib-python
```

```
apt-get install -y libgl1-mesa-dev
```
[C++] 正規表現で文字列から日付の部分を抜き出す

# もくじ

https://tera1707.com/entry/2022/02/06/144447

# やりたいこと

ファイル名の文字列に日付を表す部分が含まれてるので、それを抜き出したい。
具体的には、「Log_20201026+0900.csv」みたいな感じでログファイル名に日付が入ってる感じになってるので、「20201026+0900」の部分を抜き出したい。

# やり方

正規表現を使う。

# サンプル

```cpp
#include <iostream>
#include <regex>

int main()
{
    // ログファイル名のサンプル
    std::wstring input = L"Log_20201026+0900.csv";
    // 正規表現(数字が8個の後に+or-があって、その後に数字4個、というパターン)
    std::wregex pattern(L"[0-9]{8}[+|-][0-9]{4}");

    std::wsmatch match;
    if (std::regex_search(input, match, pattern))
    {
        std::wcout << match[0].str() << std::endl;
    }

    // regex_searchは、最初にマッチした部分しか取れない
    system("pause");
}

```

`match[0]`の中に、ヒットした部分の文字列が入ってくる。
`regex_search()`は、基本的には検索対象の文字列の中の`ヒットした1つ目の部分`しか取れない様子。
(例えば上のサンプルで`L"Log_20201026+0900＿20201026+0900.csv"`を対象に検索しても、一つ目の「20201026+0900」しか取れない、ということ。)

それを、2つ目以降も取れるようにしようと思うと、見る位置をずらす、などの工夫が必要になる。
→[こちら](https://taiyakisun.hatenablog.com/entry/20140630/1404140319)参照

# 参考

C++標準のregex_search(正規表現)の動作と使用方法
https://taiyakisun.hatenablog.com/entry/20140630/1404140319

正規表現関数（MSDocs）
https://docs.microsoft.com/ja-jp/cpp/standard-library/regex-functions?view=msvc-160
State Pattern

<font color="#00f">あるオブジェクトの状態をクラス化する。サンプルでは、水クラスの状態を、氷、液体、気体という状態を想定し、水クラス、液体クラス、気体クラスとする</font>

[Design Pattarm MENU](https://qiita.com/old_cat/items/852d980bedb9100dd7e3)

以下のクラス構成で確認します

|クラス|説明|
|-----|----|
|Water.class|水を表すクラス<br>水の状態は、固体、液体、気体の３つとする|
|waterState.interface|水の状態を共通化するインターフェイス|
|Ice.class|状態が固体であることを表すクラス|
|Liquid.class|状態が液体であることを表すクラス|
|Air.class|状態が液体であることを表すクラス|
|user(Main.class)|乱数で水の状態を変化させる|

＊user　他の開発者がこのパターンを利用する、という意味合いを含みます

```java:Water.class
class Water{
  waterState state = new Liquid();
  void setState(waterState state){
       this.state=state;
  }
  void show(){System.out.println(state.showState());}
}
```
```java:waterState_interface
interface waterState{String showState();}
```
```java:Ice.class
class Ice implements waterState{
  public String showState() {return "Ice";}
}
```
```java:Liquid.class
class Liquid implements waterState{
  public String showState() {return "Liquid";
  }
}
```
```java:Air.class
class Air implements waterState{
  public String showState() {return "Air";}
}
```
```java:user(Main.class)
public static void main(String[] args){
  Water water = new Water();
  Random rand = new Random();
  for(int i=0;i<10;i++){
    int r = rand.nextInt(30);
    if(r%5==0){water.setState(new Ice());}else{
    if(r%3==0){water.setState(new Liquid());}else{
       water.setState(new Air());
    }}
    water.show();
  }
}}
CFRでclassファイルをデコンパイル

## 経緯
javaでカバレッジ上げろと言われてもどこを通ってないのかさっぱりわからなかったので、コンパイル時にどう展開されているのか調べたかった。

## 解決方法
デコンパイルしてclassファイルを確認すればいい。日本語のサイトだとJADというツールが引っかかるが、これは古いので[CFR](https://www.benf.org/other/cfr/)というデコンパイラを使う。

## 試してみる
シンプルなtry-with-resourcesがどう展開されているのかを確認する。

- Hoge.java

```java 
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.stream.Collectors;

public class Hoge {
	public String config;
	private Hoge() {
		try (BufferedReader br = new BufferedReader(new FileReader("config"))) {
			config = br.lines().collect(Collectors.joining("\n"));
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
}
```

- デコンパイルする

```bash
$ javac Hoge.java
$ java -jar cfr-0.150.jar --tryresources false --decodefinally false Hoge.class > HogeHoge.java
```

- 結果

```java
/*
 * Decompiled with CFR 0.150.
 */
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.stream.Collectors;

public class Hoge {
    public String config;

    private Hoge() {
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader("config"));
            try {
                this.config = bufferedReader.lines().collect(Collectors.joining("\n"));
            }
            catch (Throwable throwable) {
                try {
                    bufferedReader.close();
                }
                catch (Throwable throwable2) {
                    throwable.addSuppressed(throwable2);
                }
                throw throwable;
            }
            bufferedReader.close();
        }
        catch (IOException iOException) {
            iOException.printStackTrace();
        }
    }
}
```

## 余談
カバレッジの確認でjacocoを利用していたが、jacocoのバージョンを上げたら余計な分岐の確認をしなくなったのか、無理してでコンパイルしなくても網羅できるようになった。
Python-LEGO Mindstormsのセンサーをスレッドで非同期処理する

今回はLEGO Mindstorms EV3(以降EV3)のセンサーを複数待機状態にして、それぞれがしきい値に達した際になにかしらのアクションを行わせる。センサーごとにスレッドを定義し、それぞれのスレッドを非同期に処理させていく。

[次回](https://qiita.com/Hiroki-Fujimoto/items/72005dd54a182249a951)ではライントレースも合わせて行っている。

## EV3について
教育版 [LEGO® MINDSTORMS EV3](https://afrel.co.jp/product/ev3-introduction)

## 本記事内での環境  
* PC
Windows10
Python 3.7.3
開発環境 VisualStudioCode  

* EV3
ev3dev
[APIリファレンス](https://ev3dev-lang.readthedocs.io/projects/python-ev3dev/en/stable/spec.html)

環境構築やソースコードの作成、実行方法は[こちら](https://qiita.com/Hiroki-Fujimoto/items/6ce278411ca151fee750)


## EV3のモデル
今回は超音波センサーとタッチセンサーが付いている。
モーター等は利用しないが安定して設置するために付いている。

<img width="500" alt=".png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440646/e8568a29-aa5f-168f-0b80-9a47bff959a6.jpeg">

## threading
Pythonにはいくつかの種類の非同期処理ライブラリがあるが、今回はthreadingを使って複数スレッドをたて、センサーの非同期処理をしていく。  

スレッドとしては、タッチセンサーが押されたことを判定するスレッドと、超音波センサーが15cm以内に物体を検知したことを判定するスレッドを用意して、それぞれ非同期で処理を行う。

以下がコード。

~~~ thread_test1.py
from ev3dev2.sound import Sound
from ev3dev2.motor import LargeMotor, OUTPUT_B, OUTPUT_C
from ev3dev2.sensor import INPUT_1, INPUT_4
from ev3dev2.sensor.lego import TouchSensor, UltrasonicSensor
import time
import threading

sound = Sound()
sound.set_volume(30)
touch = TouchSensor()
ultrasonic = UltrasonicSensor()


def wtouch():    
    while True:
        if touch.is_pressed:
            print('Touched')
            sound.tone(1000, 200)
            time.sleep(1.0)
            break
        

def wsonic():
    while True:
        if ultrasonic.distance_centimeters < 15:
            print('Detected')
            sound.tone(500, 200)
            time.sleep(1.0)
            break
        

def main():
    th1 = threading.Thread(target = wtouch)
    th2 = threading.Thread(target = wsonic)

    th1.start()
    th2.start()
    print('Thread is started')


if __name__ == '__main__':
    main()
~~~

関数として`def wtouch`でタッチセンサーの判定を用意し、
`def wsonic`で超音波センサーの判定を用意している。  
判定時には`print`でコンソールに文字を出力するのに加えそれぞれ異なるビープ音がEV3から鳴るようになっている。

また`def main`でそれぞれの関数をスレッドとして設定し、
スレッドを開始させている。開始時にはコンソールに文字を出力している。  

## 実行
実行してみると非同期でセンサーの判定が行われているのがわかる。  
以下では2回実行していて、1回目は超音波、タッチの順で判定してプログラムが終了しており、2回目ではタッチ、超音波の順で判定してプログラムが終了している。

<img width="600" alt="1-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440646/431d5b69-4cf3-af7d-4f98-daaadfa92a72.png">

<img width="200" alt="66.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440646/78e9d822-2a25-0b96-5256-b2b303554f7c.jpeg">　　　　　<img width="200" alt="67.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440646/99e7fb3d-01f6-4766-ed8d-7ed026a795fb.jpeg">