OmniAICreator/Qiita-1.07M huggingface dataset:
wsl2のneovimでWindows側とクリップボード共有をする


## Clip.exeに出力する方法
- ヤンクするたびにとても待たされてしまい、微妙かもしれない

### init.vimに追記しておく

```~/.config/nvim/init.vim
if system('uname -a | grep microsoft') != ''
  augroup myYank
    autocmd!
    autocmd TextYankPost * :call system('clip.exe', @")
  augroup END
endif"
```

### 参考
https://blog.logicky.com/2021/01/11/203719?utm_source=feed

## 

```powershell
Invoke-WebRequest `
    -Uri "https://github.com/equalsraf/win32yank/releases/latest/download/win32yank-x64.zip" `
    -OutFile C:\win32yank.zip

Expand-Archive C:\win32yank.zip -DestinationPath C:\WINDOWS\system32\

Remove-Item C:\win32yank.zip
```

## win32yamk.exeにわたす
clip.exeよりも早い

### init.vimに追記しておく

```vim
let g:clipboard = {
    \   'name': 'myClipboard',
    \   'copy': {
    \      '+': 'win32yank.exe -i',
    \      '*': 'win32yank.exe -i',
    \    },
    \   'paste': {
    \      '+': 'win32yank.exe -o',
    \      '*': 'win32yank.exe -o',
    \   },
    \   'cache_enabled': 1,
    \ }
```


### 参考
https://www.rhpav7.com/posts/wsl-vim-clipboard/
https://qiita.com/tMinamiii/items/0c6589806090c7fc3f8a
SourceTreeでコミットしたファイルを書き出す方法（Mac版）

# SourceTreeでコミットしたファイルを書き出す設定方法（Mac版）


##### 最初に書き出し用のファイルを用意します。
記述内容は下記の通りです（拡張子は.shです）
コメント部分は不要です
※書き出し先のパスはusersから始まるパス

```.sh
#!/bin/sh

# custom action for SourceTree
# params $SHA

ARCHIVE_TO="ここに書き出し先のパスを入力します/$(date +'%Y%m%d%H%M%S')/"

for commit_hash in $@; do
  git diff --name-only ${commit_hash}~...${commit_hash} | git checkout-index --prefix=${ARCHIVE_TO} --stdin
done
```


* * *


##### SourceTreeでコミットした部分を右クリックで「編集」をクリックします
![スクリーンショット 2022-02-26 12.10.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103633/dbeef873-f03f-e8d0-b97f-909b4535b9ab.png)

* * *

##### カスタムアクションの画面に移りますので「追加」をクリックします
![スクリーンショット 2022-02-26 12.17.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103633/ee85598b-5c62-e8e3-05ef-99732caf224d.png)

* * *

##### 下図のような画面になりますので、入力を進めます
![スクリーンショット 2022-02-26 12.18.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103633/6a3cd88e-cdf6-c074-822b-39d0b5d16730.png)

* * *

##### メニューキャプションはご自身が分かればなんでも大丈夫です
1番目の画像の「stg」と表示されているようにメニューキャプションに入力されたものはそこに表示されるようになります

* * *

##### 実行スクリプトファイルを選択します（「・・・」をクリックすればフォルダが開きます）
ここで一番最初にコードを記述したファイルを選択します

* * *

##### パラメータは```$SHA```と記述します。これでOKをクリック

* * *

##### すると下図のように追加されているかと思います
![スクリーンショット 2022-02-26 13.15.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103633/42eabefc-1be9-1185-ddb1-019b730200db.png)


* * *

##### これで再度コミットした内容を右クリックし登録したメニューキャプションをクリックすれば書き出しができます
以上です
* * *

##### もし 「 launch path not accessible 」 というエラーを吐いた場合

ターミナルを起動し、実行スクリプトファイルを保存したディレクトリに移動して下記コマンドを入力したのち、再度書き出しを行ってみてください。

```chmod +x {ファイル名}.sh```
AWS: AppSync の使い方

DynamoDB に Query を出す AppSync の使い方です。
DynamoDB　には、id, name, email という項目があるとします。

# 作成 #

「DynamoDB テーブルをインポートする」を選びます。
![appsync_feb2601.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/c912cc50-ebec-2861-d9da-7793060cb6b8.png)


テーブルを選びます。
![appsync_feb2602.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/982de5a8-be94-653d-b9a0-8df797aed311.png)

ロールを選びます。
![appsync_feb2603.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/144dd31f-c1ad-13e2-c373-17a17c67e5fa.png)


フィールドを追加します。
![appsync_feb2604.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f3ac2b21-7c5b-287b-500a-edc900dfaf5d.png)

API 名を入力
![appsync_feb2605.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/ef186894-164f-2206-9297-603243f91ab5.png)

作成したら、設定で API URL と API KEY を確認
![appsync_feb2606.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/28086712-62b6-fd5a-5363-ce15ddc50f1c.png)

# クライアントから接続 #

curl の例

```bash:client_curl.sh
API_URL="https://*****.appsync-api.ap-northeast-1.amazonaws.com/graphql"
#
API_KEY="da2-mfn*****"
#
curl -s -v  -XPOST -H "Content-Type:application/graphql" \
	-H "x-api-key:"${API_KEY} \
 -d '{ "query": "query {getUsers { items { id name email }}}" }' \
	${API_URL}
#
```

Httpie の例

```bash:client_httpie.sh
API_URL="https://*****.appsync-api.ap-northeast-1.amazonaws.com/graphql"
#
API_KEY="da2-mfn*****"
#
http POST ${API_URL} x-api-key:${API_KEY} \
        query="query {getUsers { items { id name email }}}"
#
```
AとBが同じではない時について（if 文）

簡易的なフリマアプリを作成中。

全てのコードを書き終えて、最終挙動確認を実施。

「自分の出品商品以外の商品には編集ページへ遷移しない」という挙動を確かめるため、直接URLに`/edit`を入力。
すると、意図と反して編集ページに移ってしまう。

該当するソースコードを確認。

```ruby:controllers/item_controller.rb
private 
def move_to_index 
    if !user_signed_in? && current_user.id == @item.user.id
      redirect_to root_path
    elsif @item.order.present?
      redirect_to root_path
    end
  end
```

よく見てみると`!`の位置がおかしい。
これだと「ユーザーがログインしていない時、かつログイン中のユーザーIDと出品した商品のユーザーIDが同じ時」というめちゃくちゃな日本語に笑
※「ログインいしていない時、かつログイン中」という矛盾が生じている

だからPCは「ログインしていない時」という条件をすっ飛ばして、編集ページに遷移させたのか・・・

とういうことで以下のコードに修正。

```ruby:controllers/item_controller.rb
private 
def move_to_index 
    if user_signed_in? && current_user.id != @item.user.id   #修正箇所
      redirect_to root_path
    elsif @item.order.present?
      redirect_to root_path
    end
  end
```

これで無事にトップページへ遷移してくれました。
ArrayListをC言語で作ったよ

C言語で可変長配列が必要になったから作ってみたよ
作りはすごく粗いし、最低限の機能しかねえからあんま使い物にはならないかもだけど
もっと高性能なListを作るときのヒントになるかも

# ソースコード

```ArrayList.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ArrayList.h"

struct ArrayList{
    struct index** array;
    unsigned int size;
    unsigned int arrayLen;
}__attribute__ ((__packed__));


struct index{
    char* data;
    int size;
}__attribute__ ((__packed__));


typedef struct ArrayList LIST;


int init_List(LIST** list){
    *list = (LIST*)malloc(sizeof(LIST));
    memset(*list, 0, sizeof(LIST));
    (*list)->array = (struct index**)malloc(1024 * 8);
    (*list)->arrayLen = 1024;
    (*list)->size = 0;
    return 0;
}

int addList(LIST* list, char* buf, int size){
    char* index = (char*)malloc(size);
    memcpy(index, buf, size);
    struct index* index_buf= (struct index*)malloc(sizeof(struct index));
    index_buf->data = index;
    index_buf->size = size;
    list->array[list->size] = index_buf;
    list->size++;
    if(list->size >= list->arrayLen){
        list->arrayLen += 1024;
        list->array = (struct index **)realloc(list->array, list->arrayLen * 8);
    }
    return 0;
}

int getList(LIST* list, int num, char* buf, unsigned int size){
    if(num >= list->size){
        return -1;
    }
    struct index* index = list->array[num];
    if(size < index->size){
        return -1;
    }
    memcpy(buf, index->data, index->size);
    return 0;
}

int removeList(LIST* list, unsigned int num){
    if(num >= list->size){
        return -1;
    }
    free(list->array[num]->data);
    free(list->array[num]);
    char buf[128 * 8];
    int a = list->size - num;
    while (a > 0)
    {
        if(a >= 128){
            memcpy(buf, &(list->array[num + 1]), 128 * 8);
            memcpy(&(list->array[num]), buf, 128 * 8);
            num += 128;
        }else{
            memcpy(buf, &(list->array[num + 1]), a *8);
            memcpy(&(list->array[num]), buf, a * 8);
            num += a;
        }
        a = list->size - num;
    }
    list->size -= 1;
    return 0
}

int free_list(LIST* list){
    for(unsigned int i = 0; i < list->size; i++){
        free(list->array[i]->data);
        free(list->array[i]);
    }

    free(list);
    return 0;
}


```

FILE*みたいに使えるようにしてみました
initで構造体のポインタを取得、初期化
addで最後尾に新しい要素の保存
getで指定したところの要素を取得
removeで指定したところの要素を削除
freeで使わなくなったListの削除（malloc使ってるから仕方ないね）
```__attribute__ ((__packed__))``` 使ってる理由？　気分

参考にしてね
zsh: command not found: gulp

Gulpを実行した際、「zsh: command not found: gulp」と表示されて動かない場合の対処法。

原因と解決方法は他にも沢山ありますが、
パスが通ってない場合があるので、下記を実行すると動きます。

```
export PATH=$PATH:./node_modules/.bin
```
Gatsby と GraphQL

# Why Gatsby Uses GraphQL より -何で静的pageジェネレーター GatsbyはわざわざGraphQLを採用したのか?

https://www.gatsbyjs.com/docs/why-gatsby-uses-graphql/

* プログラムによりページをビルドする場合 createPages NodeAPIを使ってページを作成する必要がある
    * → ブラウザサイドでJavascriptによりページ内容を描画するのではない。URLによるアクセスで最初に表示されるページを動的に生成する
    * プログラムにハードコードできない場合に..
        * JSON (third-party API, local Markdown, or JSON fileでデータを取得する）
            * gatsby-node.js の exports.cratePages の中でjsonから取得したデータを forEachで回してcreatePageでページを生成する
        * JSONではイメージを渡すことができない（imageフォルダに置いたイメージに対してその相対パスを渡すことになる）
        * GraphQLを使うとイメージのインポートも適切できる模様？ (graphql 関数の中で色々と指定できるみたい）
        *
【Unity】オブジェクトをターゲットに向けるLookAtコンポーネント (エディタ拡張付き)

Unityでオブジェクトを指定したターゲットに向けるためのコンポーネントです。
やっていることは単純に[Transform#LookAt](https://docs.unity3d.com/jp/current/ScriptReference/Transform.LookAt.html)で回転を制御しているだけですが、エディタ拡張でターゲットをTransformとVector3から選択できるようにしています。また、ターゲットがVector3のときにシーンビューからも位置を変更できるようにしています。

```c#:LookAt.cs
using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public enum LookAtTargetType
{
    Transform,
    Position
}

[ExecuteAlways]
public class LookAt : MonoBehaviour
{
    public LookAtTargetType targetType = LookAtTargetType.Position;
    public Transform targetTransform;
    public Vector3 targetPosition = new Vector3(0, 0, 0);
    public Vector3 up = Vector3.up;

    void Update()
    {
        if (targetType == LookAtTargetType.Transform)
        {
            if (targetTransform != null)
            {
                transform.LookAt(targetTransform, up);
            }
        }
        else // targetType == LookAtTargetType.Position
        {
            transform.LookAt(targetPosition, up);
        }
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(LookAt))]
public class LookAtEditor: Editor
{
    LookAt component;

    SerializedProperty targetType;
    SerializedProperty targetTransform;
    SerializedProperty targetPosition;
    SerializedProperty up;

    void OnEnable()
    {
        component = (LookAt) target;
        targetType = serializedObject.FindProperty("targetType");
        targetTransform = serializedObject.FindProperty("targetTransform");
        targetPosition = serializedObject.FindProperty("targetPosition");
        up = serializedObject.FindProperty("up");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        var type = (LookAtTargetType) EditorGUILayout.EnumPopup(
            "Target Type", (LookAtTargetType) Enum.ToObject(typeof(LookAtTargetType), targetType.enumValueIndex));
        targetType.enumValueIndex = (int) type;
        if (type == LookAtTargetType.Transform)
        {
            targetTransform.objectReferenceValue = EditorGUILayout.ObjectField(
                "Target Transform", targetTransform.objectReferenceValue, typeof(Transform), true);
        }
        else // type == LookAtTargetType.Position
        {
            targetPosition.vector3Value = EditorGUILayout.Vector3Field("Target Position", targetPosition.vector3Value);
        }
        up.vector3Value = EditorGUILayout.Vector3Field("Up", up.vector3Value);
        serializedObject.ApplyModifiedProperties();
    }

    void OnSceneGUI()
    {
        var type = (LookAtTargetType) Enum.ToObject(typeof(LookAtTargetType), targetType.enumValueIndex);
        if (type == LookAtTargetType.Position)
        {
            serializedObject.Update();
            targetPosition.vector3Value = Handles.PositionHandle(targetPosition.vector3Value, Quaternion.identity);;
            serializedObject.ApplyModifiedProperties();
        }
    }
}
#endif
```
M1にdocker環境移したらエラーが出た｜mysqlコンテナ

自分の環境ではmysqlのコンテナでエラーが出ました。
2022年3月現在の時点ではほぼネイティブ対応
（Rosetta2というCPU翻訳機を通さずに実行）
できるようになっているとのことでした。
[参考：Docker公式](https://docs.docker.com/desktop/mac/apple-silicon/)
一部コマンドや今回のような一部の公式イメージでは
少し対応が必要になる場合があります。

# エラー

```error.sh
$ docker compose up -d
[+] Running 0/1
 ⠹ mysql Pulling                                                                                                                                       3.1s
no matching manifest for linux/arm64/v8 in the manifest list entries
```

これはM1のプラットフォーム（アーキテクチャ）がarm64であるのに対し
mysqlのデフォルトのイメージがAMD64であるため一致しませんというエラーになります。

こちらの対策として
Docker-compose.ymlに
```
platform: linux/x86_64
```
という１行を加えます。


```docker-compose.yml
version: "3.7"
services:
  mysql:
    platform: linux/x86_64
    image: mysql:5.7
```

こうするとimageが作成されます。
これで再度docker compose up -dするとコンテナが起動すると思います。

# 環境
参考までに今回インテルマックからM1へ移行したコンテナの構成です。

nginxプロキシをdocker composeで立てつつ
↓
wordpressコンテナ
↓
mysql5.7コンテナ
↓
db専用busyboxコンテナ

こんな形でローカル環境用として動かしていました。

# 所感
M1が出た当初はかなり色々問題がネット上に上がっていたはずでしたが
現在はdocker for mac自体がほぼM1で動くようになったこともあり
スムーズに移行ができました。
自分が関わったところだけですが以上のような印象を受けました。
JupyterNotebookでF#を実行

# 概要

JupyterNotebook上でF#を実行するまでの手順を記す。


# Motivation

[Domain Modeling Made Functional](https://www.amazon.co.jp/dp/B07B44BPFB)を読んでいて、F＃の実行をさくりとやってみたい、かつ、その様子を記録しておきたいと思ったためJupyterNotebookでF#を動かしてみたいと思ったため。

# 手順

## 前提

- 環境はmacOS Monterey(12.2.1)
- pip3は入っている

## Jupyter Notebook インストール

[この手順](https://jupyter.org/install#jupyter-notebook)に従う。

下記コマンド実行でJupyter Notebookのインストールができる。
```zsh
pip3 install notebook
```

下記コマンド実行でさっくりとJupyter Notebookが立ち上がることが確認できる。
```zsh
jupyter notebook
```

![スクリーンショット 2022-02-26 11.28.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441085/b04cefe5-6809-bf4a-dae9-ca2eddaf0e66.png)

## Jupyter Notebook でF#を使えるようにする

[この手順](https://github.com/dotnet/interactive/blob/main/docs/NotebookswithJupyter.md)に従う。

### .NETをインストール
`uname -m`でアーキテクチャを確認して、[ダウンロードページ](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)からSDKのインストーラを落とす。

![スクリーンショット 2022-02-26 11.48.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441085/5679e0dc-2c72-c316-af96-18d01f48e3c8.png)

インストーラ実行したら、`dotnet --version`でインストールできたことを確認する。

### dotnet interactiveをインストール

下記コマンドを実行して、`dotnet interactive`をインストールする。
```zsh
dotnet tool install -g Microsoft.dotnet-interactive
```

### .NETのカーネルをインストール

下記コマンドを実行する。
```zsh
dotnet interactive jupyter install
```

正常にインストールできたら、下記のようにJupyter Notebookで管理しているカーネルが増えていることが確認できる。

```
[nannany@nannanynoMBP reading_memo (master *%=)]$ jupyter kernelspec list 
Available kernels:
  .net-csharp        /Users/nannany/Library/Jupyter/kernels/.net-csharp
  .net-fsharp        /Users/nannany/Library/Jupyter/kernels/.net-fsharp
  .net-powershell    /Users/nannany/Library/Jupyter/kernels/.net-powershell
  python3            /usr/local/share/jupyter/kernels/python3
```

## Jupyter Notebookで確認

再び`jupyter notebook`コマンドでJupyter Notebookを立ち上げると、下記のようにC#、F#、PowerShellが選択できるようになっている。

![スクリーンショット 2022-02-26 11.59.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441085/16339050-c239-6e46-b589-725a4029d369.png)

簡易なスクリプトを動かせることも確認できた。

![スクリーンショット 2022-02-26 12.06.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441085/4bc1ff42-9193-4352-850e-799edf82cf3c.png)
Go言語のバージョン管理ツール[goenv]の導入

## やること

Go言語のバージョン管理ツール [goenv](https://github.com/syndbg/goenv) を導入する

## 導入理由

プロジェクトによってGo言語のバージョンが異なったり、バージョンアップ対応する場合があると思うので、バージョン管理を行えるように導入する

## 環境

- OS: Ubuntu (18.04 LTS)
- Git
- Shell: bash or zsh

**Ubuntu向けに記載しますが、 `apt` とか使わないのでMacでも手順同じはずです**
→調べたらMacは `brew install goenv` だけでもインストールできるらしい。

## 導入手順

ホームディレクトリにgoenvをcloneする
```sh
git clone https://github.com/syndbg/goenv.git ~/.goenv
```

goenvを読み込むためのPATHを設定する
```sh
# bashの場合
echo 'export GOENV_ROOT="$HOME/.goenv"' >> ~/.bashrc
echo 'export PATH="$GOENV_ROOT/bin:$PATH"' >> ~/.bashrc

# zshの場合
echo 'export GOENV_ROOT="$HOME/.goenv"' >> ~/.zshrc
echo 'export PATH="$GOENV_ROOT/bin:$PATH"' >> ~/.zshrc
```

`goenv init` の設定を追加する
`GOPATH` や `GOROOT` の読み込み用に必要らしい
```sh
# bashの場合
echo 'eval "$(goenv init -)"' >> ~/.bashrc

# zshの場合
echo 'eval "$(goenv init -)"' >> ~/.zshrc
```

goenvを使用して `GOPATH` や `GOROOT` を管理する場合、上記の記述の後に以下の設定を入れるらしい。
```sh
# bashの場合
echo 'export PATH="$GOROOT/bin:$PATH"' >> ~/.bashrc
echo 'export PATH="$PATH:$GOPATH/bin"' >> ~/.bashrc

# zshの場合
echo 'export PATH="$GOROOT/bin:$PATH"' >> ~/.zshrc
echo 'export PATH="$PATH:$GOPATH/bin"' >> ~/.zshrc
```

上記の設定を読み込むためにshellを再起動
```sh
exec $SHELL
```

goenvが入ったことを確認
```sh
$ goenv -v
goenv 2.0.0beta11
```
ここで上手く行かない場合はbashrc(zshrc)の設定ミスっている可能性が高いので見直してください。

## Basic Usage

**指定したバージョンのGoをインストール**

`goenv install <version>`
```sh
# 記事作成時の最新バージョンをインストールしてみる
$ goenv install 1.17.7
Downloading go1.17.7.linux-amd64.tar.gz...
-> https://go.dev/dl/go1.17.7.linux-amd64.tar.gz
##################################################################################################################################################################################################### 100.0%##################################################################################################################################################################################################### 100.0%
Installing Go Linux 64bit 1.17.7...
Installed Go Linux 64bit 1.17.7 to /home/iwakura/.goenv/versions/1.17.7

# 確認
$ goenv versions
  1.17.7
```

↑上記でしれっと使用しましたが、インストール済みのバージョン一覧は `goenv versions` で確認可能

**使用しているPC全体のGoのバージョンを指定**

`goenv global <version>` 

```sh
$ goenv global 1.17.7

# 確認
$ go version
go version go1.17.7 linux/amd64
```

**カレントディレクトリだけ指定したバージョンのGoを使用**

`goenv local <version>`

```sh
# 確認用にディレクトリ作成&移動
$ mkdir goenv-test
$ cd goenv-test

# 別バージョンインストール
$ goenv install 1.12.0

# 切り替え前
$ go version
go version go1.17.7 linux/amd64

# 切り替え実行
$ goenv local 1.12.0

# 確認
$ go version
go version go1.12 linux/amd64

# goenv localのバージョン管理をする場合、以下のファイルが生成されます
$ ls -a
.  ..  .go-version

$ cat .go-version
1.12.0
```

## 最後に

以上、 `goenv` のインストールと使用方法についてでした！
ぶっちゃけ、[こちら](https://github.com/syndbg/goenv/blob/master/INSTALL.md)の内容を翻訳した程度なので細かい点は公式参照しましょう！
NatureRemo というタグ

# 製品情報だけみたら
Nature Remo という製品情報、そのものだけをみたら、

なんだ、これだけの機能しかないのか

それしか思いませんでした。

## [Raspberry Pi 4 B 8G](https://rpx.a8.net/svt/ejp?a8mat=1U7HX6+FG3Z56+2HOM+BW8O1&rakuten=y&a8ejpredirect=http%3A%2F%2Fhb.afl.rakuten.co.jp%2Fhgc%2F0ea62065.34400275.0ea62066.204f04c0%2Fa11102659679_1U7HX6_FG3Z56_2HOM_BW8O1%3Fpc%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Frobotshopjapan%252Frb-ras-32%252F%26m%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Frobotshopjapan%252Frb-ras-32%252F "Raspberry Pi 4 B 8G") を計画購入しちゃった

もともとRaspberry Pi 2を持っていましたが、
必要な機能を使うには十分でしたが、
やはりスペック不足でした。

今ある機能をrpi4に移して拡張しつつ
別の新たな機能をrpi2にしようかとして、
その中でrpi2による自動リモコン操作も考えました


## Raspberry Piによるリモコン、センサーはスマートではない
確かにrpiとGPIOを使って、ハードウェアのお勉強をするにはふさわしいのかもしれませんが

実用を考えるとスマートではないんです。

おまけに、必要なセンサー類を集めようとすれば、明らかに
[REMO-1W](https://rpx.a8.net/svt/ejp?a8mat=1U7HX6+FG3Z56+2HOM+BW8O1&rakuten=y&a8ejpredirect=http%3A%2F%2Fhb.afl.rakuten.co.jp%2Fhgc%2F0ea62065.34400275.0ea62066.204f04c0%2Fa11102659679_1U7HX6_FG3Z56_2HOM_BW8O1%3Fpc%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Fjism%252F0865164000361-35-45613-n%252F%26m%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Fjism%252F0865164000361-35-45613-n%252F "REMO-1W(joshinのが公式よりお得らしい）")のが安い

おまけに、APIが豊富そう

ってことで、こちらにしてみることにします。

## Raspberry Pi と Nature Remo のタッグ

rpiにはFreeBSDを入れていましたが、アップデートがめんどくさいので、ラズパイOSに不倫して、標準環境でいろいろ組んでみようかと思っています。

1㎜だけ楽しみにしてください。

どんな神コードが出るか、どんな糞コードがでるかわかりませんが。

## 参考：リモートコントロールする相手

ダイキンのエアコン

[謎の24bit 192khzデジタルオーディオアンプ](https://rpx.a8.net/svt/ejp?a8mat=1U7HX6+FG3Z56+2HOM+BW8O1&rakuten=y&a8ejpredirect=http%3A%2F%2Fhb.afl.rakuten.co.jp%2Fhgc%2F0ea62065.34400275.0ea62066.204f04c0%2Fa11102659679_1U7HX6_FG3Z56_2HOM_BW8O1%3Fpc%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Fnfjapan%252Fh194%252F%253Fs-id%253Dph_pc_itemname%26m%3Dhttps%253A%252F%252Fitem.rakuten.co.jp%252Fnfjapan%252Fh194%252F%253Fs-id%253Dph_pc_itemname "FX-AUDIO")

参考：目標

NatureRemoにもスマホアプリがあるが、スマホアプリに頼らず、
すべてより高機能にブラウザを操作できること

NatureRemoにも自動リモコン操作があるが、より高機能に操作するために、
NatureRemoのリモコン機能にも（外出先からも含めて）自動操作すること

NatureRemoで得られたセンサーを自動ロギング化する

言語　オワコンになりそうだけど、ナチュラルにperlで組んでみようかしら


## さいごに

これは、単なる購入前感想文です。あまり気にせずに
Rustでstr.lines()を使う ~ イテレータとenumerate() ~

```rust
fn main() {
  let quote = "\
The quick brown fox jumps over
the lazy dog.";
  for (i, line) in quote.lines().enumerate() {
    let line_num = i + 1;
    println!("{}: {}", line_num, line);
  }
}
```
Rustではイテレータを利用する際に生成する必要がある。

https://doc.rust-jp.rs/book-ja/ch13-02-iterators.html

文字列の場合`lines`がイテレータを生成している。
`Lines()`はString型を文字列スライスとして扱うイテレータ。

https://doc.rust-lang.org/stable/std/str/struct.Lines.html

また、`for in` でインデックスを取るために`enumrate()`を使う構文はPythonにも存在している。

https://docs.python.org/ja/3/library/functions.html#enumerate
Rails6とaxiosを連携させてデータを受け渡す！

## 実現したいこと
フロントエンドのデータをバックエンドに渡したい！

↓詳しく↓

JavaScriptのデータを[axios](https://github.com/axios/axios)を用いてDBに保存したい！

<br>

## 開発環境＆前提条件
Ruby 3.0.2
Rails 6.1.4.4
データを保存するDBテーブル等は作成済み

<br>

## 1. axiosの導入

**インストール**
```terminal:ターミナル
$ npm install axios
```
<br>

**CDN**
```html:任意のファイル
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
```

<br>

## 2. Javascriptへaxiosの記載

```javascript:任意のJSファイル
// ↓受け渡したいデータを格納
const data = { score: gameScore, user_id: "<%= current_user.id if logged_in? %>", beat_id: "<%= @beat.id %>" }

// ↓送信したいURLと渡したいデータを指定
axios.post('/scores', data);

```
<font color="DeepPink">上記記述を任意のfunction内（clickなど）に入れてaxiosを発火させます！</font>
私の場合、scores#createにpostでデータを送っています！
データの中身はscoreテーブル内のカラムに入れたい内容を格納しています！



```javascript:上記を詳しく
// ↓受け渡したいデータを格納
const data = { カラム名: "渡したいデータ" }

// ↓送信したいURLと渡したいデータを指定
axios.任意のメソッド('任意のURL', data);
```


<br>


## 3. Rails側の設定

```ruby:任意のコントローラ
class ScoresController < ApplicationController
  protect_from_forgery

# 以下省略
```
データを受け渡したいコントローラに```protect_from_forgery```の記載をします！
外部からのPOSTのため、上記を記載する必要があります。（[詳細](https://qiita.com/_ayk_study/items/88269643c675fd4ca975)）

<br>

<br>

ストロングパラメーターも以下のように修正します！
```ruby:任意のコントローラ
class ScoresController < ApplicationController
  protect_from_forgery

  # 省略

  private

  def score_params
    # requireを削除
    params.permit(:score, :user_id, :beat_id)
  end
end
```

上記の通り、requireの記述を削除してpermitのみにします！


<br>


## 4. 動作確認
1~3を行ったのち、axiosのあるfunctionを動かしてみると、データの受け渡しができているはずです🎉


<br>

## 参考にさせていただいたサイト
- https://github.com/axios/axios#instance-methods
- https://qiita.com/s_taro/items/30114cfa370aac6c085f

<br>


## 最後に
JavaScriptからRailsへのデータの受け渡しの記事が全くなかったので執筆しました！
本記事が多くの悩める方に届けば幸いです🌱
［AWS］今週の問題4週目(Windowsサーバー)

# 問題
問1. [A]を利用することにより、AWSコンソール画面から簡単にRDP接続が可能である。何か答えよ。

問2. WindowsサーバーのインスタンスからAMIを作成する際に、[A］の初期化が必要である。何か答えよ。

問3. 問2の手順は一般に下記の通りである。問2の作業は何番と何番の間に行うべきか？
また、問2の作業をすることにより[A]が出来なくなる。何か答えよ
1. 本番用インスタンスからAMIを作成
2. AMIから複製用インスタンスを起動
3. 複製用インスタンスからAMIを作成
4. 目的のインスタンスを起動

問4. Windowsサーバーのパスワードを変更すると[A]を用いたパスワードの復元が不可能になる。またカスタムAMIから起動したインスタンスのパスワードはどの状態か？答えよ。

問5. インスタンスの起動が不調な時は、コンソールから[B]を確認することでトラブルシューティングを行える。

# 解答
問1. [A]セッションマネージャー(SSMエージェント)
問2. マシンSID(システムの識別子みたいなもの)
問3. 2と3の間、[A]再起動
問4. [A]キーペア、元インスタンスと同じパスワードでデフォルトパスワードではない。
問5. システムログ(システムに関するイベントログみたいなもの)
Post Excerpt（抜粋）ブロックを機能させる方法（ver5.9.1）

# 環境
- テーマ：Twenty Twenty-Two
- バージョン：5.9.1

# 方法
投稿ページ内で、抜粋として表示させたい箇所の下に"More"（続きを読む）ブロックを追加する。

## 作業スクショ

1：挿入するブロックを選ぶ
![挿入するブロックを選んでいるところ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188888/a5c1067c-597f-6e5b-d7d0-5e6bb5c1a86e.png "挿入するブロックを選んでいるところ")

2：実際にブロックを挿入したあとのスクショ
![ブロックを挿入したあと](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188888/606379a1-a60f-4467-4e1d-560f31c6562a.png "ブロックを挿入したあと")

# 抜粋設定後の実際のスクショ

これで、Post Excerptブロックを設置した箇所に、抜粋された文章が入るようになる。
![抜粋された文章がウェブサイトに表示されているスクショ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188888/ad4506ef-51c1-86a8-79cf-b0490baf23ae.png)
時計を写経の後に作ってみた

<h2>デジタル時計を作って見た</h2>

手を動かしながら考える経験積むために時計を作ってみた
CSSは度外視の現在の時刻表示をするもの
(今回、Qiita初投稿なのだけど、こういう書き方なんですな　慣れなきゃ)

<h2>写経元にしたURL</h2>

https://qiita.com/delph/items/9c702cdf03a5679d93e0
（@delphさん、丁寧な説明で分かりやすかったです。ありがとうございます）


<h2>コード <h2>

使う言語は以下二つ

```html:clock-easy.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!--時刻表示　時：分：秒-->
    <div id="clock-time"></div>

    <!--日付表示　20xx/0x/0x-->
    <div id="clock-date"></div>

    <!--上記二つはjsから読み込む-->
    <script type="text/javascript" src="clockEasy.js"></script>
</body>

</html>
```

```javascript:clock-easy.js
  //時間が更新されるように時計機能を函数「clock」とまとめる

  function clock() {

   //前準備　曜日を表す各文字列の配列
  var weeks = new Array('sun','mon','tue','wed','thu','fry','sat')

　　// 数字が 1ケタのとき、「0」を加えて 2ケタにする
  var twoDigital = function(num) { //変数twoDigitalを設定する 引数（材料）はnum
        var digit  //変数digitを定義　numに0を加えるためのもの
         if (num < 10) {digit = "0"+ num; }  //if文 "0"+は文字列として0を足すため
         else {digit = num; }         
         return digit ;  //返り値（結果）としてdigitを返す
    }
 
  //  現在日時を表すインスタンスを取得→メソッドを使って時間情報をそれぞれ取得する

  var now =new Date();  //コンストラクタDate()により得た日時情報をインスタンス「new」に格納　newの中に現在の時間情報が全部入っている

  var year = now.getFullYear();
  var month = twoDigital(now.getMonth() +1 );        // 困る　月が２月なのに1月 → なので結果に1足す(10行目)
  var day = twoDigital(now.getDate());
  var week = weeks[now.getDay()];          // 困る  weeksがなければ曜日が数字表記 → なので、配列Arrayを使用して数字を曜日に変換するインスタンス「week」を作成し、代入　（4,13行目）
  var hour = twoDigital(now.getHours());
  var minute = twoDigital(now.getMinutes());
  var second = twoDigital(now.getSeconds());


 //　HTML: <div id="clock_date">(ココの日付文字列を書き換え)</div>
  document.getElementById('clock-date').textContent
   = year + '/' + month + '/' + day ;

 //　HTML: <div id="clock_time">(ココの時刻文字列を書き換え)</div>
  document.getElementById('clock-time').textContent
   = hour + '/' + minute + '/' + second;
   

  }

 // 上記のclock関数を1000ミリ秒ごと(毎秒)に実行 

 setInterval(clock, 1000);
```

<h2>わかった事</h2>
・VS Code

progateで勉強したのみだったので、VS Code使って見たかった
ターミナルの使い方（mkdir,touch,cd,open）をつかめた
ブラウザでの検証


・HTML
雛形の作り方
jsファイルの取り込み方と連携の仕方

・js
使用した関数の動作
変数定義の順番




・詰まったところ
写経元様の記事にて作成ステップがあったので、その順番でjsは書き足していった。
まず、「時計機能作って、その後に、0で桁合わせしよう」と思って書いてたら、桁合わせしたいgetMonthとかの下にdigit変数の定義をしていて、エラーが出て悩んだ。
しょうもないミス。
サーバへのデプロイを考慮したDjangoフォルダ構成

# 前提・やりたいこと
* DjangoでWebアプリを作成したけれど、ローカル環境で動かすことを前提としたフォルダ構成になっている。
* サーバへデプロイすることを考えたフォルダ構成にする。

# やったこと
**1. プロジェクトフォルダ名を「config」に変更**<br>プロジェクトは設定系のファイルしか入っておらず、それを明示したフォルダ名のほうが分かりやすいと考えたため。

**2. settings.pyを分割**<br>ローカル環境と本番環境で設定内容が異なるところがあるため、settings.pyをローカル・本番共通、ローカルだけに適用する設定、本番にだけ適用する設定、の3ファイルに分割。

**3. 環境変数を.envファイルに記載（django-environを使用）**<br>本番環境用のsettings.pyにはDB接続情報などを記載する必要があるが、直接settings.pyに書くとgithubにコミットする際に一緒に公開されてしまうので、.envファイルに記載してgithubには公開しないように設定。

**4. requirements.txtをローカル用と本番用に分割**<br>インストールするパッケージが、ローカルと本番で異なっているため分離。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533999/a1d18cce-244c-28a1-0b68-7d7a59828451.png)
※ 変更点以外のフォルダ・ファイルは省略しています。

# 完成
完成したフォルダ構成と実際のコードを載せておきます。

GitHub : [フォルダ構成を修正したアプリのコード（todoリストアプリ）](https://github.com/yamayuz/django-want2study.git)

```:デプロイ用のフォルダ構成
django-want2study/
　├ config/
　│　　└ settings/
　│　　　　└ base.py
　│　　　　└ development.py
　│　　　　└ production.py
　├ want2studyApp/
　├ templates/
　├ venv/
　├ .gitignore
　├ db.sqlite3
　├ requirements/
　│　　　└ base.txt
　│　　　└ production.txt
　├ manage.py
　└ .env
```

# まとめ
ローカルで動かすことだけを考えただけのフォルダ構成だと、やっぱりいろいろ足りないなあと思いました。まだデプロイ自体はできていないので、デプロイ結果によってはもしかしたら少し修正したりするかもしれませんが、とりあえずこのフォルダ構成で行ってみようと思います。
Fubiniの定理の証明の流れをチャート図でまとめてみた。

# はじめに

Fubiniの定理の流れがわかったのでチャート図でまとめておく。

# 単調族定理

ポイント！

有限加法族を含む単調族は$\sigma$-加法族となる。

**直積可測空間について**

基本集合の全体$\mathcal{K}$が有限加法族となり、基本集合の全体$\mathcal{K}$を含む単調族は$\mathcal{F}_X\times\mathcal{F}_Y$に一致する。

![有限加法族と単調族定理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/43fd4322-4d7c-fe74-9b6d-e6d15c7a69a5.png)

# E.Hopsの拡張定理とFubiniの定理

ポイント！

有限加法的測度に完全加法性を仮定すれば、有限加法的測度は完全加法的に拡張される。さらに、$\sigma$-有限と仮定すれば、拡張された有限加法的測度はE.Hopfの拡張定理より一意的に定まる。

**直積測度について**

基本集合$M$の$x$における切り口$M_x$と、基本集合$M$の$y$における切り口$M^y$のルベーグ積分が一致する。その基本集合$M$の測度$\lambda(M)$と一致すると仮定すると、その測度は有限加法的測度といえる。さらに、完全加法的である。ここで、$\mu_Y$と$\mu_Y$ともに$\sigma$-有限であると仮定すると、直積測度$\mu_X\times\mu_Y$を

$$
\mu_X\times\mu_Y(M_n):=\lambda(M_n)=\mu_X(X_n)\mu_Y(Y_n)
$$

とおけば、直積測度$\mu_X\times\mu_Y$は$\sigma$-有限であるので、E.Hopfの拡張定理から直積測度$\mu_X\times\mu_Y$は一意的に定まる。

**Fubiniの定理について**

Fubiniの定理を集合、非負可測関数（特性関数、単関数、可測関数）、積分可能関数の順に拡張して証明していけばよい。


![E.Hopfの拡張定理とFubiniの定理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/e31007fe-ae14-80f7-2b24-509558d6882e.png)

# 参照文献

- [松澤寛先生の講義資料](https://www.sci.kanagawa-u.ac.jp/math-phys/hmatsu/lecture.html)
- [単調族定理とE.Hopfの拡張定理について](https://qiita.com/momo10/items/cd40462456519bed220e)
sandbox って何のこと？

## 勉強前イメージ

アプリケーションとかを試せる・テストできる環境ってイメージ持ってる

## 調査

### sandbox とは

日本語でいうと砂漠といい、コンピュータ上の仮想空間のことを指します。
外部から受け取ったファイルなどをsandboxで実行し、安全かどうかを確認するための空間です。
もし、受け取ったファイルが悪意のあるものであっても隔離されているので通常の環境には影響が出ないようになっています。
特殊環境なので、普通は自由にできるストレージ上のアクセスも最低限に制限されています。

よく使われるのは、セキュリティソフトの機能で [ヒューリスティック検知](https://qiita.com/miyuki_samitani/items/129e045f0130052f1afa) というものがあり、
その中の動的ヒューリスティック検知というものでウイルスらしきプログラムをsandboxで実行させてウイルスかどうか確認を行います。
ただし、マルウェアの中には実行されているのがsandboxだと判断すると動作を停止するものもあるので
sandboxで問題ないから100%ウイルスではない！というわけではないです。

## 勉強後イメージ

今日は短め....
よく聞いてたけど、正直良くわかってなかったから雰囲気わかった。

## 参考

- [サンドボックス（sandbox）とは？メリット・デメリットから有効なセキュリティ対策まで解説](https://tokiocyberport.tokiomarine-nichido.co.jp/cybersecurity/s/column-detail82)
- [サンドボックス・砂場とは？機能や使い方・意味を解説！](https://cybersecurity-jp.com/column/30234)
40 代おっさん GASのHTTPリクエストとHTTPレスポンスについて学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## UrlFetchAppクラスとHTTPリクエスト

UrlFetchAppクラスはUrlFetchサービスのトップレベルオブジェクト

UrlFetchAppクラスの主なメンバー
|メンバー|戻り値|説明|
|--------|-----|----|
|fetch(url[, parame])|HTTPResponse|urlに対してパラメータparamsを渡してHTTPリクエストを行う|
|fetchAll(requests)|HTTPResponse[]|配列requestsに指定された複数のHTTPリクエストを行う|
|getRequest(url[, parame])|Object|urlとパラメータparamsによるリクエストを表すオブジェクトを返す|

fetchメソッドは指定したURLにたいしてHTTPリクエストを行うメソッド

構文

```javascript
UrlFetchApp.fetch(URL[, パラメータ])
```

パラメータは必要なものをオブジェクト形式で指定します。
単純なGETリクエストの場合は省略可能

|パラメータ|タイプ|説明|
|---------|------|----|
|contentType|String|コンテンツタイプ（デフォルト：application/x-www-form-urlencoded）|
|headers|Object|リクエストのHTTPヘッダー|
|method|String|リクエストのHTTPメソッド(デフォルト：GET)|
|payload|String|リクエストのHTTPメソッド（POSTの際のボディなど）|
|followRedirects|Boolean|リダイレクト先に取得するかどうか（デフォルト：true）|
|muteHttpExceptions|Boolean|レスポンスが失敗を示す場合に例外をスローするかどうか（デフォルト：false|

複数のリクエストをまとめて行いたいときには、fetchAllメソッドが便利

構文

```javascript
UrlFecthApp.fetchAll(リクエストの配列)
```

リクエストの配列は、URLを表す文字列か、リクエストの内容を表すオブジェクトを要素とする。

### HTTPResponseクラス

HTTPResponseクラスとは
HTTPリクエストをした際に外部から返答されたHTTPレスポンスを取り扱う機能を提供するクラス

HTTPResponseクラスの主なメンバー
|メンバー|戻り値|説明|
|-------|------|----|
|getAs(contentType)|Blod|HTTPレスポンスを指定したcontentTypeのブロブに変換|
|getBlod()|Blod|HTTPレスポンスをブロブとして返す|
|getContent()|Byte[]|HTTPレスポンスのバイナリコンテンツを取得する|
|getContentText([charset])|String|HTTPレスポンスを文字コードcharsetによる文字列に変換して取得する|
|getHeaders()|Object|HTTPレスポンスのヘッダーをオブジェクト形式で取得する|
|getResponseCode()|Integer|HTTPレスポンスのHTTPステータスコードを取得する|

お試し

```javascript
function tosiki() {
  const response = UrlFetchApp.fetch('https://twitter.com');
  console.log(response.getResponseCode());

  const headers = response.getHeaders();
  for (const key in headers) console.log(key, headers[key]);

  console.log(response.getContentText());
}
```

お試し（fetchAllメソッド）

```javascript
function tosiki() {
  const requests = [
    'https://twitter.com/',
    {
      url: 'https://www.facebook.com/',
      method: 'get'
    }
  ];

  const responses = UrlFetchApp.fetchAll(requests);
  for (response of responses) console.log(response.getHeaders()['Content-Type']);
}
```

## 参考資料

<https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Google-Apps-Script%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88/dp/4798064742>
既存のディレクトリをgit管理にしてリモートリポジトリと紐づけ

既に作成済みのプロジェクトをgit管理したかったので、備忘録。


対象のディレクトリに移動後
```
git init
```

このとき、下記のエラーが出たため、
> xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun


コマンドラインツールをインストールした。

ターミナルを開いて下記をrun:
```
xcode-select --install
```

Xcodeは必要じゃないよ、ここでは130MBのコマンドラインツールのみのインストールだよ。
もしこれだけだとワークしなければ、下記を動かしてみてね。とのこと。

> This will download and install the Command Line Tools package and fix the problem.
> You do not need Xcode, you can install only the Command Line Tools here, it is about 130Mb.
> If the above alone doesn't do it, then also run:

```
sudo xcode-select --reset
```

ref. [Stack Exchange | Why am I getting an “invalid active developer path” when attempting to use Git after upgrading to macOS Monterey?](https://apple.stackexchange.com/questions/254380/why-am-i-getting-an-invalid-active-developer-path-when-attempting-to-use-git-a)

無事git initできました。
ファインダー上からも隠しファイルとして.gitが確認できます。

続きましてリモートリポジトリを設定。

・ SSH版（GitHub）
```
$ git remote add origin git@github.com:ユーザ名/リポジトリ名.git
```
・ SSH版（HTTPS）
```
$ git remote add origin https://github.com/ユーザ名/リポジトリ名.git
```

ディレクトリ内全てのファイルをgit管理するためには、`git add`によるステージングが必要。
```
git add *
git commit -m 'first commit'
```

最後にリモートリポジトリへgit pushします。

```
git push origin master
```
AWS公式資料で挑むSCS認定(6)-IAM(続き)

[前回] [AWS公式資料で挑むSCS認定(5)-IAM](https://qiita.com/mingchun_zhao/items/eb89dd1a4d0695dbe7cb)

## はじめに

「やっぷ、やっぷーー」カーリング女子がくれた感動と余韻が今なお。
「やって、やってーー」一日勉強サボった自分への叱咤激励に聞こえたりします。

今回はVPC勉強予定でしたが、IAM続行に変更します、申し訳ありません。
前回のIAMに対し名人からご指摘頂き、本質を掴めていないことに気付きましたので。

## IAMの重要事項

以下、基本をしっかりと理解しておきます。
詳細は[AWSユーザーガイド](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/iam-ug.pdf)で確認しました。

### 「IAMユーザー」と広義の「ユーザー」は別物

- 「IAMユーザー」はAWS内部のIDで、「AWS外部のユーザー」がAWSとやり取りするためのサービスアカウント
- ユーザーだけでなくアプリケーションも表す
- IAMユーザーの実体は「名前と認証情報」で構成される

※ 同じく、「IAMロール」(AWS内部のID)と広義の「ロール」(AWS外部の職務など表すロール)も区別が必要

### AssumeRoleとPassRoleの違い

IAMロールの理解が曖昧でしたので、前回のおさらいから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/3dbce8b9-f9bd-ad66-1a52-5aaaaa5bbc0b.png)

- IAMロールとは
    - 一時アクセス権をユーザー・アプリ・サービスに付与する
    - 魔法のヘルメットで、一般人にかぶせたら一時的に秘密基地に入れる
    - ユーザーのみならず、アプリやEC2などのサービスにもかぶせ、リソースへのアクセス許可を与える


- AssumeRole
    - アクションの一種
    - ユーザーやサービスがIAMロールを引き受け、リソースへアクセス許可される
    - 自己解釈: ヘルメットをかぶる行為

- PassRole
    - 権限(アクセス許可)の一種
    - IAMロールを渡す側に必要な権限
    - 自己解釈: 秘密基地責任者が持つ、ヘルメットかぶせられる権限

### アクセスレベルの種類

ポリシーに記載されるアクションのアクセス許可は、レベル分けされている。

- リスト(List)
- 読み込み(Read)
- 書き込み(Write)
- アクセス権限管理(Permissions management)

### アクセスコントロール(制御)の種類

アクセス制御には、ロールベースと属性ベース、2種類ある。

- ロールベースのアクセル制御(RBAC)
    - (AWS外部の)ユーザーやロールの職務機能に基づいて定義したアクセス許可
    - IAMで従来から使用される認証モデルで、IAM管理ポリシーなどが含まれる

- 属性ベースのアクセス制御(ABAC)
    - 属性(タグ付け)に基づいてアクセス許可を定義する認証戦略
    - プリンシパルタグとリソースタグが一致する場合のみアクセス許可される(プリンシパルはリソースへのアクションをリクエストするユーザーやアプリ)
    - 理解に役立った公式資料: [IAM チュートリアル: タグに基づいて AWS リソースにアクセスするためのアクセス許可を定義する](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html#tutorial_abac_step2)

### アクセスアドバイザー

- IAMエンティティ(IAMユーザー、グループ、ロール)が最後にAWSサービスにアクセスした日付を表示
- IAMの各種設定が最小権限の原則に則しているか確認できる
    - IAMポリシー内で未使用または最近使用されていないアクセス許可を識別
    - 未使用のサービスに関するアクセス許可を削除
    - 類似の使用パターンを持つユーザーをグループに再編成

## クイズでリラックス

いきなりですが、クイズです。
IAM エンティティの代表的なクォータ(制限値)についてお答えください。

|リソース|クォータ|
|:------:|:-------:|
|IAM ユーザーに割り当てられるアクセスキー|?|
|AWS アカウント ルートユーザーに割り当てられたアクセスキー|?|
|AWS アカウントの別名|?|
|IAM ユーザーがメンバーになれるグループ|?|
|グループの IAM ユーザー数|?|
|IAM SAML プロバイダーのオブジェクトに関連付けられる ID プロバイダー (IdP)|?|
|SAML プロバイダーあたりのキー数|?|
|IAM ユーザーのログインプロファイル|?|
|IAM グループにアタッチされた管理ポリシー|?|
|AWS アカウントごとの OpenId Connect ID プロバイダー|?|
|IAM ユーザーのアクセス許可の境界|?|
|IAM ロールのアクセス許可の境界|?|
|IAM ユーザーが使用中の MFA デバイス|?|
|AWS アカウント ルートユーザーで使用中の MFA デバイス|?|
|インスタンスプロファイルのロール|?|
|AWS アカウントの SAML プロバイダー|?|
|IAM ユーザーに割り当てられる署名用証明書|?|
|IAM ユーザーに割り当てられた SSH パブリックキー|?|
|カスタマー管理ポリシーにアタッチできるタグ|?|
|インスタンスプロファイルにアタッチできるタグ|?|
|OpenID 接続 (OIDC) ID プロバイダーにアタッチできるタグ|?|
|IAM ロールにアタッチできるタグ|?|
|SAML ID プロバイダーにアタッチできるタグ|?|
|サーバー証明書にアタッチできるタグ|?|
|IAM ユーザーにアタッチできるタグ|?|
|仮想 MFA デバイスにアタッチできるタグ|?|
|AWS アカウントのユーザー|?|
|格納できる管理ポリシーのバージョン|?|

正解は[IAM エンティティのクォータ](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_iam-quotas.html)に載っています。

## おわりに

IAMの重要事項をピックアップし再理解しました。
机上だけでなく、AWSユーザーガイドのチュートリアルを実践することで、
理解がさらに深まる気がします。
次回こそVPCです、お楽しみに。

[次回] [AWS公式資料で挑むSCS認定(7)-VPC](https://qiita.com/mingchun_zhao/items/1492d0abee18ddc4ae1a)
Djangoのルーティングとは(urls.py)

# はじめに
Djangoを理解するためにはルーティングを理解することは大事だと思いましたので、自分の頭の中を整理するためにも書いていきます。

# ルーティングとは
リクエストに応じて、Djangoプロジェクト内でどのような処理経路を辿らせるかを指定するものです。簡単に言うとネットワーク上で行われる道案内です。

# urls.pyの役割
ルーティングは総称ですが、urls.pyは実際にコードを書いて指示を出します。urls.pyの役割はブラウザから送られるHTTPリクエストに対して、どのページを表示するかという指示を記載することです。実際にはviews.py内のどの関数を実行するか記載し、views.pyがどのページを表示するかを記載しています。


ルーティングにはプロジェクトルーティングとアプリケーションルーティングの２種類があります。実際には分けなくても動作上は問題ありませんが、管理をすることが大変になりますので分けています。
![スクリーンショット 2022-03-03 9.21.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184823/76dab476-f012-b610-3d1d-c256a5efcb48.png)


### プロジェクトルーティング
プロジェクトルーティングはサーバーからHTTPリクエストを受け取ってアプリケーションルーティングへ繋ぎます。なのでHTTPリクエストがあった際に一番初めに問い合わせがあります。urls.pyでどのアプリケーションに引き渡すかを指定します。
```プロジェクト名.urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('アプリケーション名.urls')),
]
```



### include関数
path関数の第二引数にinclude関数は使うことができます。
include関数で、アプリケーション内のurls.pyを連結させます。引数にはアプリケーションフォルダ内のurls.pyを指定します。簡単にいうとHTTPリクエストがあった場合、view.pyなどの処理をせずにそのまま指定した値へ繋ぎます。なのでinclude関数は主にプロジェクト内のurls.pyに使用し、HTTPリクエストがあった場合はプロジェクトルーティング→アプリケーションルーティングへ処理を受け渡します。

```
path(URL, include(アプリケーションフォルダ名.urls))
```






### アプリケーションルーティング
アプリケーションルーティングはプロジェクトルーティングから引き継いで指定したviewに渡し、viewで処理されたものがHTML形式でWebページに反映されます。urls.pyではどのviewのどの関数に引き渡すか指定します。
```アプリケーション名.urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('test/', views.index, name='test'),
]
```
### path関数
```
path(URL, views.関数またはviews.クラス, name=URL名称)
```
第一引数にURLを入れます。この第一引数はrequestを受けた時の受け皿となります。例えば、もともと表示されているページから表示したいページを開くためのrequestが来ます。上記画像のリクエストです。それを基にプロジェクトルーティングを辿りますが、同じアプリケーション内ではそのまま進み、アプリケーションルーティングにいきます。アプリケーションルーティングに対応するのがurls.pyです。その中のpath関数の中の第一引数とrequestがマッチするものを選びます。
第二引数のviews関数またはviewsクラスを処理したいものを指定します。（include関数も第二引数として入ります。）
第三引数は第一引数と同じで受け皿です。ここで違うのはURLではなく任意のURL名称をつけることで、もともと表示されているhtml側で表示したいhtmlのURLを全部書く必要がないことです。なのでrequest時にURL名称でも探すことができます。


```
#指定したい処理が関数の場合
path(URL, views.関数名, name=URL名称)
```

```
#指定したい処理がクラスの場合
path(URL, views.クラス名.as_view(), name=URL名称)
```

# まとめ
ルーティングを理解できるとDjangoのフレームワークの理解につながります。私もエラー発生時にどこに問題があったか判別するときに役立ちました。ルーティングは流れなのでコードを書く際にも実装していくときにイメージしやすくなりました。


[参照サイト：「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word1498.html)

[参照サイト：OFFICE54](https://office54.net/python/django/urls-path-include)

[参照サイト：エビワークス](https://ebi-works.com/django-routing/)
データフレームからのベクトルを用いたデータ抽出

# やりたいこと
noという列とキーコードという列を持つ、1000行のデータフレームがある。ここから、noをインデックスとして、あるnoリスト（ベクトル）に基づいてキーコードを取得したい。


# 方法
```R
subset(data, data$no %in% nolist)
```
`%in%`を使うことによって、nolistに掲載されているインデックスnoに含まれるもののみを抽出することができる。

参考：
https://monstera.hatenadiary.jp/entry/2018/02/15/181135
機械学習で写真をHDRに

# 写真をハイダイナミックレンジにする方法です

![pexels-francesco-ungaro-1671324.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/8d22bb47-946e-9715-4105-5488dba3dfba.jpeg)
![2dcd2f35-3e0c-46cb-84cb-7d32b987f3ea.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0ef8f063-d6bf-6887-2ae7-d5a759be33ce.png)


# 機械学習で写真を鮮明に
ローダイナミックレンジの画像を入力するだけで、ハイダイナミックレンジにレタッチしてくれるモデルがあります。
今回はCSRNetを使います。

https://github.com/hejingwenhejingwen/CSRNet

# 使い方

CSRNetのリポジトリをクローンし、test_Enhance.ymlの dataroot_LQ を任意の画像ディレクトリに変えます。

```python
python test_CSRNet.py -opt options/test/test_Enhance.yml
```

これで結果がresultに保存されます。

# 写真補正アプリケーションに

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
【Python】データ補正（全半角文字の統一、置換）

備忘録

# 計算環境
macOS Monterey 12.2
Python 3.8.2
Panas 1.4.0

# ファイル
元ファイル（汚いデータ）
csv_file_01.csv　
|名前  |Name  |都市  |登録日  |
|---|---|---|---|
|佐藤  |sato  |東_京  |2022-01-05  |
|鈴木  |suzuki  |大_阪  |2022-02-01  |

csv_file_02.csv
|名前  |Name  |都市  |登録日  |
|---|---|---|---|
|高橋  |Takahashi  |大_阪  |2022-01-20  |
|田中  |Tanaka  |東_京  |2022-02-09  |
|伊藤  |sato  |名古屋  |2022-01-17  |
|渡辺  |watanabe  |東京  |2022-01-17  |


ゴール（整理されたデータに補正）
csv_file_new.csv
|名前  |Name  |都市  |登録日  |
|---|---|---|---|
|佐藤  |SATO  |東京  |2022-01-05  |
|鈴木  |SUZUKI  |大阪  |2022-02-01  |
|高橋  |TAKAHASHI  |大阪  |2022-01-20  |
|田中  |TANAKA  |東京  |2022-02-09  |
|伊藤  |ITO  |名古屋  |2022-01-17  |
|渡辺  |WATANABE  |東京  |2022-01-17  |

# 課題
1. Nameに大/小文字が混在
2. 都市に'_'を含む 


# コード
```

import pandas as pd

# csv, excelファイルの読み込み
csv_data_01 = pd.read_csv('csv_file_01.csv')
csv_data_02 = pd.read_csv('csv_file_02.csv')

#　データを縦方向に結合
csv_data = pd.concat([csv_data_01, csv_data_02], ignore_index=True)

# 課題1の解消:大文字に統一
csv_data['Name'] = csv_data['Name'].str.upper()

# 課題2の解消："_"の削除
csv_data['都市'] = csv_data['都市'].str.replace("_", "")

# csvの書き出し
csv_data.to_csv('csv_file.csv', index=True)


```
中学2年生のみなさんへ。〈4/5〉数列「2022年共通テスト数学ⅡB第4問(1)(2)配点20点」の自転車君をmatplotlibで作図してみました。

続き

https://qiita.com/mrrclb48z/items/297442a71820732d3ea3

今さらですけど。自転車君をsympyとmatplotlibで作図してみました。
数列を使っていませんが、リストを使っています。

今回気づきましたが、問題用紙「P43のグラフ。原点(0,0)から(a1,0)に自転車君の太い実線」がありました。



### myN=4の場合
![myPolyN=4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/b7644d4c-f3d8-790e-69e5-7ff3702bcbe7.png)

### myN=2の場合
![myPolyN=2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/58b948dd-64b7-8181-f6a2-9a61982bc604.png)


# sympyとmatplotlibで

myNで最大値を変更で対応しました。

教えて下さい。
最大値を入力しない方法は、ありますか？

```python
from sympy import *
var('x y')
import matplotlib.pyplot as plt
def myJitensya(nMax):
    myPoly=[[0,0],[2,0]]
    i=2
    ans = solve([y - myPoly[i-2][1] - 1 * (x - myPoly[i-2][0]),
                 y - myPoly[i-1][1] - 2 * (x - myPoly[i-1][0])], [x, y])
    myPoly=myPoly+[[ans[x], ans[y]]]
    i=1
    for j in range(nMax):
        i=i+1
        myPoly=myPoly+[[myPoly[i][0]+1,myPoly[i][1]]]
        i=i+1
        ans=solve([y,y-myPoly[i][1]+2*(x-myPoly[i][0])],[x,y])
        myPoly=myPoly+[[ans[x],ans[y]]]
        i=i+1
        myPoly=myPoly+[[myPoly[i][0]+1,myPoly[i][1]]]
        i=i+1
        ans=solve([y-myPoly[i-2][1]-1*(x-myPoly[i-2][0]),
                   y-myPoly[i  ][1]-2*(x-myPoly[i  ][0])], [x,y])
        myPoly=myPoly+[[ans[x], ans[y]]]
    return myPoly
def myPolytLn(Ho,myLabel,myLinestyle):
    plt.plot([x[0] for x in Ho],[x[1] for x in Ho], mec='none', ms=4, lw=1, label=myLabel,linestyle=myLinestyle)
    for i in range(len(Ho)):
        if i % 2==0:
           myPos='right'
        else:
            myPos='left'
        plt.text(Ho[i][0], Ho[i][1], '({x}, {y})'.format(x=Ho[i][0], y=Ho[i][1]),
                  fontsize=6, horizontalalignment=myPos)
    return
def main():
    # myN=4
    myN=2
    myPoly=myJitensya(myN)
    print("Plot",myPoly)
    #以降作図
    plt.axes().set_aspect('equal')
    myPolytLn(myPoly,'myPoly','-')
    plt.legend(frameon=False, fontsize=10, numpoints=1, loc='upper left')
    # plt.savefig('myPoly.png', dpi=200)
    plt.show()
if __name__ == '__main__':
    main()

```




# おまけ機能

print文は,文字数制限内？であれば、文字列をコピーして、wolframalphaで実行できます。


実行例)

https://www.wolframalpha.com/input?i=Plot+%5B%5B0%2C+0%5D%2C+%5B2%2C+0%5D%2C+%5B4%2C+4%5D%2C+%5B5%2C+4%5D%2C+%5B7%2C+0%5D%2C+%5B8%2C+0%5D%2C+%5B15%2C+14%5D%2C+%5B16%2C+14%5D%2C+%5B23%2C+0%5D%2C+%5B24%2C+0%5D%2C+%5B46%2C+44%5D%5D&lang=ja

実行時エラー)文字数制限を超える時

Oops, you've exceeded the maximum number of characters.



# 参考

(2022-03-13)


Mathematica code printing


https://docs.sympy.org/latest/modules/printing.html#module-sympy.printing.mathematica

# つづく〈5/5〉へ
:::note info
https://qiita.com/mrrclb48z/items/2d3bc887074d0062e82d
:::
ターミナルで不要になったPATHを削除する

はじめまして。このたびはじめて記事を書いてみることにしました。
もし間違ってるところなどありましたら、コメントしていただけると幸いです。

---------
検証環境
MacBook Air (M1, 2020)
macOS Monerey ver.12.2.1

---------
ターミナルで

echo $PATH

と入力すると現在のPATHの状況が表示されますが、むかしPATHを通したものの、今は使っていないPATHがあることと思います。
そんなときは、ターミナルで

open ~/.bash_profile
open ~/.zshrc

のコマンド入力するとテキストエディットが出てくるので、

①安全のため全てコピーしてメモアプリなどに保存
②テキストエディット内の文章を削除
③画面左上のファイルから保存

をしてみてください。
2つとも操作が終わってから

echo $PATH

と入力してもまだ消したはずのPATHが残っていると思います。
なので一度ターミナルを終了し、再度「echo $PATH」と入力すると消したいPATHが消えていると思います。

もし消したくないPATHまで消えてしまった場合は、コピーして保存しておいた

.bash_profile
.zshrc

をもとのテキストエディットにペーストしなおして該当部分はどこか試行錯誤してみてください。
mayaの環境を構築していく　6日目

さて、骨打ちツールで寄り道したのでリグを進めていきます。

いきなり組み始めると、やり直しが面倒なので
トライアンドエラーしやすいようにリグをビルドするシステムを組んでしまいます。

最終的にはモジュラーリギングシステムにするとして、
今は開発用なので

**特定のスクリプトリストを選択して実行**

まずはこれだけにしてみようかと。

pythonFileの実行
--

実行したいのは pythonFileなので、pythonファイルを呼び出して実行する方法を調べる。

"D:\hoge.py"

```"D:\hoge.py"
print("hoge!")
```

このファイルを指定して実行したいとする。

import を使うとなると
pathをsys.pathに追加後、import　hoge するとしてこんな感じかしら

```
import os
import sys
def sourceScriptFile(filePath):
    dirPath = os.path.dirname(filePath)
    fileName = os.path.basename(filePath).split(".")[0]
    
    if dirPath not in sys.path:
        sys.path.append(dirPath)

    exec("import " + fileName)
```

exec を使うとなると
exec(open("D:\hoge.py").read())

```
def sourceScriptFile(filePath):    
    exec(open(filePath).read())
```

んー　とりあえず　execで('A)


fileのリストを取得
--
特定のフォルダに格納されているファイルのリストを取得したい

os を使うとこんな感じかしら

```
import os
def listFiles(dirPath,exts = None):
    files = []            
    for path in os.listdir(dirPath):
        if os.path.isdir(dirPath+path): 
            continue
        
        else:                        
            ext = path.split(".")[-1]
            fileName = os.path.basename(path)
            if exts != None and ext not in exts:
                continue

            files.append(fileName)
    
    return files
```

ファイルやディレクトリが大量になってくると pathlibを使った方が早いのだけれども、一旦osを使ってしまおう。

あとは適当にGUIをつけて・・・・
あれ、そもそもQFileSystemModel使えばファイルリストできるなということで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/4ac1d8c8-86a6-1248-e623-e8f213b9abf6.png)

こんな感じになりました。

眠いので続きは次回
さくらサーバーのDBを自動でバックアップする

# はじめに
さくらでレンタルサーバーとデータベースを借りている。
/wwwディレクトリ内のファイルについては、スタンダードプラン以上だと標準でバックアップ&ステージングの仕組みがあるのでそれを使えば常に定期バックアップは可能だ。
しかし、データベースについては、特段何か機能があるわけではない。
なんらかの何かで「間違って消しちゃった〜（てへぺろ）」となるのを防ぐためにも、
自動で定期的にバックアップをとる仕組みを構築したのでそのことを記載する。

なお、シェルスクリプトに関する部分はさくらインターネットと関係ない人にも利用できるネタだと思う。


# 自動バックアップの手順
## SSH接続
まずはターミナルからスクリプトを動かしたり、バックアップを保存するサーバーに接続
```
$ ssh [契約アカウント名]@[契約アカウント名].sakura.ne.jp
```
パスワードを聞かれるので入力。

## シェルスクリプト作成
接続できれば早速シェルスクリプトを保存するフォルダを作成。今回はwwwと同じ階層に作成
```console
$ cd /home/[契約アカウント名]
$ mkdir backup
$ cd backup
$ mkdir script
$ cd script
```
上記のコマンドで`/home/[契約アカウント名]/backup/script` に移動できれば以下のファイルを保存する。
viでファイルを作成してもいいし、ローカルでファイルを作成してFTPなどで保存しても何でもOK。

```sh:mysql_backup.sh
#!/bin/sh
# MySQL のバックアップ

# バックアップの保存期間（1ヶ月）
period=31

# バックアップを保存するディレクトリ
dirpath='/home/[契約アカウント名]/backup'

# ファイル名
prefix="mysql_"
filename="${prefix}`date +%Y%m%d`.sql.gz"

# mysqldump
# gzipで圧縮する
/usr/local/bin/mysqldump -u [契約アカウント名] -h [接続先データベース:*******.db.sakura.ne.jp] -p[パスワード] --no-tablespaces --single-transaction　-B [データベース名1]　[データベース名2]　[データベース名3・・・] | gzip > $dirpath/$filename

# パーミッションの変更
chmod 0600 $dirpath/$filename

# 古いバックアップファイルを削除
oldfile="${prefix}`date -v-$(($period + 1))d +%Y%m%d`.sql.gz"
rm -f $dirpath/$oldfile
```
以上です。

以下の行について詳しく記載します。
```
/usr/local/bin/mysqldump -u [契約アカウント名] -h [接続先データベース:*******.db.sakura.ne.jp] -p[パスワード] --no-tablespaces --single-transaction　-B [データベース名1]　[データベース名2]　[データベース名3・・・]  
```

`--no-tablespaces`についてはMySQL 5.7.31 以降、tabelspacesの仕様変更でつけないと以下のエラーが出るようになっています。

```
mysqldump: Error: 'Access denied; you need (at least one of) the PROCESS privilege(s) for this operation' when trying to dump tablespaces
```

`--single-transaction　`はInnobDB メインな DBでデータの整合性保つように追加。

また、今回は複数のデータベースのバックアップを取得する前提で、`-B [データベース名1]　[データベース名2]　[データベース名3・・・] `と記載しています。
単一のデータベースだけの場合、この部分は削除してデータベース名を1つだけ書いておけばOK。

なお、パスワードの前につける `-p`オプションのあとは半角スペースが不要なので注意ください。

## パーミッション変更
他のユーザーからスクリプトが見れないようにパーミッションを変更
```terminal
$ chmod 0600 mysql_backup.sh
```

## 動作確認
動作確認をしてみる。
```
sh /home/[契約アカウント名]/backup/script/mysql_backup.sh
```
`/home/[契約アカウント名]/backup/`のディレクトリ内に、`mysql_20220226.sql.gz`のようなファイルが出力されていればOK。

## さくらでcron設定
サーバコントロールパネルにログインして、スクリプト設定のメニューからCRON設定を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142359/0c67d103-c2ac-9864-c188-952fb9cb7e15.png)

スケジュール追加から、実行したい間隔と時間を記入して保存。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142359/512ee435-586f-02da-5eb8-2103e9557b4f.png)
（上記は、毎日4時に実行する設定の例）

細かい設定方法ついては　さくらのマニュアルを参照
https://help.sakura.ad.jp/360000208761/

こちらでめでたく、定期的な自動バックアップの仕組みが整いました！
これで快適さくらライフを！


# 参考（感謝）
https://qiita.com/t5h/items/eec78b6bd359d0a240f5

https://qiita.com/katzueno/items/29d812eb3aafdb23b0bb