OmniAICreator/Qiita-1.07M huggingface dataset:
JetpackComposeでDpからPxを簡単に計算する拡張関数

毎回LocalDensityを使用して取得するのは面倒なので拡張関数にする
```kotlin
@Composable
fun Hoge(){
  val size = 10.dp
  val sizePx = with(LocalDensity.current) { size.toPx() }
}
```
以下のような拡張関数を作成する
```kotlin
@Composable
fun Dp.toPx(): Float = with(LocalDensity.current) { this@toPx.toPx() }
```
使い方
```kotlin
@Composable
fun Hoge(){
  val size = 10.dp
　　　　val sizePx = size.toPx()
}
```
OCIのUbuntuインスタンスのSSHポートを変更する

OCIのインスタンスは、デフォルトのSSHポートが22番となっており、そのままでは危険。
ここでは、ポート番号を20000番（お好みで）に変更することを目標とします。

## SSHサーバの設定ファイルの変更
`/etc/ssh/sshd_config` を適切に書き換えます。（VimやEmacsを使って）
```:/etc/ssh/sshd_config
︙
#Port 22
︙
```
のコメントアウトを外し、さらに新しいポート番号の記述を追加します。
注）ポート番号の設定失敗を想定して、とりあえず22と20000の両方を開けています。
```:/etc/ssh/sshd_config
︙
Port 22
Port 20000
︙
```

## iptablesの設定変更
OCIのUbuntuインスタンスではiptablesによるファイアウォールがデフォルトで有効になっています。

20000番のポートを許可します。
```shell
$ sudo iptables -I INPUT 5 -p tcp --dport 20000 -j ACCEPT
```

このままではインスタンス（サーバ）を再起動したときに、設定がリセットされてしまうので、永続化します。
```shell
$ sudo /etc/init.d/netfilter-persistent save
$ sudo /etc/init.d/netfilter-persistent reload
```

`sudo iptables -L` で設定済の内容を確認できます。
```bash
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     udp  --  anywhere             anywhere             udp spt:ntp
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:20000
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
︙
```

## VCNのセキュリティ・リストの設定変更
該当のVCNのセキュリティ・リスト > イングレス・ルール を変更します。
![スクリーンショット 2022-03-18 9.58.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529987/77b93e14-3159-1cb5-7650-a16bf3d55726.png)
既に22番ポートが許可されているので、編集を押して、宛先ポート範囲を20000に書き換えて保存します。

## （再）SSHサーバの設定ファイルの変更
一度exitして、新しい20000ポートでログインし直します。
ログインできたら、sshd_configを再度編集して古い22ポートは閉じます。
```:/etc/ssh/sshd_config
︙
#Port 22
Port 20000
︙
```

## 参考
- https://ubuntu.perlzemi.com/blog/20200715102902.html
- https://www.tericle.jp/oci-ubuntu-iptables/
画像をリサイズして表示

## 画像をリサイズして表示する流れ
 1.画像を読む込む
imagecreatefromjpeg(ファイルパスorURL|false) 
画像オブジェクトをファイルパスもしくはURLから作成する。
成功した場合には画像オブジェクト、エラー時にfalseを返す。


2.画像サイズ取得
getimagesize(ｓtring $filename, array &$image_info = null): array|false
サポートする任意の形式の画像ファイルの大きさを決定し、 ファイルの型と高さ/幅を表す文字列を返します。
imagejpeg() 画像からJPEGファイル作成


3.リサイズ
imagecopyresized()　　画像の一部をコピーしサイズを変更する
位置 (src_x,src_y) の src_image から幅 src_w と高さ src_h の長方形の領域を取り、位置（dst_x、dst_y）の宛先画像の長方形領域の間に配置。
|arg name	|description|
|:-----|:-----|
|dst_image	|コピー先の画像リンクリソース|　　300 300
|src_image	|コピー元の画像リンクリソース|
|dst_x	|コピー先の x 座標|
|dst_y	|コピー先の y 座標|
|src_x	|コピー元の x 座標|
|src_y	|コピー元の y 座標|
|dst_w	|コピー先の幅|
|dst_h	|コピー先の高さ|
|src_w	|コピー元の幅|
|src_h	|コピー元の高さ||

4.出力
imagejpeg(ファイル、新しい名前)

<br>



## リサイズして表示した際に画像の比率が崩れてしまった。→対処
例）入力された画像を比率を変えず縦横300の画像にリサイズする
```php:
// 元の画像名を指定してサイズを取得
list($width, $height) = getimagesize($image_before);

//最大幅に縮小拡大
$newwidth = 0; // 新しい横幅
$newheight = 0; // 新しい縦幅
$dst_w = 300; // 最大横幅
$dst_h = 300; // 最大縦幅

$zoom1 = $width / $w;
$zoom2 = $height / $h;
$zoom = ($zoom1 > $zoom2) ? $zoom1 : $zoom2;
$newwidth  = floor($width  / $zoom);
$newheight = floor($height / $zoom);


// サイズを指定して新しい画像のキャンバスを作成
$image = imagecreatetruecolor($dst_w, $dst_h); 

$cutwidth = 0;
$cutheight = 0;
$rewidth = 300;
$reheight = 300;
// サイズを切り取り 300×300にする
if($newwidth>$newheight){
  $zm = $height / $dst_h;
  $rewidth = $width / $zm;
  $cutwidth = ($rewidth - $dst_w)/2 * -1;
}elseif($newheight>$newwidth){
  $zm = $width / $dst_w;
  $reheight = $height / $zm;
  $cutheight = ($reheight - $dst_h)/2 * -1;

// 元の画像から新しい画像を作る準備
$baseImage = imagecreatefromjpeg($image_before);
// 画像のコピーと伸縮
imagecopyresampled($image, $baseImage, $cutwidth, $cutheight, 0, 0, $rewidth, $reheight, $width, $height);
// コピーした画像を出力する
imagejpeg($image,$save_filename);

```




## 参考
https://www.delftstack.com/ja/howto/php/image-resizing-in-php/
https://www.sejuku.net/blog/74338
https://qiita.com/redamoon/items/60eb6e899161d516d9f3
https://dev-lib.com/php-image-size-change/
mySQLコマンド

# データベース

### ローカル環境でMySQLにログインする
```
mysql -u [username] -p;
```

### 新規データベースの作成
```
CREATE DATABASE [DatabaseName];
```

### データベースの確認
```
SHOW DATABASES;
```

### データベースの削除
```
DROP DATABASE [DatabaseName];
```

### mysqlの状態確認
```
status; 
```

### テーブルの作成
```
CREATE TABLE テーブル名 (カラム名1 データ型1, カラム名2 データ型2, ...);
```

### テーブルの中身を全て確認する
```
SELECT * FROM テーブル名;
```

### USERの追加
```
CREATE USER 'user_name'@'localhost' IDENTIFIED BY 'user_name'
```

### rootのpassword変更(xxxxにパスワードを入力する)
```
ALTER USER 'root'@'localhost' IDENTIFIED BY 'xxxx';
```

### データベースの接続を切断する。
```
exit;
```

# 参考リンク
[データベースオブジェクトの命名規約](https://qiita.com/genzouw/items/35022fa96c120e67c637)
[MySQL cheatsheet](https://devhints.io/mysql)
【Nokogiri】スクレイピングして複数ある要素の最初の1つを取得したい

# 状況

Nokogiriでスクレピングしてogp情報を取得したところ、
対象のサイトのog:imageが複数あったため、
結果が複数URLを連結した文字列となってしまった。
（連結した文字列になったのは私のせいです...）
一つ目のURLだけ欲しいのに!!
という時です。

# 結論

`at_css`を使う。です。
```
html = open('nokogiri_practice.html').read
doc = Nokogiri::HTML.parse(html)

doc.at_css('//meta[property="og:image"]/@content')
```

# at_css, css
`at_css`と`css`はcssセレクタで指定した要素を取得するメソッドです。

## at_css
`at_css`は複数ある要素のうち、最初の要素を取得してくれます。
指定の要素がない場合は`nil`を返します。

## css
`css`は指定した要素を配列型式で全て取得してくれます。
指定の要素がない場合は空の配列を返します。

### 参考
[RubyでWebスクレイピング #3 Nokogiriを使いこなす](https://zenn.dev/arao99/articles/a68d8039f85fa8#at_css%2C-css)
画像ファイルのアップロード

## 画像をアップロードの流れ
1. フォームからファイルを受け取り、バリデーションする。
2. 問題がなければ、サーバーの一時フォルダに保管。
3. move_uploaded_file()で一時フォルダから指定のパスに移動させ、保存。

<br>
<br>

**画像ファイルを送るフォーム**

```html:index.php
<form action="upload.php" method="POST" enctype="multipart/form-data">
　　　　　　<input name="image" type="file" accept="image/*">
　　　　　　<input type="submit" value="送信">
</form>
```
<br>
<br>

**フォームから画像ファイルを受け取る**
グローバル変数「FILES」
$_FILES['upload']['tmp_name']はアップロードされたファイルの情報が格納されたグローバル変数です。
```php:upload.php
image = $_FILES['image'];
imageValidate($article,$image);
```

<br>
<br>

**画像のバリデーションし、ファイルを一時ファイルから指定ファイルへ移動。（DBに保存して完了）**
```php:function.php
public function imageValidate($article,$image){
    $result = false;

    $filename = basename($image['name']);
    $tmp_path = $image['tmp_name'];
    $file_err = $image['error'];
    $filesize = $image['size'];
    $upload_dir = '/path';
    $save_filename = date('Ymdhis') . $filename; //ファイル名に日付を入れて保存する
    $err_msg = array();
    $save_path = $upload_dir.$filename;

    //ファイルのバリデーション
    //ファイルサイズは1MB未満か確認
    if ($filesize > 1048576 || $file_err == 2) {
        array_push($err_msg, 'ファイルサイズは1MB未満です。')
     }

    //許可する拡張子を指定
    $allow_ext = array('jpg', 'jpeg','png');
    //ファイルの拡張子を取得
    $file_ext = pathinfo($filename, PATHINFO_EXTENSION);
    //配列の中にあるか確認
    if (!in_array(strtolower($file_ext), $allow_ext)) {
        array_push($err_msg, '指定の画像ファイルを添付して下さい');
     }
     //エラーがあればエラーメッセージを返す
    if (count($err_msg) === 0) {
        //ファイルはあるかどうか確認、あれば一時ファイルから指定のディレクトリに移動
        if (is_uploaded_file($tmp_path)) {
            if(move_uploaded_file($tmp_path,$upload_dir.$save_filename)){
                ｆileSave($$save_filename); //DBに保存する関数
            }else{
                array_push($err_msg, 'ファイルが保存されませんでした。');
         }else{
            array_push($err_msg, 'ファイルが選択されていません。');
         }
     }else{
         return $err_msg;
     }
    }
```
<br>
<br>

　FILES [ アップロードフォームのinput name値 ] [ アップロードされたファイル情報の項目 ]
最初の[]にはHTMLアップロードフォームのinput属性のname値が設定されます。
2番目の[]にはアップロードされたファイル情報の項目が入ります。
ちなみに$_FILESの中身は以下のような連想配列になっています。

```
Array(
[name] => memo.txt
[type] => text/plain
[tmp_name] => /var/tmp/php7UNOJY
[error] => 0
[size] => 45
)
```

|項目	|内容   |
|:-----|:------|
|name  |元ファイル名|
|type  |ファイルタイプ|
|tmp_name|	サーバーに一時保管されたファイル名|
|error	|エラーコード|
|size	|ファイルのバイト数|

<br>
<br>

**エラーコードは0ならアップロード成功で、1〜4、6〜8は以下のようなエラーになります。**

|コード	|エラー定数|説明|
|:-----:|:------|:------|
0|	UPLOAD_ERR_OK	|エラーなし
1|  UPLOAD_ERR_INI_SIZE	|php.iniのupload_max_filesizeのサイズを超えている
2|	UPLOAD_ERR_FORM_SIZE|	HTMLフォームで指定された MAX_FILE_SIZE を超えている
3|	UPLOAD_ERR_PARTIAL	|一部のみしかアップロードされていない
4|	UPLOAD_ERR_NO_FILE	|アップロードされなかった
6|	UPLOAD_ERR_NO_TMP_DIR	|サーバー一時保管フォルダがない
7|	UPLOAD_ERR_CANT_WRITE	|ディスクへの書き込みに失敗
8|	UPLOAD_ERR_EXTENSION	|PHPの拡張モジュールがアップロードを中止した



<br>

## 注意する
※下記のように記述していた場合にファイルが最大サイズを超えると、
$_FILESの['type']['tmp_name']は空で送られてしまう。
```
 <input type="hidden" name="MAX_FILE_SIZE" value="1048576">
```
【Rails】カレンダーの月めくりajax化

#  環境
Ruby 2.6.3
Rails 5.2.6
本番環境 Nginx／Puma／Linux2／AWS EC2／MySQL

# この記事でわかる事
simple_calendarを実装させましたが、月を翌月や先月に切り替えるとリロードをしてしまうので
カレンダーのみ非同期で更新させる方法を解説します。

※simple_calendarの実装は以下記事を参考にさせていただきました。
[【rails】simple_calendarを使ってカレンダーつきのブログ機能を作ってみた。](https://qiita.com/isaatsu0131/items/ad1d0a6130fe4fd339d0?)
[【Rails】simple_calendarを使ってカレンダーつきのmemo機能を作る。](https://note.com/yukinooffice/n/n36789d96ba5d)
# 実装方法
## 非同期処理のざっくり手順
1. 更新トリガーを `remote :true`にする
1. 更新させたいviewを部分テンプレート化する
1. アクション名.js.erbファイルを作り、更新処理を書く


↓参考記事↓
[【Rails】 remote: trueでフォーム送信をAjax実装する方法とは？](https://pikawaka.com/rails/remote-true)

## 解説
### ①更新トリガーを `remote :true`にする
formやlink_toでcontrollerアクションを呼ぶトリガーの後ろの方にかく`local:true`の場合は `remote:true`にします。
今回はsimple_calendarで自動で生成されたview内にある月のlink_toを変更します。

```:view/simple_calendar/_month_calendar.html.erb
:
 <%= link_to t('simple_calendar.previous', default: '<<先月'), calendar.url_for_previous_view, remote: true %>
:
```

### ②更新させたいviewを部分テンプレート化する
カレンダーを更新させたいのでテンプレート化します。

```:_calendar.html.erb
 <%= month_calendar events: logs do |date, logs| %>
	<%= date.day %>
	<% logs.each do |logs| %>
     <div>
	   <i class="fas fa-tint text-primary"></i>
	   <span><%= logs.created_at.strftime('%H:%M') %></span>
     </div>
	<% end %>
<% end %>
```

部分テンプレートを呼び出しているviewはこのようになっています。↓↓↓
**ここでdivにidを付けないと.js.erbで呼び出せないです**
```:show.html.erb
:
  <div id="calendar">
    <%= render 'calendar', logs: @logs %>
  </div>
:
```

### ③アクション名.js.erbファイルを作り、更新処理を書く
showアクションでviewを呼び出しているので`show.js.erb`を作成します。
`$('#id名').html("<%= j(renderで呼び出している箇所と同じもの) %>");`
と書くので実際に書いて見るとこのようになります。

```:show.js.erb
$('#calendar').html("<%= j(render 'calendar', logs: @logs) %>");
```

これで月のカレンダーをめくった際に、ページ全体ではなくカレンダーのみを更新できました!
欠陥レポートの中身

# 欠陥レポートの中身
欠陥レポートは不具合の様子を開発担当者に伝えるためのコミュニケーションの手段です。テスト実施している私たちのメモ書きではありません。相手によりよく意図を伝えるにはどのような書き方が適切だろうかと常に自問自答することで、結果レポートはいいものになっていきます。

## 欠陥レポートの中身
欠陥レポートは、どのような不具合が、どのような条件や手順で発生したのか、開発担当者に伝えるためのドキュメントです。基本的に一つの不具合に対して一つの欠陥レポートを起票します。

### 欠陥管理情報
欠陥レポートを管理するための項目です。欠陥レポート同士を区別し、おおよその内容を明らかにし、重要度を示している部分です。具体的には次のような細目から構成されることが多いでしょう。
1. タイトル
　どのような不具合が発生したのか一目でわかるよう簡潔に表したもの。短すぎても長すぎてもいけません。
1. 欠陥管理ID
欠陥レポートそれぞれに与えられた固有の番号。これにより欠陥レポート同士を間違えることは無くなります。
1. テストケースID
 どのテストケースを実施した際に検出した不具合であるのかを明治するための細目。欠陥レポートとテストケースとの間のトレーサビリティ（追跡する能力)を確保します。テストケース外で検出した場合はその旨を記載します。
1. 起票者名
　不具合を検出し、欠陥レポートを作成したテストオペレーターの氏名。
1. 起票日時
 欠陥を検出した日時と時刻。
1. 重要度
　不具合のリスクの高さを数段階に分けて(例えばA>B>C・・・のように)記載します。開発担当者はこの記載を参考に、どの不具合から修正すべきか優先順位をつけます。全て、高重要度（あるいは低重要度）のような記載にしてしまうと役立たない細目となってしまいます。

## 欠陥の内容
1. 概要
どのような不具合が発生したのか、要約した情報を記載します。
1. 発生手順
　不具合が発生した際の操作手順を記載します。一つの文には複数の手順を記述せず、原則的に慰問一手順として記載します。
1. 動作結果
　「発生手順」を実施した結果をそのまま記載します。これが不具合の症状そのものとなるわけですが、それを強調した表現にする必要はありません。なぜなら、次の細目である「期待結果」と比較することで、充分に明らかになるからです。
1. 期待結果
　テストケースに記載された「期待結果」を転記します。テストケース外である場合は、機能仕様書やユーザーの要求から期待される理想としての挙動を記載しましょう。
1. 再現率
1. テストを実施した回数と、そのうち不具合が発生した回数を記します。テストを３回実施した際、不具合が２回発生したのなら「2/3」のように分数で記載します。
## 動作環境情報
テスト対象がどのようなものだったか、どのような環境で動作したかを記録したもの。この記載によって開発担当者はテスト実施時の状態を把握することができます。
- テスト対象の名称・バージョン
　テスト対象のソフトウェアの名称とそのバージョンを記載します。
- 期待の種類・バージョン
　PCや携帯などの機体の種類（型番）とそのバージョンを記載します。
- OSの種類・バージョン
　PCや携帯などの機体に搭載されているOSの種類とそのバージョンを記載します。
## 備考
項目にない追加情報や補足を記載します。関連ある不具合について（類似の事象や同じ操作で検出された不具合の情報など）や不具合の回避情報などもこちらに記載します。また欠陥管理情報や動作環境情報の一部がこちらに記載されていることもしばしばあります。

## エビデンス
不具合の証拠となる画像や動画を欠陥レポートに添付します。エビデンスの画像は、正とされる画像と比較できるよう配置したり、矢印や枠線を設けたり、時系列で並べたりするなど、どの点が不具合であるのか開発担当者の理解できるよう工夫して添付しましょう。

## まとめ
- 欠陥レポートはコミュニケーションの手段
- 欠陥レポートは、不具合の発生する条件・手順などを開発担当者に伝えるためのドキュメント
- 欠陥レポートは「欠陥管理情報」　「欠陥の内容」　「動作環境情報」　「備考」　「エビデンス」で構成されていることが多い。
オブジェクト指向の用語【個人的なお勉強アウトプット】

## クラスとは
設計図
属性（プロパティ）と操作（メソッド）が定義してある

## インスタンスとは
クラスからできあがったもの
インスタンス化されたあとに属性設定や操作を行う

### 参考記事
https://wa3.i-3-i.info/word1118.html

## メソッドとは
オブジェクト指向における「操作」を定義したもののこと
関数みたいなもの

### 参考記事
https://wa3.i-3-i.info/word1906.html

## 静的（スタティック）メソッドとは
クラスに対して呼び出し、どこで呼び出しても同じ処理を行う
https://prograshi.com/language/php/php-static-vs-instance/

## 動的（インスタンス）メソッドとは
インスタンスに対して呼び出し、インスタンス毎に固有の結果を返す

### 参考記事
https://prograshi.com/language/php/php-static-vs-instance/
DjangoでstaticファイルのURLをアプリごとに設定したい。

Djangoでは静的ファイルの配信は、`settings.py`にある`STATIC_URL`で配信するURLは設定されますが、アプリケーションごとに配信するURLを設定したい事例がありました。

```
https://example.com/app1/static/
https://example.com/app2/static/
```
のようなイメージです。

:::note warn
本番環境等では、静的ファイルの配信は、nginxなどのwebサーバーに任せるべきことなので、正攻法としては、webサーバーのリバースプロキシやmod_rewriteなどでURLを変更させるのが良いかと思います。
:::

djangoのrunserverでサクッと検証するには、urls.pyに以下のようにすれば、できました。

```python:app1/urls.py
from django.views.static import serve
from os.path import join
from testProj.settings import BASE_DIR

urlpatterns = [
  re_path(r'^static/(?P<path>.*)', serve, {'document_root':join(BASE_DIR, 'app1', 'static'}),
  ...
]
```

プロジェクトのurls.pyに記述する場合は、以下のように。

```python:testProj/urls.py
from django.views.static import serve
from os.path import join
from testProj.settings import BASE_DIR

urlpatterns = [
  re_path(r'^app1/static/(?P<path>.*)', serve, {'document_root':join(BASE_DIR, 'app1', 'static'}),
  ...
]
```
覚えておきたいこと

# はじめに

業務するうえで先輩社員の方に今後役に立ちそうな機能を教えてもらったので忘れないよう記事にしようと思いました。

# 目次

* ショートカットキー
  * 部分的なスクリーンショット
  * クリップボードの履歴
* サクラエディタでの機能


# ショートカットキー

ショートカットキーはたくさんあると思うのですが、最近教えてもらった2つを紹介したいと思います。

### 部分的なスクリーンショット

Windows+shift+Sで以下のような状態になります。
![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1735204/0008d6d2-5da2-0c99-96f8-2529d7e9ebb8.png)
この状態でスクリーンショットしたい部分を範囲選択すると部分的なスクリーンショットが取れます。

### クリップボードの履歴

Windows+Vで以下のように今までコピーしたものやスクリーンショットしたものが履歴で出てきます。
![スクリーンショット (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1735204/6bed5bf1-fb8a-a855-cae6-70dae00866d4.png)
ここで貼り付けたいものを選択すれば貼り付けることができます。


# サクラエディタ

メモ帳よりも便利な機能があり、使い勝手が良いです。
こちらも教えてもらった機能を紹介したいと思います。

以下の画像の数字をカンマ区切りに改行したいときに使う機能を紹介します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1735204/a1f745b4-3989-cb77-7ffe-092016cc83b4.png)

control+Rを押し置換のウィンドウを出します。
カンマ区切りで改行したいので置換前には「,」、改行したいので置換後には改行コードと言われる「￥r￥n」(入力する際￥は半角)を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1735204/ab5f62f9-be90-4f1a-a86b-e8c74b7810a8.png)

最後に正規表現の項目をチェック入れていることを確認してすべて置換をクリックすると以下のようにカンマ区切りに改行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1735204/72fb4bdc-c8c2-4cde-e140-4004170c3bc5.png)


# 最後に

覚えておいて損はないと思うのでぜひ活用してみてください。
最後まで読んでいただきありがとうございました。
ora2pg を使ってoracleのテーブル定義をpostgres用に変換してみた（windows）

# 背景
oracleに作成されたテーブルをpostgresに移動しようとしたところ、型の違いなどで単純にoracleのにテーブル作成したときのddl実行では移動させられなかった。
ora2pgというものを使えば、ある程度自動で変換してくれるとのことだったので、ora2pgを使ってみました。

本記事は、[【windows】【データベース移行】oracleからpostgresqlへ](https://gogoinaka.hatenadiary.jp/entry/2018/08/28/010859)
をもとに作成しています、リンク先の手順で、途中私が詰まってしまったところに対して
補足で解説を入れていきたいと思います。

# 手順

## 1.perl環境のインストール

[Strawberry Perl for Windows](https://strawberryperl.com/)をインストール
この時32bitと64bitどちらを選択するかはoracleのbitに合わせる必要があります。
私は、oracleが32bitなのに64bitをインストールしてしまい、子１時間ほど苦戦しました。

コマンドプロンプトで
```
perl --version
```
を実行、バージョンが出てきたらOK

## 2.関連モジュールのインストール
コマンドプロンプトで以下を実行。
```
CPAN install Time-Hires
CPAN install DBI
CPAN install DBD::Oracle
```
私の環境ではproxyを通す必要があったのですが、proxyもうまく通せなかったので、
[Strawberry Perl+Proxy接続環境でCPANモジュールをインストールする](https://www.koikikukan.com/archives/2014/01/17-005555.php)
を参考に、以下のモジュールを直接ダウンロードしてインストールしました。

[Time-Hires](https://metacpan.org/pod/Time::HiRes)
[DBI](https://metacpan.org/pod/DBI)
[DBDOracle](https://metacpan.org/dist/DBD-Oracle)

## 3.環境変数の追加
以下の環境変数を追加
```
パス名:ORACLE_HOME
C:\oracle\product\11.2.0\client_1\
パス名:LD_LIBRARY_PATH
C:\oracle\product\11.2.0\client_1\LIB
```
※この部分リンク先の記事の設定値と異なります。

# 4.ora2pgのインストール
[ora2pg](https://ora2pg.darold.net/index.html)をgitからzipファイルをダウンロードして適当な場所に解凍。
展開したディレクトリまで移動して、perlを使ってインストール
```
cd C:¥ora2pg-19.0
perl Makefile.PL
gmake
gmake install
ora2pg --version
```

# 5.ora2pgの設定
インストールが完了すると、展開したディレクトリ内に[ora2pg_dist.conf]ファイルが出来ているので、コピーして[ora2pg.conf]にリネーム、ファイルを開いて以下の設定を自分の環境に変更する。
```
ORACLE_HOME [windowsOSに通したパス]
ORACLE_DSN dbi:Oracle:host=[ホスト名]:sid=[sid名(XE等)]
ORACLE_USER [ユーザー名]
ORACLE_PWD [パスワード]
SHEMA [スキーマ名(通常はユーザー名と同じ)]
```
※ORACLE_HOMEは環境変数に指定したものが勝手に入っています。

設定が完了したら、以下のコマンドを実行して接続確認
```
ora2pg -c ora2pg.conf -t SHOW_VERSION
Oracle database 11g Release 11.2.0.1.0
```

# 6.ora2pgの実行
コマンドプロンプトでora2pg展開ディレクトリに移動し以下のコマンドを実行
```
ora2pg -c ora2pg.conf
```
そのまま放置しておくとディレクトリ直下にoutput.sqlというファイルが作成されていて、
その中にスクリプトが記載されていました、必要な部分だけ
postgresで実行して無事作成に成功しました。

# 参考URL
[【windows】【データベース移行】oracleからpostgresqlへ](https://gogoinaka.hatenadiary.jp/entry/2018/08/28/010859)

[Strawberry Perl+Proxy接続環境でCPANモジュールをインストールする](https://www.koikikukan.com/archives/2014/01/17-005555.php)
LightBox 画像ポップアップ表示

　
```
<link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/css/lightbox.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.12.4.min.js" type="text/javascript"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/js/lightbox.min.js" type="text/javascript"></script>
</head>
```
上記をhead内最下部に挿入。


```
<a href="拡大表示される画像" data-lightbox="任意の名前" data-title="画像のタイトル">
<img src="通常表示される画像" alt="" /></a>
```
私のためのGitコマンド

# Gitコマンド
自分自身のための gitコマンド集です
## git status
Gitリポジトリの状態を表示

```
git status
```

## git add
ステージ領域にファイルを登録（コミットする前の一時領域）

```
git add ファイル名

git add .   // カレントディレクトリ配下全て
git add README.md
```

## git commit
ステージ領域に登録されているファイル群をリポジトリの記録として登録

```
git commit -m 'コミットメッセージ'

git commit --amend   // 直前のコミットメッセージを変更
```
-m を付けずに実行した場合、エディタが立ち上がり詳細なメッセージの入力が可能
+ 一行目　コミットする内容の要約
+ 二行目　空業
+ 三行目　変更理由や詳細

## git remote add
リモートリポジトリを登録

```
git remote add origin リポジトリのURL
```

## git push
現在のローカルリポジトリの内容をリモートリポジトリに送信

```
git push origin main
```
*origin リモートリポジトリの main ブランチに送信する

## git log
リポジトリにコミットされたログを確認

```
git log

git log README.md      // 指定したディレクトリ、ファイルのみログに表示
git log -p README.md   // READMEファイルの差分を確認
git log --graph        // ブランチをグラフとして確認
```

## git diff
現在のワークツリーとステージ領域との差分を確認

```
git diff
git diff HEAD   // 今回のコミットと前回のコミットの差分を確認
```

## git branch
ブランチを一覧表示

```
git branch

git branch ブランチ名   // ブランチを作成する
```

## git checkout
ブランチを切り替える

```
git checkout ブランチ名

git checkout -b ブランチ名   // ブランチを作成し切り替える
```

## git merge
ブランチを結合

```
git merge 結合対象ブランチ名

git merge --no-ff 結合対象ブランチ名   // マージコミットメッセージを作成
```

## git reset
過去にコミットした時点まで遡る

```
git reset --hard ハッシュ
```
ハッシュは git log で表示したコミットログの先頭に記載されている

## git reflog
リポジトリで行われた作業を確認

```
git reflog
```
git resetで過去の状態まで遡ってブランチを切り修正を加えコミットした後、過去に遡る前の状態まで戻りたい場合（つまり未来に移動したい場合）

git reflogで表示されたログのハッシュを使用し、git reset --hardをすれば過去に遡る前の状態まで進めることができ、本来作業していたブランチと、過去に戻り修正したブランチをマージすれば現在のコードに修正を結合することができる。

## git rebase -i
過去のコミットを削除して改変

```
git rebase -i HEAD~2   // 現在のブランチのHEADを含めた二つまでの歴史を対象とする
```
エディタが立ち上がり、削除したいコミットに記載されている pick という部分を削除し fixup に変更し保存する。
削除したコミットの内容をもう一つのコミットの内容として加え、それを新しいコミットとする。

（すでにコミットしたコミットメッセージにタイプミスなどがあった場合、新しいコミットを作成し、タイプミスしたコミットメッセージは削除し、新しいコミットメッセージに書き換えたい場合などに便利）

## git clone
リモートリポジトリを取得

```
git clone リポジトリのURL
```
リモートリポジトリの情報を現在のディレクトリにコピーする

## git pull
最新のリモートリポジトリブランチを取得

```
git pull origin ブランチ名
```

# Git機能

## Issue
Issueはソフトウェア開発におけるバグや議論などを管理するために発行するもの。
タスクリストを作成したり、各Issueに独自のラベルを張り付けることができる。

## Fork
任意のリポジトリを自分のリポジトリとして作成する。

## Pull Request
自分で変更したコードを相手のリポジトリに取り込んでもらえるように依頼するための機能。

とあるリポジトリをForkし、cloneしてローカル環境にリポジトリを持ってくる
そこでブランチを切り、機能の追加や問題点を修正し、Pull Requestを送る
といった流れで、他のソフトウェア開発に参戦することができる。
同期と非同期の違い（UML：シーケンス図）新人向け説明

# UMLのシーケンス図の同期メッセージと非同期メッセージの違い
先日、UML表記法を教えていた時のこと、同期と非同期が分からないので教えて欲しいと言われました。
それが、ソフトウェア経験がほぼない方だったので、即興で日常の例で説明しました。腑に落ちたそうなので、紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197297/f4d6eae0-10bb-5fa6-4be6-4d8366c1c8f6.png)
同期メッセージは矢印が塗りつぶし、非同期メッセージは開いた矢印です。

ソフトウェアエンジニアでプログラミングで、プロセス間通信/スレッド間通信を知っている、RTOSのタスク間通信を知っている、など、イメージが湧く人も多いのですが、そのような知見がなく全くイメージできない人もいます。

# 宅配で説明
シーケンス図で描くと、
「荷物受取お願いしまーす」ってピンポーン、ってするのが、送信しているメッセージで、
メッセージの引数で、荷物が渡されている感じです。
それを「荷物受取(配達物:荷物)」って表記しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197297/57375be9-73cd-6f33-a999-1f51e183f1a0.png)
## 同期メッセージ
荷物受取でピンポーンして、荷物受取人が出てきて渡して受取りを確認してから次に行くのが同期メッセージ。(上図の1つ目のメッセージ)
ハンコを貰う場合と貰わない場合があって、戻り値の違いになる。(上図の2つ目のメッセージ)
2023/4/30追記：「荷物受取（）：ハンコ」の引数が欠けてました。「荷物受取（配達物 荷物）：ハンコ」が正しいです。
## 非同期メッセージ
荷物受取でピンポーンして、玄関前に荷物置いて、すぐにササっと立ち去って、次に行くのが非同期メッセージ（置き配）。(上図の3つ目のメッセージ)
ただし、ピンポーンってしないで、荷物を置いて行ってしまうのは、メッセージを送ってないので、非同期メッセージのイメージとは違いますね。

# 時事ネタかも知れませんが
コロナ禍での時事ネタかも知れませんね (^^
GoogleスプレッドシートでQUERY関数を使用した際に、一行目のセルに複数の情報が入ってしまう場合の対策

Google スプレッドシートで `QUERY()` 関数を使ってデータの参照をした場合に、以下のように1行目に複数の情報が入ってしまう場合があります。このメモではこれが起こる原因と、対策について共有します。

元データ（`A1:C5`にデータが有る）：
![2022-03-18_org.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423595/af2b4adb-24c7-69df-6148-cdae670c944a.png)

`QUERY(A1:C5, "select *")` で表示したデータ：
![2022-03-18_out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423595/a655587f-329e-7b9c-9f43-a6ecf9edc154.png)

## 対策のサマリ

この問題は、スプレッドシートが推定したヘッダの範囲が作成者が期待するものと異なることが原因で発生します。
そのため、`QUERY()` 関数の第3引数（`見出し`）によりヘッダの行数を明示的に指定し（`1` か `0` にする）推定を排除することで、想定外の挙動を防止する対策が有効です。

ただし、選択範囲にヘッダが複数行（第3引数が2以上）含まれる場合、上述の現象が発生するのは仕様なので、選択範囲を調整して対応すると良いでしょう。

```
=QUERY(A3:C5, "select *", 0)
```

## ポイント

- `QUERY()` 関数の３番めの引数（`見出し`）により、QUERYで参照している範囲に何行のヘッダが含まれているか示すことができます。
- `見出し` 引数を指定しなかった場合、もしくは `-1` を指定した場合はスプレッドシートは範囲を解析してヘッダの領域を推定します。この際、１行以上のヘッダがあるものと推定される場合があるようです。
- `見出し` 引数を `0` にした場合はヘッダがないものとして扱われるようです &lArr; この情報はヘルプなどにはあまり明示的に記載されていません。
- ヘッダとして認識された領域は、`QUERY()` で参照した際に一行目に表示されます。
  この際、**複数行のヘッダは１行に圧縮して表示されます** &lArr; これが１行目に複数の情報が入ったデータができる原因
- （関連）基本的に `QUERY()` では各列のデータ形式は統一されていることを想定していて、例えば列に数字と文字列が混在しているような場合は少数派の方が空欄（NULL値）で表示されるため、注意が必要です。

## 参考資料

本件のわかりやすい参考情報：

https://teratail.com/questions/123747

Googleの `QUERY` 関数のヘルプ：

https://support.google.com/docs/answer/3093343?hl=ja

関連する記事：

https://qiita.com/Shinoda_Naoki/items/d73e28a8a99fdc5ec1f5
Blazor WebAssemblyアプリのコンテンツ読み込みから未使用の.dllを削除する方法

## 背景

Blazor WebAssembly アプリプロジェクトからクラスライブラリプロジェクトが参照されるシナリオを想像してください。

![The structure of the sample project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sgtwjck0usozpqxq8h21.png)

このシナリオでは、クラスライブラリから公開されるすべての型は、何らかの理由でリリースビルドの Blazor アプリで使用されることはありません。
(C#コンパイラの機能の一つである条件付きコンパイルで制御されているかもしれません)。

この場合、"Release" 設定で公開した Blazor アプリでは、"IL Linker" のトリミング機能によって、クラスライブラリ .dll ファイルがロードされないことが期待されます。

しかし、予想に反して、**クラスライブラリ .dll ファイルは、どこにも使用されていないにもかかわらず、ブラウザに読み込まれます**。😱
![The "SampleLib.dll" is loaded unexpectedlly](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l31sxngjrlijyh6xztly.png)

## 解決策

未使用のクラスライブラリ .dll ファイルをロードしないための解決策は、**アセンブリレベルとしてクラスライブラリコードに `AssemblyMetadata("IsTrimmable", "True")` 属性を追加すること**です。

```csharp
// このコードは、クラスライブラリの.csファイルのどこかに追加する必要があります。
[assembly: System.Reflection.AssemblyMetadata("IsTrimmable", "True")]
```

そうすれば、**クラスライブラリがどこにも使われていない場合、ブラウザはクラスライブラリ .dll ファイルを読み込むことはありません**。🎉
![The "SampleLib.dll" is no longer loaded.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wsqef375u0617ok0siuj.png)

## .NET 5 の場合

残念ながら、**The `AssemblyMetadata("IsTrimmable", "True")` 属性は .NET 5 プラットフォーム上では、何の効果もありません**。

このシナリオに対する .NET 5 プラットフォームでの解決策は、以下のように Blazor WebAssembly アプリのプロジェクトファイル内に MSBuild スクリプトのいくつかを追加することです。

```xml
<!-- これは Blazor WebAssembly アプリの .csproj ファイルであり、クラスライブラリではありません。  -->
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
  ...
  <Target Name="_ConfigureAssemblyLevelTrimming" BeforeTargets="PrepareForILLink">
    <ItemGroup>
      <ManagedAssemblyToLink Condition="'%(Filename)' == 'SampleLib'">
        <IsTrimmable>true</IsTrimmable>
      </ManagedAssemblyToLink>
    </ItemGroup>
  </Target>
  ...
```

クラスライブラリを NuGet パッケージとして提供する場合、上記のようなMSBuild スクリプトも NuGet パッケージファイルに含めて、そのパッケージを参照するプロジェクトに自動的にインポートするように設定する必要があります。

このことは、.NET 6 以降のプラットフォームと比べ簡単ではありません。しかしながら、.NET 5 プラットフォームではこれ以外の方法はありません。

なお、**.NET 5のサポート終了は2022年5月8日**であることを忘れないでください。

## 公式ドキュメント

詳しくは、以下のマイクロソフト社の公式ドキュメントサイトをご覧ください。

📄 [_"追加のアセンブリのトリミング | Microsoft Docs"_](https://docs.microsoft.com/ja-jp/dotnet/core/deploying/trimming/trimming-options#trim-additional-assemblies)

公式ドキュメントでは、`<TrimmableAssembly/>`という MSBuild アイテムについても説明されています。
しかし、この記事では、`<TrimmableAssembly/>` MSBuild アイテムはあまり重要でないと考えているので、言及していません。
【MySQL】複数レコードのカラム内容を結合して取得する

## 前提
複数の行にある同じ列の内容をSQLでまとめて取得したいとき。
例えば、ブログアプリの記事一覧にコメントした人全員の名前を載せたいとする。

参考イメージ「Aさん〜」の部分など
![スクリーンショット 2022-03-17 12.42.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/6f5bbc53-1053-7b65-9335-fd6e5e3f7f99.png)

## 参考情報：列をまとめる CONCAT関数
MySQLで列の内容をまとめるときには、**CONCAT関数**が使える
```sql
-- 準備
CREATE TABLE User(id integer, last_name varchar(100), first_name varchar(100));
INSERT INTO User(id, last_name, first_name) VALUES(1, "田中","太郎"),(2, "鈴木","次郎"),(3, "遠藤","三郎");
-- 名前をくっつける
SELECT id, CONCAT(last_name, first_name) FROM User;
-- =>　1 田中太郎　など
```
ちなみに数値型と文字列型でも結合してくれる
```sql
SELECT CONCAT(id, first_name) FROM User;
-- 1太郎
```

## 本題：集計して列をまとめる GROUP_CONCAT関数
今回の場合は、複数の行にまたがっている列を1つにまとめたいので、CONCAT関数に似ている**GROUP_CONCAT関数**を使う。
GROUP_CONCAT関数はGROUPBYと一緒に用いる集計関数で、列を集計する際にどのように集計するかを指定している。

集計関数のイメージ
![スクリーンショット 2022-03-17 13.13.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/815054/5fa348b3-74b4-19f0-8435-d537844d1714.png)
GROUP_CONCAT関数の場合は **「文字列として結合してくれる」**
```sql
-- 準備
CREATE TABLE Student(id integer, class varchar(10), name varchar(100));
INSERT INTO Student(id, class, name) VALUES(1, "A", "田中"),(2, "A", "鈴木"),(3, "A", "遠藤");

-- 名前をくっつける
SELECT class, GROUP_CONCAT(name) FROM Student GROUP BY class;
-- class	GROUP_CONCAT(name)
-- A	田中,鈴木,遠藤
```

カンマになっているセパレーターは指定することができる
```sql
SELECT class, GROUP_CONCAT(name SEPARATOR '-') FROM Student GROUP BY class;
-- A	田中-鈴木-遠藤
```
並び順を指定することもできる
```sql
SELECT class, GROUP_CONCAT(name ORDER BY id DESC) FROM Student GROUP BY class;
-- A	遠藤,鈴木,田中
```
条件式などを組み込むことも可能
```sql
-- 名前をくっつける
SELECT class, GROUP_CONCAT(CASE WHEN NAME = "鈴木" THEN "◯" ELSE "×" END) FROM Student GROUP BY class;
-- A	×,◯,×
```

前提としている場合以外でも色々と使えそうなので、ぜひ活用していきたい。

## 参考

[12.19.1 GROUP BY (集約) 関数](https://dev.mysql.com/doc/refman/5.6/ja/group-by-functions.html#function_group-concat)
[MySQLの文字列結合にはCONCAT。GROUP_CONCATとGROUP BYで複数データ集約](https://style.potepan.com/articles/18383.html)
YOLOv5 環境構築でつまったところ まとめ

# はじめに
Deep Learning 初心者が、 YOLOv5 の環境構築をしていてつまったポイントと、その解決方法をまとめました。

# YOLOv5 とは
物体の位置と種類を検出する機械学習アルゴリズムです。

既に学習済みのモデルを使って物体検出したり、一からモデルに学習させたりすることができます。

[GitHub](https://github.com/ultralytics/yolov5)で公開されています。

# 環境構築でつまったところ
今回は少し古めの[バージョン4.0](https://github.com/ultralytics/yolov5/tree/v4.0)で環境を構築しました（最新は[バージョン6.1](https://github.com/ultralytics/yolov5/tree/v6.1)）。

当方のPC環境は Windows10 で、 RTX3080 Ti を積んでいます。

Linuxな環境(WSL等)は使わずに、コマンドプロンプトのみで構築しました。

## ``pip install -U -r requirements.txt`` 実行時に ``ERROR: Could not build wheels for pycocotools, which is required to install pyproject.toml-based projects`` と言われる

pipコマンドを使ってインストールする際、途中でC/C++でのコンパイルが必要になります。

しかし、利用中のWindows環境には必要なバージョンのコンパイラがないので、このエラーが出ています。

[ダウンロードページ](https://visualstudio.microsoft.com/ja/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16)から Microsoft Visual C++ vs_buildtools をインストールし、``pip install -U -r requirements.txt``を再実行することで解決しました。

## detect.py 実行時に ``AttributeError: Can't get attribute 'SPPF' on <module 'models.common' from '~\\yolov5\\models\\common.py'>`` と言われる

detect.py の初回実行時に、検出に使用する学習済みモデル(.pt)を指定しなかった場合、その時点での最新の学習済みモデルがダウンロードされ使用されます。

その際、今回構築した v4.0 の環境と v6.1 の最新のモデルで、何かしらの整合性が取れていないのだと思われます。

[v4.0 のリリースノート](https://github.com/ultralytics/yolov5/releases/tag/v4.0)から v4.0 時点の学習済みモデルをダウンロードして、差し替えることで解決しました。

## train.py 実行時に``UnicodeDecodeError: 'cp932' codec can't decode byte 0x99 in position 78: illegal multibyte sequence``と言われる
Windows は str型（UTF-8）を byte型（cp932）に勝手に変換しようとしますが、何らかの理由で変換できないため UnicodeDecodeError が発生しています。

私の場合は、現在使用している Python のデフォルトエンコーディングを UTF-8 にしたら解決しました。

参考: [Windows 上の Python で UTF-8 をデフォルトにする](https://qiita.com/methane/items/9a19ddf615089b071e71)

## 学習や物体検出がGPU動作ではなくCPU動作になってしまう
- YOLOv5のプログラムが GPU or CPU のどちらで動作しているか
- 使用している pytorch のバージョン

は、detect.py や train.py を実行した時のログで確認できます ↓
ここにGPUの名前が出てこない場合は、使用する GPU と pytorch、Driver、CUDA、CuDNN のバージョンを合わせる必要があります。

```
yolov5>python train.py --data data.yaml --cfg yolov5m.yaml --weights '' --epochs 100
Using torch 1.10.2+cu113 CUDA:0 (NVIDIA GeForce RTX 3080 Ti, 12287.5MB)
```
　

以下を参考に、バージョンが合ってないものをインストールし直します。
[Pytorch – GPU と対応するドライバ、CUDA、CuDNN のバージョン](https://pystyle.info/pytorch-relationship-between-gpu-and-driver-cuda-and-cudnn-versions/)
 

バージョンを合わせたら、CUDA と CuDNN の PATHが通っていることを確認します。
 ![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702049/21a283a9-140f-7e14-fa9f-07df71b3a4e4.png)
システム環境変数がこんな感じになっていたらOKです。

## train.py 実行時に ``OSError: [WinError 1455] ページング ファイルが小さすぎるため、この操作を完了できません。`` と言われる
仮想メモリサイズを増やしたら解決しました。
参考: [仮想メモリのサイズを変更する方法 | ドスパラ サポートFAQ よくあるご質問｜お客様の｢困った｣や｢知りたい｣にお応えします。 ](http://faq3.dospara.co.jp/faq/show/4546?site_domain=default)

仮想メモリが大きければ学習のスピードは上がりますが、その分ストレージを圧迫するのでバランスを考える必要があります。
react-responsiveの使い方

# はじめに
npmの`react-responsive`パッケージを使うと、Reactでのレスポンシブ対応が簡単にできることが分かったので、その使用方法について勉強したことを自分の備忘録として残しておきます。

https://www.npmjs.com/package/react-responsive

# パッケージのインストール

```terminal:ターミナル
% npm i react-responsive
...
...
...
% npm list | grep responsive
├── react-responsive@9.0.0-beta.6
```

> With Hooks
Hooks is a new feature available in 8.0.0!

とnpmのページに書いてあるように、`8.0.0`以上のバージョンではhooksとして使えるようになりました。

# 使い方

```tsx:index.tsx
import { useMediaQuery } from 'react-responsive'

const ResponsiveTest = () => {
  const isDesktop: boolean = useMediaQuery({ query: '(min-width: 768px)' })

  return (
    <>
      {/* 768px以上の時は、デスクトップ用のコンポーネントを表示 */}
      {isDesktop && <ForDesktopComponent />}
      {/* 768px未満の時は、 モバイル用のコンポーネントを表示 */}
      {!isDesktop && <ForMobileComponent />}
    </>
  )
}
```

このように、ユーザーが使用するデバイスの幅によってboolean値を取得でき、それに応じて表示するコンポーネントを切り替えられるようになっています。
また、
> To make things more idiomatic to react, you can use camel-cased shorthands to construct media queries.

とあるように、キャメルケースを使った短縮形でメディアクエリを書くこともできます。

```tsx:index.tsx
const isDesktop: boolean = useMediaQuery({ minWidth: 768 })
```

そしてこんな書き方も紹介されていました。

```tsx:index.tsx
import { useMediaQuery } from 'react-responsive'

const Desktop = ({ children }) => {
  const isDesktop = useMediaQuery({ minWidth: 768 })
  return isDesktop ? children : null
}
const Mobile = ({ children }) => {
  const isMobile = useMediaQuery({ maxWidth: 767 })
  return isMobile ? children : null
}

const ResponsiveTest = () => (
  <div>
    <Desktop>パソコン</Desktop>
    <Mobile>スマートフォン</Mobile>
  </div>
)

export default ResponsiveTest;
```

# まとめ
レスポンシブWebデザインを実現するためのメディアクエリをhooksを使って書けるのは非常に便利だと思いました。他にも、自動的に検出されるものとは異なるデバイス設定でコンポーネントをレンダリングする必要がある時、例えば、これらの設定が検出されないNode環境（SSR）やテストの際には、device propというのを使ってデバイスを強制的に指定することもできるそうです。
間違い等ありましたらご指摘お願いいたします。
「HTTP/HTTPSヘッダを利用しています」の意味が分かっていなかった頃の話　

## HTTP/HTTSヘッダを利用していたらどうなるの？
ブラウザで見られるようになります。

例えばAWSのSNSについて勉強しているときなど、タイトルのような文言が出てきますよね。そんな時に過去の私はふーんと流していましたが、ふーんと流さずにピンと来ていれば、ほんの少しだけ学習効率も上がったんじゃないのかなと思い、この記事を書いてみました。過去の私と同じシチュエーションでふーんとなっている方のお役に立てれば幸いです。

## そもそもHTTP/HTTPSって何？
プロトコルです。

プロトコルとはコンピュータの世界で使われる共通のルールです。たとえば自分のノートPCを日本のスタバに持ち込もうがアメリカのスタバに持ち込もうが、インターネットに接続してムフフな画像や動画を検索して閲覧できるわけです。国が違っても共通の仕組みでムフフコンテンツにたどり着けるのは、プロトコルが世界共通のルールだからです。

ここで本題です。HTTPはHyperTextTransfer Protocolという名称のプロトコルです。HTTPSはHTTPでの接続を暗号化したものです。HTTPSのSはSecureのSです。

では、ムフフコンテンツを見ていきましょう。
ムフフコンテンツを見るためには、誰かがインターネットにアップロードしてくれなければなりません。親切な人がムフフコンテンツをアップロードしてくれていることにしましょう。
![10_学習.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394378/4089b49e-aa8b-0b22-79b2-c52e6fbaba33.png)

さて、私たちはムフフコンテンツを閲覧したいです。まず、PCを立ち上げます。そして、「ブラウザを起動します」。ブラウザからムフフコンテンツを検索して、クリックすると、「ブラウザ越しにムフフコンテンツが表示」されます。
![20_学習.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394378/71ae6fbe-b0e0-91c7-214f-ff5975231889.png)

「インターネット上にアップロードされたデータ」を「ブラウザを通じて」閲覧することができましたね。ムフフコンテンツを見ているとき、ブラウザの上部に「http://~」や「https://~」を確認できると思います。この仕組みを支えているのがHTTPです。

そして最初の疑問に戻ります。
Q.HTTP/HTTPSヘッダを利用していたらどうなるの？
A.インターネット上に存在するコンテンツをブラウザで見られるようになります。

## その他
今回はインターネット越しにコンテンツを閲覧するという、上層レイヤの話だけにとどめていますが、PCのプラグをコンセントに差したところからムフフコンテンツの閲覧は始まります。ムフフコンテンツが我々の手にたどり着くまで、そこそこ長い旅をしているので、その過程についてはまた機会があれば書きたいと思います。
テスト実施の流れ

# テスト実施の流れ
テスト実施がどのような流れで行われるのか、その過程を５つ書いていこうと思います。

1. 準備
　テスト実施の前には、テスト対象そのものや、実施の方法、その環境などを準備する必要があります。具体的には「テスト対象のソフトウェア」「テストケース」「テストデータ」「テストデータ」「テスト環境」を用意します。

1. 確認
　具体的な操作などはテストケースに記載されていますが、それ以外にも「いつ」「何を」「誰が」を確認しなければテスト実施はできません。従って、テストケース内の「前提条件」「作業手順」「期待結果」に加え、テストケース外の「スケジュール」「テスト環境の内容」「報・連・相の対象」について確認する必要があります。

1. 実施
　テストケースに記載されている通りの「前提条件」を用意し、記載通りの「作業手順」でテスト対象のソフトウェアを操作したら、その実施結果を「期待結果」と比較します。比較の結果、両者が統一と判断できるならテストログ（テスト実施の結果を記録したもの。テストケースと一体のドキュメントとなっていることも多い）の記入欄に"OK"と記載し、次の項目に進みます。また比較の結果、両者が同一でないと判断で切るならばテストログに記入欄にNGと記載し、どのような事象であったのか開発担当者に報告します。

1. 報告
　実施結果と同一とならなかった場合、テストオペレーターはこれを不具合として開発担当者に報告しなければなりません。さらに「本当はこんな挙動でユーザーが満足するのだろうか」といったユーザーの要求を満たさないような実施結果も不具合として報告する必要があります。このような報告を「欠陥レポート」と呼びます。開発担当者は欠陥レポートの記載内容を参考にソフトウェアを修正します。（修正不要と判断される場合もあります。その場合テストログも修正され”OK”となります。）ですから欠陥レポートは、どのような不具合が、どのような常謙也手順で発生したのか、正確に把握できるようなドキュメントでなければなりません。

欠陥レポートを作る（これを「起票する」と表現します）前に必ず「作業手順」と「期待結果」を誤認していないかを確認します。さらに少なくとも３回は同じ操作を繰り返して不具合が再現するかをチェックするのが良いでしょう。

1. 改修確認
　欠陥レポートにより報告された不具合は、開発担当者によって修正されます。この修正されたソフトウェアを再確認するのもテストオペレーターの仕事です。ここで不具合が修正されたことが確認できたならばテストログの”NG”は再確認”OK”に変更されます。不具合が残っているようなうならば、再度欠陥レポートを起票し、開発担当者に修正を依頼します。

## まとめ
- テスト実施の流れには分岐や繰り返しがある。
- テストケースを正確に実施しつつ、ケース外の不具合に関しても積極的に報告する。
ブラウザで伏字になってるパスワードを強制的に表示する方法

## はじめに
ウェブサービスなどでアカウントを作成したり、ログインする時にパスワードを伏字で表示するのが当たり前となっていますが、
手入力すると「あれ、どこまで入力したっけ？」となることありませんか？
別のパソコン使ってログインするときだったり、特にスマホとかフリック入力してて間違えることはあるので表示してくれぇってたまに思います。
標準で切り替えて表示できるサイトはありますが、Qiitaなど対応していないサイトもたくさんあります。
そういったサイトで強制的に伏字を切り替える方法をご紹介したいなと思います。
※スマホの話しましたが今回はパソコンでのお話になります。

## そもそもなんで伏字になってんの？
後ろだったり脇から覗かれても大丈夫なように伏字にしているっていうのが一般的だと思います。
最近だとリモートワークも増えて、画面共有したときに間違ってログイン画面を映してもバレにくくするというのにも効果があるのかなと思います。
色々調べてみたんですがそれぐらいでした。

## 手順
##### １．伏字で表示されるサイトを表示
今回はQiitaで試します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156172/d7470d8f-78f4-b0e4-ed7f-22f9e8164c1d.png)

##### ２．ブラウザに標準搭載されている開発ツールを開く
F12押したら大体開くかも
※一応見なくていい所はちゃちゃっと加工で消しました。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156172/8f85e0a5-a9d9-3214-bf4f-9558f4b0cc36.png)

##### ３．パスワードを入力する<input>タグのtypeを変更する
開発ツールの左上にあるこのアイコンを押して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156172/b1548fbf-f5ff-5335-b796-8c5a00e31ba1.png)
パスワード入力部分をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156172/7486824a-c0da-ce22-e415-bff2bdf0df75.png)
そうすると該当部分のソースにジャンプするので、<input>タグのtypeをtextだったり空っぽにします。
* before
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156172/ccc6d54a-89e3-58e3-2930-8da9a7584680.png)
* after
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156172/cfb069d1-83e0-3b6c-6dd5-3393d8ecd84f.png)
すると伏字となっている部分が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156172/c6a5faff-d7c2-4934-0e22-f48617a22422.png)

## おわりに
是非とも自由に可視化出来るようにする機能を標準で実装してほしいですね。（特にスマホ）
ちなみに、自動保存されたパスワードに対しても表示可能になるので、家族などで共有して使っているパソコンの場合はお気を付けください。
AIにおけるリスクの分類の必要性


ビッグデータの台頭と情報の一般化された生産と消費は、私たちの社会の様相を変えましたが、その使用の影響についての認識も変えました。 

AIはこれまでこのような変化から恩恵を受けて来ましたが、グローバルイノベーションの主要な因子になりつつあります。 

- 私たちの社会の知的労働力を劇的に強化する 
- すべての科学分野における主要なボトルネックを打破する

現在、すべての業界で、AIは民主化の次の段階に入ろうとしています。そこでは、AIが明日の文明の柱となるであろうということは明白ですが、そのリスクはまだ誰もが理解していません。 
![gr-stocks-Iq9SaJezkOE-unsplash.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/772fddec-f3aa-751b-8ac4-3a42cecfb014.jpeg)


## リスクアセスメントをイノベーションのベクトルにする
一般に、リスクに関する発言は恐怖によって引き起こされます。AIを受け入れ、社会のあらゆる主要な側面にAIが存在するようになる世界に対する不確実性から生じる不安は、かなり理解しやすいと思います。 

これを、検索エンジン、インターネットインデックス作成技術、オンラインリソースへのアクセスの民主化など、以前の主要なデジタルイノベーションと比較すると、[クロード・シャノン](https://www.historyofdatascience.com/claude-shannon/?__hstc=186155446.7cf29593dfb8dfaddb981500e9719055.1646211075169.1647506544060.1647562855049.50&__hssc=186155446.9.1647562855049&__hsfp=1521802095)の次のような意見に同意し得ます。

<font color="LightSeaGreen">**「**</font>人工知能はGoogleの究極のバージョンになるでしょう。<font color="LightSeaGreen">**」**</font>

私たちのテクノロジーの現状における課題は、シャノン氏の信念が控えめであるように思えることです。AIが私たちの感覚や他の多くの認知能力の代わりとなる追加的な本能として作用したり、同僚やビジネスパートナーさえも仮想化することも考えられるのです。 

検索エンジンを利用したサービスとAIを利用したサービスとの信頼度の差は、オンラインサービスとのやり取りにおいてユーザー目線でのコントロール感があるかどうかに起因していると思われます。デジタル化される前のサービスには、まさにそのサービスから受け継いだ不文律やガイドラインが多く存在しました（売り手を警戒し、評判を確認したり、複数のソースの情報を相互検証したり、など）。同様のガイドラインをAIにも適用しようというのは、（データの専門家でない場合でも）以下の理由により、間違いなく、より困難です。 

- AIの実装とライフサイクルにおける[自動化](https://blog.dataiku.com/automation-in-data-science)の重要な役割とその（非常に大規模な）拡大
- 機械学習モデルの複雑さと多様性

AIに一般の人がアクセスできるようにする前に、ビジネスの状況や専門的なバックグラウンドに関係なく、誰もがそれぞれの状況に対して弱点や副作用、その起源、影響を特定できるようなシンプルな方法を構築し、共有することが必要です。 

現在、多くの扉が閉ざされたままになっており、多くの場所でイノベーションが滞っています。しかし、このようなフレームワークを、下記の役割が持つことができれば、これらの扉は開かれるかもしれません。

- 政府または特定領域における規制機関
- 各組織の指揮系統 - 何が問題なのかを明確に理解することができるようになるでしょう
- 一般有権者は- 自分たちが何にさらされているのか、時には強引な技術的侵略とみなされるものの限界は何なのか、最終的に知ることができること。

AIがもたらす社会の変化を受け入れる人々は、そのメリットとリスクを認識する必要があります。Everyday AIの時代を迎え、消費者は貢献者になり続けるでしょう。より多くの情報が得られることで、自律的に適切な判断をすることができるようになるのです。本シリーズの今後のブログでは、ソースデータ、AIモデルやサービスの実装、採用など、さまざまな段階でのリスクや影響の特定について解き明かしていく予定です。

<br>
<br>

#### MLとリスクについてさらに深く掘り下げたいですか？
O'Reillyによる書籍の初期リリースの章では、MLが運用者と消費者にどのようなリスクをもたらすかを強調し、実務担当者がそれらを回避するのに役立つ方法を紹介しています。
[こちらよりダウンロードいただけます(英語)](https://pages.dataiku.com/oreilly-responsible-ai)。

<br>
<br>

原文：[*The Necessity of Classifying Risks in AI*](https://blog.dataiku.com/the-necessity-of-classifying-risks-in-ai)
IBM Cloud: Transit GatewayのPrefix Filtering

# 1. はじめに
Transit Gatewayを使うことで、BGPのroute情報を表示するだけでなく、BGPで広告される経路のfilteringが可能になった。
https://cloud.ibm.com/docs/transit-gateway?topic=transit-gateway-adding-prefix-filters&interface=ui&locale=en

主な特徴は以下の通り。

- Connectionごとの設定。Direct Link/VPC/Classicの全てでprefix filteringは利用できる。GRE Tunnelに対しては適用されない。
- どのprefixをTransit Gatewayに広告するかを制御する。（各リソースからTransit Gatewayへの広告をフィルタリングするための機能であり、Transit Gatewayから各リソースへの広告を制御する機能ではない）
- denylist形式/allowlist形式が選べる。
- prefix filterの順番は重要であり、最初に適合したruleが採用される。
- 他アカウントのVPCなどと接続する際には、他アカウント側での承認が実施される前にprefix filteringを設定しておくこともできる。例えば、事前にDenyAllを設定しておくことにより、Transit Gateway接続時に予期せぬ経路の広告をあらかじめ避けることができる。
- prefix filterはLE値/GE値と組み合わせることにより柔軟な記述が可能。
- Transit Gatewayあたりprefix filterを設定できるのは2 Connectionまで。
- 1 Connectionあたりのprefix filter ruleは10個まで。
- この辺りのquotaはdefault値とのこと。増やしたければcase by caseでCaseを起票して相談することになる。

# 2. Prefix Filterのルールについて

Cisco機器の`ip prefix-list`コマンドの形式に似ている。
（参考）https://www.infraexpert.com/study/routecontrol07.html


## 例1. `10.0.0.0/8`を指定した時。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/5e6747b4-65a8-378b-ca93-afd713debdda.png)
以下の設定はデフォルトが`Deny all`のため、"10.0.0.0/8"というprefixのみが許可対象になる(先頭ビットが「10.」に合致した上で、prefix長が/16のルート）。Classic Infrastructureのサブネットマスク長は26-30で構成されていることが多く、このprefixルールだとどのClassic Infrastructureのsubnetも適合しないため、Classic InfrastructureからのBGP広告は何も許可されていないのと同等になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/5b95711c-9416-668a-c2eb-ca77c172c9eb.png)

## 例2. `10.0.0.0/8, GE=26, LE=28`を指定した時。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/fc4ddd36-c0a6-d91e-fddd-a980988f2c6c.png)

これだと、先頭ビットが「10.」に合致した上で、prefix長が/26, /27, /28のルートが許可対象となるため、

10.x.x.x/26
10.x.x.x/27
10.x.x.x/28

という形式のprefixが全て許可されるという意味になる。確かにClassic Infrastrutureからの/26, /27, /28のsubnetは以下のように広告されていることがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/e51dbe50-8ace-1934-a4ac-8a4ee6b4439f.png)
Anacondaの管理



**Anaconda Prompt** を使用した Windows10 における **Anaconda** の管理方法を紹介します。
紹介するコマンドは [Ubuntu](https://qiita.com/Mira_332/items/17aecde42befed51ec4c) の**端末**から実行することもできます。





## 環境
##### Windows10 x64
##### Ubuntu
- Distributor ID: Ubuntu
- Description: Ubuntu 20.04.4 LTS
- Release: 20.04
- Codename: focal


# コマンド一覧
#### アップデート
|目的|コマンド|
|:---: |:---: |
|Anaconda本体|conda update -n base conda|
|Anacondaのすべてのパッケージ|conda update --all|
|Anacondaの特定のパッケージ|conda update パッケージ名|

#### 削除
|目的|コマンド|
|:---: |:---: |
|不要ファイル|conda clean --all|
|不要パッケージ|conda uninstall パッケージ名|

#### インストール
|目的|コマンド|
|:---: |:---: |
|Anacondaに特定のバージョンをインストール|conda install パッケージ名 = X |


# 実行例

### 準備

スタートメニュー → Anaconda3 → **Anaconda Prompt** → **その他**（ Anaconda Prompt を**右クリック**で出現） →  **管理者として実行** の順で起動することができます。
![Anaconda Prompt.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339630/303621ba-2100-ddcf-c8f2-2e87e4ee9929.jpeg)
![Anaconda Promptを管理者で実行.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339630/45706063-0e2f-3d46-38ee-98e9f1bf07b9.jpeg)



:::note warn

大抵の場合、管理者で実行しなくとも問題ありませんが、稀にUACが作動する場合があります。
:::

## アップデート
#### Anaconda本体
`conda update -n base conda`をコピーして、Anaconda Prompt に貼り付けてください。
例：(base) C:\WINDOWS\system32> `conda update -n base conda`
```
(base) C:\WINDOWS\system32> conda update -n base conda




```


#### Anacondaのすべてのパッケージ
`conda update --all`をコピーして、Anaconda Prompt に貼り付けてください。
例：(base) C:\WINDOWS\system32> `conda update --all`
```
(base) C:\WINDOWS\system32> conda update --all




```




#### Anacondaの特定のパッケージ
`conda update パッケージ名`をコピーして、Anaconda Prompt に貼り付けてください。
例：(base) C:\WINDOWS\system32> `conda update パッケージ名`
```
(base) C:\WINDOWS\system32> conda update パッケージ名




```
##### 記入例( Python の場合)
例：(base) C:\WINDOWS\system32> `conda update python`

```
(base) C:\WINDOWS\system32> conda update python



```


## 削除
#### 不要ファイル
`conda clean --all`をコピーして、Anaconda Prompt に貼り付けてください。
例：(base) C:\WINDOWS\system32> `conda clean --all`
```
(base) C:\WINDOWS\system32> conda clean --all




```


#### 不要パッケージ

`conda uninstall パッケージ名`をコピーして、Anaconda Prompt に貼り付けてください。
例：(base) C:\WINDOWS\system32> `conda uninstall パッケージ名`
```
(base) C:\WINDOWS\system32> conda uninstall パッケージ名



```

##### 記入例( Python の場合)
例：(base) C:\WINDOWS\system32> `conda uninstall python`

```
(base) C:\WINDOWS\system32> conda uninstall python



```


## インストール
#### Anacondaに特定のバージョンをインストール
`conda install パッケージ名 = X `をコピーして、Anaconda Prompt に貼り付けてください。
例：(base) C:\WINDOWS\system32> `conda install パッケージ名 = X `
```
(base) C:\WINDOWS\system32> conda install パッケージ名 = X 



```
##### 記入例( Python3.6 の場合)
例：(base) C:\WINDOWS\system32>`conda install python=3.6`

```
(base) C:\WINDOWS\system32>conda install python=3.6



```

:::note info

基本形は パッケージ名 = X です。
Xにバージョン番号を当てはめることで様々なバージョンに対応できます。
:::

# 参考文献
https://qiita.com/kerobot/items/917dc7027e15f5ff75ac

https://weblabo.oscasierra.net/python-anaconda-clean/
JavaScriptのconstに関して

## 初めに
現在、JavaScriptでvarを使用している箇所をconst、letに置き換えているが、具体的にどのような場面で使用できるかが気になった。

constに関して参考文献から拝借した内容。

> 定数は、let キーワードを使って定義する変数と同様にブロックスコープを持ちます。定数の値は、再代入による変更ができず、再宣言もできません。

再代入、再定義は不可能であることが分かるが、配列へのプッシュやブロックがある場合の挙動が知りたかったのでアウトプットのため投稿する。

## 実行環境
■ Node.js
v11.1.0


### 配列でconstを使用

新しい要素のプッシュは成功する。

```js
const a = [];
a.push("a");
console.log(a);

// 出力結果
[ 'a' ]
```

新しい配列を代入するとエラーになる。

```js
const a = [];
a = [];
console.log(a);

// 出力結果
TypeError: Assignment to constant variable.
```

### オブジェクトでconstを使用

オブジェクトのプロパティの追加は正常に動作する。

```js
const a = {b: "b"};
a.c = "c";
console.log(a);

// 出力結果
{ b: 'b', c: 'c' }
```

新しいオブジェクトを代入するとエラーになる。

```js
const a = {b: "b"};
a = {c: "c"};
console.log(a);

// 出力結果
TypeError: Assignment to constant variable.
```



### for文でconstを使用

for...of文の場合、iは定数でも可能である。

```js
const arr = ["a","b","c"];
for(const i of arr) {
 console.log(i);
}

// 出力結果
a
b
c
```

for...in文の場合も正常に動作する。


```js
const obj = {"a": 1,"b": 2,"c": 3};
for(const i in obj) {
 console.log(i);
}

// 出力結果
a
b
c
```

以下のfor文は、初期化式で使用している定数iを加算式にてインクリメント演算子を使用しているため、ループが実行される前にエラーになる。


```js
for(const i = 0; 0 < 5; i++){
  console.log(i);
}

// 出力結果
TypeError: Assignment to constant variable.
```


### ブロックがある場合のconst

下記だと、ブロック内外どちらも参照できる

```js
const a = "a";
{
  console.log(a);
}
console.log(a);

// 出力結果
a
a
```

下記は、ブロック内外で同じ名前の定数を代入している。
そのため、最下部で参照する定数aの値はブロック外で定義した「"a"」という文字列になり、ブロック内で参照する定数aの値はブロック内で定義した「"block"」という文字列になる。
また、ブロック内で定義した定数のスコープはブロック内のみである。

```js
const a = "a";
{
  const a = "block";
  console.log(a);
}
console.log(a);

// 出力結果
block
a
```

上記を踏まえると、下記は、定数aをスコープ外で参照しているためエラーになる。

```js
{
  const a = "block";
  console.log(a);
}
console.log(a);

// 出力結果
ReferenceError: a is not defined
```

## 関数を使用した場合のconst

以下だと、各関数のブロック内にスコープを持った定数が作成されるため、エラーにならずに正常に動作する。

```js
const aFunc = ()=> {
    const c = "aFuncの処理";
    bfunc();
    console.log(c);
}

const bfunc = ()=> {
    const c = "bfuncの処理";
    console.log(c);
}
aFunc();

//　出力 
bfuncの処理
aFuncの処理
```

以下を確認すると、1回目の呼び出しと2回目の呼び出しで定数を代入可能であることが分かる。

```js
const aFunc = (num)=> {
    const c = num;
    console.log(c);
}

aFunc("1回目");
aFunc("2回目");

//出力
1回目
2回目
```

## 参考文献
[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const)
工学のための関数解析（凸射影）

### はじめに

「工学のための関数解析」のp.207の例１閉凸集合への二乗距離関数の凸性と微分(b)の証明で躓いたので、躓いた点を備忘録として残しておきます。理解できているか不安なので、間違いがあればコメント等で教えて頂ければ幸いです。

### 凸射影について

任意の$x\in\mathcal{H}$に対して

$$
d(x,C):=\inf_{y\in C}\||x-y\||=\||x-P_C(x)\||=\min_{y\in C}\||x-y\||
$$

を満たす唯一の点$P_C(x)\in C$が存在する。

$d(x,C)$を点$x$と集合$C$間の距離と呼ぶ。

写像$P_C:\mathcal{H}\rightarrow C , \ x\rightarrow P_C(x)$を凸射影という。


<img width=30%><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/0437d009-5115-b4fa-e6a3-09e656c8b5f4.png" width=40%>

### 躓きポイント１

$\||x-P_C(x+h)\||\geq \||x-P_C(x)\||$

$\||x-P_C(x)\||$は$\||x-P_C(x)\||$が最小となるように点$P_C(x)$が定まり点$x$との距離が決まる。一方で、$\||x-P_C(x+h)\||$は$\||x+h-P_C(x+h)\||$が最小となるように点$P_C(x+h)$が定まり点$x$との距離が決まる。そのため、$\||x-P_C(x+h)\||$は$\||x-P_C(x)\||$よりも点$x$との距離が大きくなることがわかる。

<img width=25%><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/bf768098-15d2-c688-4d88-de3e0497d2a4.png" width=50%>


### 躓きポイント２

$\left||x+h-P_C(x+h)\right||\leq\||x+h-P_C(x)\||$

$\||x+h-P_C(x+h)\||$は$\||x+h-P_C(x+h)\||$が最小となるように点$P_C(x+h)$が定まり点$x+h$との距離が決まる。一方で、$\||x+h-P_C(x)\||$は$\||x-P_C(x)\||$が最小となるように点$P_C(x)$が定まり点$x+h$との距離が決まる。そのため、$\||x+h-P_C(x)\||$は$\||x+h-P_C(x+h)\||$よりも点$x+h$との距離が大きくなることがわかる。


<img width=25%><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/15a394d5-250d-d77d-326f-78ca8dbbf919.png" width=50%>
【Android】DrawableからBitmapに変換

# png → bitmap
```Kotlin
fun getBitmap(@DrawableRes drawableRes: Int) =
 BitmapFactory.decodeResource(context.resources, drawableRes)
```

# xml → bitmap
```Kotlin
fun getBitmap(@DrawableRes drawableRes: Int): Bitmap? {
	val drawable = getDrawable(context, drawableRes) ?: return null
	val canvas = Canvas()
	val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
	canvas.setBitmap(bitmap)
	drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
	drawable.draw(canvas)
	return bitmap
}
```

[参考サイト](https://stackoverflow.com/questions/10111073/how-to-get-a-bitmap-from-a-drawable-defined-in-a-xml)