OmniAICreator/Qiita-1.07M huggingface dataset:
VBA tsvファイル 読み書き

ファイル形式：tsv
文字コード:UTF-8
改行コード:LF

```vb
Option Explicit
Function readTsv()
'tsv読み込み処理を行う
    Dim targetFilePath As String
    Dim readTxt As String
    Dim maxCol As Long, maxRow As Long
    Dim splitList_row As Variant, splitList_col As Variant
    
    targetFilePath = openFileDialog
    
    'tsv読み込み
    With CreateObject("ADODB.Stream")
        .Charset = "UTF-8"
        .Open
        .LoadFromFile targetFilePath
        readTxt = .ReadText
        .Close
    End With
        
    splitList_row = Split(readTxt, vbLf)
    
    '行、列の最大数（0始まりのため1足す）
    maxRow = UBound(splitList_row) + 1
    maxCol = UBound(Split(splitList_row(0), vbTab)) + 1
        
    Dim i
    For i = 1 To maxRow
        splitList_col = Split(splitList_row(i - 1), vbTab) 'リストの先頭0の為-1する
        '1行ずつデータをセルに代入
        Range(Cells(i, 1), Cells(i, maxCol)) = splitList_col
    Next i

End Function

Function openFileDialog() As String
'ファイルダイアログを開き、指定したファイルを返す
'return
'OpenFileDir:strng:指定したファイル名（指定しなかった場合は処理終了）


  Dim OpenFileDir As String 'オープンするFileのディレクトリ
  'デフォルトのパスをカレントディレクトリに変更
  ChDir ActiveWorkbook.path
  OpenFileDir = Application.GetOpenFilename("ファイル,*.tsv")
  If OpenFileDir = "False" Then End
  
  openFileDialog = OpenFileDir
End Function

Function createTsvFile()
'ファイルへ書き込む
 
   Dim adoObj As Variant
   Dim savefileDir As String
   savefileDir = openFolderPicker()
   
    Set adoObj = CreateObject("ADODB.Stream")
    With adoObj
        .Charset = "UTF-8"
        .Type = 2 'テキストモード
        .LineSeparator = 10 '改行コードLF
        .Open

        '文字列を行単位でストリームに書き込む
        Set adoObj = writeRowStr(adoObj)
        
        'ストリームに書き込んだ文字列をTSVファイルに保存する
        .SaveToFile savefileDir & "\test.tsv", 2
        .Close
    
    End With

End Function
Function writeRowStr(adoObj As Variant) As Variant
'文字列を行単位でストリームに書き込む
  Dim endRow As Long, endCol As Long, i, j
  Dim writeStrTmp As String
  
  endRow = Range("A" & Rows.Count).End(xlUp).Row
  endCol = Cells(1, Columns.Count).End(xlToLeft).Column
  For i = 1 To endRow
    
    writeStrTmp = "" '初期化
    For j = 1 To endCol
      
      If j = 1 Then
        writeStrTmp = Cells(i, j)
      Else
        writeStrTmp = writeStrTmp & vbTab & Cells(i, j)
      End If
      
    Next j
    '書き込み
    adoObj.WriteText writeStrTmp, 1
    
  Next i
  Set writeRowStr = adoObj

End Function

Function openFolderPicker() As String
'フォルダピッカーを開き、指定したフォルダのパスを返す
  Dim folderArray As FileDialog
  Application.FileDialog(msoFileDialogFolderPicker).Show
  Set folderArray = Application.FileDialog(msoFileDialogFolderPicker)
  
  '選択しなかった場合は処理を終了する
  If folderArray.SelectedItems.Count = 0 Then End

  openFolderPicker = folderArray.SelectedItems(1)
   
End Function

```
知っておくと一目置かれる：HTTPの中身を知ろう！

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はHTTPの中身について調べてみましょう！
![インスタスライド_202301042.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/6351080a-7fb2-7943-51b4-1ba09d1cb997.gif)


# HTTPの中身とは
ブラウザを利用してWEBサイトを閲覧しますが、やり取りはテキスト情報をやり取りしているだけです。
（httpsでは暗号化されてますが、データはテキスト情報です）
仕組みが分かればデバッグしやすくなります！

# やり取りのイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/71b2aa35-677e-2dba-b05d-dfbf046c17e5.png)

# リクエスト情報の中身
リクエスト情報の中には
**・リクエストヘッダー**
　method: GET やPOST
　cookie情報
　user-agent情報
　等

**・リクエスト情報**
　GETやPOSTで送られるデータが含まれています。

# レスポンス情報の中身

レスポンス情報の中には

・レスポンスヘッダー
　content-type:text/html; charset=utf-8
　date等

・レスポンス情報
　実際のHTML、JavaScript等データ

が含まれています。

# やり取りを見るには
Chromeであれば、

１．その他ツール -> デベロッパーツールを開く
２．ネットワークを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/92dc29f5-30ba-f3c6-4010-83b1ab06af11.png)

# まとめ
ー　ブラウザからサーバーへは、リクエスト情報が送られている

ー　サーバーからブラウザへは、レスポンス情報が送られている

ー　chromeのデベロッパーツールでやり取りの中身を見ることが出来る

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
【サービス開発のポイント】品質を定義せよ！

サービス開発・ソフトウエア開発において品質確保は、とても重要なテーマです。
しかし品質というのは、定義がとても曖昧です。これ最初に議論してますか？
**品質レベルについてチーム内、組織内、会社内でレベル合わせをしておきましょう**という提案です。

# 品質が曖昧な事例
一番わかり易い事例は車です。フェラーリとトヨタのビッツです。
販売価格を見るとフェラーリが３０００万円に対して、トヨタのビッツが２００万円です。
（正式な価格は、正しく無いかも知れません。）
詳しく調べてはいませんが、素材のコストは１５倍もないと思います。
何が違うのでしょうか
フェラーリが高くても売れる理由は、
・見た目がかっこよかったり
・排気音が良かったり
・他人に自慢できたり
・ファンのコミュニティがあったり
・店員の対応が良かったり

間違いなく素材が良いから買ってるという人は居ないです。
品質ではなくブランドだったり持った時のステータスでしょうか。

# 品質が悪くても値段が高い時がある
上記のフェラーリとトヨタのビッツでは、むしろトヨタのビッツの方が品質が高いのではないでしょうか？壊れる事等殆どないし、気温の変化等にも非常に強いです。マイナス４０度の地モンゴルでもビッツが沢山走ってます。
一方、フェラーリは良く壊れるイメージがあります。実際に所有した事は無いので分かりませんが、全然壊れないという事は無いと思います。

# 品質は良ければ良いものではない
きっとフェラーリの品質を上げようとすると、見た目がかっこ悪くなったり、排気音が静かになったり、ハンドル操作の感覚がクイックじゃなくなったりするのだと思います。
品質は、ユーザーが購入した時の期待値と価格が一致すれば売れる訳で、品質というのは、買う側の価値を意味する訳です。
**価格＝品質（原価＋期待値）**
期待値が大きい商品ほど、ブランドが高い。つまり価格が高くなっている訳です。

# サービスやソフトウエアでも同じ
品質が良いサービスやソフトウエアは大事かと聞くと全員が大事と答えると思います。
しかし、速度と品質はどちらが大事と聞くと、プロダクトリーダは、速度と答える事の方が多いのではないでしょうか？
変化の早いVUCA時代の中では、品質高く作り上げるよりも、アジャイル的に作り上げて、動かしながらディテールを詰めていく事が大事です。

# でも後から品質が大事っていうでしょ
プロダクトリーダーから速度が大事と言われて、アジャイル的に開発していくと品質はある程度置き去りしてしまいます。そして、暫くすると技術的負債が溜まっていき作り直す必要が出てきます。
しかし、プロダクトリーダーは必ず言います、そんなの聞いてない！
速度に関しても、開発速度もあれば、修正速度の話しだったかも知れません。

# 品質と速度と開発力の公式を伝えときましょう！
**品質=開発力-速度**
速度を上げすぎると、一定の開発力の中では品質は下がってしまう。
では開発力を上げれば良いのか？良く人を増やせば良いのではと言われますが、これも違います。

開発力と速度も公式があります。
Barry Boehm (バリー・ベーム) のCOCOMO式という式があります。
T ＝ c × Ed(dは指数）
T:開発期間
C:2.5
E:開発工数
d:1/3
で算出します。（cやdは色々と算出方法があります）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/4dbba2d9-8ed5-58b3-a07e-3468f6db130e.png)
これは、開発規模・人数が増えると難しさが比例以上に上がっていくという事意味します。
1.2〜1.5倍のレベルで難しさが上がっていきます。これは人数を増やせば済むという事ではないとう事を意味してます。

# 最後に
どんなプロダクト、ソフトウエアを作るかによって品質レベルは様々だと思います。見た目のかっこよさなのか、開発速度なのか、それとも修正速度なのか。
具体的な品質レベルについてチーム内、組織内、会社内でレベル合わせをして開発を開始してみて下さい。

未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
Railsの部分テンプレートで「ActionView::MissingTemplate」

### エラー発生時の状況
部分テンプレート（パーシャル／partial）機能を使おうとしたところ、
app/views以降のパスを正しく指定しているつもりなのに、エラーが発生。
「Missing partial〜」と言われてしまいました。
<img width="500" alt="before.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117645/e7e1fb5a-f508-a837-c8b6-578dd6f72c3c.png">
この場合、何が間違っているのでしょう...？

### エラー原因
パーシャル用に作ったファイル名が間違っていました。
手動でパーシャルするerbファイルを作る際は、
ファイル名の先頭に`アンダースコア（_）`をつける必要がありました。
<img width="500" alt="スクリーンショット 2023-01-23 5.49.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117645/cb0a5011-6195-3844-0955-fcb1d7fbeb61.png">
引用元：[レイアウトとレンダリング＞パーシャルに名前を与える](https://railsguides.jp/layouts_and_rendering.html#%E3%83%91%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%81%AB%E5%90%8D%E5%89%8D%E3%82%92%E4%B8%8E%E3%81%88%E3%82%8B)

### 注意点
呼び出す際のファイル名指定では、アンダースコアはなしなので注意。
<img width="500" alt="after.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117645/5709f759-036a-8b26-ee0c-aa7bd19bfbb9.png">

### 余談
今のトレンドではないpartialを使ったviewの記事ですが、
同じような状況の記事がなさそうだったので、
自分のメモとして記録します。
2023/1/23主にITとかセキュリティの記事

敵を知って臨め！ランサムウエア被害からの復旧手順
ラック　サイバー救急センター「ランサムウエアから会社を守る」（3）(1/21)
https://www.nikkei.com/article/DGXZQOUC1260M0S2A211C2000000/

米携帯Tモバイル、顧客データ流出　3700万人に影響か(1/21)
https://www.nikkei.com/article/DGXZQOGN20DGG0Q3A120C2000000/

手口が巧妙化する旅行詐欺　空港などで避けるべき3つの行動(1/21)
https://news.yahoo.co.jp/articles/863e4c8ef2fd3ba97b1e234df2fbc4440efec16f?source=rss

「米航空システム障害は人為ミス」　連邦航空局が発表(1/21)
https://www.nikkei.com/article/DGXZQOGN20CTO0Q3A120C2000000/

暴露型ランサムウエアでばらまかれた営業秘密、不競法の保護を受けられるか(1/20)
https://active.nikkeibp.co.jp/atcl/act/19/00324/122300014/

そのアプリ、インストールしても大丈夫？　あなたのスマホは狙われている！(1/21)
https://ascii.jp/elem/000/004/121/4121149/?rss

Java SEに脆弱性　IPAとJPCERT/CCは修正パッチの早期適用を呼び掛け(1/21)
https://www.zaikei.co.jp/article/20230121/706560.html

マイナンバー反対派も推進派も論点が「的外れ」、個人情報濫用防止のための仕組みを構築せよ(1/21)
https://diamond.jp/articles/-/315949

琉球大学 大学院の入試問題など一時 学内の全員が閲覧可能に(1/20)
https://www3.nhk.or.jp/news/html/20230120/k10013955941000.html

【ハイブリッド開催】個人情報保護委員会シンポジウム
個人データ・保有個人情報の流出を防ぐために(2/16開催)
https://events.nikkei.co.jp/55838/

帝人と富士通、自転車フレーム材料でリサイクル工程の可視化プロジェクトを開始(1/20)
https://xtech.nikkei.com/atcl/nxt/news/18/14482/
大学生が情報処理安全確保士試験に合格した話【やったことと学習教材】


# はじめに

![Screenshot from 2023-01-23 02-37-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641917/5aefa797-d4e5-c66a-384c-b47d9b444082.png)

令和四年度秋期の情報処理安全確保支援士試験に合格しました。登録予定です。この記事では、午後II対策と午後I、午後II対策について勉強したことと学習教材について書きます。

## 前提条件
電子工学専攻のB2です。趣味でサーバやネットワークをいじくり回しています、令和三年度秋期の応用情報技術者試験に合格していました。また趣味で（よわよわですが）CTFをやっていたりするので、最低限のセキュリティの知識は事前に備わっています。

# 事前学習

https://amzn.asia/d/dPSG0LX

上の教科書を読んで、出題される範囲について大まかに理解しました。

# 午前I対策

応用情報技術者試験に合格していたため免除されました。

# 午前II対策

https://www.sc-siken.com/sckakomon.php

上のサイトを使って、ランダムで出題したときの正答率が9割を超えるまでn回繰り返して学習しました。

# 午後I、午後II対策

https://amzn.asia/d/jk8O53v

まず、上記の問題集で暗記するべきワードや概念を暗記しつつ、問題の解き方について学習しました。
次に、IPA公式サイトからダウンロードできる過去問を10年分回しました。

https://www.jp-rissa.or.jp/post/category/news/

過去問演習の際には、IPAの公式解答だけでなく上記のページで公開されている試験対策セミナーこう出たセキスペ解答解説のスライドを参考にしました。

https://amzn.asia/d/j4RCHUI

最後に、ダメ押しとして上の本を用いて午後問題のパターンと特有の解答方法について学習しました。



# 最後に
サイバ・セキュリティの奥深さを様々な演習（過去問）を通じて学び、楽しむことができました。非常に面白い資格勉強で興味深かったです。ネットワークにも興味があるので、ネットワークスペシャリストも今回の経験を活かし一発合格を狙います。
【Flutter】webのlocalStorageをshared_preferencesを通して使用する

## 概要
webでブラウザに何か保存する際に、localStorageを使用すると思いますが、Flutter Webの場合にどう実装するかのメモ書きです。
[How to save to web local storage in flutter web](https://stackoverflow.com/questions/56417667/how-to-save-to-web-local-storage-in-flutter-web)のstackoverflowの記事に、色々と対応案が書いてあります。`shared_preferences`という端末にデータ保存するライブラリが、バージョン`0.5.4.7`以降ではlocalStorageに対応しているようなので、今回これを使用してみます。

## 前提
* Flutterのバージョンは`3.3.10`を使用します。
* shared_preferencesのバージョンは`2.0.17`を使用します。

## 実装サンプル
[shared_preferences](https://pub.dev/packages/shared_preferences)のライブラリのページに記載ある通りですが、アプリでの実装と同じ形式で以下のようにlocalStorageを使用できます。

```dart
import 'package:shared_preferences/shared_preferences.dart';

class LocalStorageManagementService {
  static const String localStorageKey = "localStorageKey";

  static Future<void> setLocalStorage(String value) async {
    final localStorage = await SharedPreferences.getInstance();
    localStorage.setString(localStorageKey, value);
  }

  static Future<String?> getAuthTokenLocalStorage() async {
    final localStorage = await SharedPreferences.getInstance();
    return localStorage.getString(localStorageKey);
  }

  static Future<void> removeAuthTokenLocalStorage() async {
    final localStorage = await SharedPreferences.getInstance();
    localStorage.remove(localStorageKey);
  }
}
```
【Android】locationフィールドにGeoPointが使えなかった時の対処法

# はじめに

次のように、`location`フィールドに対して`GeoPoint`のインスタンスを設定して、データを追加しようとしました。

```kotlin
val data = hashMapOf(
    "createdAt" to FieldValue.serverTimestamp(),
    "location" to GeoPoint(0.0, 0.0),
)

val collectionReference = firestore
    .collection("records")
    .document(recordId)

val reference = collectionReference
    .add(data)
    .await()
```

ところが、上記の処理を実行してみるとエラーが発生しました。

```shell
Found conflicting getters for name getDefaultInstanceForType on class com.google.type.LatLng
```

# エラーの理由

これは、GeoPointはクラスであり、シリアライズとデシリアライズが不可能なためこのようなエラーが発生するということを表しています。

https://stackoverflow.com/questions/60017934/how-to-map-geopoint-from-firebase-firestore-in-to-kotlin-dto-object-in-android

なので、次のようなルールを設定することはできません。

```
function isValidRecord(record) {
    return record.size() == 2
      && "createdAt" in record && record.createdAt is timestamp
      && "location" in record && (record.location == null || record.location is latlng)
}
```

# ところがどっこいの解決方法

ところが、いろいろ試していくとフィールド名に`location`という名前を設定していたことが原因だということがわかりました。

なので、`location`から`position`というフィールド名に変えて`GeoPoint(0.0, 0.0)`を渡してみると、なんとエラーを発生させることなく成功しました。

```kotlin
val data = hashMapOf(
    "createdAt" to FieldValue.serverTimestamp(),
    "position" to GeoPoint(0.0, 0.0),
)
```
Adobe Targetの小技集 - mboxParameterで配列型情報を扱う時のTips -

Adobe Targetの便利な機能のProfileScriptを使って色々なターゲティングを実現する事は可能です。
しかし、JavaScriptを使ったプログラミングが必要なことであることや、色々な前提知識が必要になります。

[プロファイル属性とは？ | Adobe Target](https://experienceleague.adobe.com/docs/target/using/audiences/visitor-profiles/profile-parameters.html?lang=ja)

## mboxParameterで配列型情報を使いたい場合
通常、Adobe Targetでリクエストにデータを付与して送るには、mboxParameterを使う方法が一般的です。
ここで配列型のような情報をおくる場合に1つの方法としては、カンマ区切り文字列など一定文字列ルールにして送り、Profile Script側でSplitなどで分解する方法です。

例：mboxParameterでtagsという値を送っている場合のProfileScript記述

```javascript
// mboxParameterを取得する
// (値がない場合にnull値をセットするイレギュラー処理も設定)
// 値の例： "カテゴリA,カテゴリB,カテゴリC" と想定
var val = mbox.param('tags') || '';

// 以下の変数はProfileScript内で配列として利用可能
// 例： val = ["カテゴリA","カテゴリB","カテゴリC"]
var tags_list = val.split(",");
```

これで行うのが一番簡単だと思います。ただ、もう1個問題のあるパターンが有りまして…

## Recommendation機能で送っている商品の配列型情報を使いたい場合

これはどういうことかといいますと...Adobe TargetのRecommendation機能を使う時に1つの商品に対してタグのような形で複数の属性情報をもたせることが出来ます。例えばこのような形ですね。

![スクリーンショット 2023-01-22 20.38.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/ad276373-ec30-2baf-31ad-a6aa2c9c1176.png)

このようにデータを送ったときの文字列はちょっと厄介でして…
そもそもこの形で送るときには送付する時にJavaScriptとして配列型で表記される記法にして、それを文字列に変換して送付しています。
この値をProfileScriptで使う時には、送付時の状態のまま…つまり**配列っぽいけど文字列**になってる状態です。
どういうことかといいますと…

上記画像の例で書くと、送付時にentity.itemCategoryという値は```["キッチンツール",インテリア","食品"]```という文字列で送られているので...
ProfileScript内でこの値を取得しますとこうなります。

```javascript
var val = mbox.param('entity.itemCategory')
// => これは '["キッチンツール",インテリア","食品"]'というString(文字列)を返す
```

これだと配列ではないので、普通のJavaScriptであれば、JSON.parse()などを使えば1発で変換可能です。
しかし、Adobe TargetのProfileScript処理はちょっと特殊なJavaScript解析エンジンなのでJSONクラスは使えません。
そこで、ちょっと面倒ですが・・・昔ならではの実装方法が必要です。

ということで、ProfileScriptの中で以下のように記述すると変換できます。

実際に上記のように送られてきた値の配列のうち一番最初の値だけを返すProfileScriptを作ると以下のようになります。
```javascript
// まずは値を取得
var val = mbox.param('entity.itemCategory') || null;

// ダブルクォーテーション区切りの文字列を取得。(正確には".+?"ではなく、[^\"]とかにしたほうが良いかもですが)
var regexstr = /\"(.+?)\"/g;
var categoryArray = [];
var return_string = null;

// 値がある場合のみ実行
if(val){
　 // Regexでループ処理を行い値を取得して結果用の配列にPushしていく
  while((m = regexstr.exec(val)) != null){
    categoryArray.push(m[1]);
  }
  // 値の1個目をピックアップしてProfileScriptとして返却する値に
  if(categoryArray && categoryArray[0]){
    return_string = categoryArray[0];
  }
}

return return_string;
```

このように書くとうまく動きます。
実際に以下のように送ると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/51da8b10-cd16-c0b1-3dc3-6f83c5337fa1.png)

結果的に作ったProfileScriptはこのようにセットされます。
(きちんと3つのうち1つ目の値だけが文字列として取り出せてる状態)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/f0824189-2dc5-29bf-2936-ba929e687a63.png)

> この記述は正規表現がかなり簡易的＋量が多くないので問題なく動いています。文字列が長い場合や、正規表現を複雑に書くとAdobe Target内部のプログラムをパースしているところでエラーする可能性がありますのでご注意ください。
Azureのkustoクエリのアットマークの意味

Kustoクエリにある@"C:\home\user"のアットマークって何？ってずっと思ってたけど、エスケープ文字\の無効化だったんだと最近知ったのでメモ。

まあそりゃクエリに"C:\\home\\user"とか書くのだるいもんな。
flutterのはじめかた ~mac~

# 1. install
```
brew install --cask flutter
```

前置き：Flutterで扱う言語はDartと呼ばれる言語です。

# 2. プロジェクトの作成
コマンドから行います。
```
dart create dart-sample
```
コマンドを走らせたディレクトリ配下に、dart-sampleができています。
vscodeで、dart-sampleフォルダを開きます。

![スクリーンショット 2023-01-23 0.54.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026740/18515c6d-1e70-eb3c-f3b1-83fbce0a1ebc.png)

# 3. プログラムの実行
bin/dart_sample.dart がそれです。

```dart
import 'package:dart_sample/dart_sample.dart' as dart_sample;

void main(List<String> arguments) {
  print('Hello world: ${dart_sample.calculate()}!');
}

```
main関数があるんですが、これを実行する形です。
実行しようとすると、拡張機能入れろって言われるので、いれちゃいましょう。
![スクリーンショット 2023-01-23 0.57.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026740/4297b7a5-a711-0a58-ea4c-cf3cd008f17f.png)

はい、実行

```
Hello world: 42!
Exited
```

ところで、dart_sample.calculate()って何出してるんだろうね。

https://pub.dev/documentation/dart1/latest/dart1/calculate.html

```dart
int calculate() {
  return 6 * 7;
}
```

まさかのこれだった？！
「楽しみながら学ぶベイズ統計(Bayesian Statistics the Fun Way exported)」【オライリーサブスク本紹介】

<iframe width="560" height="315" src="https://www.youtube.com/embed/dUE3xh5r-9Y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

【おすすめ度(5段階)】⭐⭐⭐⭐⭐


【原著】「Bayesian Statistics the Fun Way exported」

https://learning.oreilly.com/library/view/bayesian-statistics-the/9781098122492/

【日本語訳版】「楽しみながら学ぶベイズ統計」

https://www.amazon.co.jp/%E6%A5%BD%E3%81%97%E3%81%BF%E3%81%AA%E3%81%8C%E3%82%89%E5%AD%A6%E3%81%B6%E3%83%99%E3%82%A4%E3%82%BA%E7%B5%B1%E8%A8%88-%E3%82%A6%E3%82%A3%E3%83%AB%E3%83%BB%E3%82%AB%E3%83%BC%E3%83%88/dp/4815604746/ref=sr_1_2?qid=1674401306&refinements=p_27%3AWill+Kurt&s=books&sr=1-2

## テキスト(音声認識）
はいもっさんです
今日はベイジアンスタテックスザファームウェア
という本を紹介します
こちらの本
日本語で「楽しみながら学ぶベイズ統計」
というタイトルで翻訳されて出版されています
こちらの何が良いかと言うと
ベイズ統計を人の頭の中の新年の更新という形で捉えて
わかりやすい例えでベイズ統計を学べる
というところが売りになっています
とりあえず秀逸だなと思ったのが
第１章ベイズ統計の概要を把握するための章でして
まずはその賞だけでも
読んでいただいても良いかと思います
その第１章が終わると
それ以降基本的な統計の要素を
ひとつひとつ積み上げていって
その上でベイズ統計について
深く深持っていくという形になります
そのため統計の基礎が分かっている方であれば
第１章以外の序盤の章については
スキップした上で
後半だけを読むということもいいのかなと思いました
Adobe Targetの小技集 - ProfileScriptの基本 -

Adobe Targetの便利な機能のProfileScriptを使って色々なターゲティングを実現する事は可能です。
しかし、JavaScriptを使ったプログラミングが必要なことであることや、色々な前提知識が必要になります。

[プロファイル属性とは？ | Adobe Target](https://experienceleague.adobe.com/docs/target/using/audiences/visitor-profiles/profile-parameters.html?lang=ja)

## ProfileScriptについて

### 基本
ProfileScriptはAdobe Targetで訪問者ID単位に情報をもたせる訪問者属性付与処理が可能な仕組みです。
使いこなすことで、よりきめ細かいターゲティング処理が可能です。

実際にAdobe Targetにリクエストが送られてから実際にOfferが変えるまでの処理フローにProfileScriptの処理を記載するとこうなります。

pageLoad Request処理の流れ
```plantuml
Browser->AdobeTarget : リクエスト送付
AdobeTarget->AdobeTarget : 各ProfileScriptのプログラムが実行(データ更新)
AdobeTarget->AdobeTarget : 各ActivityのAudience条件を参照しマッチしたもののOfferを準備
AdobeTarget->Browser : Offerを返却
```

### ProfileScriptの書き方Tips

#### 処理量に気をつける
基本的にはJavaScriptで記述をすればOKです。ただ使っているJavaScriptのエンジンの都合上 2000 instrucrtions という制限があり、ヘルプにも以下の制約が書かれています。

- 文字列の長さは1300文字、ループ回数は50回を超えないように
- 正規表現はなるべく単純なものに
- 出来る限りProfileScript自体は小さく、簡単に

よって、例えば数がわからない文字列をSplitで区切ってその後ループ処理・・・などをした時にかなり長いものを処理するとオーバーします。
実際に処理量がオーバーしてしまっているかはすぐに判断ができません。セットした上でActiveにした後、しばらく動いている状態にはなりますが、条件により処理量がオーバーしている場合は、今の添付画像のように強制的にInactiveになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/6202269f-de4a-0f4d-9f2d-086b5e4996a9.png)

その際にエラー部分にマウスカーソルを合わせるとこのようにエラー文が見えます。(2000 instructions 以上になっていると出てます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/6867c961-e4cf-9484-1c2d-8f791900c9e0.png)


#### 値の書き換えをするかしないかをきちんと考える
ProfileScriptの中で書いたプログラムは、処理の流れ上全部のリクエストで必ず通ります。
意図しないようなリクエストで処理が動いた時に書き換えが発生した時に問題ないかを考えましょう。

また、ProfileScriptの中ではreturnすることで値が更新されます。
逆に言うとreturnしなかった場合は**過去に保持した値をそのまま返却**します。

```javascript
// mboxParameterで"user_class"という値を送付が送られた時にその値をProfileScriptで保持しておきたい。
// ただしすべて必ず送られるわけではない…場合。
var val = mbox.param("user_class") || null;
if(val){
  return val;
}
```

逆に言うと、意図的に特定の時だけしか値を返してほしくない場合はnull値を返却するようにしないと過去の値を引き継ぎ続けますので気をつけてください。

#### LocalProfile変数を活用する
プログラムによってはProfileScript内でデータを保持しておいて、なにかそれに応じた処理みたいなものをしたい場合があると思います。(1個前に持ってた値と今の値を比較して…みたいな)

その場合は**localProfile変数**を使うことが出来ます。
これはそのProfileScriptの中でしか参照は出来ないのですが、保持し続けます。(変数スコープが狭まったモノのイメージ)

```javascript
// 変数設定
user.setLocal("{設定したいKey値}","{Value値}");

// 変数利用(取り出し)
var val = user.getLocal("{設定したKey値}");
```
makeコマンド事故防止

## おことわり
ここではMakefileをコマンドのショートカット置き場のような使い方をしている場合を想定しています。

## はじめに

Makefileについてのちょっとした小ネタです。例えばこんなMakefileがあったとします。

```make:Makefile
target_a:
	echo aaaa
.PHONY: target_a

target_b:
	echo bbbb
.PHONY: target_b
```

makeコマンドを引数なしで実行すると、**最初に指定したターゲットが実行されます。**

```sh:引数なしでmakeコマンド実行
$ make
echo aaaa
aaaa
```

このサンプルでは例示用ということもあって `echo` しているだけなので、誤って引数なしでmakeコマンドを実行されても大して問題はありませんが、これが例えば **`rm -rf *` のような実行されたら大規模な影響がある内容** であったりしたら取り返しがつきません。実際にMakefileにそんなコマンド書くことはないですがあくまで例ということで。

## ではどうするのがよいか
ということで、不幸な事故を避ける方法としては、<font color="red">**一番上には何度実行されても問題のない無害なターゲットを置くようにする**</font> ことが簡単かつ安全かなとおもいます。

※もっと良い方法を教えていただきました。詳細は次項にて。

## 安全弁付Makefileサンプル

~~筆者は警告を出すだけのターゲットを置いておく方法をおすすめします。以下はサンプルです。ここでは警告がわかりやすく表示されるように出力に色をつけてますが、事故防止目的なら別にechoしておくだけでもいいと思います。~~ 

@yoshi389111 さんが `.DEFAULT_GOAL` をつかったもっと良い方法をコメントで教えてくださいましたので差し替えました。ありがとうございます。
コマンド先頭の `@` はコマンド自体を出力結果に表示させないようにするためにつけています。

```make:Makefile
.DEFAULT_GOAL = help
help: ## helpを表示
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
.PHONY: help

target_a: ## aaaaを出力
	echo aaaa
.PHONY: target_a

target_b: ## bbbbを出力
	echo bbbb
.PHONY: target_b
```

引数なしで make を実行すると .DEFAULT_GOAL に指定した `help` を実行します。

![defaultgoal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70638/743f1a32-73da-a9c1-fe0d-5958e1ef8e90.png)


## 　参考
標準出力に色を付ける記述はこちらを参考にしました。
https://misc.flogisoft.com/bash/tip_colors_and_formatting

helpを表示させる案は @yoshi389111 さんのコメント、リンク先の方法をそのまま使わせていただきました。ありがとうございます。
https://postd.cc/auto-documented-makefile/
Flutter の in_app_purchaseでGoogle Play Consoleで課金アイテムを作ったのに「The store is unavailable」

# 経緯
FlutterでAndroidのリリースビルドのために準備を済ませて、
`flutter build appbundle`

で.aabファイル（App Bundle）を作成し、Google Play Consoleにアップロードして、アプリを作成したのち、課金アイテムを作成しました。

そしてFlutterのin_app_purchaseというパッケージの使用例
（https://github.com/flutter/plugins/tree/main/packages/in_app_purchase/in_app_purchase） 
を使用したところ、
FlutterのUIで
「The store is unavailable」
との表示が出ました。

# 解決策
Android Studioで
Create Device　> Google Play Storeのアイコンマークがついているデバイス > 作成

Google Play Consoleで
課金機能を実装したいアプリ > テスト > 内部テスト > テスター作成 > リンクを取得

こちらでAndroid Studioの方で作成した Google Play Store対応のデバイスのブラウザに、Google Play Consoleで取得したテスター用のリンクを貼り付けます。

すると、テスター用のアプリがデバイス内にインストールできます。

起動すると、
「The store is available」
の表記が出ています。

# 余談 iOSの場合
iOSバージョンの場合は、リリースビルドを行う段階でApp Store Connectとの連携ができているのか、
「The store is available」
になっていました。
【未経験エンジニア就職希望】ポートフォリオ作成【PHP,Laravel,Docker,Github,AWS】

実務未経験からエンジニア転職を希望しています。
勉強したことやポートフォリオ作成について書いていきます。
アドバイスを頂けると大変うれしく思います。よろしくお願いします。

ポートフォリオ概要（作成期間約1ヶ月）
サービス名：Travel_log
・サイトURL：http://travel-log.xyz
・githubリポジトリ：https://github.com/mana0902/travel_log

旅のしおりとアルバムをまとめて、時系列で思い出を管理できるツールが欲しいと思い作成しました。
課題はたくさんありますが完成させることを目標に作成しました。


+ 使用技術
※実際の開発現場でよく使われている技術を意識して選びました
・PHP8.1.13
・Laravel9(laravelbreeze)
・vite(node.js)
・tailwindcss
・Mysql
・nginx

開発環境
・WSL2
・Docker

本番環境
・AWS（EC2, RDS, Route53)


参考教材
| 教材 | コメント | 
|:-----------|:------------|
| Progate       | HTML,CSS,PHP,Mysqlなどについて初めに学びました        |
| 独学エンジニア     | 山浦清人さんが作成された独学でエンジニアを目指すために必要なことが学べるサービスです。こちらでPHPがよく使われていることを知り、重点的に勉強しようと思いました。MySQL,Docker,Git,データの正規化についても学びました。|
| 【Laravel】マルチログイン機能を構築し本格的なECサイトをつくってみよう【Breeze/tailwindcss】Udemy       |LaravelについてECサイトを作成しながら学びました。本編はLaravel8を使用していましたが、最新版が9だったため差分を調べながら進めました。新しいほど良いのではと思っていましたが新しい技術は参考資料も少ないため無理に最新版を使わなくても良かったように思います。|
| 【AWS】【初心者向け】クラウドシェアNo.1のAWSをとことんやってみよう【わかりやすさ重視】   |AWSへデプロイするためにこちらの教材を参考にしました。          |
|Railsチュートリアル|CRUDやMVC、テスト駆動開発についてWEBアプリをcloud9の環境で作成しながら学びました。|
[MATLAB,Simulink] 技術記事の紹介 (初心者、入門者、おすすめ)

とある現役ソフトウェアエンジニアです。
当方の技術ブログにて、MATLAB、Simulinkに関する技術記事をブログで紹介しています。
初心者、入門者の方、久しぶりにMATLAB、Simulinkを使う方、
急にMATLAB、Simulinkを使う必要が出た方、
さくっと読めますので是非ご覧ください^^

https://toarusw.com/matlab/matlab-basic/



https://toarusw.com/matlab/cmd-func-selected-list/


https://toarusw.com/matlab/simulink-basic/


プロフィールはこちら

https://toarusw.com/profile/

技術記事が増えたら更新します^^


プログラミング、MATALB/Simulinkのスキルで小遣い稼ぎ、副業してみたい、興味があるという方
是非こちらもチェックしてみてください！↓

https://qiita.com/ToaruSWEng/items/08653ac02c3a60c06b35
slappasswdコマンドの書式

slappasswdコマンドの書式

slappasswd [オプション]

●slappasswdコマンド特有の主なオプション
・-s パスワード　ハッシュ化するパスワードの指定
・-h ハッシュ方式　ハッシュ方式の指定
【Laravel】validateメソッドを使ったバリデーション処理

# はじめに
validateメソッドを使ったバリデーション処理について説明します。
Laravelのバージョンは9.43.0です。
# 使い方
validateメソッドは、コントローラの基底クラスに組み込まれている`ValidateRequests`というトレイト(メンバーをまとめてクラスに追加するもの)に用意されている機能です。
第1引数にチェックする項目、第2引数に検証する設定情報を配列にまとめたものを渡します。

``` php
// contorollerファイル
public function post(Request $request) {
    // 検証ルール
	$validate_rule = [
    	'inputタグのname' => 検証ルール1|検証ルール2,
	];
	// validateメソッド呼び出し
	$this->validate($request, [検証ルールの配列]);
}
```

# 使用例
コントローラは下記になります。
validateメソッドの第1引数にチェック項目(今回はリクエスト)、第2引数にバリデーションルールを渡します。
```php
// controller

class HelloController extends Controller
{
    public function index(Request $request)
    {
        return view('hello.index', ['msg'=>'フォームを入力：']);
    }

    public function post(Request $request)
    {
        $validate_rule = [
            'name' => 'required|between:0,150',
        ];
				
				// validateメソッド使用
        $this->validate($request, $validate_rule);
        return view('hello.index',['msg' => '正しく入力されました！']);
    }
}
```

viewファイルは下記になります。
`@errorディレクティブ`は、()に指定した項目のエラーをチェックします。
下記の場合は、nameをチェックします。
このディレクティブ内では、発生したエラーメッセージを`$message`という変数を渡します。
```php
// viewファイル
<p>{{ $msg }}</p>
@if (count($errors) > 0)
    <p>入力に問題があります。再入力してください。</p>
@endif
<form actoin="/hello" method="post">
	@csrf

	<!-- ↓バリデーションエラーのチェック -->
    @error('name')
    	<p>ERROR</p><br>
		<p>{{ $message }}</p>
    @enderror

<p>name: </p><input type="text" name="name" value="{{ old('mail') }}">
</form>
```

# ちなみに
バリデーション結果の反映処理に関して
Laravelのバリデーション機能が自動に行っており、validateを実行して問題がなければそのまま処理の続きを行う。しかしvalidate時に問題が発生すると例外が発生し、その場でフォームページを表示するレスポンスが生成されてクライアントに返信される。したがって、その後に用意された処理は実行されず、フォームが再表示される。

## 参考
https://www.shuwasystem.co.jp/book/9784798060996.html
Visual Studio Code ショートカット Mac版

開発時によく利用するショートカット
バージョン: 1.74.3

# ターミナル

| 機能 | コマンド | 
|:-----------|------------:|
| ターミナルの表示・非表示 | Command + j | 
| 新しいターミナル | Control + shift + j | 
| 次のターミナルグループに移動 | shift + Command + ] | 
| 前のターミナルグループに移動 | shift + Command + [ | 


# 参考
https://support.apple.com/ja-jp/guide/mac-help/cpmh0011/mac
【Linux】コマンドでファイルの数を数える方法

## `ls`コマンド

`ls`コマンドを使用してファイル数を出力するには以下のように実行します。  

```zsh
ls -fp パス | grep -v / | wc -l
```

* `ls -fp パス`  
  ディレクトリ内のファイル一覧を表示。  
  ファイルを並べ替えずドットファイルも含めて表示。  
  ディレクトリの場合`/`を出力。  
* `grep -v /`  
  `/`を含まないもののみ出力。
* `wc -l`  
  出力結果の行数をカウント。

## `find`コマンド

`find`コマンドを使用してファイル数を出力するには以下のように実行します。  

```zsh
find パス -type f | wc -l
```

* `find パス -type f`  
  指定したパス以下の全ファイルのパスを出力。
* `wc -l`  
  出力結果の行数をカウント。
VisualStudioとGit

VisualStudioではGitを使ってバージョン管理ができるが、特にGitをインストールすることなく使うことができる
でも自分はソレを知らずに、わざわざGitを本家からダウンロードしてインストールしていた。

なんでそんなことを思ったのか
それはVS2017（2013もそうだったような）でチームエクスプローラを開くと以下のメッセージが出てくるものだから・・・
![メッセージ01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195648/a6860189-5a7e-e951-f88d-bc7a96edc91e.png)
しかも`インストール`から、本家のダウンロードページにリンクされている
こんなメッセージが出たら、ダウンロードしてインストールしないとダメって思ってしまうよね。
面倒臭いので`今後このメッセージを表示しない`をクリックして消してしまおう。

VS2019以降はそんな表示が出ないので、惑わされないようになったのかな？

因みにVSが使っているGitは、インストールされているフォルダから
\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\cmd
にあるのがそれっぽい。
【Vuetify】v-autocompleteのsearch-inputをデバウンスして0.5秒後に入力された値のみでデータを取得

個人の備忘録です。

# 環境
- vue: 2.7.x（Composition API / script setup)
- vuetify: 2.6.x

# 実現したいこと
- [Vutify の v-autocomplete の検索クエリに基づいて API でデータを取得](https://vuetifyjs.com/ja/components/autocompletes/#section-975e540c671f30a230a430c630e0)
- 0.5秒後に入力された値のみでデータを取得

# 困った点
- [@update:search-input(search-input.sync)](https://vuetifyjs.com/ja/api/v-autocomplete/#events-update:search-input)では、keydown 毎にイベントが発火してしまい、何度も API が走ってしまう。

![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/bc56a812-da82-2bb7-0811-1cb7c7ef011c.gif)

```typescript:変更前
<script setup lang="ts">
省略

interface State {
  value: string;
  isSearching: boolean;
  users: Response[];
}

const state: State = reactive({
  value: '',
  isSearching: false,
  users: [],
});

const onSearchInput = async (searchName: string) => {
  state.isSearching = true;
  state.users = await repository.getUsers(searchName);
  state.isSearching = false;
};
</script>

<template>
  <v-autocomplete
    v-model="state.value"
    :items="state.users"
    // ここが keydown 毎に発火してしまう
    @update:search-input="onSearchInput"
    :loading="state.isSearching"
  >
  </v-autocomplete>
</template>
```

# 解決コード
- JavaScritp の clearTimeout で古いタイムアウトを解除する

![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/17ec06a1-2615-2f08-e30f-11a3aef6d7ea.gif)

```typescript:変更後
<script setup lang="ts">
省略

interface State {
  value: string;
  isSearching: boolean;
  users: Response[];
  timerId?: ReturnType<typeof setTimeout>;
}

const state: State = reactive({
  value: '',
  isSearching: false,
  users: [],
  timerId: undefined,
});

const onSearchInput = (searchName: string) => {
  state.isSearching = true;

  // 古いタイムアウトは解除する
  clearTimeout(state.timerId);

  // 0.5秒後に発火する
  state.timerId = setTimeout(async () => {
    state.users = await repository.getUsers(searchName);
    state.isSearching = false;
  }, 500);
};
</script>

<template>
  <v-autocomplete
    v-model="state.value"
    :items="state.users"
    @update:search-input="onSearchInput"
    :loading="state.isSearching"
  >
  </v-autocomplete>
</template>
```

# 参照
https://stackoverflow.com/questions/56821337/vuetify-throttle-debounce-v-autocomplete

https://developer.mozilla.org/en-US/docs/Web/API/setTimeout

https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout
Webパフォーマンスボトルネックのチェックリスト

# 概要
Webシステムのパフォーマンスが悪くなった際、どの観点で見るべきなのか漏れてしまう可能性があるため、チェックリストとして観点をまとめました。

**※この記事は都度更新して観点を追加します！**

# Webパフォーマンスとは
MDNの「[ウェブパフォーマンスとは](https://developer.mozilla.org/ja/docs/Learn/Performance/What_is_web_performance)」では以下のように解説されています。
> ウェブパフォーマンスとは、遅い処理を速く見せることも含めて、ウェブサイトを速くすることです。サイトがすぐに読み込まれるか、ユーザーがすぐに操作を始めることができるか、何かの読み込みに時間がかかっている場合には安心感のあるフィードバック (ローディングスピナーなど) を提供しているか。スクロールやアニメーションはスムーズか。

今回は下記の2つの点に着目してチェックリストを考えていきます。
1. サイトの読み込み時間を削減する
1. ユーザーが操作可能な状態を早く実現する

## 1. サイトの読み込み時間を削減する
ウェブサイトの表示に必要なファイルが、ユーザーの環境にダウンロードされるまでの時間を削減する方法を考えます。

下記の観点で対応方法を検討します。
- 💽 データを削減する
- 📡 通信回数を削減する


### フロントエンド
- 💽 読み込みリソースを疑う
    - [ ] ファイルのサイズが大きくないか
    - [ ] ファイルの数が多くないか
- 💽 リソースの読み込みタイミングが適切かを疑う
    - [ ] 必要なリソースが[先読み(preload)](https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/rel/preload)されていない可能性を疑う
        - [遅延読み込み(Lazy loading)](https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading)で必要なタイミングだけ読み込む戦略を取れていることもチェックします

### バックエンド
- 💽 発行されるSQLを疑う
    - [ ] データ取得時にスロークエリ、N+1問題が発生していないか
        - データ取得時に遅いクエリ・不必要なクエリ発行は、**レスポンス速度の遅延に直結**します
            - ※ORMを利用する場合は、データ取得時に不要な問い合わせが発生していないかをチェックしましょう
            - [ActiveRecordのincludesは使わずにpreloadとeager_loadを使い分ける理由](https://qiita.com/ryosuketter/items/097556841ec8e1b2940f)
- 💽 レスポンスに含まれるリソースのサイズを疑う
    - [ ] サムネイルに保存画像がそのまま利用されていないか
        - 高画質な画像をサムネイルにそのまま利用すると、レスポンスサイズを不必要に増加させます
        - 適切なサイズに画像を加工し、データサイズが削減されていることをチェックしましょう
        - [Active StorageのVariantの指定方法いろいろ](https://qiita.com/kazuomatz/items/3cdbd2c40576c2e9d89b)
- 💽 レスポンスのレコード量を疑う
    - [ ] 一覧などのレスポンスで、取得したデータをそのまま戻していないか
        - 一覧ページは全データを表示することが多く、全てをレスポンスに含めているとデータ量の増加が直接ボトルネックになるため、ページネーションが実装されていることをチェックしましょう
        - [【Rails】Kaminariを用いたページネーション機能まとめ！導入手順、デザインの変更、日本語化についてまとめて解説](https://techtechmedia.com/pagenation-demo-kaminari/)
- 📡 適切なレスポンスが戻せていないことを疑う
    - [ ] フロント側で画面に必要な情報を作成するため、複数回のAPIを投げさせていないか
        - **フロント:バック = 1:1 の場合のみに限ります**が、画面ごとに最適なレスポンスを戻すことで通信回数が削減されます

## 2. ユーザーが操作可能な状態を早く実現する
ユーザーがすぐに使い始めることができる状態、何を操作すれば良いかを伝えるための方法を考えます。
（ここは情報が薄いので、必要）

下記の観点で対応方法を検討します。
- ℹ️ ユーザーに情報を連携する

### フロントエンド
- ℹ️ ユーザーの優先度の高い情報を表示できているか疑う
    - [ ] 優先度の高い情報を先に読み込めているか
        - ユーザーのアクティビティを考慮した、読み込みフローになっているかをチェックします
            - このフローはUXに直結する部分となるため、チェックリストレベルで考えるものではないと判断しております...
- ℹ️ ユーザーに待ち時間を与えない仕組みになっているかを疑う
    - [ ] リソースの読み込みがバックグラウンドで実施されているか
        - リソース読み込みが非同期処理で行われているかをチェックします

### バックエンド
- ℹ️ ユーザーに連携すべき情報を戻せているか疑う
    - [ ] バリデーションやエラー時に適切なメッセージが戻せているか
        - ユーザーに表示したいエラーがある場合、実装されているかをチェックします
JenkinsジョブをJenkinsfileから作成する

# 概要
GitHubで管理されているJenkinsfileからJenkinsジョブを作成する

- Jenkinsfile作成
- Jenkinsジョブ作成

# 事前準備
https://qiita.com/karaage578tech/items/e6d6f53baf977cf4556b

# 環境
Jenkins 2.375.2（本記事記載時点）

## Jenkinsfile作成
### Jenkinsfileの記法について
DeclarativeとScriptedの２つの記法が存在するが、公式ではDeclarativeを[推奨](https://www.jenkins.io/doc/book/pipeline/syntax/#compare)しているため、
本記事はDeclarativeを前提とする。
またJenkinsfileではGroovyで処理を記載できる。

- [基本的な記法](https://qiita.com/dublog/items/38831adf42e3cfeed66a)


参考：[公式ページ](https://www.jenkins.io/doc/book/pipeline/#declarative-versus-scripted-pipeline-syntax)
### サンプルコード
Helloをコンソールに出力するジョブのサンプル
```
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                sh 'echo "Hello"'
            }
        }
    }
}
```

## Jenkinsジョブの作成
### 手順
1. Jenkinsにログイン
1. 新規ジョブを作成 を押下
    1. ![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118252/0244da86-573d-9ce2-7baf-483052d888b7.png)
1. ジョブ名を入力、「パイプライン」を選択して「OK」を押下
    ![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118252/2b24c366-d91b-9c42-bc5c-3d649d5bee5d.png)
1. General > パイプライン > Pipeline script from SCM を選択
    ![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118252/d5b4ec25-44a3-2dd0-4020-d519f7aa6979.png)

1. SMC > git を選択し、Jenkinsfileを管理しているGit情報を入力して「保存」を押下
    ![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118252/b9d16335-4ba3-1542-d8a4-8c50da458afc.png)

1. job作成完了

1. 作成後の動作確認
    1. 作成したジョブを「ビルド実行」から実行
        ![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118252/55c44443-4ad2-a768-9730-8c4e02e1b372.png)
    1. コンソールログを確認し「Hello」が出力されていればOK
        ![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118252/26bd0325-0bc7-1efe-5598-acb8c6e65ae0.png)
サイバーセキュリティ切り抜き

https://internet.watch.impress.co.jp/docs/column/security/1469875.html


https://flatt.tech/magazine/entry/20230119_security_trend


https://www.itmedia.co.jp/enterprise/articles/2301/19/news127.html

https://news.mynavi.jp/techplus/list/headline/enterprise/security/2023/01/

https://atmarkit.itmedia.co.jp/ait/articles/2301/20/news051.html

https://news.yahoo.co.jp/articles/4bbff30c97b914a56c0ef9b5cdd15c2cb7e24e78
チャネルのスレッドとSharePointリストを連携させる（概要編）

# はじめに
この記事は①概要編 ②受付フロー編 ③更新フロー編 の3本立てのうち、①概要編です。
以降の記事でフローの細かい解説を予定していますが、待ちきれない方はこの記事の最終にサンプルフローを用意しておりますので、そちらからご確認ください。

# 発想の経緯
## 業務におけるありがちな問題点
Formsを起点としてSharePointリストに項目を作成して一覧として管理、と同時に通知としてTeamsにメッセージを投稿する。というフロー、よくあると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/298d1e93-aab9-f1c5-29e8-90e56e7fe8c0.png)
対応に漏れがないようにリスト管理するはずが、通知メッセージに返信の形でチームメンバーとコミュニケーションをとった結果、なんだかんだ解決→リストの更新を置き去りにしてしまう、ということがありました。

漏れがないように一覧管理しているはずが、管理と通知が別の場所にあるため起こった問題です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/403a2d88-3081-7f84-2a21-e08a1c58b7c3.png)

## やりたかったこと
リストとチャネル、どちらか一方で管理とやり取りができればよいのですが、メンバーがチャネルでのやり取りに慣れていたため、今回はTeamsのチャネルからリストを更新する方法を考えました。

リストアイテムのコメントでメッセージをやり取りしてもよかったのですが、以前からの方法に合わせた形です。

## つくったもの
ということで、作ったものがこちらです。


https://twitter.com/ksgiksg/status/1616809735558430721?s=20&t=Ix4Mr_9TwoZzhNEMYp6rTA

# フローの簡単な解説
## 失敗例①「アダプティブ カードを投稿して応答を待機する」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/2cbbb310-e705-602c-0815-646ecba86bbc.png)
初めに思いついたのがこのアクションを使う方法です。
このアクションでユーザーからの応答を取得し、その情報からリストを更新することは可能でしたが、次のような問題がありました。
- 投稿からは1回しかリストを更新することができない。
- 更新後(Action.Submit)に元のカードが消えてしまう。
- フローの制限から長期的な案件が管理できない。（30日でタイムアウト）

元のカードが消えてしまう問題に関しては以下のアクションを使って解決することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/0c5a4d51-893f-e997-eac4-6011dbf02d4a.png)
しかしながら、1回しか更新できないという問題が解決できず、この方法は廃案としました。
(状況を都度更新したかったため、複数回更新する必要があった)

## 失敗例②「誰かがアダプティブ カードに応答した場合」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a759e541-73c6-b35e-c748-49874689cb7d.png)
次に考えたのはこのトリガーを利用する方法です。
このトリガーでは、投稿からの応答を何度でも取得することが可能です。
ただし、今回のケースでは問合せごとにチャネルに通知が投稿されるため、複数のカードが投稿されます。
どのカードから応答があったのか、そして「そのカードとセットになっているリストの項目がどれなのか」を直接特定する情報がトリガーのアウトプットにはなかったため、リストを更新することができませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/0b946ef4-1774-5a4d-9523-5966a6d14a71.png)

## 解決策
アダプティブカードにテキストとしてリストのIDを記載することにしました。
「メッセージ詳細を取得する」アクションから、カードに記載したリストIDを抽出することで、関連するリストアイテムを特定しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/62eebe78-621a-236f-56fd-11715e12f480.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/c902ebc3-7a4b-67d3-34eb-a886a3f65c39.png)


# フローをGithubに保存しました
この２つのフローはセットで動きます。
詳しい解説は次回行います。

https://github.com/ksgiksg/Power-Automate/blob/main/%E3%83%81%E3%83%A3%E3%83%8D%E3%83%AB%E3%81%AE%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%81%A8SharePoint%E3%83%AA%E3%82%B9%E3%83%88%E3%82%92%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%8B%E3%80%90%E5%8F%97%E4%BB%98%E3%83%95%E3%83%AD%E3%83%BC%E3%80%91)_20230122134124.zip

https://github.com/ksgiksg/Power-Automate/blob/main/%E3%83%81%E3%83%A3%E3%83%8D%E3%83%AB%E3%81%AE%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%81%A8SharePoint%E3%83%AA%E3%82%B9%E3%83%88%E3%82%92%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%8B%E3%80%90%E6%9B%B4%E6%96%B0%E3%83%95%E3%83%AD%E3%83%BC%E3%80%91)_20230122134157.zip

今回は以上です。
***


https://qiita.com/ksgiksg/items/7c55ed74a74a668f3432

https://qiita.com/ksgiksg/items/cf2d9bfddb64cc543965
【最低限】Laravel Sailを使った開発環境構築

## Laravel Sail って何？
Laravlの開発環境をさくっと簡単に作成でき、
軽量CLIインターフェースでLaravelへのコマンド操作を行えます。

今回はMac＆Dockerで環境を構築します
Dockerがインストールされている前提で進めます

## プロジェクトの作成
"foo-project"というプロジェクト名で作成する場合は以下のコマンドをターミナルで実行します
```bash
curl -s "https://laravel.build/foo-project" | bash
```

だいたい5分くらいかかった後でMacのパスワードを求められました。

```bash
Please provide your password so we can make some final adjustments to your application's permissions.

Password:
```

正しいパスワードを入力できればsailコンテナのビルド完了です
```bash
Thank you! We hope you build something incredible. Dive in with: cd foo-project && ./vendor/bin/sail up
```

## コンテナを起動してアクセス
アプリケーションディレクトリに移動して、
Laravel sail を開始します
```bash
cd foo-project
 
./vendor/bin/sail up
```

こうなってればOKですメッセージが出てくるけど気にしなくて大丈夫です
```bash
selenium_1 exited with code 0
```

コンテナを起動できたので http://localhost にアクセスしてみましょう
welcomeページが表示されれば成功です

ちなみにアクセスしたらターミナルにメッセージが表示されます
```bash
laravel.test_1  |   2023-01-22 13:38:18 ................................................... ~ 1s
laravel.test_1  |   2023-01-22 13:38:18 /favicon.ico ...................................... ~ 1s
```

## コンテナ起動時のエラー
```
Error response from daemon: driver failed programming external connectivity on endpoint foo-project_mysql_1 (64be11dc6922ce667f1f63ce0ac58f117936f0bfb27cdbd054bf97d7669dbf56): Bind for 0.0.0.0:3306 failed: port is already allocated
```
同じポートを使用していたのでエラーになりました。
Sail側を変えられそうになかったのでもともと起動していたコンテナのポートを変更したら解消しました。

## まとめ
便利になりましたねー
Web技術の基本 Chapter1 まとめ

## webについて

- 文書や画像などの公開のためのシステムをwebという。
- URLリンクのwwwはworld wide webの略である。
- web上の画面を構成しているのがHTML(Hyper Text Markup Language)であり、ハイパーリンクを通じて他のページへ遷移できる。
- webページ同士が繋がっているので、蜘蛛の巣上になることが特徴。

## インターネットについて

- 元々は実験者たちがすぐに情報を取得できるようにwebの原型となるシステムができた。
- インターネットは、ARPAによって戦争での情報戦として開発された。
- インターネットとwebは別々のものであり、それらが組み合わさって爆発的に普及した。
- インタネット→通信や各地の拠点を繋いでいる。
- web→インターネット上で動く文章をより見やすく動くように仕組み化したもの。

## webの用途

- 1つのドメインにある複数のwebページの集まりをwebサイトという。
- コンピュータとユーザーのやりとりを橋渡ししたものはユーザーインターフェイスという。
    - 人間とコンピュータとの接地面(人間がやりたいことを機械語にしてくれる)がユーザーインターフェイスであり、そこが良いユーザー体験につながる。
- API(プログラミングインターフェイス)
    - ソフトウェア同士の架け橋の役割をするもの
    - アプリ → サーバー(情報を処理して、送信) → アプリ　の順で通信をする。
    

## HTMLとweb

- HTML(Hyper Text Markup Language)は、マークアップ言語と呼ばれる。
    - タグで囲むことでハイパーリンク(他のページに飛ぶ技術)であることを表したり、文章を表すことができる。
    
    (例)<title>タイトル</title>
    
- Webブラウザは、人間が読むことは困難であるHTMLを作り替えて表示することができる。

## webサーバーとHTTP

- webサーバーとは、ブラウザからの要求に対して適切なwebブラウザを送信する役割のこと。
- 一般的には、apacheやIIS(internet information service)が使われる。

　webブラウザ　→　サーバーに要求→返信　→　webブラウザに表示

- HTTP(Hyper Text Transfer Protocol)とは、サーバーとのやりとり手順のこと。
    - メッセージの送り方や書式までHTTPで決められており、どんなwebブラウザやサーバーでもHTTPという共通ルールでやりとりしている。

## webページが表示される流れ

- webページを取得する時にURL(uniform resouce locator)で取得したいwebページを取得。
    - このURLは、「どの手順」で「どのどのサーバー」に「なんのコンテンツ」をとりにいくかを表す。
- HTMLをブラウザが解釈してみやすいwebページができる。

(例)http://www.sbcr.jp/index.html

http → HTTPを使ってアクセスしている

[www.sbcr.jp](http://www.sbcr.jp) → www.sbcr.jpというサーバーにアクセスする

index.html →　ファイル検索している

## 静的ページと動的ページ

- 何度アクセスしても同じページを表示されるwebページを静的ページと呼ぶ。
    
    (例)企業ページなど
    
- アクセスした時の状況によって情報が異なるwebページを動的ページと呼ぶ。
    
    (例)yahooやブログサイとなどのSNSなど
    

## 動的ページの仕組み

- webサーバーがブラウザに対してプログラムを起動させるための仕組みをCGI(Common Gateway Interface)と呼ぶ。
    - 動的ページを動かすにはCGIが示すURLにアクセスすることでプログラムが起動。webサーバーが持っているデータなどからHTMLを作り出す。
- CGIから呼び出されるプログラムはサーバーサイド・スクリプトと呼ぶ。
    - 文字列の扱いに長けたものをスクリプト言語という。(ruby,python,javascript)
- HTMLに直接埋め込まれるプログラムをクライアントサイド・スクリプトという。(javascript)

## webの標準化

- HTMLなどを使っていると、開発者それぞれが独自に拡張を作ってしまうので、しっかりとした規格を決めるための作業を標準化という。
    - webの標準化を行う団体をW3Dという団体である。
    

## webの設計思想

- シンプルな設計をする4つの原理をREST(REpresentation state Transfer)という。
    - このRESTに従って設計されたシステムをRESTfulなシステムとよぶ。
    
    ### RESTの原理
    
    - 統一インターフェース
        
        あらかじめ決められた方法(HTTPなど)の情報でやりとりしている。
        
    - アドレス可能性
        
        全ての情報が一意なURLである。
        
    - 接続性
        
        やりとりされている情報にリンクを貼れる。
        
    - ステートレス性
        
        やりとりは一回ごとに完結し、前のやりとりの結果を受け付けない。
[nodejs]mysql2のpool.queryをネストさせたら動かなくなった事象を解消した例

## 何が起きた？

下記のようなロジックを作ったところ、`入ってる`まで通るけど最後のpool.queryに入らずupdateできないことがありました。

```js:test.js
var mysql = require('mysql2');
const pool = mysql.createPool({
  host: '127.0.0.1',
  user: 'root',
  password: 'password',
  database: 'test_db'
});

// 関数呼び出し
test();

// 呼び出し用の関数準備
function test() {
  pool.query("select * from emails", function (err, factDatas, fields) {
    for (const obj of factDatas) {
      pool.query(`select * from users where id = ${obj.user_id};`, function (err, user_rows, fields) {
        console.log("入ってる");
        pool.query(`update emails set new_user_id = ${user_rows[0].new_id} where user_id = ${obj.user_id};`, function (err, result, fields) {
          if (err) throw err;
          console.log(result);
        });
      });
    }
  });
}
```

## 解決方法
下記のように関数を切り出す（分割する）ことで動作しました。

```js:test.js
var mysql = require('mysql2');
const pool = mysql.createPool({
  host: '127.0.0.1',
  user: 'root',
  password: 'password',
  database: 'test_db'
});

// 関数呼び出し
test();

// 呼び出し用の関数準備
function test() {
  pool.query("select * from emails", function (err, factDatas, fields) {
    step1(factDatas);
  });
}
// 分割した
async function step1(factDatas) {
  for (const obj of factDatas) {
    step2(obj);
    await sleep(300); // スリープ処理を追加する
  }
}
// 分割した
function step2(obj) {
  pool.query(`select * from users where id = ${obj.user_id};`, function (err, user_rows, fields) {
    console.log("入ってる");
    step3(user_rows, obj);
  });
}
// 分割した
function step3(user_rows, obj) {
  pool.query(`update emails set new_user_id = ${user_rows[0].new_id} where user_id = ${obj.user_id};`, function (err, result, fields) {
    if (err) throw err;
    console.log(result);
  });
}
// sleep関数を準備
function sleep(time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
}
```



## 原因の予想
正直挙動を理解しきれていませんが、筆者としては処理が早すぎてupdateのトランザクションで弾かれたか、またはデッドロックになったのではないかと予想しています。
Burikaigi2023に行ってきた

久しぶりにオフライン開催された[Burikaigi2023](https://burikaigi.dev/)に行ってきたのでその記録。（登壇者敬称略）

# 井上 章「.NET 7 で加速する "Code-to-Cloud" アプリケーション開発」

会場着が遅れたので途中から。
説明の中で、WebUIフレームワークとWebAPIフレームワークを分けて紹介されてたのが印象的だった。確かにそういう棲み分けであるべき世界な気がする。

# 伊藤 敬「2023 Java最新トピック - JavaOne 2022 Keynoteなどから」

やっぱり生でお話を聞けるのはいいなぁ、という感想。
また、天下のOracleでさえもJava8を切り捨てられないのか、というのも印象的だった。

# 和田 卓人「サバンナ便り - 自動テストに関する連載で得られた知見のまとめ」

生t_wadaさんのお話。雑誌連載のダイジェスト版。
個人的に今回一番面白かった内容で、今まで経験的に感じてたことに名前が付き、体系がまとめられていく感覚があった。
あと、TDDとかのテスト界隈が、今までは「テクニック先行の傍流の人たち」みたいな印象で見てたのが、実はソフトウェア開発の背骨を通しなおそうとしている、というイメージに変わったのがとても大きかった。

# 櫻庭 祐一「Virtual Thread - 導入の背景と、効果的な使い方 -」

ご本人がおっしゃられたとおり、背景の説明が大半。なんか学生時代の授業のような感じだった。
説明されたVirtualThreadの実装は、まだ実装が厚すぎる印象をうけたが「使いやすい」という目的からは仕方のない部分なのかもしれない。
あと、寺田さんの補習授業になってたのが、見ていて楽しかった。

# 吉島良平 with 中村亮太「マイクロソフトビジネスアプリケーション漫談-俺たちが見てきた『攻め』と『守り』のDX【業種別編】」

すみません完全Awayでした。まぁでも違った角度の話が聞けるのも、こういうイベントの醍醐味。

# Yuku Kotani「GraphQLスキーマ設計の勘所」

正直「GraphQLとはなんぞや」という前知識しかなかったのだけど、途中から「これって、オブジェクト指向データベースがやりたかったことでは？」と気づいてからはしっくりきた。

# takanorip「Astroで始める爆速個人サイト開発」

Web方面のお話。知らない世界ではあるけど、聞いておくととっかかりになる。
私に刺さらなかっただけで、お話自体は面白かったです。

# もやし丸「ポケモンSVのレンタルチームを検索するアプリを作ってみた」

データ入力とかどうしてるのかなぁ？と思ったけど、今は手作業で間に合っているらしい。
OCRするか、固定文言画像で一致判定とかするといける？
ただご本人もおっしゃられてた、組み合わせ量がはんぱなさそうではある。

# nus3「10 年続くプロダクトのフロントエンド刷新プロジェクトのふりかえり 〜 そして、その素直な現在地 〜 (仮)」

部分リプレイスのお話とか、目立たないけど地道に頑張っていますという内容。みんなでコツコツやりましょう。
GuardDuty Malware Protectionの挙動

# はじめに
昨年リリースされたMalware Protectionを利用する機会があったので、挙動をまとめておきます。

https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/malware-protection.html

# Malware Protectionとは
>GuardDuty Malware Protection は Amazon GuardDuty の拡張機能です。GuardDuty は、マルウェアによって既に侵害されたリソース、または危険にさらされているリソースを特定します。Malware Protection は GuardDuty のサポート機能として、この侵害の原因として疑われるマルウェアを検出します。

公式では上記の通り説明があります。完結にいうとGuardDutyでマルウェアを検知（削除とかは実施できない）可能という内容です。名前の通りの機能ですね。

# 仕組み
![スクリーンショット 2023-01-22 22.18.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584167/34605420-5e57-5266-3ca8-8d00a28a4d27.png)

簡単にまとめると上記の絵の通りです。
まず、スキャンの前提として、GuardDutyの検知が条件となります。
GuardDuty側でマルウェアの挙動を示すような疑わしきイベントが発生すると、対象のEBS、ECS（Fargateは未サポート）で利用しているEBSに対してスナップショットの作成を実施します。作成されたスナップショットから、レプリカボリュームをサービスアカウントに作成し、対象ボリュームのスキャンを開始します。この際、対象のEBSはKMSで暗号化されていても問題ありませんが、IAMロールとキーポリシーの設定が必要です。なお、スキャンは２４時間に１回となるため、２４時間以内に複数のイベントを検知しても、１度しかスキャンされません。スキャンの結果マルウェアが検知されなかった場合、スナップショット、レプリカボリュームは削除されます。検知した場合、設定でスナップショットを残しておくことも可能です。２４時間に１回の実施、スキャンの前提には要注意ですね。

# 有効化する上での留意事項はあるか
上記で説明したとおり、スキャンはレプリカボリュームに対して行われるため、性能面での影響はほぼないと考えて良いでしょう。有効化における障害は特にないですが、検知後のアクションは考えておいたほうがよいですね。
本機能はあくまで、検知のみですので、マルウェアの挙動を止めることはできません。

# 検知後のアクションとして考えられる対応
上記で説明したとおり、検知までがGuardDutyで実施される対応です。その後の対応は、自身で実施する必要があります。検知内容をメールやSlack等で通知するのはもちろんですが、検知した場合のフローを事前に決めておくことが必要です。可能であれば自動化することが望ましいでしょう。以下は対応の例となります。
EventBridgeからLambdaを呼び出し、対象のEC2の隔離と分析のためのスナップショット作成までを自動化する構成です。もちろん、検知した場合の対応は運用の中で定めておく前提となります。
AWS上でのインシデントレスポンスの方法論については、以下のURLも参考にしてみてください。

https://aws.amazon.com/jp/blogs/news/forensic-investigation-environment-strategies-in-the-aws-cloud/

![スクリーンショット 2023-01-22 22.37.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584167/fc4190fc-f0af-d56f-b1ca-c91751917c96.png)

# EC2へのウイルス対策製品が不要となるのか？
結論不要とはならないと考えます。GuardDutyはあくまでマルウェアの検知までで、マルウェアの動作を停止したり、削除する機能は持ち合わせていません。また、スキャンについても、GuardDutyで疑わしいイベントが発生した場合に限られるため、定期的なスキャンや、GuardDutyで検知されない状態でのリアルタイムのスキャンはおこなわれません。そのため、EC2の中でのマルウェア対策は別途必要となります。あくまで多層的な防御として有効化することが望ましいです。以下にGuardDutyとTrendMicroの製品の比較が詳細に記載されていたので、参考に貼っておきます。

https://www.trendmicro.com/ja_jp/business/campaigns/aws/resources/guarddutymalwareprotection.html

# まとめ
GuardDutyでのマルウェア検知は非常に有効な機能だと思います。
設定の有効化はすぐにでもできるレベルですし、多機能にも影響を及ぼすものではないので、基本的に使わない理由がありません。
ただし、有効化するのはよいですが、検知した場合にどのような対応をとるのか、対応の自動化は可能なのかを必ず事前に検討するようにしましょう。
DenoでPuppeteer動かしてみた

Denoの存在は知っていたけど特に触る機会もなかったので放置していました
一応インストールだけはしていた

ちょっと調べてみたらDenoでTypeScriptがそのまま動かせることや、Puppeteerも用意されているとのことだったのでTypeScriptでPuppeteerを動かす最小限のスクリプトを書いてみました

ちなみにインストールは以下のコマンドでOK
```bash
curl -fsSL https://deno.land/x/install/install.sh | sh
```

インストールしたのがちょっと前だったのでまずはアップグレードしてみました

```bash
deno upgrade
```

```
Looking up latest version
Found latest version 1.29.4
Downloading https://github.com/denoland/deno/releases/download/v1.29.4/deno-x86_64-unknown-linux-gnu.zip
Deno is upgrading to version 1.29.4
Archive:  /tmp/.tmpB2ijqw/deno.zip
  inflating: deno
Upgraded successfully
```

Denoのインストールもバージョンアップも簡単すぎる！

# ひじょうにかんたんなコードを用意する

```typescript:index.ts
import puppeteer from "https://deno.land/x/puppeteer/mod.ts";

const browser: object = await puppeteer.launch();
const page: object = await browser.newPage();
await page.goto("https://www.google.com/");
await page.screenshot({path: "/dev/shm/deno-puppeteer-sample.png"});

await browser.close();
```

# 実行してみる

```bash
deno run -A --unstable index.ts
```

おや？エラーが出るぞ？

```
Warning Implicitly using latest version (16.2.0) for https://deno.land/x/puppeteer/mod.ts
error: Uncaught Error: Could not find browser revision 1022525. Run "PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts" to download a supported browser binary.
      if (missingText) throw new Error(missingText);
                             ^
    at ChromeLauncher.launch (https://deno.land/x/puppeteer@16.2.0/src/deno/Launcher.ts:99:30)
    at async file:///home/sakura/src/my_projects/typescript/pairs/index.ts:3:25
```

`Run "PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts"` とあるのでこれを実行してみます

```bash
PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts
```

ちょっと時間がかかりましたが、終わったので再度実行してみます

```bash
deno run -A --unstable index.ts
```

無事に終了し、指定した場所にスクショが生成されていました！

# 結果

![deno-puppeteer-sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426191/12b7f66f-0d8e-09b2-077a-c4e53edefa71.png)

非常に簡単にTypeScript + Puppeteerを使えそうです

今後スクレイピングとかするときのスクリプトはDenoで動かそうと思います

---

それでは良いDenoライフを！