OmniAICreator/Qiita-1.07M huggingface dataset:
Aura componentでの覚え

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


いつも思い出すのに苦労するので、ここに覚えを書いておきます。

```
system.debug(Logginglevel.INFO,'===== '+ up ); 
```


# 編集の初期化の書き方

```
List型の変数　List<String> myStrings = new List<String>{'a','b'}; 

Map型の変数　Map<String, String> MyStrings = new Map<String, String>{'a' => 'b', 'c' => 'd'.toUpperCase()};
```

# コーディング

+ [Syntax to add AuraHandledException](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JfB32)
+ [表示された数式項目をクリップボードにコピーしたい](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000077CcUq)

:::note
visualforceでは、document.execCommand('copy')で実行できるようです。

Aura コンポーネントでは以下にサンプルコードがありました。

https://salesforce.stackexchange.com/questions/221505/how-to-perform-copy-to-clipboard-in-lightning-component
:::


# その他

+ [4列カラムのページレイアウトを作る](https://qiita.com/Keiji_otsubo/items/cacfc294b8f6ea90c8c1)

+ [aura と LWC の両方が同じページ上にある場合、Aura JS ハンドラーから LWC に存在する特定のクラスを持つ「div」を見つけることはできますか?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007HMQ5Z)

:::note
LWC コンポーネントの名前または aura:id がわからず、それが動的にレンダリングされる場合、事態はさらに複雑になります。ただし、LWC 内で使用されている構造またはクラスについて何か知っていれば、それを見つけることができる可能性があります。

LWC が合成シャドウを使用していることを考慮すると、「総当たり」方式で DOM を介してクエリを実行できますが、これは保守性の問題と潜在的なパフォーマンスへの影響のためお勧めできません。

概念的なアプローチは次のとおりです。

Aura コンポーネントの DOM 内の LWC ルートとなる可能性のあるすべての要素をクエリします。
これらの潜在的なルートを反復処理して、 shadowRootに飛び込み、目的の要素を見つけようとします。
JavaScript の例を次に示します。

```
var potentialLWCRoots = component.getElement().querySelectorAll('*');
var foundDiv = null;
for (var i = 0; i < potentialLWCRoots.length; i++) {
    var potentialDiv = potentialLWCRoots[i].shadowRoot && potentialLWCRoots[i].shadowRoot.querySelector(".my-lwc-class");

    if (potentialDiv) {
        foundDiv = potentialDiv;
        break;
    }
}

if (foundDiv) {
    console.log("Found the div!");
} else {
    console.log("Did not find the div.");
}
```

:::

# なぜかエラーが消えない

+ [Can anyone please let me know what is wrong with this ?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007O2YhT)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ffc5fb40-c247-7897-7ca1-7d0d2620af72.png)


:::note
 I have tried the way you mentioned already, but the error is persistant. Resolved the challenge in another Playground console for time being. Thanks for the responses! Cheers!
:::

# 名前空間

+ [管理パッケージに挑戦中です。名前空間が設定されたAuraコンポーネントをVSCodeで取得すると、名前空間が消えているこれはVSCodeの事象でしょうか？](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007VhhPt)

:::note
同じようなことが質問されています。（解決してないですが...）

https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T4Rq4SAF

VFpageとちがって、auraのコントローラにはつかないようなことが質問されています。
Lightning コードと書かれていますが、2016年当時なのでAuraのことだと思います。

https://salesforce.stackexchange.com/questions/150418/namespace-in-lightning-component
:::
初心者用PHP正規表現（preg_replace）

正規表現てむずいなと感じたので、忘れないうちにメモとして残します。

今回はPHPの正規表現の``preg_replace``を使っていきます。

文字通り指定した文字を書き換えるものです。

百聞は一見に如かずなので、以下を例に自分の用途に合わせて行ってください。

```
https://firebasestorage.googleapis.com/v0/b/project-auth.appspot.com/o/images/kLF0eEW2D2QfQEfO95wnpQahODl2/image.jpg?alt=media&token=5d91bc75-e63d-4594-bf5d-265336ef925e
```

このようなURLの``images/``を``images%2F``に変換します。


```regex.php
$valid_url=https://firebasestorage.googleapis.com/v0/b/project-auth.appspot.com/o/images/kLF0eEW2D2QfQEfO95wnpQahODl2/image.jpg?alt=media&token=5d91bc75-e63d-4594-bf5d-265336ef925e
preg_replace('/(images)\//', '$1%2F', $valid_url); // images%2F
```

``$1``は``()``でくくったものを表します。

今回で言うと、``images``です。

つまり、``()``は変換したくない値をくくって``$1``で表せるという意味です。

また、``()``が複数ある場合は、例えば``/(123)(456)\//``を``$1$2%2F``とすることで``123456%2F``とすることができます。

正規表現はむずい。。。

正規表現はむずかしく慣れるまでに時間がかかると思います。僕なんかはあまり触れたくないので、全く勉強していません。

ただ、必要になった時できるものだと思っているので皆さんもそのくらいの軽い気持ちで取り組んでください！

以上、「初心者用PHP正規表現（preg_replace）」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
PHP 簡易掲示板作成　データ保存編 #1

#目標
・「名前」と「コメント」の入力フォームから値を送信


・テキストファイルに「1投稿につき1行」で保存
1. テキストファイルを指定する
2. 指定したテキストファイルを開く
3. テキストファイルに書き込む
4. テキストファイルを閉じる

・保存フォーマット
投稿番号<>名前<>コメント<>投稿日時
`$num."<>".$name."<>".$str."<>".$date;`
1.　「名前」と「コメント」を受け取る
2.　受け取った値を変数に代入
3.　日時を取得する
4.　投稿番号を取得する
5.　1~4を組み合わせて投稿を作成

```:sample.txt
1<>yuya<>完成<>2021/2/8 10:13:16
2<>yuya<>完成<>2021/2/8 10:13:22
3<>yuya<>完成<>2021/2/8 10:13:25
```
#「名前」と「コメント」の入力フォームから値を送信
入力フォームを作成

```html:HTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>簡易掲示板</title>
  </head>

  <body>
      <form action="" method="post">
          <input type="text" name="name" placeholder="名前">
          <input type="text" name="str" placeholder="コメント">
          <input type="submit" name="submit" value = "投稿">
      </form>  
  </body>
</html>
```

#テキストファイルに「1投稿につき1行」で保存
１. テキストファイルを指定する

```php:PHP
<?php
    $filename = "sample.txt";
?>
```
２. 指定したテキストファイルを開く
投稿内容を追記したいのでオープンモードを　`"a"`にする

```php:PHP
<?php
    $fp = fopen( $filename, "a");
?>
```
３. テキストファイルに書き込む
`PHP_EOL`：改行コードを出力する
→改行されて追加される
書き込む内容は`$comment`

```php:PHP
<?php
    fwrite($fp, $comment.PHP_EOL);
?>
```
４. テキストファイルを閉じる

```php:PHP
<?php
    fclose($fp);
?>
```
まとめ

```php:PHP
<?php

    // ファイルの指定
    $filename = "sample.txt";

    //　ファイルを開く
    $fp = fopen( $filename, "a");

    // ファイルに記入
    fwrite($fp, $comment.PHP_EOL);

    // ファイルを閉じる
    fclose($fp);
?>
```
#保存フォーマット：`投稿番号`<>`名前`<>`コメント`<>`投稿日時`
１. 「名前」と「コメント」を受け取る
２. 受け取った値を変数に代入

```php:PHP
<?php
    $name = $_POST["name"];
    $str = $_POST["str"];
?>
```

３. 日時を取得する

```php:PHP
<?php
    $date = date("Y/n/j G:i:s");
?>
```
４.投稿番号を取得する
`file_exists`関数　　ファイルが存在→ `true`
                    ファイルが不在→ `false`

`count`関数
→配列の要素の数を数え、それを数値として返す

`file`関数
→ファイルを読み込み行ごとに配列にして返す

ファイルが存在する場合　　→　少なくとも１行は投稿がある　→　投稿番号 ＝ 行数 + １
ファイルが存在しない場合　→　１行もない　 →　初投稿　   →　投稿番号 ＝ １

```php:PHP
<?php
    if(file_exists($filename)){
        $num = count(file($filename)) + 1;
    }else{
        $num = 1;
    }
?>
```
５. 投稿を作成

```php:PHP
<?php
    $comment =$num."<>".$name."<>".$str."<>".$date;
?>
```
まとめ

```php:PHP
<?php
    //値の受け取りと変数への代入
    $name = $_POST["name"];
    $str = $_POST["str"];
    
    //日付の取得
    $date = date("Y/n/j G:i:s");
    
    //投稿番号の取得
    if(file_exists($filename)){
        $num = count(file($filename)) + 1;
    }else{
        $num = 1;
    }
    
    //投稿の作成
    $coment =$num."<>".$name."<>".$str."<>".$date;
?>
```

#まとめ

```php:PHP
<?php
    //値の受け取りと変数への代入
    $name = $_POST["name"];
    $str = $_POST["str"];
    
    //日付の取得
    $date = date("Y/n/j G:i:s");
    
    //投稿番号の取得
    if(file_exists($filename)){
        $num = count(file($filename)) + 1;
    }else{
        $num = 1;
    }
    
    //投稿の作成
    $coment =$num."<>".$name."<>".$str."<>".$date;

    // ファイルの指定
    $filename = "sample.txt";

    //　ファイルを開く
    $fp = fopen( $filename, "a");

    // ファイルに記入
    fwrite($fp, $comment.PHP_EOL);

    // ファイルを閉じる
    fclose($fp);
?>
```
manimの作法 その46

#概要

manimの作法、調べてみた。
作品、作ってみた。
ＶＪです。

#生成した動画

youtubeにアップしたら、「著作権侵害の申し立て」が、付いた。

https://www.youtube.com/watch?v=y8P6qUSxk_g


以上。
Your certificate 'XXXXXXXX.cer' is not valid, please check end date and renew it if necessary

`match` を使用していると証明書の期限切れによって以下のエラーになってしまうことがある。

```
Your certificate 'XXXXXXXX.cer' is not valid, please check end date and renew it if necessary
```

その場合どうすればよいか。

# 方法1
fastlane match nukeでごそっと削除。
削除対象を細かく指定できないので、私はあまりやりたくない。

# 方法2
証明書管理リポジトリから、期限の切れた証明書の `.cer` `.p12` および、その証明書と紐づくプロビジョニングをすべて削除して、comit & pushする。
また、dev portalから削除したプロビジョニングを削除する。 

参考
https://sarunw.com/posts/how-to-renew-expired-certificate-with-fastlane-match/
プロのように英語でGoogleを使用する方法

### グーグルを上手に使う方法は誰にとっても最も重要なスキルの1つです。開発者だけでなく。

皆さん忙しいので、早速始めましょう～

#1 引用符（"）を使って、「完全一致検索」を強制します。

`"what is html"`

![use-google-like-a-pro-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890686/c4f4c9ad-577d-ecae-65de-8906fdd260ae.png)

#2 「AND」 は、両方の用語に関連する結果のみを返します。

`react AND vue`

![use-google-like-a-pro-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890686/e5875ddf-3e7d-4707-2650-a8c10fe1aa1c.png)

#3 同様に、「OR」 を使用して、検索語の1つに関連する結果を取得することもできます。

`(html OR css) tutorial`

![use-google-like-a-pro-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890686/6de94247-b87a-fc8a-a573-0cd96e0ba992.png)

#4 「-」は、用語またはフレーズを含む結果を除外します

`javascript -css`

![use-google-like-a-pro-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890686/20c0da1a-70c7-5d29-9a11-cd30e880ec72.png)

#5 「*」ワイルドカードをプレースホルダーとして使用できます。任意の単語またはフレーズに置き換えられます。

`"how to code * for beginners"`

![use-google-like-a-pro-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890686/cf89c7f9-1eae-99b7-d3a6-1c1223769f6a.png)

#6 「site: + 検索語」を使用して単一のWebサイト内を検索する

`site:qiita.com html`

![use-google-like-a-pro-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890686/eb0d5251-3c7f-4e9a-0ae1-5c1b74b54314.png)

#7 特定のファイルタイプをお探しですか？ 「filetype:」を使用してください。

`filetype:pdf html`

![use-google-like-a-pro-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890686/79642be9-4eef-293c-6589-d125a35c16ed.png)

---

この7ポイントで日常生活が良くなることを願っています。

**ハッピーライフハック！**

追記：
**このツイッターを参考にして書きました。引用元を記載しておらず申し訳ありませんでした。**
参考のURL：https://twitter.com/denicmarko/status/1356850984048279552
3日目：UITextFieldキーボードをニョキっと配置、リアルタイムに計算するアプリ

#3日目のアプリ
UITextFieldキーボードをニョキっと配置、リアルタイムに計算するアプリ

##画面キャプチャ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/959530/09352d98-4b4d-5693-be05-fe7631bf6890.gif" width=50%>

##以下の流れで作りました。
1. storyboadに1つのUITextFieldと、2つLabelを配置
2. ボタンを端末が変わってもレイアウトが崩れないように設定
3. 上記要素をViewController.swiftへoptionドラッグして紐付ける
4. 紐付けができたら、ViewController.swiftでコードを書く

##できたこと
+ UITextFieldの配置ができるようになった
+ デバイスサイズが変わってもレイアウトが崩れないように設定できた
+ テキスト入力エリア毎にソフトウェアキーボードを変更して表示できるようになった
+ 文字入力したものを配列に格納することができるようになった
+ 文字を入力すると、リアルタイムに計算結果を出力することができるようになった
+ UITextField内がキーボードのデリートキーで空欄になった時の処理を入れることができた
##書いたコードを共有します！

```
import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var beanWeight: UITextField!
    @IBOutlet weak var amountWater: UILabel!
    @IBOutlet weak var time: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        beanWeight.placeholder = "豆の量を入力してください" //ステークホルダー
        self.beanWeight.keyboardType = .numberPad //キーボードタイプ
        
        beanWeight.delegate = self
        
        beanWeight.addTarget(self, action: #selector(getWeight(textField:)), for: UIControl.Event.editingChanged) //何か入力があったら呼び出す
        
    
    }
    
    @objc func getWeight(textField: UITextField) {
        
        var changeInt:Double = 0.0
        var calWater:Double = 0.0
        var calTime:Double = 0.0
        
        if  beanWeight.text!.isEmpty {  //豆の量が空になったら処理
            changeInt = 0
            calWater = 0
            calTime = 0
               beanWeight.text = ""
               amountWater.text = String(calWater)
               time.text = String(calTime)
               beanWeight.endEditing(true)
        } else {  //豆の量を入力されたら処理
            changeInt = Double(beanWeight.text!)!
               calWater = changeInt * 180.0 / 10.0
               calTime = changeInt / 10.0 * 4.0 * 60.0
           amountWater.text = String(calWater)
               time.text = String(calTime)
        }
}
}

```

##感想
3日目。Qiitaに記事をアップしたつもりで下書きになっていた。。
manimの作法 その45

#概要

manimの作法、調べてみた。
begin_ambient_camera_rotation使ってみた。

#サンプルコード

```
from manimlib.imports import *

class dSurface(ParametricSurface):
	def __init__(self, **kwargs):
		kwargs = {
			"u_min": -1.5,
			"u_max": 1.5,
			"v_min": -1.5,
			"v_max": 1.5,
			"checkerboard_colors": [GREEN, BLUE],
			"checkerboard_opacity": 0.5
		}
		ParametricSurface.__init__(self, self.func, **kwargs)
	def func(self, x, y):
		return np.array([x, y, x**2 + y**2])

class test(ThreeDScene):
	def construct(self):
		self.set_camera_orientation(phi = 75 * DEGREES, theta = 30 * DEGREES)
		axes = ThreeDAxes()
		self.add(axes)
		surface = dSurface()
		self.play(ShowCreation(surface))
		self.move_camera(phi = 45 * DEGREES, theta = 30 * DEGREES)
		self.wait()
		self.begin_ambient_camera_rotation()
		self.wait()
		self.remove(surface)
		sphere = ParametricSurface(lambda u, v: np.array([1.5 * np.cos(u) * np.cos(v), 1.5 * np.cos(u) * np.sin(v), 1.5 * np.sin(u)]), v_min = 0, v_max = TAU, u_min = -PI / 2, u_max = PI / 2, checkerboard_colors = [RED_D, RED_E], resolution = (15, 32))
		self.play(ShowCreation(sphere))
		self.wait()
		self.remove(sphere)
		cylinder = ParametricSurface(lambda u, v: np.array([np.cos(TAU * v), np.sin(TAU * v), 1.0 * (1 - u)]), resolution = (6, 32))
		self.play(ShowCreation(cylinder))
		self.wait()
		self.remove(cylinder)
		w = 1
		surface_01 = ParametricSurface(lambda u, v: v * complex_to_R3(np.exp(1j * w * u)), u_min = 0, u_max = TAU, v_min = 1, v_max = 3, checkerboard_colors = None, fill_color = BLUE_B, fill_opacity = 0.8, stroke_color = BLUE_A, resolution = (60, 10))
		self.play(ShowCreation(surface_01))
		self.wait()
		self.remove(surface_01)
		surface_02 = ParametricSurface(lambda u, v: v * complex_to_R3(np.exp(1j * w * u)) + OUT * u / PI * 2, u_min = 0, u_max = TAU, v_min = 1, v_max = 3, checkerboard_colors = None, fill_color = BLUE_D, fill_opacity = 0.8, stroke_color = BLUE_A, resolution = (60, 10))
		self.play(ShowCreation(surface_02))
		self.wait()
		self.remove(surface_02)
		surface = ParametricSurface(lambda u, v: np.array([u, v, np.sin(u ** 2 + v ** 2)]), u_min = -4, u_max = 4, v_min = -4, v_max = 4, resolution = (120, 120))
		self.play(ShowCreation(surface))
		self.wait()
		self.remove(sphere)





```

#生成した動画

https://www.youtube.com/watch?v=Jif6TiDXsAk

以上。
【Kotlin】日時型LocalDateTimeを使用する

#はじめに
Javaでは日時を扱うためのLocalDateTime型が用意されており、もちろんKotlinからもそれを使うことができます。
※コメントで指摘がありましたので再度修正しました。

日時はこの型を利用して処理を行うわけですが、使い勝手が良くありません。

おまけにコンパイル時にワーニングを出します。
さらに検索しても使い方が出てきません。

ちょっと日時を扱いたかったのに挫折する人も多いでしょう。

なので日時を簡単に扱うためのクラスそのものと、そのクラスを使った日時の処理を記載します。
初歩的な処理しか書いてないので必要があれば各自で追加してください。

#日付操作クラスの作成
日付を操作するためのクラスを作ってしまいましょう。
ソースは

```DateTimeCtrl.kt
class DateTimeCtrl {
    @SuppressLint("NewApi")
    fun GetNow() : LocalDateTime{
        return LocalDateTime.now()
    }
    fun GetNowStr(pattern: String) : String{
        val dt = GetNow()
        return Format(dt,pattern)
    }

    @SuppressLint("NewApi")
    fun Format(date : LocalDateTime, pattern: String) : String{
        val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern(pattern)
        return date.format(formatter)
    }

    @SuppressLint("NewApi")
    fun Parse(str : String, pattern: String) : LocalDateTime{
        val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern(pattern)
        val dt: LocalDateTime = LocalDateTime.parse(str,formatter)
        return dt
    }
}
```

ToDoで警告を回避していたのを修正

#日時操作クラスの使い方
さっそく使って見ます。

```MainActivity.kt
class MainActivity : AppCompatActivity() {
    private val DateTime = DateTimeCtrl()
```

使いたいクラス内で定義します。

```MainActivity.kt
    DateTime.GetNowStr("yyyy/MM/dd HH:mm:ss.SSS")
```

現在の日時を文字列型で取得します。引数として文字列フォーマットを渡します。

|文字|説明|
|:--:|:--:|
|yyyy|年を西暦を4桁で表示|
|MM|月を表示|
|dd|日を表示|
|HH|時を24時間形式で表示|
|mm|分を表示|
|ss|秒を表示|
|SSS|ミリ秒を表示|

あとは一気に説明します

```MainActivity.kt
    // 現在日時を日時型で取得
    val d = DateTime.GetNow() 
    // 現在日時を指定したフォーマットの文字列で取得
    val s1 = DateTime.GetNowStr("yyyy/MM/dd HH:mm:ss.SSS")
    // 日時型を指定したフォーマットの文字列に変換
    val s2 = DateTime.Format(d,"yyyy/MM/dd HH:mm:ss.SSS")
    // 指定したフォーマットの日時文字列を日時型に変換
    val d2 = DateTime.Format(s2,"yyyy/MM/dd HH:mm:ss.SSS")
```
#最後に
たったこれだけなのですが、工夫次第で色々な用途に使うことが出来るかと思います。
年月日それぞれの要素の単体取得や設定、時分秒の加減算などあれば便利そうですね。
AWSの「AutoScaling」とは何か？

今回はAWSの**「AutoScaling」**　について学んだ事をアウトプットさせて頂きたいと思います。

##AutoScaling
**AutoScaling**とは、インスタンスを設定した上限に合わせて自動で数量を調整してくれるAWSのサービスになります。例えば、ユーザーアクセスをELBで2つのインスタンスに負荷分散をしていたとしても、イベント開催などで爆発的にユーザーのアクセスが集中してしまった場合などは、ELBだけでは対策することができません。EC2インスタンス自体の数量をアクセスに合わせて一時的に増加させる必要が出てきます。急なアクセス集中のためにサーバーが落ちてしまうなどが起きると企業にとっては大きな機会損失になります。
そのような自体を予め防止するために**AutoScaling**があったります。

###AutoScalingを作成するためには?
まずAutoScalingを作成するためには、**起動テンプレート**を設定する必要があります。
起動テンプレートは、「何のインスタンスを使うか？」を決めるものです。
具体的には「AMI」、「インスタンスタイプ」、「Key Pair」、「セキュリティグループ」はそれぞれどうするかと言ったものになります。
「AMI」や「インスタンスタイプ」など上記の単語についてイメージが沸かないという場合は、まずはこちらの記事を参考にしてみてください。
https://qiita.com/Shun-Hoso/items/a4824c3d9d15ebb86ae9

ちなみに**起動テンプレート**似たようなものとして、**起動設定**というものがあります。
起動テンプレートは、AutoScalingで使用するインスタンスのバージョン管理ができるのに対して、起動設定では別の設定ファイルとして管理する必要があり、AWS（2021年2月時点）では、起動設定よりも起動テンプレートが推奨されています。

起動テンプレートを作成した後は、いよいよ**Auto Scaling group**を設定します。
Auto Scaling groupでは、どの起動テンプレートを使用し、どこのサブネットにどの程度の数量を設置するかを指定するものになります。数量では、インスタンスの最小数、希望数、最大数などを設定します。
また、Auto Scaling groupではスケーリングポリシーというものを設定することができます。スケーリングポリシーとは、インスタンスを追加、削除する時の条件を設定するものと思って頂くと良いかと思います。
ではこのスケーリングポリシーの条件とは一体何を基準にしたら良いのでしょうか？
**結論、AWSのCloudWatchのメトリクス（情報）を基準にしたら良いと思います。**

**Auto Scaling groupを設定とCloudWatchは情報を紐付ける事ができます。**例えば、CloudWach側の設定でCPU使用率が70%以上を越えたらアラームを発信、CPU使用率が30%を下回ったらアラームを発信するなどの設定をしていた場合、こちらのアラーム発信に合わせて、Auto Scaling groupで定義していたスケーリングポリシーの内容が実施されるという事が可能になります。
また、**Auto Scaling groupの設定はELBのターゲットグループと連携させることもできます。**
ELBは、複数のインスタンスからどのインスタンスを使用するのが最適であるかを自動判断してくれるAWSのサービスになります。

ELBに関しては、以前こちらの記事を書きましたので宜しければ参考にしてみてください。
https://qiita.com/Shun-Hoso/items/17fae270f52eee3ffae7

###まとめ
Auto Scaling groupとは、インスタンスを設定した上限に合わせて自動で数量を調整してくれるAWSのサービスです。Auto Scalingを作成するためには、起動テンプレート「使用するインスタンス」の作成が必要になります。また、Auto Scaling group「何を基準にどこのサブネットにどのくらい設置するか」も合わせて設定もすることができ、こちらの設定をすることでCloudWach、ELBなどと連携することができます。
サーバーの負荷を軽減させるために、ELBの設定なども大切になりますが、それだけでは対応しきれないケースをあるので、Auto Scalingまで設定することでより安定稼働した状態でアプリケーションを公開することができます。


この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。
https://aws-cloud-tech.com
aws ecs register-task-definition --cli-input-json file://〇〇.json でエラーが出る

# 課題
```
aws ecs register-task-definition --cli-input-json file://〇〇.json
```

を実行しようとした時に

```
An error occurred (IncompleteSignatureException) when calling the RegisterTaskDefinition operation: 'ecr' not a valid key=value pair (missing equal-sign) in Authorization header: 'AWS4-HMAC-SHA256 Credential=aws ecr get-login-password --region us-east-2 | docker login --username 〇〇 --password-stdin 〇〇.dkr.ecr.〇〇.amazonaws.com/〇〇'.
```
という認証系のエラーが出る

## 解決法
ユーザー情報を確認しておかしかったら再設定する

```
$ aws configure
AWS Access Key ID [****]: 〇〇
AWS Secret Access Key [****]: 〇〇
Default region name [us-east-2]: 
Default output format [json]: 
```
設定したのちに再度コマンドを実行する

```
% aws ecs register-task-definition --cli-input-json file://〇〇.json
```
Go言語のバージョンを切り替えるためのgoenvをインストールする方法



```
git clone https://github.com/syndbg/goenv.git ~/.goenv
```
として`~/.goenv`を作成する。その後`.zshrc`に環境変数とgoenvの初期化を追加する。

```bash
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
```

記述したら、`source ~/.zsrhc`として設定を再読込する。この状態でgoenvが使えるようになる。

次にgo 1.14.14をインストールする。

```
goenv install 1.14.14
```

詳細なgoenvのインストールは、[goenv/INSTALL.md at master · syndbg/goenv](https://github.com/syndbg/goenv/blob/master/INSTALL.md#installation) を参照すること。
HTMLファイルをpythonでPDF、イメージ出力

# HTMLファイルをPythonでPDF、イメージ出力

ソフトウェア、パッケージのインストール

wkhtmltopdf ... https://wkhtmltopdf.org/
wkhtmltopdf ... https://github.com/qoda/python-wkhtmltopdf
pdfkit ... https://github.com/JazzCore/python-pdfkit
imgkit ... https://github.com/jarrekk/imgkit

## Dockerイメージ作成

1. `wkhtmltopdf` `pdfkit` `imgkit` は `pip install xxx` しバージョン指定して `requirement.txt` に追加
2. `apt-get install -y wkhtmltopdf` wkhtmltopdfをインストール
3. そのままだとPDF、イメージ出力で日本語が表記されないため `IPAexfont` をダウンロードし `/usr/share/fonts` に追加


```Dockerfile
FROM python:3.7.4

WORKDIR /app
ADD . /app

RUN apt-get update && apt-get install -y wkhtmltopdf && apt-get clean;

RUN wget https://moji.or.jp/wp-content/ipafont/IPAexfont/IPAexfont00401.zip \
    && unzip IPAexfont00401.zip \
    && mv IPAexfont00401 /usr/share/fonts \
    && fc-cache -f

RUN pip install --upgrade pip
RUN pip install -r requirements.txt

ENV TZ Asia/Tokyo
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV PYTHONPATH $PYTHONPATH:/app

ENV PORT 8080
EXPOSE 8080
```

**Dockerビルド、実行**

```
$ docker build -t pg-news .
$ docker run --name pg-news -p 8080:8080 -v ~/Sites/pg-news/:/app -it --rm pg-news bash
```

## イメージ出力

`imgkit.from_url` を使うことでWEBサイトをイメージ出力できる

```Python
import imgkit


def main():
    imgkit.from_url('https://qiita.com/about', 'sample_imgkit.jpg')


if __name__ == "__main__":
    main()

```

```
root@e5f35d156c6a:/app# python sample_imgkit.py
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
Loading page (1/2)
Rendering (2/2)
Done
```

*実行結果*
![sample_imgkit.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59264/24b2ab57-f796-1457-748b-9cf3a1d0a806.jpeg)

## PDF出力

`pdfkit.from_url` を使うことでWEBサイトをPDF出力できる

```Python
import pdfkit


def main():
    pdfkit.from_url('https://qiita.com/about', 'sample_pdf.pdf')


if __name__ == "__main__":
    main()
```

```
root@e134508e2c16:/app# python sample_pdfkit.py
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
Loading page (1/2)
Printing pages (2/2)
Done
```

`sample_pdf.pdf` がPDF出力される

## 備考

内部のHTMLを指定することもできる
HTMLをイメージ化してTwitterアップなどいろんな使い道が出来そう

---

簡単にHTMLをイメージ、PDF出力することが出来ました
いいね！と思ったら LGTM お願いします :clap::clap::clap:

【PR】週末ハッカソンというイベントやってます！ → https://weekend-hackathon.toyscreation.jp/about/
npmに公開する前に、パッケージの動作確認をする方法

## はじめに

`npm publish` で公開する前にパッケージを確認する方法として、以下の 2 つがありそうです。

- `npm link` で、開発中にパッケージの動作確認を行う
- `npm pack` で、`npm publish`で公開される内容を事前に確認する

それぞれ見ていきます。

## 環境

npm: 6.14.10

## 開発中にパッケージの動作確認を行う

npm-link を使うと、ローカルの別のパッケージから、確認したいパッケージを呼び出すことができます。

> npm link (in package dir)
> npm link [<@scope>/]<pkg>[@<version>]
>
> alias: npm ln

引用: [npm-link](https://docs.npmjs.com/cli/v6/commands/npm-link)

npm-link は次の 2 ステップで行います。

### 1. 参照したいパッケージで、`npm link`を実行する

参照したいパッケージで`npm link`を実行すると、グローバルな`node_modules`に、コマンドを実行したパッケージへのシンボリックリンクを作成します。

(グローバルな`node_modules`は、Linux だと`$(npm prefix -g)/lib/node_modules/$PACKAGE_NAME`になります)

(Windows だと`$(npm prefix -g)\node_modules\$PACKAGE_NAME`になりそうです)

また、パッケージ内の bin を `$(npm prefix -g)/bin/$PACKAGE_NAME` にリンクします。

参考: [npm-prefix](https://docs.npmjs.com/cli/v6/commands/npm-prefix)

### 2. 1.のパッケージを参照したい場所で`npm link $PACKAGE_NAME`を実行する

`npm link $PACKAGE_NAME`を実行すると、現在のフォルダの`node_modules`にグローバルな`node_modules/$PACKAGE_NAME`へのシンボリックリンクを作成します。

`$PACKAGE_NAME` は、ディレクトリ名ではなく、package.json から取得されることに注意します。

パッケージ名の前に[スコープ](https://docs.npmjs.com/cli/v6/using-npm/scope)を付けることができます。スコープは`@scopename/`で定義します。

### 例

例えば以下のような 2 つのパッケージがあるとします。

```tree
root
 ├─ some_module
 |  └─ node_modules
 └─ my_app
    └─ node_modules
```

`my_app`から`some_modules`を参照したい場合、以下のように実行します。

```sh
$ npm prefix -g # 確認用
# /usr
$ cd /root/some_module
$ npm link
# /usr/lib/node_modules/some_module -> /root/some_module
$ cd /root/my_app
$ npm link some_module
# /root/my_app/node_modules/some_module -> /usr/lib/node_modules/some_module -> /root/some_module
```

2 つのステップを一緒に行うこともできます。

```sh
$ cd /root/my_app
$ npm link ../some_module
# /root/my_app/node_modules/some_module -> /usr/lib/node_modules/some_module -> /root/some_module
```

この場合は、パッケージ名ではなく、ディレクトリ名を指定します。

## `npm publish`で公開される内容を事前に確認する

[npm-pack](https://docs.npmjs.com/cli/v6/commands/npm-pack)を使うと、`npm publish`で公開するものと同様のものが`.tgz`形式で出力されます。
これにより、公開前に出荷物を確できます。
(梱包される内容がログに吐き出されますので、分かりやすいです)

```sh
$ npm pack
# npm notice
# npm notice 📦  my_app@0.1.3
# npm notice === Tarball Contents ===
# npm notice 4.6kB dist/my-component.esm.js
# npm notice 5.2kB dist/my-component.min.js
# npm notice 5.5kB dist/my-component.umd.js
# npm notice 1.5kB package.json
# npm notice 6.2kB dist/my-component.esm.js.map
# npm notice 6.2kB dist/my-component.min.js.map
# npm notice 6.2kB dist/my-component.umd.js.map
# npm notice 310B  README.md
# npm notice === Tarball Details ===
# npm notice name:          my_app
# npm notice version:       0.1.3
# npm notice filename:      my_app-0.1.3.tgz
# npm notice package size:  5.2 kB
# npm notice unpacked size: 35.7 kB
# npm notice shasum:        d19a748b51e603fc385ec11134837428de10a0cc
# npm notice integrity:     sha512-8rxQlISLyS9zq[...]X9LBuapw7koLA==
# npm notice total files:   8
# npm notice
# my_app-0.1.3.tgz
```
PostGISでテーブルのSRIDを変更する方法

GDALを使ってPostgresSQL上にデータをインポートした際にSRIDが意図しない値になっていたことがあったので、次のようなSQLを使ってSRIDを変更しました。

```
ALTER TABLE {table_name}
  ALTER COLUMN {geometry_column} TYPE geometry(MULTILINESTRING,4326)
    USING ST_SetSRID({geometry_column},4326);
```
Python: 配列の中身をファイルに保存・読み込み


## ファイル保存
pickleモジュールを利用して配列の中身をファイルに保存します。

```python
>>> import pickle
>>> a = [1,2,3]
>>> f1 = open("aaa", "wb")
>>> pickle.dump(a, f1)
>>> f1.close()
```

## ファイル読み込み
保存したデータを配列として読み込みます。

```python
>>> f2 = open("aaa", "rb")
>>> b = pickle.load(f2)
>>> b
[1, 2, 3]
>>> f2.close()
```
PostgresSQLでテーブル構造を取得する

Oracleで言う所のtable_name DESC;のようなコマンドがpsqlにもありますので、今回はそれをご紹介します。
まず、psqlでデータベースに接続してください。

```
psql -d {databasename} -U {username}
```

このとき、テーブル構造の結果を標準出力ではなく、ファイル出力したい場合は次のようにオプションをつけてください。

```
psql -d {databasename} -U {username} -o {出力先ファイルパス}
```

そしてテーブル構造を出力するには\dコマンドを使用します。

```
\d {tablename}
```

次のように出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613298/803a5864-a614-8025-865e-3797a1dfaefc.png)
【AWS】https://SSL(ACM)証明書が「検証保留中」のエラー解決

#はじめに
SSL(ACM)証明書が「検証保留中」のまま変化せず、「発行済み」にならないエラーの対応を紹介します。
エラーの解決方法はどのような手順でそのエラーに至ったかで対応が変わると思いますので、この記事は参考程度にしてください。

#前提
インフラはAWSのみで全てを完結してます。
ドメインもAWSのRoute53をしてます。



#エラー

![スクリーンショット 2021-01-21 13.41.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769854/97fc71d8-904f-c763-18dd-005a21916800.png)

#結論
ネームサーバーが違いました。
AWEのサービスから「Route 53」 へ行き、「ドメイン」を選択し登録したドメインをクリックすると下記の画面に遷移します。
「ネームサーバーの追加/編集」をクリックして正しい値を入力する事で解決しました。

![スクリーンショット 2021-01-22 14.09.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769854/088adfd5-6847-d7c1-dc98-3bdba7d83a0c.png)

####正しい値
「Route 53」 の「ホストゾーン」から自分のドメインをクリックすると詳細が表示されます。
ドメインにはネームサーバの向き先があるらしく、これをホストゾーンのネームサーバーレコードと同じにする必要があります。
つまり、タイプ`NS`の`値/トラフィックのルーティング先`と`ネームサーバー`が同じである必要があります。

![スクリーンショット 2021-01-27 17.31.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769854/772519d0-7a6b-6d2a-0e5f-33ebef77fe7d.png)


#原因
原因はホストゾーンを作り直した事でした。

SSL証明を発行してDNS等の設定をしましたが、ブラウザにて`https://`で表示することができず、何が原因か分からないまま（後に解明されましたが）一度最初から作業をやり直しました。
**その際ホストゾーンも作り直した事が原因でした。**
Route53でドメインを取得するとホストゾーンが自動生成されますが、新しいホストゾーンを作成すると別のネームサーバーが割当られます。
その為、**ホストゾーンレコードのネームサーバーがドメインのネームサーバのと違っていたのです。**

これで無事「発行済み」になりました！



##最後に
エンジニア初学者ですが、同じ様に悩んでる方々の助けになればと思い記事を投稿しております。
万が一情報が間違っている場合ご指摘していただけると幸いです。
【React】レンダリング無限ループが発生【Class Component】

# 現象
## 背景
ReactのClassComponentでこのようなコードを書いていました。
※簡略化されています

```react
export class Header extends React.Component {
  static contextType = ThemeContext;

  render() {
    const { tab, setTab } = this.props;
    const [theme, toggleTheme] = this.context;

    return (
      <Container>
        <HeaderUl>
          <HeaderLi onClick={() => setTab('list')}>リスト</HeaderLi>
        </HeaderUl>
        <HeaderButton onClick={toggleTheme()}>テーマの変更</HeaderButton>
      </Container>
    )
  }
}
```

## エラー内容
ビルドを走らせたところ発生したエラーがこちら。

```
Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
```

適当にGoogle翻訳に突っ込んでみると、
「最大更新深度を超えた」
「setStateを繰り返し呼び出す場合に発生」
「ネストされた更新の数を制限して無限ループを防ぐ」
と言う意味ありげな内容が含まれていることが分かりました。

# 原因
どうやらReact.ComponentはsetStateが呼ばれた後に再レンダリングするサイクルがデフォルトになっているようで、

1. renderの実行
2. toggleTheme()の実行
3. setStateの実行
4. 1に戻る

と無限ループに入ってしまっていたようでした。

# 解決策
onClickに関数を渡すように記述を変更することで解決できました。

変更前

```react
<HeaderButton onClick={toggleTheme()}>テーマの変更</HeaderButton>
```

変更後

```react
<HeaderButton onClick={() => toggleTheme()}>テーマの変更</HeaderButton>
```

# 参考
[何故「Uncaught Invariant Violation: Maximum update depth exceeded.」というエラーが出るのかわかりません。
](https://ja.stackoverflow.com/questions/57002/%E4%BD%95%E6%95%85-uncaught-invariant-violation-maximum-update-depth-exceeded-%E3%81%A8%E3%81%84%E3%81%86%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E3%82%8B%E3%81%AE%E3%81%8B%E3%82%8F%E3%81%8B%E3%82%8A%E3%81%BE%E3%81%9B)
Mac の日本語・英語切り替え Shortcut

会社MBP交換により、前のIME切り替え方法が使えなくなった。
しかも今回は日本語キーボードLayoutです。

色々試して、ようやくGoogle入力法で問題解決。

下記スクリーンショットのように、Control + Shift + ; で英語に切り替えることができました。
ポイントは、GoogleのひらがなとAlphanumericを両方登録すべきです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/dccb4540-07d6-ac6f-6dd4-068ef534907e.png)
reduxのstoreの値をpropsで受け渡ししない方が良い

## 最初に
react-reduxのパフォーマンスについての記事です。

## 問題となるコード
```javascript
console.log(store.getState())
//{
//  childState1:"hoge"
//  childState2:"fuga"
//}

const ParentComponent = () => {
  const storeState = useSelector(state=>state);
  return (
    <>
      <ChildComponent text={state.childState1}/>
      <ChildComponent text={state.childState2}/>
    </>
  );
}

const ChildComponent = ({text}) => {
  return(
    <div>{text}</div>
  )
}
```

## 何が問題なのか
`storeState`は`ChildComponent`のための値なのに、`ParentComponent`のStateとして扱われます。
(厳密にはstateではありませんが、わかりやすくするためにstateとさせてください)

もし、`childState1`もしくは、`childState2`のどちらかの値が更新されると、`ParentComponent`と二つの`ChildComponent`すべてが再レンダリングされてしまいます。

再レンダリングされるコンポーネントが多くなれば、それだけパフォーマンスも悪くなります。

## 修正
```javascript

const ParentComponent = () => {
  return (
    <>
      <ChildComponent objKey={"childState1"}/>
      <ChildComponent objKey={"childState2"}/>
    </>
  );
}

const ChildComponent = ({objKey}) => {
  const text = useSelector(state=>state[objKey]);
  return(
    <div>{text}</div>
  )
}
```

## useSelecotorが多く実行されることは問題ではないのか
まず、useSelectorの仕組みについて説明します。

`const storeState = useSelector(state=>state)`

![アセット 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1063605/ee5c8f08-e1cf-b0f6-1943-0c09d7c36351.png)
storeは値が変更されると`useSeletor`によって登録されたListenerを使ってuseSelectorに通知します。
useSelectorは新しい値と古い値を比較し、違いがあればコンポーネントを再レンダリングします。

ここで、問題となるのがuseSelectorが登録するlistenerの処理量と再レンダリングされるreactコンポーネントの処理量です。
知っての通り、Reactコンポーネントを再レンダリングすると処理量が大きくなります。
useSelectorではlistenerの登録、値の比較、更新のみの処理となります。

よって、storeの値はpropsで受け渡しするよりもuseSelectorで直接取得した方が、パフォーマンスが良くなります。
【結合テスト】「本当に削除しますか」のconfirmダイアログでOKボタンを押す方法


# やりたいこと
結合テストにおいて、削除のリンクを踏んだあとに出現するconfirmダイアログのOKボタンをクリックしたい！

```
<%= link_to "削除", post_path(post.id), method: :delete, data: { confirm: '本当に削除しますか？' }  //投稿の削除ボタン%>
```
**↓confirmダイアログ↓**
![スクリーンショット 2021-02-08 9.12.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1016288/b121855f-aa19-a362-eb98-b429d793cc10.png)
# 実装方法
```
page.accept_confirm do
  //削除ボタンをクリックする記述
end
```
**↓記述例↓**

```
page.accept_confirm do
 　all(".more")[0].hover.click_link('削除', href: post_path(@post1.id))
end
```
.moreを持つ要素を全て取得し、０番目の要素にhoverを当てています。
そうすることで削除ボタンが表示され、 .click_link で削除ボタンのリンクを踏んでいます。

# expect{ } との合わせ技
実際の結合テストでは、モデルのカウントが１下がることを確認する必要があると思います。
下記のように記述することで上手くいきました。

```
expect{
  page.accept_confirm do
    all(".more")[0].hover.click_link('削除', href: post_path(@post1.id))
  end
  expect(page).to have_content('投稿を削除しました！')   //この記述がポイント！！
}.to change { Post.count }.by(-1)
```
「この記述がポイント」の行の有無で、カウントが１下がるの検証結果が変わることがあります。
理由は、削除の処理が完了する前にテストが先に進んでしまうことがあるからです。
そのため、sleepやhave_〇〇を使い、処理が完了するまで時間を数秒だけ稼ぐ必要があります。
こちらの記事を参考にさせていただきました。
[使えるRSpec入門・その4「どんなブラウザ操作も自由自在！逆引きCapybara大辞典」](http://https://qiita.com/jnchito/items/607f956263c38a5fec24#%E3%83%86%E3%82%B9%E3%83%88%E3%81%8C%E5%A4%B1%E6%95%97%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AFsleep%E7%AD%89%E3%81%A7%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E5%81%9C%E6%AD%A2%E3%81%95%E3%81%9B%E3%81%A6%E3%81%BF%E3%82%8B)

以上です！
テストコードに予想以上に詰まってしまったため、記事にさせていただきました。
【Flutter】エラー対応　assets_audio_player

#エラー内容

下記Gitでイシューに上がっていますが、根本的な解決策はまだ挙がってなさそうです。
https://github.com/florent37/Flutter-AssetsAudioPlayer/issues/399

```
e: /Users/yo4hi6o/flutter/.pub-cache/hosted/pub.dartlang.org/assets_audio_player-2.0.13+1/android/src/main/kotlin/com/github/florent37/assets_audio_player/Player.kt: (542, 5): 'handleMessage' overrides nothing
e: /Users/yo4hi6o/flutter/.pub-cache/hosted/pub.dartlang.org/assets_audio_player-2.0.13+1/android/src/main/kotlin/com/github/florent37/assets_audio_player/Player.kt: (543, 29): Type mismatch: inferred type is Message? but Message was expected
e: /Users/yo4hi6o/flutter/.pub-cache/hosted/pub.dartlang.org/assets_audio_player-2.0.13+1/android/src/main/kotlin/com/github/florent37/assets_audio_player/notification/NotificationActionReceiver.kt: (12, 85): Type mismatch: inferred type is String? but String was expected
e: /Users/yo4hi6o/flutter/.pub-cache/hosted/pub.dartlang.org/assets_audio_player-2.0.13+1/android/src/main/kotlin/com/github/florent37/assets_audio_player/notification/NotificationActionReceiver.kt: (30, 39): Type mismatch: inferred type is Intent? but Intent was expected

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':assets_audio_player:compileDebugKotlin'.
> Compilation error. See log for more details

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 37s
The built failed likely due to AndroidX incompatibilities in a plugin. The tool is about to try using Jetfier to solve the incompatibility.
Building plugin assets_audio_player...
Running Gradle task 'assembleAarRelease'...


FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':compileReleaseAidl'.
> SDK location not found. Define location with an ANDROID_SDK_ROOT environment variable or by setting the sdk.dir path in your project's local properties file at '/Users/yo4hi6o/flutter/.pub-cache/hosted/pub.dartlang.org/assets_audio_player-2.0.13+1/android/local.properties'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 0s

Exception: The plugin assets_audio_player could not be built due to the issue above.


* What went wrong:
Execution failed for task ':assets_audio_player:compileDebugKotlin'.
> Compilation error. See log for more details
```
#解決方法

buildgradle4.1.0→4.0.1 へダウングレード


```php:android/build.gradle
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'//ここを4.0.1に変更
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
```

イシューでは他で問題が発生するなど議題になっていますが、私の場合、
現時点でのFirebase最新版のパッケージと互換しております。
FirestoreのバックアップをCloud Functionsで作成する

Firestoreは何かあったときのために自分でバックアップとっておく必要があるっぽい。
FirestoreのフルバックアップをGCSに保存する用のCloud Functions（Python）を作成する。

#ソース
ランタイム環境変数として以下2つを設定

- projectid：プロジェクトIDをセット
- gcs_bucket：「gs://バケット名」の形でセット

```python3:main.py
from google.cloud import firestore_admin_v1
import os

def firestore_backup(request):

  projectid=os.environ['projectid']
  gcs_bucket=os.environ['gcs_bucket']
  request_body={"name":"projects/{}/databases/(default)".format(projectid),"output_uri_prefix":gcs_bucket}

  firestore = firestore_admin_v1.FirestoreAdminClient()
  export_return = firestore.export_documents(request=request_body)

  return 'OK'
```




```python3:requirements.txt
# Function dependencies, for example:
# package>=version
google-cloud-firestore == 2.0.2 
```



あとはCloud Schedulerから起動設定してあげれば良い

実行すると、以下のような感じでバックアップフォルダが作成され、そこの下にExportファイル、メタデータが作成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209773/634434f9-7b58-23ac-818c-9b7d4103cad2.png)


#注意点
##バックアップ保存先のバケットのリージョン
Firestoreのデータベースのリージョンと同じリージョンのバケットにしか保存できないっぽい

#参考
[Google Cloud Client Libraries for google-cloud-firestore](https://googleapis.dev/python/firestore/latest/admin_client.html)
[googleapis/python-firestore](https://github.com/googleapis/python-firestore/blob/master/google/cloud/firestore_admin_v1/services/firestore_admin/client.py)
[GCPドキュメント](https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.admin.v1#google.firestore.admin.v1.ExportDocumentsRequest)
【Unity】世界一分かりやすいuGUIのSliderでトグルスイッチを作成する方法

実はuGUIの`Slider`コンポーネントを使うと、**とっても簡単**にトグルスイッチを作ることができます。

ちなみに👇コチラのサンプルは**ソースコード不要**です。
![slider4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/a09a83d2-7d55-7310-3271-851af95045d3.gif)

## ヒエラルキー構造

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/3c03ecd3-d1db-7aa5-2e6f-74a1bb37bd06.png" width=450 />

- ピンク色背景
- 緑色背景
- ハンドル(白い円)

斜め上から見るとこのように3つのパーツからできています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/62977ba8-eb72-a649-6b3f-1dd1e5c32a1b.png" width=200 />

👆このようなヒエラルキー構造です。

- `Background`: ピンク色背景
- `Fill`: 緑色の背景
- `Handle Slide Area`: ハンドル(白い円)の可動領域
- `Handle`: ハンドル（白い円）


## Fill Rectで背景を切り替える

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/67b3adf2-9cdf-38f3-6042-0df821957264.png" width=450 />

`Slider`パラメータ`Fill Rect`に緑色の背景 **（Fill）** をセットします。

👇`Slider`の`Value`と緑色背景（Fill）のAnchorsの値が連動します。

FillのAnchors | Sliderのvalue
--- | --- 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/c2f4bddb-562f-4d32-af77-073cac2ab21d.png" width=220 />  | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/29b16d4d-dff6-747a-d240-27ff9514c2a9.png" width=320 />

`Slider` の `Value`を動かすと緑色背景（Fill）の形が変化するようになりました。
![slider7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/68e521c8-67e8-f712-7a55-3c03a7e5ba27.gif)


## Handle Rectにハンドル（白い円）を設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/02b7b8f0-aa62-c6a1-0e58-2b997f9cfc7b.png" width=450 />

ハンドルの可動領域は **「セットしたハンドルの`親階層のサイズ`に依存」** します。

今回の例では`Handle`の可動領域は`Handle Slide Area`の **サイズに依存** するということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/4c39ff17-7ba9-3f36-58b2-a772f320225f.png)

`Handle Slide Area`のサイズを調整して👇次のように可動領域を設定しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/b7b95e2c-9dd3-0742-2c36-88df410a831c.png" width=300 />

分かりやすくするために色を変えていますが、ハンドルの可動領域が**親階層のRectTransformのサイズ**に依存していることが分かります。
![slider6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/77a085b2-5e1b-ed83-d2e5-3d270b42ee83.gif)

## `Whole Numbers`にチェックを入れる

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/3f436898-6648-1ae6-8284-9c643f7af684.png" width=450 />

`Whole Numbers`にチェックを入れると`Value`の扱う値が整数のみになります。

こうすることで緑色背景はピンクを**瞬間的に覆い**、ハンドルは端から端へ**瞬時に移動**する挙動を作ることができます。

## 完成

![slider2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/ec33b0ae-0244-53e3-9a09-d8165eab0b78.gif)

## まとめ

Sliderコンポーネントを使ったトグルスイッチを作る解説をしてきました。
大事なことは次の3点です。

1. `Fill Rect`で背景を覆う
1. ハンドルは**親階層**のサイズに依存
1. `Whole Numbers`にチェックを入れる

ソースコードを一切書くこと無くトグルスイッチの見た目を実装できるのは非常に便利だなと思いました。

この後のステップですが、ボタンのON/OFFに対して処理を記述することになります。
ソースコードは `Value`の値をチェックするだけなので、とても **シンプルな処理**になるでしょう。

あなたのゲーム開発の助けになったら嬉しいです。
【Laravel】外部blade.phpファイルの読み込み

#はじめに
知識を整理するための個人的な備忘録です。

今回は、`header.blade.php`ファイルを複数のページで使い回したいと思います。

#方法
###1.`resources/views`の中にフォルダを作成
フォルダ名は`shared`としましたが、任意のフォルダ名で問題ないです。

###2.`shared`フォルダの中に`header.blade.php`ファイルを作成
`header.blade.php`ファイルですが、読み込み先のファイルに`<html></html>`タグや`<body></body>`タグが既に記載されているので、これらを書く必要はありません。

###3.読み込む
`header.blade.php`を読み込みたいファイルの中に以下のコードを書きます。

```php
@include('shared.header')
```

#参考
[【Laravel】外部PHPファイルの呼び出し方法【5分で完了】](https://seita-limitless.net/laravel-external-php-file/)
新卒１年生のJavaGold合格体験記

#はじめに
2021年1月、*Oracle Certified Java Programmer, Gold SE 8*（通称 **JavaGold**）に合格したので体験記を書きました。

![キャプチャ - コピー.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/e98b4027-90d8-9f58-9457-b9754f687ef2.png)

###なぜこの記事を書いたか
理由は簡単です、ミルクボーイです。

「いま、合格体験をいただきましたけども。」
「**こんなん、なんぼあってもいいですからね。**」

はい。

情報の新規性には欠けますが、あればあるだけいいだろうということで書きます。
あとは、私自身が受験時に他の方の体験記を読んで合格イメージを掴んでいたので、そんな記事の一つになればよいかなと。


###この記事の読み方
ファクトベースで [勉強開始時のスペック](#勉強開始時のスペック) と [勉強時間と方法](#勉強時間と方法) を書いたうえで、主観となる [合格の秘訣](#合格の秘訣) を書いていきます。


#勉強開始時のスペック
###学生時代
情報工学を専攻し、学習経験と開発経験はいずれも5年ほど。

###開発経験
個人開発のみで、業務経験は設計やテストを含めほぼなし。

それまでの言語経験は、JavaScriptやC#、C++、Pythonをメインとしたフロントエンド。
ただし、いわゆるアカデミック（レガシー）な書き方で、ポリモーフィックな作法は心得ておらず。

###保有資格
- 基本情報技術者
- 応用情報技術者


#勉強時間と方法
###勉強時間
140時間（3か月）

参考にJavaSilverは45時間（3週間）

###勉強方法
- 黒本（[徹底攻略Java SE 8 Gold問題集［1Z0-809］対応 徹底攻略シリーズ](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-Java-Gold-%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-809/dp/4295000035/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=&sr=)）を解く
- [公式のサンプル問題](https://www.oracle.com/jp/education/certification/java-809a-3516143-ja.html)を解く

#合格の秘訣
###１．とにかく黒本をやりこむ
これにつきます。他に参考書は必要ありません。

具体的には

- 全体を通して**2～3周**解く → 問題の形式に慣れる
- 問題の**コードを写経**する → コードの構造と雛形をインプット
- クラス、インタフェースの階層とメソッドを**表にまとめる** → 要点と理解の整理
- **正解の選択肢がなぜ正しいか、他の選択肢がなぜ間違いか**を説明できるようになる → 理解の確実化と回答への自信

これらをするだけで十分に“合格するための力”が身に付きます。

###２．コードを書いて想定した動きをするか確認
コードの写経から一歩進んだ内容です。

黒本のコードを書き換える、もしくはゼロからコーディングし、**ビルドを実行する前に一度動きを想定**します。

- コンパイルエラーが発生するのか。その場合、どのような理由でエラーとなるのか。
- 例外スローされるのか。その場合、なに例外なのか。
- 正常に動作するのか。狙った挙動や出力をするのか。

実際にコードを組み立て、動作を確認することで、より一層クラスやメソッドの振る舞いへの理解が深まります。
特に、攻略の鍵とされるStream APIの本質的な理解に繋がります。

###３．ドキュメントを眺める
JavaGoldはベンダー資格なので、ドキュメントはいわば公式の参考書です。

下記のインタフェースとクラスは、ほぼすべてのフィールドとメソッドが出題されます。
網羅的に理解をしておくことで井の中の蛙にならず、回答への自信にも繋がります。

- [java.util.stream.Stream\<T>](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html)
- [java.util.stream.IntStream](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/IntStream.html)
- [java.util.stream.LongStream](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/LongStream.html)
- [java.util.stream.DoubleStream](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/DoubleStream.html)
- [java.util.stream.Collectors](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Collectors.html)
- [java.util.Collesctions](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Collections.html)
- [java.util.Comparator\<T>](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Comparator.html)
- [java.util.Optional\<T>](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html)

###４．公式のサンプル問題を解いておく
私の場合、**ほぼ同じ問題が１，２問出題**されました。
それだけ問題形式が本番のものに近いです。当然ですよね、公式のサンプルですから。

試験の直前にでも、一度解いておくことをおすすめします。


#おわりに
今回は*Oracle Certified Java Programmer, Gold SE 8*（通称 **JavaGold**）の合格体験記を書きました。

ご覧になって分かったかと思いますが、経歴に関係なく学習と対策を重ねればそこまで難しい試験ではありません。
JavaGoldを通じオブジェクト指向やJavaのパラダイム、Javaの各API理解など知っておいて損はない知識は身についたかなと思います。

この記事を読んだことを機にJavaGold取得を志す、モチベーションを高める、そんな内容になっていれば幸いです。
テキスト読み込み

    def setting_number_reading(self):
        self.setting_number=[]
        
        with open('./setting.csv', encoding="shift-jis") as f:
            reader = csv.reader(f)
            header = next(reader)  # ヘッダーを読み飛ばしたい時  
        
            for row in reader:         # 1行づつ取得できる
                self.setting_number.append(row[1])
            
            if self.setting_number[0] =="":
                self.setting_number[0] = "0"
            
            if self.setting_number[1] =="":
                self.setting_number[1] = "5"
            #print(self.setting_number)
DBに保存された投稿内容が一覧画面に表示されないエラーの解決の一例

MVCの流れに沿って解決していきます。

モデルは、railsとdbの中間なのでモデルが原因ではありません。
コントローラーとビューのどちらに原因があるのか確認します。

コントローラーのcreateアクションにbinding.pryを記述します。
送られてきた情報が受け取れていなければコントローラーに問題があります。
送られてくる情報が間違っていればビューに問題があります。

```
def create
 binding.pry
 Tweet.crwate(tweet/params)
end
```
ターミナルでも上記の様になっていれば成功です。
情報の内容に間違いがない場合はコントローラーに原因があります。

続いてターミナルでtweet_paramsと入力します。
```
Unpermitted parametar::text
```
と表示された場合:textの情報が許可されていないという意味です。

コントローラーのtweet_paramsの:textを確認し修正します。
確認が終わったらターミナルでexitを入力してVScordのbinding.pryを消しましょう。
タプルの基本を抑えよう！


今回はタプルについて学び直そうと思います。

## タプルとは
タプルとは、複数の値をひとつの値として扱える変数（定数）のこと。
一つの変数に複数の型の値を入れることができます！



## タプルの作り方
タプルを使うと、StringやIntなどの型をそのまま一つの変数に放り込むことができます。
作り方は以下の通り。

```swift
let content = ("りんご", 2 , 105.8)
var student = ("インディ", 180)
```

このように、定数及び変数に()で様々な物を入れられます。


また、タプルの宣言は、値の個数だけ型を指定します。

```swift
let content: (String, Int, Decimal) = ("りんご", 2 , 105.8)
```

もし、型を指定しなかった場合は型推論で型を指定されます。


## 値の取り出し方

タプルに含まれている値は、別の変数または定数を用意することで取り出すことができます。

```swift

let content = ("りんご", 2 , 100.0)
let (fruit, count, price) = content

let kingaku = count * price
print (kingaku)
// 200.0

```

もし、使用する必要のない変数がある場合、ワイルドカード（_)を使うことができます。

```swift

let content = (_ , 2 , 100.0)
let (fruit, amount, price) = content

let kingaku = amount * price
print (kingaku)
//200.0
```

## タプルの値にインデックス番号でアクセスする方法

タプルの中から二番目、三番目の物といった部分だけを取り出す場合は、このようになります。

```swift

let content = ("りんご", 2 , 100.0)
let amount = content.1
print(amount)
// 2
```

このように、ドットシンタックスを使用することによって取り出すことができます。


## タプルの値にラベルをつける

タプルの値にはラベルを設定することができます。

```swift

let content = (fruit: "りんご", amount: 2 , price: 100.0)
let amount = content.amount
print(amount)
// 2
```

## まとめ
いかがだったでしょうか。
このように、swiftでは一つの変数・定数に様々な型の値を代入することができるのでとても便利です。
ただ、逆に何が入っているかわからなくなりそうなので、積極的にラベルをつけるのがいいかもしれませんね。
ID PlatformへのAccount移行サンプル

ID Platformの導入プロジェクトで必ず上がるテーマとして、Service毎に持っている既存のAccountをどのようにID Platformに移行するかがあるかと思います。この記事では最も考えられるケースをサンプルとして取り上げます。

# 現状
## John Doeさんの場合
John DoeさんのService利用状況です

-|Service A|Service B|Service C
---|---|---|---
Sign-upしているEmail|john.doe@example.com|john.doe@sample.com|利用していない
マーケティング目的での個人情報の利用同意状況|同意済|非同意|N/A

## Mike Smithさんの場合
Mike SmithさんのService利用状況です

-|Service A|Service B|Service C
---|---|---|---
Sign-upしてEmail|利用していない|mike.smith@example.com|mike.smith@sample.com
マーケティング目的での個人情報の利用同意状況|N/A|同意済|非同意

# 前提条件
本来であればCIAMにIDを移行する前に、Master Data Management Tool(例/Talend, Informatica)を利用してデータの名寄やクレンジングを済ませて綺麗に統合されたデータをID Platformに移行することが理想ですが、この記事ではMaster Data Management Toolによる統合は範囲外とします。

# 移行 - 1回目
Service Aに登録済のjohn.doe@example.comをID Platformに移行します。以下は移行後の状態です。

**移行元**

-|Service A|Service B|Service C
---|---|---|---
Sign-upしているEmail|~~john.doe@example.com~~|john.doe@sample.com|利用していない
マーケティング目的での個人情報の利用同意状況|~~同意済~~|非同意|N/A

**移行先**

ID|Password|同意状況|
---|---|---
john.doe@example.com|xxxx|ServerA - xx年xx月xx日xx時に同意済

# 移行 - 2回目
Service Bに登録済のmike.smith@example.comをID Platformに移行します。以下は移行後の状態です。

**移行元**

-|Service A|Service B|Service C
---|---|---|---
Sign-upしてEmail|利用していない|~~mike.smith@example.com~~|mike.smith@sample.com
マーケティング目的での個人情報の利用同意状況|N/A|~~同意済~~|非同意

**移行先**

ID|Password|同意状況|
---|---|---
john.doe@example.com|xxxx|ServerA - xx年xx月xx日xx時に同意済
mike.smith@example.com|xxxx|Service B - xx年xx月xx日xx時に同意済

# 移行 - 3回目
Service Bに登録済のjohn.doe@sample.comをID Platformに移行します。しかしながら、John DoeさんのIDと思われる"john.doe@example.com"は既にID Platformに移行済で、johh.doe@sample.comと同一のIDとみなすべきかと思います。移行前に本人に確認し、同一IDだった場合はマーケティング目的での個人情報の利用同意状況を、既に移行済のjohn.doe@example.comに紐付けます。以下は移行後の状態です。

**移行元**

-|Service A|Service B|Service C
---|---|---|---
Sign-upしているEmail|~~john.doe@example.com~~|~~john.doe@sample.com~~|利用していない
マーケティング目的での個人情報の利用同意状況|~~同意済~~|~~非同意~~|N/A

**移行先**

ID|Password|同意状況|
---|---|---
john.doe@example.com|xxxx|ServerA - xx年xx月xx日xx時に同意済, Service B - 非同意
mike.smith@example.com|xxxx|Service B - xx年xx月xx日xx時に同意済

# 移行 - 4回目
Service Cに登録済のmike.smith@sample.comをID Platformに移行します。検討する内容は移行3回目と同様です。移行済のmike.smith@example.comが同一IDだった場合はマーケティング目的での個人情報の利用同意状況を、mike.smith@example.comに紐付けます。以下は移行後の状態です。

**移行元**

-|Service A|Service B|Service C
---|---|---|---
Sign-upしてEmail|利用していない|~~mike.smith@example.com~~|~~mike.smith@sample.com~~
マーケティング目的での個人情報の利用同意状況|N/A|~~同意済~~|~~非同意~~

**移行先**

ID|Password|同意状況|
---|---|---
john.doe@example.com|xxxx|ServerA - xx年xx月xx日xx時に同意済, Service B - 非同意
mike.smith@example.com|xxxx|Service B - xx年xx月xx日xx時に同意済, Service C - 非同意

# おわりに
こちらの記事は簡易的なシミュレーションですが、厳密には移行元のServiceが持っているSchemaに従って追加の処理やエラー処理も実装すべきです。移行スクリプトのカスタム処理の実装とメンテナンス工数を考えると、初めからMaster Data Management Toolを利用してデータをきれいにしてから移行した方が効率的かつ経済的かもしれませんね。