OmniAICreator/Qiita-1.07M huggingface dataset:
[Ruby] pluckメソッド/mapメソッドでテーブルから配列を抽出/加工する

# 記事の概要
　Railsアプリでデータを取扱っていると、テーブルから特定のカラムデータだけを配列にして抽出したい、抽出した配列データを加工して新しい配列にしたい、といった場面に逢います。そうしたときに便利なpluckメソッド、mapメソッドを試してみました。
　1. pluckメソッド
　2. mapメソッド

# 1. pluckメソッド
　1つのモデルで使用されているテーブルについて、引数に指定したカラムの値を配列で返すメソッド。カラムの指定は一つでも複数でも可。
　今、下表のような、出品された家電製品のテーブルがあるとする(Itemモデルのitemsテーブル)。

![aca9ebacc240c009b5f732c38ca602a4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430273/b2f718ab-ef0d-ac8d-78db-caabed1067e8.png)

　pluckメソッドを使ってみると、下のように配列が帰ってくる。

```ruby
names = Item.pluck(:item_name) # 引数にカラムを一つ指定

# => ["掃除機", "冷蔵庫", "空気清浄機", "扇風機", "アイロン", "洗濯機", "電子レンジ", "プリンター", "ヒーター"]

nameprices = Item.pluck(:item_name,:price) # 引数にカラムを二つ指定

# => [["掃除機", 5000], ["冷蔵庫", 20000], ["空気清浄機", 10000], ["扇風機", 1000], ["アイロン", 3000], ["洗濯機", 9000], ["電子レンジ", 2000], ["プリンター", 6000], ["ヒーター", 4000]]
```
　pluckメソッドに引数を渡さない場合は、全てのカラムのデータが二次元配列に格納されて返ってくる。

# 2. mapメソッド
　配列の各要素に対して、ブロックを評価した後に新しい配列にして返してくれる。
　例として、mapメソッドを使って、上記のitemsテーブルについて全品10%割引を適用させてみる。

```ruby
prices = Item.pluck(:price) 

# => [5000, 20000, 10000, 1000, 3000, 9000, 2000, 6000, 4000]

discounted_prices = prices.map{|n|n*0.9}

# => [4500.0, 18000.0, 9000.0, 900.0, 2700.0, 8100.0, 1800.0, 5400.0, 3600.0]
```
　新たな配列に格納されて返ってきた。
MIPSアセンブリ言語入門3

#for文とwhile文

`for(sta1; expr; sta2) sta3`はwhile文と等価で
これをMIPSで書くと

```
sta1;
while (expr) {
    sta3;
    sta2;
}
```

#switch文

```
switch(expr) {
    case v_1: sta_1; break;
    case v_2: sta_2; break;
        ・・・
    case v_n: sta_n; break;
    defalut : sta_d;
}
sta_next
```

上記のようなswitch文は以下のような文と等価である。

```sum
    tmp=expr;
    if(tmp==v_1) goto l_case_1;
    if(tmp==v_2) goto l_case_2;
       ・・・
    if(tmp==v_n) goto l_case_n;
    goto l_case_d;
l_case_1: sta_1; goto l_end_sw;
l_case_2: sta_2; goto l_end_sw;
       ・・・
l_case_n: sta_n; goto l_end_sw;
l_case_d: sta_d; goto l_end_sw;
l_end_sw: sta_next;
```

これをMIPSで翻訳すればよい

#例

```C:sum.c
int s;
int i;

int main () {
    s = 0;
    i = 1;
    while (i <= 100) {
    	s = s + i;
    	i = i + 1;
    }
    return 0;
}
```
これをMIPSで書くと

```:sum.asm
# データ領域開始の宣言
        .data

# int s
        .globl s
s:      .word  0

# int i
        .globl i
i:      .word  0

# テキスト領域開始の宣言
        .text

# int main ()
        .globl main
main:

# s = 0
    la    $t0, s
    sw    $zero, 0($t0)

# i = 1
    li    $s0, 1
    la    $t0, i
    sw    $s0, 0($t0)

# while (i <= 100)
_main_1:
    la    $t0, i
    lw    $s0, 0($t0)
    li    $t1, 100
    sle   $t0, $s0, $t1
    beqz  $t0, _main_2

# s = s + i
    la    $t0, s
    lw    $s0, 0($t0)
    la    $t1, i
    lw    $s1, 0($t1)
    add   $s0, $s0, $s1
    sw    $s0, 0($t0)

# i = i + 1
    la    $t0, i
    lw    $s0, 0($t0)
    addi  $s0, $s0, 1
    sw    $s0, 0($t0) 

# }
    b    _main_1

# return 0
_main_2:
    li    $v0, 0
    jr    $ra
```

#最適化

上記の例の`sum.asm`は色々無駄があり、最適化すると以下のようになる。

```
# $t1に変数s, $t2に変数i,$t3に定数100を入れる
_main_1:
    sle    $t0, $t1, $t3
    beqz   $t0, _main_2

# s=s+i
    add    $t1, $t1, $t2

# i=i+1
    addi   $t2, $t2, 1

# while loopの最後
    b _main_1
_main_2:
    la    $t0, s
    sw    $t1, 0($t0)
    la    $t0, i
    sw    $t2, 0($t0)
```


#関連記事

https://qiita.com/twrcd1227/items/91f048de69bf92355868

https://qiita.com/twrcd1227/items/405cf58e8c9fcd3447ac

https://qiita.com/twrcd1227/items/9e4829f46d51172fed21
Jettyにしばらくアクセスしてないとjava.lang.NoClassDefFoundErrorが発生した話

普段tomcatを使ってて、業務で（組み込みではない）Jettyは使ったことなかったので知らなかったわーという話。

## 環境

AmazonLinux2
Jetty9.4
Java8

## 結論

- Linuxは標準で/tmp 配下を消しているが、Jettyのwarのキャッシュを置くデフォルトのディレクトリが /tmp を指しているので、定期削除のタイミングでキャッシュディレクトリが削除されていたのが原因

## 経緯

- Jettyを起動したまま、数日間放置。
- 久々にアクセスするとInternal Server Errorが発生していて、ログを確認すると、java.lang.NoClassDefFoundErrorと出ていた。
- そのクラスがないのはアカンじゃろ、と思いながらも、Jettyを再起動すると直るので、よくわからないからいいか。
- というのを度々発生させる
- JettyってアクセスしてないとGC発生してメモリから消しちゃうの？そんなの運用に耐えられなくない？？？:confounded:
- そして、日数があんまり経ってないのに発生した。再起動したらやっぱり直る。これは誰かが消してる？？:confounded::confounded::confounded:
- ググった結果、以下の記事にあたる。
  - [Jettyが週１、２で停止する場合はtmpwatchを疑うべきかも](https://nantonaku-shiawase.hatenablog.com/entry/2018/02/19/102325)
- 試しに、Jetty起動中に/tmpのキャッシュディレクトリを消すと、再現したので、これが正解の模様

## tmpwatch とは

Linuxとか標準で用意している機能。
詳しくは以下の記事が参考になる
[【Linux】【Cent OS】/tmpと/var/tmp以下のファイルを放っておくと勝手に削除される話](https://qiita.com/ryoya-s/items/8084d0f7de0e907eadc7)
そういえば、いつの間にかキレイになってるなぁとは思ってたけど、あんまり気にしたことなかった:sweat_smile:

AmazonLinux2の /usr/lib/tmpfiles.d/tmp.conf を確認すると以下の設定になってる。
tmpは10日でキレイになるのか

```/usr/lib/tmpfiles.d/tmp.conf
# Clear tmp directories separately, to make them easier to override
v /tmp 1777 root root 10d
v /var/tmp 1777 root root 30d
```

## 対策

[Jettyが週１、２で停止する場合はtmpwatchを疑うべきかも](https://nantonaku-shiawase.hatenablog.com/entry/2018/02/19/102325) に書いてる通りなんだけど
> ① Jettyが使用するjava.io.tmpdirのシステム設定の場所を指定する

で対応。

jetty.service の EnvironmentFile で指定したファイルに追記しました。

```
TMPDIR=/opt/jetty/temp
```

起動プロセスのVMオプションのtmpdirが

```
 -Djava.io.tmpdir=/opt/jetty/temp
```
となっていればOK
Apache⇔Nginx設定置換早見表

WEBサーバーをApache⇔Nginxで置換する場合に利用する設定の早見表です。

| Discription | Apache | Nginx |
|:-----------|:------------|:------------|:------------|
| WEBサーバーのバージョン非表示   | ServerTokens Prod | server_tokens off | nginx        |
| ETagを作成しない     | FileETag none | etag off       | This         |
| ヘッダのPHPバージョン非表示       | Header always unset X-Powered-By| fastcgi_hide_header X-Powered-By;         | This         |
| エラー表示を行う場合などに問い合わせ先となる連絡先メールアドレスまたは参照先 URL を設定         | ServerAdmin          | エラーページに埋め込まない仕様 | This         |
| サーバが自分自身を示す定義       | ServerName       | server_name       | This         |
| バーチャルホストで使用するホストの別名を定義    | ServerAlias     | server_name      | This         |
| 再起動無しで設定変更 | AllowOverride|機能なし | nginx        |
| url書き換え有効     | RewriteEngine On | 不要       | This         |
| サーバ変数を参照し正規表現と一致していれば（if文の役割)       | RewriteCond %{HTTP:X-Forwarded-Proto} =http|     if ($http_x_forwarded_proto != https) { }        | This         |
| 書き換えるurlの定義        | RewriteRule ^(/.*)?\$ https\://%{SERVER_NAME}$1 [L,R]         | rewrite ^(.*)\$ https\://xxx$1 permanent | This         |
React アプリを AWS EC2 にデプロイ

# はじめに

フロントエンド React + バックエンド Django REST Framework でアプリを作成したが、ローカル環境でしか動かすことができないので、AWS EC2 インスタンス上にデプロイして外部からもアクセスができるようにする。今回はフロントエンドである React アプリをデプロイすることとし、Web サーバーソフトウェアには、nginx を用いる。なお React アプリはすでに作成されており、コードは GitHub に push してあることを前提とする。[React/Next.jsアプリケーションを作成し、AWS EC2を使って本番環境にデプロイするまで](https://qiita.com/longtime1116/items/18553e43bfb44cbc9d81)を参考にした。

# EC2 インスタンスの作成

__Amazon Linux 2 AMI (HVM), SSD Volume Type__ という無料利用枠対象のものを使用して作成した。OS は RHEL7 / CentOS7 をベースとしているらしい。セキュリティグループ設定で HTTP 設定の追加を忘れないこと。設定されていると、以下のようになっているはず。

![httpsetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769545/f216ef49-ac95-97fc-0221-ecb358dea2ef.png)

その他インスタンス作成に関することはここでは割愛する。__以下の作業はすべて作成した EC2 インスタンスに SSH 接続を行った状態での作業であるので注意。__接続方法は [SSH を使用した Linux インスタンスへの接続](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html)を参照。

# nginx のインストールおよびセットアップ


以下コマンドで nginx をインストールする。

```
$ yum update -y
$ sudo amazon-linux-extras install nginx1
```

以下コマンドで、nginx の自動起動設定を行い、起動する。

```
$ sudo systemctl enable nginx          # 自動起動設定
$ sudo systemctl start nginx.service   # 起動
```

この状態で、EC2 インスタンスの「パブリック IPv4 アドレス」または「パブリック IPv4 DNS」にアクセスして、問題なく接続できることを確認する。
次に、/etc/nginx/nginx.conf（一部抜粋）に以下を追記する。

```/etc/nginx/nginx.conf
http {
    ...
    server {
        ...
        location / {
            proxy_pass http://localhost:3000;
        }
    ...
    }
}
```

上記でリバースプロキシの設定ができたので、このインスタンスに対するリクエストは localhost:3000 へ転送される。

設定を反映させるために、一度 ngnx を再起動しておく。

```
$ sudo systemctl restart nginx
```

# React アプリの起動

GitHub に push されているアプリをクローンして起動する。まず git をインストールして、レポジトリをクローンする。

```
$ sudo yum -y install git
$ git clone https://github.com/<your repository>
```

React アプリが動作する環境を作成するため、パッケージ管理ツールである npm をインストールする。（以下コマンドは Node.js をインストールしているが、合わせて npm もインストールされる。）インストール方法の詳細は[Node.js Binary Distributions](https://github.com/nodesource/distributions#rpminstall) を参照。

```
$ sudo su - root
# curl -fsSL https://rpm.nodesource.com/setup_16.x | bash -
# yum install -y nodejs
```

アプリをビルドして、起動する。

```
$ cd <your repository>
$ npm install           # package.json に記載されたパッケージを一括インストール
$ npm run build         # ビルド実行
$ npm run start
```

再度　EC2 インスタンスに接続すると、アプリが表示されていることが確認できる。

# おわりに

フロントエンドのアプリを EC2 上にデプロイした。バックエンド側も合わせてデプロイしたい。
Java staticメソッドと非staticメソッド・呼び出しで手こずった件

#はじめに
メソッドの呼び出しで手こずったので、忘れないようにメモしておきます。
間違いありましたら、コメント頂けますと幸いです。

ということで、staticと非staticの呼び出しについてやっていきます。

#staticメソッドについて
調べてみると、`staticなメソッド`というのはインスタンスを生成しなくも使用できるメソッドだということのようですが、初心者の私にはイマイチstaticと非staticのメソッドの違いがわからず、下記コードを実行しました。

```Main.java
public class Main {
	
	 public static void main(String[] args) {
		
		 	
		 	String firstName = "hoge";
		 	String lastName = "huga";

	        //getName関数の呼び出しと出力
	        System.out.println(getName(firstName, lastName));
	        System.out.println();

   }

   public String getName(String first_name, String last_name) {
     return last_name + first_name;
   }
```

すると、こんなエラーが出ました。

***型 Main の非 static メソッド getName(String, String) を static 参照することはできません***

解読すると、どうやら「Mainメソッド内で非staticなメソッドであるgetNameは参照できない」ということのようです。

つまり、***`staticなメソッド(main)から同一クラス(Main)内の非staticなメソッド(getName)へは直接アクセスできない`***
ということです。

では、どうすれば解決できるのかを説明致します。

#メソッドの呼び出し
[Java staticメソッドと非staticメソッドについて](https://qiita.com/nao-otsu/items/0f4f4040435db5fac890)

上記記事を参考にやらせていただいた結果、「***`クラスのインスタンスを生成し、インスタンスを通して実行する`***」というやり方で解決できました。

## クラスのインスタンスを生成し、インスタンスを通して実行する

どういうことかというと、下記コードのような状態にして解決しました。

```Main.java
public class Main {
	
	 public static void main(String[] args) {
		
		 	
		 	String firstName = "hoge";
		 	String lastName = "huga";

	        //getName関数の呼び出しと出力
            //Mainクラスのインスタンスを生成
            Main m = new Main();
　　　　　　　//インスタンスmのgetNameメソッドの呼び出し
	        System.out.println(m.getName(firstName, lastName));
	        System.out.println();

   }

   public String getName(String first_name, String last_name) {
     return last_name + first_name;
   }
```

このようにすることで、Mainクラスのインスタンスmをmainメソッド内で生成することで、***インスタンスmを通して***getNameメソッドを呼び出すことができるのです。

要するに、直接的にアクセスするのではなく、インスタンスを介して間接的にアクセスすることで、mainメソッド外の非staticなメソッドを呼び出すことを可能にするということです。

ぜひ、参考になれば嬉しいです。

#参考文献
[Java staticメソッドと非staticメソッドについて](https://qiita.com/nao-otsu/items/0f4f4040435db5fac890)
iPad フリーズしてしまう原因と対策

iPadのアプリを起動する際、或いは、iPadを遊んでいる最中にiPadが全然動かなくなって、いわゆるフリーズ状態に陥ったのです。iPad フリーズになった原因は色々あります、この文章では、上記の問題に遭遇しても自分で解決できるよう、iPadがフリーズ状態に陥った原因と解除仕方を紹介しましょう。

iPad フリーズ 原因:
1.メモリ不足：長年使ってきたiPadが容量不足である場合、データの処理速度が遅くなり、負荷がかかってフリーズを起こしました。

2.電量低下：iPadのバッテリの残量が少ない場合、高いパフォーマンスを実行するには消費電力モードになってしまい、動作が重くなり、フリーズする可能性があります。

3.インストールしたアプリの問題：iPadにインストールしたアプリがiPadとの相性が悪い場合、そのアプリを起動すると、iPadがフリーズになります。特にiOSを新しくアップデートした頃です。

4.水没や落下による衝撃：水没や落下などによる衝撃でiPadが壊れた際、起動できない?フリーズしたことも起こりやすいです。

iPad フリーズ 直し方:
1.不要なファイルやアプリを削除：iPad内にメモリが足りない場合、或いは、特定のアプリを起動すると、iPadがフリーズしてしまう場合、不要なファイルやアプリを削除してください。

2.iPadを充電：フリーズが起こった際、iPadのバッテリー残量が少ない場合、まずUSBケーブルでiPadを充電してください。30分ほど、まだフリーズするかどうかを確認してください。

3.iPadを強制起動：ボタンを押して反応がない場合、iPadのホームボタンとスリープ解除ボタンを同時に長押しして、iPadを強制終了してください。

4.iPadを初期化：iPadを強制起動しても依然としてフリーズする場合、iPadを初期化する必要があります。この操作はiPadを工場出荷状態に戻すので、事前にバックアップしておいたほうがスマートです。

また、iTunesでiPadを初期化する他、iPad フリーズ、リンゴマーク等の異常モードを解除できる修復ツール(https://jp.imyfone.com/ios-system-recovery/ )も利用できます。
【連載】初心者のためのMacCatalyst講座

#この講座について
この講座では「MacCatalystって何？」「MacCatalystを使ってみたい」という方向けに解説を
行っていきます。この記事を見てくれた方がMacCatalystを説明できる、MacCatalystが使える、
といったことを目標に解説していきます。

#目次
第1回　[iOSアプリ開発を考えているなら知っておくべきMacCatalystの基礎知識](https://qiita.com/passion_t_sato/private/62cb3dfa44ee670963b6)
第2回　作成中...
Feature Scaling（標準化・正規化）とは

## はじめに
　機械学習では，変数の「標準化」というものが出てきますが，この標準化についてよく理解できなかったので調べてみました．また，実際に標準化がある時とない時で比較してみました．

## Feature Scalingについて
　Feature Scaling とは，特徴量の取りうる値のスケールを変えることであり，その種類として「標準化」と「正規化」があります．データセットの特徴量間でスケールが異なることは多くあります．例えば，体重と慎重，家の価格と部屋数ではその単位と値の範囲が異なります．そのような異なるスケールのデータセットを学習させると，うまく学習できなくなるので，学習前の前処理で特徴量間のスケールを揃える必要があります．
 
## 標準化とは
　標準化とは，特徴量を標準正規分布（平均を0，分散を1）のスケーリングに合わせる処理のことです．変換の式は，次式となります．
$$x_{std, i} = \frac{x_i-\mu}{\sigma}$$ 
 $$(x_i: 元データ, \mu:平均, \sigma:標準偏差)$$
 
## 正規化とは
　正規化とは，特徴量の値の範囲を一定の範囲に収める変換で，その範囲は主に[0, 1]，または [-1, 1]となります．範囲を[0, 1]にするときの変換式は，次式となります．
 $$x_{norm, i}=\frac{x_i - x_{min}}{x_{max}-x_{min}}$$
 $$(x_i:元データ, x_{min}:最小値, x_{max}:最大値)$$
 
## 標準化と正規化の使い分け
　正規化は外れ値の影響が大きいので，基本は標準化を使います．以下が使い分けの例です．

#### 標準化
- ロジスティック回帰、SVM、NNなど勾配法を用いたモデル
- kNN, k-meansなどの距離を用いるモデル
- PCA, LDA(潜在的ディリクレ配分法), kernel PCA などのfeature extractionの手法

#### 正規化
- 画像処理における RGBの強さ [0, 255]
- sigmoid, tanhなどの活性化関数を用いる，NNのいくつかのモデル

#### 使わない時
決定木，ランダムフォレスト

## 標準化した時としてない時の比較
　最後に，irisデータのSVMによる分類において，標準化した時としてない時の正答率を比較していきます．
#### 実行したプログラム
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
% matplotlib inline

# irisデータセットの読み込み
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data[50:150, [2,3]]
y = iris.target[50:150]

#　データの標準化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X)
X_std = scaler.transform(X)

from sklearn.model_selection import train_test_split
X_1_train, X_1_test, y_1_train, y_1_test = train_test_split(X, y, test_size=0.3, random_state=0) 
X_2_train, X_2_test, y_2_train, y_2_test = train_test_split(X_std, y, test_size=0.3, random_state=0) 

# 線形SVCの学習
from sklearn.svm import SVC
svc_1_slack = SVC(kernel='linear', C=1.0)
svc_2_slack = SVC(kernel='linear', C=1.0)
svc_1_slack.fit(X_1_train, y_1_train)
svc_2_slack.fit(X_2_train, y_2_train)

# 正答率を出力
print('標準化なしの場合: %f' % svc_slack.score(X_1_test, y_1_test))
print('標準化ありの場合: %f' % svc_slack.score(X_2_test, y_2_test))
```
#### 実行結果
```
標準化なしの場合: 0.500000
標準化ありの場合: 0.966667
```
以上のように，特徴量を標準化した時の方が，実際に正答率が高くなることを確認することができました．

## 参考文献
- [「Feature Scalingはなぜ必要か」](https://qiita.com/ttskng/items/2a33c1ca925e4501e609)
- [「標準化と正規化の違い」](https://arakan-pgm-ai.hatenablog.com/entry/2019/01/07/090000)
iOSアプリ開発を考えているなら知っておくべきMacCatalystの基礎知識

#MacCatalystとは
「MacCatalyst」とは、Appleの統合開発環境である「Xcode」の機能の一つです。

かつては「Project Marzipan」と呼ばれていましたが2019年に「Project Catalyst」として発表され同年リリースされたXcode11から「MacCatalyst」を使用した開発が可能になりました。

#iPadアプリからMacアプリを作成が可能
アプリのiPad版さえあれば簡単にMac版を作ることができます。
細かく言うと、iPadアプリのソースコードを使って、Mac版のアプリをビルドすることができます。
1つのソースコードから2つのアプリができるので、開発コストは半分になります。
(そんな単純な訳ないですが…)

#デバイスに合わせた機能追加も可能
また、Mac版かどうかで処理を分岐させることも可能で、Mac版のデザインや機能をiOS版と分ける事もできます。
例えば、Mac版は画面の広さを生かしてボタンを増やしたり、カメラアプリなら編集機能の追加などができます。



以上がMacCatalystの概要でした。
次回はMacCatalystを使うメリットを紹介します。
Sublime Text 3でJavaをビルドする

Javaをエディタで手軽に勉強したい。

## 前提
- Windows 10 Pro 64bit
- Javaのキットをインストール済

## Sublime Text 3の設定
Tools -> Build System -> New Build System... でsublime-buildファイルを作成し[^1]、\\(Sublime Textのフォルダ)\Data\packages\Userに保存する。これでCtrl+bでコンパイル～実行まで行うことができる。
デフォルトでも「JavaC」が入っているが、エンコードの問題で日本語文字がコンパイルエラーに繋がってしまう。UTF8でソースを作成することを前提に（File -> Save with Encodingで指定できる）、コンパイル時に-encoding utf-8のオプションをつけるように記述している。

```Java.sublime-build
{
    "selector": "source.java",
    "file_regex": "^(.*?):([0-9]*):?([0-9]*):? (.*)",
    "shell": true,
    "cmd": ["javac", "-encoding", "utf-8", "$file_name"],
    "windows":
    {
        "encoding": "cp932"
    },

    "variants":
    [
        {
            "name": "コンパイルして実行",
            "shell": true,
            "windows":
            {
                "encoding": "cp932",
                "cmd": "javac -encoding utf-8 $file_name & java $file_base_name"
            }
        }
    ]
}
```

Build Systemについてはこちらの記事に色々まとまっている。→[Sublime Text 3のBuild Systemについて](https://qiita.com/lunatea/items/2bd07ae58e657d625868)

## 動作確認

Build SystemでJavaを選択し、適当なソースを保存してCtrl+Shift+bで「コンパイルして実行」。
標準入力を含む場合はコンパイルだけCtrl+bで行って、コマンドプロンプトから実行する（Sublime Textの実行結果のパネルからは入力できない）。

```HelloJP.java
public class HelloJP {
    public static void main(String[] args) {
        System.out.println("Hello じゃぱん！");
    }
}
```

```実行結果
Hello じゃぱん！
[Finished in 1.2s]
```

[^1]: [Build Systems – Sublime Text 3 Documentation](https://www.sublimetext.com/docs/3/build_systems.html)
ROSのlaunchファイル内でノードの起動順を遅らせる

ROSを使用しているとトピックをsubsucribeするタイミングなどで、同じlaunchファイル内でノードの起動順番を制御したいときがある。

以下launch-prefixを用いて特定のノードの起動を遅らせる設定のメモ

以下のようにTopicを配信する`talker`ノードと、購読する`listener`ノードがあり、
`talker`ノードが起動したあとに`listener`ノードを起動したいとする。

```xml
<launch>
<node name="talker" pkg="roscpp_tutorials" type="talker" />

<node name="listener" pkg="roscpp_tutorials" type="listener" />
</launch>
```

以下のように`launch-prefix`機能を使ってbashコマンドを実行してsleepコマンドで処理を遅延させる。

```xml
<launch>
<node name="talker" pkg="roscpp_tutorials" type="talker" />

<arg name="node_start_delay" default="1.0" />  
<node name="listener" pkg="roscpp_tutorials" type="listener" launch-prefix="bash -c 'sleep $(arg node_start_delay); $0 $@' " />

</launch>
```

# 参考

https://answers.ros.org/question/233353/set-delay-between-starting-nodes-within-launch-file/

https://www.moriken254.com/entry/2019/02/17/213433
フローから承認プロセスを呼び出す

ここ最近でフロー（正式名称：Salesforceフロー）は大きく進化を遂げました。
トリガが扱えるようになり、そのトリガの種類も増え、アクセスできるリソースも増え、もはや自動化はこの子だけでいいんじゃないかな…と思うぐらいのものになりました。

ということで、ここしばらくの間はTrailheadのハンズオンにて、プロセスビルダーで組んできたものをフローで組み直すなどして勉強を重ねているのですが…

「あれ？どうやってフローから**承認プロセス**を呼び出したらいいんだっけ…？？」

プロセスビルダーからなら、「ルール適用時のアクション」の「アクションを追加」を選択してアクション種別に「承認申請」を選んで承認プロセスを選べばいいだけでした。
![20210511_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/bf49beb8-bc73-ff55-fd2a-bca257dcf0fd.png)
分かりやすい位置にあるものです。

一方、フローでは…
![20210511_2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/a97c6086-d785-7efa-a1e7-9c0001a9d5e3.jpeg)

「要素」タブの「アクション」要素をキャンバスに持ってくることで、プロセスビルダーでの「アクションを追加」と似たようなことができます。
![20210511_3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/4675aff4-053a-1525-319b-740f76922e9c.jpeg)
左のカテゴリで「承認」を選んで、アクション検索の欄を押せば「承認申請」が出てきます。選択すると、詳細設定に移ります。
![20210511_4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261412/ec16acd6-1856-48ae-e9dc-46a6ae5ec52c.jpeg)
後は適切な入力値を設定して…　って、何を設定すればいいのかさっぱり分からん！！
「カスタムオブジェクトID」なんて設定値、プロセスビルダーではなかったよ？
というわけでHelpを見てきました。

https://help.salesforce.com/articleView?id=sf.flow_ref_elements_actions_approval.htm&type=5

どうやら、「承認プロセス名またはID」に呼び出したい承認プロセスのIDか名前を入れて（直に入力することができた）、
カスタムオブジェクトIDに申請したいレコードのIDを叩き込めばいいらしいです。
（ヘルプでは「レコードID」って表記されていたけど…、多分この理解であっているはず…　~~いつもの和訳ガバじゃないかな~~ ）

…ということは、フローをトリガしたレコード以外のレコードについても、そのフロー内で承認プロセスに入れる事も可能なのか…。**すごい便利じゃん。**
~~（プロセスビルダーだったら、プロセスに入ったレコードについてしか承認申請できないぞ）~~

また一つ、フローでできることが増えた。
Process Automation Specialistのスーパーバッジで組んだプロセス、フロー化しよっと♪
Gitでローカルをリセットして、リモートに合わせたい時

ローカル環境でコーディングしていて、作業がカオスになる時があると思います。
リモートが合っていて、リモートの状態に戻したいなって時は以下コマンドを叩きましょう。

```
git fetch origin
git reset --hard origin/master
```
Azure functionsでプロジェクト内のファイルを読み込む

## AzureFunctionsでファイル（テキスト）とか読み込んで使いたい時
もちろん`settings.json`に環境変数とか入れられるんだが、JSONとかわりと内容が多いときに困る。
そういうときのTips

## MacとWindowsではパスの表現が違います。
まずここ注意、最近VSとかもMacで使えるようになって便利なんだけど、ここは相変わらず同じにはできない（当たり前）
Mac(Linux)とWindowsで書き方変えるのもいただけない、そんなときの表記はこちら。
`System.IO.Path.Combine(context.FunctionDirectory, "..", "hoge", "foo.json")`
これでパスセパレータとかよしなにやってくれます。

## たぶん相対パスでも辿れるはずだが…
念の為、このように変更しましょう。

``` func.cs
namespace Api
{
    public static class BAWColumnName
    {
        [FunctionName("hoge")]
        public static async Task<IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
            HttpRequest req, ILogger log, ExecutionContext context)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            string text = System.IO.File.ReadAllTextAsync(System.IO.Path.Combine(context.FunctionDirectory, "..", "static_json", "some.json")).Result;
            
            return new ContentResult(){Content = text, ContentType = "application/json"};
        }
    }
}
```

`ExecutionContext context`をRunAsyncの引数に追加してます。

### 忘れずに
読み込むべきファイルはプロジェクト設定で、かならず出力フォルダに含めるようにしましょう。
これを結構忘れていつまでも上手く行かないときがある…
Python 3.8.5でpyatsのインストールにエラーになる

# 概要 インストールメモです。
Python 3.8.5でpip install pyats[full」を実行したら次のようなエラーになりました。

```
ERROR: Could not find a version that satisfies the requirement pyats[full] (from versions: none)
ERROR: No matching distribution found for pyats[full]
```

# 解決
問題はpipのバージョンが古いからでした。

## 手順：
1. 既存のpipバージョンを確認<pre>pip --version</pre>pip 20.0.2であることを確認
1. pipをアップグレード<pre>pip install -U pip</pre>
1. pipのバージョンを再確認<pre>pip --version</pre>pip 21.1.1であることを確認
1. pyatsをインストール<pre>pip install pyats[full]</pre>無事にインストール

以上
[AWS_11]RDSの作成

##環境
MacBook Pro (13-inch, 2016, Four Thunderbolt 3 Ports)
macOS 11.3.1（20E241）

#前提知識
RDSを作成するにはサブネットグループ（複数のAZにあるサブネットをグルーピング）が必要。
要は以下の準備が無いとRDSを作成できない。

1. 別のAZにサブネット作成
1. サブネットグループ作成
1. RDS作成

##別AZでサブネット作成
マネジメントコンソールからVPCを検索して、`サブネット　＞　サブネットを作成`をクリックする。
#####[パブリックサブネット]
VPC:　MyVPC
サブネット名：　PublicSubnet2
AZ:　ap-northeast-1c
IPv4 CIDR ブロック:　10.0.1.0/24

#####[プライベートサブネット]
VPC:　MyVPC
サブネット名：　PrivateSubnet2
AZ:　ap-northeast-1c
IPv4 CIDR ブロック:　10.0.3.0/24

![構成図02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758644/b05a04aa-8212-77ae-920c-9191aa3eda1b.png)

##サブネットグループの作成
マネジメントコンソールからRDSを検索して、`サブネットグループ　＞　DBサブネットグループを作成`をクリックする。
名前:　MySubnetGroup
説明:　MySubnetGroup
VPC:　MyVPC
AZ:　ap-northeast-1a , ap-northeast-1c
サブネット:　10.0.2.0/24 , 10.0.3.0/24
![構成図03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758644/391864b7-cb63-c6ca-fb1e-27320527fa93.png)

##RDSの作成
マネジメントコンソールからRDSを検索して、`データベース　＞　データベースの作成`をクリックする。
エンジンのオプション: MySQL
テンプレート: 無料利用枠
マスターユーザー名: xxxxxxxx
マスターパスワード: xxxxxxxx
DBインスタンスサイズ: db.t2.micro
VPC:　MyVPC
サブネットグループ:　mysubnetgroup(先ほど作成した[サブネットグループ](#1サブネットグループの作成))
VPCセキュリティグループ: RDS-SG-1
最初のデータベース名:　wordpress

![構成図04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758644/36c313a8-dd0c-f52d-80ae-ccf47bc7eee3.png)

##RDSのセキュリティグループを編集
RDSへのアクセスをWEBサーバのみとする。
マネジメントコンソールからVPCを検索して、`セキュリティグループ　＞　作成したセキュリティグループ`をクリックする。下側に設定画面が表示される。
`インバウンドルールのタブ　＞　インバウンドルールを編集`をクリックする。

1. 既存のソースを削除する。
1. `sg`と入力すると候補が出てくるので、WEB-SG-1(WEBサーバに設定したセキュリティグループ)を選択する。
1. `ルールを保存`をクリックする。

これによりRDSへアクセスできるのは、WEB-SG-1を適用したリソースのみとなる。

![構成図05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758644/ab7bb06c-82cc-0d2a-5e36-6c5d8a40afb4.png)
LeafletでGPSログ(GPX)地図：ルート上に30分間隔で時間をラベルで表示。

地図データを扱うJavaScriptライブラリ「Leaflet」を使って、GPSログ(GPXファイル)の地図表示を試している。

今回、ルート上に30分間隔で時間をラベルで表示するようにした。

詳細は以下。
LeafletでGPSログ(GPX)地図：ルート上に30分間隔で時間をラベルで表示。
https://2ndart.hatenablog.com/entry/2021/05/11/150933

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374794/c2161053-543f-a26c-24af-f23a44476af2.jpeg)
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374794/e0f51726-c455-0f65-7709-515557f44a35.jpeg)
AI周りに関する用語を五文字で説明した辞書

#この記事は
基本情報の学習でやったつもりが忘れてしまった、AI周りの用語の備忘録として残していきたいと思います。
自分にしか分からない部分もありますが、随時更新していきます。

###AI（人口知能）
脳みそ再現
###ニューロン
脳神経細胞
###ディープラーニング
脳みそ再現
###ニューラルネットワーク
ニュロ再現
補足説明：ニュロは、ニューロンの事です。
###重さ
調整

ニューラルネットワーク
：再現

訓練データ：

AI：脳

機械学習：再現

訓練データ：学習用

MNIST:手書き

隠れ層：処理（これ超適当）
Azure Functions + Spring Cloud Function で Spring Retry を使う


QiitaAzure + Java の企画も終わってしまいました、以前、 [Azure Functions で Spring Cloud Functionを使う - Qiita](https://qiita.com/statemachine/items/5133e415dfad95ebafa6) という記事を書いたのですが、もうすこし Spring フレームワークの機能を使えないと思い Spring Retry の機能を Azure Function + Spring Cloud で試してみました。

# Spring Retry 

Spring フレームワーク上で、アノテーションベースでリトライ処理を書けたりする便利なライブラリです。Spring Retry 単体でコードベースでリトライを記述することもできます。

GitHub は、以下です。
 
https://github.com/spring-projects/spring-retry

ここでは、Spring Retry そのものの解説はしないので、ドキュメント等を当たってください。

# Azure Function + Spring Cloud 上で使うには

結論から言えば、きちんと使えましたので、どのように実装したかを記録として残しておこうと思います。

ハンドラ（Trigger)から呼ばれる Function があり、そのメソッドに `@Retryable` アノテーションを指定します。引数には、ハンドルする例外クラスを配列で指定し、試行回数などを指定します。リファレンスは以下の通りです。固定バックオフ、指数関数的バックオフなども指定できます。

* [Retryable (Spring Retry 1.3.1 API)](https://www.javadoc.io/doc/org.springframework.retry/spring-retry/latest/org/springframework/retry/annotation/Retryable.html)

以下の例では意図的に、例外をスローしています。関数は `Function<I,O>` を実装しているのスロー句とかを勝手に拡張できませんので、検査例外を扱いたい場合は、未検査例外 `RuntimeException` を継承したラッパーを用意する必要があります。

```java
    @Retryable(value = { UnwrapedIOException.class }, maxAttempts = 5)
    public Mono<Greeting> apply(Mono<User> mono) {
        logger.info("hello function");
        if (Math.random() < 0.5) {
            logger.error("Throw IOException.");
            throw new UnwrapedIOException(new IOException("File not found :-)"));
        }
        return mono.map(user -> new Greeting("Hello, " + user.getName() + "!\n"));
    }
```

`@Recover` も指定できます。

```java
    @Recover
    public String recoverBar(UnwrapedIOException exception) {
        logger.error("----------------- error ---------------------");
        return "error";
    }
```

# まとめ

前回は単純なDIでしたが、Spring Retry も動作確認できました。こういった決まり切った処理をフレームワーク側に任せられるのは便利ですね。また、なにか機能を試したいと思います。

# 補足＆追記

Twitterでご指摘いただいてそれはまさにおっしゃる通りです。元々のサンプルを流量しつつ Spring フレームワークをどこまでAzure Functionで使えるかの実験をしていたので、あまり深く考えてませんでした。

https://twitter.com/making/status/1392041439035412482?s=20

といわけで Reactorのフレームワーク内でRetryできるならそれを使った方が良いでしょうという話です。
gspreadでGoogleスプレッドシートを更新する際にセルの表示形式をきれいにしたい

# 概要
gspreadでスプレッドシートに値を張り付けるときに、表示形式も意識すると幸せになるので、その方法をまとめました。

# 結論

- ファイルから読み込んだものを張り付ける場合は値を適切に変換する（変換にやや考慮点がある）
- update_cells のオプションにUSER_ENTEREDを入れる



# 貼り付ける値の例
例えば以下を張り付けていくとします。
実際にはファイルだったり、BigQueryだったりAthenaだったりから読み込むと思います。

## ケース1
特に何も考えず、縦に張り付けていきます。

```case1.py
# 前略
wkb = gc.open_by_key("xxxxxxxxxxx")
wks = wkb.worksheet("data1")
wks.clear()

cell_list = wks.range('A1:A10')

vlist=[]
vlist.append("12039")
vlist.append("1111222233334444")
vlist.append("3.141592")
vlist.append("2021-01-14")


idx=0
for val in vlist :
    cell_list[idx].value = val
    idx+=1

wks.update_cells(cell_list)
```

## ケース1の結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/2fa8f9b1-acdf-3077-7ee2-a6c62212a980.png)

一瞬、ん？いいんじゃない？と思いますが、すべて文字列なので計算などが行えません。
しかも=sum()を文字列に実行すると0になるようで、想像しただけで恐ろしいことになりそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/3e2a1fcc-fe9e-ecfe-f8ba-afce4f97c428.png)


## ケース2
gspreadはpythonの型を適切に変換して渡せば、セルもよい感じにしてくれるようです。
なので

```case2.py
#前略
idx=0
for val in vlist :
    try :
        val = int(val)
    except :
        pass

    cell_list[idx].value = val
    idx+=1

wks.update_cells(cell_list)
```

としてみます。

## ケース2の結果
やったか！？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/dea5a9b2-7916-55f1-f8c7-b7691e600de1.png)

はい、以下がダメです。
- 長い数値が壊れる
- 少数が文字列のまま

これらも考慮していきます。

## ケース3
ロジックの組み方はほかにもあると思いますが、変換の順序だったりを考慮する必要があり、少し煩雑にはなるかと思います。今回は

- ドットが含まれていたらfloatへ変換
- 一定文字数以下の場合にintへ変換

といった判定をしています。

```case3.py
#前略
vlist=[]
vlist.append("12039")
vlist.append("1111222233334444")
vlist.append("3.141592")
vlist.append("2021-01-14")
vlist.append("2021-01-15")

idx=0
for val in vlist :
    try :
        if len(val) <= 10:
            val = int(val)
    except :
        pass
    try :
        if "." in val:
            val = float(val)
    except :
        pass
    cell_list[idx].value = val
    idx+=1

wks.update_cells(cell_list)

```

## ケース3の結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/313a6dcf-1880-5482-8dc4-09904a3915b2.png)

良い感じです。
日付があるので、最新データを別シートに表示したいな、、、と=max(

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/59dc3ee2-8853-b43d-5dae-87dd9ea47926.png)

ああっ
日付型が文字列のままになってしまいました。


## ケース4
よしじゃあ日付型に変換して渡す、、、と途中でJSONを介すためか、エラーになってしまいます。
これは、文字列のままにして update_cellsのオプションとして USER_ENTERED を渡すと解決します。

```case4.py
#前略
idx=0
for val in vlist :
    try :
        if len(val) <= 10:
            val = int(val)
    except :
        pass

    try :
        if "." in val:
            val = float(val)
    except :
        pass
    cell_list[idx].value = val
    idx+=1

wks.update_cells(cell_list,value_input_option="USER_ENTERED")
```

## ケース4の結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/8d8fb850-b6fe-f0a5-66ee-e7fee3bca8bf.png)

これでようやく良い感じになりました！


# 雑感
貼れるか貼れないかではなく「貼れたけどなんかおかしい」となってしまうのが厄介ですね。

なお適切に型が設定されたBigQueryのテーブルに、ライブラリで取得したデータをそのまま上記のようなことをする場合は、変換は不要となります。
が、ファイルを読み込んで、、、というのもRPAとしては結構あるケースなのではと思いまとめてみました。
NameErrorが出た！ 

#はじめに#
フリマアプリを作成中、**NameError**が出ました。

私の場合だいたい誤字の可能性があるので確認したのですが、誤字・脱字はなく別で原因がありました。

#エラー箇所確認#

商品出品機能の実装で商品を出品する際に必要なものをAcitiveHashを使って表示させようとしました。



```app/models/shopping_date.rb
class shopping_date < ActiveHash::Base
  self.data = [
    { id: 1, name: '--'}, { id: 2, name: '1~2日で発送'}, { id: 3, name: '2~3日で発送'},
    { id: 4, name: '4~7で発送'}
  ]

  include ActiveHash::Associations
  has_many :items
  
end
```

```views/items/new.html.erb
 <div class="weight-bold-text">
          発送までの日数
          <span class="indispensable">必須</span>
        </div>
        <%= f.collection_select(:shopping_date_id, shopping_date.all, :id, :name, {}, {class:"select-box", id:"item-scheduled-delivery"}) %>
      </div>
    </div>
```
データをプルダウン形式で表示させたかったのでcollection_selectメソッドを使用しました。

#結論：モデルの命名規則を忘れていました

モデルに命名規則がある事を忘れていました。
shopping_date.rbを確認するとモデルクラスが小文字でアンダースコア使用してました。

訂正をすると以下になります、

```app/models/shopping_date.rb
      #訂正
class ShoppingDate < ActiveHash::Base
  self.data = [
    { id: 1, name: '--'}, { id: 2, name: '1~2日で発送'}, { id: 3, name: '2~3日で発送'},
    { id: 4, name: '4~7で発送'}
  ]

  include ActiveHash::Associations
  has_many :items
  
end
```

```views/items/new.html.erb
 #発送までの日数

<div class="weight-bold-text">
   <span class="indispensable">必須</span>
</div>                   
#訂正
<%= f.collection_select(:ShoppingDate_id, ShoppingDate.all, :id, :name, {}, {class:"select-box", id:"item-scheduled-delivery"}) %>
      
```

![スクリーンショット 2021-05-11 14.39.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264460/f1029d74-6d98-2847-6a4f-b6596533aca1.png)

上手く反映されました。
[Oracle Cloud] 誰もログインしていないサーバーを自動で停止する

## 1. 本記事について
開発・検証などの用途でクラウド環境を用意していて、
課金額の節約のためにしばらく誰もサーバーにログインしてない時は
自動で停止するスクリプトを書いてみました。

課金額を節約するという観点では、9:00~17:00など定刻で起動停止するように
設定するのも手ですが、もう少し柔軟に対応したい時に使えるかもしれません。
## 2. 前提
UnixベースのOSがインストールされたサーバー(インスタンス)であること。
OCICLI(Oracle Cloudのコマンドラインインターフェース)が対象サーバーに
セットアップ済であること。

・[参考] OCICLIのセットアップ手順
[Oracle Cloud : コマンド・ライン・インタフェース(CLI) をインストールしてみた](https://qiita.com/shirok/items/e63be9a22158fef10ba9 "Oracle Cloud : コマンド・ライン・インタフェース(CLI) をインストールしてみた")

## 3. スクリプト
ログインしているユーザー数を定期確認して、
指定時間ログインがなければ停止します。
バックグラウンドで流しておいて使うイメージです。
"DEST_OCID"に対象サーバーの識別用のIDを指定します。

・Computeインスタンス用

```bash
#!/bin/bash

# 対象インスタンスOCID
DEST_OCID="ocid1.instance.oc1.ap-tokyo-1.xxxxxxxxxxxxxxxxxxxxxxxx"
# シャットダウンまでの無ログイン時間(秒)
SHUTDOWN_THRESHOLD=3600
# ログインユーザ数チェック間隔(秒)
CHECK_INTERVAL=600

# ログインユーザ監視処理
while [ $((COUNT * CHECK_INTERVAL)) -lt ${SHUTDOWN_THRESHOLD} ];
do
        LOGIN_USER_COUNT=`who | wc -l`
        if [ ${LOGIN_USER_COUNT} = 0 ]; then
                COUNT=$(( COUNT + 1 ))
        else
                COUNT=0
        fi
        sleep ${CHECK_INTERVAL}
done

# インスタンス停止コマンド発行
echo "閾値に達したためインスタンスを停止します"
oci compute instance action --instance-id ${DEST_OCID} --action stop
```

・Database Cloud用

```bash
#!/bin/bash

# 対象インスタンスOCID
DEST_OCID="ocid1.dbnode.oc1.ap-tokyo-1.xxxxxxxxxxxxxxxxxxxxxxxx"
# シャットダウンまでの無ログイン時間(秒)
SHUTDOWN_THRESHOLD=3600
# ログインユーザ数チェック間隔(秒)
CHECK_INTERVAL=600

# ログインユーザ監視処理
while [ $((COUNT * CHECK_INTERVAL)) -lt ${SHUTDOWN_THRESHOLD} ];
do
        LOGIN_USER_COUNT=`who | wc -l`
        if [ ${LOGIN_USER_COUNT} = 0 ]; then
                COUNT=$(( COUNT + 1 ))
        else
                COUNT=0
        fi
        sleep ${CHECK_INTERVAL}
done

# インスタンス停止コマンド発行
echo "閾値に達したためインスタンスを停止します"
oci db node stop --db-node-id ${DEST_OCID} --action stop
```

## 4. OCIDの確認方法
・Computeインスタンスの場合
Oracle Cloudの管理コンソール画面から
[コンピュート]⇒[インスタンス]⇒[インスタンスの詳細]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217525/83ba1a30-f9b7-ba2f-1e85-ccb9d5b163a5.png)

・Database Cloudの場合
[Oracle Database]⇒[ベア・メタル、VMおよびExadata]⇒[DBシステム]⇒[DBシステムの詳細]⇒[ノード]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217525/ea173cd7-4c32-8e08-31b3-61a747554742.png)

## 5. 注意点
実際に使用する場合はsystemdなどでスクリプトをサービス化して
サーバーの起動と共にスクリプトが動くようにするかと思います。

この場合、無ログイン時間の閾値を誤って極端に短く設定してしまうと
サーバー起動⇒スクリプト自動起動⇒即時に閾値到達⇒停止処理 となって
ログインできず復旧が困難となる恐れがあるので注意が必要です。

## 6. 参考
[Oracle Cloud Infrastructure CLI Command Reference](https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.24.4/oci_cli_docs/ "Oracle Cloud Infrastructure CLI Command Reference")
Azure Static Web AppsのサイトにGitHub認証でアクセス制限をかける方法

# はじめに
GitHub認証でアクセス制限をかけてみました。

# 開発環境
+ GitHub
+ Windows10
+ Azure

# サンプルサイト
![bandicam 2021-05-11 13-45-06-347.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/a5f10390-0ead-3ce4-4eb5-17ccca43ab3d.jpeg)

![bandicam 2021-05-11 13-45-10-828.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/7ac7dc28-0203-7936-7cbd-70440c3c04fb.jpeg)

```html:index.html
<h1>Hello World</h1>
<a href="/admin.html">Admin</a>
```

```html:admin.html
<h1>Admin Page!!</h1>
```

# やり方

## staticwebapp.config.jsonをルートフォルダに追加
![bandicam 2021-05-11 13-55-08-615.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/1834aafc-73fc-7952-64ce-ece9947e49f9.jpeg)

```json:staticwebbapp.config.json
{
    "routes": [
        {
            "route": "/login",
            "rewrite": "/.auth/login/github"
        },
        {
            "route": "/logout",
            "rewrite": "/.auth/logout"
        },
        {
            "route": "/admin.html",
            "allowedRoles": ["admin"]
        }
    ]
}
```

これでadminページにはアクセスできなくなります。
![bandicam 2021-05-11 14-02-53-219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/c0cdda6c-7504-77b6-93a0-b67a5568fa5a.jpeg)

## ユーザーをロールに追加
AzureのStaticAppにアクセスしてロール管理→招待からリンクを作成
![bandicam 2021-05-11 14-10-35-383.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/447b3ac6-0665-20ce-cf52-dafbd98fe00c.jpeg)

招待リンクにアクセスして同意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/2a61a524-8bce-a5b8-3a32-fef9ca93907f.png)

## ログイン/ログアウト リンクを追加
```html:index.html
<h1>Hello World</h1>
<a href="/admin.html">Admin</a>
<a href="/login">login</a>
<a href="/logout">logout</a>
```

ロールを付与したアカウントでログインするとadminページにアクセスすることができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/1ce3da7b-4068-7096-0e4f-95888b73ac49.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/74dba7a2-492b-44c9-a193-9910f235bbc2.png)

ロールが付与されていないアカウントで認証を行ってもアクセスすることはできません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/17760aaa-2d81-5fe3-3252-f9f2a1f05f49.png)

# 追記
```json:staticwebapp.config.json
{
    "routes": [ 
    {
        "route": "/login",
        "rewrite": "/.auth/login/github"
    },
    {
        "route": "/logout",
        "rewrite": "/.auth/logout"
    },
    {
        "route": "/*",
        "allowedRoles": ["admin"]
    }
]
}
```
設定ファイルを上のようにすると全ページにフィルターをかけることができます。
この場合ログインリンクへのアクセスは直urlで行うことになります。
boto3でDynamoDBテーブルの属性（attribute）を削除する

ググってもすぐ見つからなくて難儀したのでここに残します。

```python:remove_attribute.py
import boto3

dynamodb = boto3.resource('dynamodb')

my_table =  dynamodb.Table('MyTable')

partition_key = 'hoge'
sort_key = 123

# 項目の取得
result = my_table.get_item(
    Key= {
        'pk': partition_key,
        'sk': sort_key
    }
)
print(result['Item'])

# 項目から属性の削除
my_table.update_item(
    Key= {
        'pk': partition_key,
        'sk': sort_key
    },
    UpdateExpression='remove foo'
)

# 項目の再取得
result = my_table.get_item(
    Key= {
        'pk': partition_key,
        'sk': sort_key
    }
)
print(result['Item'])
```
```bash
$ python remove_attribute.py
{'pk': 'hoge', 'sk': Decimal('123'), 'foo': 'bar'}
{'pk': 'hoge', 'sk': Decimal('123')}
```
Atcoderアルゴリズム勉強会第1回（シミュレーション・全探索）

#はじめに

こんにちは

現在京都に住んでいる修士2年の大学院生です．自己紹介だけの記事はかけないとのことで、ここで自己紹介について書こうと思ったものの、長くなりそうなのでやはり短めにいきたいと思います．

S台で浪人するも第1志望に落ち、関西圏公立大学に入学しましたが、仮面浪人して今の大学の学部に入りなおした多浪大学生です．

さて、今回はatcoderで高橋さんが行った講義、最強のアルゴリズム勉強会の第1回について取り組んでいきたいと思います．スライドにのっている問題を中心に解いていきます．

全探索なので難しい問題はないはずです（多分）

スライドはこちらになります．[https://www.slideshare.net/chokudai/wap-atcoder1]
#全探索問題
###天下一プログラマーコンテスト2012 予選B    A問題　孫子算経
これは特にコメントないです．恐らく全探索の導入的な問題です．

スライドでは簡単にforループが列挙できる条件として、「**分岐の回数が少なく、回数が決まっている**」「**ループごとに、選択肢が有限個で決まっている**」とのことです．

```python
a,b,c=map(int,input().split())

for i in range(1,128) :
    if i%3==a and i%5==b and i%7==c :
        print(i)
```

###ARC001 A問題　センター採点
1,2,3,4の選択肢の個数を数えました．なんかこんな感じのコード昨日のABC200のC問題でも書いた気がする．

どんどん次の問題にいきましょう．

```python
n=int(input())
c=list(input())
count=[0]*4

for i in c :
    count[int(i)-1]+=1

print(max(count),min(count))    
```

###ARC004 A問題　2点間距離の最大値
特に意識したことはないですが、根号は最後に付けました．

この種類の問題は難しくなってくると誤差が生じてきて厄介ですよね


```python
n=int(input())
x=[]
for i in range(n) :
    x.append(list(map(int,input().split())))

ans=0
for i in range(n-1) :
    for j in range(i+1,n) :
        distance=(x[j][0]-x[i][0])**2+(x[j][1]-x[i][1])**2
        ans=max(ans,distance)

print(ans**0.5)
```

###ARC018 B問題　格子点と整数
for文３つ書いて愚直に計算しました．個人的にはfor文3個以上になるのは好きではないので他に良い解法があれば知りたいですね．

３つの組み合わせを出してくれるようなitertoolあったような気がするけど，リスト内の要素の組み合わせはどうするんだっけ．

```python
n=int(input())
x=[]
for i in range(n) :
    x.append(list(map(int,input().split())))
count=0

for i in range(n-2) :
    for j in range(i+1,n-1) :
        for k in range(j+1,n) :
            ans=abs((x[j][0]-x[i][0])*(x[k][1]-x[i][1])-(x[k][0]-x[i][0])*(x[j][1]-x[i][1]))
            if ans%2==0 and ans!=0:
                count+=1
print(count)          

```

###ABC004 D問題　マーブル
これはこの中では一番面倒な問題でした．

中央に位置する緑色の配置を決めてから、左に位置する赤色、そして右に位置する青色の配置を決めました．結論（最後の配置）から遡る問題でした．

各マーブルの移動関数については、マーブル全体が初期中央位置よりも左側にある場合、右側にある場合、そして初期中央位置が含まれている場合の3通り考えられますが、1つの関数にまとめることができました．

例）緑のマーブル7個が座標-8から-2に配置された場合の移動回数

```math
(0-(-8))\times(0-(-8)+1)\div2-(-2-0)\times(-2-0+1)\div2=35\\
```
左辺については、
**（マーブル8個の座標-8から-1までの移動総回数）ー（マーブル1個の座標-1までの移動総回数）**
となっている．

これはマーブル全体が初期中央よりも左側に位置する場合の計算である．右側の時も同様に計算すれば求まる．

この式を一般化する．
（マーブル移動後の左端）＝l、（マーブル移動後の右端）＝r、（初期中央位置）＝cとおくと


```math
(-1)^{c<l}(c-l)\times(c-l+1)\div2+(-1)^{r<c}(r-c)\times(r-c+1)\div2=ans\\

```

となる．

ここでc<lおよびr<cがでてくるが、これは**各々の不等式を満たすと1となり、満たさない場合は-1**となる．これによって、3通りの場合すべてを1つの関数で表すことができる．

これはこの問題で初知りでした、、、不等式満たさないと0になると思ってました


後は、for文で緑左端の位置を回していき、赤の右端、青の左端の位置を決めていくだけでした．

```python
r,g,b=map(int,input().split())
ans=10**10

#----各マーブルの移動回数の関数----#
#----l=left,r=right,center=c,r<cが成り立てば1,不成立なら-1----#
def cost(l,r,c) :
    return (-1)**(r<c)*(r-c)*(r-c+1)//2+(-1)**(c<l)*(c-l)*(c-l+1)//2


#----緑色のマーブルの左端の位置から決めていく----#
for l in range(-500,201) :
    rR=min(l-1,-100+r//2)   #min(緑色マーブル左端からひとつ左，赤色マーブル右端)
    lB=max(l+g,100-b//2)    #max(緑色マーブル右端からひとつ右，青色マーブル左端)
    ans=min(ans,cost(rR-r+1,rR,-100)+cost(l,l+g-1,0)+cost(lB,lB+b-1,100))

print(ans)

```

#最後に

最後の問題だけは結構難しかったです．関数を作るところが悩みました．

こんな感じでアルゴリズムについてスライド配布してくださるのでatcoderには感謝しかありません．

次は，第2回アルゴリズムのスライドを扱っていきたいと思います．なんの範囲かは忘れてしまいましたが、恐らくまた全探索だったような気がする．
【GCP】組織とは何かを説明する

端的に言って、Googleアカウントとして登録している特定ドメインのことを組織と呼んでいると思って問題ないと思います。

しかし、最初にややこしく感じるのが、「組織なし」という概念です。
これはおそらく、GMAILアカウントでGCPを利用している場合は組織という概念がないので、その状態で組織を作ると「組織なし」になるのではないかと思ってます。

組織があれば、その下にプロジェクトを作成していくようなイメージになるのですが、組織ありのメリットデメリットとしては、
組織の下にプロジェクトを作成すると、組織そのものにIAMを追加しておけば配下の全てのプロジェクトに引き継がれるので毎回オーナーを設定すると言った煩わしい作業が無くなるので楽です。
組織の下に置くとプロジェクトを組織から移動させる事が大変になります。

組織の関係とPJの関係を頭の片隅に置いておくと、GCPを操作するときにわかりやすいのではないかと思います。

###参考URL
公式ドキュメント
https://cloud.google.com/resource-manager/docs/creating-managing-organization?hl=ja
https://cloud-ace.jp/column/detail148/
https://cloud.google.com/resource-manager/docs/creating-managing-organization?hl=ja
EC2インスタンスのパスワードを忘れてしまった場合の対処法

お疲れ様です。
先日、EC2インスタンスのパスワードがわからなくなってしまったので、その対処法です。

いつもはキーペアを作成して保存していたり、パスワードログインできるようにしていたりするんですが、
いつも、これをなくしたらどうしよう、と不安でした。
そんな時は、次の方法で解決できます。

## インスタンスを作り直す

身も蓋もない解決策ですが、これが一番手っ取り早いです。

## セッションマネージャーで接続する

セッションマネージャーを使用すれば、SSHキー、踏み台ホストなしで、ブラウザ上でインスタンスに接続できます。
セッションマネージャーを使用するには、インスタンスに`AmazonSSMManagedInstanceCore`の権限を持ったロールを割り当てる必要があるようです。
それが設定されていれば、以下の画面（EC2>インスタンス>接続）に接続ボタンが表示されます。

![スクリーンショット 2021-05-11 13.57.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/b6176d66-a597-ea6d-4799-1f811498b56b.png)


接続ボタンを押すと、以下の画面が立ち上がります。
コンソールと同じような操作感なので、違和感なく使えます。
![スクリーンショット 2021-05-11 14.01.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/e5991253-cf63-290d-6dc6-3fa5cc35136c.png)
Androidアプリ リリース手順（手動公開）メモ

Androidアプリリリース（Google Play Store公開）時の流れと不明だった点を簡単にまとめました！

新しいGoogle Play Console（2020年6月〜）
↓

https://play.google.com/intl/ja/console/about/?utm_source=google&utm_medium=cpc&utm_campaign=Console2020-Branded&utm_term=google%20play%20console%7ce&utm_content=480033287219&gclid=Cj0KCQjws-OEBhCkARIsAPhOkIb69MEtVyuhsDO9KuQYeu7vKIe-doVuZ5LytY4zr_ZWAbettqikj2MaAqtGEALw_wcB


### **初回審査時入力項目**
基本的には「新しくリリース作成」ボタンからのナビゲーションに従えば良し。

・ストア情報の入力（説明文、スクショ、ヒューチャーグラフィックなど）

・リリースの作成（バイナリアップロード、リリースノートなど）

・製品版→国と地域の選択

・アプリのコンテンツ（プライバシーポリシーなど）

・審査→公開

参考：[【2021年最新版】Androidアプリのストア公開手順まとめ](https://pursue.fun/tech/how-to-android-app-release-overview/#toc3)

### **時間指定公開のやり方：”公開の概要”→”管理”→”オン”**

※初回審査申請時に「完全公開」という表記（←心臓に悪い）になっているが、この設定をしておけば公開は手動に変更される。設定なしの場合、審査終了後に公開が自動。（アプリのアップデートリリース時も同様）
![スクリーンショット 2021-05-11 11.05.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643897/2fa9b829-11a5-2ee0-6911-bd14992730ae.png)


### **審査関連メモ**

- 審査は初回、アップデートごと
- アプリの公開→新規ユーザーへの公開
- アプリの非公開→新規ユーザーへの配布はストップ、既存ユーザーへの公開やアップデート配信はされる
- アプリの削除はできないため、非公開設定にすることが限界のよう

参考：[公開に関する問題 - Play Console ヘルプ](https://support.google.com/googleplay/android-developer/answer/9061737?hl=ja#zippy=%2C%E5%85%AC%E9%96%8B%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E5%89%8A%E9%99%A4)
laravel fill() メソッドの定義場所 個人メモ

# 目的

- 各モデルクラスでモデルに配列を追加するときに使用する`fill()`メソッドの記載場所をメモ的にまとめておく

# 場所

- `アプリ名ディレクトリ/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php`の中に記載されている。
- 下記に定義部分を抜粋して記載する。

    ```アプリ名ディレクトリ/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
    /**
     * Fill the model with an array of attributes.
     *
     * @param  array  $attributes
     * @return $this
     *
     * @throws \Illuminate\Database\Eloquent\MassAssignmentException
     */
    public function fill(array $attributes)
    {
        $totallyGuarded = $this->totallyGuarded();

        foreach ($this->fillableFromArray($attributes) as $key => $value) {
            $key = $this->removeTableFromKey($key);

            // The developers may choose to place some attributes in the "fillable" array
            // which means only those attributes may be set through mass assignment to
            // the model, and all others will just get ignored for security reasons.
            if ($this->isFillable($key)) {
                $this->setAttribute($key, $value);
            } elseif ($totallyGuarded) {
                throw new MassAssignmentException(sprintf(
                    'Add [%s] to fillable property to allow mass assignment on [%s].',
                    $key, get_class($this)
                ));
            }
        }

        return $this;
    }
    ```
treeコマンドの取得結果をExcelに乗せやすいように加工する

# 前提

* Windowsのコマンドプロンプトの標準`tree`ではなく、Chocolatelyでインストールした`tree`コマンドを使用します。私は普段、git bashばかり使っているので、今回もターミナルはgit bashを使用します。ちなみに、出力の違いは以下のような感じです。
   
```bash:cmd
>tree
フォルダー パスの一覧:  ボリューム OS
ボリューム シリアル番号は XXXX-XXXX です
C:.
│  aaa.txt
│  ccc.txt
│
└─bbb
        zzz.txt
```

```bash:git_bash
$ tree
.
|-- aaa.txt
|-- bbb
|   `-- zzz.txt
`-- ccc.txt

1 directory, 3 files
```

# 解決したいこと
git_bash側の出力そのままでも、CSVに出してExcel化することはできますが、「--」とか「\`」が邪魔なわけです。


# 解決方法
`sed`コマンドで取り去ります。

```shell
FILE_NAME="./dir_structure.csv"
DIR_PATH="//HOGEHOGE/FUGA/piyo"

tree -d -N -L 2 $DIR_PATH > $FILE_NAME

sed -z -i -e 's/\n[0-9]*\sdirectories\n//g' $FILE_NAME
sed -i -e 's/--//g' $FILE_NAME
sed -i -e 's/`/|/g' $FILE_NAME
sed -i -e 's/    |/|    |/g' $FILE_NAME
```
Datadog のログを正規表現を使って検索する

## 部分文字列を検索

`*` を使う。
例えば、 `IllegalArgumentException` という文字列を含むログを検索したいときは、下記のようにする。

```
@stack:*IllegalArgumentException*
```

## スペースありの文字列を含む部分文字列を検索

スペースを `?` で置き換え、前後に `*` を付ける。
例えば、`Cannot find record` という文字列を含むエラーを検索したいときは、下記のようにする。

```
@stack:*Cannot?find?record*
```

## スラッシュありの文字列を含む部分文字列を検索

`/` を `\/` とエスケープして、前後に `*` を付ける。
例えば、`/v1/users` という文字列を含むエラーを検索したいときは、下記のようにする。

```
@stack:*\/v1\/users*
```
【Java】ポリモーフィズム：フィールド・メソッドは型とインスタンスのどちらが優先される？

##はじめに
JavaSilver：継承とポリモーフィズムの問題

ポリモーフィズムについて、
継承関係にある2つのクラス内に同名のフィールド・メソッドがあった場合、
どちらが優先されるのか分からなくなったのでまとめる

＊「継承関係にある2つのクラス内に同名のフィールド・メソッドがあった場合」というのは、以下のコードのようなものである＊

```java
public class A{
    String val = "A";
    public void sample(){
       System.out.print(val);    
    }
}

public class B extends A{
    String val = "B";
    public void sample(){
        System.out.print(val);
    }
}
```


##結論
* フィールドを参照した場合
    * ->変数の型で宣言されたものが優先
* メソッドを参照した場合
    * ->オーバーライドされたものがあるならそちらを優先
    * ->なければスーパークラスのものを優先
    * （スーパークラスにそのメソッドがなければコンパイルエラー）

##具体例

```java
public class A{
    String val = "A";
    public void sample(){
       System.out.print(val);    
    }
}

public class B extends A{
    String val = "B";
    public void sample(){
        System.out.print(val);
    }
}

public class Main{
     public static void main(String[] args){
         A a = new A();
         A b = new B(); //B型インスタンスをA型に代入
         System.out.print(a.val);
         System.out.print(b.val);
         a.sample(); 
         b.sample(); 
    }
}

```
```:出力結果
AAAB
```

ちなみに、ポリモーフィズムでない継承関係については、
もちろんサブクラスの方が優先される

```java
class A{
    String val = "A";
    public void sample(){
       System.out.print(val);    
    }
}

class B extends A{
    String val = "B";
    public void sample(){
        System.out.print(val);
    }
}

public class Main{
     public static void main(String[] args){
         B c = new B();
         System.out.print(c.val);
         c.sample();
    }
}
```
```:出力結果
BB
```



##おわりに
こちらのQ&Aが個人的にドンピシャだったので載せておきます

https://teratail.com/questions/29599
pyenvのインストール周りの仕様が変わっていたので

## 出会ったエラー

- いつものDockerfileを新しいサーバーでbuildしていたら、pipがnot foundになってこけた。
- こんなwarningも出ていた。 ``WARNING: `pyenv init -` no longer sets PATH.``

## Dockerfileの仕様

- ubuntu18.04, cuda10.2, zsh
- pyenv 1.2.27


## fix

- 旧仕様でのDockerfile(pyenv部分の一部)

```Dockerfile
RUN curl https://pyenv.run | zsh && \
    echo '' >> /root/.zshrc && \
    echo 'export PATH="/root/.pyenv/bin:$PATH"' >> /root/.zshrc && \
    echo 'eval "$(pyenv init -)"' >> /root/.zshrc && \
    echo 'eval "$(pyenv virtualenv-init -)"' >> /root/.zshrc
```

- 新しい仕様
    - 実質 `pyenv init -` ⇨ `pyenv init --path` ？
    - (`.profile`をいじれ的なメッセージが出ていたけど従っても動かなかったので、メンテが行き届いてない感がある。)

```Dockerfile
RUN curl https://pyenv.run | zsh && \
    echo '' >> /root/.zshrc && \
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> /root/.zshrc && \
    echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> /root/.zshrc && \
    echo 'eval "$(pyenv init --path)"' >> /root/.zshrc && \
    echo 'eval "$(pyenv virtualenv-init -)"' >> /root/.zshrc
```

- 新しい仕様でのpyenv部分の全体的には

```Dockerfile
RUN curl https://pyenv.run | zsh && \
    echo '' >> /root/.zshrc && \
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> /root/.zshrc && \
    echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> /root/.zshrc && \
    echo 'eval "$(pyenv init --path)"' >> /root/.zshrc && \
    echo 'eval "$(pyenv virtualenv-init -)"' >> /root/.zshrc
RUN source /root/.zshrc && \
    pyenv install 3.8.0 && \
    pyenv global 3.8.0 && \
    pip install -U pip
```

- (ところで毎回 `source /root/.zshrc` 書かずに済む方法はないのかな…？)

## 参考

- (つい2,3日前の記事)

https://qiita.com/aCKoVICe/items/988bd36efc297a46fcff#%E8%87%AA%E5%88%86%E3%81%AE%E7%92%B0%E5%A2%83%E3%81%A7%E3%81%AE%E7%B5%90%E8%AB%96
Firebase cloud functionsのソースコードをpullしたいとき

Firebase cloud functionsを使った昔のサービスのソースコードが手元になかった...
Firebaseコマンドではdeployはできるけどpullすることはできない。
最新版がどれか自信がない...。

そんなときは、
以下URLにアクセスし
https://console.cloud.google.com/functions/list?project=_

プロジェクトを選択して、
関数をクリック。

そうすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7447/a97eefb4-2e34-90ce-d798-5a415b388fa6.png)
こんなのが出てくるので、「ソース」をクリックすると、
今deployされているソースコードが出てくるので、
zipダウンロードしてローカルでFirebase initしてからまたDeployしたらOK。

めったにやらないので忘れてしまうので、メモでした。