OmniAICreator/Qiita-1.07M huggingface dataset:
動画生成AIで「見たい広告」へ

# インターネット広告がなぜ嫌われているのか

インターネット広告、嫌われ者ですよね。
なぜ嫌われるのでしょうか。

一般社団法人 日本インタラクティブ広告協会（JIAA）が、2022年インターネット広告に関するユーザー意識調査「定量調査」をおこなっています。

調査では、インターネット広告のイメージとして

- しつこい／不快：**35.8%** 
- 邪魔な／煩わしい／うっとうしい：**34.0%** 
- いかがわしい／怪しい：**23.2%**
- 誤解を招く／虚偽感：**19.6%**

が挙げられています。

https://www.jiaa.org/news/release/20231017_user_chosa/

また、＠DIMEによる「Web上で流れる動画広告について」という別の調査では、

- 本編を邪魔される：**81.9%**
- 興味がない商品やサービスの広告が流れる：**59.5%**
- 何度も同じ広告が流れる：**41.4%**
- 広告自体面白くない：**37.5%**

が嫌う理由に挙げられています。

https://dime.jp/genre/1077857/

この中で「**しつこい**」や「**何度も同じ広告が流れる**」に対しては、「動画生成AI」の技術で解決できると考えています。

# 動画生成AIをどう使うのか

2024年になってから、[OpenAI Sora](https://openai.com/sora) や [Runway](https://runwayml.com/) などの動画生成AIの技術が進化し、もはや実映像との見分けがつかないレベルに達しています。

見たことが無い方は是非リンク先を見てみてください。これ実写じゃないの？と思うほどすごいです。

## 動画広告の作成の流れ

ポイントは、この動画生成AI技術を使って、広告を無数に作成させるということです。

以下が作業の流れです。

- 字幕・BGM・ナレーション・企業ロゴ、等を素材として準備しておきます
　↓
- プロンプトを調整して、動画広告を大量に生成します
　↓
- 各動画に対して、最初に準備した素材を機械的に合成処理します
　↓
- 作成物を人がチェックして、OK/NGの最終判別をします

これで、大量の広告コンテンツが完成します。

素材のパターンは少なくても、映像はバラエティに富んでいるので、企業イメージの統一感を持った動画が大量に完成します。

## 完成した動画広告をどう使うのか

それぞれのユーザーには、大量の動画広告のうち、ランダムに1つ表示させます。
既に見た動画が再生される確率が低いので、毎回異なる動画が流れることになります。
「しつこい」や「何度も同じ広告が流れる」の不満が無くなるのです。
そして、広告が一期一会になります。

## そして見たい広告へ

動画生成AIの技術はすさまじいため、感動するようなすばらしい動画ができる可能性も高いです。
すばらしい動画広告ができても、上記の方法だと全てのユーザーが見られませんね。
これは一見デメリットに思えますが、人は「素晴らしい動画があるようだけど、なかなか出会えない」という、いわゆる **レア度** を強調されると、逆に見たくなるものです。
誰かがキャプチャーした動画広告をインフルエンサーに手によって拡散させるまでの動きになれば、宣伝効果は期待以上のものになります。

**嫌われる広告**から**見たい広告**へ、劇的に変われる可能性があります。
広告業界の新たなビジネスの可能性が、そこにある気がします。
フロー保存時に重複がある場合の回答例



# Notification_Case_for_Large_Account-1 already exists.

+ [Create an Automation with Flow Builder /](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ajTaN)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cd0b2ac9-3553-bd92-ea68-4578207177be.png)

:::note
I think a flow with the same name already exists.
Try saving it under a different name, deleting the old flow, and saving it with the same name.
:::
関わらない方がいいグループ

閉鎖的なグループみたいです。メンバーでないので以下のグループの質問はスルーします。

+ [Commons Project: Salesforce Indicators](https://trailhead.salesforce.com/trailblazer-community/groups/0F94S000000HEDASA4?tab=discussion&sort=LAST_MODIFIED_DATE_DESC)


https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLQ9r
[Python]boto3でAWSを操作する(S3, DynamoDB, Lambda)

# はじめに
副業でPythonを使用してAWSを操作する方法を学んだので、書いていきます。

# boto3をインストール
Pythonを使用してAWSを操作するには「boto3」ライブラリをインストールして使用します。

まずは、以下のコマンドでboto3をインストールします。
```
pip install boto3
```

次にファイルの先頭でboto3をインポートします。
``` py
import boto3
```
これでboto3を使用する準備は完了です。

# サンプルコード
今回は、S3、DynamoDB、Lambda(関数を呼び出す)についてのサンプルコードを書いていきます。

## S３
S3のオブジェクトを操作するサンプルコードを書きます。
以下は、あるバケットのオブジェクトの一覧を取得するコードです。
``` py
client = boto3.client('s3')

# バケット名を指定
bucket_name = 'your-bucket-name'

# バケット内のオブジェクト一覧を取得
response = s3.list_objects_v2(Bucket=bucket_name)
objects = response.get('Contents', [])

for obj in objects:
    print(f"- {obj['Key']}")
else:
    print(f"{bucket_name} バケットにオブジェクトはありません。")
```
このコードは、「list_objects_v2」で指定したバケットの辞書から「Contents」というキーを指定して、その値を取得しています。

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html

## DynamoDB
S3を操作するサンプルコードは以下になります。

``` py
client = boto3.client('dynamodb')


# 更新対象のテーブル名
table_name = 'sample_table'

# テーブルの取得
table = dynamodb.Table(table_name)

# 更新するアイテムの主キー
primary_key = {
    'user_id': 'value'
}

# 更新するデータ
update_expression = 'SET attribute1 = :val1, attribute2 = :val2'
expression_attribute_values = {
    ':val1': 'new_value1',
    ':val2': 'new_value2'
}

# 更新処理の実行
response = table.update_item(
    Key=primary_key,
    UpdateExpression=update_expression,
    ExpressionAttributeValues=expression_attribute_values,
    ReturnValues='UPDATED_NEW'  # 更新後の値を返す
)

# 更新後のアイテムを出力
print("Updated Item:", response)
```

こちらのコードは、「sample_table」という名前のテーブルに対して、「user_id」をキーにして、そのキーに一致したデータに対して、「expression_attribute_values」で指定した値を挿入しているコードです。
ほかにも、テーブルの作成、データの新規登録、削除などの様々な機能があります。

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html

## Lambdaを呼び出す
Lambdaを操作するサンプルコードは以下になります。
以下は、「my-lambda-function」という名前のLambda関数を呼び出しているコードになります。
``` py
client = boto3.client('lambda')

# Lambda関数名を指定
function_name = 'my-lambda-function'

# ペイロード（引数）を指定
payload = {
    'key1': 'value1',
    'key2': 'value2'
}

# Lambda関数を呼び出し
response = lambda_client.invoke(
    FunctionName=function_name,
    InvocationType='Event',  # 非同期呼び出し
    Payload=str(payload)  # ペイロードを文字列に変換
)
result = response.get('Payload').read().decode('utf-8')
print(f"Lambda関数の実行結果: {result}")
```
このコードでは、**「FunctionName」で指定した関数名と一致するLambda関数**を呼び出し、「InvocationType」で**同期か非同期化の指定**を行い、「Payload」で関数に引数を渡しています。

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html

# まとめ
今回はS3、DynamoDB、Lambdaの3つの操作について書きましたが、boto3はたくさんのAWSの機能を呼び出すことができます。
以下が、boto3を使用して呼び出せるAWSの機能の一覧です。

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html

# 最後に
他にも色々な記事を書いているので、よければ読んでいってください！

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/2c07c52ff3386d5d75b9

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
upLaTeXの初期設定#1

# upLaTeXの初期設定方法その1

LaTeXを始めるにあたり、様々な方が様々なページでインストール方法から設定方法まで記載しているが、大体どれを見ても自環境ではエラーが出て解決策を探すのに数時間～数日費やすのは珍しくない。
そこで、__あくまでも私の環境構築で__ の構築方法並びに発生したエラーについて(思い出せる範囲で)その内容と対処方法について複数回に分けて記載していく(続くとは言ってない)。

## 環境

- windows 10 Pro
- TeX Live 2021(以降であれば基本同じ)
- Visual Studio Code(以下、VScode)

## TeX Liveのインストール

i7-7700で4時間ぐらい、i7-12700で1.5時間ぐらい、i9-13900Kで30分ぐらいかかった。
ただただ待つだけではあるがインストール後Pathが通っているか確認した(upLaTeX、XeLaTeX、latexmk、mktexlsrぐらいは確認した)。インストール後の再起動はおまじない。

## VScodeのインストール

公式サイトからダウンロード、インストールした。日本語化拡張機能とLaTeX Workshopをとりあえずインストールしたが、なんだかんだLaTeXと銘打つ拡張機能を片っ端からインストールしたような記憶もある(VScode内のMarketplaceより)。

## latexmkrcファイルの作成

.texから.dviや.pdfへコンパイルする際にupLaTeX→upBiBLaTeX→upLaTeX→upLaTeX→upLaTeX→dvipdfmxのように特定の順番かつ一定回数TeXエンジンを走らせる必要があるのはわざわざ記す必要がない情報ではあるが、これを毎回順番に走らせるのはかなりめんどくさい。
そこで最初からレシピ(上記コンパイルの順番や最大繰り返し回数などを記載したもの)を用意してそのレシピに基づいてコンパイルするのが一般的であり、このレシピが%\USERPROFILE%直下に保存する.latexmkrc(latexmkrcファイル)である。
本記事ではlatexmkrcファイルの中身には触れないが、ドキュメントクラスとTeXエンジンの不一致(jsarticleをpLaTeXでコンパイルする等)をするといつまでもコンパイルできないだけでなくlatexmkrcの書き換えを伴う場合がある(そうならないようにTeXエンジンの指定も自動でするようにすれば問題ないだけではある)。

## その他の設定

.latexmkrcの場所をLaTeX Workshopに教えてあげるために設定を書き換える。

## エラー事象

### latexmkでコンパイルできない

→先述の通りドキュメントクラスとTeXエンジンの不一致が原因。TeXエンジンの指定をする前に自動で切り替えるように設定した([参考](https://qiita.com/kazukiM-k/items/015bc26467c1997505cc))。

### それでもコンパイルできない

→コマンドの綴りミス等はさておき、ファイルパスの文字数制限かも(perlの仕様)。

### 別端末のVScodeではコンパイルできない

→.latexmkrcの場所指定が正しくない。(ユーザー名が同じ(だと信じて設定したとしても)%USERPROFILE%等の環境変数を使って指定するのが無難)

## まとめ
その2があるかは未定
【サクラエディタ】CSVの中身をカラムごとにきれいに見たい

## はじめに
CSVファイルをそのまま開くとデータが正しく表示されないことがあるので、サクラエディタで開く方も多いかと思います。
設定なしでサクラエディタで開いてもデータを見ることはできますが、データ量が多ければ多いほどごちゃっと見えてしまいます。

今回は、少しの手間でデータを見やすく設定する方法についてご紹介します。

## サクラエディタ設定前だと。。
カンマ区切りで、ずらっと表示されます。

▼ CSV
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726107/cd3bdf07-967d-5b2d-ae8a-6d150cfc5868.png)

▼ サクラエディタ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726107/e9802eea-9f5a-9673-6cac-0bc7de53db38.png)

この状態だと、どのカラム名に対しての値なのかわかりづらいですよね。
カラム名が増えるとなおさらです。

## サクラエディタの設定方法
①"設定" > "タイプ別設定一覧" を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726107/5a51be64-2e27-7766-33cf-4dfa1258824a.png)

②"追加"を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726107/55578c9b-6837-4e8d-de2f-35393a62f015.png)

③追加された設定（最終行）を選択した状態で、"設定変更"を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726107/ffb7ea79-399c-732e-4cd4-673f71261b8e.png)

④以下のように追記し、"OK"を押下
設定の名前　　　　　：`CSV`　※任意
ファイル拡張子　　　：`csv`
ドロップダウンリスト：`CSV`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726107/9a0512af-9500-3444-72dc-ec6115b71cf0.png)

CSVをサクラエディタで開く際、もしくはタイプ別設定一覧でCSVを指定すると、CSVモードになりカラムごとに見やすい形で表示することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726107/9c9d1d6e-2814-cf6f-11d6-557433152fd1.png)

## 最後に
今回は、サクラエディタでCSVファイルの内容を見やすく設定する方法についてご紹介いたしました。
世にあるツールは便利なもので、「こういう風にしたいな～」を調べてみるとヒットすることも多いので、また何か小ネタを仕入れたら記事にしようと思います。

最後までお読みいただき、ありがとうございました:cherry_blossom:
休日に入った予定を平日にシフトするマクロ

###  VBAマクロの詳細解説 休日に入った予定を平日にシフトする

この記事では、Excel VBAを使用して特定の条件に基づいてセルの値をシフトするマクロ `ShiftValueForHolidays` のコードを詳しく解説します。このマクロは、特定の日（休日など）に予定されていたタスクやイベントを翌日にシフトするのに便利です。それでは、各部分の機能と役割を一つ一つ見ていきましょう。

#### マクロの概要
このマクロは、アクティブシートの特定の列をチェックし、条件に合致する場合、その行のデータを次の行にシフトします。主に以下の処理を行います：
1. アクティブシートの取得
2. 最終行と最終列の特定
3. 条件に基づくデータのシフト処理
4. エラーハンドリング

#### コードの詳細解説

##### 変数の定義
```vb
Dim ws As Worksheet
Dim lastRow As Long, lastCol As Long
Dim i As Long, j As Long
```
- `ws`: 処理を行うワークシートオブジェクト。
- `lastRow`, `lastCol`: データが存在する範囲の最終行と最終列。
- `i`, `j`: ループ処理で使用するカウンタ変数。

##### ワークシートの設定
```vb
Set ws = ActiveSheet
```
アクティブなワークシートを `ws` に設定します。

##### 最終行と列の取得
```vb
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
lastCol = 32
```
- `lastRow`: 列Aの最後の行を取得します。`xlUp` は下から上への検索を示し、空白ではない最後のセルを見つけます。
- `lastCol`: 32列目までのデータを処理対象とします（これは月日を示す場合が多いです）。

##### 条件に基づくデータのシフト
```vb
For i = ActiveCell.Row() To lastRow
    If ws.Cells(i, 3).Value = 2 Or ws.Cells(i, 3).Value = 3 Then
        For j = ActiveCell.Column() To lastCol
            If Not IsEmpty(ws.Cells(i, j).Value) Then
                colLastRow = ws.Cells(ws.Rows.Count, j).End(xlUp).Row
                If colLastRow > i Then
                    ws.Range(ws.Cells(i, j), ws.Cells(colLastRow, j)).Copy
                    ws.Cells(i + 1, j).PasteSpecial Paste:=xlPasteValues
                    ws.Cells(i, j).ClearContents
                    Application.CutCopyMode = False
                End If
            End If
        Next j
    End If
    Application.StatusBar = "Processing row: " & i & " of " & lastRow
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Next i
```
- このループは、アクティブセルの行から最後の行まで繰り返されます。
- 第3列の値が2または3の場合（休日or祝日）、その行のデータを次の行にシフトします。
- `IsEmpty` 関数を使用して空白でないセルを確認し、データをコピーして1行下にペーストし、元のセルの内容をクリアします。

##### エラーハンドリング
```vb
ErrorHandler:
    MsgBox "Error " & Err.Number & ": " & Err.Description & " in " & VBE.ActiveCodePane.CodeModule

.Name, vbCritical
    Application.StatusBar = False
```
エラーが発生した場合、エラー番号と説明をメッセージボックスで表示し、ステータスバーの表示をリセットします。

### まとめ
このマクロは、特定の条件に基づいてExcelのセルの値を効率的にシフトさせることができる便利なツールです。カスタマイズによってさまざまなシナリオに適用可能で、日々の作業を自動化するための基盤を提供します。エラーハンドリングもしっかりと行い、予期せぬ問題にも対処できるようにしています。
秋月の1.3 インチフルカラーグラフィック液晶ディスプレイで時計を作って遊ぶ(Arduino UNO)



x 時間合わせは、別
x あまり、正確では、ない
x 秋月のDS1307ユニットを使用
x 秋月のAE-ATM0130B3を使用
x 過去ログを見よ!!

目的
ST7789V2のディスプレイで時計を作って遊ぶ。

結果

![o_coq053.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/27e4a6a3-2099-94f5-44f6-760d970e44cd.jpeg)


![o_coq054.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5f306fbe-95e8-b319-9e5d-ed782fa11321.jpeg)

プログラム

```C++


//spi_st7789_DS1307_UNO_V3_1


//ヘッダーファイル
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>


//定義
#define TFT_CS        10
#define TFT_RST        9 // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC         8
//13 SCK
//12 (not connect)
//11 MOSI
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);


//初期化
void setup() {

  //I2Cの初期化
  Wire.begin();

  //DS1307用の電源供給5V
  pinMode(A3, OUTPUT);
  digitalWrite(A3, HIGH);

  //240x240の液晶を使用する。
  tft.init(240, 240);           // Init ST7789 240x240

  // 画面表示をクリア
  tft.fillScreen(ST77XX_BLACK);

  // テキストサイズを設定
  tft.setTextSize(5);

}//setup


char cn1[16] = "12:34"; //時刻

//メインループ
void loop() {

  // 前に表示した内容で消す。
  // テキスト色を設定
  tft.setTextColor(ST77XX_BLACK);
  // テキストの開始位置を設定
  tft.setCursor(0, 10);
  tft.print(cn1); //前に表示した内容


  // テキスト色を設定
  tft.setTextColor(ST77XX_WHITE);
  // テキストの開始位置を設定
  tft.setCursor(0, 10);

  //RTC DS1307のアドレス
#define ADDR    0x68    // 2進数 1101000

  // レジスタのアドレスを先頭にする
  Wire.beginTransmission(ADDR);
  Wire.write(0x00);
  Wire.endTransmission();
  delay(1);

  // I2Cスレーブに8byteのレジスタデータを要求する
  Wire.requestFrom(ADDR, 8);

  // 8byteのデータを取得する
  unsigned char data_read[16] = {0x88, 0x88, 0x88}; //データバッファー
  int ii = 0;
  while (Wire.available())  {   // 要求より短いデータが来る可能性あり
    data_read[ii++] = Wire.read();       // 1バイトを受信
  }//while

  //dbug
  //char data_read[16];//debug
  //data_read[2] = 0x01; data_read[1] = 0x23;

  //表示変換する
  cn1[0] = '0' + (data_read[2] >> 4);  //0 時 上位
  cn1[1] = '0' + (data_read[2] & 0xf); //1 時 下位
  cn1[2] = ':';
  cn1[3] = '0' + (data_read[1] >> 4);  //2 分 上位
  cn1[4] = '0' + (data_read[1] & 0xf); //3 分 下位
  cn1[5] = 0;

  tft.print(cn1); //表示

  for(int hh=0;hh<60;hh++) {delay(1000);  /*1秒待つ*/}

}//loop



```
ProxmoxのUbuntuコンテナを日本語化

備忘録がわりにかいとく

インストール
```bash
apt -y install language-pack-ja-base language-pack-ja
```
設定
```bash
localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
source /etc/default/locale
```
このままコピペしたら動く...はず
ARC176 A - 01 Matrix Again

- $N$ 行 $N$ 列の白いマス目がある
- うち $M$ マスは黒く塗られている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638261/0626f0cc-7394-bb13-51c2-38803a371c12.png)

----

- 追加で何マスか黒く塗って、
どの行も列も黒マス $M$ 個にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638261/3bc72ceb-a5ae-04b2-41df-3f9f13372d87.png)

----

# 解き方（一例）

----

- ナナメの直線を足すと、どの行も列も $1$ マス増える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638261/532fc46e-f384-4ef0-65e4-0885fc2a3d70.png)

----

- すでにある黒マスから直線を引いてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638261/70760f68-9420-9332-cc65-669656264060.png)

----

- まだ足りない場合は、適当に
白マスを選んで直線を引く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638261/7ac2b726-193d-03d4-ba83-27816b1818a3.png)

----

# 計算量
- 線を $1$ 本引くのに $O(N)$ かかる
- 線は $M$ 本ある
- → $O(MN)$ で解くことができた
Javaで「Javaを使ったプログラムの作成と保存」の動作を確認してみた

# 概要

Javaで「Javaを使ったプログラムの作成と保存」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/before/index2.html

# 実装

以下のファイルを作成しました。
```Hello.java
class Hello{
  public static void main(String[] args){
    System.out.println("Hello");
  }
}
```

以下のコマンドを実行しました。
```
$ javac Hello.java 
$ java Hello 
Hello
```

# まとめ

何かの役に立てばと。
2024/4/23主にITとかセキュリティの記事

Microsoft 365のパスワード更新を求めるフィッシングメールに注意(4/21)
https://news.mynavi.jp/techplus/article/20240421-2931565/

「初心者でも扱える安価なランサムウェア」がダークウェブで大量に出回っている(4/20)
https://gigazine.net/news/20240420-cheap-ransomware/

サイバーセキュリティ脆弱性の「修復」に特化、希少な女性CEO率いるイスラエルDazz(4/21)
https://techable.jp/archives/232069

初心者大学生が作った機械学習ライブラリがGitHubでスター数300を超えた話(4/21)
https://qiita.com/Koukyosyumei/items/8f8b06a97bf8e17098aa

[Dart, Flutter] DartでJWT認証サーバーを実装してみた (JWT入門)(4/19)
https://qiita.com/Odatetsu/items/2326575f01a9a460ace4

ＨＯＹＡの安心レンズ受注再開　　ＥＹＥメガネ(4/21)
https://www.shimintimes.co.jp/news/2024/04/post-25350.php

AIで「親族の声」を生成、「相続乗っ取り」、さらに「震災義援金」まで…詐欺被害者が明かす「ヤバすぎる証言」(4/21)
https://gendai.media/articles/-/127785

アクト、【オリジナル漫画】セキュリティ営業の異世界転移　～EDRの概念で魔族の侵入を防ぎ、成り上がる～を制作し公開(4/21)
https://japan.cnet.com/release/30966166/?ref=rss

ＳＮＳでデマ拡散し世論操作、選挙イヤーで各国警戒　ＡＩで本物そっくりの音声や動画(4/21)
https://news.yahoo.co.jp/articles/971dba078e8917893de35493aeb36a7a228d9a9e

「市民に開かれた政治を」…日本では絶対にあり得ない「オープンな政治」を台湾が実行できた秘訣に迫る(4/21)
https://news.yahoo.co.jp/articles/2738fd85da31f7934075e47a40c71a584b5c7cf2?source=rss

マルウエアが暗号資産を狙う、認証情報の窃取や不正取引の承認など4つの脅威(4/22)
https://xtech.nikkei.com/atcl/nxt/column/18/02805/041000001/
Google Drive上のファイルをGoogle Colabで読み込み


#### Google Drive上にデータセットを格納して、Google colabから読み書きする方法について


Kaggle上のデータセットを使って、Google Colab上で分析するために色々な手法を調べたのですが、超初心者のため荒技だけど一番簡単なこちらの方法を紹介します。
### step1.Google Driveにマウントする。
コードは以下をアレンジなしでそのままコピペでOK!
~~~
from google.colab import drive
drive.mount('/content/drive')
~~~
実行するとこのような画面が出てくるので、[Googleドライブに接続]を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/abdbc806-294d-bee6-0c1a-9cdcb6135e0d.png)
その後、googleアカウントの選択画面が出てくるので、Google Driveに接続したいGoogleアカウントを選択し、出てくるポップアップ画面は次へなどを選択していくと、先ほど実行したコードの部分がこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/72adebbb-0027-f606-28c7-cdcf69876178.png)
"Mounted at /content/drive" このコメントはつまり、GoogleDriveにマウントが成功したという事です。

※マウントするとは？
外部のリソースを、自分のリソースで使えるようにする事（雑）。
つまり、Google Drive上のファイル（外部）を、Goolge Colab（自分のリソース）で使えるようにする事。

### step2.Google Drive上の読み込みたいファイルのパスを取得する。
パスというのはPC上にあるファイルの住所のことです。
以前私は勘違いしていたのですが、このパスはGoogle Colab上から取得します。
つまり、Google Drive上にファイルがあるからと言って、Google Driveの画面に移動する必要はありません。

Google Colab画面上の左端にある、ファイルボックスのアイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/6b779875-4185-77de-404c-15115812e0bb.png)

するとフォルダが縦に並んだ画面が出てくるので、[drive]というフォルダのアイコンを押し、[MyDrive]というフォルダのアイコンをクリック。すると、自分のGoogle Driveと同じフォルダの構成が下に出てくるので、読み込みたいファイル名を見つけてドットマークを押すと、[パスをコピー]が出てくるのでクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/43565fab-37d7-ebc5-e925-b497dd0b4c77.png)

これで完了です


#### 他にはこんな方法もあるようです

 ・KaggleデータセットをGoogle Colabで利用する方法
https://www.toolify.ai/ja/ai-news-jp/kagglegoogle-colab%E5%88%A9%E7%94%A8%E6%96%B9%E6%B3%95-2076048

・
[UE5]mixamoが言う事を聞かない

## 何があった？

[mixamo](https://www.mixamo.com/#/)(無料でモーションを買えるサービス)でダウンロードしてきたモーションが下記の図のように思った通りに動きませんでした。


サービスサイトの表示の様子

![mixamo](https://github.com/KONTA2019/git-app/assets/58900062/b16e56a1-067c-4c22-ada8-3f405993a7c6)


実際の動作の様子

![fail_play](https://github.com/KONTA2019/git-app/assets/58900062/cf684081-891b-4f21-8d09-6baeda5e366c)


## なぜこうなった？

原因はスケルトンの規格が違うからだと思われます。

さらに詳細に言うとUEは4から5に移行した時にマネキンのボーンの命名規則を変えていて、mixamoのデフォルトがそれに対応していなかったと思われます。（主に腕周りが変わっているようです）




## 解決した方法

UE5に適するものに変換してくれる[Mixamo Converter](https://terribilisstudio.fr/?section=MC)というサービスを利用することで解決しました。（解説は[この動画](https://www.youtube.com/watch?v=84hI_Kk_LDg)がわかりやすかったです。）

ゲームの検証画面で正しく動いている様子
![success](https://github.com/KONTA2019/git-app/assets/58900062/8f304afd-33b7-487b-a684-f854895d8038)


※ちなみにMixamo Converterの詳細な動きは下記のようになっていました。
①マネキンのrootボーンなしのfbxファイルをmixamoに渡す（quiinを自分でエクスポートすると何故かrootボーンが入ってくる）
②mixamoから受取ったモーションの腕周りのボーン割り当て調整を自動でする



## 余談

原因調査の際に、アニメーションのリターゲティングで動くか検証すべくRigのマッピングをしようとしたのですが、こちらもUE5への変化で操作方法に破壊的な変更が起こっておりつまづいたため、UE**5**のリターゲティングのやり方が載っている記事を下記で共有しておきます。（コンバーターが存在しないmixamo以外の場所からモーションを取得する場合は、こちらの方法を使って自分で調整する必要があるので知っておくと良いと思います）

・公式の該当ページ：https://dev.epicgames.com/documentation/ja-jp/unreal-engine/ik-rig-animation-retargeting-in-unreal-engine?application_version=5.0


## 2024/05/18追記
UE5.4以降なら、Mixam Converterを使わなくても大丈夫になったそうです

参考動画：https://www.youtube.com/watch?v=1GvTBr99AwY
【VSCode】GraphQLのクエリの定義からschemaファイルを参照できる拡張機能

## 概要
VSCodeで、GraphQLのクエリ定義からschemaファイルを参照できる拡張機能があったので、少し紹介したいと思います。

## 拡張機能のセットアップ
* 拡張機能は[GraphQL: Language Feature Support](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql)になります。まずはこちらをインストールします。
* `.graphqlrc.yml`にてschemaファイルと、クエリを定義するファイル（documents）を設定します。TypeScriptにてクエリを定義する場合は、上記の拡張機能のページにあるように以下のような設定になります。

```.graphqlrc.yml
schema: 'schema.graphql'
documents: 'src/**/*.{graphql,js,ts,jsx,tsx}'
```

## できること
以下のキャプチャーのように、クエリを定義してるファイルからschemaファイルの定義に参照できるような感じになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/f76642a8-0c14-2bf3-0c6e-024d843fbb10.png" width=450px>

また、以下のようにクエリを書くときのサジェストもしてくれます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/b5dc65dd-304f-2863-18fd-176d46dba95b.png" width=450px>
custom-resource-apigw-cw-roleがnode16.xランタイムでデプロイされる件

## いきさつ
ある日AWSからnode16のサポート終了のお知らせが届きました。

> ...
LambdaでのNode.js 16のサポートは2024年6月12日に終了します
...

自分のLambdaを眺めていると、`xxx-custom-resource-apigw-cw-role`node16ランタイムがいました。
これはServerless frameworkでデプロイしたときに自動生成されるもので、API GatewayのCloudWatch Logsのロールを作成するために使用されるらしい。
slsのバージョンを上げればいけそうだな〜と思い現在のバージョンを確認すると`3.38.0`。これは記事執筆時点での最新バージョンです。えぇ...。

調べてみると以下のやりとりが：
https://github.com/serverless/serverless/issues/12307


ざっくり、こんな流れでした：

- サーバーレスフレームワークを介して作成されたcustom-resource-apigw-cw-role lambdaのランタイムを変更するにはどうすればよいですか？
- `lib/plugins/aws/custom-resources/index.js`にハードコードされてるからどうしようもないかも...
- SLS v4で対応する予定よ(2024/2/17)
    - 来週にはベータ版がリリースされる(予定)
- (3/5)まだすかね...
- node16サポート終了せまってるんだけど...
- そのうち解決されるはずだが、もう間に合わないのでなんらかの代替策を考えるしかないかな...(4/23)

という感じらしい

## どうする？
6/12までに対応がされない場合、新規にSLSでデプロイをすることはできなくなります。
すでにデプロイされているものについては、`sls deploy`コマンドで更新をすることができます。

もしも、6/12までに対応されなかった場合や、終了予定が決まっているnode16ランタイムが存在することが気になる場合、[こちらの通り](https://github.com/serverless/serverless/issues/12307#issuecomment-2069355898)`serverless.yml`の以下を書き換えて、`xxx-custom-resource-apigw-cw-role`を生成しないようにする方法が考えられます。
```
  logs:
+    restApi: false
      # accessLogging: true
      ...

```
これで対象のLambdaは無くなります。
ただしAPI gateway周りのログがcloudwatchに記録されなくなるので、運用方針が合っているか検討する必要はあると思います。


## 2024/05/23更新
serverless v4がリリースされました。
これで解決するのかも(未確認)
【図解】もう迷わない、ホールドアウト検証法とクロスバリデーションの違い

本記事は、データ分析初心者の私がよく迷ってしまう、モデル学習時のデータ分割の手法についてまとめます。

Kaggleで磨く機械学習の実践力によると、trainデータを全てモデルの学習に回すのではなく、trainデータの一部を使ってモデル学習、trainデータの残りを使ってモデルで推論してみて、その精度を確かめる。という手法が説明されています。

その際の手法が主に2つ紹介されているので、ここでそれらの違いを簡単にまとめます。

### 1.ホールドアウト検証法
データ分析初心者向けに紹介されている教材なんかでは、この手法がよく紹介されています。train_test_splitというコードを使います。

```サンプルコード
x_tr, x_va, y_tr, y_va = train_test_split(x_train,
                                          y_train,
                                          test_size=0.2,
                                          shuffle=True,
                                          stratify=y_train,
                                          random_state=123)
```
図解するとこんなイメージです！

![スクリーンショット 2024-04-22 13.04.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/5f8f7e05-af14-f4da-0c13-e9b1438002ec.png)

![スクリーンショット 2024-04-22 13.06.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/20628bf1-83f9-f21c-f14f-f394f10233e6.png)

分割した後モデル学習に使わずに2割取っておく事で、正解のyが分かっている状態でモデルを使って予測したy_predとyを比較でき、作ったモデルの性能を評価できるというわけです。
評価できるから、モデルをどんどん改変していき精度改善につなげられます。

### 2.CV（クロスバリデーション）

ホールドアウト検証法には１つ弱点があります。
それは、分割した２割のデータをモデル学習に使えないという事です。
より精度の高いモデルを作るという観点では、データが揃っている以上モデルの学習使いたいわけです。
そこで、ホールドアウト検証法をベースに、欠点を克服した手法がクロスバリデーションになります。考え方は簡単、ホールドアウト検証法を5回繰り返すというものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/c2bb33cc-344d-67bc-28a0-748a37291cb4.png)

データの分割を行った後、以下の流れを5回繰り返します。
・モデル学習
・モデルを使って検証データのxを使ってy_predを予測
・検証データのyと、予測したy_predの差分を評価した指標(*)を計算する

5回繰り返したら、(*)の平均を取る事で、その値をモデルの評価とします。

かなり省略して説明しましたが、まずはこれくらいを抑えておけば良いです。

### ではどのようなルールで分割するのか？
このような疑問を持てたら凄いです。ここでは簡単に紹介して終わりにします。

##### trainデータのyの分布が同じになるように分割
例えば、分割前のtrainデータのy全体の分布が正規分布に従っているとしたら、分割して8:2にする際もそれぞれが正規分布に従うように分割する、という事です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655766/d3c42ca7-341d-ea95-bcdb-6572dc8ec6c7.png)

この辺りは私もまだまだ勉強中なので、もっと知識をつけて行けたらと思います。
[UE5]Third Personのデフォルトで準備されているブループリント内のCast To Player Controllerが動かなくなった

## 何が起こった？

何もしていないのにデフォルトで準備されている機能（下記の画像の赤枠部分）が動かなくなるという事象が起きました。
（そのせいでGameplay Abilityが動かせない状況でした。）

![スクリーンショット 2024-04-23 1.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/b1ec6870-67c1-f456-a2e3-7364d10bf693.png)

## エラーの原因

動作確認機能をデフォルトではないもの（下記図）にしてしまっていたためでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/ae59894b-37d3-30e4-0f24-ae2354db0337.png)


## 解決方法

縦三点リーダーを押して選択ビューポートを選ぶことで直りました。

![スクリーンショット 2024-04-23 2.07.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/50f00e87-9864-e1d5-6a27-aef88244484d.png)


## 余談

今回の失敗はショートカット`option + s`で再生機能を切り替えてしまった（`cmd + s`と間違えて打った）ことだと思われます。

よくありそうなので皆さんもご注意いただければと思います。

あとロジック観点でエラーになった原因も調査しましたが解明できませんでした。

筆者には再生ボタンの隣のコントローラボタンを押した時にBeginPlayするだけのはずなので、見た感じバグにはならなそうに見えるのですが、実際はバグっていてお手上げでした。

ひとまず筆者の作業の本質的ではない部分になるので、また必要になった時に調べてみようと思います。
Mockitoでメソッド内のobjectMapper.writeValueAsStringの例外は発生させる

convertToJson.java

```java
package com.example.helloworld3.app.welcome;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonConverter {

    public String convertToJson(Object object) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(object);
    }
}
```

abcTest.java

```java
package com.example.helloworld3.app.welcome;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

//import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.Assert.*;

import org.junit.Test;

public class abcTest {

    @Test
    public void testConvertToJsonThrowsException() {
        JsonConverter jsonConverter = new JsonConverter();
        
        // Test that calling convertToJson throws JsonProcessingException
        assertThrows(JsonProcessingException.class, () -> jsonConverter.convertToJson(new Object()));
    }
}
```
AWS Certified Solutions Architect - Associate

# 概要
AWS SAA資格を取得する必要があるので、ブログ投稿しながら、資格準備をしようと思います。

# AWS SAAとは
AWS技術に関する知識と、さまざまなAWSサービスにわたる技術を検証する試験です。
この試験は以下の主要な範囲を含みます:
1. コンピューティング、ネットワーク、ストレージ、データベースの AWS サービス、および AWS のデプロイと管理サービスに関する知識およびスキル
2. AWS 上でのワークロードのデプロイ、管理、そしてオペレーション、およびセキュリティコントロールとコンプライアンス要件の実装に関する知識およびスキル
3. AWS マネジメントコンソール、および AWS コマンドラインインターフェース (CLI) の使用に関する知識とスキル AWS Well-Architected フレームワーク、AWS ネットワーク、セキュリティサービス、AWS グローバルインフラストラクチャに関する理解
4. 提示された技術的要件を満たす AWS のサービスを特定し、AWS ベースのアプリケーションの技術的要件を定義する能力

#  準備過程

1. 試験内容及び範囲の把握
試験の内容と範囲が記載されているので、内容に合わせて取得した知識をまとめる。
https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Exam-Guide.pdf

1. AWS 公式ドキュメントを通じた学習
各サービスのFAQページを見ると概要や Use caseを確認できる。
どうすれば効率的なアキテクチャを立てるのか、どうすれば障害対応もできるアキテクチャを立てるのかを知ることが大事なので、ドキュメントで学習する。

1. AWS Skill Builder 講座
各領域ごとになにを学習したら良いか、教えるので試験の概要を確認できる。
https://explore.skillbuilder.aws/learn/course/external/view/elearning/16856/exam-prep-standard-course-aws-certified-solutions-architect-associate-saa-c03-japanese-na-ri-ben-yu-shi-xie-ban

1. 公式サンプル問題及びUdemy
公式サンプル問題だけでは実際に出る問題タイプを把握できないので、Udemyも使って勉強する
https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Sample-Questions.pdf
macOSで/etc/ssh/sshd_configを書き換えてパスワード認証禁止にしてもリセットされる

# よくある解説とリセットされる設定
「ssh パスワード認証 禁止」でググるとよく出て来るのは、
~~~ conf:sshd_config
PasswordAuthentication no
KbdInteractiveAuthentication no
~~~
と`sshd_config`に書け、いうもの。自分も`/etc/ssh/sshd_config`をそのように書き換えていたのだが、ある日元に戻っていることに気付いた。「OSの更新でsshd_configがデフォルトに戻されたのかな」程度に考えていたのだが、毎回書き換えるのも面倒だ、ということで対処法を調べて見た。なお、OSはmacOS Sonoma(14.4.1)である。
# 原因
「元に戻ってしまう原因」は`sshd_config`がデフォルトに戻ってしまうこと。そりゃそうだ。戻ってしまうのは仕方無いので、「戻されても設定を維持できる方法」を調べよう。すると18行目に以下の記述があった。
~~~ conf:/etc/ssh/sshd_config
Include /etc/ssh/sshd_config.d/*
~~~
うん、まあそうだよね。ちなみに`/etc/ssh/sshd_config.d/`には`100-macos.conf`があり、
~~~ 100-macos.conf
# Options set by macOS that differ from the OpenSSH defaults.
UsePAM yes
AcceptEnv LANG LC_*
Subsystem	sftp	/usr/libexec/sftp-server
~~~
と書かれている。コメントにもある通り、OpenSSHのデフォルトとは異なるオプションを設定してある。このファイルを書き換えてもいいんだけど、`100-macos.conf`がデフォルトに戻されるとまた面倒なので、新しいファイルを作る事にした。
~~~ /etc/ssh/sshd_config.d/999-nopasswordauth.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
~~~
ファイル名は例なので、各自適当に変更すれば良いと思う。とりあえずこれで様子を見よう。
Railsで多対多の関係を扱う - Part 3: Eager Loadingを避けるべき場面と最適化戦略

## 前回までの記事
https://qiita.com/KM9973/items/9072aa1f0c43284e536d

https://qiita.com/KM9973/items/9ac44032e1918bbc8b35


## はじめに
前回は `includes` と `joins` の使い分けについて詳しく解説しました。今回は、Eager Loading（事前読み込み）を避けるべき場面と、データ取得戦略を最適化するためのテクニックに焦点を当てます。

## Eager Loadingを避けるべき場面
Eager Loadingは多くの場合に便利でパフォーマンス向上に寄与しますが、すべてのシナリオで最適なわけではありません。以下は、Eager Loadingを避けた方が良い場面です。

1. **大量の関連データがある場合**:
   - 関連データが非常に多い場合、事前にすべてを読み込むとメモリ使用量が大幅に増加し、アプリケーションのパフォーマンスが低下する可能性があります。例えば、一つの親レコードに対して数千から数万の子レコードがあるような場合、必要なデータだけを選択的にロードする方が効率的です。

2. **関連データがほとんど使われない場合**:
   - ページや処理において関連データがほとんど使われない場合、無駄なデータ読み込みとなります。たとえば、ユーザー一覧を表示するだけで、ユーザーの詳細なプロフィール情報は不要な場合です。

3. **特定の条件によってのみ関連データが必要な場合**:
   - 関連データが特定の条件下でのみ必要とされる場合、その条件が一般的でない限り、Eager Loadingは無駄になる可能性があります。例えば、管理者だけがアクセスする詳細情報などです。

## データ取得戦略の最適化
効率的なデータ取得戦略を立てるためには、以下のようなテクニックが有効です。

1. **選択的Eager Loading (`preload`, `eager_load`)**:
   - `includes` に代わり、`preload` や `eager_load` を使用することで、より細かく制御できます。`preload` は関連データを別々のクエリで事前に読み込み、`eager_load` は `LEFT OUTER JOIN` を使用して単一のクエリでデータを取得します。

2. **バッチ処理**:
   - 大量のレコードを処理する場合、`find_each` や `find_in_batches` を使用して、メモリの消費を抑えながらレコードをバッチ処理することができます。

3. **クエリのリファクタリング**:
   - クエリの選択肢を見直し、必要なカラムのみを選択することで、読み込むデータ量を減らし、パフォーマンスを向上させることができます。

## まとめ
Eager Loadingは強力なツールですが、その使用は状況に応じて慎重に行う必要があります。適切な場面で適切なデータ読み込み戦略を選ぶことで、アプリケーションのパフォーマンスとスケーラビリティが大きく向上します。これにより、より快適で効率的なユーザーエクスペリエンスを提供できるようになります。

## 次回以降の記事
https://qiita.com/KM9973/items/b016d8b661f7175a67b6
Railsで多対多の関係を扱う - Part 2: `includes` と `joins` の使い分け

## 前回までの記事
https://qiita.com/KM9973/items/9072aa1f0c43284e536d

## はじめに
前回の記事で、Railsで多対多の関係を持つモデルの設定と基本的なデータ取得方法について説明しました。今回は、`includes` と `joins` の違いに焦点を当て、これらのメソッドをいつ、どのように使い分けるべきかを詳しく見ていきます。

## `joins` メソッドの基本
`joins` はSQLの `INNER JOIN` を使ってテーブルを結合し、関連するデータを取得するために使用します。しかし、`joins` だけでは関連テーブルのカラムは自動的には選択されません。これが意味するのは、関連データにアクセスしようとした場合、追加のクエリが必要になることです。

```ruby
@services = Service.joins(:categories)
```

このクエリは `services` と `categories` を結合しますが、`Service` オブジェクト内で直接 `Category` のデータにアクセスすることはできません（追加のクエリを記述しないと、@servicesに空の配列が代入されます）。これが、直感に反しているように感じるかもしれません。

### 補足: @services = Service.joins(:category)と記述した場合
以下のようなエラーが出る。
```bash
ActiveRecord::ConfigurationError at /services
Can't join 'Service' to association named 'category'; perhaps you misspelled it?
```

## `includes` メソッドの利用
一方、`includes` は関連データを事前に読み込むために使用されます（Eager Loading）。これにより、必要なすべての関連データが初期のクエリで読み込まれるため、後からアクセスする際に追加のクエリが発生しません。これは特に、ビューで多くの関連データに頻繁にアクセスする場合に有効です。

```ruby
@services = Service.includes(:categories).all
```

この方法では、各 `service` から `service.categories` にアクセスする際に、関連する `categories` がすでにロードされているため、効率的です。

## `joins` と `includes` の使い分け
- **`joins` の利用**: 特定の条件でフィルタされたレコードを抽出する場合や、関連テーブルのデータでソートする場合に有効です。例えば、特定のカテゴリに属するサービスだけをリストアップする場合などです。
- **`includes` の利用**: データを表示する際に関連データも一緒に扱う必要がある場合、または N+1 クエリ問題を回避したい場合に適しています。

## まとめ
`includes` と `joins` の違いを理解することは、Railsで効率的なデータ取得戦略を立てる上で非常に重要です。各メソッドの使用目的を理解し、適切な状況で適切なメソッドを選択することで、アプリケーションのパフォーマンスと保守性を向上させることができます。

## 次回以降の記事
https://qiita.com/KM9973/items/85c9861623dc18faeecf

https://qiita.com/KM9973/items/b016d8b661f7175a67b6
Railsで多対多の関係を扱う - Part 1: モデル設定と基本のデータ取得

## はじめに
多対多の関係は、Webアプリケーションのデータモデリングで頻繁に遭遇するパターンの一つです。Rails では `has_many :through` アソシエーションを利用して、この種の複雑な関連を簡単に扱うことができます。本記事では、`service` と `category` の多対多の関係を例に、Rails でのアプローチとSQLクエリの両方を通じて、データの効率的な取得方法を解説します。

## モデルの設定
まず、`service`、`category`、`service_category` の三つのモデルを設定します。以下のように各モデルに適切なアソシエーションを設定することから始めます。

```ruby
# app/models/service.rb
class Service < ApplicationRecord
  has_many :service_categories
  has_many :categories, through: :service_categories
end

# app/models/category.rb
class Category < ApplicationRecord
  has_many :service_categories
  has_many :services, through: :service_categories
end

# app/models/service_category.rb
class ServiceCategory < ApplicationRecord
  belongs_to :service
  belongs_to :category
end
```

## データの取得：ActiveRecordを使用したアプローチ
モデルが設定されたら、次にデータの取得方法を考えます。Railsの `includes` メソッドを使用して、`Service` のデータと関連する `Category` のデータを効率的に取得する方法を見てみましょう。

```ruby
# Service と関連する Category を取得
@services = Service.includes(:categories).all
```

このコードにより、`@services` に含まれる各 `service` オブジェクトから `service.categories` を呼び出すことで、関連するカテゴリがすでにロードされているため、N+1問題を回避できます。

## SQL クエリでのアプローチ
Railsの外でSQLを直接書く必要がある場合は、次のようにJOINを使用して関連するデータを取得します。

```sql
SELECT services.*, categories.*
FROM services
JOIN service_categories ON services.id = service_categories.service_id
JOIN categories ON service_categories.category_id = categories.id;
```

このクエリでは、`services` テーブルと `categories` テーブルを `service_categories` を通じてJOINしているため、`services` に関連する `categories` の情報も一緒に取得できます。

## まとめ
Railsでの開発ではActiveRecordを活用することで、複雑なデータ構造も簡単に扱うことができます。次回は、includesとjoinsの違いについて詳しく解説し、いつどちらを使うべきかを掘り下げます。興味がある方は、ぜひフォローしてください。

## 次回以降の記事
https://qiita.com/KM9973/items/9ac44032e1918bbc8b35

https://qiita.com/KM9973/items/85c9861623dc18faeecf

https://qiita.com/KM9973/items/b016d8b661f7175a67b6
APIを呼び出すLambdaで、リクエストヘッダーを全部送るとRuntime.MarshalErrorが起きる

# 起こったこと
自分で開発したAPIを叩いて、戻ってきたレスポンスをそのまま返すAWS Lambdaを作っていたのですが、固定のヘッダーをつけてリクエストするときは問題なく呼び出せるのに、API Gatewayに渡されたリクエストヘッダーをそのままつけてリクエストすると、原因どころか発生箇所すらもよく分からないエラーが起きるようになりました。
```python:lambda_function.py
import json
import urllib.request

def lambda_handler(event, context):
 
    headers = event.get('headers')
    request_body = event.get('body').encode('utf-8')
 
    # リクエスト送信
    req = urllib.request.Request('https://xxxx/api/v1/yyyy', headers=headers, method='POST', data=request_body)
    with urllib.request.urlopen(req) as res:
        body = res.read()
        code = res.getcode()
 
    return {
        'statusCode': code,
        'body': body
    }
```

> [ERROR] Runtime.MarshalError: Unable to marshal response: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte
> Traceback (most recent call last):

なぜかスタックトレースが何も表示されない…


# APIのレスポンスが圧縮されていた
このエラーメッセージについて調べてみたところ、ひとつの鍵は```byte 0x8b in position 1```でした。  
[python - UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte, while reading csv file in pandas - Stack Overflow](https://stackoverflow.com/a/44660123)  
```0x8b```はgzipで使われるマジックナンバーとのこと。gzip圧縮されたレスポンスは確かにUTF-8デコードできません。
そういえば、このAPIはASP.NETで開発しており、[応答圧縮](https://learn.microsoft.com/ja-jp/aspnet/core/performance/response-compression)を有効にしていたのでした。
この機能はクライアントから送られたリクエストヘッダーのAccept-Encodingを見て、レスポンスを圧縮していいかを判断しています。
実際に、送ろうとしたヘッダーには以下が含まれていました。  
```'accept-encoding': 'gzip, deflate, br'```
このヘッダーを除外してAPIを呼び出すことで、レスポンスの圧縮を防ぎ、問題を回避することができました。
```diff_python
    headers = event.get('headers')
+   headers.pop('accept-encoding', None)    # 応答圧縮を回避
    request_body = event.get('body').encode('utf-8')
```

# エラーはLambdaランライムで起きていた
直接の原因と回避策は分かったものの、Lambdaのコードの中でUTF-8デコードしている箇所がないのになぜこのエラーが起きるのか、気持ち悪さが残ります。
しかも、エラーのスタックトレースが何もないので、発生箇所が分かりません。
上記のプログラムにログを仕込んで調べたところ、returnの直前まで実行されていることが分かりました。  
```Runtime.MarshalError```について調べたところ、Lambdaは戻り値をJSONシリアライズしてから呼び出し元に返しており、戻り値がシリアライズできない場合にこのエラーが起きることが分かりました。
[Python の Lambda 関数ハンドラー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-handler.html#python-handler-return)
スタックトレースが何もなかったのは、エラーの発生箇所がLambdaラインタイムだったからのようです。

ちなみに、戻り値をBase64エンコードしてから返せばこのエラーを回避できるとの情報もありましたが、試していません。
手癖でコードを書いてしばらく悩んだ話

# 問題

以下のようなコードをJavaScriptで書いた。

```javascript:あるクラスの一部分
class ContentList {
  constructor(contents) {
    this.contents = contents;
  }
  getContent(n) {
    if (0 <= n < this.contents.length) {
      return this.contents[n];
    }
    return null;
  }
}
```

なんとなく違和感を感じつつも、実際に使ってみると以下のようになった。

```javascript
const list = new ContentList([...]);  // contents を初期化
list.getContent(0);  // この結果が null となる
```

当然、想定した結果ではなく最初のコンテンツが欲しかった。

# 原因

なぜ問題が起こったのか。 それは if の条件式 `(0 <= n < this.contents.length)` の部分である。

この `a < b < c` のような条件の記載は Python ではよく用いられる。
JavaScript でも構文チェッカーがエラーを出さず構文としては正常なのだが、Python とは異なる結果を返す。 JavaScript では

- 最初に a < b を評価して bool 値を得る
- 次に (a < b) < c を評価するが、この時真偽値は `0 = false` , `1 = true` として整数にキャストされて評価される

という順で評価が行われる。

今回は `n` が 0 , `contents` の長さが1だったので、`(0 <= n < this.contents.length)` = `((0 <= 0) < 1)` = `(1 < 1)` = `false` という形で評価され、想定通りの結果が得られなかった。

このような問題を起こさないようにするには、`(0 <= n && n < this.contents.length)` とちゃんと `&&` で個別の条件を記載すればよい。

# 教訓

今回は構文エラーにならなかったので JavaScript でも `a < b < c` という範囲計算ができると裏どりをせずに信じ込んでしまったのが原因。 違和感がある場合、ちゃんと使えるかどうかを裏どりをしよう。

同様の事例を Google で検索しようとしてもどのようなキーワードで調べてよいかがわからなかったが、ChatGPT に文章で聞いてみると意図した通りの結果にはならないという応答が返ってきたので、こういう記号が入った式の質問をするときには便利に使えると思う。
[Conoha][Wordpress]query-monitorプラグインでエラー

2024-04-22 23:10頃に突如発生（自前の死活監視機能で検知）

管理サイトにもアクセスできないので焦りました（💦）

たぶん自動バージョンアップによるものでしょうか？

（プラグインは無効状態ですが）以下の対処で復旧したので記録しておきます。

## 症状

フロントも管理サイトもアクセス不可。まっしろページに以下のエラーメッセージが表示される

> Warning: require(/home/YOUR-USER-DIR/public_html/YOUR-DOMAIN/wp-content/plugins/query-monitor/vendor/composer/../symfony/deprecation-contracts/function.php): failed to open stream: No such file or directory in /home/YOUR-USER-DIR/public_html/YOUR-DOMAIN/wp-content/plugins/query-monitor/vendor/composer/autoload_real.php on line 42

[![Image from Gyazo](https://i.gyazo.com/98962dbd325e6238cdbe37c1b200c913.png)](https://gyazo.com/98962dbd325e6238cdbe37c1b200c913)

## 対処

なんらかの方法（Conohaファイルマネージャ、FTP、SSH)で問題のサイトのプラグインディレクトリに移動して、query-monitor プラグインのディレクトリ名を変更する。

これによってWordpressにより自動的にプラグインが無効化されます。

当方の場合は、これでサイトアクセスが可能となりました。(フロント、管理とも）

```bash
cd /home/YOUR-USER-DIR/public_html/YOUR-DOMAIN/wp-content/plugins
mv query-monitor query-monitor-disabled
```

[![Image from Gyazo](https://i.gyazo.com/57aed5a1a7b48095975d9041cdf9874a.png)](https://gyazo.com/57aed5a1a7b48095975d9041cdf9874a)
#323 2024-04-21 駄菓子 議事録

# [消費電力を検証しよう](https://android-developers.googleblog.com/2024/04/how-to-effectively-ab-test-power-consumption-for-your-android-app-features.html)
- hedgehogからpower profilerが見れる
    - power profiler : 消費電力を確認できるところ
- Profilerから頑張って開けるらしい
    - レコードしたら見れる
- 記事では緑枠部分の和を消費電力として計算している
![スクリーンショット 2024-04-22 22.25.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906559/a305be06-95ee-f9f0-c4f4-f6843a68bd6d.png)

- この記事のユースケースでは動画をダウンロードしているのでDisplayとGPUは必要ない
    - ユースケースによってどの値の和を消費電力とするかは都度考える必要がある


# Master of ViewModel
- [part 1](https://proandroiddev.com/mastering-android-viewmodels-essential-dos-and-donts-part-1-%EF%B8%8F-bdf05287bca9)
    - `init{}`を使うとき気をつけや！
    - initの中でuiState(Livedata)の監視をするとかやっちゃうと、ViewModelの初期化が実行されてから監視が開始することになる
    - ViewModel の初期化とデータ取得ロジックを切り離すことで、uiStateが参照されてからlivedataの監視を開始することができる（よりViewModelのライフサイクルとlivedataの監視のフローが紐づいてるっていうのが良い！）
    - :question: これなんで？
    - :exclamation: initの中でコルーチンを起動するとスレッドが立って、initが終わった後にコルーチンが終わらない可能性がある。もしかしたら画面回転で初期化が行われず、getWordsが走らずにデータが表示されない/失われてしまうとかあるのかも？
> Android ViewModels are designed to survive configuration changes, such as screen rotations. If data loading is initiated in the init{} block, a configuration change might lead to unexpected behavior or unnecessary data re-fetching if not carefully managed.


- [part 2](https://proandroiddev.com/mastering-android-viewmodels-essential-dos-and-donts-part-2-%EF%B8%8F-2b49281f0029)
    - ミュータブルな状態の公開を避ける。
        - ⏬ のようにやればいいよってﾊﾅｼ
        ```kotlin
        private val _uiState: MutableStateFlow = 
        val uiState : StateFlow = _uiState
        ```
    - MutableStateFlowsを使用する場合はupdate{}を使用してください
        - `mutableStateFlow.value = mutableStateFlow.value.copy()` ←のようにvalueで直代入した場合、この処理が例えば別々の三つのスレッドから呼び出された時、スレッドを客観的に監視できているわけではないので、順番が保証されない！（データの不整合が起きる可能性がある！）
    - アトミック：順番の保証のこと
        - ロックをとる：何かしらミューテーションが起こった時に一旦dbを変更できない状態にして他のところから変更が入らないようにする。ミューテーションが終了したらロックを解放して次のミューテーションに備える
        - [Mutex](https://at-sushi.work/blog/44/)：KoltinにあるロックをとってくれるAPI, Booleanとかの場合はMutexを使わなくてもatomicBooleanを使えばいい
    - emit使ったらあかんよ
        - ステートが消費されるのを待つ必要がある状況向けに設計されているから
        - コルーチン内で呼び出されるべきで、ステートが消費されるのを待つ必要がある
#322 2024-04-14 駄菓子 議事録

# [ComposeでDI](https://medium.com/androiddevelopers/dependency-injection-in-compose-a2db897e6f11)

- composeDIむずいな
- Single Activityの場合：すべてのViewModels（と注入されたオブジェクト）は、そのアクティビティが生きている限り保持される
- Compose Navigation ライブラリを使用した場合：hiltViewModel() が自動的にナビゲーション目的地のバックスタックエントリーを ViewModel のオーナーとして使用。ナビゲーションバックスタックに目的地が存在する限り、ViewModelは保持されます

- :question: SingleActivityの時と比べてどうなるのかちょっと分かりにくい。ViewModelの寿命の依存先が変わってくるんだろうけど
- Composable関数を含むクラスを作成し、依存関係をそのクラスに注入することができます。そして、そのクラスが必要なアクティビティやフラグメントの近くにインジェクトし、そこからコンポーザブル関数を呼び出します
- こういう書き方すんのかー

```kotlin
class CheckoutScreenFactory @Inject constructor(
    private val paymentApi: PaymentApi,
    // ... more dependencies
) {
    @Composable
    fun Content(...) {
        // paymentApi can be accessed here
    }
}
```

- :question: ここどういう意味か全くわからん
> This is a useful pattern because you can construct a CheckoutScreenFactory with a test double of PaymentApi to test the Composable
>
> これは、ComposableをテストするためにPaymentApiのテストダブルでCheckoutScreenFactoryを構築することができるので、便利なパターンです

- Use an enclosing class with constructor injection
    - このやり方だと1Activity-1Composeだといけるけどネストした時にバケツリレーみたいにインスタンスを渡さないといけなくなるかも？ → single Activityの場合に辛い
- Use Entry Points
    - デメリットが少ないかも。（やってみないとわからんけど）


# [LazyListの新しいアニメーション](https://medium.com/@gregkorossy/animating-lazylist-items-in-jetpack-compose-6b40f94aaa1a)

- 前まではリストが並べ替えられたり、既存のリストの途中からアイテムが挿入/削除されたりすると、リスト全体がアニメーションして移動する一方で、アイテムの追加や削除がリストの最後から行われた場合は、アニメーションがなかった
- バージョン1.7.0-alpha06のCompose Foundationライブラリから、アイテムの配置（通常はほとんど並び替えを意味する）だけでなく、出現や消滅のアニメーションもできるようになった！
Rust で GitHub のプライベートリポジトリに依存する場合のメモ


`Cargo.toml` の `[dependencies]` に, GitHub のプライベートリポジトリを指すものがある場合.

## GitHub: fine-grained personal access token
まず GitHub アカウントで fine-grained personal access token を作っておく.

コミットにアクセスするために, `Permissions` で `Contents` に `Read and Write` を付与しておくこと.

https://qiita.com/ko-he-8/items/29d72226b93065c676ff

## Cargo: net.git-fetch-with-cli

cargo を使う際には, [`net.git-fetch-with-cli`](https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli) を `true` に設定する.
環境変数を使う場合は `CARGO_NET_GIT_FETCH_WITH_CLI`.

コンソールコマンドで都度設定する場合:
```shell
cargo --config net.git-fetch-with-cli=true build
```

GitHub のクレデンシャルを求められるので,
パスワードとして, 上記で取得した fine-grained personal access token を入力する.
AWS LambdaでPlaywrightを動かす

今まで https://github.com/JupiterOne/playwright-aws-lambda を使わせてもらっていたのですが、コードを更新すると急に動かなくなってしまい https://github.com/Sparticuz/chromium に乗り換えたので導入メモです。

ほとんどREADMEに記載の通りです。

```
npm init
npm install --save playwright-core
npm install --save-dev @sparticuz/chromium
```

- node_modulesフォルダをzip化
- 50MBを超えるのでS3にアップ
- Lambdaのレイヤーを作成
    - 先ほどS3にアップしたzipのURLを指定
    - x86_64とNode.js 18.xを指定
- Lambdaの関数を作成
    - 先ほど作成したカスタムレイヤーを追加
    - 設定→一般設定からメモリを2000MB程度、タイムアウトを2分程度に増やす
    - コードソースのindex.mjsをindex.jsに変更して中身を書き換え
    - DeployとTestを実行してページタイトルが表示されたら完了

```
const { chromium: playwright } = require('/opt/node_modules/playwright-core');
const chromium = require('/opt/node_modules/@sparticuz/chromium');

chromium.setHeadlessMode = true;

exports.handler = async (event) => {
  const browser = await playwright.launch({
    args: chromium.args,
    executablePath: await chromium.executablePath(),
    headless: chromium.headless,
  });

  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://example.com');
  const pageTitle = await page.title();
  await browser.close();

  console.log(pageTitle)
}
```

ちなみに、以前の環境で出ていたエラーログは以下でした。

```
page.goto: Target page, context or browser has been closed
```
AWS でのメール送信制限解除申請について

- 数年ぶりにメールの送信制限解除申請が必要となってきたので、そのメモです
    - まだ申請するかもな状態で、申請した際には記事をアップデートしたいと考えています

# どこから申請するのか？
- サポート画面から申請するのだろうと考え、サポート画面を見るが申請箇所が見つからず、結局ググり下記URL が出てきたので、aws ログイン後下記URL にアクセスするのが良さそうです
    - この申請はルートアカウントのみのようなので、IAM ユーザではなくルートアカウントでaws へログインしてください
    - 申請URL: https://support.console.aws.amazon.com/support/contacts#/rdns-limits
    - ![screencapture-support-console-aws-amazon-support-contacts-2024-04-22-14_31_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551379/d7d4b060-4c08-dd6d-7d5c-582675e0cb5f.png)
- 自分の知っている画面からすっかりデザインが変わっていました...
- 同時に100 申請ができるのはすごいと思いつつ、こんなに申請しなくて済むようにアプリケーションをなんとかして欲しい...

# まとめ
- メール送信は年々厳しくなっていくイメージで、そのうちEC2 からは直接メールが送れず、SES を使ったメール送信になるのでは？と考えています
- 本来SES を使うのが良いですが、アプリケーションとしてどうしてもEC2 からメール送信したいと言った要件もあり、極力SES を使うように促したいがSES が使えないときはこの申請が必要となるのでメモしておきます
#13 アンケートアプリ

この記事では、私が開発したアプリケーション「StressScanApp」を紹介します。これは、ユーザーが仕事のストレスを識別し、管理するのを助けるツールです。このアプリケーションは、ユーザーエクスペリエンスとデータ処理の効率を向上させるために、さまざまな技術を使用しています。これには、データ伝達のためのsegue技術の使用、コードを整理して機能関数を他のファイルに抽出すること、そしてunwind技術を使用してメインページに戻ることが含まれます。さらに、異なるユーザーのニーズに応えるために、日本語と台湾中国語の二つの言語バージョンを設計しました。

![JP.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3703986/7958c26c-cedb-42c8-8951-a3b63b44425a.gif)

![TW.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3703986/59bf514d-52df-74b6-0965-d42006ad0df0.gif)


## Segueを使用したデータ伝達
StressScanAppでは、segue技術を使用して異なるビューコントローラー間でデータを伝達します。ユーザーがアンケートを完了すると、アプリはsegueを使用して得点をSurveyViewControllerからresultViewControllerに伝達します。
以下のコードは、アンケートを完了した後、ユーザーのスコアに基づいて結果ページにナビゲートし、ユーザーの得点と言語設定を結果ページに伝達する方法を示しています。

```
@IBSegueAction func resultSegue(_ coder: NSCoder) -> resultViewController? {
    let controller = resultViewController(coder: coder)
    controller?.result = score
    controller?.language = language
    return controller
}
```
## 機能関数の抽出
コードを整理するため、すべてのUI要素を更新する機能関数は別のファイルfunction.swiftに配置しました。これには、問題テキストの更新、回答ボタンの更新、スコアに基づく結果の表示が含まれます。以下の関数は、現在選択されている言語と問題番号に基づいて、問題ラベルの内容とアラインメントを更新します。

```
func updateQuestion(language: String, count: Int, questionLabel: UILabel!, question: [Question]) {
    if count < 5 {
        switch language {
        case "JP":
            questionLabel.text = question[count].JP
            questionLabel.textAlignment = .left
        case "TW":
            questionLabel.text = question[count].TW
            questionLabel.textAlignment = .center
        default:
            questionLabel.text = question[count].JP
        }
    }
}
```

## Unwind技術を利用してホームページに戻る
unwind segueは、iOS開発でビューコントローラーのナビゲーションを管理する別の方法です。
この方法では、ユーザーがアンケートを完了して結果を確認した後、アプリのメインページに直接戻ることができます。
```
@IBAction func unwindToRootViewController(segue: UIStoryboardSegue) {
}
```

## 多言語デザイン
異なる地域のユーザーのニーズに対応するために、このアプリは日本語と台湾中国語の二つの言語をサポートしています。ユーザーはメインページで言語を選択でき、その後のすべての質問と回答は選択された言語で表示されます。
このコードは、言語選択のアクションを処理し、ユーザーの選択が正しく記録され、後続のアンケートページに適用されることを保証します。

```
@IBAction func languageChosen(_ sender: UIButton) {
    switch sender.titleLabel?.text {
    case "日本語" :
        language = "JP"
    case "中国語" :
        language = "TW"
    default :
        language = "JP"
    }
    
    performSegue(withIdentifier: "languageChosenSegue", sender: nil)
}
```
## 総括

###### :one:データ伝達とインターフェースナビゲーション
segue技術を実装することで、iOS内のインターフェース間でのデータ伝達メカニズムを深く理解しました。特に、performSegueやprepare(for:sender:)メソッドを使用してデータを伝達することで、データフローとインターフェースの挙動をより柔軟に制御し、アプリの全体的なユーザーエクスペリエンスを向上させることができました。
    
###### :two:コードの整理とモジュール化
機能関数を独立したファイル（function.swiftなど）に分離することで、コードをより良く組織し、可読性とメンテナンス性を向上させる方法を学びました。このモジュール化のアプローチは、コードベースをより整理されたものにし、将来の拡張と管理を容易にします。

###### :three:多言語サポートの実装
多言語サポートを実装する過程で、異なる言語環境をサポートするための柔軟な言語切り替えメカニズムの設計方法を学びました。これはアプリの国際化能力を強化するだけでなく、対象ユーザーの範囲も広がりました。

###### :four:Unwind Segueを使用したビューコントローラーの管理
unwind segueを実装することで、複雑なナビゲーション構造内でビューコントローラーの戻り動作を管理する方法を習得しました。これにより、アプリのナビゲーションプロセスをより良く制御し、ユーザーが異なるインターフェース間をスムーズに移動できるようにしました。

全体として、このプロジェクトは私の技術的スキルを向上させるだけでなく、問題解決能力と革新的な思考も豊かにしました。これらの学びは、私の将来のプロジェクトや職業發展に深い影響を与えるでしょう。

https://github.com/liyoway/StressScanApp
【Docker Compose】DB接続エラーの解決方法（mysql.connector.errors.DatabaseError: 2005 (HY000): Unknown MySQL server host 'db' (-2)）

## はじめに
備忘録
どなたかのお役に立てれば幸いです。

## 問題の詳細
Docker Composeで動かしているMySQLコンテナへ、Pythonの`mysql-connector-python`や、PHPを使って接続しようとした際に、以下のエラーに遭遇しました。

ここではPythonの例を紹介します。

```console
mysql.connector.errors.DatabaseError: 2005 (HY000): Unknown MySQL server host 'db' (-2)
```

以下のような`test.py`を使ってDBに接続しようとしていました。

```python:test.py
import os
import mysql.connector

conn = mysql.connector.connect(
    host=os.environ['DB_HOST'],
    port=os.environ['DB_PORT'],
    user=os.environ['DB_USER'],
    password=os.environ['DB_PASSWORD'],
    database=os.environ['DB_NAME']
)

conn.ping(reconnect=True)
cur = conn.cursor()

sql = "SELECT * FROM table"
cur.execute(sql, )
data = cur.fetchall()
```

また、`.env`は以下のようになっていました。

```:.env
DB_HOST = db
DB_PORT = 3306
DB_USER = test
DB_PASSWORD = test
DB_NAME = test
```

## 解決方法
上記のエラーを検索するとよく出てくるのが、`DB_HOST`として`docker-compose.yml`で指定したコンテナ名にするという方法です。

以下の例であれば、`db`が`DB_HOST`となります。

```yaml:docker-compose.yml
version: '3'
services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: test
      MYSQL_DATABASE: test
      MYSQL_USER: test
      MYSQL_PASSWORD: test
    ports:
      - 3306:3306
```

ただ、今回エラーが発生したのは`.dockerignore`の設定が間違っていたことが原因でした。

もともとは以下のように設定していましたが、`.env`が含まれていたことが原因で環境変数の読み込みがうまくいっていませんでした。

```:.dockerignore
.dockerignore
.git
.gitignore
README.md
*Dockerfile*
.env
```

`.env`を消すとうまくいきました。

```diff:.dockerignore
.dockerignore
.git
.gitignore
README.md
*Dockerfile*
- .env
```
【Python】range関数の数値がタプルに...「'tuple' object cannot be interpreted as an integer」エラー

# 概要
環境変数で設定した値に「`1,000,000`」のようにカンマを入れていたら、タプルとして解釈されてしまうことが分かりましたので、備忘録として紹介します。

# エラーが発生したコード

（実際に運用していた時は、別の環境設定ファイルから数値を取得していましたが）実際にやっていたことは以下の通りです。

```py
### 別ファイルで設定した値 ###
NUMBER = 1,000,000

### プログラムのコード ###
number = NUMBER

for i in range(number):
    # ...処理...
```

エラーメッセージ

```
    for i in range(number):
TypeError: 'tuple' object cannot be interpreted as an integer
```

# 原因と解決方法
冒頭にも記載した通り、Pythonではカンマで区切られた数値はタプルとして解釈されます。
そのため、`1,000,000`と記載していると、タプルとして`range`関数に渡されてしまいます。

この関数は、整数値を引数に取る必要があるので、「整数値じゃないよ、これタプルだよ」と怒られてしまうのです。

カンマを取り除いて実施すれば問題なく実施されます。

```py
NUMBER = 1000000
```

ということで、当然といえば当然の話ですが...
カンマを入れて数値を見やすいようにする癖がついていると、要注意だなと思いました。