OmniAICreator/Qiita-1.07M huggingface dataset:
TSKaigi2024の運営スタッフをしたら最高だった件

少し振り返りついでに書いてみようと思います。

## 参加した理由
参加した理由は、TypeScriptが好き！！！
ただその気持ちだけで、運営スタッフに参加しました。
自分自身、初めての運営参加だったので右も左も分からない状態でした。

## 参加したチーム
ノベルティTに所属しました！
https://tskaigi.hatenablog.com/

私たちの本稼働は今年の2024年になってからでした。

ノベルティ選定は
どのような物なら喜ばれるのだろうかと考えながら楽しくやらせてもらいました。
（当日、登壇者の皆様がTシャツ着てくださっていてめちゃくちゃ嬉しかったです）

業者選びも調査から始まり、中々大変でした。
とても業者に詳しくなったと思っています。w

## ちょっと事件が...！

どんな事にもトラブルは付きものですね。

チームメンバーや、
コアチームの方々に助けてもらい、無事にスケジュールが落ち着きました。
お陰で当日を迎えることが出来ました。

## 開催直前
4月後半くらいからは仕事後にチームMTGを頻繁に行って
22時頃までMTGしていたりました。
ちょっと大変でしたが、チームメンバーが皆いい人だったから苦じゃなかったです♪

（自分はいつも周りの人に本当に恵まれてるな...と改めて感じました。）

## TSKaigi前日
前日準備も参加しました！
スピーカーディナーのスタッフとして参加してきました。
TSの神様、Danielさんや登壇者さんとお話し出来てとても刺激を受けました！

Danielさん、登壇者の皆さんは目がキラキラしていました！

## TSKaigi当日
内容については、皆さんが素晴らしい記事を書いて下さっているので割愛します。
スポンサーの皆様、セミナー登壇してくださった皆様、
今回に携わって下さった皆様、本当にありがとうございました。

### 参加者
オフライン:380名
オンライン:2020名

合計2400名の方々がTSKaigiに来てくださいました。
初回開催にも関わらず、お陰様で大盛況でした。

そして「TSkaigi」がXの日本のトレンド4位にもなっていました！
（スタッフ業務の合間で見たので誤差があるかもしれません）

TypeScriptがどれだけ注目されているか、改めて知れました。
そしてもっとTypeScriptが好きになった日でした。

## ちょっと反省点
準備など、前もって出来たことはあったと思うので
もう少し早く気付けば稼働出来たな...と思う所はあります。
こちらは今回の反省点だと感じています。

英語が出来なすぎてDanielさんと何も話せなかったこと。
熱い思いだけは！と思って
「I Love TypeScript♡」
「I Like You♡」
だけ伝えられました！w

そして来年は、司会者もやってみたい！

## 最後に
「TypeScriptが好き」っていう一つの共通点から
大きなカンファレンスを一緒に作り、
そんな仲間ができたこと、カンファレンス終了後は感極まりました！

そして尊敬する方々が増えまくりました。
皆さんに負けないよう明日からも頑張りたいと思います！！

来年のTSKaigi2025もスタッフで参加予定です( ¯꒳¯ )ﾆﾔﾘ
更に大規模になる予定なので、TSKaigi2025のスタッフも募集しています！
またお会いしましょう！！！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【<a href="https://twitter.com/hashtag/TSKaigi?src=hash&amp;ref_src=twsrc%5Etfw">#TSKaigi</a> 2024終了しました】<br>無事すべてのコンテンツが終了いたしました！<br>様々な形で多くの方にご参加いただきました！<br>ありがとうございました！！ <a href="https://t.co/Ui6TFX2vJz">pic.twitter.com/Ui6TFX2vJz</a></p>&mdash; TSKaigi (@tskaigi) <a href="https://twitter.com/tskaigi/status/1789250460031094894?ref_src=twsrc%5Etfw">May 11, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
密っこくん

# 目次
[1. 概要](#1-概要)
[2. 背景](#2-背景)
[3. 技術スタック](#3-技術スタック)
[4. アプリの詳細](#4-アプリの詳細)
[5. GitHubリポジトリ](#5-githubリポジトリ)
[6. まとめ](#6-まとめ)
# はじめに
　このアプリは**Golang**と**Websocket**による**双方向通信**を学びたいというモチベーションのもと、唐突な思いつきで作成したアプリです。(現在もまだ修正中。最終的には一時的にでもデプロイしたい。)
**やさしい目**で見てもらえると嬉しいです。
　とりあえずアプリの発信のために本記事を書いてます。
 **(※使用する場合はリポジトリの注意書きを参照して下さい。)**

　また双方向通信やGolangについてはまた別でまとめられればと思ってます。
(現状あまりやる気が...)
# 1. 概要
　みなさん、こんな経験ないですか？

### 学校で、授業中寝てる友達に先生が気づくように、音を立てて先生の注目を引いたりして、どうにか友達をチクりたい！

みたいな経験ありませんか？(周りにはないと言われてしまった...)
そんなふざけ合いや、チクリ合いをアプリという形で行えるものになります！
# 2. 背景
　初めはただただ**GolangとWebsocketを触ってみたい**というモチベーションからはじまりました。
　僕は何か新しい言語やライブラリ、技術を触る際は**実際にやってみる**。**とりあえず何か作ってみる**というのが性に合っているので今回もとりあえず何か作ってみるか精神でした。
 　ただチャットアプリなどはあり触れてたので**もう少し違うもの**が作りたいとなり今回のアプリを作成しました。
# 3. 技術スタック
大まかなスタックは以下の通りです。(詳細はリポジトリを見てみて下さい。)
- ### Frontend
    - TypeScript
    - Next.js
    - React
    - Recoil
    - Websocket client
    - daisyUI!

- ### Backend
    - Golang
    - gin
    - gorilla/websocket
    - Swaggo
# 4. アプリの詳細
- ### 前提
    本アプリは**まだローカルでしか使用できません。**(これからデプロイやその他諸々やっていくつもりです。)
    また、本アプリは**座席番号が振られた席などについていることを想定**しています。

　まずは以下のホーム画面で**自身の座席番号を入力してログイン**します。
![home.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2925753/acc9f396-fc9f-1b5e-c8b2-cbe451f08111.png)

　ログイン後は以下の画面に遷移します。
基本的にアプリからのメッセージや通知はサイドにあるヒストリーにて表示されます。
![スクリーンショット 2024-05-14 23.10.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2925753/1c3f6b75-b63b-f920-d07a-0a65eccd596b.png)

　その後は同様にログインしている**他の席の人の席番号を指定して密告ボタンを押すことで密告**対象とされたユーザーの画面に**モーダルが表示**されます。
この密告し、**対象ユーザーにモーダルを出す部分や密告する部分にてWebsocket通信**を用いています。
![send-alert.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2925753/0e8d6e83-f7f6-5108-2056-3f34a09665fa.png)

タイムオーバーになった場合は、以下の画像のように接続されている密告対象以外のユーザーへ寝ていることがブロードキャストされてしまいます。😱
(通知はサイドにあるヒストリーにて表示されるが、**いずれはタイマーオンを鳴らす**などを検討したい)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2925753/dd8fc741-c983-c42a-3c93-3a45da88cffd.png" width=300 alt="密告後のブロードキャストログの画像"/>



# 5. GitHubリポジトリ
よかったらリポジトリも覗いてみて下さい。
(あまり参考にはなりません...)
- <a href="https://github.com/Inoue416/mikkokun-frontend">Frontend</a>
- <a href="https://github.com/Inoue416/mikkokun-backend">Backend</a>
# 6. まとめ
今回はGolang、Websocket通信を触りたいから始まり、よくわからんアプリを作るまでのお話でした。
まだまだバグや未完成部分が多いことやコードが汚すぎるのでこれから直しつつ、できればデプロイまでしてみなさんに遊んでいただけるようにしたいです。
(できるように頑張れ、わい)

また、中身のGolang、Websocketについてはまた別でまとめたいと考えてます。
(気が向いた時にやるお)

ここまで読んでくださった方、長々とお付き合いありがとうございました。
(何かあればコメントください。)
ハッキング・ラボのBurpというトラップ

# 趣旨

ハッキング・ラボを読み進めているとバージョンの違いのせいでBurpが作動しない状況に陥ったので数時間直し方を調べてやっと直せたので備忘録を残します。

色々いじって最終的に動いたので、もしかしたらどこか抜け落ちてたりいらないことをやってるかもしれません。何か間違いがあればご指摘いただければ幸いです。

### 本カバー
![81KqiCeVm2L._SY522_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670541/bebccb07-0a5b-c5c5-01ab-d7e339658f83.jpeg)

### 著者イプシロン氏

https://twitter.com/ipusiron?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor

### 他のハッキング・ラボ関連Qiita記事

https://qiita.com/tags/%e3%83%8f%e3%83%83%e3%82%ad%e3%83%b3%e3%82%b0%e3%83%bb%e3%83%a9%e3%83%9c%e3%81%ae%e3%81%a4%e3%81%8f%e3%82%8a%e3%81%8b%e3%81%9f


# 公式サイトからBurpを改めてダウンロード
BurpSuiteの最新バージョンは、公式サイトからダウンロードできます。ダウンロードページのリンクは以下です：

https://portswigger.net/burp/releases/professional-community-2022-1?requestededition=community

:::note info 
公式DLページはGoogleで検索して以下の記事を読んだことで見つけました。
https://forum.portswigger.net/thread/burpsuite-not-running-eaa56c63b2a51e

:::

Javaも互換性のあるバージョンを導入する必要があります。
必要なJavaのバージョンは以下のコマンドで入手、解凍、移動します。

```bash
wget https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-x64_bin.tar.gz
tar xvf openjdk-21.0.2_linux-x64_bin.tar.gz
sudo mv jdk-21.0.2/ /usr/lib/jvm/jdk-21
```

# BurpSuiteのインストールと設定手順

以下は、BurpSuiteをParrotOSにインストールし、Java 17以上で動作させるための手順を記録したものです。

## 手順 1: インストールスクリプトの実行
まず、ダウンロードしたBurpSuiteのインストールスクリプトに実行権限を付与し、その後スクリプトを実行します。

```
chmod +x ~/Downloads/burpsuite_community_linux_v2022_1.sh
~/Downloads/burpsuite_community_linux_v2022_1.sh
```

## 手順 2: BurpSuite起動スクリプトの作成
次に、BurpSuiteの起動スクリプトを /usr/bin/burpsuite に作成します。

```
sudo nano /usr/bin/burpsuite
```

以下の内容をファイルに追加します：
```
#!/bin/sh
JAVA_HOME=/usr/lib/jvm/jdk-21
exec $JAVA_HOME/bin/java \
    --add-opens=java.desktop/javax.swing=ALL-UNNAMED \
    --add-opens=java.base/java.lang=ALL-UNNAMED \
    -jar /home/daniel/BurpSuiteCommunity/burpsuite_community.jar "$@"
```
## 手順 3: スクリプトに実行権限を付与
作成したスクリプトに実行権限を付与します。

```
sudo chmod +x /usr/bin/burpsuite
```

## 手順 4: BurpSuiteの起動
設定が完了したら、ターミナルからBurpSuiteを起動します。

```
burpsuite
```
これで、BurpSuiteがJava 17以上で正常に動作するはずです。
Pythonでお祝儀計算プログラムを作る

# 背景

人間の人生で、きょうだいの結婚ほどめでたいことはない。
ということで、お祝儀を包む気満々なのだが、きょうだいの結婚は人生で初めてであるため、お祝儀の計算がわからない。

早速ググったところ…

https://m.niwaka.com/ksm/radio/wedding/gift-money/price/08/#:~:text=結婚式を挙げない場合でも、兄弟姉妹へ,決めると安心ですね%E3%80%82

>
>まとめ
>
>新郎新婦が兄弟姉妹でも、お祝いの気持ちとしてご祝儀は必要なんですね。
>金額の相場は、だいたい5万円。
>ただし、年齢や地域、新郎新婦との関係性や立場によっても変わります。
>年代が高い場合や、新郎新婦が弟・妹の場合は、相場より少し高めの金額を包むのが一般的。
>逆に若い場合、新郎新婦が兄・姉の場合は、相場より少なめでもOKとされています。
>包む側が未婚の場合は、相場通りの5万円が基本。
>既婚で夫婦連名の場合は、7万円から10万円程度が相場になります。
>子供が一緒なら、年齢に応じて子供の食事代もプラスしましょう。
>自分が学生だったり、親と同居の場合は、親と同一世帯ということで個人的にご祝儀を包む必要はありません。
>ただし、親族間で決められたルールがある場合は、それに従うようにしましょう。
>再婚の場合も同様で、相場通りにご祝儀を贈るのが一般的ですが、結婚式の有無や相手の希望によっても変わってきます。
>ご祝儀は当日に渡さず、結婚式の1ヶ月前から1週間前くらいまでに手渡しします。
>会えない場合は、手紙やメッセージカードを添えて、現金書留などで送ればOK。
>ご祝儀はお祝いの気持ちなので、たとえ結婚式をしない場合でも贈ります。
>その場合の金額も、親族間で相談して決めると安心ですよ。
>結婚祝いをギフトで贈る場合は、ご祝儀分とギフトの分の合計金額を相場にあわせましょう。
>この場合も結婚式の当日ではなく余裕を持った日取りで渡すのがマナー。
>
>そして、ギフト選びについては、夫婦で使えることと実用性が高いものであることがポイントでした。
>大切な兄弟姉妹の結婚、相場を参考に無理のない範囲で、お祝いの気持ちを贈りたいですね！
>

明確に相場があって有難い。しかしめちゃくちゃ条件があるので、これはPythonに計算させたいと考えた。

# 目的

適切なお祝儀の金額をPythonに算出させるためのプログラムを実装する

# 実装

基本的には上記のマナーを踏襲しつつ、最終的には「割り切れない」値を返させる。

```python
import sympy

def calculate_goshugi(age, relationship, marital_status, spouse_attending=False, has_children=False, is_student=False, living_with_parents=False):
    # 基本の相場
    base_amount = 50000
    
    # 年代や関係性による調整
    if relationship in ['弟', '妹']:
        base_amount += 10000  # 弟や妹の場合、相場より高め
    
    # 未婚の場合
    if marital_status == '未婚':
        amount = base_amount
    
    # 既婚の場合
    elif marital_status == '既婚':
        if spouse_attending:
            amount = 70000  # 夫婦連名の場合、7万円から10万円が相場
        else:
            amount = base_amount
    
    # 子供がいる場合、食事代をプラス
    if has_children:
        amount += 5000  # 仮に子供一人あたり5000円を追加
    
    # 学生や親と同居の場合
    if is_student or living_with_parents:
        amount = 0  # 親と同一世帯の場合、個人でご祝儀を包む必要なし
    
    return amount

def next_prime(n):
    # sympyのnextprime関数を使用して、nより大きい次の素数を返す
    return sympy.nextprime(n)

# ご祝儀の金額を計算
goshugi_amount = calculate_goshugi(age, relationship, marital_status, spouse_attending, has_children, is_student, living_with_parents)

# ご祝儀の金額より大きい素数を計算
final_goshugi_amount = next_prime(goshugi_amount)

# 結果を出力
print(f"適切なご祝儀の金額は {final_goshugi_amount} 円です。")
```


# 実行

下記の条件で試してみる。

```python
	•	age: 25
	•	relationship: 弟
	•	marital_status: 既婚
	•	spouse_attending: false
	•	has_children: false
	•	is_student: false
	•	living_with_parents: false
```

このプログラムを実行すると、指定された条件に基づいて適切なご祝儀の金額が素数として算出されます。今回の条件では、60,013円が適切なご祝儀の金額として出力されました。

# まとめ

マナーは大変だけれども、ちゃんと頑張りたい。
LaravelのCollectionのuniqueメソッドの挙動で気になったのでコードを追ってみた

## ある日の出来事

「複数件のデータが取得できるはずなのに一件分しか取得できてない！」とバグがあがりました。

調べてみると取得クエリのwhereInの引数に渡す際、laravelのpluckで`$collection`から必要な要素を取り出した後にuniqueで重複削除処理をしている部分があるのですがそれによって
想定だと複数の要素が入ってくる予定なのに要素が一つだけになっていました。

### 
```php
 // 想定だと [1,2,3,4]と複数が入ってくるはずなのに 
 //　　　結果は、[1]が返ってきた
 $targetIds = $collection->pluck('target_id')->unique('target_id') 
 
 Target::whereIn('target_id',$targetIds)->get();
```

## 結論
```php
->pluck('target_id')の部分で [1,2,3,4]のようなデータ構造になっていて
```
その後にuniqueメソッドの引数で存在してないkeyを渡していたことが原因でした

単なるミスなのですが
でもなぜ1つだけは返ってくるのかが気になったのでlaravelのコードを追ってみました

## 解説

lararvelのuniqueメソッドの定義
```PHP
    /**
     * Return only unique items from the collection array.
     *
     * @param  string|callable|null  $key
     * @param  bool  $strict
     * @return static
     */
    public function unique($key = null, $strict = false)
    {
        if (is_null($key) && $strict === false) {
            return new static(array_unique($this->items, SORT_REGULAR));
        }

        $callback = $this->valueRetriever($key);

        $exists = [];

        return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
            if (in_array($id = $callback($item, $key), $exists, $strict)) {
                return true;
            }

            $exists[] = $id;
        });
    }
    
```
rejectの定義
```php
    /**
     * Create a collection of all elements that do not pass a given truth test.
     *
     * @param  callable|mixed  $callback
     * @return static
     */
    public function reject($callback = true)
    {
        $useAsCallable = $this->useAsCallable($callback);

        return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
            return $useAsCallable
                ? ! $callback($value, $key)
                : $value != $callback;
        });
    }
```

valueRetrieverの定義
```php
    /**
     * Get a value retrieving callback.
     *
     * @param  callable|string|null  $value
     * @return callable
     */
    protected function valueRetriever($value)
    {
        if ($this->useAsCallable($value)) {
            return $value;
        }

        return function ($item) use ($value) {
            return data_get($item, $value);
        };
    }
```

collect([1,2,3])->unique('a')のように実行すると以下のコードで
unique関数での戻り値の部分は実質このようになります


```php
$exists = []
return $this->filter(function ($value, $key) use(&$exists) {
            if(in_array($id = data_get($value, 'a'), $exists, $strict)) {
                return false
            }

            $exists[] = $id;
            return true
       })

```

一番最初
1が評価されます、その時`$id`にnullが入ります。
そして`$exists`に1がpushされます
そしてreturn true

2番目
２が評価されます、その時`$id`にnullが入ります。
`$exists`にはnullが既に入っているのでifの条件式がtrueになります
そして return falseされます

その次以降
2番目と同じ全てfalseを返します

よって一番最初の要素のみが入ったコレクションが返却されるということになる


## 補足
unique関数での戻り値の部分の実質のコードへの変換する際に
以下の前提を考慮する必要がある

- PHPは戻り値を明示的に書かない場合は暗黙的にnullが返ってくる
- PHPは定義している関数の想定より引数が少ない状態で実行した場合はエラーになるが、引数を余計に渡している場合は無視してエラーは出ない
[SwiftUI]UIKitプロジェクトへの導入事例まとめ

UIKitからSwiftUIへの書き換えを行なっている方をまとめています！:0
参考にしたい部分を書き出してます！

# 導入事例
## Navitime

https://note.com/navitime_tech/n/na83e29a43719

一つずつ認識のすり合わせをして、みんなが自信を持って書けたら嬉しい。
話し合い大事！
* アプリのベース部分、共通機構のレビュー
* モブプロでの開発
* 複数パターンの開発

https://note.com/navitime_tech/n/n10bbef4416e6

* 再描画を抑制する
→ bodyの中身を意識。別のStructで定義するなどの工夫。
→ ObservableObjectの参照のみで、バインディングしない場合、@ObservableObjectを付けずに、普通のプロパティとして定義する(再評価の対象から外す)
* UIKitとSwiftUIの混在は極力避ける
→ 混在させた場合で、データの共有が必要な場合、ObservableObjectを使用して共有を行うと良い
→ @StateObjectでObservableObjectクラスのインスタンス化をして、親から子に渡す際は@ObservedObjectを使用して共有

## ZOZOTOWN

https://techblog.zozo.com/entry/zozotown-ios-adopt-swiftui

* SwiftUIを小さく導入する
→ UIViewとして書くであろう部分をSwiftUIのViewで実装する(UIViewの中でもまた小さく区切る必要はある)
* SwiftUIで実装する際は、UIKitの実装へと戻る可能性も考えたリソース配分・スケジューリングを行う
* UICollectionViewCell, UITableViewCellでSwiftUIを使わない

## Retty

https://engineer.retty.me/entry/2021/12/08/212051

* ほとんどがUIViewController + UIHostingControllerの構成
* 画面の一部からSwiftUIを適用していく形
* 画面遷移は基本的にUIViewController系統のものを使用して、NavigationLinkは使ってない
* 店舗詳細ページなどは、少しずつ施策開発や機能修正をする中でSwiftUIへの置き換えを進めている
* UITableViewはそのままでUITableViewCellにUIHostingControllerを持たせて、セルのコンテンツはSwiftUIのViewを表示する手法(不具合が発生するとの記載がある)

## MIXI

https://team-blog.mitene.us/introduce-swiftui-7bcc5cd50b7a

* View+ロジック(アーキテクチャ)まで含めてSwiftUIに合わせて変更
* 画面遷移はUIKit
* UIがStateを監視して際レンダリングを行うアーキテクチャ
* MVVM + Clean Architectureへの変更(これ使ってる人多い)
Mockを作成する手間が省ける。
Previewの高速化。
![スクリーンショット 2024-05-14 13.35.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1640998/3ca97416-87e4-1606-17ea-a5925a169bc4.png)

## ニフティ

https://tech.niftylifestyle.co.jp/entry/706

* ViewControllerを使用してUIHostingControllerを介したSwiftUIを置く
* データ参照はObservableObject
* SwiftUIからViewControllerへのイベント受け渡しはdelegate

## クックパッド

https://techlife.cookpad.com/entry/2021/01/18/kaimono-swift-ui

* VIPERベースのLayered Architecture
* View層のみでSwiftUIを使う
* 画面単位で完全に切り分けられているため、SwiftUIに困難が生じたらすぐにそこだけでもUIKitに戻せるリスク対策
* 画面(VIPERシーン)ごとに従来通りUIViewControllerがあり、そこに橋渡し役のUIHostingControllerを介して、SwiftUIで書かれたVIewが置かれる
![スクリーンショット 2024-05-14 14.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1640998/dc66aa3a-cb0f-3aea-82b5-3c8ecdb61411.png)
* 遅延読み込み(LazyVStack, LazyHStack)の使用

# まとめ
記事にしていただけるのは本当に感謝です！‥🙇
既存プロジェクトへ導入する際は再描画処理や、UIKitとの共存、アーキテクチャの選定など気をつけていきたいと思います！
Azure Functionsでdate-fnsのformat結果がローカル実行とAzure上で実行したときに差が出ていたメモ

## 概要
[前回でローカル実行環境を構築した](https://qiita.com/hibohiboo/items/ddcc6125bf61d9b308cc)が、日付をDBから取得してフォーマットしたところで問題が起きた。

環境|TimeZone|`format(d,'yyyy-MM-dd HH:mm:ss')`
--|--|--
Azure|UTC|2024-05-14 **00**:00:00
ローカル|JST|2024-05-14 **09**:00:00

結論からいうと、TimeZoneのlocaleの問題であった。
ローカル実行時の環境変数`TZ`に`UTC`を設定することでローカルもAzure上と同じ挙動にできることを確認した。



[date-fns format](https://date-fns.org/v3.6.0/docs/format)より
> Return the formatted date string in the given format. The result may vary by locale.
> 指定された形式で書式設定された日付文字列を返します。結果はロケールによって異なる場合があります。

[Node.js TZ](https://nodejs.org/api/cli.html#tz) より
> The TZ environment variable is used to specify the timezone configuration.
> TZ 環境変数は、タイムゾーン構成を指定するために使用されます。

## 設定

[ローカル設定ファイル](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-develop-local#local-settings-file)に環境変数を追加する

```diff:local.settings.json 
{
  "IsEncrypted": false,
  "Values": {
+   "TZ": "UTC",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "AzureWebJobsStorage": "<connection-string>",
    "MyBindingConnection": "<binding-connection-string>",
    "AzureWebJobs.HttpExample.Disabled": "true"
  },
  "Host": {
    "LocalHttpPort": 7071,
    "CORS": "*",
    "CORSCredentials": false
  },
  "ConnectionStrings": {
    "SQLConnectionString": "<sqlclient-connection-string>"
  }
}
```

## 試したがダメだったもの

ローカル実行時の[環境変数にWEBSITE_TIME_ZONEを設定](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-app-settings#website_time_zone)しても、date-fnsのformatの挙動は変わらなかった。

## 参考


[Jestによるテスト実行時のタイムゾーンを固定する](https://qiita.com/Tsuyoshi84/items/e3d79d9842280549723c)
[vscode-jest](https://github.com/jest-community/vscode-jest/issues/153#issuecomment-543814787)
[React] Custom Hookを理解する！

### Custom Hook とは？

`Custom Hook`は、再利用可能なフック処理を関数として抽出し、独立させる機能。

噛み砕くと、状態や副作用をコンポーネントとは別のファイルに定義して、コンポーネントでそれらをインポートします。

#### 命名規則

Custom Hookの命名は「`use`」で始めるのが慣例です。
例：`useFetch.ts`, `useLocalStorage.ts`

`bulletproof-react`では、hooksディレクトリにファイルを配置します。

https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md

#### サンプルコード
タイマーの状態、副作用をカスタムフックとして、コンポーネントから分離します。

`hooks/useTimer.ts`
```typescript
import { useEffect, useRef, useState } from 'react';

export const useCountUp = (): [number, () => void, () => void] => {
  const [time, setTime] = useState(0);
  const intervalIdRef = useRef<NodeJS.Timeout | null>(null);
  
  const setTimer = () => {
    if (intervalIdRef.current !== null) {
      clearInterval(intervalIdRef.current);
    }

    intervalIdRef.current = setInterval(() => {
      setTime((time) => time + 1);
    }, 1000);
  };

  const reset = () => {
    setTime(0);
    setTimer();
  };

  useEffect(() => {
    setTimer();

    return () => {
      if (intervalIdRef.current) {
        clearInterval(intervalIdRef.current);
      }
    };
  }, []);

  return [time, reset];
};
```

---

#### インポート 
カスタムフックを利用する場合は、コンポーネントで対象のフック処理をインポートして利用する。
```jsx
import React from 'react';
import useCounter from './hooks/useCounter';

function CounterComponent() {
  const [time, reset] = useCounter();

  return (
    <div>
      <p>Count: {time}</p>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

export default CounterComponent;
```

---

### Hooksを独立させる理由

Custom Hookは特定のコンポーネントに依存しないように設計すると、他のコンポーネントでも再利用が容易になります。

これにより、アプリケーション全体のコードの一貫性と保守性の向上につながります。

参考記事

https://ja.react.dev/learn/reusing-logic-with-custom-hooks
[エラー備忘録]Lambdaのロググループが見つからない

# はじめに
Amplifyで作成したLambdaのログをCloudWatchで見ようとしたときに、「Log group does not exist」というエラーに出くわしたので、備忘録として簡単に残しておきます。

# 原因、対処
以下の記事を確認してみると、Lambdaが一度も実行されず、ログが一度も出力されていない場合に、このようなエラーになるみたい。
ということで、Lambdaが呼び出される処理の流れを辿っていると、ソースコードでエラーになっている箇所があり、Lambdaを呼び出しているソースまでたどり着いていなかった。
ソースを修正して、Lambdaを呼び出せるようにしたら、CloudWatchにログが出力されており、エラーも消えました。

https://repost.aws/ja/knowledge-center/lambda-cloudwatch-log-streams-error

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

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

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

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
今更ながらXcodeで開発しているiOSアプリのデバッグをiPadで行った記録

# はじめに
自分でどうやったのか人に教えるのが面倒なので，立てた記録．
それぞれのデバイスのバージョンは以下の通り．
MacOS Sonoma 14.4.1
Xcode 15.3
iPadOS 16.7

最新情報にはなってないかもので，ご注意ください．


# Xcodeの準備
iOSやiPadOS, MacOS向けのモバイルアプリケーションをビルドするために必要なXcodeを準備する！

### Xcodeのインストール
App storeでXcodeと検索してインストール

![スクリーンショット 2024-05-13 20.39.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680423/10638561-9749-6c6f-6a8f-91df0c0e80f2.png)

### iOSのインストール
今回はiPadでのデバッグを行うので，iOSをインストールしてデバック可能にする．
（MacOSは標準でインストールされているので問題ない）
最初にXcodeを起動したときに設定できるが，そこで設定できなくても，Xcodeのメニューバーの
Xcode > Settings > Platform から設定できる．
![スクリーンショット 2024-05-13 20.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680423/2f6faad1-e476-59f9-ce98-033b39f5628b.png)


### Xcodeのアプリを準備（略）
各々アプリを作成する．
とりあえずデバッグを試したい場合は，デフォルトの状態で行う．

# iPad側の準備
デバック環境を準備する
### iPadのデベロッパーモードをオンにする
1. MacとiPadを優先で接続する．
1. iPadで「このMacを信頼しますか？」を表示されるので「信頼」を選択する．
（⭐ここまでは一度設定したことがある場合は省略可能）
1. 「設定」の「プライバシーとセキュリティー」から「デベロッパーモード」を選択しオンにする． 

### ビルド
メニューバーの「Product」の「destination」から「Manage Run Destinations」を選択し，左下の「＋」からiPadを選択．![スクリーンショット 2024-05-14 22.29.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680423/2e09393f-ab6a-da47-10d7-87f6c362f46a.png)

### Runを実行
メニューバーの「Product」から「Run」を実行するか，⌘command+Rを押して行う．

### 認証の設定
iPadからすると「このアプリ動かして大丈夫そうなん？」となっているので「大丈夫だよ」と言ってあげる必要がある．
設定アプリの「一般」→「VPNとデバイス管理」から設定する．

# 実行
ホーム画面に追加されているはずのアプリアイコンを選択してアプリケーションを起動する．

# 最後に
自分で作ったアプリが動くって楽しいですよね．
楽しく開発続くためのプロジェクト（Udemy driven development）

# 開発者としての悩み
- 技術力が上がらない
- 自分に合う勉強の方法を探し難しい
- プログラミングを始めて作った時の楽しさが最近低い
- 個人開発のパターンが毎回同じような気がする
の理由で最近悩みが増えました。

仕事で開発をすると一人で勉強する時より技術力がすぐ伸ばして個人開発や自分のアプリをローンチングできると思ったんですが、気づいたのはプログラミングの世界は深くて広いことです。

どんどん自信がなくなり、開発は特別にプログラミングを作る人達がやるものではないかなって思う時、チャッとGPTに聞いたら、当たり前の話ですが、毎日ちょっとでもコードを書いて勉強を続けるとエンジニアとして成長できるって言う答えが出ました。それで自分なりの実験をやろうと思います。

**やりたいことを自分がやりたい方法で続く**

今まで一番楽しんだ学び方法はUDEMYの動画を見ながら議論を勉強して、新しいものを学んで、サンプルコードを練習し、アイデアがあったら個人開発に続くことで、今日から毎日Udemy driven Developmentの方で開発勉強をやり直そうと思います。

## Udemy Driven Developmentとは？
1. 毎日１時間ほど勉強したい開発動画を見る
1. 学んだことをここで書く
1. 続く
1. コードを書きたい時は作りたいものを作る
1. 義務ではなく、楽しい心が出る勉強をやる

それで、
今学期で学校で学ぶこともあったので、今日から勉強するものはCプログラミングです！
C言語だと、難しいイメージがあって今まで避けた言語でしたが、急に興味が出てきて下の動画を購入しました。

[Beginning C++ Programming - From Beginner to Beyond](https://www.udemy.com/share/101WQM3@cQUgc_Hi9JI9qBTAZwo8jTqfOcPLqvb7CUS2NOqnlIjpUFksuo_3JYm_Ako--CdMfQ==/)

一応なんとなく自分がやりたい方法でいろんな勉強の仕方を試そうと思います。
【Java】Kotlin経験者が気になった違いまとめ

### クラスの生成方法の違い
- インスタンス化時には、クラス名の前に`new`が必要
### プリミティブ型
- BooleanやIntegerは、ラッパークラスであり、`null`が許容される
- booleanやintは、プリミティブ型であり、`null`はコンパイルエラーとなる
### 拡張メソッド、プロパティが定義できない
- Kotlinで定義した拡張メソッド、プロパティをJavaから呼び出すことは可能
    ``` JavaSample2.java
    public class JavaSample2 {
    }
    ```
    ``` JavaSample2Ext.kt
    // 拡張プロパティの定義
    @get:DrawableRes
    val JavaSample2.iconResourceId: Int get() {
        return R.drawable.ic_launcher_background
    }
    
    // 拡張メソッドの定義
    fun JavaSample2.sayHello(name: String) {
        // TODO:
    }
    ```
    ``` JavaSample.kt
    public class JavaSample {
        void say(String name) {
            JavaSample2 javaSample2 = new JavaSample2();
    
            // 拡張プロパティの呼び出し
            Integer resId = JavaSample2ExtKt.getIconResourceId(javaSample2);
    
            // 拡張メソッドの呼び出し
            JavaSample2ExtKt.sayHello(javaSample2, name);
        }
    }
    ```
    
### nullがコンパイル時にわからない
- @NotNullまたは、@NonNullを定義時に付けとくと、エディターで警告⚠️が出るようにはなる
### nullのアンラップが冗長になる
- `?:`や、`?.`が使用できない
### スコープ関数がない
- `let`, `also`などが使用できない
- 配列クラスの`.forEach`や`.filter`は使用できる
### デフォルト引数が定義できない
- 多く呼び出し箇所をもつメソッドに引数を追加したときに困る時がある
- 対処法
    - 新たにメソッドを定義し、古いメソッドからそれを呼び出す（この時デフォルト値を渡す）
    ```
    public class JavaSample2 {
        void methodOld() {
            methodNew("This is default value");
        }
    
        void methodNew(String name) {
            // 元の処理
        }
    }
    ```
### sealedクラスが、switch文(when文)のパターンマッチに使用できない
- Java8では不可能。Java17から利用できる。
- このため、enumクラスを定義するなどして対応する必要がある 
### 変数の定義方法
- `val`がない。`final`が似た扱い。
- 型を先に書く
- 型に`?`を付けてなくても、基本的に全て`nullable`になってしまう
### 関数の定義順序
- `fun`を書かない
- `戻り値の型` `関数名`の順
- 何も返さない場合でも、`void`が必要
### クロージャーを引数に渡す方法の違い
- 戻り値が`Void`の場合に詰まった。`return null`が必要
    ```SampleViewItem.kt
    class SampleViewItem(
        val onItemTapped: (Int) -> Unit,
    ) {
        val index = 1
    
        fun onTapped() {
            onItemTapped(1)
        }
    }
    ```
    ```JavaSample.java
    public class JavaSample {
        void setUp() {
            SampleViewItem sampleViewItem = new SampleViewItem((index) -> {
                handleTap(index);
                return null; //　これが必要
            });
        }
    
        void handleTap(Integer index) {
            // 処理
        }
    }
    ```
### コンストラクタの定義方法
- Javaでは`constructor()` ではなく、`クラス名()`で定義する
### companion objectがない
- Javaでは`static`修飾子を付けたものになる

### 知っとくと良いもの
- kotlin -> binary -> javaへのデコンパイル方法
ER図について②

https://qiita.com/takesiumemoto/items/42ba977332aeb4a277ee

前回の続きです。
備忘録のため、記事にします。

4.外部キーで置き換える
　以下は注文テーブルカラムになります。会員氏名というカラムがありますが、ある問題が起こる可能性があります。

![order_data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788856/1e2081e1-333c-451a-6ed1-347d9991e616.png)
会員氏名を name:stringというデータ型で保存しているため、同姓同名の人がいた場合に識別できなくなってしまいます。

ではどのようにすればよいでしょうか。

![uniqueness.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788856/b12c2db9-e038-100b-0719-63be3f598c03.png)

注文テーブルの会員氏名を会員idというカラムに変更することにより、同姓同名の場合でもidにより識別することができます。

注文id 1 の会員氏名は会員テーブルのid 14 の山田花子さん
注文id 2の会員氏名は会員テーブルのid 89 の山田花子さんになります。
外部キーで置き換えられる場合はほかのテーブルから関連付けをする必要があります。

５．マスタ項目を分割する
![product_genre_data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788856/5803b7e0-0f35-2147-7aa6-4dcf95dd3cd5.png)
上記のような商品テーブルが存在するとします。
例えば、リリース後に商品ジャンルを変更・追加する必要が発生しました。
一つ一つ変更するのはとても手間で、大変ですよね。
そこで、商品マスターテーブルを作成して、商品テーブルのジャンルカラムに外部キーとしてカラムを追加したいと思います。![create_genre_table_modified_column_name.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788856/b8f3181e-b79a-7122-9f6c-3bc648c55b9b.png)
商品ジャンルテーブルを新たに作成し、ジャンルidを関連付けました。ジャンルidを追加したことにより、変更や追加などがあった場合、商品ジャンルテーブルを更新すればいいので、修正が簡単になりましたね。

６．多重度を考える
ER図を作成する上で一番理解が難しかった部分になります。
データベースは上記のようにほかのテーブルと関連づける場合がありますが、関連付ける際に注意するポイントがあって、「片方のカラムから見て、相手のカラムはいくつあるか」という部分を注意する必要があります。具体的にデータベースを作成しながら確認していきます。

例１　１対多の場合
あるクラスのデータベースになります。
![スクリーンショット 2024-05-14 221235.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788856/25356c50-1678-b55f-c9ba-2c82cce134e5.png)

学生が所属するクラスは１つ
そのクラスには生徒が複数いる　このような関係を1対多の関係といいます。

例２　多対多の場合
次に部活動テーブルを用いて説明します。
学生は１つ以上の部活動に所属できることとします。
![many_to_many_relationship.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788856/62e95c4d-2851-ecf7-7709-c9f81492740c.png)
一つのカラムに繰り返しが発生してしまっていたり、同じカラムが増えてしまいます。ではどのように改善すればいいのでしょうか。![スクリーンショット 2024-05-14 222028.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788856/b4d71d4d-aa52-484c-dd0f-e7541b530b2f.png)
部活動中間テーブルというテーブルを作成することにより、1対多の関係が作れるようになりました。

Railsでは１対多の関係にすることにより、テーブル間でデータの受け渡しができるようになります。この１対多という関係は非常に大切だと思ったので、理解を深めたいと思います。

エンジニアの未経験転職を目指しています。間違いなどがあればご指摘いただきたいです。拙い文章でしたが、御覧いただきましてありがとうございました。
＜2: コメント＞Progate学習修了者がJavaScriptPrimerを読んだら

# はじめに
こんにちは。Satoです。
本稿では、Progate学習を修了した段階のプログラミング学習者が、JavaScriptPrimer（以下、Primerとします）を学習するとどうなるのかを記録したものです。基本的には自身のアウトプットを主眼に置いていますが、初学者が躓いた点とその解決方法も記載するつもりなので、良かったら参考にしてみてください。
# 学習事項
## コメントとは
プログラムとして評価されないので、ソースコードの説明を書くために利用されている。
```
// 一行コメント
// この部分はコードとして評価されない
```
## 複数行コメント
説明が長くなる場合は、下記のようにコメントすると良い。
```
/*
　複数行コメント
　囲まれている範囲はコードとして評価されない
*/
```
### [ES2015]HTML-likeコメント
後方互換性のためだけに存在する機能なので、書ける必要はない。
こういうのがあるんやなーと知っておくだけでOK。
```
<!-- この行はコメントと認識される
console.log("これがHTML-likeコメントやで");
-->  この行もコメントと認識される
```
# 躓いた点
特になし。
# 参考文献
azu・Suguru Inatomi「第一部: 基本文法　コメント」『JavaScript Primer』
https://jsprimer.net/basic/comments/
プライベートIPアドレスが設けられるようになった経緯

　現在プライベートIPアドレスには3つのクラスがあたえられている。
　　クラスA：10.0.0.0~10.255.255.255(サブネットマスク: 255.0.0.0)
　　クラスB：172.16.0.0~172.31.255.255(サブネットマスク: 255.240.0.0)
　　クラスC：192.168.0.0~192.168.255.255(サブネットマスク: 255.255.0.0)

本来、IPアドレスはインターネット機器にそれぞれ固有の値を設定する必要があり、昔は社内のLANをインターネットに接続する場合はアドレスを一元管理する機関に申請を出して、IPアドレスを取得していた。ただし、1990年代にインターネットが一般的に解放されると、接続台数が急速に拡大し、近い将来IPアドレスが枯渇する可能性が生じました。この問題を解決するために独立する社内のネットワークを固有に判断することで、2つの会社で同一のIPアドレスを使用することが可能になりました。そこで、社内で設定することができるIPアドレスをプライベートIPアドレス、従来の固有で存在するIPアドレスをグローバルIPアドレスと言います。つまり、プライベートIPアドレスは従来、グローバルIPアドレスで使用していたアドレスから、社内で使用可能なIPアドレスに範囲を決めた、約束ごとに過ぎません。ただし、このまま、社内機器をインターネットに接続するとプライベートIPアドレスが重複してしまいます。そこで社内からルーターを通過する際にIPアドレスとポート番号を変換するアドレス変換機能を使用します。プライベートIPアドレスはルーターのグローバルIPアドレスに、ポート番号は未使用の番号を適当に選択し、設定をしています。
【ポエム】GPT4o (omni) と人類の仕事について（クソデカ主語） | OpenAI Spring Update

GPT4oの発表を通して思ったことを書き連ねてるだけ

## 一言で
- 小規模化やアシスタント化が謳われるAI業界で、OpenAIは「**コミュ力**」で勝負してきた
- 人類から機械に仕事が奪われる理由は、「機械でいいじゃん」という消極的なものではなく、「機械にやってほしい」という積極的なものだと感じた

~~明日Googleの発表に感激したらその記事も書きます~~
予告動画を見る限り、音声と動画での会話について今発表ではOpenAIの完全勝利になりそうですね

https://twitter.com/Google/status/1790055114272612771?t=YQboX9G7g_d6TRraij8KAg&s=31

## OpenAIは「**コミュ力**」で勝負してきた

### 昨日までの世界

昨日までの生成AI、言語モデル界隈のトレンドは、
- phi3-miniをはじめとするローカル・モバイルで動くほどの「小規模化」
- GPTストアやDify、そのほか様々なサービスが目指す「アシスタント化」

だったはずだ。

近頃のOpenAI・ChatGPTは、
Geminiから始まり、
Claude、
オープンソースモデル（⌘R+, mixtral, llama3）、
そんなモデルたちにそろそろ追いつかれそうというところだった。

実際私も、ChatGPTへの課金はすでにやめ、
（APIだけは残していたがそこもClaudeをより気に入りつつあり）、
ローカルで無課金でモデルを動かすことを楽しんでいた。

しかし、

### OpenAIは１つ未来で戦っていた

だから追いつかれているように見えて、
蓋を開けてみたら想像もしない地点に到達していた。

chatgpt2 という匂わせはたしかにあったわけだが、
たしかに音声と動画でのライブモードは、
今までのChatGPTとはメジャーバージョンの違う「ChatGPT ver2.0」だった。

まだOpenAI Spring Updateのデモ映像を見てない人はすぐに見てほしい。
こちらの呼びかけにすぐ答え、
相手の口調を読み取り、自分の口調を変化させ、
カメラで見ながら人に物を教えるChatGPTを。

https://www.youtube.com/live/DQacCB9tDaw?si=yD77R-u1j8_Kb6Vb

OpenAIは、
- オーディオ、画像、動画を読み込める能力
- 桁違いの表現力を持つ音声で出力できる能力
- 会話のカットインをスムーズに行えるUI
- 明らかに速い応答

これらをひっさげてChatGPTにコミュ力を獲得させていた。
目で見て音で聞いて話せる「ChatGPT 2.0」は人類に近づいた。
（しかもモデルは速く安くなってる）

このコミュ力は、小規模化やらローカルやらアシスタントやらに目を取られていた私には全く持って想像できていないものだった。
しかし間違いなくChatGPTにはこれを求めていたという感じだ。
私はChatGPTを使う時、ツールやシステムとして使いたいというのはあくまで主目的ではなく、「Chat」したいわけだ。
それを叶える新しい形がこれだった。

ツールやシステムとしては他にもっといい選択肢がありうるのだから、
「ChatGPT」というサービスに求めることは会話であり、
そこに対する正統進化を提供してくれた。
こういうサービスの考え方は見習いたい。

それもただ「正統」なだけでなく、予想もしなかった妄想・魔法を実現してくれた。
人に驚きを与えるには、妄想や未来像を信じ抜いて実現する力が必要なのだろうと痛感した。
「あっと驚くサービスに必要なのは、改善ではなく革命なのだ」と心に刻みたい。

## 機械に仕事が奪われる理由は積極的な願望

去年GPT4が出た時も、「AIに仕事が奪われる」ということはたくさん言われてきたわけだ。
しかし今日まで本格的に奪われてる仕事はそうない。

少なくとも私は、「AIに仕事が奪われる」という時、
「もうGPT4でよくなるじゃん」という気持ちで言っていたと思う。
その裏には「コスト的に」とか「面倒だから」みたいな消極的な理由があったんだと、思い返して感じる。

でも本当に「仕事が奪われる」時、
こんな後ろ向きな理由では奪われないんだろうと今回感じた。

GPT4oを見た人なら、
「これもうコールセンターとかこれでいいんじゃね」
と少なからず感じたのではと思う。
実際そうなるかは別とする（実際それをやれば、それを悪用してコールセンターからGPT4oに無料でアクセスするなんてこと起きそうだし）

だが同じ「AIでいいんじゃね」でも、
去年のGPT4のときと違うなって思ったのは、
「昨今の機械的なコールセンターの対応より、感情表現豊かなGPT4oに対応してもらいたい」
という積極的に求める気持ちがそこにあったことだ。

最近のコールセンターと言えば、
「〇〇の人は１を、〜〜の人は２を、、、」
みたいな機械的な対応が多い。
それと比べた時、この感情表現豊かでこちらの感情も汲んでくれるGPT4oに感じたことは、
「もうGPT4oでいいや」から、
「GPT4oにやってほしい！」に近づいていた。

こういう「積極的に機械に代わって欲しい」と思う時、
人類の仕事は機械に奪われるのではないだろうか？
蒸気機関が普及した時も、コンピュータが普及した時も、
「〇〇でいいや」ではなく「人間より〇〇のほうがいい！」という民意に人類の仕事は奪われたのではないだろうかと感じた。
人類から仕事を取り上げるのは人類なのだろうと思う。（今のところ）

「結局シンギュラリティまだ？」と感じている気持ちの中には、
「たしかにすごいけどまだまだ」とか、
「これじゃあまだ人間に任せておきたい」とかっていう気持ちがあると思う。

これを吹き飛ばして、
「これはもう人間よりAIに任せたい！」と思わせてしまうような驚きと興奮の片鱗を、GPT4oの発表に見た。

終わりどころがわからなくなってしまったが、明日深夜のGoogleの発表も楽しみだ。
Redshiftのデータ共有で元DBに作成したテーブルを即時反映させる

# はじめに
Redshiftのデータ共有、皆さん使われているでしょうか。
物理的なコピーをせず、Redshift間でデータの共有ができて便利ですよね。

さて、このデータ共有ですが、既に共有されているテーブルに対してデータの追加や更新（INSERTやUPDATE）をすると即時反映されますが、**テーブルの作成（CREATE TABLE）はデフォルトでは即時反映されません**。

テーブルの作成も即時反映させたい場合は、ALTER文で `SET INCLUDENEW = TRUE SCHEMA schema` を実施する必要があります。デフォルトではこれがFALSEになっており、かつGUI上ではこれをTRUEに設定できるところが見つかりませんでした。

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_ALTER_DATASHARE.html

今回はこれをクエリエディタv2で実施してみます。

# 前提条件
以下のRedshiftを、それぞれ別のアカウントで作成済み。

- プロデューサーはRedshift Provisioned (RA3)
    - データベース名 `dev`
    - データ共有名 `demosharing`
- コンシューマーはRedshift Serverless
    - 上記のデータ共有から作成したデータベース名 `sharing_dev`

# やってみる

## プロデューサー側

### テーブルの確認
クエリエディタv2で、`dev`データベースに存在するテーブルを確認します。
現在は、`demo_tbl`と`table_3`の2つが存在しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/9669b32e-c42e-0693-cf46-5c829dd9445a.png)

### ALTER文実行
`dev`データベース上で以下のALTER文を実行します。

```sql
ALTER DATASHARE demosharing SET INCLUDENEW = TRUE FOR SCHEMA public;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/d839cabc-cb88-2bb8-2efb-5e5ab6b782eb.png)

### テーブルの新規作成
同じく`dev`データベース上でCREATE文を実行してテーブルを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/8647ab69-406f-6aa9-e596-facb839c6f58.png)

### 再度テーブルの確認
プロデューサー側はもちろんテーブルが新規作成されていて、テーブルが3つになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/6632553f-8bce-ba60-d432-eeebd95b60e9.png)

## コンシューマー側

### テーブルの確認
コンシューマー側では、既にデータ共有からデータベースは作成しています。
そのデータベース`sharing_dev`を見てみると、以下のように3つのテーブルが出来ています。プロデューサー側で`CREATE TABLE`しただけで、コンシューマー側にも即時反映されていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/dfe5d78f-f16f-f30f-04c3-f440f0aea455.png)

# 注意点
プロデューサー側で実行したALTER文ですが、以下のように最後の`FOR SCHEMA public`を抜いて実行するとエラーになります。スキーマを指定しないとうまくいかないようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/956481cc-2828-5ada-7cdf-22df88393f51.png)

# おわりに
今回は、データ共有のデータ元のデータベースにテーブルを新規作成した際に即時反映されるように設定してみました。データ共有を作成したタイミングでこのオプションが設定できれば良いのですが、`CREATE DATASHARE`を見てもそのようなオプションはありませんでした。

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_CREATE_DATASHARE.html

そのため、今回のように一度データ共有を作成してから、ALTER文で設定するしかなさそうです。
即時反映されるようになると便利になる反面、それを知らずに新規テーブルを作成してしまい、**共有したくないものが勝手に共有されてしまった**という事故につながる可能性もあります。この設定を行う際は注意してください。
OpenAMのDockerイメージをSSL化して永続化する

# はじめに
OpenAMの公式Dockerイメージである openidentityplatform/openam をSSL化し、かつ設定内容を永続化させるdocker-compose  
※本設定は検証目的であり、この内容で実際のIdP構築を推奨するものではありません。

docker-compose.yaml等一式はこちら

https://github.com/MichitoIchimaru/openam

## 準備
### サーバー証明書作成
下記コマンドでサーバ証明書を作成する。コマンドは本リポジトリ直下（docker-compose.yamlファイルと同じ場所）で実行することを想定。

``` sh
openssl req -x509 -sha256 -nodes -days 3650 -newkey rsa:2048 -subj /CN=idp.example.com -keyout openam/cert/server.key -out openam/cert/server.crt
```
### OpenAM configフォルダ権限設定
Linux上でdocker起動する場合、下記コマンドでコンテナ側からバインドマウントしたフォルダにファイルを書き込めるようにする。コマンドは本リポジトリ直下（docker-compose.yamlファイルと同じ場所）で実行することを想定。  
コンテナ上ではopenamユーザーがID:1001で作成されているため、フォルダの所有者を1001とする。ホスト上1001がopenamである必要はなく、IDが一致していればよい。また、1001ユーザーが存在していなくてもよい。

``` sh
chmod 755 openam/config
chown 1001 openam/config
```

### hostsファイル更新
hostsファイルにidp.example.comを追加し、ホストOSのIPアドレスを定義する。

## 起動
下記コマンドでコンテナを起動する。

``` sh
docker-compose up
```

https://idp.example.com:8443/openam にアクセスし、初期設定を実施すると openam/config フォルダにOpenAMの諸情報が書き込まれる。

## 補足
### SSL化
openidentityplatform/openam を起動した際の/usr/local/tomcat/conf/server.xmlを持ってきて下記を有効化したのみ。

``` server.xml
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true"
               maxParameterCount="1000"
               >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/server.key"
                         certificateFile="conf/server.crt"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
```
カニ🦀になって絵日記書くSNSの構成技術〜インフラ編〜

# カニ🦀になって絵日記書くSNSの構成技術〜インフラ編〜

## はじめに
[カニ🦀になって絵日記書くSNSつくったので技術まとめ](https://qiita.com/kawerlake0322/items/ba97be7a098d57afde26)のインフラ編になります🦀
AWS Copilot CLIを使ったのでまとめます。

## AWS Copilot CLI
CLIで、簡単な質問に答えればAWS環境をあっという間に構築してくれる優れものです。私のようなインフラのことよく分からなくてもデファクトスタンダードで作ってくれちゃいます。アーキテクチャを聞いてくる質問があるのですが、フロントエンドはApp Runner(Request-Driven Web Service)を、バックエンドはECS on fargate(Load Balanced Web Service)を使うっぽいということだけ知っておけば多分もう大丈夫です。
[ドキュメント](https://aws.github.io/copilot-cli/ja/docs/overview/)も結構分かりやすいと思います。
docker使って開発している方は是非使ってみてください！

### メリット

#### インフラやったことない人でも高速デプロイ可能
VPC？サブネット？みたいな感じでも、よくあるデファクトで作ってくれます。CLIで聞かれる質問も、サービス名何？とかその程度。アーキテクチャだけは事前にどれ選択すればいいかは検討しておきましょう。
#### インフラできる人も、環境のカスタマイズしながら時短で作業可能
CLIのコマンドで出来上がったmanifestファイルを編集してカスタマイズできます。GUIポチポチする手間省けて時短になりそうかな？と思いました。
#### サービスをまるごと消すのも楽ちん
コマンド一つで環境丸ごと消すことが可能です。
```
copilot app delete
```
#### CI/CDも作れる
CodePipelineできちゃいます。

### デメリット
#### インフラできない人間は一度レールから外れると元に戻りにくい
インフラできない＝応用が効かないので、何かの拍子に変なことするとよくわからなくなり、`copilot app delete`で最初からやりなおしたこともありました(そりゃそう)。
#### まだアップデートが必要な部分もあり
「取得済みドメインを使う場合は`copilot app init`時のオプションで指定しなければならない」など、注意しなければならない点があったり、永遠に続いているissueがあったりと改善の余地はあるっぽいです。
#### web画面のマネジメントコンソールで変更した場合、どうやって同期とるのか分からない
デメリットというか、まだわからないのが、マネジメントコンソールで変更した場合、該当箇所のmanifestファイルも変更してあげないと整合性とれないよな〜と思います。基本的にはmanifestファイル編集して反映した方が良さそう？

### ちょっと分かりにくかったけど解決したこと
#### 複数環境にデプロイの流れ
dev環境と本番環境を用意したら、既に`copilot svc init`で作成したサービスを`copilot svc deploy`でそれぞれの環境にデプロイできます。環境ごとに`copilot svc init`する必要ありません。

## サービスについて
大元の記事でも紹介させていただきましたが、エンジニアに馴染みのあるカニにまつわるサービスになります🦀

- サービスURL: https://diary-crab.com
- 気が早いけど公式インスタは[こちら](https://www.instagram.com/diary_crab?igsh=MW9xd2R2ZG9kNmV2dw%3D%3D&utm_source=qr)
  - 怪しい人じゃないことが分かるようにという意図もあります


どんなサービスか少しでも気になっていただけたら是非インスタ覗いてみてください🦀
メモ：データ分析基盤概要（２）


#### 今回のテーマ：
ビジネスに繋げるためのデータ活用策と、それをデータ基盤に落とし込む際の考え方


## ユースケース

ここでのユースケースは、データ分析基盤の用途を指す。

例えば、食品メーカーで考える施策として、
・サプライチェーン最適化
・在庫最適化
・売上や仕入れ数、広告コストのモニタリング
・商品開発におけるABテスト

などが挙げられるが、これらの施策に対し、以下の流れでユースケースを定める

 **ユースケースの定め方**
1、事業についての目標、現状、課題、施策を洗い出す
2、データ活用施策の投資対効果を見立て、優先順位を定める
3、期待される効果と必要なコストを算出し、総合的に判断して優先順位を決める

上記ユースケースを実現するためにデータ分析基盤を整備することになるが、
データ基盤構築の目的＝ユースケースの実現であり
**開発・運用コスト < ユースケースの便益**
が前提となる。

つまり実務においては、最初にユースケースを検討→データ活用方法検討→データ収集・投資の判断という流れとなる。

ユースケースについては、課題やニーズを深掘りし、解像度を上げていくことが重要かと思われるが、そこら辺については下記の書籍が個人的には参考になった。

[解像度を上げる――曖昧な思考を明晰にする「深さ・広さ・構造・時間」の４視点と行動法](https://www.amazon.co.jp/dp/4862763189)

## サービスレベルの設定・計測

サービスレベル＝サービスの品質水準
サービスレベルはユースケース毎に以下の流れで設定、計測する。

**1、目標設定**
例えば、

・営業支援システムにおいて、「週次の売上データの集計が月曜日の8時までに終わっている」
・労務で使用するシステムにおいて、「勤怠情報の更新が毎朝7時までに終わっている」

といったものが挙げられる。使用する人や部署によりサービスレベルは異なる。例えば、前者の営業支援システムでの遅延率が5%は許容範囲かもしれないが、後者の労務システムでは許容できないなど。

**2、関係者との合意**
仮に遅延率目標を1%とした場合、それが達成可能かどうかをデータエンジニアやデータ生成者に確認する。

**3、現状の計測**
遅延率目標1%に対し、現状ではどの程度達成できているかを計測する。

**課題の設定**
現状の計測の結果、未達であれば何が問題かを分析する。

**必要な施策の実施**
問題を取り除くことができる施策を実施。

**結果の振り返り**
最後に、実施した施策によって結果がどうなったかを検証する。

## データパイプライン

ここから具体的に、データを収集するところからユースケース（データ活用）までの流れをまとめていく。

一連のデータパイプラインに関する基本的な用語などについては、以下にもまとめてあります。

https://qiita.com/sho91/items/4330b257e9a6a5d39ea8

## データレイク
#### データレイクの正しい活用法
##### １、データをそのままコピーしてくる
データレイクに置いておくデータは、そのままの状態、いわゆるROWデータが望ましい。とりあえずありのままのデータを溜めておくイメージ。

むやみに加工してしまうと、異なる視点（月単位、週単位など）から分析をしたいと考えた際に柔軟性がなく、使い勝手が良くない。

また、後々データに誤りが見つかった際、元データが間違っているのか、加工後のデータがおかしいのか問題を切り分けられない。

なので加工・修正するとすればデータレイクに取り込む前段階で大元のデータソース自体に行う、それが間に合わなければ後述のデータウェアハウスで行うのがベター。

##### ２、データレイクを作るのは一箇所とする
複数箇所に作るとデータソースの修正が発生した際に全てのデータレイクに取り込み直さないといけない。
また、データレイクは部署を横断してデータを溜めておく場でもあるので、複数箇所に作ると各部署からデータをかき集める事態にもなり得るため共通の場としておく。


## データウェアハウス
#### データウェアハウスでは共通指標を管理する
会社全体で見た時、部門毎に言葉の定義が異なっていると、分析結果を見た経営層は誤った意思決定をしてしまう。
主要指標については、共通指標をデータウェアハウスで管理する。例えば、部署横断での分析の際、「売上」が何を示すのか共通の指標を作るべき（税込、税抜、割引のありなしetc)
部署によって用途が異なるデータについては、後述のデータマートで管理する。


#### データウェアハウスは分析用DB（データウェアハウス製品）を使用するべし
分析用DBは他のツールから参照されることを前提に作られているが、スプレッドシートやBIツールはその限りではない。なので、「売上」のような主要な指標はBIツールなどではなく、部門横断で分析用DBにデータを用意した方が良い。

※DBにはオペレーショナルDBと分析用DBがあり、オペレーショナルDBはアプリケーションに使うようなDBで行指向型、分析用DBは分析に特化しており列指向型となる。ここら辺は別途どこかで記事をまとめたい。

## データマート
用途（ユースケース）と１対１の関係になるのがデータマート

#### データマートを作るメリット
##### １、試行錯誤できる
ユースケースと１対１の関係になるため、他部門や他用途への影響を気にする必要がなく、試行錯誤しても影響範囲が限られる。
##### ２、過去のロジックを再利用できる
ユースケース毎にデータ集計ロジックを用意しておけば、類似の業務が発生した際に既存ロジックを参考にできる。
##### ３、システムの応答時間が速くなる
事前に集計処理を施しておけば、ダッシュボードを表示するたびに複雑な集計が必要ないので、応答時間の早さにつながる。


#### データマートの課題と解決策
**課題１：**
個別にデータマートを作りすぎ、似たような集計ロジックが無駄に散在する。
**解決策：**
データの利用状況や依存関係を整理し、不要なデータマートは削除するなど組織としてクリーニングの仕組みを作る。

**課題２：**
データマートに各ツールを使う場合、集計ロジックが格ツールに分断され、依存関係が管理できない。
**解決策：**
各種使いやすいツールで試行錯誤→軌道に乗りそうだったら、ロジックをSQLに書き換え、定常的に実行できるようにワークフローエンジンに組み込む。

## 終わりに
今回は、ビジネスに繋げるためのデータ活用策として重要なユースケースとサービスレベルの考え方、それを実現するためのデータパイプライン設計の考え方についてまとめました。

次回のテーマは検討中！

#### 参考図書
[実践的データ基盤への処方箋〜 ビジネス価値創出のためのデータ・システム・ヒトのノウハウ](https://www.amazon.co.jp/dp/4297124459)
UnityのCanvasを解像度が変わってもズレないようにする

# 解像度を変えてもそのままのレイアウトで適応させる

**1.** 適応させたいCanvasのInspectorから**Canvas Scaler**内の**UI Scale Mode**の項目を**Scale With Screen Size**に変更

![スクリーンショット 2024-05-14 213010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508870/4fa3cdeb-5c0c-05bc-eedc-8590a607c680.png)

この項目によって画面サイズが変わってもそれに合わせてUI要素の大きさが変わります。

**2.** **Screen Match Mode**の項目を**Expand**に変更

こちらはUI要素がCanvas外にはみ出てしまうことを防ぎます。

![スクリーンショット 2024-05-14 213918.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508870/1b09d402-1902-d199-cdf2-c5872380d76f.png)



**Reference Resolution**の項目でベースとなる解像度を調整できるので作成するゲームによって調整してください。
[ReviewAI 使用例] ヤンピョン ヘジャンク [新大久保 韓国料理店]


# はじめに

レビュー分析AIサービスの ReviewAI (レビューアイ) を開発しています。
本記事ではレビュー分析の例として、新大久保の韓国料理の人気店を取り上げていきます！
[人気店の記事をまとめているページはこちらです。](https://qiita.com/RetegyLink/items/3d94852bf25a724a82cc)

今回は、ヤンピョン ヘジャンク の食べログに集まっているレビューを分析します。

## ヤンピョン ヘジャンク

> 本場韓国の味を、新大久保で気軽に堪能！

[食べログ](https://tabelog.com/tokyo/A1304/A130401/13030759/)

## ReviewAI (レビューアイ)

弊社 RetegyLink が開発中のレビュー分析 AI です。
https://reviewai.next-seed.work/
試作版を公開中で、現在は
- [食べログ](https://tabelog.com/)
- [じゃらん](https://www.jalan.net/)
のレビューを分析できます。

# レビュー分析

さっそくですが、こちらが分析結果です！
ランチという単語に加えて、
ホルモン・スープ・ネジャンタンと美味しそうなのもありますね。
円 にオレンジ色が多いのが気になるところです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/dccaef23-822f-2593-1a45-28713977b6bd.png)



## ランチ

<font color=steelblue>**良い評価**</font>

- またボリュームもかなりなもので、大満足なランチでした。
- ランチもやっているので二日酔いの日にホントハマるだろう。
- 今回は2人での来店で食べたいものを頼んでみましたが、おひとり様でも入りやすいお店なので今度はランチに1人で来てみようと思います(^O^)


## ホルモン

<font color=steelblue>**良い評価**</font>

- ホルモンが好きであれば、問題無く満足出来ると思います。
- ホルモンはちょっと苦手なものもありましたが、思ったよりクセなく美味しく食べれました！
- ホルモンには無機質やカルシウムなどが多く含まれていてとても体に良く、ホルモンを食べると翌朝は元気ハツラツです。


<font color=chocolate>**黄色・橙色の評価**</font>

- ホルモンのスープ、て説明だったチョレギサラダを頼んで様子見どれも量が多くて２人だとたくさんは注文できない

## スープ

<font color=steelblue>**良い評価**</font>

- 牛テールスープも深い味で、自分で塩分調整できるのも嬉しい！！
- 健康的なスープ専門店、前から気になっていたので、とても楽しみです♪
- 好みとしてはもう少し濃い味が好きなのですが本当に身体に良さそうなスープなのでおすすめです。



## ネジャンタン

<font color=steelblue>**良い評価**</font>

- 新大久保駅から少し離れますが、ここのネジャンタンやヘジャンクは本当に美味しい牛生の内臓系もたっぷり入っていて、満足ですね✨
- ここはスープが有名なお店なので、人気No.1のネジャンタンにしました。
- ソルロンタンもトガニタンも自分で塩などで味付けをするのに対して、ネジャンタンは最初から結構しっかりと味がある。


## 円

<font color=steelblue>**良い評価**</font>

- 焼き立て、熱くて〜「ネジャンタン910円」もしホルモンが苦手な方はちょっと......
- ランチだと、ご飯つきで1000円を切るのが嬉しい。
- コッチョリ…キムチのような物を７８０円でテイクアウトしました。

<font color=chocolate>**黄色・橙色の評価**</font>

- 自家製豚足(800円)
- １５００円は、野菜がシャキシャキしているのに、　生地が『もっちり』　外はサクサク香ばしい。
- お酒も相当飲んだはずなのに4000円くらいとお安め。


## ReviewAI の改善点

良い評価をしている文なのに
感情分析でオレンジ色に予測されてしまうことがあり
これは改善が必要そうです。

# おわりに

ホルモンたっぷりのネジャンタンがランチで楽しめるお店のようです。
二日酔いのときは ぜひ行きたいですね！

観点ごとの詳細を確認されたい方は、ぜひサイトにアクセスして確認してください！
レビュー分析AI の [ReviewAI](https://reviewai.next-seed.work/) は試作版を公開中です。
今回分析した ヤンピョン ヘジャンク の URL はこちらです。
```
https://tabelog.com/tokyo/A1304/A130401/13030759/
```

今後どんどん使いやすくしていく予定ですので、
ぜひ皆様の ReviewAI に関するご意見を[アンケート](https://docs.google.com/forms/d/e/1FAIpQLSc-yVTDeqqMc9GqM93BvzaYWCB6wyToesYj_wl8bhwKgw8LqQ/viewform?usp=sf_link)で教えてくださると幸いです。
Chat GPTに聞いてみた #1

## Chat GPTへの質問
　1997年、トヨタが世界で初めてハイブリッドのプリウスを世に出しました。あれから約30年が経過し、トヨタはハイブリッド技術で競合他社の追従を許さない確固たる地位を築くことに成功しました。この歴史からBEVの広がりが鈍化してといっても、今BEV業界で生き残ることができたOEMが、30年後自動車業界を牛耳っていると思いますが、どうでしょうか？

## Chat GPTの回答(5/14)

　トヨタが1997年にハイブリッド技術を搭載したプリウスを初めて市場に投入してからの成功は、技術的な先進性と市場戦略の両方において重要な教訓を提供しています。約30年後の今、その成功に基づく洞察をもとに、BEV（バッテリー電気自動車）市場の将来について考察することは有意義です。

### トヨタのハイブリッド技術の成功
　トヨタはハイブリッド技術に早期に投資し、大規模な製品展開を行うことで、市場における圧倒的なリーダーシップを築きました。この成功の要因には以下が挙げられます：

#### 技術革新: 
 　ハイブリッドシステムの開発と改良に絶え間ない努力を注ぎ、燃費効率や信頼性を向上させました。

#### 市場の理解: 
　消費者のニーズを的確に捉え、エコカーの市場を創出し、拡大させました。

#### 規模の経済: 
　大量生産によるコスト削減と価格競争力の確保に成功しました。

### BEV市場の将来
　BEV市場においても、同様の要因が成功のカギを握ると考えられます。

#### 技術革新:
　バッテリー技術: 現在、多くの企業が固体電池や新型リチウムイオン電池の開発に注力しており、これにより航続距離の延長や充電時間の短縮が期待されています。
充電インフラ: 充電ステーションの拡充が急務であり、これにより消費者の利便性が向上します。

#### 市場の理解:
　消費者教育: 消費者のBEVに対する理解を深めるための教育やマーケティング活動が重要です。
製品の多様化: 様々なライフスタイルに対応したBEVモデルの開発が求められます。

#### 規模の経済:
　大規模生産: 大規模生産によるコスト削減と価格競争力の確保が、普及のための鍵となります。
提携と協業: 他企業や政府との提携によるコスト分担や技術共有が重要です。

### 生き残るOEMの条件
　30年後に自動車業界を牛耳るのは、以下の条件を満たしたOEM（自動車メーカー）である可能性が高いです：

#### 持続的な技術投資: 
　バッテリー技術や充電インフラへの継続的な投資を怠らないこと。
#### 市場の適応力: 
　消費者のニーズや市場の変化に迅速に対応できる柔軟性を持つこと。
#### 戦略的提携: 
　他の技術企業やインフラ企業との戦略的提携を通じて、市場の支配力を強化すること。
　
 　例えば、テスラはBEV市場の先駆者として位置付けられ、充電インフラの整備やバッテリー技術の革新に積極的に取り組んでいます。また、伝統的な自動車メーカーも新技術への投資を拡大し、競争力を高めています。

### 結論
トヨタがハイブリッド技術で成功したように、現在のBEV市場でも同様の戦略が成功の鍵となるでしょう。技術革新、市場理解、規模の経済という要素を確実に押さえることで、BEV市場でのリーダーシップを獲得し、30年後の自動車業界を支配する企業となる可能性があります。


Chat GPTくん、回答が早いよ。。。
.htaccessを使いファイルの置き場所を変えずにURLを変更する【WordPress】

未検証( ..)φメモメモ

ファイルの置き場所を変えずにURLを変える場合、内部リダイレクトを使用して、サーバーが実際のファイルの場所を処理する一方で、ユーザーには新しいURLを表示する方法があります。WordPressの場合、htaccess ファイルでこの設定を行います。

以下に具体的な手順とコード例を示します。

## 手順
#### WordPressのルートディレクトリにある .htaccess ファイルを編集:

通常、WordPressインストールディレクトリに .htaccess ファイルがあります。
このファイルを編集します。
もし .htaccess ファイルがない場合は、新しく作成します。   

#### .htaccess ファイルに以下のコードを追加:
```
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# サブディレクトリの名前をここに入力 (例: blog)
RewriteRule ^サブディレ/(.*)$ /$1 [L]

# ここからWordPressの標準のリライトルール
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

```
具体的な例として、サブディレクトリ が blog という名前の場合は、
以下のようになります：
```
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# blog サブディレクトリからルートへの内部リダイレクト
RewriteRule ^blog/(.*)$ /$1 [L]

# ここからWordPressの標準のリライトルール
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
```
### 説明
RewriteRule ^blog/(.*)$ /$1 [L]:

^blog/(.*)$：blog サブディレクトリ以下のすべてのパスにマッチします。
/$1：blog を取り除いて、残りの部分をルートディレクトリにマッピングします。
[L]：このルールがマッチした場合、他のルールは適用されないようにします。
WordPressの標準リライトルール:

RewriteRule ^index\.php$ - [L]：index.php への直接アクセスはそのまま処理します。
RewriteCond %{REQUEST_FILENAME} !-f：リクエストされたファイルが存在しない場合。
RewriteCond %{REQUEST_FILENAME} !-d：リクエストされたディレクトリが存在しない場合。
RewriteRule . /index.php [L]：すべてのリクエストを index.php に渡します（WordPressのフロントコントローラー）。

この設定により、ユーザーが example.com/blog/post-title にアクセスすると、内部的に example.com/post-title にリダイレクトされます。ただし、実際のファイルの場所は変更されません。

### 注意点

パーマリンク設定: WordPressのパーマリンク設定を確認し、適切な構造に設定されていることを確認します。
キャッシュのクリア: ブラウザのキャッシュをクリアして、新しい設定が正しく反映されることを確認します。
テスト: いくつかのURLをテストして、期待通りに動作するか確認します。
これにより、WordPressサイトでファイルの置き場所を変更せずにURL構造を変更することができます。
MX MASTER3のキーボードショートカット割り当てが反応しない問題の解決方法

MX MASTER3のマウスにキーボードショートカットを設定した際、ショートカットが反応しない問題に対処する方法について解説します。この問題は特定のキー（CommandやShift）の左右の区別が原因となることがあります。

環境　MacBook Air 2020
Chip Apple M1
Memory 16 GB
Startup disk Macintosh HD
macOS Sonoma 14.5
KeyBoard HHKB Professional HYBRID Type-S 英語配列／墨

問題の概要

MX MASTER3にショートカットを割り当てる際、ショートカットが反応しないことがある。
特にCommandキーやShiftキーを使用したショートカットが設定できない場合がある。

HHKBのキーボードに変更してからこの問題が発生したのでもしかしたら内臓キーボードでは再現性がないかもしれません。

原因

Logicoolのソフトウェア（Logi Options+）では、CommandキーやShiftキーの左右を区別する場合がある。
そのため、左側のCommandキーと左側のShiftキーを使用する必要がある。

解決方法

ショートカットを設定する際に、左側のCommandキーと左側のShiftキーを使用して入力する。
例：Cmd + Shift + T のショートカットを設定する場合、Left Cmd + Left Shift + T として入力する。

手順

Logicoolのソフトウェア（Logi Options+）を開く。
ショートカットを設定したいボタンを選択する。
キーボードショートカットを入力する際、左側のCommandキーとShiftキーを使用する。
設定を保存し、動作を確認する。
まとめ

左右のキーの区別に注意することで、ショートカットが正常に動作するようになります。
この方法を試しても解決しない場合は、ソフトウェアの再インストールや他の設定を確認することをお勧めします。
最後に
この記事が役に立ったと思ったら、ぜひ「いいね」やコメントをお願いします。同じ問題に直面している人たちの参考になることを願っています。
【GitHub メモ】ブランチを切ってプルリクエストを作成する

<br>
こんにちは、Reikaです。<br>私は現在、アプレンティスの5期生として日々勉強に励んでいます。<br>

https://apprentice.jp/lp


アプレンティスの課題では、チームで開発するカリキュラムがあります。<br>そこで、**初めてGitHubを使ってチーム内でコードを共有する経験**をしました。<br>今回は、その一連の操作について簡単にまとめていきます。

# remote addからpushまで

早速ですがつらつらとコマンドを書いていきます。

1.まずはリポジトリに移動する

```
cd <リポジトリ名>
```

2.リモートリポジトリの確認

```
git remote -v
```

4.リポジトリをクローンする（リモートリポジトリが設定されていない場合）

```
git clone <リポジトリのリンク>
```

5.最新の状態に更新

```
git pull origin main
```

6.新しいブランチを作成して切り替える

```
git checkout -b <ブランチ名>
```

7.ブランチで作業

```
git add .
git commit -m "<コミットメッセージを書く>"
```

8.リモートブランチをプッシュ

```
git push origin <ブランチ名>
```

9.プルリクエストを作成
GitHubやGitLabなどのリポジトリホスティングサービス上で作成。<br>