OmniAICreator/Qiita-1.07M huggingface dataset:
[備忘録]TortoiseSVN ログイン時における注意点

# 備忘録

忘れた時のために必要な情報を書き留めておくメモ

# TortoiseSVN ログイン時における注意点

TortoiseSVNを使用していて、自分のアカウントでログインしているはずなのに
別のアカウントでログインしている状態になる。

ログイン時に「資格情報を記憶する」を押してしまうと、ログイン時のデータを保存してしまうので注意が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/a25b6100-19ca-221a-9c5c-b5889a816359.png)

# 解決方法

設定ウィンドウより保存されたデータ　→　認証データを削除する。

この後、ログインし直せばOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/9996d048-aea4-83e7-6e8d-d5ea5aa73cfa.png)


SVNの使い方を他の方に教えたり、教えられたりしている時にやってしまうので注意が必要



こちらの記事を参考にさせていただきました。

https://schima.hatenablog.com/entry/20090604/1244119240
maxScriptでトレイルを作ってみた

スクリプトで板ポリを作る機会がありましたので、その副産物としてトレイルを作ってみました。
あまり高機能ではありませんが、とりあえずっという時や、レンダーファームのインストールが面倒な時など、お使いください。

```maxScript:CreateTrail.ms
fn createTrail obj  widthsize segmentcount axis startframe endframe =(
	--createTrailObject
		trailobj = editable_mesh name:(uniqueName "trailObject")
		convertToPoly  trailobj
			
		pos = obj.position +  obj.transform[axis] * widthSize 
		polyop.createVert trailobj  pos
		
		pos =obj.position 
		polyop.createVert trailobj  pos
		
		pos =obj.position  + obj.transform[axis] * -widthSize 
		polyop.createVert trailobj  pos
		
		for i = 2 to segmentCount do (
			pos = obj.position +  obj.transform[axis] * widthSize 
			polyop.createVert trailobj  pos
			
			pos =obj.position 
			polyop.createVert trailobj  pos
			
			pos =obj.position  + obj.transform[axis] * -widthSize 
			polyvertcount = polyop.createVert trailobj  pos
			polynum = polyvertcount  - 6
			
			polyop.createPolygon trailobj #(polynum + 1,polynum+  4, polynum + 5,polynum + 2)
			polyop.createPolygon trailobj #(polynum + 2,polynum + 5,polynum + 6,polynum + 3)
		)
		
		--animated trail 
		positionBuffer = #()
		for currentFrame  = startframe  to endframe do (
			animate on (
				at time currentFrame  (
						posA = obj.position +  obj.transform[axis] * widthSize 
						posB =obj.position 
						posC =obj.position  + obj.transform[axis] * -widthSize 
						append positionBuffer #(posA,posB,posC)
					for i =1 to segmentcount do ( 
						vertnum = (i - 1 ) * 3 
						bufferID = positionBuffer.count - i  + 1 
						
						if bufferID > 0 then (
						polyop.setvert trailobj (vertnum + 1 )  positionBuffer[bufferID][1]
						polyop.setvert trailobj (vertnum + 2 )  positionBuffer[bufferID][2]
						polyop.setvert trailobj (vertnum + 3 )  positionBuffer[bufferID][3]
						)
					)
				)	
			)
		)
	)




rollout createTrailSetRO  "Settings"
(
	spinner widthsp "Width" value:2.5
	
	spinner segsp "Segment"  type:#integer value:10
	spinner startFsp "StartFrame"  type:#integer  value:1
	spinner endFsp "EndFrame"  type:#integer value:100
	
	radiobuttons  axisRadioBtn  "Axis" labels:#("X","Y","Z") default:1
	multiListBox mlb "MultiListBox" 
	button nodeAddBtn "ADD" across:2
	button nodeRemovebtn "Remove" 
	button RuningBtn "Runinng"
	label laba "Create Trail v1.00 2023.0425  Fudie"
	on pickbtn picked obj  do (
		pickbtn.text = obj.name 
	)
	on nodeAddBtn pressed do (
		items = mlb.items  as array 
		print mlb.items
		
		for obj in selection do (
			appendIfUnique items   obj.name
		)
		mlb.items = items
		
	)
	on nodeRemovebtn pressed do (
		  sellist = mlb.selection as array 
			items = mlb.items 
		for i = 1  to sellist.count do (
			deleteItem  items sellist[  sellist.count + 1 - i ]
		)
		mlb.items  =  items 
		mlb.selection  = #{}
	)
	
	on RuningBtn pressed do (
		for objname = mlb.items do (
			slidertime = startFsp.value
			obj = getnodebyname objname 
			createTrail obj widthsp.value segsp.value axisRadioBtn.state  startFsp.value endFsp.value 
		)
		
	)		
)
rof=newrolloutfloater "CreateTrail" 300 380
addrollout createTrailSetRO rof

```
SFTPのバッチ処理

Linxuで構築したSFTPサーバに対して、クライアントのバッチプログラムでSFTPコマンドでファイル取得を行った。

### 環境
CentOS 7.9
Windows 10

### コマンドについて
1\.公開鍵認証方式で接続するため、-iに指定した秘密鍵に対応する、公開鍵をログインユーザ（以下ではsftpuser）のホームディレクトリに.ssh/authorized_keysとして配置。

2\.初回接続時のホスト鍵を無視するため。StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/nullを設定しています。

3\.sftpコマンドの-bには、実行するコマンドを書いたファイルを指定。'-'は標準入力。

#### Linux
Linuxでは、ヒアドキュメントを使用してコマンドを渡しました。

```bash
sftp -b - -i id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null sftpuser@host <<EOS
get FILE SAVE
quit
EOS
```

#### Windows
Windowsでは、パイプを通してコマンドを渡しました。
```batch
(
echo get FILE SAVE
echo quit
) | sftp -b - -i id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null sftpuser@host 
```
Laravel の419エラーの解決法

# このエラーの背景
ユーザーの編集機能を作っていたときに419のエラーが発生しました。
最初はエラーが謎すぎて詰まってしまいましたが、記事を見つけて解決できました。

# エラー画面


![スクリーンショット 2023-04-25 9.12.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/1ce52ea5-323b-b7ed-c564-cdd3feb3d947.png)

# エラー原因
調べてみたらLaravelが持つtokenの値とPOSTする_tokenパラメータが一致しないことが原因みたいです。

# 解決策
```@csrfがbladeに無いかformの外側になっていた```ことが原因でした。
これが圧倒的に多いみたいです。自分の場合です。

```edit.blade.php
@extends('layouts.app')
@section('content')
    <h2 class="mt-5 mb-3">ユーザ情報を編集する</h2>
    @csrf
    <form method="POST" action="{{ route('users.update', $user->id) }}">
    @method('PUT')
    @include('commons.error_messages')
//省略
```
こんな感じでした。以下に修正しました。
```edit.blade.php
@extends('layouts.app')
@section('content')
    <h2 class="mt-5 mb-3">ユーザ情報を編集する</h2>
    <form method="POST" action="{{ route('users.update', $user->id) }}">
    @csrf
    @method('PUT')
    @include('commons.error_messages')
//省略
```
これで解決しました。1番多い原因みたいです。

# 他の原因と解決法
1.単純なセッションの期限切れ
ブラウザを更新すると解決できるみたいです。

2.ブラウザの再起動
文字通りブラウザの再起動です。


3.configのキャッシュが残っている
キャッシュクリアをする必要があります。

```
php artisan cache:clear 
php artisan config:clear
```



詳しくは参考資料を読んでください。


# 資料

https://programing-school.work/laravel-419-csrf-error/
JavaScriptで文字列の配列をエスケープしつつ<br>でつなげる

```json
["こんにちは", "<script>", "さようなら"]
```

のような文字列の配列を、Webブラウザーに

```text
こんにちは
<script>
さようなら
```

と出力するように、

```json
"こんにちは<br>&lt;script&gt;<br>さようなら"
```

と変換したいとする。いろいろな方法があるけれど、以下が簡単。

```javascript
function escapeAndJoinWithBr(arr) {
  const span = document.createElement('span');
  span.innerText = arr.join('\n');
  return span.innerHTML;
}
```
参考: [HTMLElement.innerText](https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/innerText)

> セッターとしては、この要素の子要素を指定された値で置き換え、すべての改行を `<br>` 要素に変換します。
SAPパフォーマンス

# 前提
CPUやメモリの使用率に問題がない場合に、SAPのパフォーマンス（例：トランの登録が通常より遅い）悪化している場合に、具体的に何を確認しないといけないかを備忘のために整理。

## プロセス数（ワークプロセス数, WP)
Tr-cd：SM50

上記コードから、使用しているワークプロセス数を確認可能。
CPUやメモリ使用量に問題がない場合は、ここから確認してみる。

## ジョブの優先度設定
例えばJP1のジョブスケジューラーを使用している場合に、ジョブごとに優先して処理する設定が存在する。

## 多重度確認
・親ジョブ→子ジョブで多重度を分けて処理させる
　（例：品目コードの末尾（1-9)の10多重度で並列実行）
　POINT:なるべく多重度で動かすデータ件数を平準化させる条件が必要

・多重度を上げても、SAPが裏で更新できるワークプロセス数は限界があるため、各環境のワークプロセス数や多重度の関係を把握する。
（自チーム以外のジョブとバッティングすることでワークプロセス数の取り合いになるケースもあるので、パフォーマンス検討の際に、対象のPGM・ジョブとワークプロセス数の関係性の整理が必要）


---
### 参考)一般的なSAPの取込の流れ
|周辺Sys||ETLツール||SAP|
|:---|:--|:--|:--|:--|
|フロントシステム|→|ファイル連携|→|IF WORK(中間アドオンTBL)　→　SAP登録|
|a|b||||
|c|d||||
要件定義の進め方

# 前提

・対応スコープの検討
・全体のシステム図の作成
・（新規システムの導入の場合）既存システムの情報整理と新規システム導入の際のFit&Gap
・体制図、対象システムの担当者決め(PIC)
・リスク管理
・4ランドスケープでの検証が前提


# 具体的な対応
#1.データバリエーション
・フロントシステムで発生する業務のバリエーションを洗い出す
　その際に、#2のデータを事実に、業務側にヒアリングを行なってバリエーションの妥当性をデータをもとに要件整理

#2.フロントシステムのデータ連携
・過去の発生データをチェック。
　フロントシステムでしか確認できないものは、クラウドにデータを集約する必要がある。
  ※業務側にデータ確認依頼をするとリードタイムがかかるので、なるべくシステム部門側でデータの確認とバリエーション整理を行うことで、要件確定のリードタイムを減らすことができる

#3.データのボリューム確認
・ボリュームに応じて、システム環境構築のスペック検討。
　また、他のシステムに相乗りする場合に、他のシステムの容量を食ってプロセス枯渇に陥らないか確認

#4.月次や四半期、年次のジョブを並行稼働環境でテスト
・並行稼働でテストできないイベントに対して、並行稼働期間中でボリュームテストを実施し、タイミングも実際の発生タイミングに合わせて、並行稼働環境でワークプロセス数や処理時間に影響がないことを確認


# 稼働判定
・稼働判定時の合格条件を明確化
（例：フロントシステムの売上金額と新規システムの売上金額の一致）

・不具合/課題管理表の状況を共有
　→残課題に対しては、5W1Hで着地点を明確化

# 稼働後
本番稼働後のCPプラン（Contengency Plan)を計画

・切替後に稼働後検証の基準を明確にする
→基準未達の場合に、CPプランを発動する（
タワーデフェンスゲーム　Unity　敵の機能　7/10 HPバーの作成　オブジェクトの上に生成するように実装

# 概要
前回の続きです。

https://qiita.com/RYA234/items/f4af52f2bfa8538bf6b1

今回は敵オブジェクト上部にHPバーを実装します。
以下gifアニメ
![neoatlas.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/8b0e8cc9-81a8-c59b-587d-752392184bcf.gif)

次へ

https://qiita.com/RYA234/items/b1f54272c1d63d95d859


# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
# EnemyObject
HPバーのポジションオブジェクトを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ee6889c7-09ad-63b5-b4a6-e51fcb75e2d7.png)


# HealthCanvas
新規にHPバーのプレハブを作成します。
uGuiで作ってます。
（作り方がややこしかった記憶　詳細は動画観たほうが早いです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/f6ae34f5-9f99-41a5-582f-02c62dc6af75.png)





# 実装のポイント
新規にEnemyHealthクラスを作成します。
EnemyHealthクラスではHPバーをEnemyObjectで定義した位置に生成します。
EnemyHealthはEnemyObjectにアタッチします。（Enemyクラスと同じとも）


# コード部分
```diff_c_sharp:test.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyHealth : MonoBehaviour
{
    // Start is called before the first frame update
    [SerializeField] private GameObject healthBarPrefab;
    [SerializeField] private Transform barPosition;

    [SerializeField] private float initialHealth = 10f;
    [SerializeField] private float maxHealth = 10f;

    void Start()
    {
        CreateHealthBar();
    }


    private void CreateHealthBar()
    {
        GameObject newBar = Instantiate(healthBarPrefab,barPosition.position,Quaternion.identity);
        newBar.transform.SetParent(transform);
    }
}


```


# 参考

Section4 17

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/22979824#content


github コミット分

https://github.com/RYA234/2DTowerDeffenceMyLearning/commit/5ab080eb7f7a9d7f8c9f3af50435d76ee07d4532


章まとめ

https://qiita.com/RYA234/private/6d878a7958a3c760c8af
Nuxt3でimgタグのsrc属性に変数を使えない問題の回避策

## 🤔 発生した問題
imgタグのsrc要素を静的に指定するとWebpackによりモジュールとして読み込まれる。
一方、src属性に`v-bind`を使い動的に指定するとそのままのパスとして扱われる。
この違いにより、何も考えずにsrcに変数を渡すと404エラーが発生してしまう。
```vue
<script setup>
    const fileName = 'img-1';
</script>

<template>
    <!-- 変数を展開せずにファイル名を指定すると表示される -->
    <img :src="~/assets/images/img-1.png" />

    <!-- 変数を展開しても画像ファイルが表示されない -->
    <img :src="`~/assets/images/${fileName}.png`" />
</template>
```

## 💡 解決法1
`import.meta.glob`を使う。
```vue
<script setup lang="ts">
import { filename } from 'pathe/utils';

const glob = import.meta.glob('~/assets/images/*.png', { eager: true });
const images = Object.fromEntries(
  Object.entries(glob).map(([key, value]) => [filename(key), value.default])
);

const dynamic_image_name = 'img-1';
</script>

<template>
  <img :src="images[dynamic_image_name]" alt="Discover Nuxt 3" />
</template>
```
`import.meta.glob`はVite.jsで提供されている関数みたいで、ファイルシステムからのモジュールのインポートをサポートしているらしい。
詳しくは参考リンクを参照のこと（[参考](https://vitejs.dev/guide/features.html#glob-import)）。

## 💡 解決法2
動的インポート`import()`を使う。
```vue
<script setup lang="ts">
  const imageName = 'img-1'

  let image = {}
  try {
    image = await import(`~/assets/img/${imageName}.png`)
  } catch (e) {
    console.log(e)
  }
</script>

<template>
  <img :src="image.default" />
</template>
```
注意として、Vite内で使っているRollupの都合上、`import()`の引数が「変数で始まってはいけない」とか、「拡張子で終わらなければいけない」とか制約が色々ある。
詳しくは参考リンクを参照のこと（[参考](https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations)）。

## Nuxt3で使えなかった解決法
`require()`を使う。
```vue
<script setup>
    const fileName = 'img-1';
</script>

<template>
    <!-- require()で囲ってあげる -->
    <img :src="require(`~/assets/images/${fileName}.png`)" />
</template>
```
これにより、モジュールとして読み込んでくれる。
だが、viteだと`require()`が使えないのでこの方法は採れなかった。

## 参考
[Vue.jsで画像のsrcに変数を使ったら画像が表示されない - Qiita](https://qiita.com/yusuke1209kitamura/items/fa92ab869ac4955b47d8)
[【Vue.js】imgタグのsrc要素は指定の仕方によって読み込み方が違う - Qiita](https://qiita.com/coppieee/items/4260bd0af246aebf5557)
[require is not defined · Issue #12797 · nuxt/nuxt · GitHub](https://github.com/nuxt/nuxt/issues/12797)
[Assets with dynamic names are not resolved · Issue #14766 · nuxt/nuxt · GitHub](https://github.com/nuxt/nuxt/issues/14766)
[Nuxt - Starter (forked) - StackBlitz](https://stackblitz.com/edit/github-pq8nym-aoavsh?file=app.vue)
[plugins/packages/dynamic-import-vars at master · rollup/plugins · GitHub](https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations)
[Features | Vite (vitejs.dev)](https://vitejs.dev/guide/features.html)
備忘

備忘です　

Option Explicit

Sub UploadFile()
    Const strURL As String = "http://127.0.0.1:5000/upload"
    Const strFile As String = "C:\path\to\your\file.jpg"
    Dim objHTTP As Object
    Dim objFSO As Object
    Dim objFile As Object
    Dim strBoundary As String
    Dim strBody As String
    Dim arrBytes() As Byte
    Dim lngBytes As Long

    ' Random boundary string
    strBoundary = "---------------------------" & Replace(Replace(Replace(Now(), ":", ""), "-", ""), " ", "")

    ' Read the file data into a byte array
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.GetFile(strFile)
    lngBytes = objFile.Size
    ReDim arrBytes(lngBytes)
    With objFile.OpenAsTextStream(1, -2)
        .Read lngBytes
        .Close
    End With

    ' Create the request body
    strBody = BuildRequestBody(strBoundary, "example", strFile, arrBytes, lngBytes)

    ' Send the request
    Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
    With objHTTP
        .Open "POST", strURL, False
        .setRequestHeader "Content-Type", "multipart/form-data; boundary=" & strBoundary
        .send strBody
        Debug.Print .Status & " " & .statusText
        Debug.Print .responseText
    End With
End Sub

Function BuildRequestBody(ByVal strBoundary As String, ByVal strFileField As String, ByVal strFile As String, ByRef arrBytes() As Byte, ByVal lngBytes As Long) As String
    Dim strCrLf As String
    Dim strHeader As String
    Dim strFooter As String
    Dim binaryData As String
    Dim objStream As Object

    strCrLf = vbCrLf

    strHeader = "--" & strBoundary & strCrLf & _
                "Content-Disposition: form-data; name=""" & strFileField & """; filename=""" & Mid(strFile, InStrRev(strFile, "\") + 1) & """" & strCrLf & _
                "Content-Type: application/octet-stream" & strCrLf & strCrLf

    strFooter = strCrLf & "--" & strBoundary & "--" & strCrLf

    Set objStream = CreateObject("ADODB.Stream")
    objStream.Type = 1 ' adTypeBinary
    objStream.Open
    objStream.Write arrBytes
    objStream.Position = 0
    objStream.Type
    objStream.Type = 2 ' adTypeText
    objStream.Charset = "iso-8859-1"
    binaryData = objStream.ReadText
    objStream.Close

    ' Combine the header, binary data, and footer to create the request body
    BuildRequestBody = strHeader & binaryData & strFooter
End Function
vbsの作法 その62

# 概要
vbsの作法、調べてみた。
練習問題、やってみた。

# 練習問題
Windows11でInternet Explorer11を起動して、イベントを取得せよ。

# サンプルコード

```


Dim objIE
Set objIE = WScript.CreateObject("InternetExplorer.Application", "IE11_")
objIE.Visible = True
objIE.Navigate "about:blank"

Do
  WScript.Sleep 200
Loop

Sub IE11_BeforeNavigate(browser, url, flags, target, postdata, headers, cancel)
	msgbox "BeforeNavigate"
End Sub

Sub IE11_BeforeNavigate2(browser, url, flags, target, postdata, headers, cancel)
	msgbox "BeforeNavigate2"
End Sub

Sub IE11_DocumentComplete(browser, url)
	msgbox "DocumentComplete"
End Sub

Sub IE11_DownloadBegin()
	msgbox "DownloadBegin"
End Sub

Sub IE11_DownloadComplete()
	msgbox "DownloadComplete"
End Sub

Sub IE11_FileDownload(ActiveDocument, Cancel)
	msgbox "FileDownload"
End Sub

Sub IE11_NavigateComplete(browser, url)
	msgbox "NavigateComplete"
End Sub

Sub IE11_NavigateComplete2(browser, url)
	msgbox "NavigateComplete2"
End Sub

Sub IE11_NavigateError(browser, url, target, status, cancel)
	msgbox "NavigateError"
End Sub

Sub IE11_NewProcess(lCauseFlag, pWB2, Cancel)
	msgbox "NewProcess"
End Sub

Sub IE11_NewWindow(browser, Cancel)
	msgbox "NewWindow"
End Sub

Sub IE11_NewWindow2(browser, Cancel)
	msgbox "NewWindow2"
End Sub

Sub IE11_NewWindow3(browser, Cancel, dwFlags, bstrUrlContext, bstrUrl)
	msgbox "NewWindow3"
End Sub

Sub IE11_OnFullScreen(FullScreen)
	msgbox "OnFullScreen"
End Sub

Sub IE11_OnMenuBar(MenuBar)
	msgbox "OnMenuBar"
End Sub

Sub IE11_OnQuit()
	msgbox "Internet Explorerが閉じられました。"
	Set objIE = Nothing
	WScript.Quit() 'スクリプトの終了
End Sub

Sub IE11_OnStatusBar(StatusBar)
	msgbox "OnStatusBar"
End Sub

Sub IE11_OnTheaterMode(TheaterMode)
	msgbox "OnTheaterMode"
End Sub

Sub IE11_OnToolBar(ToolBar)
	msgbox "OnToolBar"
End Sub

Sub IE11_OnVisible(vVisible)
	msgbox "OnVisible"
End Sub

Sub IE11_PrintTemplateInstantiation(browser)
	msgbox "PrintTemplateInstantiation"
End Sub

Sub IE11_PrintTemplateTeardown(browser)
	msgbox "PrintTemplateTeardown"
End Sub

Sub IE11_PrivacyImpactedStateChange(bPrivacyImpacted)
	msgbox "PrivacyImpactedStateChange"
End Sub

Sub IE11_PropertyChange(sProperty)
	msgbox "PropertyChange"
End Sub

Sub IE11_RedirectXDomainBlocked(browser, url, RedirectURL, Frame, StatusCode)
	msgbox "RedirectXDomainBlocked"
End Sub

Sub IE11_SetPhishingFilterStatus(PhishingFilterStatus)
	msgbox "SetPhishingFilterStatus"
End Sub

Sub IE11_SetSecureLockIcon(SecureLockIcon)
	msgbox "SetSecureLockIcon"
End Sub

Sub IE11_StatusTextChange(sText )
	msgbox "StatusTextChange"
End Sub

Sub IE11_ThirdPartyUrlBlocked(URL, dwCount)
	msgbox "ThirdPartyUrlBlocked"
End Sub

Sub IE11_TitleChange(sText)
	msgbox "TitleChange"
End Sub

Sub IE11_UpdatePageStatus()
	msgbox "UpdatePageStatus"
End Sub

Sub IE11_WindowActivate()
	msgbox "WindowActivate"
End Sub

Sub IE11_WindowMove()
	msgbox "WindowMove"
End Sub

Sub IE11_WindowResize()
	msgbox "WindowResize"
End Sub

Sub IE11_WindowStateChanged(dwFlags, dwValidFlagsMask)
	msgbox "WindowStateChanged"
End Sub





```

以上。
Falconでdeploy時にログの出力形式を変更する方法

Ruby製のWebサーバーであるFalconでログの出力形式を変更する方法をメモしておきます。

Falconはserveで使うとターミナルにテキスト形式のログを出力しますが、デプロイ時のhostモードでは動作環境によってはJSON形式になるようです。この出力形式を明示的に設定するには`CONSOLE_OUTPUT`環境変数を指定します。
例えばテキスト形式にするには以下の通りです
```sh
CONSOLE_OUTPUT=Text
```
【VBA Personal】Excelシートをショートカットキーで方眼紙化するマクロ

!!編集中のため、現在この記事のコードは参照しないようにしてください

# PERSONALに追加する
下記のコードをVBEのPERSONALに追加してください

※PERSONALについて知らない方は下記の記事を参考
https://vbabeginner.net/how-to-create-a-personal-macro-book/


```vb
Option Explicit
'----------------------------------------------------------------
'Key             :  Code
'----------------------------------------------------------------
'Shift            : + (正符号)  他キーと組み合わせで使用
'Ctrl              : ^ (カレット)    他キーと組み合わせで使用
'Alt               : % (パーセント記号)  他キーと組み合わせで使用
'----------------------------------------------------------------
'a~z             :  {a} ~ {z}
'Enter           :  {ENTER}
'F1~F15       :  {F1} ~ {F15}
'Esc              :  {ESC}
'BackSpace  :  {BACKSPACE} {BS}
'Break          :  {BREAK}
'CapsLock     :  {CAPSLOCK}
'Clear           :  {CLEAR}
'Delete         :  {DELETE}
'End             :  {END}
'Home          :  {HOME}
'Ins              : {INSERT}
'PageDown   :  {PGDN}
'PageUp       :  {PGUP}
'Tab             :  {TAB}
'↓                :  {DOWN}
'←                :  {LEFT}
'→                :  {RIGHT}
'↑                :  {UP}
'----------------------------------------------------------------

Public Sub squareAllCells()

    Application.OnKey "+^{j}", "squareAllCells"
    
    Dim pixel As Variant
    Dim width As Long
    Dim height As Long
    
    pixel = InputBox("How many pixels do you want?")
    If IsNumeric(pixel) = False Then
        Exit Sub
    End If
    
    height = pixel * 0.6
    width = pixel * 0.10956
    
    Cells.Select
    Selection.RowHeight = height
    Selection.ColumnWidth = width

End Sub

```

# ショートカットキーについて
Application.OnKey "+^{j}", "squareAllCells"　のところは好きなショートカットに変えてください。
ショートカットの記述方法は「Application.OnKey」で調べればすぐ出てきますし、上のコメントブロックにも記載しています。

# 実行時の挙動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734868/54367c1a-b1bc-9ac6-a2d4-26a3b4b70750.png)


①設定したショートカットキーをシートの上で入力するとインプットボックスが表示されます

②任意のpixel数を入力し「OK」

③対象のシートの各セルの縦横が変更されます

※入力値が数値以外またはキャンセルを押したときは処理を終了します


30pixel前後だといい感じなんですが、数値が小さすぎたり大きすぎたりすると正方形じゃなくなってきます。
そのあたりはpixelの計算式をうまいこと調整してください。



↓ちなみに「30」を入力して実行するとこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734868/499cab4e-5f39-244e-5036-68c404131a52.png)
java初心者が行く～Scanner～

# はじめに
java初心者が備忘録的な感じで書いています．
間違ったこと書いていたらコメントで指摘してくれると助かります．

# Scanner
入力を求めるときはc言語だとscanfだけでよかったのにjavaはなんか長くねと最初は思ってた．
改善前はいちいち

```java
int input = new java.util.Scanner(System.in).nextInt();
```

と書いていて正直面倒だった．
しかし複数回Scannerを使う場合以下の方法で書けば楽になる．

```java
import java.util.Scanner;

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int input = scanner.nextInt();
```

なにをしているかというと，まずjava.util.Scannerをimportし，その後scannerインスタンスを生成し，コンストラクタの引数にSystem.inを指定する．最後にscannerインスタンスのnextIntメソッドを呼び出しているという流れである．

scannerが一つだけだと書く分量はあまり変わらないが，複数回各場面ではかなり有効になるのではないでしょうか，，，
.NET MAUIでのCtrl+Enterなどのキーイベントハンドリングの難しさ

.NET MAUIは、クロスプラットフォームのアプリケーション開発を容易にするためのフレームワークです。しかし、現状では、Ctrl+Enterなどのキーイベントを簡単にハンドリングする方法が見つからないことがあります。本記事では、.NET MAUIでCtrl+Enterキーイベントを発生させる方法について探ります。また、他の開発環境ではどのように実現されるかも概説します。

1. まず、.NET MAUIには`KeyDown`や`KeyPress`イベントが見つからないことがわかりました。
    これにより、キーイベントに対応するのが難しくなっています。

2. 次に、カスタムエディタを作成しようと試みました。以下のコードは、カスタムエディタを作成する試みです。

    ```csharp
    public class CustomEditor : Editor
    {
        public event EventHandler<KeyEventArgs> KeyDown;
        
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            KeyDown?.Invoke(this, e);
        }
    }
    ```

    しかし、.NET MAUIでは現在カスタムエディタへの対応が不十分であることがわかりました。`KeyEventArgs`や`KeyPressEventArgs`が見つからず、この方法での実装が難しいことが判明しました。

3. その他にも、プラットフォーム固有の実装を試みる方法も検討しましたが、これによってクロスプラットフォームの利点が失われるため、適切な解決策とは言えません。

## 他の開発環境での実現方法

- Xamarin.Formsでは、プラットフォーム固有の実装を用いてキーイベントをハンドリングすることができます。ただし、クロスプラットフォームの利点が失われることが難点です。
- WPFでは、`KeyDown`イベントを使用してキーイベントをハンドリングできます。これにより、Ctrl+Enterでメールやチャットを送信する機能などが容易に実装できます。
- Windows Formsでは、`KeyDown`イベントを使用してキーイベントをハンドリングできます。WPF同様、Ctrl+Enterでの送信機能が実装しやすいです。

## まとめ

以上の結果から、.NET MAUIでCtrl+Enterなどのキーイベントを簡単にハンドリングする方法が見つからないことがわかりました。これにより、メールやチャットアプリケーションの送信機能をCtrl+Enterで実装することが難しい状況です。今後の.NET MAUIのアップデートによって、キーイベントのハンドリングが容易になることを期待します。

他の開発環境では、プラットフォーム固有の実装や`KeyDown`イベントを利用することで、キーイベントのハンドリングが可能であることがわかりました。しかし、現状の.NET MAUIでは、そのような実装が難しいことが判明しました。

この記事で説明した内容は、.NET MAUIでキーイベントを扱う際の注意点や他の開発環境との違いを理解する上で役立つことでしょう。今後の開発において、これらの情報が参考になれば幸いです。
a11y（accessibility）13のポイント

## はじめに
Webアクセシビリティは、ウェブサイトやアプリケーションがすべてのユーザー、特に障害を持つ人々にとって利用しやすくなるように設計されていることを指します。
アクセシビリティを考慮した設計は、視覚障害、聴覚障害、運動障害、認知障害などのさまざまな障害を持つユーザーにとって使いやすさを提供します。

次に、Webアクセシビリティの具体例をいくつか挙げます。

## Webアクセシビリティ 13のポイント
__1. キーボード操作:__
すべての操作をキーボードだけで行えるようにすることで、運動障害を持つユーザーやマウスが使えない状況のユーザーに対応します。
例えば、タブキーでフォーカス可能な要素を移動し、エンターキーでクリック操作を実行できるようにすることが重要です。

__2. キーボード操作に対応したカスタムコントロール:__
カスタムUIコントロール（例: カスタムドロップダウンメニューやスライダー）を作成する場合は、キーボード操作に対応させることが重要です。
これには、適切なtabindex属性の設定や、キーボードイベントの処理（例: 矢印キーで選択肢を移動）が含まれます。

__3. フォーカス管理:__
モーダルウィンドウやポップアップメニューなどの要素が開いたときに、フォーカスをその要素に移動させることでキーボード操作によるアクセシビリティが向上します。
例えばモーダルが開いたときにフォーカスをモーダル内の最初のフォーカス可能な要素に移動させたり、モーダルが閉じたときにフォーカスを元の位置に戻すことでユーザーが現在地を見失わなくなります。

__4. 画像の代替テキスト:__
画像に適切な代替テキスト（alt属性）を設定することで、視覚障害を持つユーザーがスクリーンリーダーを使用してコンテンツを理解できるようになります。

__5. 音声読み上げ順序:__
モーダルウィンドウやポップアップが表示される際にスクリーンリーダーに適切な読み上げ順序を渡すことで視覚障害者に正しく情報を伝えるができます。
方法としてモーダルやポップアップが開かれたときに、適切なARIA属性（aria-modal="true"やaria-describedby）を設定し、スクリーンリーダーがコンテンツを正しく解釈できるようにする必要があります。
また、モーダルやポップアップが閉じられた際にはスクリーンリーダーが元のコンテンツに戻って読み上げを再開できるようにすることも必要です。

__6. 色とコントラスト:__
色覚障害を持つユーザーや年齢による視力低下があるユーザーにも配慮し、十分なコントラストを担保する必要があります。
また、情報を伝える際に色だけに依存せず、テキストやアイコンなど他の手段も併用することが望ましいです。

__7. ARIA（Accessible Rich Internet Applications）:__
ARIAは、スクリーンリーダーや支援技術に対して、コンテンツの意味や役割、状態を正確に伝えるための追加情報を提供するHTML属性です。
これにより、視覚障害や認知障害を持つユーザーがより簡単にコンテンツを理解できるようになります。
例えば、ARIA属性を使用して、フォームの入力エラー情報やナビゲーションメニューの状態（展開中、閉じている）などを明示的に示すことができます。

__8. 適切な見出し構造:__
ページ内で見出しタグ（h1, h2, h3など）を適切に使用し、階層構造を明確にすることで、スクリーンリーダーを使ってコンテンツをナビゲートするユーザーやキーボードナビゲーションを使用するユーザーにとって理解しやすくなります。
見出しタグは、ページのセクションを識別し、情報を効果的に整理する役割があります。
適切な見出し構造を持つウェブページでは、キーボードナビゲーションを使用するユーザーが容易に次のセクションに移動できます。
また、スクリーンリーダーは読み上げをスキップして次の見出しにジャンプする機能を提供しています。
これにより、視覚障害を持つユーザーが素早く目的の情報にアクセスできるようになります。

__9. リンクの明確な説明:__
リンクテキストは、そのリンク先の内容を明確に示すようにすることが重要です。
例えば、「ここをクリック」や「詳細」のような曖昧なリンクテキストよりも、「当社のプライバシーポリシー」や「製品の詳細情報」のように具体的な説明が含まれたリンクテキストを使用することが望ましいです。

__10. 字幕と音声解説:__
動画コンテンツには、聴覚障害を持つユーザーのために字幕を提供することが重要です。
また、視覚障害を持つユーザーのために音声解説を提供する必要があります。
これにより、動画コンテンツがより多くのユーザーにアクセシブルになります。

__11. タッチ操作に対応:__
タッチ操作にも対応したアクセシビリティ対策が必要となります。
例えば、タッチ操作に対応したカスタムUIコントロールを実装し、タッチ操作でのアクションやジェスチャーを適切に処理することが求められます。

__12. ウェブページの言語属性:__
ページの言語属性を正しく設定することで、スクリーンリーダーは適切な音声合成エンジンを使用してコンテンツを読み上げます。
これにより、異なる言語のユーザーにとっても理解しやすくなります。

__13. フォームのアクセシビリティ:__
フォーム要素に適切なラベルを設定し、入力エラーを明確に表示することで、認知障害や視覚障害を持つユーザーにも使いやすいフォームを提供できます。
また、必須入力フィールドに明確な指示を追加することも重要です。

## まとめ
これらのアクセシビリティ対策を実践することで、ウェブサイトやアプリケーションはより多くの人々にとって使いやすいものになります。
アクセシビリティを向上させることで、全てのユーザーが等しく情報やサービスにアクセスすることができ、ユーザーの満足度を高めることができます。
そして、検索エンジンがページの内容をより適切に評価し、検索結果の上位に表示される可能性が高まります。
検索エンジンは、アクセシビリティ対策が適切に実施されているページを高く評価し、ユーザーにとって価値のあるコンテンツとして認識します。
その結果、ウェブサイト全体の評価が向上するでしょう。
2023/4/25主にITとかセキュリティの記事

iPhoneを物理デバイス認証でフィッシングから防御、iOS 16.3の「セキュリティキー」(4/21)
https://active.nikkeibp.co.jp/atcl/act/19/00130/031300076/

健康保険料をVプリカで払え!?　厚生労働省を装う偽SMS(4/23)
https://ascii.jp/elem/000/004/134/4134153/

ゼロデイ攻撃に「弱いIT」と「強いIT」　何が運命を左右するのか(4/21)
https://kn.itmedia.co.jp/kn/articles/2304/21/news064.html

医療現場で最もサイバー攻撃を受けやすい機器を調査＝米アーミス〔ＢＷ〕(4/21)
https://www.risktaisaku.com/articles/-/78691

FBIも警告、空港やホテルのUSB充電ポートを使ってはいけない理由(4/23)
https://news.yahoo.co.jp/articles/5582311309260f31f4169fd1173f8ef91da6714b

FBIが警告「公共の場にある充電ポートは危険」仕込まれたマルウェアに注意(4/23)
https://news.biglobe.ne.jp/it/0423/lfh_230423_9282048263.html

広がるチャットGPT　利便性に偏らない議論を(4/23)
https://mainichi.jp/articles/20230423/ddm/005/070/064000c

自治体も試験導入 対話型AIの開発競争が激化、日本企業も参戦【WBS】(4/23)
https://news.yahoo.co.jp/articles/40b5a0a48db8467dc6bef7b41803b4e94efa6d16

日本のサイバーセキュリティはなぜ弱い？　米軍調査団を仰天させた自衛隊の闇(4/23)
https://www.epochtimes.jp/2023/04/145718.html

Alibaba CloudのPostgreSQLデータベースに2つの脆弱性が発見(4/23)
https://news.mynavi.jp/techplus/article/20230423-2660065/

若者を中心にユーザーが急増している「Discord」の特徴と利用する時の注意点(4/23)
https://dime.jp/genre/1558041/

さくらインターネットで障害　電源トラブルでサービスが停止(4/24)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031800050/041900050/

WAF(4/24)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031500132/041900015/

デジタルスキル標準（Digital Skill Standards）(4/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600009/041800140/

相次ぐIT不祥事　情報をどう開示すべきか(4/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600014/041700143/

ChatGPTで保守点検支援など、MSやシーメンスらが製造業の生成AI活用事例を披露(4/24)
https://xtech.nikkei.com/atcl/nxt/column/18/02435/042100004/

ローコードで基幹システム刷新　オフコン脱却、月60時間超の削減
モンテール(4/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600004/041300129/

「野良ChatGPT」は防げない　利用禁止ではなくDXに生かせ(4/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600007/041700137/
Microsoft MVPになるためには

### はじめに

こういったタイトルの記事はMicrosoft MVPに実際になられた方が実際の経験をもとに書かれるケースがほとんどと思います。私はMicrosoft MVPではないですが、Microsoft MVPを目指す立場の視点から決意も込めて書きます。このためかっこいい話は書けないのですが初学者の方々にとっては身近な内容や苦悩が含まれていると思うのでぜひ読んでいただけると嬉しいです。

この記事は実際にMicrosoft MVPを7年間取得され、その後Microsoftにて内部からMVPの方々と働いている[Thomas Maurer氏の記事](https://www.thomasmaurer.ch/2023/04/how-to-become-a-microsoft-mvp/)を参考に記載しています。

### Microsoft MVPとは


Microsoft MVPとはMicrosoft Most Valuable Professionalの略称になります。ユニークでイノベーティブ、かつ一貫した知識の共有を通じて技術コミュニティを積極的にサポートする優れたコミュニティリーダーに与えられる賞です。これらのリーダーはMicrosoft製品やサービス、関連するオープンソース技術について深い知識を持ち、そのスキルと影響力を活かして他の人々がこれらの技術を学び、構築し、使用できるように支援しています。

### Microsoft MVPになる方法

Microsoft MVPになるためにMicrosoft MVP取得の経験から以下の5つの要素が重要だと述べられています。

1. 専門家になる
Microsoft関連サービスについて専門的であり、そのスキルをオンライン/オフラインのブログやイベントなどの活動でアピールする。自身の興味のある分野の最新トレンドや開発情報を常に把握しておく。
1. リーダーになる
技術コミュニティでリーダーシップを発揮し、影響を与える。さらに他のコミュニティリーダーやMicrosoft社員とも連携し、コミュニティを発展させる。
1. 支援する
技術的知見と影響力を活かしGitHubやTechコミュニティなどを通じてMicrosoft関連サービスを支援する。
1. 一貫性を持つ
数か月で活動を止めてしまうのではなく、活動継続する
1. 役に立ち、共有する
他者を助ける。

### Microsoft MVPになるために取り組むこと

上述のようなMicrosoft MVPになるためのステップは、[Microsoftのホームページ](https://mvp.microsoft.com/ja-jp/Pages/what-it-takes-to-be-an-mvp)にも述べられていますし、特別なことに言及しているわけではありません。求められる人物像はイメージつくのですが、自分の立場に翻って具体的にどんなことを取り組んだらよいか考えようとするとやっぱり難しいものです。ここからは自身の考えと現在の取り組み、決意を述べます。

偉そうに語っていますが自身に言い聞かせています（笑）。

1. Microsoft MVPになりたいと心から思う
最初から精神論的な話になりますが上述の”一貫性を持つ”ために一番重要なポイントだと思っています。MVPになりたいと思ってから実際になれるまでの道のりは長いです。その間に職務が変わったり、ライフイベントが発生したりと目指していた当初と自身の置かれた環境は大きく変わり得ます。それでも努力を続けるためにはモチベーションの源泉が他者（人から言われた/会社から言われた）ではなく、自身にある（自分がなりたいと心から思う）ことが重要だと思っています。

1. Microsoft MVPになりたいと宣言する
こちらも精神論、と言いたいところですが心理学用語で”宣言効果（Public Commitment）”とも呼ばれるようで実際に提唱される心理理論だそうです。所説あるようなので専門家でもない私は細かく突っ込みませんが、体感値として宣言することで自分にも言い聞かせることになりモチベーションになります。またパブリックにすることで他者とのコミュニケーションも生まれるため大きな効果があるように思います。
1. 継続的に技術情報を発信する
ようやく具体的な話。まずはQiitaに毎日記事を投稿するということを目標にしています。ソーシャル活動（技術情報をアウトプットし他者と繋がる活動）を全くしてこなかった私にはそもそもの習慣とノウハウがありません。まずは習慣化してどんなに忙しくても1記事/日 書ききるという仕組みを作っていきます。
1. 活動計画を改善する
残念ながら現時点でMicrosoft MVPになるための明確な活動計画は私の中に作れていません（本当はそんなこと言っていたらダメなのだと思いますが。。。）。現在はただ技術共有のリズム/仕組みを作り、コミュニティにどんな情報が求められているのかを把握→共有というサイクルをがむしゃらに自分のものにしようとしています。現Microsoft MVPなど自分のありたい姿に既にある方に協力してもらい、定期的に自分の足りない部分を指摘してもらい改善するというサイクルを回すことで段々とゴールと直結した具体的な活動計画を作っていきたいです。

### まとめ
Microsoft MVPになるための方法論について述べました。資格試験と違って人々に共通した具体的な指標はないため、特に初学者にとって何をどうすれば目標に到達できるのか分かりづらいです。本記事の内容はMicrosoft MVP目指し始めの筆者が現時点での考えを書いているため、実際にMVPになるためにはそれだけでは足りないという点が複数あると思います。トライ＆エラーを繰り返して定期的に方法論をアップデートしていきたいと思いますので、陰ながら（表もぜひ！）応援していただけると嬉しいです。同じような心持ちの方がいらっしゃったらぜひ一緒に切磋琢磨していきましょう！
＜ジーズアカデミー2週間経過＞プログラミングを通じて感じた、モチベーションを保つコツ

<h2>前段

ジーズアカデミーに入学して2週間が経ちました。
日々、プログラミングに向き合い仲間と苦悩する日々が苦しいようで最高に楽しいです。
夢にもコードが出てくるようになった自分が、プログラミング初心者、これからジーズ入学を考えている人に向けて
暑苦しい文章を書きます。

※この記事は「自分が作りたいプロダクト」について考えているときに思いついた、プログラミング初期にもつべき考えを
1人でも多くの人に伝えたい、自分に刻むという思いで書ききりました。

<h2>結論

プログラミング初心者が学ぶときに持つべき考え方は「小さな成功体験をとにかく一つ積む。そしてそれを自分でめっちゃ喜ぶ。」です。
ありきたりな内容ですが、これに尽きると思っています。

上記は
①小さな成功体験をとにかく一つ積む
②自分でめっちゃ喜ぶ。
の2要素でできています。

そのため2つを実行するためのマインドセットについて説明します。

<h2>「小さな成功体験をとにかく一つ積む」ためのマインドセット

小さな成功体験を積むということは、失敗、苦労を乗り越えるということです。

プログラミングを勉強していると、絶対に「え、わからん…」ってタイミングが来ます。
そんなときのマインドセットです。
めっちゃシンプルです。

『目の前の失敗、苦労を乗り越えることしか考えない。』

です。

私が陥ったのが、自分がつまずいたタイミングで
「自分、こんな序盤でつまずいちゃったよ…もっと先があるのに…」
でした。

こうなると最悪です。
自分はこの先、ついていけるのかな？とか向いていないのかもな？
とか考えても仕方ないことを勝手に頭が考えだします。

もしエラーが出たら、『目の前の失敗、苦労を乗り越えることしか考えない。』で一緒に乗り越えましょう！
（自戒も込めて）

<h2>「自分でめっちゃ喜ぶ」ためのマインドセット

こちらも結論から言うと、
「過去の自分と比較する。(他人や将来のなりたい自分と比較するのではなく。)」です。

気づかず、自分はやってしまってました。
みんなが課題を早々に終わらしている中、自分は時間かけているのに全然終わらない…
ああ、やっぱり自分はだめなんだな…って思いました。

上記の状態になると、プログラミングがとにかく楽しくないです。
きついです。
中学のみんなの前でやる歌のテストくらいきついです。

相当な精神力が必要になってしまいます。
そんな自分だったからこそ、「将来のなりたい自分、他人と比較するのではなく、過去の自分と比較する。」事の大切さに気付けました。

<h2>まとめ

エネルギーを保つには

①小さな成功体験をとにかく一つ積む
    →目の前の失敗、苦労を乗り越えることしか考えない。
②そしてそれを自分でめっちゃ喜ぶ。
    →将来のなりたい自分、他人と比較するのではなく、過去の自分と比較する。


<h2>余談

自分のことについて話さず、記事を作ってしまっていたので
最近のエキサイトな気付きを含めて。

自分は「人のエネルギーを爆発させる」プロダクトを作りたいと考えています。
人が一歩踏み出す瞬間、情熱が溢れている人が最高に好きです。

そんな思いを持ってジーズに入学し、実現手段として「人に死を体験させる」というサービスを考えていました。
短絡的ですが、人間は死ぬかもって思ったら、エネルギーが爆発すると思ったからです。
この思いや経緯をジーズのチューターの方に伝えたところ、「解決したい課題を持っている人を、自分から拒絶しちゃってるんじゃない？」って言われました。

ん！？！？！？って思いました。
だけど、自分にめちゃくちゃ刺さってました。
何日経っても、その言葉が頭に残っていました。
無意識に避けてしまっていることを認めました。

この気づきを頂いたお陰で、作るサービスの方角を再度検討することにしました。
今後は「セカイに成功体験を生み出す」というコンセプトで改めて考えてみようと思います。
気付きを与えてくださったジーズのチューターの方に感謝です！

ただの日記っぽくなりましたが、備忘録として！
また進捗あったらご報告します！
トラブル知らずのシステム設計 エラー制御・排他制御 No1

本を読んだ備忘録です！


# 排他制御
- 共有資源に対して複数のアクセスが同時に発生しても問題なく動作できる制御


## 排他制御の種類
- ロック
    - 共有資源にロックをかけて同時にアクセスさせない方式。
        - 悲観ロック
            - 更新対象データを取得時にロックして他者が操作できないようにする方式
        - 楽観ロック
            - 同時アクセスはあまり起きない」という楽観的な考え方の排他制御
            - 複数のトランザクションが同時に同じデータにアクセスしても競合が発生しないようにするための手法
- ニューテックス
    - 「未使用」と「使用中」で判断し、共有資源を同時にアクセスさせない方式。
- セマフォ
    - 同時にアクセスできる数を管理し、その人数までしか共有資源に対して同時にアクセスさせない方式。


### 楽観ロックの流れ（バージョン比較）
1. テーブルのカラムにバージョンを用意しておき、データ閲覧者にはバージョンを付与

2. データ更新時にバージョンがカウントアップされるようにする
バージョンがアップすることで、古いバージョンを付与されている閲覧者はデータを更新できない

![スクリーンショット 2023-04-25 1.27.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/f5723c39-3bf7-52ae-98db-04997a2053d9.png)
![スクリーンショット 2023-04-25 1.27.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/022f4777-aef1-42d5-7c00-6b31861d4e17.png)

![スクリーンショット 2023-04-25 1.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/9e3f59d8-f1f7-d61a-ef47-25b4e5a79737.png)

*引用
https://medium-company.com/%e6%a5%bd%e8%a6%b3%e3%83%ad%e3%83%83%e3%82%af%e3%81%a8%e3%81%af/


- タイムスタンプ比較、前列データ比較など種類がある
- デメリットは、他社による更新が頻繁に行われるサービスには向いてない。なぜなら、滅多なことじゃ更新は起きないという前提だから


### 悲観ロックの流れ
1. トランザクションがデータにアクセスする前に、先にアクセスしている他のトランザクションからデータが更新されていないかをチェックする。
2. 更新されていた場合は、トランザクションはロックをかけることで他のトランザクションからのアクセスを制限する。
3. ロックをかけることで他のトランザクションからのアクセスを制限し、データの整合性を保つ。
4. トランザクションが処理を終了したら、ロックを解除することで他のトランザクションがデータにアクセスできるようにする。

＊無理やり終了されると、ロック解除が検知できないので
例）ブラウザの×ボタン押下や、シャットダウン
管理者がロック解除できるロック解除画面
深夜にシステムが全ロックを解除する
同じユーザーからの再アクセスは許可
などの対策が必要


排他制御奥が深い。。。
初心者が開発中に思ったこと(まだ途中)

プログラミング初心者が思ったことです。

１,開発をする際に、全体の大まかな流れ、計画をある程度立てる。

2,classやfunction,引数等が正しく機能しているのかを検証用のファイルを作って一つずつ確かながら、コードを増やしていく。(後に関数等の使い方の復習もしやすい気がする。)

3,chatGPTに丸投げすると、動きはするけど何しているのかわからないので、質問やバグ探し用に使う.
基本的なサイバー攻撃のおさらいと対策

# XSS(Cross Site Scripting)
- 不正なプログラムをWebページに仕込み、攻撃対象とは別のWebページに情報を流出させたりすること
    - サイトに設置されたフォームにユーザーが情報を入力・送信する際に、埋められた悪質なHTMLスクリプトが実行され、入力された情報に加えCookie情報なども攻撃者に送られます。

![スクリーンショット 2023-04-25 0.31.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/59020782-dc8c-8a91-de7d-640c21bbefdf.png)
*引用
https://www.shadan-kun.com/waf_websecurity/xss/  

## 対策
- スクリプトの構成に必要な&，<，>，”，’の５文字の特殊文字に着目し、これらが文字列としてそのまま画面に表示されるように置換（エスケープ）し、スクリプトの無害化（＝サニタイジング）を行います 
    - htmlspecialchars関数
- 入力値を制限する
    - 例えば郵便番号の入力では、数字以外の入力を許可しないこと
    - 入力値の長さに制限を設けることで、攻撃が可能となるスクリプトの挿入をある程度抑制することが可能

# CSRF(Cross Site Request Forgeries)
- Webアプリケーションに対して不正なリクエストを送信する攻撃手法

    - 1.ログイン状態で、不正なリンクを踏ませる（「面白い画像を見つけた」とか「プレゼントに当選しました！」とか「至急、口座の確認が必要です！」といった内容)
    - 2.このリンクには、Webアプリケーションに対して、勝手に投稿を行ったり、決済したりするような処理が仕込まれており、ログイン状態にあるユーザーがこれをクリックすることで、自分がWebアプリケーションに対してその操作を命令した状態になっ
    - 3.処理リクエストを受け取ったWebアプリケーションは、ユーザーからの正規のリクエストだと判断してしまい、実際にその処理が実行されてしまう

![スクリーンショット 2023-04-25 0.48.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/ac930ab9-f350-82fe-b623-c18676b9d235.png)
＊引用
https://blog.senseshare.jp/csrf.html

## 対策
- ユーザー側の対策としては、怪しいリンクは絶対にクリックしないこと
- サービス開発側の対策としては、処理リクエストが「正規なアクセスなのかどうか」をチェックしてから処理を行う仕組みを導入
    - トークンの確認（一時的なランダムトークンをサーバで発行し、セッションとして保持）
        - ブラウザにはセッション Cookie と、トークンを <input type="hidden" value="token-xxx"> とフォームパーツとして含んだ HTML を返す
        - POST された際に、フォームの送信データのトークンと、セッションで保持しているトークンが一致するかで正規なリクエストかどうかを判断する
![スクリーンショット 2023-04-25 0.53.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748934/0c4d9c30-2cc5-d019-91db-c028a25be2cc.png)
*引用
https://tech.basicinc.jp/articles/231


# SQL Injection
- 第三者がSQLコマンドを悪用してデータベースの情報へ不正にアクセスし、情報を搾取や改ざん、削除する攻撃手法
    - サイトに設置されたお問い合わせフォームなどの入力フォームに対し、攻撃者が不正に情報を引き出させるSQL文を入力されるケース

## 対策
- SQL文の組み立ては全てプレースホルダで実装する
    - 変数のように値が変動する箇所」と「データベースへ登録する処理」の間に挟むことで変動する箇所を「値」として処理するしくみ
- エスケープ処理を行う

＊プレースホルダ
- QL文中に変数を埋め込むための仕組みを提供します。SQL文中に「?」または「:name」のような特殊な文字列
＊プリペアドステートメント
- データベースへのクエリを実行するための準備が整ったSQL文
```
プリペアドステートメント例）
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
```

# セッション固定攻撃
- セッションIDを取得して送り付け、なりすましログインをする
    - 攻撃者は、正規サイトにセッションIDを作成する
    - 何らかの方法で、利用者に送り付け、セッションIDを強制させる
    - 利用者が攻撃者に強制されたセッションIDを使って正規サイトにログインに成功すると、正規サイトではセッションIDと利用者の紐づけを行い記憶
    - 正規サイトでは、利用者との紐づけが行われたセッションIDでアクセスすれば、利用者になりすますことができま

## 対策
- セッションIDの更新
    - session_regenerate_id(true);が利用できます。引数にtrueをセットした場合、サーバのセッションファイルを破棄した上でセッションIDを更新します。
- セッションIDの管理をクッキーでのみ扱う
- 認証にはセッションID以外の多重チェックを行う
rex0220 算式自動採番プラグイン 異なる区分で通番

rex0220 算式自動採番プラグインで、異なる区分で通番を自動採番する例です。

# 概要

[rex0220 算式自動採番プラグイン](https://qiita.com/rex0220/items/2e40a57d2d08023affde)：　計算式で番号を組み立てる自動採番プラグインです。
Ver.24 で追加された「採番後変換機能」を使って、異なる区分で通番を自動採番を行います。

- 採番例１；　区分と通番
    -  A-00001, B-00002, A-00003, A-00004...
- 採番例２：　年と区分と通番（年毎に通番をリセット）
    -  2023A-00001, 2023B-00002, 2023A-00003, 2023A-00004...

# 採番例１　 A-00001

- 採番ルール
    - 番号内に区分(A, B)を持つ
    - 番号は、１からの通番
    - 番号例： A-00001, B-00002, A-00003, A-00004...

![2023-04-25_00h19_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3da9c2cd-52e2-1048-a63c-ba783b970a06.png)

![2023-04-25_00h18_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/afcb254d-7912-c248-ffe8-f62b4ec9f242.png)

## 操作例

![2023-04-25_00h21_59.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/87caa3a5-f70e-c2db-1cb9-43e20b2806e7.gif)

## 画面設定

- 番号：自動採番する番号
- 採番キー：　算式自動採番プラグインで使用する作業用項目
- 通番：　算式自動採番プラグインで使用する作業用項目
- 区分：　番号に付加する区分

![2023-04-25_00h25_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/9fcda901-9f19-9a73-3828-cc334b371b35.png)


## 算式自動採番の設定

- 採番項目：　番号
- 採番　計算式：　"#-@@@@@"
    - 　# は、区分に変換用の仮文字
- 変換　計算式：　REPLACE(番号,"#",区分)
- 採番キー項目：　採番キー
- 連番項目：　連番

![2023-04-25_00h25_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3e3c1d52-2519-ff28-559e-1b6b8302c5e9.png)


# 採番例２　 2023A-00001

- 採番ルール
    - 番号内に日付の年と区分(A, B)を持つ
    - 番号は、１からの通番で、年毎にリセット
    - 番号例： 2023A-00001, 2023B-00002, 2023A-00003, 2023A-00004...

## 画面設定

- 番号：自動採番する番号
- 採番キー：　算式自動採番プラグインで使用する作業用項目
- 通番：　算式自動採番プラグインで使用する作業用項目
- 日付：　日付の年を番号に付加する
- 区分：　番号に付加する区分

![2023-04-25_00h54_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/28a94dfe-8895-03d8-529a-c2e740b42435.png)

## 算式自動採番の設定

- 採番項目：　番号
- 採番　計算式：　DATE_FORMAT(日付,"YYYY")&"#-@@@@@"
    - 　# は、区分に変換用の仮文字
- 変換　計算式：　REPLACE(番号,"#",区分)
- 採番キー項目：　採番キー
- 連番項目：　連番

![2023-04-25_00h56_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/455692cd-6204-4d30-cec4-aeb77b930f1e.png)
aws コストメール送るもの

以下は、AWS Lambda関数のコード例です。このコードは、AWS Cost Explorer APIを使って今月の利用料金を日ごとに取得し、Amazon SNSを使ってメールを送信するロジックを実装しています。Python言語を使用しています。

まず、Lambda関数に必要な権限を持つIAMロールを作成し、`boto3`ライブラリを使用してAWSサービスにアクセスできるようにしてください。

以下のコードを `lambda_function.py` として保存し、AWS Lambdaにデプロイします。

```python
import os
import json
import boto3
from datetime import datetime, timedelta

def get_cost_and_usage(start_date, end_date):
    client = boto3.client('ce')
    response = client.get_cost_and_usage(
        TimePeriod={
            'Start': start_date,
            'End': end_date
        },
        Granularity='DAILY',
        Metrics=['UnblendedCost'],
        GroupBy=[{
            'Type': 'DIMENSION',
            'Key': 'SERVICE'
        }]
    )
    return response

def send_email_notification(cost_data):
    sns = boto3.client('sns')
    topic_arn = os.environ['SNS_TOPIC_ARN']

    message = json.dumps(cost_data, indent=2, default=str)
    subject = 'AWS Daily Cost Report'

    sns.publish(
        TopicArn=topic_arn,
        Message=message,
        Subject=subject
    )

def lambda_handler(event, context):
    end_date = datetime.now().date()
    start_date = end_date.replace(day=1)

    cost_data = get_cost_and_usage(start_date.isoformat(), end_date.isoformat())
    send_email_notification(cost_data)
```

このコードでは、環境変数 `SNS_TOPIC_ARN` にSNSトピックのARNを設定する必要があります。これは、AWS Lambda関数の設定で行います。

次に、Amazon SNSのトピックを作成し、Eメールサブスクリプションを追加して、メール通知を受信できるようにします。そして、SNSトピックのARNをLambda関数の環境変数 `SNS_TOPIC_ARN` に設定してください。

これで、AWS Lambda関数がAWS Cost Explorer APIを使用して今月の利用料金を日ごとに取得し、Amazon SNSを使ってメールを送信するロジックが実装されました。Lambda関数を実行すると、指定されたEメールアドレスにAWSの利用料金のデイリーレポートが送信されます。
Cloud Natural Language の料金 と Google Cloud 料金計算ツール

Natural Language API の感情分析を使ってみたので料金を確認していたのですが、[Cloud Natural Language の料金](https://cloud.google.com/natural-language/pricing?hl=ja) と [Google Cloud 料金計算ツール](https://cloud.google.com/products/calculator) が一致しないような感じがしたので調べてみました。

各APIにキリの良い回数を入力し、金額を試算してみました。
[感情分析](https://cloud.google.com/products/calculator/#id=cb3e842d-4ffc-4cf4-8030-32d5cb610d42)だけ料金表と一致しない数字がでました。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/59cbcb68-f868-a573-8083-d474c764bce4.png)

CSVダウンロードしてみると、料金計算ツールの UI に表示されている `Sentiment Analysis` は `Entity Sentiment Analysis Operations（エンティティ感情分析）` だという事がわかりました。
![スクリーンショット 2023-04-25 0.20.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/411f3fb5-2944-09f8-baa0-5caaa5847fca.png)

こういう事ですね。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/1f25fd51-5099-81a1-d6de-133672a5455a.png)

感情分析はエンティティ分析と同じ金額だから、エンティティ分析に含めて試算してしまえという事なのでしょうか...
React 18 の useTransition を触ってみる

さて、またもや今更感ありますが、、、、
デモアプリを作ってuseTransitionの動作を見ていこうと思います。

## useTransitionって何？

状態変更に伴う画面遷移やコンポーネントの表示切り替え時、
`今の画面を保持しつつ、次の画面を裏で準備(レンダリング)させるための機能`です。
人間の操作感はそのままに、裏でレンダリング終わるまでさっきの表示をずっと出しておいて。。。という具合です。

useTransitionは、遷移が進行中かどうかを示す `isPending` と、遷移を開始するための `startTransition` 関数を得ます。

### startTransition
コンポーネントのレンダリングとstate更新を遅らせる機能で、主な機能は遅延された更新とレンダリングの遅延です。
遅らせるstate、遅らせないstateと分けること、つまり`状態更新の優先順位を任意で設定`できます。

### isPending
遅延された更新が完了するまでの間、trueになります。
更新が完了すると、falseに戻ります。これにより、UIにローディングインジケータやスピナーを表示することができます。

早速試してみましょう

```jsx
import { useState, useCallback, useTransition } from "react";

function createLargeArray() {
  const array = new Array(20000).fill(0).map((_, index) => index + 1);
  return array;
}

function App() {
  const [isPending, startTransition] = useTransition();
  const [counter, setCounter] = useState(0);
  const [array, setArray] = useState([]);

  const handleClick = useCallback(async () => {
    const largeArray = createLargeArray();
    startTransition(() => {
      setArray(largeArray);
    });
  }, [startTransition]);

  return (
    <div className="App">
      <h1>useTransition</h1>
      <p>{counter}</p>
      <button
        onClick={() => {
          setCounter((c) => c + 1), handleClick();
        }}
      >
        Create array
      </button>
      {isPending && <p>isPending...</p>}
      <ul>
        {array.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

```

![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/88bf8c29-06d2-c6ea-ded1-8662d4086ce6.gif)

li内が表示されるまで、`isPending...` が表示され続けました。
下記2点が確認できました。
 - カウントは即座に増えている
 - `startTransition`内のstateが整うまで、isPendingを出している

では、カウントも `startTransition`の中に入れるとどうなるのでしょうか？

```diff
  const handleClick = useCallback(async () => {
    const largeArray = createLargeArray();
    startTransition(() => {
+     setCounter((c) => c + 1);
      setArray(largeArray);
    });
  }, [startTransition]);
```

![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/6b1c5f95-6891-976b-4a96-a85183ba3212.gif)

想像通り、配列の表示と同時に表示が変わりました。

## まとめ
useTransitionは、応答性の向上や高コスト処理の制御に効果的で、準備中にローディングインジケータ表示するなどしてユーザーに今何が起こっているのかを知らせることができます。
一度触ってみてくださいね！

参考 : 
Reactのトランジションで世界を分岐させるハンズオン  
https://zenn.dev/uhyo/books/react-concurrent-handson-2/viewer/mixing      

Reactの2種類の新フック「useTransition」と「useDeferredValue」を最速で理解する（プレビュー版
https://qiita.com/uhyo/items/6be96c278c71b0ddb39b#usetransition
No16_ググったこと投稿(5分)_バウンスメールと洗替

初めて聞いた言葉があったのでそれの備忘録として残します

## バウンスメール（bounce mail）
- 送信したのに跳ね返されてきたメールを指します。メール送信後にMAILER-DAEMONやPostmaster、Mail Delivery Systemなどが送信元となって戻ってくるメールがバウンスメールです。
    - 未達メール、リターンメールと呼ばれることもあります。
- バウンスメールには、「メールが送れませんでした」といった内容のメッセージとともに、
    - バウンスされた日時
    - バウンスしたメールサーバー
    - 情報エラーコード
    - バウンスした理由



### バウンスの種類
- ソフトバウンス（一時的エラー）
    - 一時的に問題が発生したことによってメールが送信できなかった際に発生するエラーです。問題が解消されればメール配信できる可能性が高いため、多くのメールプロバイダーは数日の間メール送信を試行し続けます。
- ハードバウンス（恒久的エラー)
    - 何らかの事情でメールが恒久的に配信できないエラーを指します。時間をおいて試行してもメールが届くことはないので、送信できるようにするための対策が必要です。


### その他
- sendGrid使えば、バウンスメール管理ができるぽい？
    - https://sendgrid.kke.co.jp/docs/Tutorials/A_Transaction_Mail/manage_bounces.html


## 洗い替え
- クレジットカードの有効期限等、クレジットカードの有効性をチェックし、最新の情報に更新すること
    - データの入れ替えのことを指してると思ってたのですが、クレジットカード系の開発？だとよく聞く言葉らしいですね。。。初耳

### 機能
- 売上計上の前に有効期限やクレジットカード番号の更新の有無をカード会社へ確認すること（有効性チェック）で、自動的に情報を更新する。
【Django】汎用ビュー CreateView を用いたフォームのラベルを変更する

# CreateView
モデルの作成に使われる、汎用ビューの一つである
汎用ビューを用いることでコードの量を減らすことができる

# こたえ： get_form()
~~~views.py
class PostCreateView(LoginRequiredMixin, CreateView):
    model = Post
    template_name = "post.html"
    fields = ['shop_name', 'shop_link']
    success_url = reverse_lazy('APP:posted')

    #ラベルを日本語に
    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        form.fields['shop_name'].label = '店名' 
        form.fields['shop_link'].label = 'お店のURL'
        return form

    #ログインユーザーで投稿
    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)
~~~

## 注
CreateViewを使用しないときはforms.pyで

~~~forms.py
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['shop_name', 'shop_link']
        #これを記述
        labels={
            'shop_name':'店名',
            'shop_link':'お店のリンク（ラーメンDB等）'
           }
~~~
とする。
（CreateViewではこれが反映されなかったけど、普通はされるのかな...??）

参考: https://yu-nix.com/archives/django-create-view/
HP2530_ループ検知

## 環境
HP2530 YB.16.10.0011

# HP2530の設定
VLAN50を作成し、ポート３と４をタグ付けにする
```
# configure terminal
(config)# vlan 50
(vlan-50)# name roop_test
(vlan-50)# tagged 3-4
```
ポート3でloop-protectを有効にして、ループ検出時ポートをシャットダウンし、60秒毎に自動復旧、10秒毎にループパケットを送信するように指定。
* send-disable : ループ検知時にループ検知パケットを送信したポートをシャットダウンします。(デフォルト) 
* no-disable : ループを検知してもポートをシャットダウンしません。
* send-recv-dis : ループ検知時にループ検知パケットを送信したポート、受信したポートの両方をシャットダウンします。 
```
(config)# loop-protect 3 receover-action send-disable
(config)# loop-protect transmit-interval 10 disable-timer 60  
(config)# save
```
手動復旧するにはinterface <Port-List> enableを実行。

# Catalyst3560設定
```
#configure terminal
(config)#vlan 50
(config-vlan)#name roop_test
(config-vlan)#exit
(config)#interface gi0/3
(config-if)#switchport trunk encapsulation dot1q
(config-if)#switchport mode trunk
(config-if)#switchport access vlan 50
(config-if)#no keepalive
```
```
(config)#interface gi0/4
(config-if)#switchport trunk encapsulation dot1q
(config-if)#switchport mode trunk
(config-if)#switchport access vlan 50
(config-if)#no keepalive
```
vlan1,50はSTPを無効
```
(config)#no spanning-tree vlan 1
(config)#no spanning-tree vlan 50
```



# ループ検知の動作確認
ポート3でループ検知してのでポート4番でDOWN。それから約60秒経過してからポート4番UP。またポート3で検知しての繰り返しが表示されている。


```php:(config)# show logging Keys
:   W=Warning   I=Information
          M=Major     D=Debug E=Error
 ----  Event Log listing: Events Since Boot  ----
 I 04/19/23 10:30:46 00184 mgr: Log cleared as a result of  'clear logging' 
             command
 I 04/19/23 10:31:16 00886 loop-protect: port 3 - loop detected.
 W 04/19/23 10:31:17 00884 loop-protect: port 4 disabled - loop detected.
 I 04/19/23 10:31:17 00898 ports: Loop Protect(62) has disabled port 4 for 60
             seconds
 I 04/19/23 10:31:17 00077 ports: port 4 is now off-line
 I 04/19/23 10:32:17 00900 ports: port 4 timer (62) has expired
 I 04/19/23 10:32:21 00076 ports: port 4 is now on-line
 I 04/19/23 10:32:26 00886 loop-protect: port 3 - loop detected.
 W 04/19/23 10:32:27 00884 loop-protect: port 4 disabled - loop detected.
 I 04/19/23 10:32:27 00898 ports: Loop Protect(62) has disabled port 4 for 60
             seconds
```
```php:(config)# show loop-protect
  Status and Counters - Loop Protection Information
 
   Transmit Interval (sec)     : 10          
   Port Disable Timer (sec)    : 60          
   Loop Detected Trap          : Disabled    
   Loop Protect Mode           : Port        
   Loop Protect Enabled VLANs  :             
 
 
          Loop    Loop     Detected  Loop   Time Since  Rx            Port   
   Port   Protect Detected on VLAN   Count  Last Loop   Action        Status  
   ------ ------- -------- --------- ------ ----------- ------------- --------
   3      Yes     Yes      NA        117    11m,52s     send-disable  Up      
```
例外クラスの継承関係

# 記事内容
現在Rubyを学習中。
個人的に大事だと思ったものを残す。

rescue節での例外クラスに継承関係について、認識しておくべき点をまとめる。

# 例外クラスの継承関係
例外クラスの継承元は`Exceptionクラス`になる。
一番の親クラスになり、最初に置いてしまうと、後の子クラスが反応しないことに注意が必要。

# 順番を間違えた例
```ruby:rescue.rb

begin
#NoMethodErrorが発生する箇所
rescue NameError
puts "NameError"
rescue NoMethodError
puts "NoMethodError"
end
```

上記コードでは親クラスである`NameError`が補足されると`NoMethodError`も捕捉されるため
2個目のrescue節は実行されることがないままとなる。
順番を置き換えることで状況は改善される。
逆コンパイルとは

## 逆コンパイル（Reverse Engineering）

既存のバイナリファイル（機械語の形式で書かれたプログラム）を解析して、元のソースコードに近い形式で再現すること
→ソースコードが紛失したり、変更を加えたい場合に役立つ

・ディスアセンブル（バイナリファイルをアセンブリ言語に変換すること）
・動的解析（プログラムを実行して動作を観察すること）
・静的解析（バイナリファイルの構造を解析すること）
など


利用される場面の例
・セキュリティ分析
・脆弱性検出
・リバースエンジニアリング
など