OmniAICreator/Qiita-1.07M huggingface dataset:
Bigqueryでスケジュールクエリを使って5日分ずつ更新する方法

## はじめに
・Bigqueryを使ってLooker Studioでダッシュボードを作成している
・カスタムクエリが毎回回っていて、コストが爆増
・そのためスケジュールクエリを作成
・Bigqueryサウンドボックスをもとに作成

## やりたいこと
・はじめに過去データをすべてぶちこんだテーブルを作成する
・そのテーブルに最新5日分のデータを追加していく
・GAのデータ確定に3日ほどかかるため、年のため5日分のデータを取得し既存の場合はUPDATE、新規の場合はINSERTする

## 工程
### もとになるテーブルを作成
全期間のデータをいれたテーブルを作成する
```SQL
CREATE OR REPLACE TABLE
  sql-book-350002.schedule.test
AS
SELECT
    user_pseudo_id
  , PARSE_DATE("%Y%m%d",event_date) AS event_date
  , (ev.value.string_value) as url
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`,
UNNEST(event_params) as ev
WHERE event_name = "first_visit"
AND ev.key = "page_title"
```
CREATE OR REPLACE TABLEでテーブルがなければ、新規作成あれば上書きができる
※上書きの場合、既存のデータがすべて削除されるので注意

### クエリを作成
以下のクエリでスケジュールクエリを設定する
```SQL
-- 更新するテーブルを選択
MERGE `sql-book-350002.schedule.test` AS existing_data
USING(
  SELECT
      user_pseudo_id
    , PARSE_DATE("%Y%m%d",event_date) AS event_date
    , (ev.value.string_value) as url
  FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`,
  UNNEST(event_params) as ev
  -- 5日分更新
  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(DATE(FORMAT_DATETIME('%Y-%m-%d', @run_time, 'Asia/Tokyo')), INTERVAL 4 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(DATE(FORMAT_DATETIME('%Y-%m-%d', @run_time, 'Asia/Tokyo')), INTERVAL 1 DAY)) 
  AND event_name = "first_visit"
  AND ev.key = "page_title"
) AS new_data
-- 既存か新規かを判定するカラムを設定
ON (existing_data.event_date = new_data.event_data)
-- 既存ならUPDATE
WHEN MATCHED THEN
  UPDATE SET
    existing_data.event_date = new_data.event_data, existing_data.url = new_data.url, existing_data.user_pseudo_id = new_data.user_pseudo_id
-- 新規ならINSERT
WHEN NOT MATCHED THEN
  INSERT
    (event_date, url, user_pseudo_id) VALUES(new_data.event_date, new_data.url, new_data.user_pseudo_id)
```
## スケジュールを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/786947/d77f5861-0d76-6000-334a-a14b352e4fd7.png)

サウンドボックスじゃ出来ないみたい
↓手順は以下↓
スケジュール→スケジュールされたクエリを新規作成

名前や時刻を設定→クエリ結果の書き込み先は無視(MERGEで設定済み)→自動ロケーションを選択

## まとめ
ダッシュボードのコストが1/3になった
リポジトリにタスク定義ファイルを含めないでGithubActionsでECSを自動デプロイしたい、tagも付与したいとき

リポジトリにタスク定義ファイルを含めないでGithubActionsでECSを自動デプロイしたいな〜とググっていたとき、
https://github.com/aws-actions/amazon-ecs-deploy-task-definition
のreadmeを見ると下記の記載が！

> タスク定義を git リポジトリにファイルとして保存したくない場合は、GitHub Actions ワークフローで既存のタスク定義をダウンロードできます。

    - name: Download task definition
      run: |
        aws ecs describe-task-definition --task-definition my-task-definition-family --query taskDefinition > task-definition.json


task definitionはリポジトリで管理しなくてよかったんや。。。。！と真似してみたところ、今度はタグ生成されるサービスにtagsが付与されていないことがわかった
describe-task-definitionコマンドには--query引数でJMESPathというjsonを整形する方法が提供されているが、結構癖があり、初学だったこともあり詰まったので共有。
結局下記のように書き換えてあげればtagsをtask definitionに含めることができ無事デプロイできましたとさ。

      - name: Download task definition
        run: |
          aws ecs describe-task-definition --task-definition task-definition --include TAGS --query "merge(taskDefinition,{tags:tags})" > ./task-definition.json



参考
https://chariosan.com/2021/07/19/githubactions_ecs_deploy_taskdef/
Linuxカーネルの削除

# ビルドしてインストールしたカーネルの削除

## 参考

https://wiki.gentoo.org/wiki/Kernel/Removal/ja

## 実際のコマンド

### ソースの削除

```
rm -r /usr/src/kernels/linux-6.1.12
```

### modules内ファイルの削除

```
rm -r /lib/modules/6.1.12
```

### boot内ファイルの削除

```
rm /boot/vmlinuz-6.1.12
rm /boot/System.map-6.1.12
rm /boot/initramfs-6.1.12.img
```

参考のページにはconfigを削除しているが私の環境ではそのファイルがなかったので、そのコマンドは実行していない。
あるとすれば次のようなコマンド。

```
rm /boot/config-6.1.12
```

参考のページではブートローダのエントリも削除するように指示がある。
次のように対応した。

/etc/grub.d/10_linuxというファイルに、

blsdir="/boot/loader/entries"

なる記述がある。
その中ディレクトリ(/boot/loader/entries/)に.confという拡張子のファイルがある。
これらのうち、削除するカーネルのバージョン番号に対応したものを削除した。
これによって起動後のgrubメニューから削除したカーネルのものは消えた。
Chaosのシュミレーション結果をStaticMeshに変換する方法 [Unreal Engine]

# はじめに



Chaosを使って破壊をし,シュミレーションした状態をStaticMeshにして使いたい！
調べてみたらUE5.1ではそんな機能ないみたい！
けどなんか頑張ったらできた！

のでその方法を残していきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/33499e66-3959-7511-6ca4-213f4490904f.png" width=90%>

この状態をStaticMeshに変換する





## 0.準備
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/200078ef-a8e6-5716-bb77-44a764543652.png" width=90%>

フラクチャモードでいい感じにバラバラにしておく





## 1.chaos cache managerでシュミレーションを記録する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/38652431-dad9-4bc1-ab76-f30ce8b65cf9.png" width=90%>

破壊を記録したいGeometry Collectionを選択して
**アクター → Chaos → キャッシュマネージャーを作成**
でChaos Cache CollectionとChaos Cache Managerを作成する





<br><br>

Cacheのバグなのか 破壊が始まった座標を初期値として保存するみたい。
それでは困るので,開始した瞬間に少しだけ破壊をさせて初期値を記録させる


<br><br>




Geometry Collectionの**Object Type**を **Sleeping**にする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/123dad1e-d37c-c4f4-53a7-8cf27b4ccbde.png" width=50%>



エンジンのコンテンツから **FS_MasterField**を見つけてレベルに配置する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/07104188-bbc6-5fdd-9cae-36fe414eea77.png" width=90%>


FS_MasterFieldの設定を画像のようにする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/2e23be14-362e-07fa-0e66-059f5ae3be0b.png" width=90%>


下向きに配置して 少しだけ下方向に破壊するようにする
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/77fdc19c-e9fc-6bbc-692c-721099b4f27c.png" width=90%>





設定し終わったらシュミレーションをさせて記録する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/23645253-f58b-8d9b-a6d4-bef349126729.png" width=90%>

シュミレーションを止めると
これで作成したChaos Cache Collectionに記録される




## 2.StaticMeshに変換したい状態を決める

レベル上のChaos Cache Managerの**Cache Mode**を
記録からスタチィックポーズにする
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/98b9b525-fbea-ee4a-893c-490728d48c73.png" width=90%>


この状態で**Start Time**を変えると記録された状態にGeometry Collectionが変化する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/9909a7b2-3fbf-dd08-4197-a34fc8467cd4.png" width=90%>




## 3.StaticMeshに変換する


フラクチャモードにして 
Utilities → ToMesh を選択する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/e1c6fcbb-6b1c-5535-6797-bde93dc95749.png" width=90%>

ここのチェックを外すと1つのStaticMeshとして変換される
(逆にチェックがあるとパーツごとにStaticMeshが生成れる)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/7c38b80f-3eb8-dd56-b29f-bff0f9e0747b.png" width=90%>







変換されているね


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/72e4f531-c660-e13c-d267-95eeb8194e42.png" width=90%>


StaticMeshのサイズがランドスケープの大きさが原因なのか巨大になってしまうみたい。
FBXに書き出して直したり,
パーツごとに書き出してアクターをマージしたりして対応するのが良さそう
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219682/693684cd-307f-27eb-3298-e971229835b2.png" width=90%>




おわり
Eternalplanet、住宅用蓄電システム「EP Cube」を日本で販売開始

![Eternalplanet1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784576/d09be68e-dd01-d1f7-4f43-87161e09827a.jpeg)
[Eternalplanet](https://eternalplanetenergy.com/)が、北米、欧州に続き、日本版[EP Cube](https://eternalplanetenergy.com/)を発売し、日本市場への正式参入を果たしました。その皮切りになるのが、以下の最新イベントです。

■イベント情報
•	スマートエネルギーWeek
•	開催日：2023年3月15～17日
•	会場：東京ビッグサイト
•	ブース番号：18-36

同社は、太陽光発電ソリューションの提供元であるCanadian Solar社傘下の消費者向けエネルギー技術の独立ブランドです。スペイン、アメリカでのローンチを成功裏に終え、今回の日本市場展開は、EP Cubeのグローバル戦略にとって新たな一歩となります。

EP Cubeは、家庭用統合型蓄電システムです。ハイブリッドインバーターとリン酸鉄リチウム電池を組み合わせたシステムで、家庭でのエネルギー生産、消費、貯蔵をスマートに管理することができます。また、魅力的でコンパクトなデザイン、簡単な設置、カスタマイズ可能な蓄電容量、リモートコントロール、安全かつ堅牢な操作性を誇ります。

【柔軟な拡張性】
電池モジュール1個で約3.3kWh、重さ35kg。スタッキングが可能で、運搬や設置が容易な商品となっています。各ユニットで、2～4個のバッテリーモジュールを積み重ねることができます。モジュールには5つのサイズがあり、さまざまな住宅のエネルギー需要を満たす代物です。

【安全・堅牢な技術】

EPキューブは、常に安全性を最優先し、高い安全基準をクリアした長期的なエネルギーソリューションの提供に注力しています。熱的・化学的安定性に優れたリン酸鉄リチウムを使用。IP65に対応し、15年間の保証付きです。

【完璧な互換性】

EP Cubeはハイブリッドインバーターを内蔵し、4つのMPPT接続と最大16Aの太陽光発電（PV─直流）の入力をサポート。また、既存のPVシステムおよびグリッドからの直流電流を蓄えることができます。さらに、EP Cubeには最大5.9kWの電気自動車用充電器を接続することも可能です。この強力な互換性により、家庭内のコスト削減に貢献します。

【アプリを用いたスマートモニタリング】

EP Cubeの操作・管理は非常にスマートです。Wi-FiとEthernetに接続することができます。EP Cubeのアプリを使って、住宅のエネルギー生産、貯蔵、消費をリモートで監視することも可能。天候の悪化を予想し、事前にエネルギーの貯蔵を通知。また、OTA（Over-the-Air）によるファームウェアのバージョンアップも可能です。

【環境・人に優しい未来をつくる】

EP Cubeは、環境と人に寄り添い、美しい未来を形作るソリューションです。最新鋭の技術から、エネルギー分野を先導。家庭で求められる真の効率性を実現しながら、明快さと使いやすさから、未来を見据えたスマートな暮らしを後押しします。

ウェブサイト：[https://eternalplanetenergy.com](https://eternalplanetenergy.com)
![Eternalplanet2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784576/b93eff37-7fe7-42af-5e63-2bc8963fac1c.jpeg)
String.valueOf(Object o)

String.valueOf(Object o)はo.toString がreturn
```java
class Sample {
    int i;
    public String toString() {
        System.out.println("sample tostring called");
        return "";
    }
}
public class SampleProject {
    public static void main(String[] args) {
        String.valueOf(new Sample());
        Integer.valueOf("");
    }
}
```
```
sample tostring called
```
Djangoでwebブラウザに画面表示させるまで（超初心者）

# 1.はじめに
本記事は「Django 初心者」などと調べると同じような記事がたくさん出てくる、いわゆる既出の内容です。
あくまで自分の勉強した内容をアウトプットする意図で書いている記事ですので温かい目で見守っていただけますと幸いですｍｍ

# 2.早速アプリを作ってみる
### Q.どうやってアプリを作るのか
※環境は構成済み（筆者はAnacondaを使用）

A.Djangoプロジェクトの中に用意されている「manage.py」というプログラムを使って作成していきます。
```
python manage.py startapp 名前
```

なんとこの「名前」の部分にアプリ名を入れるだけでアプリが作れてしまうらしい・・・

次にアプリを作成したフォルダに移動する必要があります。
筆者はデスクトップの「django_app」というプロジェクトに「hello」というアプリを作成したのでそこに移動します。ターミナルでのコマンドは
```
cd Desktop
cd django_app
```
このように「cd フォルダ名」で移動できます。
フォルダをのぞいてみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/dec29757-78d8-a738-1add-f16c29e3e0b7.png)
このように勝手にいろいろファイルが作成されています。
（筆者が足したものもありますが、ほとんどが勝手に追加されたものです）

それぞれが重要な役割を担っているのですが、ここでの説明は割愛させていただきます。

# 3.下準備完了
## views.py
さて、いよいよコードを書いていきます。
「views.py」というファイルを適当なテキストエディタで下記のように書き換えてみます。（筆者はVSCodeを使用）
```
from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse('Hello Django')
```
非常にざっくり説明すると
HttpResponse（）でインスタンスを作り、引数requestに括弧内で書いた内容がそのままreturnされクライアント側にそのまま返送されます。
つまり今回は「'Hello Django'」が返送されているといった具合です。

また、from~import...文はそれを実行するために必要な記載といった認識でとりあえずは大丈夫だと思います。
## urls.py
先ほどviews.pyに処理を記載しました。
ただそれだけでは表示はされないらしいので次にdjango_appプロジェクト内の「django_app」フォルダをのぞいてみます。
そこに「urls.py」というファイルがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/2fb54cbd-09db-6f09-7736-574e5b0381fe.png)
ここは文字通りURLを管理するファイルです。
確かに「Hello Django」を表示させるページのURL（**どのアドレスにアクセスしたらviews.pyのindex関数が実行されるか**）に関する記載をしておかなければなりません。
早速urls.pyを書き換えます。
```
from django.contrib import admin
from django.urls import path
import hello.views as hello

urlpatterns = [
    path('admin/',admin.site.urls),
    path('hello/',hello.index),
]
```
今回記載した「path('hello/',hello.index)」で「**hello/というアドレスにアクセスしたら「hello」フォルダ内のindexという処理を実行する**」という意味になります。

# 4.表示させてみる
ターミナルで
```
python manage.py runserver
```
というコマンドを実行しましょう。これでwebサーバーが実行されます。

適当なwebブラウザを起動し、以下のURLでアクセスしてみます。
**http://localhost:8000/hello/**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/fca97e51-d51c-625b-c0b0-60f734ab7f55.png)

自分の場合勉強する過程で色々足しちゃっているのでこんな感じです。
すみません・・・orz。
ただイメージ的にはこの真っ白な画面の左上に「Hello Django」と表示されるイメージです。

# 5.さいごに
今回勉強で使用させていただいた参考書を紹介します。
[「Python Django 超入門」](https://www.amazon.co.jp/Python-Django-%E8%B6%85%E5%85%A5%E9%96%80-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798054488)
こちらになります。

ひとまずこちらの参考書を一通り実施していきたいと思います。
まだまだ先ほどの実装画面も序盤ですが、一応それっぽい形にはなっているかと思います。
Anacondaや、他のファイルに関する説明を割愛しているので気になる方いらっしゃいましたら調べてみてください。
もちろん参考書には載っています。

ご覧いただきありがとうございました。
<HTML/CSS> Memo: Simple and Cool Expansible TOC Menu

## Goal

To put an expansible, easily-accessible TOC menu using only HTML and CSS.

## Code

```html:index.html
<link href="./style.css" rel="stylesheet" />

<div id="toc">

    <details>
        <summary>Table of Contents</summary>
        <ul>
            <!-- TOC -->
        </ul>
    </details>

</div>
```

```css:style.css

    :root{
        --display-max-width: 1200px;
    }
    
    *{
        box-sizing: border-box;
    }

    #toc{
        --toc-bg-color:#cccccc;
        --toc-detail-bg-color:#ffffff;
        position: fixed;
        bottom: 0px;
        left:0px;
        width: 100vw;
        padding: 0 5px 5px 5px;
        background-color: var(--toc-bg-color);
        height: calc(1em + 35px);
        overflow-y: auto;
        transition: height 0.5s;
    }
    
    #toc:has(details[open]){
         height:50vh;
    }
    
    #toc details{
        margin:0 auto;
        max-width: var(--display-max-width);
        background-color: var(--toc-detail-bg-color);
    }
    
    #toc details ul{
        margin-bottom:0px;
    }
    
    #toc details summary{
        box-sizing: border-box;
        position: sticky;
        padding-top:5px;
        top: 0px;
        background-color: var(--toc-bg-color);
        border: 5px solid var(--toc-bg-color);
}

```
【Swift】Point-Free Style：クリーンでエレガントなコードを書くためのテクニック

# はじめに
ポイントフリースタイルという言葉を目にし、気になったのでChatGPTで調べてみました。コード例にはSwiftを使用しています。この記事は、情報の正確性を保証するものではありませんので、あくまで参考程度に留めてください。

# Point-Free Styleとは何か
ポイントフリースタイルは、関数型プログラミングのテクニックの一つで、関数合成や部分適用を行う際に、引数を使わずに関数を表現する方法です。このスタイルは、関数の中身よりも引数や名前よりも関数の型に注目するため、より抽象的で、よりコンパクトなコードを記述することができます。

# Point-Free Styleの例
以下は、Swiftでのポイントフリースタイルの例です。
```swift
let numbers = [1, 2, 3, 4, 5]

func addOne(x: Int) -> Int {
    return x + 1
}

// 非ポイントフリースタイル
let result = numbers.map({ x in addOne(x: x) })
print(result) // [2, 3, 4, 5, 6]

// ポイントフリースタイル
let result2 = numbers.map(addOne)
print(result2) // [2, 3, 4, 5, 6]
```
この例では、mapメソッドを使って、配列の各要素に1を加えています。非ポイントフリースタイルの例では、クロージャを使って、addOne関数を呼び出しています。しかし、ポイントフリースタイルの例では、addOne関数を直接mapメソッドに渡しています。このように、ポイントフリースタイルを使うと、コードを簡潔にすることができます。

---

また、ポイントフリースタイルを使うと、関数合成や部分適用などのテクニックをより簡単に実現できます。
```swift
func multiplyByTwo(x: Int) -> Int {
    return x * 2
}

// 非ポイントフリースタイル
let result3 = numbers.map({ x in multiplyByTwo(x: addOne(x: x)) })
print(result3) // [4, 6, 8, 10, 12]

// ポイントフリースタイル
let result4 = numbers.map(addOne).map(multiplyByTwo)
print(result4) // [4, 6, 8, 10, 12]
```
この例では、最初に各要素に1を加え、その後2倍にすることが目的です。最初の例では、addOneとmultiplyByTwoの2つの関数をクロージャで組み合わせています。しかし、ポイントフリースタイルを使用すると、2つの関数を直接mapメソッドで合成することができます。

# まとめ
ポイントフリースタイルを使うと、コードがより短く、より読みやすくなります。ぜひ、使ってみてください。

---

ご覧いただきありがとうございました。

🐦 [Twitter: @shota_appdev](https://twitter.com/shota_appdev)

📱 [個人アプリ: Symbols Explorer](https://apps.apple.com/jp/app/symbols-explorer/id1612933742)
Nuxt3 / Vue3 – util で Fetch の処理を共通化する 

# 内容

- utils に共通処理を置いて Vue ファイルから呼び出す
-  fetch の結果として 呼び出し側の data を書き換えるには then の中で処理する必要があるので、 共通関数の引数として data を渡してしまう

# 呼び出し側

`Foo.vue`

```vue
<script lang="ts" setup>

const errors = ref([])
const result = ref([])

fetchFoo({result: result, errors: errors})

</script>
```

# Util

`utils/fetchFoo.ts`

```ts
export const fetchFoo = ({result: result, errors: errors}) => {
  let httpStatus = 0

  const fetchURL = new URL(`/path/to/api`)

  const fetched = fetch(fetchURL, {
    method: "GET",
    headers: {
      'Content-Type': 'application/json',
    },
  })
    .then((response) => {
      httpStatus = response.status
      return response.json()
    })
    .then((response_json) => {
      if (httpStatus == 200) {
        result.value = response_json["result"]
      } else if (response_json['errors']) {
        errors.value = response_json['errors']
      } else {
        errors.value = ["データ取得でエラーが発生しました"]
      }
    })
    .catch((_error) => errors.value = ["接続でエラーが発生しました"]);
}
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
YoutubeのHTMLが酷すぎて泣いたが、結局自分が悪かった日

## タイトル及び表現修正について
記事内にスクレイピングという言葉を使っていてコメントよりyoutubeの規約に違反してるという趣旨、及び私が違和感を持った所も「そもそもcustom elementだから問題ない」という指摘もいただきました。

スクレイピングに関しては実際にやった作業に修正、また記事内にcustom elementsを記載していながらそれに気づいていない自分の愚かさを鑑みてタイトルも修正いたしました。
以下を読まれる方は上記を踏まえて一読下さい。



## idって重複していいの？
タイトルにネタバレを持ってきましたが、まぁその通りです。  

だってソース見たら

```html
<div id="content" class="style-scope ytd-app">
//略
<div id="content" class="style-scope ytd-comments-entry-point-header-renderer">
//略
<div id="content" class="style-scope ytd-expander">
//略
<div id="content" class="style-scope ytd-ads-engagement-panel-content-renderer">
```

って記述にと

```html
<div id="content" class="style-scope ytd-engagement-panel-section-list-renderer">
```

が複数あるんですよ…

SPAであってもHTML5でもHTMLの[idって複数持っちゃダメ](http://www.html5.jp/tag/attributes/id.html)なはずですよね。


## Chromeでdebugツールで見てる時に困った

なんで泣いた(嘘)か？ってChromeのdebugツールでdomを見ている時で、ctrl+fを使った時でした。(当初スクレイピングというワードを使っていましたが規約で禁止されているのと実際の作業と乖離があったため表現を修正します。)
検索ワードに「div#content」ってやって**予想以上の数が返ってきて**「あれ？」って感覚に陥ったのです。  

ちょっと面白くなってローカルにhtmlをDLしてRubyのnokogiriのxpathでやってみたり色々やって遊んだりしたんですが、「何が怖いか？」ってhtmlをパースするライブラリによっては**配列じゃなく最初や最後のだけが返ってくる可能性も捨てきれません。**  
(人的ミスでidが重複する可能性がある以上可能性はかなり低いと思います。)

## レイアウトには問題ない
前述したように、html4の時代から今までも人が作成したサイトでidが重複していることもあれば、ライブラリによって意図せずidが複数になることもあったでしょう。  
何よりブラウザが
ちゃんと?
解釈してくれているので問題ないんでしょう。

ただYoutubeって天下の検索エンジンのGoogle傘下のサービスなのになぁ…（最初から開発したわけじゃなく買い取ったわけですし、昨今はchat GPTが〜みたいな話もありますけど）という感情があったので「おい！」となったの事実です。

もちろん検索エンジンのサービスを作っている会社のwebサービスのHTMLタグ厳格でなければならいということもないと思います。

## 細かいことはどうでもいい(んだろうな)
まぁ、**世の中のwebサイトを閲覧している人の90%以上はマークアップなんて気にしてないわけでidが重複しようがどうでもいい話**ですし、ブラウザが解釈して意図した通りにレンダリング&動作してくれれば目的は達成できていると言えると思います。  

ブラウザの性能が上がり、virtual DOMやCustom elementsが普通に使えるようになっている2023年においてHTMLをLintにかけて「idが重複していますよー」というのにどれくらい意味があるのか？と言われると私も「まぁ、そこまで厳密にしなくてもいいんだろうなぁ」まして「正しくないから表示させないよ」ってのはナンセンスだしユーザーの不利益になる場合もあると思います。

電子書籍で使われているEpubとかの需要度を見るともしかしたら…（こちらは流石になさそうですけど。）

## まとめ
実装中に「え？」となった感情だけで記事を書きましたがHTMLの歴史を見ると割と柔軟に変わってると思うので、近い将来idの重複をOKとする仕様になるのかもなぁと思っています。  

そうなると「classとの線引きどうなるの？」とか「labelは流石に重複しちゃダメじゃない？」というのはあると思いますが、そうなったらそうなったで対応するしかないんで頑張ってアップデートしていかなければと思った次第でした。
ChatGPT使ってみた（技術記事と著作権について）

みなさま、お久しぶりです。Sacomyです。
最近、記事を書いていないなとかと思いながら、Twitterをぼーっと見ていたら、ChatGPTというツールが話題になっていたので触ってみました。
また、制御に関する記事をぼちぼち書いていこうと考えているので、気になる著作権についてChatGPTを用いて調べてみました。

## ChatGPTの使い方を簡単に
- [ChatGPT | OpenAI](https://chat.openai.com/auth/login) より新規登録
    - メールアドレスの入力、または、Google/Microsoftアカウントでのログインが要求される
    - ログインの後は氏名の入力、電話番号の認証が必要
- 登録完了したら、メッセージを送ってみましょう
![ 2023-03-03 21.10.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288714/c91613d2-77bf-6c1e-9b26-2fa3297ff547.png)

簡単ですね。
ChatGPTの使い方も簡単に解説してくれました。

## 技術記事と著作権
ChatGPTに聞いてみました。
これ以降の画像はChatGPTより生成された文章を利用しています。
信頼性については担保されていないので、盲信することのないようご注意ください。

![ 2023-03-03 21.15.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288714/7b6c4039-f355-c796-defd-d5cd83f2d8f6.png)
![ 2023-03-03 21.15.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288714/c18b5f01-2e7d-49fb-2ea6-8761b2c57a20.png)
![ 2023-03-03 21.15.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288714/84877043-d975-df69-fd62-fca88d47c847.png)
![ 2023-03-03 21.15.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288714/dd1b0d43-5f30-f6ee-d461-e485fb793949.png)
![ 2023-03-03 21.16.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288714/b4bde0ee-3801-c00e-c3a2-3fa9e42c3ea9.png)

## おわりに
思ったより簡単に利用できて、帰ってくる文章もぱっと見問題なさそうでした。
是非皆さんも利用してみてください。
【Python】PySimpleGUI 備忘録

## タスクトレイにアイコンを設置

pystray を使用することで実現可能

* install
  ```
  pip install pystray
  ```
* 参考：https://blog2.k05.biz/2021/09/python-pystray.html
* `sg.Window` と併用するときはマルチスレッドにする必要あり
* 英語だと System tray
* Windows で「隠れているインジケータを表示します」としか表示されないので、このワードにたどり着くまでに苦労した

### ■ 結論

* タスクトレイにだけ出現するアプリケーションにしたかったが、そういう使い方じゃない
* バックグラウンドで走っているアプリを配置しておくところで、実際に使用するときはタスクバーにアイコンが出る（LINE や Discord などもそう）
* 今回は常時画面を表示させたかったのでタスクトレイには置かない

## タスクバーにアイコンを表示しない

* `sg.Window` の引数に `no_titlebar=True, grab_anywhere=True` を指定することで可能
* しかしこれをするとウィンドウ上部の掴む場所がなくなるのでよくない

## タスクバーにもアイコンを反映

`sg.Windows` の引数に `icon=icon.ico` を含めないといけない

## EXE 化

Nuitka を使用する

* install
  ```
  pip install nuitka
  ```
* EXE 化
  ```
  nuitka app.py --standalone --onefile --enable-plugin=tk-inter --disable-console --windows-icon-from-ico=icon.ico
  ```
* **軽量化**（追記）
仮想環境内に使用していないライブラリが含まれていると、それも使えるようにする前提で nuitka が EXE 化してしまうので、不要なライブラリをアンインストールしてから実行するとファイルが軽くなる
tweepy で 画像付きツイート

# tweepy がインスコされていることが条件

pythonでツイートしたい

```hoge.py

import tweepy

client = tweepy.Client(
    consumer_key=API_KEY,
    consumer_secret=API_KEY_SECRET,
    access_token=ACCESS_TOKEN,
    access_token_secret=ACCESS_TOKEN_SECRET
)

auth = tweepy.OAuthHandler(API_KEY, API_KEY_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)

tweet_txt = "あいうえお"
tw_img_pass = "screen_shots/hoge.png"

media = api.media_upload(tw_img_pass)
api.update_status(status=tweet_txt, media_ids=[media.media_id])


```

こんな感じ。
APIV2だと無理みたいなので、V1を使って投稿しようね
Go: gorm で PostgreSQL のデータを削除 (Delete)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_postgres.go
└── gorm_pg_delete.go
```

```go:gorm_pg_delete.go
// ----------------------------------------------------------------
//
//	gorm_pg_delete.go
//
//					Mar/03/2023
//
// ----------------------------------------------------------------
package main

import (
	"fmt"
	"os"
	"gorm.io/gorm"
	"gorm.io/driver/postgres"
)


/*
type City struct {
	Id           string
	Name         string
	Population   int
	Date_mod     string
}

	cities := []City{}
*/


// ----------------------------------------------------------------
func main() {
	fmt.Fprintln (os.Stderr,"*** 開始 ***")
	key_in := os.Args[1]

	fmt.Printf ("key_in = %s\n" , key_in)

	host,user,password,data_base := config_postgres_proc()

dsn := "host=" + host + " user=" + user + " password=" + password + " dbname=" + data_base + " port=5432 sslmode=disable TimeZone=Asia/Tokyo"

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
		}


	db.Exec ("delete from cities WHERE id = ?", key_in)

	fmt.Fprintln (os.Stderr,"*** 終了 ***")
}

// ----------------------------------------------------------------
```

.env
config_postgres.go
はこちら
[Go: gorm で PostgreSQL のバージョンを表示](https://qiita.com/ekzemplaro/items/c34800f0086a24b3947b)

## 実行の準備

```bash
go mod init delete
go mod tidy
```

>go.mod go.sum が作成される。

## 実行結果

```text
$ go run gorm_pg_delete.go config_postgres.go t3463
*** 開始 ***
key_in = t3463
*** 終了 ***
```
AWS SysOps Administrator 試験に不合格した話

## この記事について
先日 AWS の SOA 資格試験を受けて見事に落ちました。
この記事では私の試験対策とその効果、不合格の原因分析を記録したいと思います。

### 前提
受験時、私は AWS に関して CLF と SAA と DVA の資格を所持していました。
また、AWS 環境はある程度自由に動かすことができ、受験勉強の時間も十分に確保できました。

### 対策

下記について、合計 1 か月弱くらいを対策期間に充てました。

- 選択問題対策
こちらのテキストを使用しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730345/02dcac39-6c13-c682-bdc8-968fe617f045.png)

https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9ASysOps%E3%82%A2%E3%83%89%E3%83%9F%E3%83%8B%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/481560908X

普段は Udemy の模擬試験を利用しているのですが、SOA は現在非対応だったので紙のテキストを使うことにしました。教科書形式になっていて、巻末に 65 問の模擬試験が 1 回分あります。また、後述するラボ試験の例題も 3 問掲載されています。こちらのテキストを軽くさらいつつ、模擬試験で不足知識を補う算段で対策しました。

- ラボ試験対策
SOA では C02 版から、コンソール操作で環境を構築するラボ試験が追加されました。こちらは受験登録すると公式のデモ環境が使えるため、そちらを試しました。
課題となる環境は VPC や CloudWatch など、ハンズオンなどで作成する初歩的なものでほとんどカバーできているため、ツボにはまらなければ大丈夫だろうという感じでした。

### 当日の所感

実際に当日試験を受けたときの感想です。
受験はオンラインで行い、いつも通り寝室に雀卓を展開しました。
ティッシュを手元に置けず、少しだけ花粉症が気になりました。

- 選択問題
テキストの問題より少し広範囲で難しく感じました。2 択を絞り込む決定打が全体的に不足していたように感じます。55 問を解くのに 100 分くらい使いました。ラボ試験に余裕を持たせたかったので、見直しはほとんどしませんでした。

- ラボ試験
問題自体は簡単だったのですが、とにかくブラウザが重かったです。クリック、文字入力、コピペなど、あらゆる操作に毎回 3~5 秒のラグが発生していました。おまけに試験用ブラウザの設計が少し特殊でした。仮想環境にリモート接続して AWS のマネコンを操作するものだったのですが、VM を表示する画面の縦スクロールが問題文を挟んでブラウザ右端に潜んでいたため、ラボ試験開始後 30 分ほどは VM 上のブラウザでタブ操作ができない状態でした。ラボ試験の 2 問目に移ってようやくスクロールできる場所に気づきましたが、これだけで 20 分くらいロスしたと思います（ブラウザを拡大するだけで 3 秒ラグが発生するため）。「S3 バケット作成する →　先に IAM ロール設定したい」みたいなケースでタブを行き来することは多いと思うのですが、それができずにパニックした形です。
結局試験を終えたのは終了 2 分前で、環境の見直しをする時間はまったくありませんでした。

### 反省

結果的に合格ライン 72% に届かない 68% で不合格となりました。選択問題にして 3 問分ほどですね。原因を分析していきます。

- テキスト変えたら油断しない
今回の一番の敗因がここにあると思います。 Udemy の模擬試験を利用していた際には毎回 300 問ほどを周回できたため、十分な範囲で知識の穴を埋められていたと思います。しかし今回は 65 問しか触れられなかったため、模擬試験で習得度を把握する対策設計が甘かったと言わざるを得ません。Udemy 早く帰ってきてくれ。

- 予想外の重さにイライラしない
ラボ試験で操作がうまくいかなかった点について、タブ操作を諦められずにブラウザをガチャガチャ動かしたり、台パンしそうになって試験監督から注意されたり、本当に無駄な時間だったと思います。その時間を見直しに割けていればもう少し点が上がったかもしれません。問題は見直しでクリックするだけで毎操作ラグることですが、次回はもうわかっているので慌てません。

### まとめ

- 周回は数で攻める
- Udemy は神
- 台パンはしちゃだめ
- ティッシュも NG
Go: gorm で PostgreSQL のデータを更新 (Update)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_postgres.go
└── gorm_pg_update.go
```

```go:gorm_pg_update.go
// ----------------------------------------------------------------
//
//	gorm_pg_update.go
//
//					Mar/03/2023
//
// ----------------------------------------------------------------
package main

import (
	"fmt"
	"os"
	"strconv"
	"time"
	"gorm.io/gorm"
	"gorm.io/driver/postgres"
)

// ----------------------------------------------------------------
func main() {
	fmt.Fprintln (os.Stderr,"*** 開始 ***")
	key_in := os.Args[1]
	population_in,_ := strconv.Atoi (os.Args[2])

	fmt.Printf ("key_in = %s\t" , key_in)
	fmt.Printf ("population_in = %d\n" , population_in)

	host,user,password,data_base := config_postgres_proc()

dsn := "host=" + host + " user=" + user + " password=" + password + " dbname=" + data_base + " port=5432 sslmode=disable TimeZone=Asia/Tokyo"

	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
		}

	today := get_current_date_proc ()

	fmt.Println (today)

	db.Exec("UPDATE cities SET population = ?,date_mod = ? WHERE id = ?", population_in,today,key_in)

	fmt.Fprintln (os.Stderr,"*** 終了 ***")
}

// ----------------------------------------------------------------
func get_current_date_proc () string {
	now := time.Now ()
	fmt.Printf ("%s\t" ,now)
	fmt.Printf ("%d-%d-%d\n" ,now.Year (),now.Month(),now.Day())
	today := strconv.Itoa (now.Year()) + "-" +
		fmt.Sprintf ("%d",now.Month()) + "-" +
		strconv.Itoa (now.Day())

	return	today
}

// ----------------------------------------------------------------
```

.env
config_postgres.go
はこちら
[Go: gorm で PostgreSQL のバージョンを表示](https://qiita.com/ekzemplaro/items/c34800f0086a24b3947b)

## 実行の準備

```bash
go mod init update
go mod tidy
```

>go.mod go.sum が作成される。

## 実行結果

```text
$ go run gorm_pg_update.go config_postgres.go t3466 48532100
*** 開始 ***
key_in = t3466	population_in = 48532100
2023-03-03 17:38:09.509613607 +0900 JST m=+0.005400168	2023-3-3
2023-3-3
*** 終了 ***
```
プログラミングにおける識別子の命名規則について学んで見る

## はじめに
コードを書いていくうえで見やすいコードを意識していくのはエンジニアとして必須のこと。
よりわかりやすいコードを書いていくために必要とされる識別子の命名規則について少しまとめてみる。

## キャメルケース
キャメルケースとは、複数の単語を組み合わせた識別子を表す際に、先頭の単語を小文字、それ以降の単語の最初の文字を大文字にして表記する命名規則のこと。
例えば、「firstName」「lastName」のように表記する。クラス名、メソッド名、変数名などに使用される。

```Controller.php
// クラス名
class MyClass {
  // プロパティ名
  private $firstName;

  // メソッド名
  public function getLastName() {
    // 変数名
    $lastName = 'Smith';
    return $lastName;
  }
}
```

## スネークケース
スネークケースとは、複数の単語を組み合わせた識別子を表す際に、アンダースコアを使って単語を区切って表記する命名規則。
例えば、「first_name」「last_name」のように表記する。主に変数名、関数名、定数名などに使用される。

```Controller.php
// 変数名
$first_name = 'John';
// 定数名
define('LAST_NAME', 'Doe');
// 関数名
function get_full_name($first_name, $last_name) {
  return $first_name . ' ' . $last_name;
}
```

## ケバブケース
ケバブケースとは、複数の単語を組み合わせた識別子を表す際に、ハイフンを使って単語を区切って表記する命名規則。
例えば、「first-name」「last-name」のように表記する。主にHTML、CSSなどのWeb開発の分野で使用される。

```Controller.php
// HTMLのclass属性
<div class="container-fluid">
  <h1 class="text-center">Hello World</h1>
</div>

// CSSのセレクター名
.container-fluid {
  background-color: #ffffff;
}

// JavaScriptの変数名
let first-name = 'John';

```

## まとめ
これらの命名規則は、可読性や保守性を高めるために重要な役割を果たす。
また、プログラミング言語や開発環境、規約によっては、異なる命名規則が推奨されることがある。
よって、プロジェクトの規約に従って適切な命名規則を選択することが重要とのこと。

以上
Go: gorm で PostgreSQL のデータを読む (Read)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_postgres.go
└── gorm_pg_read.go
```

```go:gorm_pg_read.go
// ----------------------------------------------------------------
//
//	gorm_pg_read.go
//
//					Mar/03/2023
//
// ----------------------------------------------------------------
package main

import (
	"fmt"
	"os"
	"gorm.io/gorm"
	"gorm.io/driver/postgres"
)

type City struct {
	Id           string
	Name         string
	Population   int
	Date_mod     string
}

// ----------------------------------------------------------------
func main() {
	fmt.Fprintln (os.Stderr,"*** 開始 ***")

	host,user,password,data_base := config_postgres_proc()

dsn := "host=" + host + " user=" + user + " password=" + password + " dbname=" + data_base + " port=5432 sslmode=disable TimeZone=Asia/Tokyo"

// dsn := "host=localhost user=scott password=tiger123 dbname=city port=5432 sslmode=disable TimeZone=Asia/Tokyo"


db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
		}

	cities := []City{}

	db.Find(&cities)

	llx := len(cities)
	fmt.Println(llx)

	for it := 0; it < llx; it++{
		unit_aa := cities[it]
		fmt.Printf("%s\t",unit_aa.Id)
		fmt.Printf("%s\t",unit_aa.Name)
		fmt.Printf("%d\t",unit_aa.Population)
		fmt.Printf("%s\n",unit_aa.Date_mod)
	}


	fmt.Fprintln (os.Stderr,"*** 終了 ***")
}

// ----------------------------------------------------------------
```

.env
config_postgres.go
はこちら
[Go: gorm で PostgreSQL のバージョンを表示](https://qiita.com/ekzemplaro/items/c34800f0086a24b3947b)

## 実行の準備

```bash
go mod init read 
go mod tidy
```
>go.mod go.sum が作成される。


## 実行結果

```text
$ go run gorm_pg_read.go config_postgres.go
*** 開始 ***
9
t3466	竹原	74582	1921-01-10T00:00:00Z
t3467	三次	48297	1921-10-19T00:00:00Z
t3469	府中	25978	1921-05-14T00:00:00Z
t3461	広島	37452	1921-11-11T00:00:00Z
t3462	福山	89271	1921-08-25T00:00:00Z
t3465	尾道	41749	1921-06-24T00:00:00Z
t3463	東広島	63597	1921-04-14T00:00:00Z
t3464	呉	95178	1921-02-20T00:00:00Z
t3468	大竹	38591	1921-12-28T00:00:00Z
*** 終了 ***
```

## 確認したバージョン

```text
$ go version
go version go1.22.2 linux/amd64
```
いちいちシェルコマンド思い出せないので、ChatGPTで自然言語からスクリプトを生成するツールつくった




# はじめに
ChatGPT APIが出たので早速さわってみました。せっかくなので何か便利なものをということで自分向けに使えそうなツールをつくっていたら
良いかんじに動作したのでご紹介します。

つくったものは、「ChatGPTを用いた自然言語によるシェルコマンドランチャー」です。百聞は一見にしかずと言うことでまずは動作するところをみてください。
![japanese-usage.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/4b7bdeb2-71cf-316f-bc83-cff1dc0196a2.gif)

https://github.com/hirokidaichi/wanna


## 概要
`wanna`コマンドは、ChatGPTを用いた自然言語によるシェルコマンドランチャーです。自然言語によって、`bash script`を生成し、名付けし、管理できます。

コマンドライン上での操作は簡単に多くのことを行うことができるため、非常に便利です。しかし、多くのコマンドやオプションの組み合わせを覚えておくのは熟練したプログラマでもむずかしく、Google検索や`man`コマンドなどを駆使して思い出しながら実行することも多くあるでしょう。

たとえば、**「このディレクトリの配下にあるすべての.pyファイルを再帰的に発見して、それらの行数の合計を出力する」** といったタスクを行おうとするとき、`find`や`xargs`、 `wc`などのコマンドをどのように組み合わせたら良いのかを一発で思い出すのは中々難しいです。

### wanna think 

このようなときに`wanna think`コマンドを使います。

```bash
$ wanna think このディレクトリの配下にあるすべての.pyファイルを再帰的に発見して、それらの行数の合計を出力する
```
と打てば、AIアシスタントが自動的に次のようなbash scriptを生成します。

```bash
#!/usr/bin/env bash
find . -name "*.py" | xargs wc -l | awk '{total += $1} END{print total}'
```
あなたはただ、それをみて、実行するかしないかを決めれば良いだけです。
```
? What's next? (Use arrow keys)
 » Do
   Save
   Another Question
   Exit
```
あなたの依頼に対して、AIはスクリプトを生成し、その解説をします。
`Do`を選べば、提案されたスクリプトを実際に実行してその結果を表示します。
実行後に問題なく動作することを確認したら、保存をすることができます。
```
? I thought of the following names. Which one do you like? (Use arrow keys)
 » count_py_lines
   py_line_counter
   recursive_py_counter
   py_line_sum
```
そういえば、「コンピュータサイエンスで最も難しいことは"命名"である」とフィルカールトンも言っていました。
このAIは、生成したスクリプトに丁度良い名前も提案してくれます。あなたは、コードレビューアとして良さそうな名前を選ぶだけです。

### wanna do
`wanna do`コマンドを使えば、過去に保存したコマンドを実行することができます。
ただ単に`wanna do`と入力すればインクリメンタルに保存済のコマンドを選び、実行できます。
```zsh
$ wanna do
```
![wanna-do.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/53d1fc32-7345-8184-c3bf-0d79301f4881.gif)


```
$ wanna do random_passwords
```
のようにコマンド名を直接打って実行することもできます。

## wanna list 
記録済のスクリプトをリストアップします。
```
$ wanna list 
count_py_lines      :このディレクトリの配下にあるすべての.pyファイルを再帰的に発見して、それらの行数の合計を出力する
top_memory_usage    :メモリ使用量の多いプロセスを上位10個出力する
random_passwords    :ランダムに10個のパスワードを生成する
```

これを用いると、たとえば、こんなことができます。
```
$ wanna list | peco | xargs wanna do
```
![wanna-list-peco.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/ca0f12db-ca23-a432-b6c7-e2fd1f93dde2.gif)

## インストール
インストールは、pipを用いて簡単にできます。python3.10以上の環境で動作します。
```bash
pip install wanna
```
また、OEPNAI_API_KEYを使うため、ご自身のアカウントでtokenを取得してください。
```bash
export OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

# 雑感
さわってみて思ったのは、`text-davinci-003`よりも素直でプロンプトがストレートに記述できるのと、コードの中に`think_xxxx`のような関数を定義しているときに、思考可能な何かをプログラムに組み込んでいる実感がわいてわくわくしました。

あわせてこちらもご一読ください。

https://newspicks.com/topics/dx/posts/43?ref=TOPIC_POST_MANAGEMENT_VIEW

https://newspicks.com/topics/dx/posts/42?ref=TOPIC_POST_MANAGEMENT_VIEW

# 本記事に関するイベントについて

登壇します。是非ご参加ください！

https://rector.connpass.com/event/278495/
Go: gorm で PostgreSQL のデータを作成 (Create)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_postgres.go
└─── gorm_pg_create.go
```

```go:gorm_pg_create.go
// ----------------------------------------------------------------
//
//	gorm_pg_create.go
//
//					Mar/03/2023
//
// ----------------------------------------------------------------
package main

import (
	"fmt"
	"os"
	"gorm.io/gorm"
	"gorm.io/driver/postgres"
)

// ----------------------------------------------------------------
func unit_gen_proc (name string,population int,date_mod string) map[string]interface{} {
	unit_aa := make (map[string]interface{})
	unit_aa["name"] = name
	unit_aa["population"] = population
	unit_aa["date_mod"] = date_mod

	return (unit_aa)
}

// ----------------------------------------------------------------
func data_prepare_proc () map[string](map[string]interface{}) {
	dict_aa := make (map[string](map[string]interface{}))

	dict_aa["t3461"] = unit_gen_proc ("広島",37452,"1921-11-11")
	dict_aa["t3462"] = unit_gen_proc ("福山",89271,"1921-8-25")
	dict_aa["t3463"] = unit_gen_proc ("東広島",63597,"1921-4-14")
	dict_aa["t3464"] = unit_gen_proc ("呉",95178,"1921-2-20")
	dict_aa["t3465"] = unit_gen_proc ("尾道",41749,"1921-6-24")
	dict_aa["t3466"] = unit_gen_proc ("竹原",74582,"1921-1-10")
	dict_aa["t3467"] = unit_gen_proc ("三次",48297,"1921-10-19")
	dict_aa["t3468"] = unit_gen_proc ("大竹",38591,"1921-12-28")
	dict_aa["t3469"] = unit_gen_proc ("府中",25978,"1921-5-14")

	return (dict_aa)
}

// ----------------------------------------------------------------
func main() {
	fmt.Fprintln (os.Stderr,"*** 開始 ***")

	dict_aa := data_prepare_proc ()

	host,user,password,data_base := config_postgres_proc()

dsn := "host=" + host + " user=" + user + " password=" + password + " dbname=" + data_base + " port=5432 sslmode=disable TimeZone=Asia/Tokyo"

	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
		}

	db.Exec ("drop table cities")

	sql_str := "create table cities (id varchar(10),name varchar(20),population int,date_mod date)"
	fmt.Println (sql_str)

	db.Exec (sql_str)

	for key,_ := range dict_aa {
		name := dict_aa[key]["name"]
		population := dict_aa[key]["population"]
		date_mod := dict_aa[key]["date_mod"]
		sql_str :="insert into cities (id,name,population,date_mod) values (?,?,?,?)"
		db.Exec (sql_str,key,name,population,date_mod)
		}

	fmt.Fprintln (os.Stderr,"*** 終了 ***")
}

// ----------------------------------------------------------------
```
.env
config_postgres.go
はこちら
[Go: gorm で PostgreSQL のバージョンを表示](https://qiita.com/ekzemplaro/items/c34800f0086a24b3947b)

## 実行の準備

```bash
go mod init create
go mod tidy
```

>go.mod go.sum が作成される。


## 実行結果

```text
$ go run gorm_pg_create.go config_postgres.go
*** 開始 ***
create table cities (id varchar(10),name varchar(20),population int,date_mod date)
*** 終了 ***
```

## 確認したバージョン
$ go version
go version go1.22.2 linux/amd64
```
Fargateのresolv.confを設定する

## 課題
ECS on Fargateで起動するタスクにおいて名前解決先を複数設定したい要件があり、どのように設定すればよいか調査した。


## 結論
- FargateにおいてもDHCPオプションセットでresolv.confを変更することができる。
- Fargateを起動するVPCにリゾルバを指定したDHCPオプションセットを作成することで、タスクに反映することが出来る。
- 起動中のタスクには反映されず、タスクに再起動が必要（かも）


## 検証

### 準備と確認
まずは起動中のタスクにログインし、resolv.confの中身を確認してみる。
なおタスクにログインするためには事前に設定が必要なので注意
- https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/ecs-exec.html
- https://dev.classmethod.jp/articles/ecs-exec-for-fish-shell/

タスクにログインするためにはAWS CLIコマンドで下記を実行する。
```
aws ecs execute-command --region ap-northeast-1 --cluster <クラスタ名> --interactive --comand "/bin/sh" --task <タスクID>
```
タスクIDはECSのコンソール画面から起動しているタスクを確認し取得した。

まず初期状態を確認すると、VPCのresolver IPを指していた（10.0.0.2）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659784/217d13e5-ab52-ac4b-21ef-4664b4acf3c5.png)

### DHCPオプションセット
DHCPオプションセットとは、VPC内のEC2インスタンスのDNS/NTPサーバの設定ができる。
DHCPオプションセットの詳細についてはこちらを参照のこと。
- https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/DHCPOptionSetConcepts.html

下記のDHCPオプションセットを作成し、該当のVPCへ関連付けを実施した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659784/f87ff790-3e4e-8d8b-70b5-1d175fa15a32.png)

想定ではresolv.confが下記のようになっていればOK
```
nameserver 10.0.0.2
nameserver 8.8.8.8
nameserver 1.1.1.1
```

### 反映確認
タスクの再作成を実行し、再度確認する。
想定通りDHCPオプションセットの内容が反映されていることが分かる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659784/dfc03e37-4324-2faa-bfc7-590ddcf0eef5.png)

なおsearchがなくなってしまっているが、これはDHCPオプションセットのドメインに設定すれば記載される。

## まとめ
- AWS公式ドキュメントに詳細な記載は見つけられなかったが、EC2インスタンスに限らずFargateもDHCPオプションセットの影響を受ける模様。
- 一時的には手動でresolv.confを変更すればよいが、タスクの入れ替わりが前提のECSにおいては永続的な方法であるDHCPオプションセットが良いと思う。
関数の理解を育ててみる。

# 目的
・関数を理解して使えるようにする。
・関数を理解するまでの頭の中を整理する。
・理解が進んだら更新する。

# 正方形の面積を関数にしてみるの巻
[正方形の面積を求める公式](https://rikeinvest.com/arithmetic/s-seihoukei/)
・1辺 × 1辺　(今回はこっちを使う)
・対角線 × 対角線 ÷ 2

```C
#include <stdio.h>

int square(int x)     //squareは正方形の意味
{
	int sq = x * x;   //sqはsquareのsq
	return(sq);
}

int	main(void)
{
	int r;
	
	printf("正方形の長さを入力してください:");
	scanf("%d",&r);
	
	int y = square(r);
	printf("一辺%dcmの正方形の面積は%dcmです。\n", r,y);
	
	return (0);
}
```
<b>実行結果</b>
正方形の長さを入力してください:3
一辺3cmの正方形の面積は9cmです。

# 長方形の面積を関数にしてみるの巻
[正方形の面積を求める公式](https://medemanabu.net/sansu/area-rectangle/)
たて × よこ
```C
#include <stdio.h>

int rectangle(int x,int y) //rectangleは長方形の意味
// 長方形の公式が たて × よこ の2種類の値を掛け算するから
// 引数も2種類用意する必要がある。
 {
    //int re = x * y;      //reはrectangleのre
 	return(x * y);         //returnにx * yを入れても関数機能する。
 }

int	main(void)
{
	int r;
	int e;
	// int y; 
    // printfの直前でint y = rectangle(r,e);してるからint y;って書かなくてもいい

	printf("長方形の縦と横の長さを空白区切りで入力してください:");
	scanf("%d%d",&r,&e);

	int y = rectangle(r,e);
	printf("縦%dcm、横%dcmの長方形の面積は%dcmです。\n", r,e,y);

	return (0);
}
```
<b>実行結果</b>
長方形の縦と横の長さを空白区切りで入力してください:3 3
縦3cm、横3cmの長方形の面積は9cmです。

# 大事かもって思ったところ
・main関数のvoidは戻り値なしという意味
・関数はmain関数の下に書いてはいけない。しかし、プロトタイプ宣言をすればmain関数の下に書いても良い。
理由は、main関数の下に関数を書くとエディターはmain関数から最初に処理されるので
関数をmain関数の下に書くと再定義されてしまうから。


# 関数の機能を日常で例えてみる。
<b>例1</b>
髪の毛を洗う時、シャンプー、リンス、コンディショナーをそれぞれ使うけど
時間がかかってめんどくさいからシャンプー、リンス、コンディショナーのそれぞれの機能が入った
オールインワンという関数を使えば時短になる。

<b>例2</b>
外出した時にメイク直しをしたいからリップ、チーク、アイシャドーをそれぞれ持ち歩くと
メイクポーチに入らないからリップの形状をしたリップにもチークにもアイシャドーにもなるリップ関数を使えばポーチに入る。
# 参考にした動画
https://www.youtube.com/watch?v=VPQGnV_z-hM&t=11s

https://www.youtube.com/watch?v=AIptyrEk0Nc
Node-REDを使ってWhisperで音声認識してChatGPTで回答させてみた

OpenAIからAPIが公開されたChatGPTと音声認識のWhisperを使ってノーコードで会話ができないかNode-REDで作ってみました。


https://twitter.com/yskmjp/status/1631539501704286208


## 事前準備

### 環境

使っている環境は以下の通りです
- enebular / Node-RED v2.2.2
- ChatGPT API gpt-3.5-turbo
- Whisper API whisper-1
- Windows 10 / Microsoft Edge

### ノードの追加
Node-REDを手軽に使えるプラットフォームとして[enebular](https://www.enebular.com/ja/)を使っています。デフォルトのノード以外に2つのノードを追加しています。メニューの「パレットの管理」から追加してください。
- node-red-node-ui-microphone　マイクを使うためのノード
- node-red-contrib-simple-chatgpt　ChatGPT APIを利用するためのノード

### OpenAI の API KEY の準備
OpenAI 管理画面の API Keysからキーを発行しておいてください。
ChatGPT API と Whisper API の利用に必要です。課金対象のAPIですので使いすぎにも注意してください。

## Node-REDでノードを作成
以下のフローで実行しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149785/3091ff92-dc02-9518-dd9e-2f6c8445bcfd.png)

各ノードについて説明します。

### 「マイク」ノード
node-red-node-ui-microphone のノードです。デフォルトのまま使っています。wav形式でmsg.payloadにBufferオブジェクトとして出力されます。

### 「音声リクエスト作成」ノード
functionノードでWhisper API へのリクエストを作成しています。OpenAIのAPI仕様は[こちら](https://platform.openai.com/docs/api-reference/audio/create)です。

HTTPヘッダには以下を指定しています。[API-KEY]にはOpenAIの管理画面で発行したKEYを入れてください。
- Authorization: Bearer [API-KEY]
- Content-Type: multipart/form-data

HTTPボディには以下を指定しています。ボディはmultipartになっています。
- model: whisper-1　使うモデルを指定します。現状は他のモデルは無いようです
- language: ja　日本語を指定しています。
- file:　msg.payloadから入ってくる音声データが入ります。Content-Typeはwavを使っているので形式を指定しています。filenameは適当に指定しています。

```
const sound = msg.payload;
msg.payload = {
    'model': {
        'value': 'whisper-1'
    },

    'language':{
        'value': 'ja'
    },

    'file': {
        'value': sound,
        'options':{
            'filename':'test.wav',
            'Content-Type': 'audio/wav',
        }
    }
};

msg.headers = {
    'Authorization': 'Bearer [API-KEY]',
    'Content-Type': 'multipart/form-data'
};
return msg;
```

### 「STT結果取得」ノード
Whisper APIからの結果がmsg.payload.textに入るので、後続で扱えるようにchangeノードを使って msg.payload にデータを入れ替えています。

### 「ChatGPTに質問」ノード
node-red-contrib-simple-chatgpt のノードです。テキストをインプットするとChatGPTへの問い合わせをしてくれるとても便利なノードです。OpenAIのAPI KEYをノードのTokenに設定してください。
SystemSettingを設定すると語尾などの話し方を指定したり、pastMessagesを設定することで継続的な会話をすることもできます。

### 「質問を表示」「回答を表示」ノード
ダッシュボード用のtextノードです。マイクから音声認識した質問内容、ChatGPTからの回答内容をそれぞれ表示します。

### 「回答を音声で出力」ノード
ダッシュボード用のaudio outノードです。テキストを入力すると音声合成して読み上げてくれます。

### 「リセット」ノード
ダッシュボード用のbuttonノードです。ボタンを押すと空白が送信されて「質問を表示」「回答を表示」の表示をクリアします。

### ダッシュボード
ダッシュボードはこのような画面になり、マイクからの音声が「質問」として表示され、ChatGPTからの応答が「回答」として表示されると同時に読み上げられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149785/9bcdb155-330c-bb0c-ffd5-b94de02c3997.png)

## 終わりに
ChatGPT/WhisperのAPI公開から、すでに様々な使い方がされていますが、Node-REDでノーコードでもとても簡単に使うことができました。高度なAIを使ってお手軽に面白いサービスを作っていきましょう！（課金にはくれぐれもご注意を）
ログイン不要　すぐ使える ChatGPT を実装してみました


ログイン不要　すぐ使える ChatGPT を実装してみました。
公式より反応は速い気がします。

https://softbase.jp/addon/chatgpt


最新のModel 「gpt-3.5-turbo」を使っています、APIの料金も大分安くなってきましたので、大変助かります。


![S__34316304.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125746/f23e573d-97a6-2674-5e96-b4f3a45fc834.jpeg)
【Swift, iOS15.x 以上】タップされた時にハイライトするカスタムUIButtonクラス

## 経緯
`button.setBackgroundImage(image, forState: .Highlighted)`
(image には、UIColorをUIImageに変換したやつが入る)
で、ボタンタップしたときにハイライトしなかった。

あー、そういえば、iOS15からUIButton変わったんだった！
って思って備忘録のために記事を書くことにした。

## コード
```swift
class CustomButton: UIButton {
  override var isHighlighted: Bool {
    didSet {
      var config = self.configuration
      //ハイライトさせたい色を指定する。とりあえずグレー
      let highlightColor = UIColor.gray.image()
      config?.background.image = isHighlighted ? highlightColor : nil
      self.configuration = config
    }
  }
}

extension UIColor {
  /// UIColorをUIImageに変換する
  func image(_ size:CGSize = CGSize(width: 1, height: 1)) -> UIImage {
    UIGraphicsBeginImageContext(CGSize(width:1, height:1))
    let ctx = UIGraphicsGetCurrentContext()
    self.setFill()
    ctx!.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image!
  }
}
```

Storyboard上で配置したUIButtonのカスタムクラスに上記で作成したクラスを指定すれば
タップしたときにハイライトするUIButtonの完成 :smiley: 

## 参考にした記事
https://qiita.com/akatsuki174/items/c0b8b5126b6c12f62001
Notion 📝 Mac アプリ新しいウィンドウで開く方法

タブを、右クリックして、
`Move Tab to New Window` を押す。

![Screenshot 2023-03-03 at 16.16.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/544789d8-c1c6-0f54-2bc5-44bb0633fe2b.png)


もしくは、
`command + shift + N`

🦄
[next.js] next.config.jsでのリダイレクト。クエリパラメーター付きの注意点

# 概要
next.jsでリダイレクトを行ういくつかある方法で、next.config.jsを使用した方法について記載します。

# 基本
基本的なリダイレクト方法は公式を参照ください。
`.htaccess` だと `$1` などを使用していたと思いますが、その辺りが `:slug` など書き方が違っていたりします。

https://nextjs.org/docs/api-reference/next.config.js/redirects

# クエリパラメータ付きのリダイレクト先への注意点
現在（2023.03.03時点）で、リダイレクト元のクエリパラメーター付きURLをリダイレクトの際に、パラメータを外してリダイレクトすることは`next.config.js`での設定では難しいようです。

```: 例
/old?qu=abc を /new へリダイレクトしたい
https://exsample.com/old?qu=abc
↓
https://exsample.com/new
```

上記を行いた場合下記のような設定になりますが、結果は `https://exsample.com/new?qu=abc` となってしまいます。
```: next.config.js
{
  source: '/old',
    has: [
      {
        type: 'query',
        key: 'qu',
        value: 'abc',
      },
    ],
  destination: '/new',
  permanent: false,
},
```

公式にも
```
When /old-blog/post-1?hello=world is requested, the client will be redirected to /blog/post-1?hello=world.
```
と記載があります。

下記のissueでReadmeが更新されただけのようですね。
https://github.com/vercel/next.js/issues/27194

### 対応方法は？

ページ側で強制的に外す感じでしょうか？（ちょっと適当です）
再リダイレクトするか、router.pushでasPathでパラメーターをなくすとか？かなと思います。

それならクエリ文字列を含むリダイレクトについては`next.config.js`ではなくはなからページ側で行うなどでも良いかもしれないですね。

# 参考にさせていただいたサイト
https://zenn.dev/uttk/articles/4649e49f1e6628
【Django + AWS ECS + Fargate】Djangoで形態素解析アプリを作成してみた（概要・アーキテクチャ図・参考文献）


# はじめに（記事の概要）

個人的な勉強もかねて、Django WebフレームワークとAWS ECS + Fargateを用いたWebアプリケーションを作成しましたので、その際に使用したアーキテクチャ図と参考文献を記載します。

Webアプリの概要としては、GooglePlayストアで配信されているアプリに投稿されたレビューを収集し、簡易的なスコア推移・レビューの形態素解析が行える、オンラインBIアプリケーションとなります。取得したレビューはCSV形式でダウンロードでき、生成した図表については、レポートとして保存した後、PDF形式でダウンロードすることができます。

大まかなプログラムについては、以前投稿した記事を元に作成しております。

https://qiita.com/hastings/items/41243ee723fe56568f60

今のところ、GooglePlayストアで配信されているアプリのレビューのみ取得が行えます。今後、AppStoreで配信されているアプリのレビューの取得も行えるように改修できればと考えております。
また、Webアプリ開発に関する詳細については、機会があれば記事にしたいと思います。


# サイトURL・Github

### サイトURL
https://ez-app-reviewer.com/

<font color="red">※このツールはまだ開発版です。登録したアカウントや保存したレポートは削除されることがございます。また、お気づきの点がありましたら、フィードバックをお送りいただければ幸いです。</font>

### Github
https://github.com/hastings-net/ez-app-reviewer


# アーキテクチャ図

![20220524_AWS-LAMP-WP-ページ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1201852/8fc73170-4c5d-559e-5272-bd4953dab840.png)


# 参考文献

### Django

- 大橋 亮太『Djangoのツボとコツがゼッタイにわかる本』（‎秀和システム、2020年）

- 大高 隆『動かして学ぶ! Python Django開発入門』（翔泳社 、2019年）

- Deploy a Serverless Django web app with AWS Fargate - 2023 - Udemy
https://www.udemy.com/course/deploy-a-serverless-django-web-app-with-aws-fargate-2022/

- Django 3 Course - Python Web Framework (+ pandas, matplotlib, & more) - YouTube
https://www.youtube.com/watch?v=04L0BbAcCpQ

### AWS・コンテナ仮想化・CircleCI

- 新井 雅也、馬勝 淳史『AWSコンテナ設計・構築[本格]入門』（SBクリエイティブ、2021年）

- 中垣 健志『AWSではじめるインフラ構築入門 安全で堅牢な本番環境のつくり方』（翔泳社、2021年）

- 浦井 誠人、大竹 智也、金 洋国『CircleCI実践入門──CI/CDがもたらす開発速度と品質の両立 (WEB+DB PRESS plus)』（技術評論社、2020年）

- AWS ECR/ECS へのデプロイ - CircleCI
https://circleci.com/docs/ja/ecs-ecr/

- ECS上のコンテナアプリをCircleCIでCI/CDする - Qiita
https://qiita.com/saki-engineering/items/d35ea75e95ffa77e307a

- CircleCI + GitHub + Amazon Elastic Container Registry (Amazon ECR) + Amazon Elastic Container Service (Amazon ECS) (+ AWS Fargate) で継続的デリバリー環境を構成する
https://www.seeds-std.co.jp/blog/creators/2019-09-11-201930/
baserCMS5をcomposerからセットアップする方法

# baserCMS5をcomposerからセットアップする方法

ついにbaserCMSのバージョン5がリリースされるのでcomposerを使ったセットアップ方法を記載します。

https://basercms.net/ver5/

baserCMS5のソースコードは今まで通り
- github
- 公式サイト

から取得できるのですが、バージョン5からはcomposerからも取得することができるようになりました。
composer版を使用すると以下のようなメリットを享受できます。

1. コマンドラインから簡単にCMSコアをアップデートできる
2. CMSのオートアップデート機能を使って管理画面からCMSのバージョンアップができる
3. cakephpのプラグインフォルダがスッキリする

composerを使って導入してみたので、導入方法を記載します。

## 実行環境

- macOS13
- docker on mac
- apache2
- php8.1
- MySQL5.7

## composerのインストール

homebrewからインストールするかパッケージ版を導入しておくと楽です。

### homebrew

https://brew.sh/index_ja

### composer

https://getcomposer.org/

## セットアップ手順

### 1.cake4のプロジェクトを作る

```
$ composer create-project --prefer-dist cakephp/app:"4.*" basercms_project_dir_name
```

### 2.basercmsを導入する

```
$ cd basercms_project_dir_name
$ composer require baserproject/baser-core
```

### 3.cakeのプラグインにbaserを追加

```
$ bin/cake plugin load BaserCore
```

### 4.filesフォルダ作ってphpからの書き込み権限を与える
```
$ mkdir webroot/files ; chmod 777 webroot/files
```

### 5.ブラウザからセットアップを実行する
```
https://your-host-name/install
```

こちらのURLにアクセスするとbaserCMSのインストール画面が表示されますので、db設定情報や管理者アカウントの登録を行なってセットアップを完了させてください。