OmniAICreator/Qiita-1.07M huggingface dataset:
【React】要素とは？

https://ja.legacy.reactjs.org/docs/rendering-elements.html

本記事ではReactの**要素**について整理しています。

## 要素のレンダー

:::note
要素とは、Reactアプリケーションの最小単位の構成ブロック。
要素が画面上に表示したいものの説明書き。
:::

**最小単位**
```react
const element = <h1>Hello,World<h1>
```


:::note warn
要素とコンポーネントは別の概念。
要素は、コンポーネントを構成するもの。
:::

### 要素をDOMとして描画する
#### ルートDOMノード
HTMLファイルに以下のような<div>要素があるとする。
この中にあるすべてのものが、React DOMによって管理される。
```html
<div id="root"></div>
```


Reactだけで構築されたアプリケーションは、通常ルートDOMノードを一つだけ持つ。

#### React要素をルートDOMノードにレンダーする方法
1. `ReactDOM.createRoot()`にDOM要素を渡す。
1. `root.render()`に React要素を渡す。

```react
const root = ReactDOM.createRoot(
    document.getElementById('root')
);
const element = <h1>Hello, world</h1>
root.render(element)
```

### レンダーされた要素の更新
:::note
React要素はイミュータブル。一度要素を作成すると、その小要素もしくは要素を変更することはできない。
要素は映画の中の1つのフレームのようなものであり、それを特定のある時点のUIを表す。
:::

ここまででUIを更新する方法は、新しい要素を作成してroot.render()に渡すことだけ。

```react
const root = ReactDOM.createRoot(
  document.getElementById('root')
);

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  root.render(element);
}

setInterval(tick, 1000); // 一定の遅延間隔を置いて関数やコードスニペットを繰り返し呼び出す。
```

### Reactは必要な箇所のみを更新する
:::note
React DOMは要素とその子要素を以前のものと比較し、DOMを望ましい状態へと変えるのに必要なだけのDOMの更新を行う
:::

![スクリーンショット 2023-10-08 10.17.18（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191928/06e7b107-680d-7486-ca6e-d6c06fc50254.png)
SESで45歳目前にして危機感②　「どうしてこうなった」

どうも。詳細設計、プログラム経験しかない中年エンジニアです。

今常駐先を探し中で中々決まらない為、将来に危機感を感じています。

今回は、「どうしてこうなった？」「どうすればいいのか？」を考えます。

SESに勤めていて、将来まで働けるかどうか漠然と不安に思っている方は、
まさに今私がそういう状況に直面しているので参考になればと思います。

### なぜこの年齢まで詳細設計以降しかしてこなかったのか？
・営業さんが持ってきてくれる案件を何も考えずに受けていた為。
・また、SESは下流工程の仕事しか来ない為です。
　基本設計以上の仕事を振られる事は無いです。（私の場合）

### SESはやめとけ！の理由の一つ
WEB記事や動画サイトで「SESはやめとけ！」と解説されている方が居ますが、
「そんな事はない。SESは上流工程の経験は積めないが技術力はアップするから問題ない。」
そんな風に考えていました。SESで一生食べていけると思っていました。
が、実際はそれは難しそうです。

自分が所属しているような中小SESは自社作業がない為派遣しか仕事がありません。
また、小規模なので現場にもチームではなく、ソロで入ることが多い為、
「チームに待機社員を潜り込ませる」ような事もできません。

なので、派遣先が無くなれば収入が無くなります。
正社員の待機中でも為給料は出ますが、待機が長引けば給与が減ります。

今更遅いですが、将来のキャリアパスを考えてもっと早く転職しておくべきでした。

悩んでも仕方がないので、これからどうやって定年まで給与を維持して生き抜けるか。
それを考えて行動していきたいと思います。
遅すぎるかもしれませんが、何もしないよりかはマシなはずです。

### 定年までどうやって生き残るか。
もう年齢もそこそこ行っているので「どこを目指すか」ではなく、
「どう生き抜くか」という考えです。。
昔、そんな考えの人を見た時「向上心ない人だな」と思っていましたが、
自分がそうなるとは思いませんでした。

1. 上流工程のスキルを身につける為転職する。
→これは厳しいと考えています。転職可能な年齢を過ぎている。
　また、転職したとして収入が減る為、それは避けたいです。

1. 流行、需要のある技術(WEB系、AI系等)を身につける。
→これも厳しいです。覚えたとしてそういう仕事があるかどうか、
　また、実務経験がない人を雇ってくれる可能性が低い為。
　実務経験がないので、若いエンジニアに競争で勝つことは難しい為。

1. SES客先常駐で生き残る方法を考える。
→これが一番可能性があると考えています。
　今までの知識、経験を活かして生き残る道を考えたいです。（考え中）
PowerShellでSelenium動かしてみる - Google検索 by Edge

# 動機
Seleniumの操作習得のために、ヘルプをじっくり読むというかまず色々単純なのもから動かしてみようかなと思って、とりあえずGoogle検索してみようと思いました。


# 環境
* OS: Windows 10 EnterPrise
* Selenium : 4.0.0 Preview-3

# リソース
* ゼロから作らずとも、インストールしたモジュールの中に"Examples"というフォルダがあり、その中に"A-Simple-Google-Search.ps1"というファイル名で何するかすぐわかるファイルがあるのでそれベースにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/4b36fee1-d49a-a682-a6b4-5dc88dd12327.png)

* テキスト(メモ帳)だと見にくいのでPowerShell ISEで開くと中身は下記。クロームで実行するベースのスクリプトが記載されてます。自分の理解ではざっくり下記：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/7912e472-1245-f87d-015e-4425b6c5fea9.png)

    * ~5行目：ブラウザの起動
    * 11~13行目：Googleの検索窓のHTMML要素の抜粋
        * これはブラウザでF12押して開発者ツール開いても確認できます
        * Power Automate for Desktopでは「セレクタービルダー」の時に確認・設定できるやつです。自分は基本ド素人ですがPADやってこの概念を取得してました。色々やってみるものですね。
    * 17~31行目：HTML要素の属性の指定 ... 指定方法は色々ある様子
        * PAD的な感覚で言うと「要素」を変数に入れるのは要は「インスタンス」にしてるというイメージです。Excelインスタンス、Browserインスタンスなど色々ありましたけど要は要素インスタンスにしてる感じですかね。
    * 33~41行目：検索窓に文字入力しその要素に対しキー入力を送信する操作
    * 42~52行目：待機操作の例 ... 所定の要素が表示されるまで待機し表示されたら所定の操作をする
        * Invoke-SeClickは所定の要素をクリックするコマンド。前述の$LogoImageElementに格納された要素インスタンスそのものをクリックするイメージです。
    * 54,55行目：ブラウザを閉じる by Stop-SeDriver


# サンプルスクリプト(Google検索)
* ひとまずEdgeを利用して検索結果を表示するまでやってみよう、と思い下記スクリプトを作成

``` PowerShell
Start-SeDriver -Browser Edge -StartURL 'https://www.google.com/'

$Searchbox = Get-SeElement -By Name -value q -Single
Invoke-SeKeys -Element $Searchbox -Keys 'Powershell-Selenium'
Invoke-SeKeys -Element $Searchbox -Keys ([OpenQA.Selenium.Keys]::Enter)
```


# 実行結果
* 無事"Powershell-Selenium"で検索した結果が出ました。この画面まで大体8秒くらい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/15fbcca3-a4a6-c6c3-fab0-a90a77553b3a.png)


# おわりに

* 基本自分用メモですがどこかの誰かの役に立てば幸いです。

* PADで知ったことが生きる場面があるので、ローコード開発ツールはリテラシー向上にも役立つな、とあらためて思いました。

* もし知見のある方でコメントある方いれば是非よろしくお願いします。
【Android】SearchViewをComposeで実装する

# はじめに
だいぶComposeで実装しやすい環境が整ってきましたが、AndroidViewの機能であるSearchViewをComposeで実装したらどんな感じになるのか調べる機会がありましたので、備忘録的に残しておこうと思います。

# SearchViewをComposeで実装する
まず旧実装は以下になります。

```main.xml
<SearchView
    android:id="@+id/search"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:iconifiedByDefault="false"
    android:queryHint="検索" />

```
Composeが普及してきているとはいえ、XMLを使用したAndroidViewの実装はまだまだ現役ですよね。
上記に対してComposeの実装は以下になります。

```main.kt
val focusManager = LocalFocusManager.current
SearchBar(
    query = input,
    onQueryChange = { new -> input = new },
    onSearch = { _ -> focusManager.clearFocus()},
    active = true,
    onActiveChange = { ... },
){
    
}

```
比べてわかる通り、Composeは直感的に実装ができて良いですね、、、！
このSearchBarが追加されたのは比較的最近なようですが、SearchViewで実現できることはSearchBarでも問題なく実装ができそうです。

ComposeでTextFieldで頑張って実現しようとしている方はSearchBarを使用いただくことを検討しても良さそうです。

# さいごに
やはりComposeはいいですね、まだ課題はありつつも着実に使用しやすいように改良されていっています。
もはや新規機能はComposeで作らない理由はなさそうですが、SearchViewのような特殊なUIがComposeでも変わらず実装できるかどうか今後も調べていこうと思います。
ABC323回答メモ

0.はじめに
　アットコーダー初参加は、去年のユニークビジョンだったなぁと思いながら参戦。
　Cまではそこそこのペースで解けましたが、Dでブレーキ。
　結局Cまでクリアで終わりました。
　問題難易度は楽しく解けるちょうどよい感じでした。
　レートは+10と微増しました。

1.A - Weak Beats
　ビットを使って綺麗に解けそうな気もしつつ
　回答の早さ優先で単純な実装

　Sを読み込んだら、先頭からチェックしていき
　偶数番の時（pythonのカウンター的には奇数の時）
　0でなかったらフラグを立てる
　最後までチェックして、フラグが立っていたらNo
　立っていなかったらYesを出力して終了

　https://atcoder.jp/contests/abc323/submissions/46282719


2.B - Round-Robin Tournament
　ペアを格納するリストを用意
　勝敗表を読んでいき
　(勝利数、プレイヤー番号*-1)を
　リストに格納
　リストを降順にソート
　リストを順番に読んでいき回答用リストに
　プレイヤー番号*-1を格納し
　最後に回答用リストを表示して終了

　https://atcoder.jp/contests/abc323/submissions/46293606


3.C - World Tour Finals
　なかなかしっくりこないややこしい条件があるなと思いつつも
　まぁ素直に実装すれば生けるかと取り掛かりました。
　結果的に制約的にTLEすることなく行けました。
　
　考え方
　　プレイヤーごとの得点状況を読み込む際に以下の下準備をしておく
　　　・各プレイヤーの現在の得点をリストSUMに格納
　　　・各プレイヤーの現在正解していない問題の得点を
　　　　リストに格納し、降順にソートしたのち
　　　　2次元リストmoreに格納
　　　・プレイヤー全員の中で最高の得点をwinに格納
　　リストSUMをindex　iで順に読み込んでいき回答を出力
　　　・win＝SUM[i]の時0を出力
　　　・SUM[i]に、more[i]のリストを先頭から足していき
　　　　win以上になる個数をカウントし表示

　https://atcoder.jp/contests/abc323/submissions/46315812


4.D - Merge Slimes
　1時間以上時間が残っていましたが、結局解けませんでした。
　コンテスト後解説や、他の方の解答を見てなんとかACにこぎつけました。

　最初の考え方
　　・キーをS_スライムの大きさ、値をCスライムの匹数で
　　　辞書に登録
　　・辞書Dのキーsを昇順に読み込んで
　　　匹数cが奇数なら変数ansに+1
　　　引数が2以上なら、キー[s*c]にc//2を加算
　　・↑を繰り返していき辞書Dが空になったら終了
　問題点
　　・keys()で呼び出しながら、その辞書に新たなキーを登録できない
　　→キーを別項目で切り出して並べかえて参照して・・・等
　　　いろいろ工夫したが、TLEとなる
　　　→コンテスト中はTLE12止まりでした。
　解決策
　　・解説等を見て優先度キュー等を使っても
　　　TLEが外せ無かったのですが、他の方の解答を見て
　　　keysをコピーして使うことで、読み込みながら入力
　　　できることが分かり採用
　　　→それでもTLEが外れず、さらによく考えると、
　　　　keysでキーだけ取り出すのではなく、itemsで値も取り出せば
　　　　時間早まるなと気づき、(参考にした方のソースを見て気づきましたが)
　　　　ほぼ、丸パクリでACとなりました。

　https://atcoder.jp/contests/abc323/submissions/46358162

以上
キー入力でアルファベットやコントロールキーが効かなくなった原因はこれだった

# はじめに
プログラミングをしていて、それまでは、動作していたが、ある時から動作しなくなったということはよくあります。そのあるときがいつだったのか、何をしたからかが、その不具合に気が付いたときにはわかりません。大抵はしばらくたってから気が付きます。そこから、不具合の原因を探し続けることになります。直接の原因が何なのか、まったく見当がつきません。今回の例をもとに、ご説明いたします。

# 現象と原因
どんな現象が起こったのかと言いますと、テキスト入力画面で、文字入力をするのですが、ひらがなは何とか入力できますが、そのほかのキーが効きません。例えば、バックスペース、デリートキー、数値キー、アルファベットキーなどです。ある時点までは何事もなく入力できていました。そのため、いくつかのチェックをしてみました。

#### (1) かな漢字変換ツールがおかしくなったのか
試しに、他のページで試してみました。例えば、yahoo!Japanの検索入力で、文字入力してみましたが、問題はありません。その他のページのも文字入力も問題はありません。かな漢字変換ツールは正常に動作しています。
#### (2)今デバッグしているページのみがおかしい。
他のページでは、正常に文字入力ができます。キーボードが故障したわけではなさそうです。
#### (3)ページをリロードして何度も確かめました。
何度、リロードしても現象は同じ結果です。ある時点までは、正常にできていました。このことから、じっくり、考えてみました。
いつ、何をしてからなのか。考えられるスクリプトファイルを中心に調べました。デバッガーでキー入力しているイベント処理あたりにブレークポイントを入れてみたりしました。ワンステップずつ、進めてゆきました。この時、このファイルは別のフォルダーからコピーしたものだったことから、そちらのスクリプトで確認したところ、そのスクリプトでは正常に文字入力ができました。
#### (4)何が原因だろうか
そこで、この二つのファイルを差分チェックしてみました。幸い、使っているIDEは、NetBeansIDEだったため、差分チェックがあります。
そこで、比較してみたところ、いくつかの相違箇所がありました。
おそらく、この中のどこがに原因があるだろうと検討をつけました。
ひとつひとつつぶして行き、最後にたどりついたのが、イベント処理の最後で、不具合がある方のスクリプトに、return false;が追加されていました。正常な方にはありません。記述にはありませんが、単にreturn;しているはずです。ようやく、原因がわかりはじめました。
そうか、これが原因かと。実は、ある現象のため、迂闊にもこのreturn false;を追加してしまいました。その時は、イベントバブリングをしたくなかったためです。しかし、今回の現象から、このreturn falsel;があるために、それ以降のイベント処理が停止していました。
そのため、その次の文字入力が実行されなかったようです。
#### (5)return false;を外して実行しました。
見事に正しく、文字入力ができました。他のすべてのコントロールキーも効いています。やった!!と自己満足しています。
この快感があるから、デバッグは楽しいといつも思っています。
年寄りの、脳の健康維持にはデバックは最適な作業だと感じています
。
# 実画面で比較確認します
今回の事例は、自作の「コーナープレーヤー」を作成しているときに発生しました。以下にそのURLをリンクしました。


#### (1)悪い例
[悪い例リンク]
(https://iframe.tecoyan.net/corner/index_1.php)
初期画面のページでクリックすると、右側にメッセージとサムネイルが表示されます。

![悪い例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198006/82eade1e-ea69-97c6-943d-d1cc4d2fa97f.png)
悪いケース
このコメント入力画面は、背景色がグレー表示のメッセージをクリックすると表示されます。この例では、文字入力ができません。上の[悪い例リンク]で確認できます。ひらがなは入力できますが、他のキーは動作しません。



#### (2)正常な例
[正常なリンク](https://iframe.tecoyan.net/corner/index.php)
初期画面のページでクリックすると、右側にメッセージとサムネイルが表示されます。

![正常な例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198006/e0d5f808-7b58-db02-7bed-ddc2d5353195.png)
正常なケース
このコメント入力画面は、背景色がグレー表示のメッセージをクリックすると表示されます。この例では、文字入力ができます。上の[正常な例リンク]で確認できます。



# あとがき
デバックしていると、いつもこのような不具合に出会います。
結果を知りたくて、あまり考えずにスクリプトを記述しているとことのようなことが起こります。しかし、熟考ばかりしていたら、先へ進みませんので、とりあえず進めて、テストしてみます。結局、試行錯誤の連続になってしまいますが、この作業の過程で得るものは結構多く、後々に役立っているものと思います。スキルアップにもなっているのかと自己満足しています。
Splunk: マトリクスとリストを相互に変換してみる


###### 実施環境： Splunk Free 8.2.2

### 0. 概要

次のようなマトリクス形式のデータがあるとします。

![WS000390.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/a4e86841-f34d-e144-d16e-e1f8d504733f.jpeg "マトリクス")

一方で、次のようなリスト形式のデータもあるとします。

![WS000391.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/1ef48da1-6385-55db-6e33-426d1e8946d3.jpeg "リスト")

この2つは、同じデータを表しています。
集計方法によっては、この2つを相互に変換したい場合もあるかもしれません。
今回はその変換方法について考えてみます。

### 1. マトリクス ⇒ リスト

以下のようなマトリクス形式のデータをリスト形式に変換することを考えます。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval TEST_1 = CNT + 2, TEST_2 = CNT * 2, TEST_3 = CNT % 2
```

![WS000287.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/7b705ec0-2055-725c-ee78-0aab178901d8.jpeg "変換前マトリクス")

まずは mvappend 関数を用いて、3つのフィールドをマルチバリューに結合します。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval TEST_1 = CNT + 2, TEST_2 = CNT * 2, TEST_3 = CNT % 2
| eval TEST_0 = mvappend(TEST_1, TEST_2, TEST_3)
```

![WS000288.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/1539268a-1198-c244-3b50-5b3ad937d6db.jpeg "mvappend")

![WS000392.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/b462b836-a04c-810a-3b0d-88ebe3dcc2dd.jpeg "イメージ1")

次に mvexpand コマンドを用いて、先ほど結合したフィールドを複数のデータにまたがる形で展開します。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval TEST_1 = CNT + 2, TEST_2 = CNT * 2, TEST_3 = CNT % 2
| eval TEST_0 = mvappend(TEST_1, TEST_2, TEST_3)
| mvexpand TEST_0
```

![WS000289.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/0040e5f3-766e-b81a-f27c-46a874d0729f.jpeg "mvexpand")

![WS000393.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/21677620-255d-8412-9ffa-7c67f97129b3.jpeg "イメージ2")

最後にフィールド名を付与していきます。
今回 mvappend 関数で結合した順番は TEST_1 ⇒ TEST_2 ⇒ TEST_3 なので、その順番が繰り返されるようにフィールド名を適宜付与します。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval TEST_1 = CNT + 2, TEST_2 = CNT * 2, TEST_3 = CNT % 2
| eval TEST_0 = mvappend(TEST_1, TEST_2, TEST_3)
| mvexpand TEST_0
| streamstats count AS CNT_2 BY CNT
| eval HEAD = "TEST_" . CNT_2
```

![WS000290.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/3c738c29-3681-e90d-adca-fe884dae5ede.jpeg "streamstats")

これでリスト形式に変換できました。

### 2. リスト ⇒ マトリクス

リスト形式のデータをマトリクス形式に変換するのは、 chart コマンドを用いれば非常に簡単に実現できます。

```Splunk:Splunk
| makeresults count=3
| streamstats count AS CNT
| eval TEST_1 = CNT + 2, TEST_2 = CNT * 2, TEST_3 = CNT % 2
| eval TEST_0 = mvappend(TEST_1, TEST_2, TEST_3)
| mvexpand TEST_0
| streamstats count AS CNT_2 BY CNT
| eval HEAD = "TEST_" . CNT_2
| chart values(TEST_0) OVER CNT BY HEAD
```

![WS000292.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/eaadab84-ba1f-61b9-05a2-db29938af6a5.jpeg "chart")

![WS000394.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/3e06167d-a8e0-55c2-b487-84bec8332471.jpeg "イメージ3")
Javaで「StringBuilderオブジェクトを初期化する」の動作を確認してみた

# 概要

Javaで「StringBuilderオブジェクトを初期化する」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/stringbuilder/index10.html

# 実装

以下のファイルを作成しました。
```JSample10_3.java
class JSample10_3{
  public static void main(String[] args){
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < 5; i++){
      for (int j = 0; j < 5; j++){
        sb.append((int)Math.ceil(Math.random() * 9));
      }

      System.out.println(sb.toString());
      sb.delete(0, sb.length());
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample10_3.java 
$ java JSample10_3 
42634
89912
23551
77242
62438
```

# まとめ

何かの役に立てばと。
Alibaba CloudでのLet's Encrypt証明書更新失敗と対処

## 更新失敗

`systemctl stop <YOUR_HTTPD>` でポート80で動いているデーモンを止めても、例のこれが出ます

```
$ certbot renew
<中略>
... Problem binding to port 80: Could not bind to IPv4 or IPv6.. Skipping.
```

`lsof -i:80` で調べると、どうもAlibaba Cloudのセキュリティ関連のデーモン（AliYunDun）が80番ポートで動いているらしく、更新時にはこれが邪魔をしてます。なので、このデーモンを `kill` してから `certbot renew` ください。 更新終了後はOSのリブートまたは停止させたデーモンを再起動して完了です！

以下公式サイトの記述です。

https://www.alibabacloud.com/help/en/security-center/user-guide/overview-of-the-security-center-agent

:::note warn
After the Security Center agent is installed, the server automatically downloads the aegis_client and aegis_update files and starts the AliYunDun and AliYunDunUpdate processes. The server downloads and starts the other files and processes listed in the following table only after you enable related features. Therefore, you need to pay attention to the files and processes only after the related features are enabled.

For example, if you enable the client protection feature, Security Center downloads the AliSecGuard file and starts the corresponding process on your server. If you do not enable the feature, Security Center does not download the file or start the corresponding process.
:::
Azure functionsローカル開発環境作成ログ

# ローカル開発環境を作るために行った作業ログ
## 環境整備
1. ドキュメントを見る(https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-develop-vs-code?tabs=node-v3%2Cpython-v2%2Cin-process&pivots=programming-language-python)
1. vscodeの[Azure Functions拡張機能](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions)をインストールした<img width="1024" alt="image.png (112.6 kB)" src="https://img.esa.io/uploads/production/attachments/20553/2023/10/01/148161/237b3862-4547-49b5-8d88-3a235f0123bc.png">

1. [Azure Functions Core Tools](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=windows%2Cisolated-process%2Cnode-v4%2Cpython-v2%2Chttp-trigger%2Ccontainer-apps&pivots=programming-language-python)からインストーラをダウンロード
1. インストーラを実行
1. Azure functionsでサポートされているPython3.9をpyenvでインストール
     参考：https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-cli-python?tabs=windows%2Ccmd%2Cazure-cli&pivots=python-mode-decorators#create-venv
1. Pythonプロジェクトのフォルダにローカルのバージョンを指定（pyenv local 3.9.13）
1. venvで仮想環境を作成（python -m venv 仮想環境名）

## ローカル関数の作成
参考：https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-cli-python?tabs=windows%2Ccmd%2Cazure-cli&pivots=python-mode-decorators#create-a-local-function

1. プロジェクトフォルダ作成
    func init LocalFunctionProj --python -m V2
1. プロジェクトフォルダの中身を確認
    <img width="186" alt="image.png (8.5 kB)" src="https://img.esa.io/uploads/production/attachments/20553/2023/10/01/148161/2547cff5-bd8a-4175-9cbc-a1ae25134ddf.png">
1. azuriteを実行したところ、以下のエラーが出力された
    1. azurite: The term 'azurite' is not recognized as a name of a cmdlet, function, script file, or executable program.
    1. 赤枠の準備を忘れていた模様
    <img width="957" alt="image.png (56.9 kB)" src="https://img.esa.io/uploads/production/attachments/20553/2023/10/01/148161/6785614d-6810-4d3d-8171-ab0831883068.png">

1. Azurite拡張機能のインストール
    <img width="570.6" alt="image.png (42.9 kB)" src="https://img.esa.io/uploads/production/attachments/20553/2023/10/01/148161/f4952d32-c15e-46bb-a66f-98f90fdbba4a.png">
1. vscode拡張機能をインストールしたため、azuriteの有効化はコマンドパレットで行う
    1. Ctrl + Shift + Pで起動するやつ
    1. 参考：https://learn.microsoft.com/ja-jp/azure/storage/common/storage-use-azurite?tabs=visual-studio-code#run-azurite
1. azuriteを有効化後、以下のコマンドで関数を起動状態？にしておく
    ```
    func start
    ```
1. ターミナル内に関数へのエンドポイントが表示されるため、ブラウザからアクセスすると関数が実行される
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1918417/a461ce1c-d957-96b6-ba35-b8bee203639e.png)


## デバッグしてみる
1. Azureリソースの画像内の部分をクリックする
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1918417/0d76e2e5-8e43-c2c1-6b88-167a80619e99.png)

1. 以下の警告が出たけど、一旦無視
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1918417/e6c851ca-e648-2a83-1418-400aac00809d.png)

1. Debug anywayをクリックし、エンドポイントへアクセスすると、ブレークポイントで止まってくれた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1918417/3099b55c-ee96-625d-b471-b694981bff29.png)



### 次回確認予定
Service Busキューへのメッセージを追加したときをトリガーにするfuctionsのデバッグ実行をやりたい。
pythonと　powerシリーズ連携

pythonで　測定したりAIした結果を
マイクロソフトの　listsへ保存しようとすると　手強かったりします。

大体あきらめて　ローカルにCSVファイルか頑張っても　ネットワークにDBを建てるくらいですが　
よくよく眺めてみたら、
ファイルシステムに　OneDriveが、マウントされています！！
ならば、OneDriveにjsonファイルを保存しておけば　後は　powerautomateでlistsへ書き込みしてもらえます。

簡単でした。
メモリ使用量を取得する


作成しているサイトが重いと感じたとき、もしかすると、メモリをたくさん使用しているかもしれないです。`performance.memory`を使用すれば簡単に取得できます。メモリ情報の取得方法とそれぞれの値の意味はこちらの[ChromeでJavascriptのメモリ使用量を確認する方法](https://blog.pokechoi.com/archives/1096)の記事に書かれています。
以下のコードはぱっと見でどのくらい使用しているかを確認するためのメモです。

```js
setInterval(() => {
    getMemory()
}, 1000);

function getMemory() {
    console.log(`使用可能なメモリ    ${(performance.memory.jsHeapSizeLimit / 1048576).toFixed(2)}MB`);
    console.log(`割り当てられたメモリ  ${(performance.memory.totalJSHeapSize / 1024).toFixed(2)}KB`);
    console.log(`現在使用中のメモリ   ${(performance.memory.usedJSHeapSize / 1024).toFixed(2)}KB`);
}

```

調べてみると、`performance.memory`はすでにdeprecatedみたいです。代替として`performance.measureUserAgentSpecificMemory()`を使用すればいいみたいですが、こちらはクロスオリジン分離しているページでないと使用できないです。([JavaScript で使用メモリ量を調べる](https://let.blog.jp/article/31672764))
なんか面倒になってきました。

#### 参考

https://blog.pokechoi.com/archives/1096

https://let.blog.jp/article/31672764
Edge の拡張機能を更新させない方法

# これは何？
推奨する訳ではないですが、ポリシーで拡張機能の更新を止める設定方法です。

# テストの前提
今回はトップにいたマイナポイント君に犠牲になってもらいましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/b8e71f08-f54d-6180-87ab-904ee31b4801.png)

インストール後、edge://extensions/ から 拡張機能の GUID をチェックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/73ac8b52-b727-a95c-d17a-40aa503b04dd.png)

今回は "belffchjaoimedencfpniadfmnfpnopp" です。

# 設定

レジストリエディタから ExtensionSettings ポリシーを設定します。
HKLM の方が設定が早いので楽。もちろん普通に gpedit.exe からポリシー設定でもよいです。

```regedit.exe
 {"belffchjaoimedencfpniadfmnfpnopp":{"installation_mode":"normal_installed","update_url":"http://localhost","override_update_url":true}}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/21667055-085e-2016-9802-96922846df9c.png)

設定後、 edge://policy から更新ボタンを押下。

# どうなるのか。
うまくいっていれば、削除リンクが消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/b96d0114-6e4d-fe7a-2680-7dc0dae9f404.png)

また、Fiddler で通信の中身を覗くと設定前後で下記のように変わるのがわかります。
(このキャプチャは変更後のもの)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/462a8b16-7a13-a64e-6754-900618fb40ae.png)

〇設定前
1通信のみで、当該の拡張機能の GUID 有。
edge.microsoft.com/extensionwebstorebase/v1/crx?os=win&arch=x64&os_arch=x86_64&nacl_arch=x86-64&prod=edgecrx&prodchannel=&prodversion=117.0.2045.36&lang=ja&acceptformat=crx3,puff&x=id%3Djmjflgjpcpepeafmmgdpfkogkghcpiha%26v%3D1.2.0%26installedby%3Dother%26uc&x=id%3Dkfbdpdaobnofkbopebjglnaadopfikhh%26v%3D113.0.1765.0%26installedby%3Dother%26uc **&x=id%3Dbelffchjaoimedencfpniadfmnfpnopp%26v%3D6.3.3%26installedby%3Dinternal%26uc**

〇設定後
2通信となり、https://edge.microsoft.com/extensionwebstorebase/v1/crx へのアクセスから当該の拡張機能の GUID が消える。
edge.microsoft.com/extensionwebstorebase/v1/crx?os=win&arch=x64&os_arch=x86_64&nacl_arch=x86-64&prod=edgecrx&prodchannel=&prodversion=117.0.2045.36&lang=ja&acceptformat=crx3,puff&x=id%3Djmjflgjpcpepeafmmgdpfkogkghcpiha%26v%3D1.2.0%26installedby%3Dother%26uc&x=id%3Dkfbdpdaobnofkbopebjglnaadopfikhh%26v%3D113.0.1765.0%26installedby%3Dother%26uc

localhost への通信が追加される。
localhost/?os=win&arch=x64&os_arch=x86_64&nacl_arch=x86-64&prod=chromiumcrx&prodchannel=&prodversion=117.0.2045.36&lang=ja&acceptformat=crx3,puff&x=id%3D**belffchjaoimedencfpniadfmnfpnopp**%26v%3D6.3.3%26installsource%3Dnotfromwebstore%26installedby%3Dexternal%26uc


# 補足1
https://edge.microsoft.com/extensionwebstorebase/v1/crx は Edge の 拡張機能の更新 URL エンドポイント。 ([公式](https://learn.microsoft.com/en-us/deployedge/microsoft-edge-manage-extensions-faq#what-is-the-update-url-for-the-microsoft-edge-add-ons-store))
[](https://edge.microsoft.com/extensionwebstorebase/v1/crx)

# 補足2
私は IIS 立ててるので localhost はすぐ応答を返しますが、応答の無い URL を update_url に設定した場合、
タイムアウトを起こしているので何か悪影響があるかも。(未検証

# 参考文献

[ExtensionSettings (Microsoft Edge - Policies)](https://learn.microsoft.com/en-us/deployedge/microsoft-edge-policies#extensionsettings)
[A detailed guide to configuring extensions using the ExtensionSettings policy](https://learn.microsoft.com/en-us/deployedge/microsoft-edge-manage-extensions-ref-guide)
よく使う変数名まとめ

<h2>
一般的な変数名
</h2>

1. **i, j, k**: インデックス変数。通常、ループ内で使用されます。
例: `for (int i = 0; i < array.length; i++)`

2. **count, total**: カウンター変数や合計を格納する変数。

3. **result**: 関数の結果を格納する変数。

4. **value**: 値を一時的に格納する変数。通常、一時的な計算に使用されます。

5. **input, output**: 入力データと出力データを表す変数。

6. **message, text**: メッセージやテキストを格納する変数。

7. **error**: エラーメッセージやエラー情報を格納する変数。

8. **flag, isXXX**: ブール値を格納する変数。条件を表現するのに使用されます。

9. **min, max**: 最小値と最大値を格納する変数。

10. **user, username, password**: ユーザー情報を表す変数。

11. **file, filename**: ファイルを表す変数。

12. **temp**: 一時的なデータを格納する変数。

13. **config**: 設定情報を格納する変数。

14. **index**: インデックスや位置情報を格納する変数。

15. **element, item**: 配列やコレクションの要素を表す変数。

16. **client, server**: クライアントとサーバー関連の変数。

17. **response, request**: HTTPリクエストとレスポンスを表す変数。

<h2>
SQLクエリ生成するための変数名
</h2>

1. `connection`: データベースへの接続を表す変数。
2. `sql`: 動的なSQLクエリ文字列を格納する変数。
3. `statement`: SQLクエリを実行するためのステートメントを表す変数。
4. `resultSet`: SQLクエリの結果を格納するための変数。
5. `department`: 動的な条件を指定する変数。この変数に基づいてSQLクエリが動的に生成されます。
GoogleAppsScriptでツールを作成する際の選択肢3選

GAS(GoogleAppsScript)を用いてツールを作成したい！となったときに考えられる選択肢を自分なりにまとめてみました。

# そもそもGASを使いたくなる場面とは
GASとは、GoogleAppsScriptの略で、Googleが開発し提供しているプログラミング言語です。

Google製品との連携が容易で、スプレッドシートやドキュメントを用いたツールを作成したり、それらからデータを取得できたりします。特に、スプシやドキュメントからデータを取得したい場合はGAS一択と言ってもいいのではないでしょうか。

参考：【GoogleAppsScript】活用事例集・一覧
https://eguweb.jp/gas-casestudy/

そんなこんなでGASを使いたくなったときに、どのように実装するかで悩んだのでここに書き残しておきます。

# 選択肢1 スプシやドキュメントをそのまま使う

最も一般的な選択肢です。もちろんこれで済むのであれば問題ないのですが、少し複雑な実装を試みるとすぐに頭打ちになってしまいます。

例えば、スプレッドシートのセルにはクリックイベントを設定することができません。一応、図形を配置してそれにスクリプトを設定することでクリックイベントを擬似的に実現することはできます。しかし、例えば取得データを一覧画面に表示し、行をクリックすると詳細が表示されるような動的なクリックイベントの設定はできません。
- メリット：最も一般的で簡単
- デメリット：複雑な機能は実装できない

参考：【GAS】スプレッドシートにボタンを追加する方法【Google Apps Script】
https://prtn-life.com/blog/gas-button

# 選択肢2 GAS+HTMLでWebアプリを作成しデプロイする

ではHTMLを書いて複雑な機能もつけたい！となったときに、GASのデプロイ機能を用いてWebアプリを作成するという方法があります。この方法ならGASでデータを取得しつつHTMLベースのアプリを作れてとても便利です。なので、基本的には複雑な機能が必要な場合この方法でいいんじゃないかと思います。

参考:Google Apps Script で Web アプリを作る
https://www2.kobe-u.ac.jp/~tnishida/programming/GAS-02.html

一見良さそうですが、この方法にも1つ落とし穴があります。この方法でデプロイしたアプリは、デフォルトでconsole.logが効きません。ちょっと調べてみるとGCP(GoogleCloudPlatform)と連携させないとログが出ない仕様になっているそうです。

もちろん長期的に開発をしていくつもりならやれよという話ですが、簡易的なものをササっと作りたいだけなら少し億劫な気もします。

- メリット：GASを用いてHTMLベースのWebアプリが簡単に作れるので、選択肢1よりも複雑な機能が実装できる
- デメリット：GCPと連携させる必要があり環境構築がちょっと面倒

参考:Google Apps Script (webapp) でログを記録する
https://mallowlabs.hatenablog.com/entry/2020/05/07/200000

# 選択肢3 スプシやドキュメントのカスタムダイヤログを使う

ササっとGAS+HTMLでツールを作りたい！というわがままに応えられそうな選択肢がこちらです。方法としては、スプシやドキュメントに"カスタムダイヤログ"という機能があり、HTMLでカスタマイズできるので、じゃあスプシとかはそっちのけでダイヤログをメイン画面にしてしまおうというものです。
この方法なら面倒な環境構築をせずにHTMLベースの複雑な挙動を実装でき、なおかつログも見られるので、意外とアリな選択肢だと思いました。

- メリット：簡単にGAS＋HTMLのツールを作成できる
- デメリット：スプシ(ドキュメント)である必要性はない、ダイヤログの幅が固定されてしまう

参考：GASで最も簡単なHTMLサービスによるダイヤログを作成する方法
https://tonari-it.com/gas-html-show-dialog/

# 最後に
GASでツールを作成するにあたって、意外と色々な選択肢があるよということを伝えたかったので記事を書きました。ざっくり書くと以下のような使い分けになるでしょうか。
- HTMLを使わなくてもできそう→選択肢1
- HTMLを使用したい、かつ面倒でも良い環境を構築したい→選択肢2
- HTMLを使用したい、かつ手っ取り早く実装したい→選択肢3

ちなみに私は、業務で1人日くらいでツールを作成しようとなったときに選択肢2を試し、面倒そうだったので止めて選択肢3を採用しました。ですが、後々機能が増えてきたことを考えてやっぱり2に戻そうかなという感じでフラフラしています。後々はclaspを用いてVSCode上で編集できるようにしたいです(これも色々模索中)。

参考:claspを使ってGoogle Apps Scriptの開発環境を構築してみた
https://dev.classmethod.jp/articles/vscode-clasp-setting/
コードを書くのは楽しいですか？

## おい、Qiitaどういう事やねん
先日久しぶりにQiitaにログインして[記事](https://qiita.com/monsoonTropicalBird/items/36129c49cb3d0aa39c49)を投稿し、戻って来てみたら数万ビューの閲覧があり、結構いいねがついていたりしていて、Javascriptでも最重要だと思うオブジェクトについて書いたり、Webアプリの根幹でもあるAPIについてがんばって書いた記事よりも、せっかく殺傷能力の高く実践的な英語とプログラミングというスキルを手に入れたのに職が無い、さかいをころす　等というオッサンの愚痴を書いたエントリーの方が読まれているというのは、全くもってQiitaというプラットフォームの闇が深い部分である。

### 改めて、なぜ自分がプログラミングを始めたのか考えてみた
で、久しぶりにQiitaのページを開いた事もあり、色々と他の人のエントリーを見たりしたわけですが、プログラマーはプログラミングを好きであるべきかとか、いち職業としてのプログラマーのあり方とか、働き方に関しての記事なんかが結構読まれていて、そういうテーマに現役の方々やプログラマーを目指している人は興味があるんだなと。
前の自分のエントリーも就職に関することであって、実は書きながら、自分は一体なぜコードを書きだしたんだろうかという事を考えざるを得ない心理状況になってしまい、この記事を書いているわけです。

### 就職のためでは無い
一番最初の記事でも少し書いたのですが、元々自分は薬科大学で製薬の勉強をしていたわけですが、そもそもデザイナーになりたくて、その当時に出てきたDTPというものにすっかり魅了され、パソコン一台で、画像やグラフィックのデザインから、活字、パブリッシングまで全てが机の上で出来てしまうというコンセプトに衝撃を受けた勢いのまま、大学を中退、親には勘当を言い渡され、真っ当な道を踏み外したまま現在に至り、一番最初にお金をもらった仕事はウェブページの制作でありました。
とにかく、自分で作ったものを世界にむけて発信できるという体験に酔いしれていたわけです。
で、その後ウェブからは距離を置き、人生紆余曲折を経て、パンデミックという大厄災により、今まで一生懸命積み上げてきたものを一気に失い、セブのアパートメントにロックダウンされている時に、なんの縁か舞い降りてきたのが、プログラミング。
そういえば、ラクダ本とか読みながらやっていたよねと、昔の知り合いを思い出すような感じで、さらにバックエンドで挫折した思いから、何となくやり残した感を長年引きづりつつ、めんどくさいヤツに関わりたく無いという気持ちもあり、昔嫌な別れ方をした彼女と再会するような気分で、初期アマゾンのシステムを開発し、アマゾンのバイスプレジデントも勤めた以前のボスから与えられたエイリアンウェアでUbuntuを立ち上げ、YouTubeやUdemyを英語で見ていると、あれっ、めちゃ簡単やん　とドンドンのめり込み、お金も仕事も自由も無いロックダウンの最中に、真夜中にセブの海を見ながら、安いビールを飲みつつコードを書いている時間が、唯一何か生産的な事をしているという実感と、行く末への希望のようなものが感じられるひと時でありました。

### コードを書くのは楽しいですか？

で、ある程度世の中の状況も落ち着きを取り戻し、そろそろ仕事を見つけないと死ぬ　という時に色々とエンジニア求人も見てみたのですが、仕事内容を見ていてもなんか全然これやりたいって感じないんだよね。
なんか大きなコードの一部を書くみたいな感じで、**ものを作るっていう雰囲気を感じない。**
日系ITの海外オフショアとかだと、ブリッジエンジニアとか、なんか管理職って感じだし。
コードを書いて、テストして、それが自分の思っているように動いた時は快感であるし、コーディング作業そのものは楽しいのだけど、**それが仕事っていう枠の中に入ると急に色合いが灰色になって見える。**
で、結局自分がプログラミングをして、何がしたいの？って考えた時に、やっぱり自分自身のアイデアを自分の手で形にするって事なんだよね。
そうなると、エンジニアという職業でどこかに就社するっていうカタチじゃなくて、自分の机の上で、自分の為にコードを書くのが、自分にとって一番幸せなカタチやんっていうことに気づき、結局２０数年以上も前にDTPに出会った時と自分は何も変わっていないよねと。
で、今はずっと考えていたピンク色のアプリを毎晩開発中です。
誰にも何も言われず、自分の部屋でやりたいようにコードを書いて、頭のアイデアをカタチにしていくっていう作業はやっぱり楽しいね。
Qiitaにいるプログラマーの大半はおそらく企業でプログラムを書いてる人達なんで、プログラミングが好きか嫌いか、ストレスをどう発散させるかみたいな記事が多いんだろうけど、それぞれにコードを書き始めたきっかけとか、続けてきた理由が何かあると思うので、その辺を思い出せば、もう少しコードを書くという作業が楽しくなるんでは無いだろうかと、自分がこれを書いていて思いました。
[baserCMS]コンテンツの公開状態を調べてみる（self_status, self_publish_begin, self_publish_end）


baserCMSでは、各コンテンツに公開開始日時、終了日時を設定することができます。
コンテンツ管理されている各コンテンツ（固定ページ、フォルダ、エイリアス、リンク、ブログ、メールフォーム）では基本的に全てに設定することが可能な便利機能となっています。

![スクリーンショット 2023-10-07 23.03.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26110/2f425fd4-17a1-9c08-cf4c-e2ec95f0d448.png "スクリーンショット 2023-10-07 23.03.03.png")

コンテンツデータが持っているカラムで、公開状態を示すものは以下となってます。

| カラム名 | 名前 | 備考 |
| --- | --- | --- |
| status | 公開状態 |  |
| publish_begin | 公開開始日時 |  |
| publish_end | 公開終了日時 |  |
| self_status | 自身の公開状態 |  |
| self_publish_begin | 自身の公開開始日時 |  |
| self_publish_end | 自身の公開終了日時 |  |

![スクリーンショット 2023-10-07 23.07.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26110/515d69c9-3cac-7df7-58ad-ec47785123b1.png "スクリーンショット 2023-10-07 23.07.17.png")

これらがどういった動作になっているのか調べてみました。


## 想定している対象者
- baserCMSでウェブサイトを制作をしている方
- PHPer


## 結論

- 親フォルダの公開状態、公開開始・終了日時を更新したタイミングで、配下コンテンツの公開状態、公開開始・終了日時を、親フォルダの値で更新している
- コンテンツの編集画面で表示しており編集出来るのは 自身の公開状態, 自身の公開開始日時, 自身の公開終了日時
- コンテンツの編集画面で編集した自身の公開状態, 自身の公開開始日時, 自身の公開終了日時は、保存時に公開状態, 公開開始日時, 公開終了日時に反映している
	- 親フォルダの公開状態を自身の公開状態に反映する

でした。
つまり、公開状態は常に親フォルダの値を見ているのと同義で、各コンテンツの公開状態を判定する際には、いちいち親フォルダの状態チェックを行わずとも済む仕組みとなってました。

| カラム名 | 名前 | 備考 |
| --- | --- | --- |
| status | 公開状態 | 親フォルダの値が入る |
| publish_begin | 公開開始日時 | 親フォルダの値が入る |
| publish_end | 公開終了日時 | 親フォルダの値が入る |
| self_status | 自身の公開状態 |  |
| self_publish_begin | 自身の公開開始日時 |  |
| self_publish_end | 自身の公開終了日時 |  |



### データで見る公開状態

■ これはフォルダと配下全てが公開状態にあるとき。
![スクリーンショット 2023-10-08 1.21.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26110/dbe4f421-3cf9-bc3e-3163-1613d38d9901.png "スクリーンショット 2023-10-08 1.21.04.png")

■ フォルダを非公開に更新 → 配下の公開状態も併せて更新される
![スクリーンショット 2023-10-08 1.19.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26110/da1c4f0a-ae99-7b8d-c3f4-df4b359cb24d.png "スクリーンショット 2023-10-08 1.19.18.png")

■ フォルダの公開開始・終了日時を設定
![スクリーンショット 2023-10-08 1.22.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26110/e2108d4c-7df2-45a6-fdad-09c81c5d5a37.png "スクリーンショット 2023-10-08 1.22.52.png")

■ フォルダを非公開にし、配下のコンテンツ（固定ページ）に公開開始・終了日時を設定
![スクリーンショット 2023-10-08 1.25.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26110/a796ecbf-f75f-ef1d-de13-3d3429d6da79.png "スクリーンショット 2023-10-08 1.25.29.png")


## まとめ

自分自身の公開開始・終了日時を保持しつつ公開状態を切り替えることのできる仕組みはこうなっていたんですね。
baserCMSの内部動作の理解をするのに良い機会でした。
Liggghts-PFMとCFDEM-PFMのマニュアルを作成

以前の記事でLiggghts-PFMとCFDEM-PFMのインストールを行いました。
通常のPublic版であれば、マニュアルがWebページで公開されているので確認しながら作業ができるのですが、PFM版ではWebページはなく、ソースから自分でHTMLを作成する必要があります。今回はその方法を共有します。今回の手順は、はリンク先の記事の方法で実施されているものとして進めます。

https://qiita.com/maumu1119/items/89c83569b0a7b195fd7f

### 方法
HTMLのmマニュアルの生成は、sphinx という Python 製のドキュメント生成ツールを使用します。
まず、Python3がインストールされていない場合は、Python3をインストールします。
~~~.sh
sudo apt-get install python3
~~~
pipをインストールし、sphinxパッケージもインストールします。
~~~.sh
sudo apt-get install python3-pip
pip3 install sphinx
pip3 install sphinxcontrib-image
~~~
CFDEMのインストール先に移動します。
以前の記事の手順でインストールされていれば/opt/CFDEM-5になります。
LAMMPS Documentation UtilitiesというものをGithubからクローンします。
その後、クローン先のディレクトリでpythonスクリプトを実行します。
~~~.sh
cd /opt/CFDEM-5
git clone https://github.com/ParticulateFlow/lammps-doc-utils
cd lammps-doc-utils
python3 setup.py install
~~~
まず、Liggghts-PFMのマニュアルから生成します。
Liggghts-PFMのディレクトリ内のdocに移動します。
~~~.sh
cd LIGGGHTS-PFM
cd doc
~~~
Makefileを編集します。冒頭のSPHINXBUILDのパスを指定します。
恐らく、/home/$USER/.local/bin/sphinx-buildになると思いますが、環境によって変わる可能性があるので、sphinx-buildの場所を確認し、パスを書き換えてください。
~~~.Makefile
# Makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXBUILD   = /home/$USER/.local/bin/sphinx-build
~~~
Makefileが編集出来たら、HTMLを生成します。docフォルダ内で以下スクリプトを実行してください。
~~~.sh
make html
~~~
問題なく完了していれば、docフォルダ内にhtmlが生成されていると思います。それをブラウザで開けばマニュアルを確認することができます。
CFDEMのマニュアルについても同様の手順で作成可能です。
CFDEMcoipling-PFMディレクトリ内のdocで同じ作業をすればhtmlのマニュアルを生成できるので実施してみてください。
Atcoderを振り返る(AtCoder Beginner Contest 323)

# はじめに

ここ数か月ほぼ毎週参加していますが、今回の問題の解き方で今後使えそうなものがあったため自分用にまとめています。

https://atcoder.jp/contests/abc323

# D - Merge Slimes
こちらの問題ですね。どういう問題なのかは、実際に上のサイトに飛んでいただいて確認してもらえればと思うのですが、要するに以下のような問題に変換できます。

* 小さいサイズ(a)のスライムから個数(b)を確認していき、それが2体以上いるならば倍の大きさ(2a)のスライムの数をb/2増やす。
* 最終的に小さいスライムから一番大きいスライムまでの数を計算していく

文字だけで見ると簡単そうなんですが、制約が個人的に厳しくて悩みました。
一つ方法として考えたのは配列をめちゃくちゃ作って、大きさの配列の番号に個数を入れていくというやり方で、下のような例の場合このように解けばいいじゃんと考えていました

```php

3
3 3
5 1
6 1

int ans[100009];
ans[3] = 3;
ans[5] = 1;
ans[6] = 1;

//ans[3]は個数が3以上あるため減らす
ans[3*2] += ans[3] / 2;

```

ただこの場合、配列の大きさが足りなくなるんですね。（大きさが1000000000,数が1000000000
のスライムがいた場合、もっと大きい値の配列が必要になるが作れない）

そこでいろいろ方法を調べると、上記よりも全然いい方法がありました。それが連想配列を作るやり方です。
先にコードを見せます
```php

#include <iostream>
#include <map>

using namespace std;

int main() {
    //Nに標準入力を代入する
    int N;
    cin >> N;

    map<long long, long long> slime_count;
    for (int i = 0; i < N; i++) {
        long long S, C;
        //S(スライムの大きさ),C(スライムの数)に標準入力を代入する
        cin >> S >> C;
        //連想配列を使い、スライムの大きさに対して何体いるのかを代入する
        slime_count[S] += C;
    }

    //連想配列が終わるまで、for文の中で連想配列のキーが増える可能性もあるため、これで最後まで確認する
    for (auto it = slime_count.begin(); it != slime_count.end(); ) {
        long long size = it->first;
        long long count = it->second;

        //数が2以上なら合体させる
        if (count >= 2) {
            slime_count[size * 2] += count / 2;

            //限界まで合体させたため、現在のイテレータの個数は0か1になる
            it->second %= 2;
            //もし個数が0なら確認する必要がないため削除
            if (it->second == 0) {
                it = slime_count.erase(it);
            } else {
                ++it;
            }
        } else {
            ++it;
        }
    }

    long long result = 0;
    //連想配列slime_countのキーが残っている値を確認していき、足していく
    for (auto &p : slime_count) {
        result += p.second;
    }

    cout << result << endl;

    return 0;
}

```

最初に自分が考えていた方法の場合、無駄に配列を作り、また配列の数にも限界があります。
それを連想配列を使うことにより、配列の個数を最低限に抑え、今回の条件を満たす大きさの個数を保存することができます。
このやり方だとサイズと個数が大きい以下の場合にも対応ができます

```php
1
1000000000 1000000000

map<long long, long long> slime_count; //スライムのサイズと個数の連想配列
slime_count[1000000000] = 1000000000; // 先ほどの式よりキー1000000000に対応する値を設定します

for文
{
    slime_count[2000000000] = 500000000;
    slime_count[1000000000] = 0; //0なので子の連想配列は消して次のイテレータ(2000000000)に移動する

    slime_count[4000000000] = 250000000;
    slime_count[2000000000] = 0;
}


```

みたいなことを繰り返して最終的に個数が2よりも少なくなったタイミングで一番下の値のキーの値を足していって答えを出します。

結論としては連想配列使うとこういうことができるよってことでした。
Swift 07 スイフト制御

>どんなフログラミーぐ言語を使用しても、アフリケーシン開発は`Logicを適用する作業`であり、対部分のフログラミーぐ技術は、一つ以上の`条件を基で決めていくコードを作る事`です。

>どんなコードを実行するか、何回を修行るかと関した`決定で`フログラミーぐが実行された時、どのコードを通るかが決ます。

>これは実行されるフログラミーぐの根の巻く気迫釜の茎かハス各窯の区なマンシクの流れを統制するもので`制御フロー`だと言います。
>>一般的に制御フローは、コードを何回実行するかについての`反復制御`と

>>どんなコードを実行するかについての`条件付き制御フロー`と別れる。

> 今度の章にはスイフトでの制御フローについて説明します。

# 7-1 反復制御流れ
初めて見渡しものは「for-in」反復文です。
# 7-2 スイフトfor-in構文
```swift
for 常数名 in コレクション or 範囲　{

}

```
> コレクションと範囲に包含された一連の項目を反服するに使用され、使いやすい反服文選択紙を提供します。

>ここで常数名は常数に使えられる名前で、反復文が行うコレクションまたはランジの現在項目を盛り込むことになります。

>一般的には反復文中のコードは反服周期の現在項目につにての参照体で常数名を使えることになります。(理解難しい)

>for-in反復文は`配列`と`ディクショナリー`みたいコレクションを持って作業する時に特に有用する。

>必ず参照体を貯蔵するために常数名を必ず宣言することはありません
```swift
var count = 0

for _ in 1...5{
count += 1
```

## 7-2-1 while反復文
```swift
while 条件文{
//遂行されるスイフト構文
}
```
条件がtrueの間で実行される

# 7-3 repeat ... while 反復文
これは　while反服文を逆くにすることだと考えればいい。
repeat while反復文は少なくても**一回には実行されなければならない状況**のために使用される。
例えば、配列中の項目たちの中で
```swift
var i = 10

repeat { 
   i -= 1
} while (i > 0)
```

# 7-4 反復文から抜けれる。
無限反復を作る時、例えばネットワークソーケットの活性化を時速的に点検しなければならない場合にがある。
もし、ネット活性化が感知さればモニタリングする反復文から出て他の作業をするはずだ。

# 7-5 continue 構文
これあとのコードは飛ばして反復文の最初に戻させする。

# 7-6 条件つき制御
フログラミーぐは理論を適用する巨大な作業なので、一つ以上の基にして決定するコードを作成するに、対部分のフログラミーぐ技術が使用されます。
# 7-7 if構文使用する
他のフログラミーぐ言語とは異なり、実行することが一行だとしても必ず{ } が必要です。
# 7-8 if ... else ...
# 7-9 if ... else if ...
その方法は数が少ない比較にはいいですが、**多いな条件文がある場合**には面倒なことがあります。
こんな場合のためにswitch構文を使う。
# 7-10 guard 構文
これはBoolean表現式を含み、trueの時だけguard構文の後に位置されるコードが実行される。
これはBoolean表現式がfalseの時に遂行されるelse節を必ず含くめるべきです。
else節には必ず現在のコード流れから出ていく構文「例え、return, break, continue, throw」含むことです。
他の方法で、elseブロックは自分自身をreturnしない他のfunctionとかmethodを呼ぶことが出来ます。
```swift
guard <条件文(Boolean)> else{
条件がfalseの時で実行されるコード
(コード流れから出ていく構文)
}
```
基本的に、guard syntaxは特定条件を満足されない場合に現在のfunctionとfor,whileで抜け出せるようにしてくれる。
```swift
func multiplyByTen(value: Int?) {
    guard let number = value, number < 10 else {
        print ("Number is too high")
        return
}
    let result = number * 10
    print(result)
}
multiplyByTen(value: 5)
multiplyByTen(value: 10)
    
```
ここの重要な点は、unwrappinged number 変数は　guard syntax外のコードでも有効することです。
反面、if syntax内で　unwrappingされた　変数は　if syntax外には有効ではない。　

# 7-11 要約
制御フローという用語applicationのsourceCodeが実行される時に実行経路をは指すlogicを表現する時に使われます。この章にはSwiftが提供する二つのフロー制御(if, for)と二つかたちの flow control logicを具現するために使用できる多様なswift structureを調べました。
メモリリーク検出（Sanitizer）

## 背景
メモリリークのチェックでValgrindを使用したが動作が重く、解決方法を探していたところgccに組み込まれている機能で動的にメモリリークと不正メモリアクセスをチェックできることが分かったのでまとめる。

## LeakSanitizerの概要
* メモリリークの動的チェックツール
* gcc/g++のコンパイルオプションに設定するだけで使用できる
* Valgrindより軽い
* Sanitizerにはリークチェック以外にも色々と機能がある

## リークチェックの例

サンプルコード
```C:main.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char* foo = (char*)malloc(sizeof(char));
    return 0; // mallocしたメモリをfreeせずにプログラム終了
}
```

サンプルコードを下記のコンパイルオプションでビルドする。
```shell
$ gcc gcc -fsanitize=leak -g -o main main.c
# -gオプションは出力結果にファイル名とコード行数を表示するために必要
```

ビルド後出力されたelfファイルを実行すると以下のように出力される。
`#1 0x55a32e84b17e in main /home/jkano/main.c:6`の部分で解放されていないメモリが割り当てられた場所を教えてくれる。

```shell
$ ./main

=================================================================
==1966==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1 byte(s) in 1 object(s) allocated from:
    #0 0x7fab9071b302 in __interceptor_malloc ../../../../src/libsanitizer/lsan/lsan_interceptors.cpp:75
    #1 0x55a32e84b17e in main /home/jkano/main.c:6
    #2 0x7fab90508d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
```
## メモリ不正アクセスチェックの例

サンプルコード
```C:main.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char* foo = (char*)malloc(sizeof(char) * 2);
    foo[2] = 0x01; // 確保していない3番目の要素にアクセス
    return 0;
}
```
サンプルコードを下記のコンパイルオプションでビルドする。


```shell
gcc -fsanitize=address -g -o main main.c
```

ビルド後出力されたelfファイルを実行すると以下のように出力される。
`#0 0x564ce0e501fe in main /home/jkano/sanitizer/main.c:7`の部分でメモリの不正アクセスが行われた場所を教えてくれる。

```shell
=================================================================
==5108==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000012 at pc 0x564ce0e501ff bp 0x7fff4cbbad30 sp 0x7fff4cbbad20
WRITE of size 1 at 0x602000000012 thread T0
    #0 0x564ce0e501fe in main /home/jkano/sanitizer/main.c:7
    #1 0x7f5e9d6d5d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #2 0x7f5e9d6d5e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #3 0x564ce0e500e4 in _start (/home/jkano/sanitizer/main+0x10e4)

0x602000000012 is located 0 bytes to the right of 2-byte region [0x602000000010,0x602000000012)
allocated by thread T0 here:
    #0 0x7f5e9d988887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x564ce0e501be in main /home/jkano/sanitizer/main.c:6
    #2 0x7f5e9d6d5d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/jkano/sanitizer/main.c:7 in main
(以下略)
```

## 注意
上記メモリ不正アクセスの例だと、メモリの不正アクセスが行われた時点でプログラムが止まってしまうが、以下を実施することでプログラムを実行し続けることが可能。
* コンパイルオプションの追加：-fsanitize-recover=address
  * 例：`$ -fsanitize=address -fsanitize-recover=address -g -o main main.c`
* 環境変数の設定：ASAN_OPTIONS=halt_on_error=0
  * 例：`$ export ASAN_OPTIONS=halt_on_error=0`

## 補足
Sanitizerには以下5種類あり、様々な動的コード分析が行える。
* AddressSanitizer メモリ破損チェック
* LeakSanitizer メモリリークチェック
* ThreadSanitizer スレッド間でのデータ競合チェック
* UndefinedBehaviorSanitizer 未定義動作の実行チェック
* MemorySanitizer 未初期化メモリの参照チェック

## 参考
* https://pleiades.io/help/clion/google-sanitizers.html
react-playerで再生速度の変更・スキップ操作を禁止する

Eラーニングのサービスを開発しています。react-playerを使って学習用の動画を再生する機能を実装しているのですが、とある事情で再生速度の変更(1.5倍速再生等)を禁止する対応を取りました。
意外と調べても対応方法が出てこなかったため、メモを残しておきます。


# やりたいこと
react-playerの再生速度の変更メニュー(赤枠の箇所)を非表示にしたい。
![playbackrate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2453728/6d47741a-4958-9128-8dd5-a9b33d58a275.png)


# 方法
configの`controlsList`で**noplaybackrate**を指定するだけです。
`controlsList`ではプレイヤーのコントロールバーに表示するメニューを制御できます。

```javascript
// 必要な個所のみ記載
  const config = {
    file: {
      attributes: {
        controlsList: 'noplaybackrate',
      },
    },
  }

  <ReactPlayer
    config={config}
  />
```
なお公式ドキュメントによると、この`controlsList`は試験的な項目であり、将来挙動が変わる可能性があると書かれているためご注意ください。またブラウザによってはサポートされていない場合があるそうです。

# 今後の話
今回の対応の背景としては「ユーザーの学習時間を担保したい。」という意図があります。(例えば30分の動画であれば、必ず30分視聴させることで「30分学習した」という事実を担保する。)
だとすると、スキップ操作(未視聴の部分へのシークバーの移動)も禁止しなければなりません。
これについてはconfigをいじるだけではどうにもならないため、ざっくり言うと以下の方法で実現を考えています。

**実装方針**
 - 何秒地点まで視聴済みかをstateで保持(変数名は`playedSeconds`とする)
 - `onProgress`発火時に「現在の再生秒数 > playedSeconds」の場合はplayedSecondsを現在の再生秒数で更新
 - `onSeek`の発火時に「シーク先の秒数 > playedSeconds」の場合はシークバーをplayedSecondsまで戻す

※実際には動画開始時にonSeekが走ったり、シーク時にonProgressが走ったりするため、↑に加えて細かな制御も必要になる認識です。

もし他にもっと楽な実装方法あれば共有いただけると幸いです！
【pytest】 pytest において mock を生成する方法

### 概要
mock の生成方法が複数存在し、複雑だったので整理した。


### mockとは
mock を知らない人のために簡単に説明を。

- テストにおける mock とは、テストに必要なオブジェクトを代替するもの。  
- mock を使用することで、オブジェクトの属性や戻り値を自由に設定できる
- DB から値を取得する必要のあるメソッドをテストしたい時などに重宝する

### mock を生成する方法
1.  unittest.mocker.patch を使用する
    - 以下のいずれかの方法で指定したオブジェクトを mock 化できる
        - @patch() アノテーションを使用する
        - patch() メソッドを使用する
            - with 文で生成可能
            
    - 以下の例では os.getcwd() メソッドの戻り値を固定している

    ```python
    import os
    from unittest.mock import patch
    class TestApp:
        @patch('os.getcwd')
        def test_patch(self, mock_getcwd):
            mock_getcwd.return_value = 'mocked'
            print(f"cwd={os.getcwd()}")

        def test_with(self):
            with patch('os.getcwd') as mock:
                mock.return_value = 'mocked-with'
                print(f"with={os.getcwd()}")

    # 実行結果
    # cwd=mocked
    # .with=mocked-with
    ```
    - 以下のように、patch() 内で戻り値を定義することもできる
    
    ```python
    import os
    from unittest.mock import patch
    class TestApp:
        @patch('os.getcwd', return_value = 'mocked')
        def test_patch(self, mock_getcwd):
            print(f"cwd={os.getcwd()}")

        def test_with(self):
            with patch('os.getcwd', return_value = 'mocked-with') as mock:
                print(f"with={os.getcwd()}")

    # 実行結果
    # cwd=mocked
    # .with=mocked-with
    ```

1. pytest-mock
    - @pytest.fixture を付与したメソッドに mocker を渡す
    - fixture を用いて mock を定義しているので、テスト後に自動でモックが破棄される

    ```python
    import os
    import pytest

    @pytest.fixture()
    def fixture_pytest_mocker(mocker):
        return mocker.patch(
            'os.getcwd', return_value='mocked'
        )

    def test_pytest_mock(fixture_pytest_mocker):
        print(f"pytest_mocker={os.getcwd()}")

    # 実行結果
    # pytest_mocker=mocked
    ```

### 各方法のメリットとデメリットについて
1. unittest.mocker.patch
    - メリット
        - Python 標準ライブラリの機能であるため、追加でライブラリをインポートする必要がない
    - デメリット
        - mock を使用する毎に処理を記述しなければならないので、冗長なコードになりがち  

1. pytest-mock
    - メリット
        - fixture で mock を管理でき、mock を使用する毎に処理を記述する必要がなく、コードが簡潔になる
    - デメリット
        - pytest を追加でインポートする必要がある

### まとめ
pytest を使える環境なら、2 の pytest-mock を使用する方がコードが簡潔になって良さそう
Webの住所はURL以外にある！！

## なぜ知りたいと思ったか？
URLを指定してWebサイトにアクセスしたが、関連情報として「URN」や「URI」もあり、調べてみようと思った。


## URLの内容を確認してみよう
URLは「Uniform Resource Locater」の略で、インターネット上にあるファイルの場所を指したもの
「プロトコル名」「ホスト名」「ドメイン名」「ディレクトリパス名」「ファイル名」で構成されている
```
https://www.geekly.co.jp/example/wp/index.html
```
・プロトコル名
通信方式で、上記の場合「https」の部分
・ホスト名
サーバーを表していて、上記の場合「www」の部分
・ドメイン名
自分で決められる固定の文字列で、上記の場合「geekly.co.jp」の部分
・ディレクトリパス名
ファイルを経由するディレクイトリで、上記の場合「example/wp」の部分
・ファイル名
アクセスするファイル名で、上記の場合「index.html」の部分


## URNについて
URNは「Uniform Resource Name」の略で、インターネット上に存在するファイルの名前のこと
ファイルの場所を変えるとURLは変わるが、URNは固定値のままで変わらない
コンテンツを閲覧する部分では、コンテンツのHTMLページが用意されている


## URIについて
「Uniform Resource Identifier」の略で、インターネット上にあるファイルを区別するための識別子
URLとURNを合わせたのがURIであり、普段見かけるURLはURIの一部なので、URIと呼んでも問題ありません。


## 調べてみて分かったこと
URNはIANAと呼ばれる組織で割り当てるので、設定は不要になる
Webページの住所をURL・URIのどちらを使っても問題はない
[Go]変数についてまとめた。[初心者向け]


## 初めに

Goの環境構築は、以下の記事を参考にして見てください。

https://qiita.com/yuto_swift_flutter/items/0a3d978c3cf557719d0a

## 変数について

明示的な変数の定義は以下です。

```Go
func main() {
var i int = 100
	fmt.Println(i)
}
```

こちらを、**go run main.go**をプロジェクトのルートで叩くと、

```Go
100
```

このように100が出力される。

int型以外も同様に出力できます。

```Go
func main() {
var i int = 100
	fmt.Println(i)

var s string = "Hello"
    fmt.Println(s)

var t,f bool = true,false

fmt.println(t.f)
}
```



ちなみにGoは宣言した変数や定数をどこかしらで使わないとビルドエラーが起きる。
これありがたい機能ですよね。

#### 異なる型を同時に宣言する

```Go
func main() {
	var (
		i2 int    = 100
		s2 string = "hello"
	)
	println(i2, s2)
}

```

このように、複数の型を同時に宣言することもできます。

#### 初期値の設定


以下のように変数に値を設定せずにprintした場合はその型の初期値が出力される。

int型は０、string型は空文字が初期値に設定されている。

```Go
var i3 int
var s3 string

println(i3,s3)
```

後から初期値を設定する方法は以下。

```Go
var i3 int
var s3 string

　　　　　　　　i3 = 300
	s3 = "Hello"

println(i3,s3)
```

#### 暗黙的な定義について

暗黙的な定義は以下のi5のように行う。
暗黙的な定義はその変数を関数外からアクセスできないようにすること。
つまり以下のコードはi5を関数外から呼び出しているためエラーが出ます。

```Go:悪い例
i5 := 100

func main() {
	
	println(i5)
}

```

#### 最後に

最後まで読んでいただきありがとうございました。
何かご指摘等ある場合はコメントいただけると幸いです。
ありがとうございました。
Rails & PostgreSQL: 本番環境のバックアップとローカルでの復元手順

# はじめに
個人で運営しているRailsアプリケーションでDBにPostgreSQLを使用しています。
データ数が多くなってきたため、本番と同等のデータで開発をしたく本記事では、本番環境のバックアップとローカル環境での復元方法の手順を記述しています。

# 概要図

1 本番環境のサーバーでバックアップコマンドを使用してdumpファイルを取得します。
2 dumpファイルをS3へアップロードします。
3 ローカル環境にてS3バケットからdumpファイルをダウンロードします。
4 ダウンロードしたdumpファイルをローカル環境のDBへリストアします。

![DBバックアップ・リストア手順.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/b5d419e3-d939-8547-a2b9-4f11b2a6967b.png)



# 本番環境でのバックアップ
下記スクリプトを用意して、本番環境のサーバーにて実行します。

```backup.sh
#!/bin/bash
source ~/.bashrc
# スクリプトのディレクトリを取得
script_dir=$(dirname "$0")

# 「Backup」ディレクトリを作成
backup_dir="$script_dir/backup"
mkdir -p "$backup_dir"

# バックアップファイルの保存先とファイル名を指定
DATE=$(date +%Y%m%d_%H%M%S)
backup_file="$backup_dir/db_schema_${DATE}.dump"

# データベース接続情報を指定
host="$DB_HOST"
port="$PORT"
username="$DATABASE_USERNAME"
database="$DATABASE_NAME"
password="$DATABASE_PASSWORD"

# pg_dumpコマンドを実行してバックアップを作成
PGPASSWORD="$password" pg_dump --file "$backup_file" --host "$host" --port "$port" --username "$username"   --verbose --format=c --blobs --no-owner --no-privileges --inserts --encoding "UTF8" --schema "public" "$database"

# S3へアップロード
sudo aws s3 cp "$backup_file" s3://[サービス名]/production/
```

# ローカル環境での復元

```restore.shell
#!/bin/bash

# S3バケット名とプレフィックス（ディレクトリパス）を指定
bucket_name=[バケット名]
prefix="production/"

# S3バケット内のオブジェクト一覧を取得し、最新のオブジェクトを検索
latest_object=$(aws s3api list-objects-v2 --profile [プロファイル名] --bucket "$bucket_name" --prefix "$prefix" --query "sort_by(Contents, &LastModified) | [-1]" --output json)

# 最新のオブジェクトからファイル名を取得
latest_object_key=$(echo "$latest_object" | jq -r '.Key')

# ダウンロードするファイルの名前を動的に設定（ここではオブジェクトキーの末尾を使用）
backup_file="downloaded_files/$(basename "$latest_object_key")"

# S3からファイルをダウンロード
aws s3 cp "s3://$bucket_name/$latest_object_key" "$backup_file" --profile [プロファイル名]


# データベース接続情報を指定
host="db"
port="5432"
username=[ユーザー名]
password=[パスワード]
database=[サービス名]

# pg_restoreコマンドを実行してバックアップを作成
PGPASSWORD="$password" pg_restore --host "$host" --port "$port" --username "$username" --dbname "$database" --no-owner --no-privileges --clean --verbose --schema "public" "$backup_file"

```

# 注意点
- 環境変数の取り扱い: 上記のスクリプトは環境変数を利用しています。これらの変数が正しく設定されていることを確認してください。また、パスワードなどの機密情報は公開しないようにしましょう。

- sudoの使用: sudoを使用してS3にファイルをアップロードしていますが、必要に応じて適切な権限を持つユーザーで操作することを推奨します。

- データの取り扱い: 本番環境のデータは機密情報を含む場合があります。取り扱いには十分注意し、不必要に外部に公開しないよう心がけてください。
Rで「あてはめ」ができるまでの道筋　トップページ

# トップページ
## このシリーズの趣旨
こんにちは。sflabです。
私は統計検定準1級の受験をきっかけにRを使い始めました。Rって便利ですよね。単回帰や重回帰はもちろん、PCAや分散分析なども少ない手数でできますし、ggplot2できれいなグラフを描くこともできます。Stanと連携させればMCMCだってお手のものです。私はSPSSを使ったことがありませんが、SPSSでできることはすべてRでできる、という方もいます。しかもSPSSは高価ですがRは無料です。

しかし、使えば使うほどまとまった情報を提供してくれるサイトが少ないことに悩まされてきました。そこでこれまであちこちで調べて実践してきたことをこの場でまとめておきたいと思います。基本はあくまでも備忘録ですが、より洗練されたものになればという期待を込めて公開することにいたします。シリーズを通して、Rをまったく使ったことがない方が、なんとなく使えるようになるまでの道筋を示していきたいと考えています。統計検定準1級の取得を目指している方々もRでのシミュレーションが合格への一助となると思います。

なお、内容が多岐に渡るため、本記事をトップページと位置付け、下記の内容を別記事として書きリンクを貼ります。リンクの貼られていないものは未完成です。

## 目次(予定)
以下のような内容を盛り込んでいこうと思います。まだまだ未確定ですので、本項目は度々修正することになると思います。

[とりあえずやってみる(単回帰)](https://qiita.com/sflabtech/items/bca5b11d0d63e5a01944)
[基本事項](https://qiita.com/sflabtech/items/ad9cb4d7e7a696958afa)
[基本的な関数](https://qiita.com/sflabtech/items/95b3c87344b636b50ebb)
[行列演算](https://qiita.com/sflabtech/items/6b1382cf70d8bb0f7f76)
[制御構文](https://qiita.com/sflabtech/items/1222db29fa0c6e687f6c)
[apply系関数](https://qiita.com/sflabtech/items/79723fc25f6dc280bf8a)

[ggplot2　①](https://qiita.com/sflabtech/items/5018cab0ba252eeda5bb)
[ggplot2　②](https://qiita.com/sflabtech/items/993f2b2d0202900b1d9c)
[ggplot2　③](https://qiita.com/sflabtech/items/f10865f63e533f02ca14)
[ggplot2　④](https://qiita.com/sflabtech/items/92c1ec2e262c5f6b23ba)

---以下、未完成---


t検定
単回帰・重回帰
PCA
分散分析
乱数
一般化線形モデル(GLM)
ロジスティック回帰
組み込みデータセット

ggplot2入門
　エラーバー
　pdfの描画
　フィルタの利用

Stan入門
　rstanのインストール
　単回帰
　重回帰
　二項ロジスティック回帰
　ロジスティック回帰
　ポアソン回帰
　ベクトル化
　弱情報事前分布

列挙するだけでうんざりしてきます...が、がんばります！
週に1〜2稿のペースで投稿することを目標にします。

## バージョン
本記事で用いたソフトウェアのバージョンは以下の通りです
R : version 4.2.1 (2022-06-23)
Stan : 2.21.0
OS : MacOS Monterey 12.4

## 筆者自己紹介
関西地区で高校教員(数学、物理、情報)しています。
E資格(2022#2)取得。統計検定準１級取得。