OmniAICreator/Qiita-1.07M huggingface dataset:
初心者　MySQL8に挑戦する 7

# ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)を解決する

　せっかく導入したSequel Aceを接続できないまま、terminalからもいろいろいじり倒して挫折した昨日。PCをシャットダウンして、寝た。

　PCはシャットダウンしない、という人も多いけれど、大昔、今とは比べものにならないような性能の時代からPCを使ってきたので（ただのユーザーとしてです）、「PCもちゃんと寝ないと頭が働かない」的な感覚がある。なので特に理不尽な（と感じる）エラーに悩んだ日は、メールの確認さえ止めて、シャットダウンしてPCから離れる。しっかり寝て、明日は元気に働いてね〜、という気分。

## MySQLも寝てしまう。

　確かに再起動で直るエラーもある。が、実は今回のエラーは、再起動そのものが原因だった。きのう私は、別の理由で一度再起動したのだ。それはそれで役立ったのだけれど、そのとき、MySQLも寝てしまった、ということに気づかないまま、Sequel Aceを繋ごうとした。エラーが出て、いろんな記事を見ていじり倒して、挫折して、寝た。

　寝て起きた私は、PCを起こす。いまいま興味のないアプリがいろいろ勝手に立ち上がるのを消して回る。（ちゃんと設定で消せばいいんだが、めんどうくさい）　そして思ったのだ。MySQLは起きたのかな？

-  % mysql -u root -p      
Enter password: 
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

　今までいつもここからスタートしていた。でもそれって、導入してから一度も、PCを消していなかったときじゃないか？　確かもう一つ、コマンドがあったはずだ。

-  % mysql.server restart
 ERROR! MySQL server PID file could not be found!
Starting MySQL
. SUCCESS! 

　全く紛らわしいことに、エラー！といいつつ、Success！している。で、もう一回。

-  % mysql -u root -p    
Enter password: 
Welcome to the MySQL monitor.  （中略）
mysql> 

　やった。起きた！　で、Sequel Aceから接続。できた！

## 結論、寝た子はちゃんと起こしましょう。

https://qiita.com/dongri727/items/8c2b4125530d4b0147eb

https://qiita.com/dongri727/items/0e060282b66cdffa004a
【MySQL学習】一般クエリーログ

# はじめに
MySQLの一般クエリーログについて学習したことを簡単にまとめます。

# 検証に使用した環境
DB：MySQL8.0

# 一般クエリーログとは
一般クエリーログは、mysqlの実行内容が記録されるログファイルです。
クライアントが接続/解除したときの情報に加え、クライアントから受け取ったSQLステートメントをロギングします。
そのため、何かエラーが発生した時にクライアントが送信した内容を正確に知るのに利用します。

出力先を変更でき、ログファイル、DB内のgeneral_logテーブル、または両方に出力できます。

# ファイル名
ファイル名を指定しない限り、データディレクトリ内に「ホスト名(host_name).log」でファイルを作成します。

全てのログはWindows上のエラーログを除き、デフォルトでは無効化されています。
そのため、システム変数を設定して有効化する必要があります。

## システム変数
### general_log
一般クエリーログのロギングの有効・無効を設定できます。
「1」を指定するとロギングが有効になり、「0」を指定すると無効になります。
※「general_log」とだけ記載した引数なしの状態でも有効になります

### general_log_file
ファイルロギングでデフォルト以外のファイル名を指定します。

### log_output
ログの出力先を指定します。
log_outputには以下の単語をカンマ区切りで指定します。
TABLE　→　テーブルに出力
FILE　→　ファイルに出力
NONE　→　テーブル、ファイルに記録しない 
※NONEがある場合、他よりも優先されます。

起動時にlog_outputを指定していない場合、デフォルトのロギング先はFILEになります。

### log_timestamps
一般クエリーログに書き込まれるメッセージのタイムスタンプのタイムゾーンを指定します。
※スロークエリーログとエラーログにも反映されます

## セッション変数
### sql_log_off
現在のセッションに対する一般クエリーログのロギングを無効または有効に設定する
※一般クエリーログ自体が有効になっていることが前提

# ログの内容
前述の通り、一般クエリーログには、クライアントが接続/解除したときの情報に加え、受け取ったSQLステートメントがロギングされます。

以下、
MySQLに接続して「SHOW VARIABLES;」を実行した例です。

```shell
sh-4.2# tail -f 2476896863b5.log 
/usr/sbin/mysqld, Version: 8.0.29 (MySQL Community Server - GPL). started with:
Tcp port: 3306  Unix socket: /var/lib/mysql/mysql.sock
Time                 Id Command    Argument
2022-07-18T10:01:36.501366Z	    9 Connect	devuser@localhost on  using Socket
2022-07-18T10:01:36.501868Z	    9 Query	select @@version_comment limit 1
2022-07-18T10:02:16.887064Z	    9 Query	SHOW VARIABLES
2022-07-18T10:02:19.546411Z	    9 Quit
```

# 注意
## 出力順 
実際に実行された順番通りに出力されるとは限らない。

## パスワードの扱い
一般クエリーログにロギングされたステートメント内のパスワードは、プレーンテキストで出力しないようにサーバーによって書き換えられます。

一応、「--log-raw」オプションでパスワードの書き換えを抑制できます。
MySQLが受け取ったステートメントの正確なテキストが必要な時などに便利ですが、セキュリティー上の理由により本番用には非推奨とされています。

# 参考文献
https://dev.mysql.com/doc/refman/8.0/ja/log-destinations.html

https://dev.mysql.com/doc/refman/8.0/ja/query-log.html
【C++】基礎を学ぶ㉒～STL～

# STL
**STL**とは、`C++`の**標準ライブラリ**のひとつ
**汎用性が高く**、**型安全**で**高速**なクラステンプレートや関数を提供するライブラリ
ゼロから作成するよりも**効率的**に開発できる
**Standard Template Library**の略

### STLに含まれる機能の例
* コンテナ
* イテレータ
* アルゴリズム
* ファンクタ

## コンテナ
**コンテナ**とは、複数のオブジェクトを**管理**するオブジェクトのこと
**スタック**や**キュー**などのデータ構造も作成できる

### 代表的なコンテナの例
`vector`、`list`、`set`、`stack`、`queue`

### vector
**可変長配列**のこと
**動的**に配列の要素数を管理する仕組み

### サンプルプログラム
```cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
  vector<int> vec;
  
  for (int i = 0; i < 3; i++)
  {
    vec.push_back(i);
  }

  for (int i = 0; i < vec.size(); i++)
  {
    cout << vec[i] << endl;
  }
  return 0;
}
```
```
0
1
2
```

## イテレータ
**イテレータ**とは、コンテナ内での**要素の位置**を指すもの
コンテナの種類に**依存しない**で処理を**共通化**できる

### サンプルプログラム
```cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
  vector<int> vec;

  for (int i = 0; i < 3; i++)
  {
    vec.push_back(i);
  }

  for (auto it = vec.begin(); it != vec.end(); it++)
  {
    cout << *it << endl;
  }
  return 0;
}
```
```
0
1
2
```

## アルゴリズム
**アルゴリズム**とは、コンテナ要素の**ソート**などの操作を行う**テンプレート関数**のこと

### サンプルプログラム
```cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
  vector<int> vec;

  for (int i = 0; i < 3; i++)
  {
    vec.push_back(i);
  }

  // 降順でソート
  sort(vec.begin(), vec.end(), greater<int>() );

  for (int i = 0; i < vec.size(); i++)
  {
    cout << vec[i] << endl;
  }
  
  return 0;
}
```
```
2
1
0
```

## ファンクタ
**ファンクタ**とは、関数のように振る舞うことのできるオブジェクトのこと
**関数オブジェクト**とも呼ばれる

### サンプルプログラム
大富豪の強いカードを判定するファンクタ
```cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

// ファンクタ
class Daihugou
{
public:
    // 演算子 () をオーバーロード
    bool operator()(const int& a, const int& b)
    { 
      int new_a = a;
      int new_b = b;
      if (a <= 2){
        new_a += 13;
      }
      if (b <= 2){
        new_b += 13;
      }
      return new_a > new_b; 
    }
};

int main() {
  vector<int> vec;

  for (int i = 1; i <= 13; i++)
  {
    vec.push_back(i);
  }

  // 大富豪の強いカード順でソート
  sort(vec.begin(), vec.end(), Daihugou());

  for (int i = 0; i < vec.size(); i++)
  {
    cout << vec[i] << endl;
  }
  
  return 0;
}
```
```
2
1
13
12
11
10
9
8
7
6
5
4
3
```

## 次の記事
[【C++】基礎を学ぶ㉓～例外処理～](https://qiita.com/rapirapi/items/60308561de660dad0eb4)
100日後くらいに個人開発するぞ！day058

## 今日も継承について学んでみた！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/4945e170-7e44-d06b-1f7b-7e6ba8cdd398.png)


## 今日の学び
### インスタンス変数を用いる際はselfをつける
* 例
        * `class Food`
        * ` arttr_accessor :name`
        * ` arttr_accessor :calorie`
        * ` def calorie_info`
        * `  return "#{self.name}は#{self.price}円です"`
        * ` end`
        * `end`


### 継承されてないインスタンスメソッドを追加する
* 子クラスに独自のインスタンス変数を追加できたように継承されてないインスタンスメソッドを追加する
    * 例
        * `class Food < Menu`
        * ` arttr_accessor :calorie`
        * ` def calorie_info`
        * `  return "#{self.name}は#{self.price}円です"`
        * ` end`
        * `end`
【C#】ドライブの使用量を算出するプログラムを作ってみた

# この記事は移転します

https://ymd65536.hatenablog.com/entry/2023/10/30/000938

## どんなときに使うか

ディスクの使用量を調べるときに使うプログラム

## 動作環境

- Windows10 21H2
- dotNETCore 5.0

## サンプルコード

```csharp

using System;
using System.Windows.Forms;
using System.IO;


public class ProcessShow
{
  public static void Main(string[] args){
    
    // 保存先を変えたいときはここを変える
    string file_path = Path.Combine(@""+Environment.MachineName+"_driveInfo"+".txt");
    DriveInfo drive = new DriveInfo("C");
    
    long bitdivide = 1024 * 1024 * 1024;
  
    long CallSpace = drive.AvailableFreeSpace/bitdivide;
    long ALLSpace = drive.TotalSize/bitdivide;
    long TotalFreeSpace = drive.TotalFreeSpace/bitdivide;
    long UseByte = (drive.TotalSize - drive.TotalFreeSpace)/bitdivide;
    
      using (StreamWriter sw = File.AppendText(file_path))
      {
        if (drive.IsReady)
        {
          //DateTime.Now
          sw.WriteLine("呼び出し側が利用できるバイト数"+","+"ドライブ全体のバイト数"+","+"ドライブ全体の空きバイト数"+","+"ドライブ全体の使用容量");
          sw.WriteLine("{0}GB"+","+"{1}GB"+","+"{2}GB"+","+"{3}GB",CallSpace,ALLSpace,TotalFreeSpace,UseByte);
          
        }     
      }
  }
}
```

## おわり
戸建て住宅マーケティングAI 開発 (0)

これから、積もってきた python vue.js java 等の kipple を使って
戸建て住宅を題材に、マーケティングシステム(AI ?) の開発してみます。

以下のurlは、とりあえず立ち上げたもので、
今後、必要な機能を継ぎ足していきます。

[![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2639/a87baac6-01c0-ce21-ce73-bd1c1dada726.png)](https://15db.end0tknr.jp/)
STM32F010で時間関数と繰り返しタイマー割込みで遊ぶ(1秒)


x Mbed2リビジョン143


目的
簡易な時間づくり
例題をほぼそのまま使用


https://os.mbed.com/users/okini3939/notebook/time_jp/


https://os.mbed.com/users/okini3939/notebook/ticker_jp/


![o_con584.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e9821e4f-7fea-9100-cb1a-746ba5183112.jpeg)



SER_time_test1_010_1



```c++


#include "mbed.h"

DigitalOut led(PA_4);

RawSerial pc(PA_2, PA_3); //010

Ticker flipper;

time_t seconds = 0 + (60 * 60 * 9); // JST

void flip() {
    led = !led;
    seconds++;
}

int main()
{
    
    flipper.attach(&flip, 1.0); // the address of the function to be attached (flip) and the interval (1 seconds)

    
    pc.printf("\r\n<START>\r\n");
    
    
    struct tm *t;
    
    while(1) {
            
    t = localtime(&seconds);
 
    pc.printf("%04d/%02d/%02d %02d:%02d:%02d",
      t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
 
    pc.printf("\r\n");

        wait_ms(1000);
    }
}

//容量削減
void error(const char* format, ...){}




```
ID毎に値を累積してフラグをカウントアップする(SPSS Modeler データ加工逆引き4-6)

# ID毎に値を累積してフラグをカウントアップ（カウント）

![スクリーンショット 2022-12-21 12.46.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1172fe1a-0a83-efa7-08a2-ca13296f891f.png)

## 1.想定される利用目的

・顧客の累積購入金額や特定の行動回数を特徴量にする
・設備ログから累積値と発生回数を特徴量にする

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/count_up.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-12-21 12.48.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d35239ac-f8df-8fd6-3e6a-435e08d05504.png)

a.入力するデータは以下の通りです。ID(顧客/設備)が2種類存在します。
![スクリーンショット 2022-07-12 14.56.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1df7f01f-d369-180c-95cb-dfa3b4ab1c18.png)

b.[フィールド作成]ノードを編集します。ひとつ上のレコードとIDが一致するとカウントアップするインデックス（通し番号）を作ります。
![スクリーンショット 2022-07-12 14.58.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/973a0edb-f6c3-a18a-f129-36ce4f271061.png)

式ビルダーから@&#xFFF0;関数を探すと簡単に入力できます。
![スクリーンショット 2022-12-21 12.52.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/72f69a78-29cb-0966-4f19-7549eee5274b.png)

[プレビュー]します。
![スクリーンショット 2022-07-12 14.58.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/514422c4-c327-4a9f-d48d-ac0e1026626a.png)

c.[フィールド作成]ノードを編集します。INDEXの数だけ上方参照して累積します。
![スクリーンショット 2022-07-12 14.58.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/87189a79-5c6a-c994-4716-ab3934414c8d.png)

[プレビュー]します。
![スクリーンショット 2022-12-21 12.56.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/757b79c0-0789-51eb-3001-0e74235fd191.png)

d.[フィールド作成]ノードを編集します。
![スクリーンショット 2022-07-12 14.59.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/bb378106-3b09-38cf-9661-09bc141247f8.png)

[テーブル]を実行します。
![スクリーンショット 2022-12-21 12.57.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a2b50378-4f83-f5fd-aba6-580f2d232c59.png)

#### 注意点

カウント型を使ってフィールド作成するときにはレコードの並びが適切かを確認し適宜ソートします。

## 4.参考情報

#### フィールド作成のカウント型を解説した記事

https://qiita.com/kawada2017/items/7b3c279963d39043214a#3m-%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E5%9E%8B%E3%82%B8%E3%82%B0%E3%82%B6%E3%82%B0%E3%82%92%E8%B5%B7%E3%81%93%E3%81%97%E3%81%9F%E7%B4%AF%E7%A9%8D%E5%9B%9E%E6%95%B0modeler%E7%89%88

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
Leetcode easy: 412. Fizz Buzz(JavaScript)

[Leetcode](https://leetcode.com/)を始めたので記録しています。

## やった問題
https://leetcode.com/problems/fizz-buzz/

>Given an integer n, return a string array answer (1-indexed) where:
answer[i] == "FizzBuzz" if i is divisible by 3 and 5.
answer[i] == "Fizz" if i is divisible by 3.
answer[i] == "Buzz" if i is divisible by 5.
answer[i] == i (as a string) if none of the above conditions are true.

## 処理の流れをざっくり考える

* 3で割り切れる
    * 5で割り切れる => "FizzBuzz"
    * 割り切れない => "Fizz"
* 5で割り切れる => "Buzz"
* 割り切れない => return n

## 最初に書いたコード
```javascript
/**
 * @param {number} n
 * @return {string[]}
 */
var fizzBuzz = function(n) {
    const fizzbuzz_list = [];
    // in the range of n 
    for (let i = 1; i < n + 1; i++){
        // if　n kan devided by 3
        if (i % 3 === 0){
            if (i % 5 === 0){
                element = 'FizzBuzz'
            } else {
                element = 'Fizz'
            }
        } else if (i % 5 === 0){
            element = 'Buzz'
        } else {
            element = String(i)
        }
        fizzbuzz_list.push(element);
    }
    
    return fizzbuzz_list
};
```

>Runtime: 76 ms, faster than 86.26% of JavaScript online submissions for Fizz Buzz.
Memory Usage: 44.7 MB, less than 19.90% of JavaScript online submissions for Fizz Buzz.

## 調べたこと

https://begin-javascript.set0gut1.com/fizzbuzz.html

概ね同じ内容である。
最短だとこんな解き方があるらしい。

https://qiita.com/obake_fe/items/041715068665dc94aac4#comments

- for文の中で処理が一つの時は{ }を省略できる。
- 論理演算子||は、xがtrueの場合は1つ目の値（演算子の左）、falseの場合は2つ目の値を返す（演算子の右）
- for文の条件処理順。for文の条件の中でconsole.logの中で条件を書くとは思わなかった・・・

## 答えを見て改善したこと
特になし
EC2(Amazon Linux 2)でLAMP環境構築

# 1.はじめに
WordPress、Joomla!をインストールする際に使用するLAMP環境をEC2(Amazon Linux 2)で構築します。
インストールするバージョンは下記となります。
```
# php -v
PHP 8.0.20 (cli) (built: Jun 23 2022 20:34:07) ( NTS )

# mysql --version
mysql  Ver 8.0.29 for Linux on x86_64 (MySQL Community Server - GPL)
```

# 2.事前作業
1.root昇格
```
sudo su -
```

2.yumのパッケージをアップデート
```
yum -y update
```

# 3.Apacheインストール

1.Apacheインストール
```
yum -y install httpd
```

2.Apacheのバージョン確認、インストールされている事を確認します。
```
httpd -v
```

3.Apache起動
```
systemctl start httpd
```

# 4.MySqlインストール

1.MySqlのEPELリポジトリを追加
```
yum -y install https://repo.mysql.com/yum/mysql-8.0-community/el/7/x86_64/mysql80-community-release-el7-3.noarch.rpm
```

2.MySqlインストール
```
yum -y install mysql-community-server
```

<details><summary>Public key for mysql-community-icu-data-files-8.0.29-1.el7.x86_64.rpm is not installedエラーが表示された場合</summary>
MySQLのGPGキーの有効期限切れがエラー原因です。

新しいGPGキーをインポートします。

```
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
```

</details>

3.MySqlのバージョン確認、インストールされている事を確認します。
```
mysql --version
```

4.MySql起動
```
systemctl start mysqld
```

# 5.PHPインストール

1.amazon-linux-extrasでphpが管理されているか確認
```
amazon-linux-extras | grep php
```

2.PHPインストール
```
amazon-linux-extras install -y php8.0
```

3.PHPのバージョン確認、インストールされている事を確認します。
```
php -v
```
Fedora36 に VirtualBox-6.1 をインストール

新しいカーネルをインストールすると、VirtualBox が動かなくなることがあります。

VirtualBox のカーネルモジュールのためだと思われますが、私のように常に新しい Fedora を使用していると、Fedora をアップグレードする、あるいは、新しいカーネルをインストールすると VirtualBox をインストールすると困ることになります。

Fedora 36 では、インストールページにあるパッケージではうまく動かないようです。

以下のサイトを確認して、VirtualBox のテストビルドサイトからダウンロードした .run ファイルを実行したところ動きました。

（参考）
 https://ask.fedoraproject.org/t/virtualbox-still-cant-run-in-fedora-36-until-now/23664
【初心者】Hasuraとnextauth.jsを繋げた際の備忘録

# はじめに

皆さんは、Hasuraを使ったことはありますか？

端的に表現すると
<b>「GraphQLのAPIサーバーをDB（Heroku）と連携した状態で、立ててくれる」</b>
というものです。

CLIでいじれたりもするのですが、
僕はブラウザで動かすGUIをいじっております。

ただ、このHasura、かなり厄介な点もあります。
それは、「日本語での学習コンテンツが充実していない」というものです。
そもそもGraphQL自体がかなり新しめのものであるから、仕方ないっちゃ仕方ないですけども。

そんなわけで、個人的にいじったりしていたんですけど、かなり序盤でつまづきました。
どこでつまづいたかというと、「Next.js+Auth0+Hasura」のセットアップチュートリアルです。

https://hasura.io/learn/graphql/nextjs-fullstack-serverless/auth0-setup/2-connect-hasura-auth0/

まさかの超序盤で申し訳なくなりました。
チュートリアルの通りにやっても、エラーを吐き、そのエラーを調べても解決策が見つからず。。。と言った感じでした。

ただおそらくAuth0側のエラーであり、Auth0自体の経験が少ない自分は、他の認証サービス・パッケージを使えばよいのではないかと考え、
「そういやNext.jsに認証パッケージあったな」と思って調べたら、該当するdocsがあったので、それを参考にエントリしました。

https://hasura.io/learn/graphql/hasura-authentication/integrations/nextjs-auth/

# そもそもHasuraって？
Hasuraに関しては先程端的に、
>「GraphQLのAPIサーバーをDB（Heroku）と連携した状態で、立ててくれる」
としましたが、もう少し掘り下げてみましょう。

https://hasura.io/blog/what-is-hasura-ce3b5c6e80e8/

### 1.QueryやMutationを勝手に作ってくれる
テーブルを作成・定義するだけで、CRUDに関するクエリやミューテーションを扱えるAPIを作ってくれます。
ページネーションとかも実装できるらしいですね、すごい、、、
また、subsciptionも作ることができるので、リアルタイム処理が必要なときも助かります。

ちなみにsubscription?ってなった同志の方はこちらをどうぞ。

https://www.slideshare.net/fukuis/graphqlsubscription

### 2.サーバレスなサービスとつなげることができる
AWS lambdaなどのサーバレスFaaSで独自でDB扱うビジネスロジックを書いて、
それをHasuraを通して実行！なんてこともできるそうです。

### 3.認証サービスや既存のデータベースとも連携可能
Auth0,firebaseなどのIDaaSと互換性もあります。
また、既存のPostgresDBなら接続ができるそうです。

いずれの特徴も自分はまだ十分に使えるわけではないので、
今後触れる機会を作っていけるように精進します。

# nextauth.jsって？
名前の通り、Next.jsを用いて認証機能を実現するためのライブラリです。

sessionやJWT認証を用いた機能の実装や、
GithubやGCPなど、様々なログイン機能に対応しています。

個人的にはdocsがかなり充実していると感じるので、結構好きです。

https://next-auth.js.org/

# どうやって実現していくの？
本当にチュートリアルをガン見でできました。
なんならAuth0のdocsより楽だったんじゃ、、、

`@skillrecordings/next-auth-hasura-adapter`というライブラリが、
Hasuraとnextauth.jsをつなげてくれるんですね。

コードをQiitaに書き起こそうかとも思ったのですが、
下手に書く必要性も感じなかったので、こちらを参考にしてください。

https://hasura.io/learn/graphql/hasura-authentication/integrations/nextjs-auth/

余談ですが、開発初心者の自分は、
docsの`Create User Table`内が、いきなり説明もなく出てきて困惑しました。
そんなときは、nextauth.jsのdocsを参考にしましょう。

https://next-auth.js.org/adapters/models

nextauth.jsに準拠したテーブルを作る＋`Hasura Adapter`でエンドポイントを呼び出し操作することで、
Userテーブルなどの操作を実現するんですね。

# おわりに
読んでいただきありがとうございました。

認証で使うライブラリや、JWT認証が個人的に理解が乏しいと感じました。
ただ、これだけははっきりしました。

<font color="Red"><b>Hasura めっちゃ便利。</b></font>
sedでmatchした行を置換/した行の前/後に追加

# 1. マッチした行の後に追加
## 1.1. 文字列を追加

```
sed '/<matchする条件>/a <追加するコンテンツ>' <対象となるファイル>
```

例:

```txt:target.txt
abc
```

```
sed '/^abc$/a def' target.txt
abc
def
```

## 1.2. ファイルの中身を追加

```
sed -i '/<matchする条件>/r <追加するコンテンツの入ったファイル>' <対象となるファイル>
```

[r filename](https://www.gnu.org/software/sed/manual/sed.html#sed-commands-summary)

例:

```txt:target.txt
abc
```

```txt:content_to_add.txt
def
```

```
sed '/^abc$/r content_to_add.txt' target.txt
abc
def
```

# 2. マッチした行の前に追加
## 2.1. 文字列を追加

```
sed '/<matchする条件>/i <追加するコンテンツ>' <対象となるファイル>
```

例:

```txt:target.txt
abc
```

```
sed '/^abc$/i def' target.txt
def
abc
```

## 2.2. ファイルの中身を追加

```
sed -i $'/<matchする条件>/{e cat <追加するコンテンツの入ったファイル>\n}' <対象となるファイル>
```

[e [command]](https://www.gnu.org/software/sed/manual/sed.html#Extended-Commands)

例:

```txt:target.txt
abc
```

```txt:content_to_add.txt
def
```

```
sed $'/^abc$/{e cat content_to_add.txt\n}' target.txt
def
abc
```

# 3. マッチした行をファイルの中身で置換する

## 3.1. マッチ条件が一行の場合

```
sed 's/<matchする条件>/cat <追加するコンテンツの入ったファイル>/e' <対象となるファイル>
```

例:

```txt:target.txt
abc
```

```txt:content_to_add.txt
def
```

```
sed 's/abc/cat content_to_add.txt/e' target.txt
def
```

## 3.2. 複数行マッチさせる場合

```txt:target.txt
func aaa() {
   aaa

}

func bbb() {
   bbb
}
```

```txt:content.txt
func aaa() {
   AAA
}
```



```bash
gsed "/func aaa() {/,/^}/c $(sed 's/$/\\n/' content.txt | tr -d '\n' | sed 's/.\{2\}$//')" target.txt
func aaa() {
   AAA
}

func bbb() {
   bbb
}
```

`sed 's/$/\\n/' content.txt | tr -d '\n'` は複数行あるものを`func aaa() {\n  AAA\n}\n`に変換する役割

# 参考
- https://www.gnu.org/software/sed/manual/sed.html#Extended-Commands
- https://www.gnu.org/software/sed/manual/sed.html#sed-commands-summary
- https://stackoverflow.com/questions/31056599/bash-sed-replace-text-with-file-content
- https://fabianlee.org/2018/10/28/linux-using-sed-to-insert-lines-before-or-after-a-match/
- https://stackoverflow.com/questions/5178828/how-to-replace-all-lines-between-two-points-and-subtitute-it-with-some-text-in-s
Ubuntu 20.04へのDocker Composeのインストール

参考にした記事
1.  [Docker Compose のインストール](https://matsuand.github.io/docs.docker.jp.onthefly/compose/install/)
1.  [Ubuntu 20.04へのDocker Composeのインストールおよび使用方法](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04-ja)

## 結論：2のcomposeのインストール方法をサイトの通りに実施して下記の部分だけに1のバージョンを入れ込む

~~~SHELL
1の方法
 curl -SL https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose

２の方法
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

混ぜた
 sudo curl -L "https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose


~~~
正直１で使用した部分って`v2.4.1`のところだけですが
２の方法で`2.4.1`と打ってもうまくいかなく`v`が必要だったみたい

## おまけ
- unameのコマンドとオプションについて
    - カーネルのバージョンなどの情報を表示する
        - s : カーネル名を表示する（デフォルト）
        - m : ハードウェア名（x86_64など）を表示する
- curlのコマンドとオプションについて
    - HTTPリクエストして標準出力する
    - （だとわかりにくいのでURLにデータ頂戴って言ってもらったデータを-oオプションでファイルに書き出す）
        - o : 取得したデータを指定したファイルFILEに出力する

参考サイト
- [よく使うcurlコマンドのオプション](https://qiita.com/ryuichi1208/items/e4e1b27ff7d54a66dcd9)
- [【 uname 】コマンド――カーネルのバージョンなどの情報を表示する](https://atmarkit.itmedia.co.jp/ait/articles/1901/24/news026.html#opt)

## 終わりに
かえってわかりにくいかもしれない
２の方法で最新のリリースページのバージョンをそのまま書くでもいいかも
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246495/a0c22940-8237-7d52-be6e-11631fa3d8dd.png)
となってるので素直にv2.6.1と入れる
（2.6.1だと通らない）
【Bundler】コマンド一覧

## bundleコマンド一覧
```

bundle init                   Gemfileを生成する

bundle update [パッケージ名]     インストール済みのgemパッケージのバージョンを更新する

bundle install                Gemfile(.lock)にかかれているgemパッケージをインストールする

bundle list                   インストール済みのgemパッケージの一覧表示

bundle exec [コマンド名]         Bundlerでインストールされているgemパッケージを使用してコマンドを実行

bundle config                 Bundlerの設定を表示                   

bundle config [設定] [値]          設定を編集


```
2022/7/19主にITとかセキュリティの記事

なりすましフィッシングメール対策「送信ドメイン認証」、どれを導入すべき？(7/17)
https://news.mynavi.jp/techplus/article/20220717-2400268/

北朝鮮のサイバー攻撃者が世界の中小企業狙うランサムウェア攻撃観測、要注意(7/17)
https://news.mynavi.jp/techplus/article/20220717-2400450/

個人開発(1人システム)担当者がサイバー攻撃に備える7つの心がけ(7/15)
https://qiita.com/Tyamamoto1007/items/fc06004938cc1e761d96

中国、約10億人の個人情報流出を調査(7/16)
https://jp.sputniknews.com/20220716/10-12022914.html

中国や北朝鮮が支援するサイバー攻撃者、ジャーナリストやメディアを標的に(7/17)
https://news.mynavi.jp/techplus/article/20220717-2400446/

古くなるソフトウェアと、人間の心(7/17)
https://www.orangeitems.com/entry/2022/07/17/070000

Microsoft、2024年にWindows 12をリリースか(7/17)
https://www.zaikei.co.jp/article/20220717/681425.html
React の ref, useRef, forwardRefの基本的な知識

## はじめに

あやふやな理解だったので、勉強がてらのメモです。

## refとは

refはコンポーネントの描画結果であるDOMノードへの参照を保持するオブジェクトです。

refを使うには、Reactの提供するHooksであるuseRefを関数コンポーネント内で呼ぶ必要があります。

refオブジェクトはcurrentというプロパティを持っています。useRefに渡した引数がcurrentプロパティの初期値になります。引数を渡さなかった場合の初期値はundefinedです。

currentは、自由に書き換え可能です（ミュータブル）。また、変更しても再レンダリングされません。この点（ミュータブルな値を抱えること）は、Reactの思想（宣言的UI）と違ってしまうと感じます。公式見解も「Don’t Overuse Refs」（使いすぎないでください）とあります。

https://ja.reactjs.org/docs/refs-and-the-dom.html#dont-overuse-refs

しかし、アクセシビリティの向上を実現する手段としてのユースケースはあるので、使い所だなと感じました。

https://ja.reactjs.org/docs/accessibility.html#programmatically-managing-focus

### ユースケース

仕事で実際に使用したのは、オートフォーカスくらいです。他にもいくつかあるみたいです。[^1]

[^1]: ユースケースを見ると、アニメーションの発火にも利用されるけど、具体的な書き方がわからなかったので教えて欲しい。:pray_tone2:

https://ja.reactjs.org/docs/refs-and-the-dom.html#when-to-use-refs

## forwardRefとは

forwardRefはコンポーネント内のDOMにRefオブジェクトを渡すための機能のことです。

refは特殊な属性らしく、propsとして渡したり、受け取ったりができません。

そもそも関数コンポーネントにrefを渡すことはできません。

https://ja.reactjs.org/docs/refs-and-the-dom.html#refs-and-function-components

そこで、forwardRefの登場です。forwardRefを用いれば、関数コンポーネントに対して ref が使えるようになります。

### 例

子コンポーネント（CustomInput）のテキストインプットを外からフォーカスできるようにしたい場合。

```jsx:App.jsx
import React, { useRef, forwardRef } from "react";

const CustomInput = (props, ref) => {
  return <input type="text" {...props} ref={ref} />;
};

const WrappedCustomInput = forwardRef(CustomInput);

export const App = () => {
  const ref = useRef();

  const onClick = () => {
    ref.current.focus();
  };

  return (
    <>
      <WrappedCustomInput ref={ref} />
      <button type="button" onClick={onClick}>
        focus
      </button>
    </>
  );
};
```

関数コンポーネントに対してrefを使う場合、fowardRefでコンポーネントをラップすることでコンポーネント内のDOMにrefを渡すことができました。

![9cf63ca000afbad6110bd36a1d417c1a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/20ffdab2-9388-35ed-2d57-a5d816dd3776.gif)

公式はあまり推奨していなさそうだけど、アクセシビリティの手段や、いざという時のための手段として覚えておきます。

## 参考

https://ja.reactjs.org/docs/refs-and-the-dom.html

https://qiita.com/chelproc/items/de83a6f2959490109b49
KotlinでBMIを計算してみた

# １　はじめに

Kotlinの操作に未だ慣れていませんが、簡単なBMI計算機を作成してみました。

# ２　BMIとは
BMI（Body Mass Index）はボディマス指数と呼ばれ、体重と身長から算出される肥満度を表す体格指数です。
健康の指標にも使われているのだそうです。
BMIが高すぎるのも健康によくありませんね。

# ３　計算式と判定基準

BMI ＝ 体重kg ÷ (身長m)2


|  BMI|  判定基準|
|:--|:--|
| 16未満 | 痩せすぎ |
| 16.00〜16.99以下 |  痩せ|
| 17.00〜18.49以下 | 痩せぎみ |
|18.50〜24.99以下  | 普通体重 |
| 25.00〜29.99以下 |  前肥満|
| 30.00〜34.99以下 | 肥満(1度) |
| 35.00〜39.99以下 | 肥満(2度) |
| 40.00以上 | 肥満(3度) |

https://www.e-healthnet.mhlw.go.jp/information/dictionary/metabolic/ym-002.html

# ４　コードを書く

```bmi.kt
import kotlin.math.*

fun main(){
    val weight = readLine()!!.toInt()
    val height = readLine()!!.toDouble()
    val bmi = (weight/((height/100).pow(2))) //分母のべき乗
    println(bmi)
//bmiの判定
    if(bmi<16){
        println("痩せすぎ")
    }else if(bmi <= 25){
        println("普通")
    }else{
        println("肥満")
    }
}
```

```
$kotlinc bmi.kt -include-runtime -d bmi.jar
```
```
$java -jar bmi.jar

```
### 出力結果

```
65
184
普通
```
# ５　コードを書いて分かったこと

まず、初めにkotlinで割り算(/)を行う場合、2つの数値のうちどちらかをDoubleで指定する。
次にkotlinでは、べき乗はそのまま**を使用できないのです。
なので、最初にjavaのmathモジュールをインポートしてから計算ができるようになるそうです。
jsからaxiosを用いて画像データを送ってFlaskで受け取ろうとしたら「400 BAD REQUEST」が出た話

# ざっくりまとめ
##### jsからaxiosを用いたPOSTリクエストでBASE64形式の画像データを'multipart/form-data'として送ってFlaskで受け取ろうとしました。
##### しかし、 400 BAD REQUESTが出ました。
##### 「BASE64をバイナリ形式経由でfile形式にすること」と「送るデータのnameと受け取るデータのnameを一致させること」をして解決しました。

# 目次
0. はじめに
1. やろうとしたこと
2. コード
3. 今回詰まったエラー
4. 思考
5. 参考にさせていただいたサイト


# 1. はじめに
エラーで詰まったときは備忘録として記事に残しておこう、ということで第一弾です(第一弾で終わりそう。。。)。

先日、ハッカソンに参加してきまして、今回はその時に詰まったエラーについて書いていきます。
(ちなみに今回jsとかaxiosとかNext.jsとか諸々初めて触れたので、内容に間違いがあったら優しく教えて欲しいです。)

先に結論を言ってしまうと、簡単なミスでした()


# 2. やろうとしたこと
フロントエンド：Next.js
バックエンド：Flask(Herokuを用いてデプロイ)

BASE64形式の画像データをファイル形式でaxiosを用いてPOSTで送って、Flaskで受け取る。

# 3. コード

js側
```javascript
const image = BASE64形式の画像データ
const data = new FormData();
data.append('file', image);
const postImageUri = 'ポスト先のURL'
axios({
  method: "POST",
  url: postImageUri,
  data: data,
  headers: {"Content-Type": "multipart/form-data", "Access-Control-Allow-Origin": "*"},
})
.then(res => {
      
})
.catch(err => {
  
})
      

```

flask側
```python
@app.route("/analyze", methods=["POST"])
def analyze():
    request_image = request.files['image_file']
    ...
    
    return 
```

# 4. 今回詰まったエラー

```
POST (URL) 400 (BAD REQUEST)
```

これだけ。。。。。。
コンソールのエラーの詳細を見てもエラーの詳細はなく、Herokuのログを見てもそれらしいものもない。。。

ここまで長かったですが、今回はこのどこでエラーを吐いてんのか分からんエラーをなんとかするという話です。


# 5. 思考
まず知識が浅いこともあり、エラーと相対して、
「400 BAD REQUEST！？。。。ってなんだ。。？」
となってみたので、少し調べてみました(参考文献1)。

それによると、リクエストが悪いぞ！とのこと

という訳で、画像データがファイル形式になっていないのでは？と考え、さらに色々と調べました。

その結果、BASE64形式をバイナリ形式経由でfile形式に変換することで解決しました(方法については参考文献2に記載されているものを使用させていただきました)。

その結果がこちら
```
POST (URL) 400 (BAD REQUEST)
```

解決してないやーん
前進した気はするのですが。。。
と、ここでまたすごい時間詰まってしまいました。。。


結局、原因は基礎的なとこにありました。
まず、Flask側が悪かったことが判明しました。
Flaskでは、データを
```python
request.files['image_file']
```
で受け取ろうとしていたのですが、通常この'image_file'という部分はリクエストする側のhtml内のinputのnameの値と一致している必要があります。
今回の場合では、FormDataに追加するところ
```javascript
data.append('file', image); // ココダヨ
```
の'file'と一致している必要がありました。(灯台下暗し)

という訳で最初のjs側のコードに最初のエラー解決法を加え、'file'を'image_file'に変更することでうまくいきました！

# 6. 参考にさせていただいたサイト
0. 「400 Bad Request」エラーの解決方法（原因と対策) (https://kinsta.com/jp/knowledgebase/400-bad-request/ )

1. Base64形式のデータをFileオブジェクトに変換する (https://gray-code.com/javascript/convert-base64-format-data-to-file-object/ )
WordpressでテーマをMySQLから変更（焦るな）

いやー焦った焦った。
テーマ変更したらいきなりWordpressお馴染みのエラーがwp_adminやそれ以外の全ての画面で表示されたからビビった。
Mysql上でデフォルトテーマを変更する方法です。

```sql
UPDATE wp_options SET option_value = 'twentySeventeen' WHERE option_name = 'stylesheet';
UPDATE wp_options SET option_value = 'twentySeventeen' WHERE option_name = 'template';
```

テーマ情報などはwp_optionテーブルに保管されており、それらの「stylesheet」と「template」の値をテーマフォルダ名に変更するだけで完了します。IDで指定してもいいですが、環境によってことなるのでID指定の場合は事前にチェックして置きましょう。

```sql
SELECT * FROM ap_options;
```
kindle本セールの開催情報を、出版社くくりではなく一冊ごとにリマインダー通知を受け取りたくて作った

kindle本セールの開催情報を、出版社くくりではなく一冊ごとにリマインダー通知を受け取りたくて作ったのが、この
<a href="https://figreen.org/it/%e3%81%84%e3%81%a4%e6%9d%a5%e3%82%8b%e3%81%ae%e3%81%8b%e5%88%86%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84amazon-kindle%e3%82%bb%e3%83%bc%e3%83%ab%e3%82%92%e3%80%81%e6%a4%9c%e7%b4%a2%e3%81%97%e3%81%a6/" target="_blank">kindleセールチェッカー</a>というスクリプトです。

出版社のセール情報だと、欲しいと思っていた本がセール対象になっているのか、いちいちAmazonトップから検索をかけないとなりませんでした。

それが面倒くさかったので、キャンペーン情報をページ内からスクレイピングするファイルを作りました。
Cloud9で開発したLaravelプロジェクトを、ローカルで動かそうとした時につまった話

# はじめに
大学講義の最終課題で、Laravelを使用したWebアプリケーションを作成した。
参考にした書籍に従って、AWSのCloud９を使って開発を行なったが、教授に提出する際のデバッグのことを考え、ローカルで動くように改修しようとした際つまったことを記述する。

# 問題点
Cloud９で開発していた際にはhttpsでの接続がされていたが、localhostではhttpでの接続をしなければならなかったために、php artisan serve --port=8080　をコマンドで入力してから接続すると、
```
Invalid request (Unsupported SSL request)
```
がコマンドラインに表示され、接続ができなかった。
# 解決策
/routes/web.php に
```php
URL::forceScheme('http');
```
を追記したところ、httpsがhttpに問題無く変わった。
Flutter: database is locked Possibly there are two concurrent builds running in the same filesystem location

Flutterのアプリを実行した際
~~~
Flutter: database is locked Possibly there are two concurrent builds running in the same filesystem location
~~~
このようなエラーが発生

調べてみるとM1　Mac bookで同じエラーに遭遇した人がいたのでそれを参考にしました
参考文献：https://stackoverflow.com/questions/71606334/flutter-database-is-locked-possibly-there-are-two-concurrent-builds-running-in

手順１:iosディレクトリにあるPodfile.lockを削除する

手順２:プロジェクトディレクトリにて以下コマンドを実行
~~~ 
$sudo arch -x86_64 gem install ffi 
~~~ 

手順３:
~~~ 
$cd ios 
~~~

手順４:
~~~ 
$arch -x84_64 pod install 
~~~

ぜひ試してみて下さい。
SSH接続のための設定まとめ

# はじめに
備忘録
SSHでのサーバー接続のために必要な設定をまとめました。
|            | OS             | SHELL | REMARKS  |
|:----------:|:--------------:|:-----:|:--------:|
| **CLIENT** | macOS Monterey | zsh   | `%`で表記 |
| **SERVER** | Ubuntu 20.04    | bash  | `$`で表記 |
どなたかのお役に立てれば幸いです。
# サーバーでの事前準備
SSHのためにはサーバーをSSH接続に対応させる必要があります。
以下では、そのための事前準備の方法を紹介します。
## openssh-serverのインストール
サーバー側（今回はUbuntu）に`openssh-server`をインストールします。
```bash
$ sudo apt install openssh-server
```
:::note warn
`openssh-server`が入っていないとSSHできないので、初めに必ずインストールしましょう。
インストールすることで`ssh`のデーモンさん（`sshd`）が働き始めます。
:::
## SSHのステータスを確認
以下のコマンドで確認できます。
```bash
$ sudo systemctl status ssh
```
サービスが`active`になっていればOKです。
```bash
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
   Active: active (running)　・・・ ＜＝　　ここです
　　　　　　　　　　　　　　              :
```
## サービスが実行されていない場合
以下のコマンドで実行できます。
```bash
$ sudo systemctl enable ssh
$ sudo systemctl start ssh
```
## その他
SSHを停止する
```bash
$ sudo systemctl stop ssh
```
SSHを無効にする
```bash
$ sudo systemctl disable ssh
```
# 鍵の生成〜登録〜接続
これまでの設定でSSHのための事前準備が整いました。
以下では
+ [クライアント側での鍵ペア（公開鍵＆秘密鍵）の生成方法](#鍵を生成する)
+ [サーバーへの公開鍵の登録方法](#サーバーに鍵をコピー)
+ [SSHでの接続方法](#サーバーにSSH接続する)
を紹介します。
## 鍵を生成する
SSHに必要な鍵ペア（秘密鍵と公開鍵）は以下のコマンドで生成できます。
```zsh
% ssh-keygen
```
`-t`を利用することで暗号の種類を指定することができます。
```zsh
% ssh-keygen -t rsa
% ssh-keygen -t ecdsa
% ssh-keygen -t ed25519
```
`-b`を利用することで鍵長を指定することができます。
```zsh
% ssh-keygen -t rsa -b 4096
% ssh-keygen -t ecdsa -b 384
```
:::note
`rsa`と`ecdsa`は鍵長を指定できます。
`ed25519`は`256bit`固定のようです。
:::
`-C`を利用することで公開鍵の後ろにコメントをすることができます。
```zsh
% ssh-keygen -t ed25519 -C ""
```
:::note
コメントの有無は認証には関係ありません。
`-C`なしで鍵を生成すると`username@hostname`がコメントに設定されるようです。
プライバシーが気になる人は`""`でコメントをブランクにしても良いかもしれません。
逆に大人数で管理する等の都合でたくさんの公開鍵を管理するサーバーであればコメント有りの方が誰の鍵かわかって良いかも？
:::
`ssh-keygen`を実行すると以下の文章が表示されます。
```zsh
Enter file in which to save the key (/username/.ssh/id_ed25519):
Created directory '/username/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```
`1行目`：鍵ファイルの名前や作成場所を変える場合は入力します
`2行目`：ディレクトリがなければ自動的に作られます
`3, 4行目`：パスフレーズを設定する場合は入力します
:::note
パスフレーズを設定することで安全性を高めることができますが、SSHするたびにパスフレーズを入力しなければいけません。
秘密鍵が安全に管理されており、パスフレーズの入力が面倒であれば、パスフレーズの設定は見送ってもいいかもしれません。
:::
パスフレーズは後から変更することもできます。
```zsh
% ssh-keygen -p -f ~/.ssh/id_ed25519
```
## サーバーに鍵をコピー
`ssh-copy-id`コマンドは以下のように書くことができます。
```zsh
% ssh-copy-id ユーザー名@サーバーのipアドレス
```
## サーバー側で鍵が書き込まれていることを確認
`less`コマンドをつかってファイルの中身を見ます。
```zsh
$ less ~/.ssh/authorized_keys
```
閲覧を終了するには、`esc`を押してから`:q`と入力して`Enter`を押します。
## サーバーにSSH接続する
`ssh`コマンドは以下のように書くことができます。
```zsh
% ssh -i 秘密鍵へのパス ユーザー名@サーバーのipアドレス
```
`id_ed25519`を使う場合は以下のようになります。
```zsh
% ssh -i ~/.ssh/id_ed25519 user_name@xxx.xxx.xxx.xxx
```
:::note warn
パスフレーズを設定した場合は、`ssh`コマンドを実行すると秘密鍵のパスワード入力が求められます。
:::
## SSH接続を切断する
`exit`コマンドで切断できます。
```zsh
ユーザー名@ホスト名:~$　exit
```
# SSHできないとき（UFWの設定方法）
ファイアウォールによってSSH接続が拒否されているかもしれません。
Ubuntuでは、UFWを設定することでアクセスを制限することができます。
SSHは`22`番ポートに設定されていることが多いので、ファイアウォールの設定を確かめてみてください。
また、適切に設定することでサーバーの安全性を高めることができるので、余裕がある人は試してみてください。
https://qiita.com/010Ri/items/f37f7f5fb35265823c7c
# ブログもあります
https://kyit.net/how-to-make-ssh/
仮想通貨 ブロックチェーン　入門 その1

## まずは通貨について考えてみる
通貨のない世界でモノを手に入れるために機能するシステムは交換です。この交換システムの欠点は調整です。当事者同士でお互いが必要としているものを偶然持っていればニーズは満たされますがその限りではありません。ではこの問題を解決するために、信用と現金の二つのシステムが生まれました。
### 信用ベースのシステムと現金ベースのシステム
**信用ベースのシステム**は取引の段階で互いに必要なものが揃っていなくても、AさんがBさんにモノを与えへ貸しを作りBさんにその貸しを返してもらえばよいはずです。言い換えれば、BさんはAさんのほしいモノを手に入れ借りを返さなければいけません。
**現金ベースのシステム**はモノを売り現金を得て、得た現金でモノを買えば、個々の取引相手の買い手が現金を持っている限り、取引はどの順序で発生しても問題ありません。
２つのシステムについて考えると信用ベースのシステムは現金を分配するというブートストラップは不要だが、貸しを作った相手がリスクを引き受けます。一方、現金ベースのシステムでは、現金分配のブートストラップは必要だが、モノの価値を数値で正確に表現できます。

## クレジットカード　信用問題
Webでよく使用されている決済方法はクレジットカード取引です。クレカ情報を入力して、オンラインショップに送るとオンラインショップ（販売業者）は、クレカ会社やその他仲介業者とやり取りを行います。販売業者にクレカ情報を渡しているのでセキュリティリスクになりえます。
paypalのような決済方法を利用すると、販売事業者と購入者の間に仲介企業が入る構造なので、販売事業者に直接クレカ情報を渡さなくてよいはずです。
しかしながら、現在では大半の人はクレカの情報を与えることも購入情報を集めてアクティビティを眺めている企業がいることにも慣れているはずです。
つい20年ぐらい前は、オンラインベンダーにクレカ情報を渡すことを躊躇していたはずです。評価のよくわからにオンラインベンダーにわたすなんて正気の沙汰ではなかったはずです。
だからこそ、当時仲介構造に関心が集まることになりました。

## 最初の仲介業者
1994年にFirstVirtualという会社が設立されました。この会社が提案したシステムは、まず、利用者はFirstVertualに利用者登録を行い、クレジットカード情報を渡します。利用者が何かオンラインで購入したい場合、販売事業者はFirstVertualに支払い情報を渡し、FirstVertualは利用者(購入者)にその支払いの確認を取り、使用者が承認すればクレジットカードに請求が回ります。当時HTTPSの暗号化プロトコルが出始めたばかりだったこともあり、このやり取りはすべて電子メールで行っていました。

## 仲介構造の新しいアプローチ SET
SETはFirstVirtualのシステムのように販売業者にクレカ情報を送らず、さらに、仲介業者に利用登録もしません。これはクレカ情報と取引情報を暗号化し、仲介事業者だけが複合化できるようにしたためです。また、販売事業者は送られてきた暗号化された情報には手をつけず、この情報に新たに取引情報を付与して仲介業者に転送します。仲介業者は、利用者と販売業者の取引情報が一致した場合のみ取引を成立させます。

## SETがうまく機能しなかった理由
取引の暗号化のために証明書の取得を販売事業者のみならず、利用者全員が取得しなければいけなかったためです。

## 現金の匿名性
現金の利点の一つは、匿名性の高さです。クレカは利用者名義で発行されるので、銀行は支出を全て追跡できます。現金の支払いは銀行の出番はなく、販売業者側もあなたがだれか知る必要はありません。販売業者はポイントカードを提示させて特定しようとしてるけど、現金のみであれば追跡不可能です。

ビットコインはオンラインで買い物もでき、現金程ではないが匿名性も高いです。


[仮想通貨 ブロックチェーン　入門 その2](https://qiita.com/sharpman/items/0d0c0e9513b9c4ed5ce2)
tkinter でドラッグアンドドロップ!


# ファイルをドラッグアンドドロップするだけで結果が見えるプログラムを作りたい!

ファイルを加工したいとき、ファイルを分析したいとき、投げ込むだけで動作する方が効率的だと思ったのでまずは雛形を作ってみました!


## 実行環境

- OS
    - Windows 10
- python 
    -  3.9.13
        -  tkinter
        -  [tkinterDnD2](https://github.com/Eliav2/tkinterdnd2)

## 環境作成

Miniconda(Anaconda) を使って環境作成を行いました。
pip で tkinterdnd2 をインストールしています。

```sh
conda create -n dev39 python=3.9 pyinstaller
conda activate dev39
pip install tkinterdnd2
```

## コード

以下に、作成したコードを記載します。
実行と加工は自己責任でお願いします。

```python
import tkinter as tk
from tkinterdnd2 import DND_FILES, TkinterDnD

class MyApp(TkinterDnD.Tk):
    def __init__(self):
        super().__init__()

        ## ウィンドウサイズ
        width = 300
        height = 100
        self.geometry(f'{width}x{height}')
        self.minsize(width, height)
        self.maxsize(width, height)
        self.title(f'DnD')

        ## フレーム
        self.frame_drag_drop = frameDragAndDrop(self)

        ## 配置
        self.frame_drag_drop.grid(column=0, row=0, padx=5, pady=5, sticky=(tk.E, tk.W, tk.S, tk.N))
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)


class frameDragAndDrop(tk.LabelFrame):
    def __init__(self, parent):
        super().__init__(parent)
        self.textbox = tk.Text(self)
        self.textbox.insert(0.0, "Drag and Drop")
        self.textbox.configure(state='disabled')

        ## ドラッグアンドドロップ
        self.textbox.drop_target_register(DND_FILES)
        self.textbox.dnd_bind('<<Drop>>', self.funcDragAndDrop)

        ## スクロールバー設定
        self.scrollbar = tk.Scrollbar(self, orient=tk.VERTICAL, command=self.textbox.yview)
        self.textbox['yscrollcommand'] = self.scrollbar.set

        ## 配置
        self.textbox.grid(column=0, row=0, sticky=(tk.E, tk.W, tk.S, tk.N))
        self.scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

    def funcDragAndDrop(self, e):
        ## ここを編集してください
        message = '\n' + e.data

        self.textbox.configure(state='normal')
        self.textbox.insert(tk.END, message)
        self.textbox.configure(state='disabled')

        self.textbox.see(tk.END)


if __name__ == "__main__":
    app = MyApp()
    app.mainloop()

```

## 実行結果

ファイルを投入すると、ファイル名を取得して textbox へ追加します。
そのため、`funcDragAndDrop` を編集すれば、ファイルを投入すると必要な結果が帰ってくるアプリケーションになる...はずです。

![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174323/91b125de-9f21-7fb2-c4c4-1269d924489c.png)


## exe 化

pyinstaller を使って exe 化も試してみました。
`--collect-data` がないと tkinterdnd2 がパッケージングされないのかエラーが表示されてしまいました。

```
pyinstaller tksample.py --onefile --noconsole --collect-data tkinterdnd2
```
旧型アーケードスティックのレストア

# できたもの

**古いアーケードスティック（PS1/2用，HORI RAP2）をUSB接続型に改造しました．** Steamでも利用できました（本体にのっているのは不要になったPS1/2用ケーブル）．

<img width="640" alt="RAP2 after" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156705/2c40094b-d9e6-a3f8-3e77-671e503871fc.jpeg">

# きっかけ

長らく使っているアーケードスティックの調子が悪くなってきていました．

モノは１０年くらい前，ゲームセンターで出会った友人（SF4ではフォルテというキャラを使っている人だった）に，1000円で譲ってもらった **Playstation1/2向けの製品（RAP2）です．** PCで使用するため PS1/2 to USB 変換コネクタを併用していましたが，時々"過電流エラー"なるものが出力される有様でした．

これを改造し，**外装だけそのまま＆電装部分だけUSBにいれかえ**ることにしました．

<img width="480" alt="変換コネクタ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156705/7797c0d9-726a-3de9-8edd-9e5f640303ca.jpeg">

※エラーの原因だったであろうPS1/2 to USB 変換コネクタ

# 必要な部品

- [ADRVMICR2 REVIVE USB †MICRO](https://bit-trade-one.co.jp/adrvmic/) x 1
- ピンヘッダ（2.54mmピッチ） x 40（多めに用意）
- ケーブル用コネクタ（QIコネクタ） x 30（多めに用意）
- 収縮チューブ 
- ユニバーサル基板

# 改造手順

1. 本体開く＆旧基板取り外し
1. REVIVE USB 取り付け
1. ケーブル加工
1. 組付け

### 1.本体開く＆旧基板取り外し

まずは本体を開け旧基板を取り出します．筐体は古びているものの，スティックとボタンはまだ十分つかえそうでした．ケーブル（全部で25本）は基板側で切断しました．

<img width="640" alt="旧基板取り出し" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156705/559e5ac1-656b-7e06-21d4-60afe2b81fcd.png">

### 2.REVIVE USB 取り付け

Revive USB はゲームパッド制作用のチップです．チップ上の

- ボタン接続ピン
- GNDピン

間を通電すると「ボタンを押した」という情報がPCに送られます．チップのボタン接続ピンとピンヘッダを，チップのGNDピンと基板上のGND線をそれぞれはんだ付けしておきました（裏面ではんだづけ）．

<img width="640" alt="基板取り付け" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156705/9cef706f-6c17-f30e-8197-673ba1b6f3a8.png">

### 3.ケーブル加工

次にスティック・ボタンから伸びているケーブルの加工をおこないました．①各ケーブルの先にコネクタ接続，②収縮チューブでカバー．コネクタ圧着には所持していた専用工具を使いました（頑張ればラジオペンチでもいけると思います）．

<img width="640" alt="配線加工" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156705/8d01ebfe-5357-7c2d-099e-25c2d96e7da9.png">

### 4.組付け

各ボタンごとに1本をボタン接続ピンに，もう一本をGND線に接続します．収縮チューブが緩衝材になり，差し込むだけで結構しっかり固定されました．残念ながら Revive USB には12本しか接続できないので，"L2", "Select" をあきらめました．正直ここは16ボタンくらいまで対応してほしいものです．．．ユニバーサル基板は筐体底面に両面テープで固定しました．

<img width="640" alt="変換コネクタ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156705/cd5b4a1e-c93e-7b15-e113-021c08917bd6.png">

こののちUSBケーブルをPC（Windows10）に接続し，[Revive USB 付属の設定ツールでチップの設定をおこなう](https://bit-trade-one.github.io/ADRVMICR2-REVIVE-USB-Micro-Rev2/Rev2.html)ことで，無事アーケードスティックとして認識されました．

# Steamで使うには工夫が必要

結論から言うと，**接続するだけだと不具合が出たため，[x360ce](https://github.com/x360ce/x360ce)を併用する必要がありました**．

機器自体はPC接続するだけで認識されましたが，Steam上で動きを確認するとなぜかスティックが右下に入りっぱなしになってしまいました（一方，[HTML5 Gamepad Test](https://greggman.github.io/html5-gamepad-test/)で確認すると正常）．

Rrevive USB の F/W のなにかが関係しているのかもしれませんが，理由はよくわかりませんでした．

# まとめ

これで StreetFigher6 まで闘えます（多分）．押入れで眠っている旧型アーケードスティックスティックがある方，週末電子工作のテーマにどうでしょうか．
remote.itで複数デバイス一括更新！

# remote.itってなに？
これは、「めっちゃ簡単にセキュリティの高いネットワークが構築できる」という代物。

何がどう簡単かというと、
- 端末にグローバルIPアドレスが不要
- ポートオープンも不要

これは結構すごいんじゃないか・・・？！

複数デバイスを管理しようとした場合、普通はその端末にアクセスできるようにIP振ったりポート開けたり設定が必要で、
しかもセキュリティもしっかりしようと思ったら自力で構築するのは中々たいへん。

それをさくっと構築できるのであれば、色々活用できそう！

![](https://amnimo.com/column/020/sub-img01.png)

# 構築はかんたん？
アプリを入れるのは説明不要なくらいとってもかんたん！
ダウンロードしてアカウント作成すればOK！

## CLI(Mac)インストール時にちょっと困った点
### ダウンロードされるのはインストーラじゃなく実行用スクリプト
`remoteit.x86_64-osx` というファイルがダウンロードされる。
はじめこいつをクリックして起動しようとしたら、
![](https://i.gyazo.com/c767a44b8c7cedd0fec6fb5e8aa411dd.png)
が出てくる。
インストーラじゃなくて実行用スクリプトだからねｗ

で、[Installationのページ](https://docs.remote.it/software/cli/overview)を見て、
```
# ファイル名変更
mv ~/Download/remoteit.x86_64-osx /usr/local/bin/remoteit
# 実行権限付与
sudo chmod +x /usr/local/bin/remoteit
# 実行
remoteit
```
とすると、
![](https://i.gyazo.com/372a8706d8561a9a103452598c89e86a.png)
が出てきた。
これを解決するには、スクリプトファイルを右クリックー＞開く　で、
![](https://i.gyazo.com/9318e0b38d752a8991f9f4961a7670a9.png)
が出てくるので、「開く」を押すと、次からはCLIでも普通に実行できるようになる。

# 具体的なユースケースは？
## 複数デバイス一括更新！
複数拠点に同様の端末を配備していて、月末にホスト端末にデータを送信するバッチスクリプトをcronで設定していたとする。
仕様変更でバッチスクリプトの実行を月末から半月に一回に変更になりました。

そんな時の更新処理はremote.itにおまかせ！
cron設定を書き換えるスクリプトを用意して、 bulk scriptを実行！
全端末を一括で変更できます！

（全端末でgit pullするコマンドとかでもいいかも）

### 方法
#### 1. スクリプトのアップロード
![](https://i.gyazo.com/edba1831148fe46c9c132a77b7427f7b.png)
https://legacy.app.remote.it/
が開く。
![](https://support.remote.it/hc/article_attachments/360069999071/wp_21.png)
![](https://i.gyazo.com/1f58d1d77085639c64c3c2414e2cd060.png)
![](https://support.remote.it/hc/article_attachments/360069999091/wp_23.png)
[Scripting]のページからスクリプトをupdloadする。

#### 2. スクリプトを実行する
![](https://support.remote.it/hc/article_attachments/360069778532/wp_25.png)
[デバイス]のページから対象のデバイスを選ぶ。
![](https://support.remote.it/hc/article_attachments/360069999311/wp_26.png)
「アクション」メニューで、「Execute Script」を選択する。
![](https://i.gyazo.com/c990edb08c8a24118662c8fa40638651.png)
実行したいスクリプトを選んで・・・
![](https://i.gyazo.com/c293d052214e442e854c160598e7c615.png)
実行！！
![](https://i.gyazo.com/0b335c2bee2dc4ab5bce249076c523e4.png)
[Scripting]ページで状況を確認できます。

# 気になった点
## 操作用のアプリに関して
2022/07/18現在において操作用のアプリは、
- デスクトップアプリ
- https://app.remote.it
- https://legacy.app.remote.it

があるみたい。
デスクトップアプリと`app.remote.it`はほぼ同等で最新版。
`legacy.app.remote.it` は古いけど、まだ最新版に全ての機能を移植しきれていないよう
バルクスクリプトはめっちゃ使えそうなので早く移植完了してくれる事に期待！

## Bulk Executionのモーダルの真っ赤なアラートが怖いｗ
なにか設定が足りなかったか、真っ赤なアラートが。。。
Submit自体はできたが、Runningが終わらないので何か権限が足りていなそう。

ちなみにジョブが失敗したらこんなメールが届きます。
![](https://i.gyazo.com/e2d80516ef1f870bc854919e354fa5a7.png)
ちゃんと日本語化されててすごい。

# Refs
- [バルクスクリプトのドキュメント](https://support.remote.it/hc/en-us/articles/360049187631-Bulk-Scripting)
- [remote.it価格表](https://ja.remote.it/pricing)
- [remote.it CLI Installation](https://docs.remote.it/software/cli/overview)
秘密鍵を使ってサーバーにSFTP接続してファイルやフォルダをアップロードする方法

## はじめに
備忘録
タイトルの通りです。
FileZillaやCyberduckのようなFTPソフトを使わず、sftpコマンドを利用して接続する方法です。
実行環境はmacOSのターミナル（zsh）です。
どなたかのお役に立てれば幸いです。
## サーバーにSFTP接続する
sftpコマンドは以下のように書くことができます。
```zsh
% sftp -i 秘密鍵へのパス ユーザー名@サーバーのipアドレス
```
id_ed25519を使う場合は以下のようになります。
```zsh
% sftp -i ~/.ssh/id_ed25519 user_name@xxx.xxx.xxx.xxx
```
:::note warn
sftpコマンドを実行すると秘密鍵のパスワード入力が求められます。
:::
## ファイルをアップロードする
ファイルをアップロードするためには、SFTP接続した状態でputコマンドを利用します。
```zsh
sftp> put ファイル名
```
ファイル名にはパスを指定します。
ターミナルにファイルをドラッグ&ドロップすることで自動的にパスが入力されます。
```zsh
sftp> put /Users/user_name/Documents/index.html
```
:::note warn
pwdコマンドを使い、ターミナルでパスを確認することもできます。
:::
## フォルダをアップロードする
フォルダをアップロードするためには、-rという引数を利用します。
```zsh
sftp> put -r フォルダ名
```
書類フォルダの中のhtmlフォルダをアップロードするためには以下のように書きます。
```zsh
sftp> put -r /Users/user_name/Documents/html
```
## SFTP接続を切断する
exitコマンドで切断できます。
```zsh
sftp> exit
```
# ブログもあります
https://kyit.net/how-to-make-sftp/
風変わりなデバイスでも表示崩れが起きてないか確認したい→Remote TestKitが便利そう

## この記事の概要

たくさんの端末で表示検証をしたい、けどたくさん購入して管理するのは大変。
果たしてどうしたものか……と思っていたら、Remote TestKitが便利そうだったので記事にしました。

Qiita Engineer Festa 2022の「Remote TestKitを使ってレビューを書こう！」への投稿用記事です。

https://qiita.com/official-events/f0e8b25feb05af6326b3

## 今回検証する端末

物理的に非常に小さいRakuten Miniと、折りたたみ機構があるGalaxy Foldです。
発表された当初から、これらのデバイスでサイトを表示しても問題ないだろうか……とやや不安でした。

## 端末の借り方

:::note
ソフトウェア版とWeb版がありますが、今回はソフトウェア版で記載します。
:::

Remote TestKitを起動後、検索窓にキーワードを入れます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/ba62160e-506e-7dc9-6db2-20be86225f52.png)

同じ端末でもキャリア別に用意されていました。
今回は使いませんでしたがキャリアによって挙動が怪しい……みたいな場面があれば助かる機能だと思います。

注意というほどではありませんが、曖昧な検索には対応していないようです。
`Galaxy Fold`と打ち込んだ際は候補が出ませんでした。
正しくは`Galaxy Z Fold`だったため、`Galaxy`や`Fold`での検索なら表示されます。

| `Galaxy Fold`で検索 | `Fold`で検索 |
| --- | --- |
| ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/f504208c-24e9-6f38-c4c7-316db57db51d.png) | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/23c3302e-dbe0-687d-c84f-eb1a2d536c14.png) |

レンタルしたい端末を選んだら、ウィンドウ右下にある`レンタル`から借りれます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/8f02c315-6cd2-e0af-217f-d92a51301313.png)

30分、または60分で借りれるようです。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/57f8e3ab-ef80-67c6-ead3-a0429da9d0e2.png)

## 端末での検証の仕方

起動すると、このような画面でした。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/cc84ec3e-778e-6809-c61b-b4d8ac339ded.png)

ウィンドウ右上にある`URL`を押して、確認したいサイトのURLを入れるだけでOKです。
タップやスワイプ、文字の入力などはブラウザのデベロッパーツールと同じ感じで使えました。

PCのキーボードから文字が打てるので楽だったのですが、ペーストは設定が必要です。
例えばパスワード入力などは手打ちするのは嫌ですよね。

ツールバーから`デバイス > PCと端末のクリップボード同期`を有効にすればOKです。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/a37491a4-5719-96a2-10bc-437b95ad78dc.png)

表示サイズはあくまでディスプレイのサイズ基準らしく、デバイスの実寸を再現する項目は見当たりませんでした。

今回は画面に定規を当てて手動で調整しました笑
`デバイスの実寸で表示`のような項目があると嬉しいですね。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/b3cb5b85-2ed6-fc71-f808-72a3e848c03c.png)

## おまけ

若干どきどきしながら検証していましたが、Qiitaの主要なページは崩れていなくてほっとしました笑
（画像は記事ページのabove the fold）

| Rakuten Mini | Galaxy Z Fold |
| --- | --- |
| ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/f389bdb0-9caf-142a-b72e-a7c980e7a4cb.png) | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/95ad71b3-c3c0-0ae9-64f6-b337fafffc00.png) |

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox
SetNativeSize()をした時に画像の位置が変わってしまうのを修正する拡張クラス

# はじめに
<!-- 発端や概要を記載 -->

Imageのスプライトを動的に変更したい時、サイズ感(見た目)が変わる時に便利なのが[SetNativeSize()](https://docs.unity3d.com/ja/2018.4/ScriptReference/UI.Image.SetNativeSize.html
)

ただ、SetNativeSize()を実行すると位置がずれてしまうので、煩わしいこと考えずにスプライト変更できる拡張クラスを紹介します。




# 目次
<!-- タイトルとアンカー名を編集 -->
1. [コード](#Chapter1)
1. [解説](#Chapter2)
1. [使い方](#Chapter3)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# コード

```c#:ImageExt.cs
using UnityEngine;
using UnityEngine.UI;

public static class ImageExt
{
    public static void SetNativeSizeOriginPos(this Image self)
    {
        var originalSize = self.rectTransform.sizeDelta;
        var sizeRate = self.rectTransform.localScale;
        Vector3 offsetSize;

        self.SetNativeSize();
        offsetSize = (originalSize - self.rectTransform.sizeDelta) * sizeRate;
        self.rectTransform.localPosition -= offsetSize / 2;
    }
}

```

<a id="#Chapter2"></a>
# 解説

元の画像サイズを取得し、SetNativeSize()した後に元の画像サイズと現在の画像サイズの差分を計算。
最後に差分の半分の値を現在の位置に引く。




<a id="#reference"></a>
<a id="#Chapter2"></a>
# 使い方

```c#:Sample.cs
using UnityEngine;
using UnityEngine.UI;

public static class Sample : MonoBehaviour
{
    [SerializeField] private Image _image;
    [SerializeField] private Sprite _sprite;

  
    void Start()
    { 
         _image.sprite = _sprite;
         _image.SetNativeSizeOriginPos(); 
    }
}
```

スプライトを変更した後に呼び出すだけ。(SetNativeSize()を同じ要領)

<a id="#reference"></a>
# 参考文献
https://docs.unity3d.com/ja/2018.4/ScriptReference/UI.Image.SetNativeSize.html

https://motunikomi.com/unity%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%A7%E7%94%BB%E5%83%8F%E3%81%AE%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E3%82%B5%E3%82%A4%E3%82%BA%E3%82%92%E6%88%BB%E3%81%97%E3%81%9F%E3%81%84setna