OmniAICreator/Qiita-1.07M huggingface dataset:
統計情報に振り回された話

テーブルAからテーブルBに移送していく中で
一度のバッチ処理の中で移送されたAからさらに別のテーブルのデータを作る処理があり、
A1とA2、B1のデータからA3を作成する
といった具合に面倒くさい処理がありまして、、、

全ての移送処理はテーブルを空にして
データを移送、旧スキーマの統計情報を作成
という流れで移送されていました。

バッチ処理全体の最後のテーブル移送の処理の統計情報作成に
異常なまでの時間がかかっていたため
これは変だぞ？と思い調査を始めました。

初回の実行では約6hかかるのですが、
二回目以降の再実行だと5分で終わるため

「あ～これは新規で移送しているAのテーブルを何回も繰り返し見るせいでは？？」

という判断に。

試しにAの移送時にAの統計情報を作成する処理をはさむことにしました。
先に統計情報を作成することで、
統計情報がない状態でテーブルにアクセスする場合よりも
アクセス速度の改善が見られました。

今回の私の事象の場合6h→4m

以下、統計情報取得用のSQLです

```SQL
/*
諸々の移送処理関連のSQLは省略
*/

dbms_stats.gather_table_stats(
    user,REC.TABLE_NAME,cascade => true)

PROCEDURE XX IS
    BEGIN
        DECLARE
            CURSOR TAB IS
                SELECT TABLENAME
                    FROM USER_TABLES
                WHERE TABLE_NAME = 'OO'
                AND TEMPORARY = 'N'

            BEGIN
                FOR REC IN TAB LOOP
                    dbms_stats,gather_table_stats(
                    user,REC.TABLE_NAME,cascade => true);
                END LOOP;;
            END;
    END;
```

アクセス時間が異常にかかって悩む場合は
インデックスを作成するか
統計情報を作成するかを試すのも一つの手かもしれません
『リファクタリング:Rubyエディション』より、つい忘れてしまう書き方

## はじめに

『[リファクタリング:Rubyエディション](https://www.amazon.co.jp/dp/4048678841)』という本を読んでます。

業務でよく出てくる&すぐ使えるのについ自分が忘れてしまいがちな書き方を備忘録としてまとめます。

第6章と第9章で紹介されていた内容です。

## ループからコレクションクロージャメソッドへ

配列から特定の条件を満たす値を抽出する際は、`each`メソッドでループを回さず`select`や`reject`といったメソッドを使うことで、よりシンプルに記述できます。
<br>

いくつかのサンプルをまとめます。

### 配列から奇数だけを抽出する

#### before

```ruby
irb(main):001> odd = []
=> []
irb(main):002> [1,2,3,4,5,6,7,8,9].each { |i| odd << i if i % 2 != 0 }
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):003> odd
=> [1, 3, 5, 7, 9]
```

これは`select`メソッドを使えばよりシンプルに記述できます。

#### after

```ruby
irb(main):001> odd = [1,2,3,4,5,6,7,8,9].select { |i| i % 2 != 0 }
=> [1, 3, 5, 7, 9]
irb(main):002> odd
=> [1, 3, 5, 7, 9]
```

### 配列から3の倍数ではない値だけを抽出する

#### before
```ruby
irb(main):001> non_multiple_of_three = []
=> []
irb(main):002> [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].each { |i| non_multiple_of_three << i if i % 3 != 0 }
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
irb(main):003> non_multiple_of_three
=> [1, 2, 4, 5, 7, 8, 10, 11, 13, 14]
```

これは`reject`メソッドを使えばよりシンプルに記述可能です。

#### after

```ruby
irb(main):001> non_multiple_of_three = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].reject { |i| i % 3 == 0 }
=> [1, 2, 4, 5, 7, 8, 10, 11, 13, 14]
irb(main):002> non_multiple_of_three
=> [1, 2, 4, 5, 7, 8, 10, 11, 13, 14]
```

## 条件分岐の組み替え

OR演算子を用いることでより簡潔かつRubyらしく記述できます。

### before

```ruby
irb(main):001* def greeting(name)
irb(main):002*   if name
irb(main):003*     "Hello, #{name}!"
irb(main):004*   else
irb(main):005*     "Hello, guest!"
irb(main):006*   end
irb(main):007> end
=> :greeting
irb(main):008> greeting("Taro")
=> "Hello, Taro!"
irb(main):009> greeting
=> "Hello, guest!"
```

OR演算子を用いることで条件分岐をシンプルに書けます。

### after

```ruby
irb(main):001* def greeting(name)
irb(main):002*   name = name || "guest"  # OR演算子を活用
irb(main):003*   "Hello, #{name}"
irb(main):004> end
=> :greeting
irb(main):005> greeting("Taro")
=> "Hello, Taro"
irb(main):006> greeting
=> "Hello, guest"
```

## おわりに

『[リファクタリング:Rubyエディション](https://www.amazon.co.jp/dp/4048678841)』にはこの他にもたくさんのリファクタリング手法が出てきます。

Rubyらしい書き方についても理解が深まります。

どれも「必ずそう書くべき」というものではなく、時と場合によって柔軟な判断が求められるように思いました。

業務や学習の中で役に立ったリファクタリング手法があったら、適宜アウトプットしていきます。

### 参考資料

https://www.amazon.co.jp/dp/4048678841

https://docs.ruby-lang.org/ja/latest/class/Enumerable.html
ダンプはとろうねっていう話

先日、DBの移行時に新規のスキーマに各テーブルの
DROP→CREATEのSQLを流すバッチをたたこうとしたのですが、

手癖で検証用のDBに接続してしまい、
検証用DBのテーブルをDROP→CREATEしてしまいました。

データを吹き飛ばしたというやつです。

血の気が引いたのですが、前日にダンプを取っていることを思い出したので
大慌てでdmpをimportして事なきを得ました

（補足）
DB移行などだと新旧DBのカラムが異なる場合があります。
ダンプを流す際のテーブル、カラムの指定には注意しましょう。

以下は便利なバッチのメモです

```
エクスポート用

expdmp.bat

SET　DBUSER　=　DBUSER/PASSWORD/DATABASE
SET　dumpfile　=　ファイルパス
SET　logfile = ログファイルパス
SET　tables　= テーブル名※場合によってはスキーマも

expdp %DBUSER% directory=%1  dumpfile=%dumpfile% logfile=%logfile%　tables=%tables%
```

```
インポート用

impdmp.bat

SET　DBUSER　=　DBUSER/PASSWORD/DATABASE
SET　dumpfile　=　ファイルパス
SET　logfile = ログファイルパス
SET　tables　= テーブル名※場合によってはスキーマも

impdp %DBUSER%  directory=%1  dumpfile=dumpfile.dmp logfile=%logfile%　tables=%tables%
```

インポートの場合、オプションを用いたインポートが可能で
・SKIP　表はそのままに次のオブジェクトへ
・APPEND　ソースから行をロードし、既存行に付け足す
・TRUNCATE　既存の行を削除してからソースから行をロードする
・REPLACE　既存の表を削除してソースから表、行をロードする

があり場合によって使い分けが可能だが、
dumpファイルを作成、取り込みを行う場合は一度バッチファイルの中身を
確認してから行うのが安牌かと思われる。
SSHを使ってGitHubのリポジトリをclone

[概要](#概要)
[環境](#環境)
[手順](#手順)
- [1: SSHキーを生成する](#1-sshキーを生成する)
- [2: SSHエージェントを起動し、SSHキーを追加する](#2-sshエージェントを起動しsshキーを追加する)
- [3: SSH公開鍵をGitHubに登録する](#3-ssh公開鍵をgithubに登録する)
- [4: SSHでリポジトリをクローンする](#4-sshでリポジトリをクローンする)

# 概要
OSを変更し、新しいローカル環境で開発をするために自分のリポジトリからクローンを行う方法を解説します。


# 環境
Ubuntu 20.04.6 LTS


# 手順


## 1: SSHキーを生成する



### SSHとは
暗号化された通信を行うためのプロトコルのことで、GitHubのリモートにアクセスするとき安全にデータをやり取りできます。

大きなメリットは、パスワードが不要という点と感じています。

<br>
SSHキーが生成されていない場合は、作成する

```bash
ssh-keygen -t rsa -b 4096 -C "GitHubに登録しているメールアドレス"
```

`ssh-keygen`:公開鍵と秘密鍵を作成するコマンド

https://atmarkit.itmedia.co.jp/ait/articles/1908/02/news015.html

`-t rsa`:`-t`は鍵タイプ、`rsa`はrsaアルゴリズム（RSA暗号）を意味しています。


`-b 4096`:`-b`はビット数、ビット数は暗号鍵の長さを示します。ビット数が多いほど鍵の強度が上がり、安全性が向上します

`-C "コメント"`:`-C`はコメントのことで、鍵にコメントを追加するオプションです。

<br>

生成されたキーはデフォルトで `~/.ssh/id_rsa` に保存されます。
```bash
ls
# -> id_rsa  id_rsa.pub
```


## 2: SSHエージェントを起動し、SSHキーを追加する
```bash
eval "$(ssh-agent -s)"

ssh-add ~/.ssh/id_rsa
```
`ssh-add`:SSHエージェントに鍵を追加するためのコマンドです。




## 3: SSH公開鍵をGitHubに登録する
```bash
cat ~/.ssh/id_rsa.pub
```
`.pub`は公開鍵（Public Key）ファイルを示す拡張子です。

```
ssh-rsa ..........
```
ssh-rsaからすべてコピー

1. GitHubにログイン。
2. 右上のプロフィールアイコンをクリックし、Settings（設定） を選択します。
3. 左側のメニューで「SSH and GPG keys」を選択し、「New SSH key」ボタンをクリックします。
4. Title には適当な名前を入力し、コピーした公開鍵を Key に貼り付けます。
5. 「Add SSH key」をクリックして登録します。


# 4: SSHでリポジトリをクローンする

1. GitHubでクローンしたいリポジトリにアクセスします。

2. 緑色の「Code」ボタンをクリックします。

3. SSH タブを選択し、表示されたSSHアドレスをコピーします。

4. ターミナルで次のコマンドを実行して、リポジトリをクローンします。

```bash
git clone git@github.com:username/repo.git
```
Spresense Arduinoの周期タイマ割り込みについて

Spresense Arduinoには時間割り込みの関数として ```attachTimerInterrupt()```が存在します．大変ありがたいです．

本記事の発端はちゃんと[公式マニュアル](https://developer.sony.com/spresense/development-guides/arduino_developer_guide_ja.html)をちゃんと読んでいなかったために生じた問題ですが，自戒の念を込めて記事にしておきます．

### 症状
周期タイマ割り込みにしたかったのに割り込みが一回で停止する．

問題となったコードは次の通りです．
```c
    #include <MP.h>  // MPLog用
    #define INTERVAL_US 500
    
    void flip(){
        MPLog("poyo\n");
    }
    
    void setup(){
        attachTimerInterrupt(flip, INTERVAL_US);
    }

    void loop(){
    }
```

こちらの気持ちとしてはシリアルモニターにつないだとき，500usごとにpoyoが続けて表示されてほしいのですが，このコードだと１回しか表示されません．

### 原因
割り込み関数で待ち時間を返す必要がある．

結論から言えば下記のように修正する必要があります．
```c
    #include <MP.h>  // MPLog用
    #define INTERVAL_US 500
    
    unsigned int flip(){
        MPLog("poyo\n");
        return INTERVAL_US;
    }
    
    void setup(){
        attachTimerInterrupt(flip, INTERVAL_US);
    }

    void loop(){
    }
```

変更点としては，flip関数の型をunsigned intに変更したうえで，return文を追加しています．
マニュアルのattachTImerInterruptの項に次のように記載があります．
> ・この関数が 0 を return したときは、タイマーが停止し、ワンショットタイマーとして使用できます。 
> ・周期タイマーとして使用したいときは、attachTimerInterrupt() で指定した us 時間と等しい値を return で返してください。
> ・その他、return で任意の値を返すことで、次のタイマー割り込みまでの時間を動的に変更することができます。

つまり割り込みの周期を動的に変更できるようになっているようです．

大変ありがたいんですが，例えばmbedのTickerのような感覚で使った結果事故りました．
【macOS】OSのアップデートが打ち切られて、Xcodeがダウンロードできない！


## ある日のこと

`Xcode` 入れてアプリ開発するかぁ〜  

![スクリーンショット 2024-10-07 17.45.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/dc68c00d-2581-7875-d480-c1d769104ad2.png)  

あれ、OS最新にしなきゃダメか

![スクリーンショット 2024-10-07 18.32.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/ecd4a92d-5764-89c1-d4d2-7cc5fad471d8.png)

:angel: 

いつの間にかサポート切られた...  
えー新しいの買いたくない... :scream:

左上のりんごマークから、このMacについて確認する  

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/66f66ace-72d7-26f3-1faa-99aa4dce4b90.png" width="300px">

流石に古いな...




## バージョンを指定して Xcode をインストールする

`Xcode` のバージョンごとのサポート要件は、下のリンクから確認する

https://developer.apple.com/jp/support/xcode/

今のOSは `Veutura 13.7` なので、`Xcode 15.2` までが対象みたい  

`Xcode` をダウンロードするために、以下のリンクにアクセス  
Develop って書いてあるけど apple ID はいつも使ってるやつでOK
https://developer.apple.com/download/all/

`Xcode` にバージョンをつけて検索したら出てきた  
これをダウンロード  
相変わらずくそでかサイズなので、しばらく待つ  

> xip は署名付き zip らしい

![スクリーンショット 2024-10-07 18.41.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/93ab1eb8-8472-11a0-cddc-4c8564ba18f6.png)

ダウンロードしたら、ダブルクリックで実行する
解凍もまた時間かかる...

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/12a38eed-852f-52aa-59fe-112e0b69dd23.png" width="100px">

すると、同じフォルダに `Xcode` のアイコンが生成される！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/45e0493e-d2b1-7a70-6dd8-82d803098f86.png" width="100px">

mac の流儀に従って、「アプリケーション」に移動させよう

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/5fe9fd8f-8c6b-bbe9-dca2-db0ba8f8dd64.png" width="400px">  

ダブルクリックすると、起動準備が始まり...
どれをインストールするか選ばされる  
`macOS` と `iOS` を選択  

![スクリーンショット 2024-10-07 18.59.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/33c5b17d-e75b-8445-dc3b-efe59b4322fe.png)

これでインストール完了！  

![スクリーンショット 2024-10-07 19.02.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/4d769b21-b94f-1bdd-2c40-a7a4bbd05725.png)


## 参考

https://qiita.com/naginx/items/0d560c460235f1ab2282
PL/SQL　#04　デバッグ

前回例外処理を書いたので、その流れで
エラーのデバッグ等に関しても説明していく。

基本的には前回の例外処理の際にも記載した

```SQL
DBMS_OUTPUT.PUT_LINE('DEBUG');
```

を利用してコンソールやlog上に任意のデバッグ文字を出力することで
どのタイミングまでの処理が実行できているのかなどの判断をしていく。

もちろんの事、変数などの中身を出力することができるので、
```SQL
DECLARE
    TEST　NVARCHAR2(300)；


    --変数にデータベースの中身を入れ込むようなSQLを用意する
CURSOR cur IS 
    SELECT　*　
        FROM　XXX　;

BEGIN
　　OPEN cur;
        LOOP　FETCH cur INTO row;
        EXIT WHEN cur%NOTFOUND;
            TEST := row.AAA;
            DBMS_OUTPUT.PUT_LINE(TEST);
        END LOOP;
    CLOSE cur;
END;
　　　　

```
上記のような変数を出力するSQLも実行可能である
※上記のような場合だと出力文字列の長さ次第でエラーになるので
タイミングは注意。
UTL_FILEなどで出力するタイミングで
出力データが何処までできているのか？など
タイミングを見極めてデバッグをはさまないと無駄足になる可能性がある。
【WindowsからMacへ移行】Git、GitHub設定メモ

## マシンスペック
- MacBook Pro M3
- Sonoma 14.6


## Homebrewのインストール
https://brew.sh/ja/

:::note info
デフォルトでMacにGitが入っていますが、Homebrew経由でインストールするとバージョン変更しやすいそうなので設定します.

※ターミナルでgit --versionを実行すると、「Apple Git-〇〇」と表示されていました.
これはMacに入っているGitを参照していることになります.
:::

ターミナル上で実行し、インストール
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

passwordを求められますが、PCログイン時に入力しているものを入力すればOK

するとエラーが発生:frowning2:

/opt/homebrew/bin is not in your PATH.


下記コマンドをターミナルで実行し、pathを通せばOK
```
export PATH="$PATH:/opt/homebrew/bin"
```

brew -vを実行してバージョン確認できればインストール成功


## Gitインストール

```
brew install git
```

パスを通すための作業準備として、使用しているシェルを確認
```
echo $SHELL
```

bashの場合で進めます
```
vi ~/.bash_profile
```

下記コマンドを入力(mac pro M3の場合.M1/M2だとパスが異なるようです)
```
export PATH="/opt/homebrew/bin:$PATH"
```

保存
```
source ~/.bash_profile
```

実行してApple表記が消えていればOK
```
git --version
```

### 参考：
https://qiita.com/shott/items/ec9d8fe95cae1d9eb9d8

https://zenn.dev/koichiba/scraps/e1bd5c3ab18cfa


## GitHubに接続
基本的に以下記事の動画通りに進めればOK(お世話になっています:sunny:)

https://qiita.com/Sicut_study/items/0318cc136c189b179b7f


### 参考：
https://docs.github.com/ja/enterprise-cloud@latest/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection
if args.hoge:記法をオススメしない理由

argparseを使って引数で受けた数値ゼロ（`0`）の条件処理でハマった問題。
まず数値を持つか否かで分岐してから数値判定したいとき、最初の分岐で横着して単に`if args.hoge:`と書くときに遭遇した。

まず、問題が起きない非ゼロの例
```py
num = args.hoge #type=int
# num: int = 1

if num:
    if num > 0:
        print("positive")
    else:
        print("zero or less")
else:
    print("ERROR")

# positive
```
上記のように、`if num:`は`num`が正でも負でも動くが、実は`num`がゼロのときだけ期待通りに動いてくれない。
```py
# num: int = 0

if num:
    if num > 0:
        print("positive")
    else:
        print("zero or less")
else:
    print("ERROR")

# ERROR
```
※逆に、numにゼロが来た時だけ動かない挙動を実装したい場合は（ゼロか非ゼロかで条件分岐させたい場合等）、この書き方のままでよい。

原因は、`if`が`0`を認識していないのではなく、`if 0:`が`False`扱いになる仕様のせい。
```py
if 0:
    print("yes")
else:
    print("no")

# no

if -5:
    print("yes")
else:
    print("no")

# yes

if 5:
    print("yes")
else:
    print("no")

# yes
```

`if num:`に`num=0`も`num`が値を持つと認識させるには、`is not None`を加えればよい。
```py
# num: int = 0

if num is not None:
    if num > 0:
        print("positive")
    else:
        print("zero or less")
else:
    print("ERROR")

# zero or less
```
この修正なら、それ以降の条件文を一切イジらなくて済む。

# 教訓（戒め）
`if args.hoge:`と横着せず、面倒でも
`if args.hoge is not None:`と書くこと！
codeium使ってみた

# codeium
　AIによってコード補完、コード生成、チャット機能を提供するサービス。
　VS Codeなど各種IDEで利用できる。

https://codeium.com/

# 選定理由
　私の勤めている企業が所謂オレオレフレームワークを利用しているため、オレオレフレームワークを理解してもらわないとコード補完、チャット機能が使い物にならない。
 　codeiumにはコンテキスト（RAGみたいなもの）があり、IDEで開いているファイルや開いていないプロジェクトのファイルの情報を元にコード補完、チャットを行ってくれるため、オレオレフレームワークを考慮した結果を返してくれるためcodeiumを選択しました。
  
https://docs.codeium.com/context-awareness/overview

# 使用感
　チャット機能がなかなかに素晴らしいです。オレオレフレームワークのクラス、メソッド、引数の説明などをかなりのレベルで返してくれます。それ以外にも神クラスを読み解くのに役立ったり使用価値が高いです。
　コード補完は個人的にはそこそこ使えるかな止まりでした。タイピングする手間が省けるかなくらい。
 　固定コンテキスト、カスタムチャットをより利用したら、もう少し使用感良くなりそうなので、今後の課題です。

# コード以外の使い道
　プロジェクトの仕様が書かれたテキストファイルを固定コンテキストに設定することで、チャット機能でコードの説明と仕様の説明両方できないかなと思い試してみましたが、上手くいかなかったです（設定が悪かっただけかも？）。どのみち固定コンテキストに設定してしまうとコード補完にも影響が出そうなので、ドキュメントの管理は別のチャットAIを利用した方が良いかも。

# データの取り扱い
　無料プランの場合、チャット機能でデータ収集がされるみたいです。（2024年10月7日）
　無料プランの場合でも、設定でデータ収集不可にできるのですが、チャット機能が使用不可になります。データ収集を防ぎたい場合は有料プランをおすすめします。

>How does Codeium Chat work?
Codeium Chat seamlessly integrates the powers of open-ended conversation with IDE context. Besides allowing familiar interactions like those with ChatGPT, users can use smart suggestions to perform common actions such as adding documentation to functions or refactoring code. Under the hood, Codeium Chat has a variety of models to choose from. There is our Base Model (Llama 3.1 70B based, fine-tuned in house), Codeium Premier (Llama 3.1 405B based, fine-tuned in house), as well as OpenAI's GPT-4o and Anthropic's Claude 3.5 Sonnet. For paying SaaS and Hybrid users, we are able to promise zero data retention for Chat (contact us for more information about paid SaaS plans), but because of this usage of Open AI, we can only enable it for free tier users that have code snippet telemetry enabled since we cannot guarantee how OpenAI stores and uses telemetry data. For self-hosted enterprise customers, we are able to provide Chat via our own Chat models, as well as provide optionality to integrate with private endpoints of leading model API providers.

https://codeium.com/faq
[SwiftUI] レビューリクエストの頻度を設定する方法

# 1. はじめに
アプリを開発する際、ユーザーからのフィードバックを得ることは非常に重要であり、レビューはユーザーがアプリをインストールするかどうかを決定する際の参考になります。
しかし、レビューリクエストは頻度が多いと、ユーザー体験を損なう可能性もあります。そこで、適切な頻度でレビューを促す仕組みを導入することが大切です。

本記事では、SwiftUIを使って、アプリ内でビューの遷移回数に応じて`SKStoreReviewController`を用いたレビューリクエストを行う簡単な実装方法を紹介します。
ユーザーがある程度アプリを使い慣れた段階で自然にレビューを促すことで、ポジティブなフィードバックを得やすくし、UX（ユーザーエクスペリエンス）を向上させることができます。

# 2. 完成イメージ
FirstViewに3回遷移した時にレビューリクエストが送られる。
![ScreenRecording_10-07-2024 10-30-54_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892118/357d3fd8-64b9-3b05-e202-14791bdd4af0.gif)
<br>

# 3. サンプルコード
・レビューリクエストを送るための関数
```swift:RequestReview
import StoreKit

// レビューリクエストをカウントして、特定の回数に達したらリクエストを送る関数
func RequestReview() {
    // アクション回数を保存するためのUserDefaultsキー
    let key = "reviewRequestCount"
    let threshold = 3  // レビューをリクエストする頻度（例：3回に1回）
    
    // 現在のカウントを取得
    let currentCount = UserDefaults.standard.integer(forKey: key)
    
    // カウントをインクリメント
    let count = currentCount + 1
    UserDefaults.standard.set(count, forKey: key)
    
    // 指定回数に達したらレビューをリクエストし、カウントをリセット
    if count >= threshold {
        if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
            SKStoreReviewController.requestReview(in: windowScene)
        }
        UserDefaults.standard.set(0, forKey: key)  // カウントをリセット
    }
}
```
・FirstView（３回遷移したとき、レビューリクエストが表示される。）
```swift:FirstView
import SwiftUI

struct FirstView: View {
    var body: some View {
        NavigationView {
            VStack {
                Text("FirstView")
                    .font(.largeTitle)
                    .padding()
                // SecondViewへのリンク
                NavigationLink(destination: SecondView()) {
                    Text("Go to SecondView")
                        .font(.title)
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(10)
                }
            }
            .onAppear {
                // 画面表示時にRequestReviewを呼び出す
                RequestReview()
            }
        }
    }
}

#Preview {
    FirstView()
}
```
・SecondView
```swift:SecondView
import SwiftUI

struct SecondView: View {
    // dismissを使うためにEnvironmentから取得
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        VStack {
            Text("SecondView")
                .font(.largeTitle)
                .padding()
            
            Button(action: {
                // dismissを使って前の画面に戻る
                dismiss()
            }) {
                Text("Back to FirstView")
                    .font(.title)
                    .padding()
                    .background(Color.red)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
        }
        .navigationBarBackButtonHidden()
    }
}

#Preview {
    SecondView()
}
```
<br>

# 4. まとめ
レビューリクエストをアプリ内で適切な頻度で表示することは、UXを損なわずにフィードバックを得るための重要な手法です。今回紹介した実装方法では、ビュー遷移の回数に応じて自動的にレビューリクエストを送信する仕組みを構築しました。
また、今回は3回に1回の頻度にしましたが、ご自身が適切だと思う頻度に設定して試してみてください。
【Vuetify】プルダウンのテキストに、リストとは別の文言を表示したい

# こういうことをしたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153233/a26ac1b0-6be0-aa41-b9f3-34e12f0b8e16.png)
## 条件
- Vuetifyの`v-select`を使用する
- ややこしい処理は書きたくない

# 調査結果
- `v-select`の`slots-selection`を使用するといい感じになるらしい

## コード
```Vue:
<template>
  <v-app>
    <v-container>
      <v-select :items="fruitList" item-value="price" item-title="name">
        <template #selection="select">
          {{ select.item.title + '(' + select.item.value + '円)' }}
        </template>
      </v-select>
    </v-container>
  </v-app>
</template>

<script setup>
  const fruitList = [
    {
      name: 'りんご',
      price: 30,
    },
    {
      name: 'みかん',
      price: 10,
    },
    {
      name: 'ばなな',
      price: 50,
    },
  ]
</script>
```

### `#selection="select"`の中身
```JavaScript:
{
  "item": {
    "title": "orange",
    "value": 10,
    "props": {
      "title": "orange",
      "value": 10
    },
    "raw": {
      "name": "orange",
      "price": 10
    }
  },
  "index": 0
}
```

# 参考
https://vuetifyjs.com/en/api/v-select/#slots-selection

https://qiita.com/a_pori/items/780da65c34981b3db04c
next/image レスポンシブ対応

備忘録

next/imageを使用する時、
```typescript
<Image 
  src={src}
  alt={alt}
  layout='fill'
/>
```
`layout='fill'`にすると、`width`と`height`の省略が可能。
この場合、親要素に`position: 'relative'`と`display: 'block'`が必要.

```typescript
<div style={{position: 'relative', display: 'block'}}>
  <Image 
    src={src}
    alt={alt}
    layout='fill'
  />
</div>
```

📝今後のtodo
  -> `layout='responsive'`を使用するケースなど、他のケースについても調べてまとめる

誤認などあれば、ご指摘いただけますと幸いです🙇‍♂️
ロケールを一時的にCに変更してコマンドを実行する（LANG=C コマンド実行）

## はじめに

普段はロケールをC以外、たとえば日本人であれば`ja_JP.UTF-8`にしているケースが多いと思います。

ただ、コマンドの実行結果を一時的に英語で受け取りたいなど、何かしらの事情があったときにロケールの設定を都度変更するというのは手間です。

そのような場合は、ロケールを一時的にCに変更することが可能です。

## どのような場面で使えるか？

これは一例ですが、RHEL 9でグループリストを表示すると、グループ名は日本語で表示されます。グループ名の確認をするだけなら日本語でよいのですが、コマンドでグループ名を用いるときは、日本語ではなく英単語で入力できればその方が楽だなと思ったのがきっかけでした。

## 書式

実行したいコマンドの前に`LANG=C`を記述して、コマンドを実行します。

```bash
LANG=C <実行したいコマンド>
```

## 実行例

ロケールを`ja_JP.UTF-8`に設定しているケースを想定します。

```bash:ロケール ja_JP.UTF-8で実行
# dnf grouplist
サブスクリプション管理リポジトリーを更新しています。
メタデータの期限切れの最終確認: 0:00:24 時間前の 2024年09月09日 18時38分01秒 に実施しました。
利用可能な環境グループ:
   サーバー (GUI 使用)
   最小限のインストール
   ワークステーション
   カスタムオペレーティングシステム
   仮想化ホスト
インストール済みの環境グループ:
   サーバー
インストール済みのグループ:
   コンテナー管理
   ヘッドレス管理
利用可能なグループ:
   レガシーな UNIX 互換性
   RPM 開発ツール
   スマートカードサポート
   .NET Development
   コンソールインターネットツール
   グラフィカル管理ツール
   システムツール
   開発ツール
   ネットワークサーバー
   セキュリティーツール
   科学的サポート
```

```bash: 一時的にロケールをCにして実行
# LANG=C dnf grouplist
Updating Subscription Management repositories.
Last metadata expiration check: 0:00:32 ago on Mon Sep  9 18:38:01 2024.
Available Environment Groups:
   Server with GUI
   Minimal Install
   Workstation
   Custom Operating System
   Virtualization Host
Installed Environment Groups:
   Server
Installed Groups:
   Container Management
   Headless Management
Available Groups:
   Legacy UNIX Compatibility
   RPM Development Tools
   Smart Card Support
   .NET Development
   Console Internet Tools
   Graphical Administration Tools
   System Tools
   Development Tools
   Network Servers
   Security Tools
   Scientific Support
```

## 疑問点

方法がわかったのは良いのですが、この方法についての公式情報に当たる情報が見つけられませんでした。

たとえば、UbuntuやAWS、各種OSSなどであれば、それぞれ公式のドキュメントというものがあります。しかし、`LANG=C <実行したいコマンド>`については、公式情報というものがどこにあるのかがわかりませんでした。

一般に知られている、もしくは少々調べれば対処方法が判明することはよくあります。しかし、方法はわかっても、公式情報を見つけられないことがあります。この件もその一つです。

どなたか、この方法の公式情報に当たる情報をご存じの方がいたら教えて下さい。
SQLの基礎を学ぼう！データベース操作の基本

<br>

## ■ はじめに
<br>
この記事では、SQLの基礎を解説します。<br>
これからSQLを学ぶ方や、基礎を再確認したい方はこの記事でSQLの基本操作を一緒に見ていきましょう。<br>
データベース操作の検索、追加、更新、削除の基本操作をサンプルコードで説明します。

## ■ 目次
<br>

1. [SQLとは](#1-sqlとは)
2. [データの抽出（SELECT文）](#2-データの検索select文)
3. [データの追加（INSERT文）](#3-データの追加insert文)
4. [データの更新（UPDATE文）](#4-データの更新update文)
5. [データの削除（DELETE文）](#5-データの削除delete文)
6. [まとめ](#6-まとめ)

## 1. SQLとは
<br>
SQL（Structured Query Language）は、リレーショナルデータベースを操作するための言語です。<br>
SQLを使って、データベースに対してデータの検索・追加・更新・削除を行うことができます。

- 検索:データの検索時にselect文を使用します。
- 追加:データの追加時にinsert文を使用します。
- 更新:データの更新時にupdate文を使用します。
- 削除:データの削除時にdelete文を使用します。

## 2. データの検索（SELECT文）
<br>
データベースから必要なデータを取得するには`SELECT`文を使用して検索を行います。<br>
例えば、以下のように書くことでテーブル`users`から全てのデータを取得できます。

```sql
SELECT * FROM users;
```

テーブル`users`から特定のカラムだけを取得したい場合は、カラム名を指定します。

```sql
SELECT name, email FROM users;
```

ここでは`name`と`email`というカラムだけが返されます。
条件を絞るためには、`WHERE`句を使用します。

```sql
SELECT * FROM users WHERE age >= 20;
```

このクエリでは、age というカラムが20以上の場合のみ取得することができるので、
20歳以上のユーザーのみが取得できることになります。

## 3. データの追加（INSERT文）
<br>
新しいデータをデータベースに追加するには、`INSERT` 文を使用します。<br>
例えば、以下のように書くことで、新しいユーザーを`users`テーブルに追加できます。

```sql
INSERT INTO users (name, email, age) VALUES ('Test Taro', 'taro@example.com', 25);
```

これにより、`name`、`email`、`age`のフィールドにデータが追加されます。
<br>
ここでテーブルには上記以外に`Adress`という項目があったとします。
値を設定しているのは上記3項目以外のフィールドのみのため、値を設定していない`Adress`はどうなるかというと、
テーブル定義によっても異なりますが初期値（`null` や `0`など）が設定されます。

## 4. データの更新（UPDATE文）
<br>
既存のデータを更新したい場合は、`UPDATE`文を使用します。<br>
例えば、特定のユーザーのメールアドレスを更新するには以下のようにします。

```sql
UPDATE users SET email = 'tarotaro@example.com' WHERE name = 'Test Taro';
```

このクエリは、名前が`Test Taro`であるユーザーのメールアドレスを更新します。
`WHERE`句を忘れると全てのレコードが更新の対象になってしまうため注意しましょう。
<br>
また、仮に同テーブル上に同姓同名の`Test Taro`が複数存在した場合、更新対象も複数となります。
対象レコード1レコードのみ更新したい場合には、テーブルごとに一意になる主キー（PRIMARY KEY）などを用いて対応するようにします。


## 5. データの削除（DELETE文）
<br>
不要なデータを削除するには、`DELETE` 文を使用します。<br>
例えば、特定のユーザーを削除する場合は次のようにします。

```sql
DELETE FROM users WHERE name = 'Test Taro';
```

このクエリは、`name`が`Test Taro`であるユーザーをデータベースから削除します。

## 6. まとめ
<br>

- SQLはデータベース操作のための言語
    - `SELECT`文でデータを抽出
    - `INSERT`文でデータを追加
    - `UPDATE`文でデータを更新
    - `DELETE`文でデータを削除
<br>

- 基本的な操作を理解することで、データベースを効率的に操作可能

この記事では基礎的なSQLをご説明しました。
SQLにはJOINやサブクエリなど、さらに複雑なクエリも存在するため、基礎的な構文を理解しておきましょう。
個人的によく使うpytestコマンドのオプション

# よく使うオプション

--showlocals
テストが失敗した場合、失敗したテストの中でローカル変数の値を表示します。これにより、テストが失敗した際にデバッグしやすくなります。

--junitxml=junit.xml
テスト結果をJUnit XML形式でjunit.xmlというファイルに出力します。CIツール（例: Jenkins）でのテスト結果の収集や表示に役立ちます。

--cov-report=html:htmlcov
カバレッジレポートをHTML形式で生成し、htmlcovというディレクトリに出力します。生成されたHTMLファイルをブラウザで開くと、どのコードがテストされているかを視覚的に確認できます。

--cov-report=term
テストカバレッジの結果をターミナル上にテキスト形式で表示します。テスト実行後に概要がターミナルに表示されるため、即座にカバレッジを確認できます。

--cov=app（ディレクトリ名）
appディレクトリにあるコードのカバレッジを測定します。このオプションは特定のディレクトリやモジュールのカバレッジを指定する際に使用されます。

--cov-branch
ブランチカバレッジを有効にします。分岐（ifやelse、tryやexceptなどの条件分岐）がどれだけテストされたかもカバレッジレポートに含まれます。

-s
テスト中に標準出力（print文など）を抑制せずに表示します。デフォルトでは、pytestは標準出力をキャプチャして非表示にするため、テスト実行中に出力を確認したい場合にこのオプションを使います。

-lf
失敗しているテストだけを実行します
JavaScriptでアップロードしたファイルのマジックナンバーを取得

# やりたいこと
Inputタグに対してファイルがアップロードした際に、JavaScriptでアップロードしたファイルのマジックナンバーを取得し画面に表示したい

# やり方
※ファイルの拡張子を変更しても、マジックナンバーは変わらない

```
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ファイルのマジックナンバー取得</title>
</head>
<body>
  <h1>ファイルのマジックナンバー表示</h1>

  <input type="file" id="fileInput">
  <p id="magicNumberDisplay">マジックナンバー: なし</p> <!-- 表示用の要素 -->

  <script>
    const fileInput = document.getElementById('fileInput');
    const magicNumberDisplay = document.getElementById('magicNumberDisplay');

    fileInput.addEventListener('change', function(event) {
      const file = event.target.files[0]; // 最初のファイルを取得
      if (file) {
        const reader = new FileReader();
        
        reader.onload = function(e) {
          const arrayBuffer = e.target.result;
          const uint8Array = new Uint8Array(arrayBuffer).subarray(0, 4); // 先頭4バイトを取得
          let magicNumber = "";
          
          // 16進数に変換してマジックナンバーとして表示
          for (let i = 0; i < uint8Array.length; i++) {
            magicNumber += uint8Array[i].toString(16).padStart(2, '0') + " ";
          }
          
          magicNumberDisplay.textContent = 'マジックナンバー: ' + magicNumber.trim(); // 画面に表示
        };

        // ファイルの先頭部分をArrayBufferとして読み込む
        reader.readAsArrayBuffer(file.slice(0, 4)); // 先頭4バイトを取得
      } else {
        magicNumberDisplay.textContent = 'マジックナンバー: なし'; // ファイルが未選択の場合
      }
    });
  </script>
</body>
</html>

```
こんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/b6f2dd4e-4732-5670-2717-5c98cedbaa7f.png)


# 参考サイト
https://wa3.i-3-i.info/word12868.html

https://ite-notes.com/others-magic-number-1/
JavaScriptでアップロードしたファイルのMIMEタイプを取得

# やりたいこと
Inputタグに対してファイルがアップロードした際に、JavaScriptでアップロードしたファイルのMIMEタイプを取得し画面に表示したい

# やり方
※PCのブラウザはiphoneのheicファイルのMIMEタイプを取得できない

```
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ファイルのMIMEタイプ表示</title>
</head>
<body>
  <h1>ファイルのMIMEタイプ表示</h1>

  <input type="file" id="fileInput">
  <p id="mimeTypeDisplay">MIMEタイプ: なし</p> <!-- 表示用の要素 -->

  <script>
    const fileInput = document.getElementById('fileInput');
    const mimeTypeDisplay = document.getElementById('mimeTypeDisplay');

    fileInput.addEventListener('change', function(event) {
      const file = event.target.files[0]; // 最初のファイルを取得
      if (file) {
        const mimeType = file.type; // MIMEタイプを取得
        mimeTypeDisplay.textContent = 'MIMEタイプ: ' + mimeType; // 画面に表示
      } else {
        mimeTypeDisplay.textContent = 'MIMEタイプ: なし'; // ファイルが未選択の場合
      }
    });
  </script>
</body>
</html>

```

こんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/7301d44c-d04c-fe8c-9e3e-6346b3c094fa.png)

# 参考サイト
https://developer.mozilla.org/ja/docs/Web/HTTP/MIME_types
Lambda（python）でS3からファイルを取得し、ファイルのマジックナンバーとMIMEを判定する

# やりたいこと
Lambda（python）で事前にS3バケットへアップロードしたファイルを取得し、ファイルの各メタデータであるマジックナンバーとMIMEを取り、ファイル形式を判定したい

# 構築
・S3バケット
・Lambda
・IAMポリシー
・IAMロール

# やり方
Lambda→S3のポリシー
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}
```

Lambdaソース
```
import boto3

def lambda_handler(event, context):
    # S3バケットとファイルキーを指定
    bucket_name = "バケット名"
    object_key = "ファイル名"
    
    # S3リソースの作成
    s3 = boto3.resource('s3')
    
    # バケットオブジェクトの取得
    bucket = s3.Bucket(bucket_name)
    
    # オブジェクトの取得
    obj = bucket.Object(object_key)

    
    # オブジェクトのメタデータを取得
    mime_type = obj.content_type
    print(f"MIME type: {mime_type}")
    
    # コンテンツを取得
    file_content = obj.get()['Body'].read()
    
    print("Finished fetching object")
    
    # ファイルの最初の100バイトを読み込む（マジックナンバーをチェックするため）
    file_content = obj.get()['Body'].read(100)  # 最初の100バイトを読み取る
    
    # バイナリデータを16進数の文字列に変換
    file_content_hex = file_content.hex()

    # マジックナンバーに基づいてファイル形式をチェック
    file_type = None
    if file_content_hex.startswith('ffd8ff'):
        file_type = 'JPEG'
    elif file_content_hex.startswith('89504e47'):
        file_type = 'PNG'
    elif file_content_hex.startswith('474946'):
        file_type = 'GIF'
    elif file_content_hex.startswith('424d'):
        file_type = 'BMP'
    elif file_content_hex.startswith('66747970', 8):  # HEICのマジックナンバーは9桁目から
        file_type = 'HEIC'
    else:
        file_type = 'Unknown'
 
    return {
        'statusCode': 200,
        'body': f"MIME type from S3: {mime_type}, File type detected:{file_type}, {file_content_hex}"
    }
```
2024年11月27日 watsonxイベントの参加方法 - Tech Xchange Japan 2024@ホテル雅叙園東京

## はじめに
IBM製品とテクノロジーに関する最新情報をお届けするTexhXchange Japan 2024イベントが開催されます。
日時：2024年11月27日 (水)　10:00~19:00
会場：ホテル雅叙園東京
〒153-0064 東京都目黒区下目黒1-8-1
イベントサイト: [ibm.biz/techxchange24](ibm.biz/techxchange24)
本記事ではTechXchangeイベントにて、watsonx関連のセッションやハンズオンに登録する方法について解説いたします。

## イベントに登録する
まずは[IBM TechXchangeの予約サイト](https://www.ibm.com/jp-ja/events/techxchange?utm_medium=Exinfluencer&utm_source=Exinfluencer&utm_content=TXCWW&utm_id=sales-invitation#ww)で参加を申し込みます。
①〜⑤の手順で参加登録〜セッション一覧までアクセスしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738536/62fd63ce-bc06-82bc-15b4-3b0195f7bfd0.png)

## 完了・お礼メールからマイサイト経由で個別セッションを登録
個別登録をもってwatsonx関連の個別セッション/ハンズオンに参加できるようになります。
watsonxに関するセッションは以下をご用意しています。
![スクリーンショット 2024-10-07 12.23.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738536/991eb6af-0b14-bc18-4878-827e89e620e3.png)

watsonxに関するハンズオンは以下をご用意しています。
![スクリーンショット 2024-10-07 12.22.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738536/8df6a91b-6460-3db7-cf9c-8a489fbe1d3a.png)

詳細は下記のようにTechXchangeの予約サイトのブレイクアウト・セッションの項からも確認することができます。（これは私が登壇するハンズオンですね！）
![スクリーンショット 2024-10-07 12.25.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738536/93d7ce44-cbaa-cd32-e63f-fd16b29795c1.png)

ぜひ興味があるセッションにお申し込みください！
pgAdminでアカウントロックされたときの対処法

# 前提
+ **Docker Desktopを使用して**localでプロジェクトを立ち上げている。
+ DBにはデータは０だったので初期化されているかどうか分からない。 
:::note warn
今回のケースはたまたま上手くいっただけかもしれません。公式では別の方法が記載されていますので不安な方は下を参照してください。
:::
[「pgAdmin　アカウントのロック/復元」](https://www.pgadmin.org/docs/pgadmin4/latest/restore_locked_user.html "タイトル")
## なぜこうなったか
アカウントパスワードを3回以上間違えたから。
初心者なので何が起きたか理解するのに10分かかりました…

## 方法
### 1. Docker Desktopを立ち上げる。
※プロジェクト自体は立ち上げなくて良い。

### 2."Volumes"を選択
![スクリーンショット 2024-10-07 16.05.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125367/95ef54b9-9994-c7fa-7d15-ab7ea7b657df.png)

### 3."プロジェクト名_sail-pgadmin4"の項目を探してチェックボックスにチェックを入れてdeleteボタンを押す
![スクリーンショット 2024-10-07 16.08.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125367/0853cdcc-a56a-1483-e1c3-aff998248d20.png)


### 4. 「./vendor/bin/sail up -d」コマンドでバックグラウンドでプロジェクトを立ち上げる
このときDocker Desktopの"Containers"内を確認して「pgadmin4」がRunning状態ならOK
![スクリーンショット 2024-10-07 16.16.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125367/4316569b-1f7d-268a-0d70-dc43ebd9e672.png)


### 5.再度pgadminにアクセスしてログインすれば、ロックは解除されているので問題なくログインできる

## 終わりに
初投稿です。
ネットで調べたんですけど、全然簡単に解決できる方法がなくて、途方に暮れていましたが、プログラミングスクールの講師の方に泣き付いたら５分で解決しました。こんなことは簡単すぎてだれも記事書かないのかと悲しくなりましたが、私みたいな方が一人でもこの記事を見て「うおおおお解決した！焦ったああああああ」となってくだされば幸いです。
レビューアイで 星野リゾート 界 アルプス のレビュー分析をしてみた

弊社リテジーリンクではレビュー分析AIレビューアイの無料デモを公開中です。
レビューアイ (英語表記 ReviewAI) は、商品・サービスのレビューを分析し、
観点ごとに強みと改善点を明らかにする、レビュー分析AIです。

本記事では、星野リゾート 界 アルプス のレビューを例に
レビューアイで明らかになった強みと改善点を1つずつ紹介します

## 強み ##
レビューアイでレビュー分析すると、レビューでよく出てくる観点が一覧できます。
強み順に並べると、**部屋** が一番上にきます。
![スクリーンショット 2024-09-15 22.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/1709d5a3-9380-923b-5d0e-5cdda9821c56.png)


**部屋** の詳細を確認すると、部屋に関してどのようなレビューがあるのか可視化されます。
こちらを強み順に並べると、**風呂、過ごす、食事** が上位にきます。
![スクリーンショット 2024-09-15 22.36.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/f4ed694d-2c59-5551-ae81-233aa9b1f349.png)


**風呂** のレビューを見ると、感情分析した結果で整理してレビューの抜粋文が確認できます。
入浴時間も長めに設定されていたりまた、囲炉裏でのお粥の提供があります。
![screencapture-reviewai-next-seed-work-review-2024-10-01-21_03_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/4bfa6e3d-435d-a528-5a5a-7a447eb82471.png)



## 改善点 ##
レビュー分析で見つかる観点を改善順で見ると、**部屋、風呂、食事**が上がっています。
![スクリーンショット 2024-09-15 22.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/0946d26d-5320-cf06-7dda-51a46fda27c6.png)
**食事** の詳細を確認すると、どのような点で改善の余地があるか一覧できます。
![スクリーンショット 2024-09-16 3.08.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/bdfa737d-30d9-a1ab-f815-f90da217de1b.png)
**寒い**のレビュー文を見てみると食事処が別棟になっており移動時に寒かったり、
エアコンが寒かったりという改善点の声がありました。

![スクリーンショット 2024-09-16 3.11.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/c77f637b-ed8a-5b88-89f9-e1b706759dc3.png)

## まとめ ##
レビューアイで 星野リゾート 界 アルプス のレビュー分析をしました。

結果として
・部屋や風呂が広く清潔感がある。
・場所によっては寒さ対策が必要な場所がある
ということが判明しました。

今回は紹介できませんでしたが、
・サービスやスタッフの対応
・食事の量
についての意見もありました。

[レビューアイ](https://reviewai.next-seed.work/)の無料デモを公開中です。
ぜひ[こちら](https://reviewai.next-seed.work/)からお申込みください。
【Blender4.0】Blender's extension must be refreshed!　

## 環境情報
* Blender 4.2.LTS

## 発生した課題
* `Blender 4+`インストール後、`Blender 3`でダウンロードしたアドオンがインストールすることができない。

![スクリーンショット 2024-10-07 16.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087199/2d43a395-345e-61c6-91fa-5acf33dbc7c8.png)

## 解決策

* エラーメッセージを確認すると、`システムプリファレンスを開いてオンラインアクセスを有効化してください`との指示があるので、従います。

![スクリーンショット 2024-10-07 16.31.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087199/cf59243b-2bf0-7bb8-a129-7e89dfa26a08.png)


* [システム]タブを開き、[ネットワーク]セクションの中に「オンラインアクセスを許可」というチェックボックスがあるので、そちらのチェックをONにしてください。

![スクリーンショット 2024-10-07 16.32.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087199/67ceb3b2-742f-2fb7-54db-5a721206c030.png)



## 結果
* Disabledだったボタンが押せるようになりました。
* 私の環境でインストールできなかった`Dynamic Sky`及び`LoopTools`の2つのアドオンを、ダウンロードすることができました。

![スクリーンショット 2024-10-07 16.32.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3087199/942555da-78b2-e000-b79d-0820b388a8ee.png)
[tips][cpp][problemSolver] boolとは0か0以外か

# boolとは0か0以外か

boolは数値も設定できます。0がFalse、0以外がTrueに変換されます。以下は例です。`bool a`とします。

## a≠0の例

```cpp
bool a = 100;
cout << a << endl;
```

output
```cpp
1
```

```cpp
bool a = 5;
cout << a << endl;
```

output
```cpp
1
```

```cpp
bool a = -1;
cout << a << endl;
```

output
```cpp
1
```

次のif文の中の処理は実行されます。
```cpp
bool a = 999;
if (a) {
　　　　// この処理は実行されます
  cout << "Hello" << endl;
}
```

```output
Hello
```

## a=0の例

```cpp
bool a = 0;
cout << a << endl;
```

output
```cpp
0
```

次のif文には入りません。
```cpp
bool a = 0;
if (a) {
　　　　// この処理は実行されません
  cout << "not reached" << endl;
}
```

output
```cpp
```
特定のセルの値に応じて行の背景色を変更(メモ)

Excelで、特定のセルの値に応じて行の背景色を変更するには、「条件付き書式」を使う方法が便利です。今回の要件では、N列の値が「完了」になるとA列からN列までのセルがグレーになるように設定します。

以下の手順で設定できます：

1. **セル範囲を選択する**  
   - A6からN61までの範囲を選択します。つまり、`A6:N61`を選択してください。

2. **条件付き書式を設定する**
   - Excelのリボンで「ホーム」タブに移動し、条件付き書式の「新しいルール」をクリックします。

3. **数式を使用して、書式設定するセルを決定**  
   - 「数式を使用して、書式設定するセルを決定」を選択します。

4. **数式を入力**  
   - 次の数式を入力します：
     ```excel
     =$N6="完了"
     ```
   - この数式は、N列のセル（N6, N7, …）の値が「完了」になったときにその行全体に書式を適用するためのものです。

5. **書式を設定**  
   - 「書式」ボタンをクリックし、背景色をグレーに設定します。

6. **設定を完了**  
   - 「OK」をクリックして条件付き書式の設定を完了します。

これで、N列の値が「完了」になった行の背景色がグレーに変更されるようになります。
【DAX】スライサーの選択値で返すテーブルの行を変える！【Power BI】

# はじめに
どうも、ATLのヴィリアスです。

最近 Power BI (DAX) をいじっていると、「スライサーの選択値に応じて、返すテーブルの行を変えたいな～」と思うことがありました。

パッと考えると、「そんなの Switch でスライサーの選択値を見ればいいじゃない」と思いますよね。
思わない？…私がそう思いました。

ところがどっこい、そう簡単には実装させてくれないのが PowerBI (厳密には DAX)。

そこで色々試してみた結果、最終的には想定していた動きを実装できたので、  
今後似たようなことで悩む人の参考になれるように記事に残していきます！

# やりたいこと

**スライサーで選択されている値に応じて、返すテーブルの行を変える！**
(そして、返ってきたテーブル内の数値を集計して、メジャーとして扱いたい)

# まずは私のアンサー！

※ ここでのスライサーは 1, 2, 3 のいずれかが選択されるとします。

```DAX
メジャー = 
    VAR table1 = FILTER(テーブル, SELECTEDVALUE(スライサーの選択値) = 1 [&& 任意のフィルター条件1] …)
    VAR table2 = FILTER(テーブル, SELECTEDVALUE(スライサーの選択値) = 2 [&& 任意のフィルター条件2] …)
    VAR table3 = FILTER(テーブル, SELECTEDVALUE(スライサーの選択値) = 3 [&& 任意のフィルター条件3] …)
    
    VAR table = UNION(table1, table2, table3)
    
    RETURN SUM(table[集計したい数値を含む列])
```

# ちょっとした解説

```
FILTER(テーブル, SELECTEDVALUE(スライサーの選択値) = 1 [&& 任意のフィルター条件1] …)
```

まず FILTER では、条件に合うテーブルの行を取得しています。
条件に合わない (FALSE) 場合、FILTER は 0 行を返します。

これによってスライサーの選択値に応じた、特定のテーブルの行を返すことができます。
(スライサーで 1 が選択されていれば、2, 3 の条件はすべて FALSE (0行) となり、1 のフィルター結果が返ってくる)

https://learn.microsoft.com/ja-jp/dax/filter-function-dax

```
SELECTEDVALUE(スライサーの選択値)
```

SELECTEDVALUE ではスライサーで選択された値を取得しています。

https://learn.microsoft.com/ja-jp/dax/selectedvalue-function-dax

```
VAR table = UNION(table1, table2, table3)
```

スライサーの選択値を評価し終えた後は、全テーブルを UNION で結合します。
ここで結合することで、スライサーの選択値がいかなる場合でも 1 つの変数を参照すれば良くなります。
(スライサーの選択値によって、参照する変数を分岐させる必要がなくなる)

https://learn.microsoft.com/ja-jp/dax/union-function-dax

(ただ UNION は異なるテーブル間では使えないのがネックですね)

```
RETURN SUM(table[集計したい数値を含む列])
```

最後に、私の場合はテーブル内の数値をメジャーとして扱いたかったので、
取得できたテーブルの列に対して集計関数を噛ませています。

# なんで Switch を使わない？

Switch を使わないのではなく、"**使えない**" のです。

ここで、DAX における Switch のドキュメントを見てみましょう。

https://learn.microsoft.com/ja-jp/dax/switch-function-dax

「戻り値」に注目です。

> **戻り値**
> value との一致があった場合、対応する result からのスカラー値が返されます。 

そうです。**スカラー値** (単一の値) しか返せないんです。
なので、以下みたいな DAX を記述すると Switch の部分でエラーになります。

```DAX
メジャー =
    VAR table = SWITCH(SELECTEDVALUE(スライサーの選択値),
                    "1", FILTER(テーブル, フィルター条件1),
                    "2", FILTER(テーブル, フィルター条件2),
                    "3", FILTER(テーブル, フィルター条件3)
                )

    RETURN SUM(table[集計したい数値を含む列])
```

> エラー: 複数の列を式で参照しています。複数の列をスカラー値に変換することはできません。

Switch からはスカラー値しか返せないので、 
複数の列 (テーブル) が Switch 内の処理結果となってしまうと NG ということです！

# おわりに

あくまでもこの記事のやり方は、数ある中の1つのやり方にすぎないと思うので
もしこの記事よりもスマートな方法があれば、ぜひそちらも試してみてください！

それではまた、次の記事で。

# 参考にしたもの

- [Return a Table With a SWITCH](https://community.fabric.microsoft.com/t5/Desktop/Return-a-Table-With-a-SWITCH/td-p/3267069)
- [DAX How to return a table based on a condition - workaround for IF to return a table](https://stackoverflow.com/questions/71930745/dax-how-to-return-a-table-based-on-a-condition-workaround-for-if-to-return-a-t)
【Blender】簡単ワイヤーフレーム化

# 概要
ノードやモデファイアを使わずにメッシュをワイヤーフレーム化する方法を紹介します

# 環境
- Blender 3.6

# 手順

1. ワイヤーフレーム化したいポリゴンを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/9bca51fa-f47a-f0ab-4432-adf326f3ef93.png)
<br\>
2. 面の差し込みショートカット「i」キーを押し、もう一度「i」キーを押し(各ポリゴンごとに面の差し込みON)、お好きなワイヤーフレームの幅[m]を入力しEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/d118c56f-0c8f-ac27-1e1e-16607e2cb221.png)
<br\>
3. ワイヤーフレーム以外の面が選択されているので、その状態でDelキーを押し、面を消去
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/7e33fb00-6d90-2cce-b3c5-185a5a5a1b01.png)
<br\>
4. 完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/08debf4b-40ed-fcc0-9964-f421120853f2.png)


# おまけ
大きさの異なるポリゴンが混在しているメッシュで、上記の方法で幅の太いワイヤーフレームを作ろうとすると、面の差し込み量がポリゴンの大きさを越してしまうことがあります

実際にUV球で幅の広いワイヤーフレームを作ろうとすると、上部や下部の小さいポリゴンの頂点が飛びでます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/9fcc5480-3991-7d88-6da4-3dceb6df38a0.png)

この場合はワイヤーフレームの太さを、ポリゴンの大きさを基準にした「スケール」で決める方法が有効です

1. トランスフォームピボットポイントで「それぞれの原点」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/d936fd82-7413-dbc1-f400-b5733b417dd6.png)
<br\>
2. 面の差し込みショートカット「i」キーを押し、もう一度「i」キーを押し(各ポリゴンごとに面の差し込みON)、**ワイヤーフレームの幅として0を入力**しEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/05815087-2101-2769-3fc7-552df36853aa.png)
<br\>
3. その状態でSキーを押し、ワイヤーフレームの幅を調整しEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/17f3e3b2-83e7-5c2b-752f-48aad4026190.png)
<br\>
4. ワイヤーフレーム以外の面が選択されているので、その状態でDelキーを押し、面を消去
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/51fb6adc-4338-517d-0e6a-784fa87ec99e.png)
<br\>
5. 完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864812/ca4145f7-972f-7441-e9cc-2472bfc9dfd8.png)
cloud digital leader に合格する為にやったこと

# はじめに
cloudの実務経験無し。
サーバに関する知識ほぼ０。
基本情報持ち。

こんな僕がcoludに興味を持ち9月上旬に1回目の試験を受ける。
見事撃沈。

そして2回目を先日受け無事合格した為、参考になればと思います。

# 勉強時間
1回目(8時間)：定番本1週 + 公式問題2週 + Udemy定番コース1,2 を2週
2回目(30時間)：合格対策本2週 + 公式問題2週 + Udemy定番コース1,2,3 を3週,短期突破コース1,2,3,4,5,6 を3週 20時間程度

合計：38時間程度
# 公式トレーニング
英語で色々と話をしてくれて各章の最後に小テストがある。
大体は喋ってるだけなので、翻訳を読みながら進めて行くのが良い。
# 公式問題
全30問の問題集です。実際の問題と比較すると出題内容が浅い為、感覚を掴むなら良いと思う。
各回答が何故ダメなのかというのが説明出来るレベルであれば合格出来るレベルと思って良いと思う。
# Udemy
[GCP：Google Cloud Digital Leader模擬試験問題集（6回分320問）
](https://www.udemy.com/course/google-cloud-digital-leader6320/?couponCode=JPLETSLEARNNOW "定番のコース")皆がオススメしてくれてるド定番。
このコースの演習1,2を完全に理解していると合格すると言われている。
公式問題を少し深くした感じなので、しっかりと理解をしながら進めたい人向けではあるが、
あくまで理解を深める為の問題集。同じ問題はマジで出ない。

[【GCP】短期突破！Google Cloud Digital Leader模擬試験問題集（6回分）](https://www.udemy.com/course/gcpgoogle-cloud-digital-leader6/?couponCode=JPLETSLEARNNOW,"おすすめコース")
合格したいだけならこれを暗記で良い。
レビューに9割同じ問題が出たと書いてあって半信半疑ではあったが、これと全く同じ問題がマジで9割は出る。
残りは文言が多少違うレベルだったり、見た事ない問題が2問ぐらいあったりというレベル。
その為、理解は後で良いから、とにかく合格したいっていう人向け。

# 書籍
定番本
<img width="25%" src="https://m.media-amazon.com/images/I/819e2q20FFL._SY466_.jpg">
さすが定番本と言われるだけあって、分かりやすくはあったが、試験で出る範囲はもう少し深い部分も多く、あくまでとっかかりとして使う分には有りって感じです。

比較的最近出た合格対策本
<img width="25%" src="https://m.media-amazon.com/images/I/71o5fuhUlXL._SY466_.jpg">
定番本と比べて、読みやすく書かれていて初心者向けに寄せた本という感じ。項目の説明とかは分かりやすくしてあるが、テスト範囲で求められるレベルとしては足りていないのかなという感じがした。

合格対策本のほうがCloud未経験者としては分かりやすかった。

# 最後に
合格するだけならUdemyの短期突破を暗記するだけで良い。
理解するなら合格対策本が分かりやすくて良かったなって感じでした。
404エラーハンドリングのテストでつまずいた経験とその解決策

# はじめに
ウェブアプリケーションを使用していると、「404 Not Found」というエラーページに出くわすことがあります。例えば、URLを手入力したり、古いリンクをクリックした場合に表示されることが一般的です。このようなエラーメッセージは、ユーザーにとっては不便ですが、適切なエラーハンドリングを実装することで、ユーザーにとってより良い体験を提供することができます。

しかし、実際に404エラーハンドリングをテストする際には、苦戦することもあると思いこの記事では、私が404エラーのテストに取り組んだ経験を通じて、陥りやすいミスとその解決策についてお話しします。


# 404エラーハンドリングの重要性
404エラーが発生した際、適切なエラーページを表示することは、サイトの信頼性を高めるためにも重要です。ユーザーが存在しないページにアクセスした場合、明確で親切なメッセージを表示することで、他のページへの誘導を行うことが可能になります。
404エラーはテスト設計をする中で確認しておく項目があります。

# 確認項目

1.settings.pyでDEBUGをオフにする

404エラーページを確認するには、settings.pyファイルでDEBUGをFalseに設定します。これにより、Djangoは404エラー時にカスタムエラーページを表示します。

```settings.py
DEBUG = False
```

2.templatesフォルダにエラーハンドリング用のファイルを作成する

カスタム404エラーページを表示するためのHTMLテンプレートを用意します。例えば、404.htmlというファイルを作成し、ユーザーに親切なメッセージを表示します。

``` templates/404.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ページが見つかりません</title>
</head>
<body>
    <h1>404 - ページが見つかりません</h1>
    <p>申し訳ありませんが、お探しのページは存在しないようです。</p>
    <a href="{% url 'home' %}">ホームに戻る</a>
</body>
</html>
``` 

3.test_views.pyの作成

404エラーが発生するURLに対するテストケースを作成し、期待するレスポンスコードが返ることを確認します。

```tests/test_views.py
from django.test import TestCase
from django.urls import reverse

class YourViewTests(TestCase):
    def test_nonexistent_url(self):
        response = self.client.get('/nonexistent-url/')
        self.assertEqual(response.status_code, 404)  # 404エラーが返されることを確認
```

4.カスタム404ビューの設定

urls.pyでカスタム404ビューを設定します。これにより、404エラーが発生した際に特定のビューが呼び出されるようになります。

```urls.py
from django.conf.urls import handler404
from .views import custom_404_view

handler404 = custom_404_view
```

5.アプリケーションのviews.pyにクラスを設定

404エラーが発生した際に表示する内容を定義したカスタムビューを実装します。

```views.py
from django.shortcuts import render

def custom_404_view(request, exception):
    return render(request, '404.html', status=404) 
    # 404ページを返す
```

# つまづいた箇所
実際に確認項目を前提に踏まえた上で、404エラーの処理が期待通りに動作するか試してみたところ、以下のエラーに直面しました。

```
AssertionError: 404 != 200 : Couldn't retrieve content: Response code was 404 (expected 200)
```

404エラーを試す試験で200のステータスコードが返却されていました。
原因を特定するのに時間を要しましたが、200を返すケースとして
 self.assertContainsを扱っている場合も理由の1つであることがわかりました。
 プロジェクト作成の際に、エラーメッセージを返す確認のプロセスとして以下のコードを末尾に加えていました。
 
```
  self.assertContains(response, 'ページが見つかりません')
```

この内容を省略することで無事テストケースをパスすることができました

```tests/create.py
  def test_404_error_handling(self):
    # 存在しないページへのアクセス
    response = self.client.get('/nonexistent-url/')
    
    # ステータスコードが404であることを確認
    self.assertEqual(response.status_code, 404)
    
    # エラーページのテンプレートが正しく表示されているか確認
    self.assertTemplateUsed(response, 'test_templates/404.html')
     
```

# まとめ

今回の経験を通じて、カスタム404エラーページを設定するためのステップや、テストケースの重要性を実感しました。特に、テスト中に予期しないステータスコードが返された際には、原因を探ることが重要であり、self.assertContainsの使用に注意が必要であることを学びました。
これらの手順をしっかりと踏むことで、404エラーに対する効果的なエラーハンドリングが実現でき、ユーザーにとって快適なサイトを提供できると感じました。
LaTeX で破線の囲みをする。

ascmac みたいなのを破線でやる方法

```tex
\documentclass{jlreq}
\usepackage{tcolorbox}

\tcbuselibrary{skins, breakable} % 破線などのライブラリ

\newenvironment{dashedScreen}{%
    \begin{tcolorbox}[
        frame hidden,
        interior hidden,
        enhanced, % 高度な設定を可能にする
        arc=1em, % 角の半径
        borderline={1pt}{0pt}{dashed}
    ]
}{%
    \end{tcolorbox}
}

\begin{document}

\begin{dashedScreen}
    $n\geq3$ なる整数 n に対して，\par $x^n+y^n=z^n$ を満たす正の整数の組 $x,y,z$ は存在しない。
\end{dashedScreen}

\end{document}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986389/dec5b86c-8276-fffa-b0cc-86b7e81f70c1.png)

```tex
\documentclass{jlreq}
\usepackage{tcolorbox}

\tcbuselibrary{skins, breakable} % 破線などのライブラリ

\newenvironment{dashedItembox}[1]{%
    \begin{tcolorbox}[
        coltitle=black,
        title=#1,
        frame hidden,
        interior hidden,
        enhanced, % 高度な設定を可能にする
        arc=1em, % 角の半径
        borderline={1pt}{0pt}{dashed}, % 破線
        attach boxed title to top left={ % タイトルボックスの移動
            xshift=1em, 
            yshift*=-\tcboxedtitleheight/2
        },
        colbacktitle=white,
        boxed title style={frame hidden}, 
    ]
}{%
    \end{tcolorbox}
}

\begin{document}

\begin{dashedItembox}{フェルマーの最終定理}
    $n\geq3$ なる整数 n に対して，\par $x^n+y^n=z^n$ を満たす正の整数の組 $x,y,z$ は存在しない。
\end{dashedItembox}

\end{document}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986389/a7dc63ef-ad0a-b8f6-eb99-9fb35737798c.png)
初Hackathon体験記

# 初ハッカソンに出てみた
縁あって、今まで出るのを渋っていたハッカソンに出ました
（約1か月前なので記憶が曖昧...）
その感想をここにまとめておきます。

:::note info
My Profile：C, C++, html/CSS （git未経験者）
:::

## 担当箇所
自分はバックエンドの担当で、未経験のpythonをカキカキしてた。
C言語の知識で乗り切った感じ。今後、pythonのクラスなど、C言語にはない部分をしっかり勉強しなおさないといけない。

## 結果
結局、作品は完成せず...といった感じだった。
原因は、最終日でフロントエンドとバックアップを接続する部分が完成しなかったところだった。
次回は、先に接続を確かめてみようと思う。
あとは、githubの運用もごちゃついたのでそこも改善していきたい。
（具体的には、普段からgithubに触れるようにしたい）
自分的に心配だったgithubの使い方も、メンターさんのサポートで何とかなった。

## 感想
結論からいうと、なかなかいい経験になった。
今後のハッカソンも、機会を見つけて参加したい。