OmniAICreator/Qiita-1.07M huggingface dataset:
エラー発生　NoMethodError in QuestionsController#new　（解決済み）

## はじめに

今まで動いたのにトップページに質問相談検索機能を実装したら突然質問相談投稿ができなくなり以下エラーが表示。

```NoMethodError in QuestionsController#new
undefined method move_to_index' for #<QuestionsController:0x00000000025c60>
Extracted source (around line #400): 
398　　def make_lambda 
399 　lambda do |target, value, &block| 
400 　target.send(@method_name, &block) 
401 　target.send(@method_name, &block) 
402 　 end 
403 　end
```

どうやら検索機能を実装中にmove_to_indexの定義を消してしまったようだ。
以下訂正。
```
class QuestionsController < ApplicationController
  before_action :set_question, only: [:show]
  before_action :move_to_index, except: [:index, :show, :search]

  def index
    @questions = Question.all
  end

  def new
    @question = Question.new
  end

  def create
    @question = current_user.questions.build(question_params)
    if @question.save
      redirect_to @question, notice: '質問が作成されました。'
    else
      render :new
    end
  end

  def show
    @questions_answers = @question.questions_answers.includes(:user)
    @questions_answer = QuestionsAnswer.new
  end

  def search
    @questions = Question.search(params[:keyword]) # 検索処理  
    if @questions.count == 1
      redirect_to question_path(@questions.first) # 検索結果が1件ならそのページに遷移
    elsif @questions.empty?
      redirect_to questions_path, alert: '該当する質問は見つかりませんでした。' # 検索結果が0件ならメッセージを表示
    else
      render :search # 複数件ヒットの場合はそのままリスト表示
    end
  end

  private

  def set_question
    @question = Question.find(params[:id])
  end

  def move_to_index    # ココ追記。ログインしていない場合、トップページへリダイレクト
    unless user_signed_in?
      redirect_to root_path, alert: "ログインが必要です。"
    end
  end

  def question_params
    params.require(:question).permit(:symptoms, :progress, :medicine, :hospital, :habit,
                                      :favorite_food, :favorite_place, :image, :pet_id)
  end
end
```

 ## おわりに
 いろいろ機能を追加実装していくと前後のつながりが分断されてしまう事があるので（特にマイグレートは親子の順番で動かなくなったりするので）気を付けよう！！！
ゲームプログラマのための設計：事前処理・事後処理の強制方法比較

[ゲームプログラマのための設計シリーズ](https://qiita.com/kobitnex/items/93397d985682c806884c)：デザインパターン編の記事です。

# 概要
* 事前処理・事後処理を確実に呼び出したいなら、RAII・ローンパターン・Template Methodパターンが考えられる
* スコープ外に持ち出す必要があるならRAII
* そうでなければローンパターンがオススメ

# 本文

こんなAPIがあるとします。
```cpp
class Graphics
{
public:
	void beginDraw(); // 描画開始
	void drawXXXX();  // 具体的な描画
	void drawYYYY();  // 具体的な描画
	void endDraw();   // 描画終了
};
```
beginDraw/endDrawが「具体的な描画」関数の呼び出し前後に確実に呼ばれるようにするにはどうしたらよいでしょうか。

## RAII
まずは、おなじみのRAIIです。
```cpp
class RAIIDrawer final
{
public:
	explicit RAIIDrawer(Graphics& g) : mGraphics(g) { mGraphics.beginDraw(); }
	~RAIIDrawer() { mGraphics.endDraw(); }

	// ※コピーやムーブの実装は要注意。必要なければ消しておくのがオススメ
	RAIIDrawer(const RAIIDrawer&) = delete;
	RAIIDrawer(RAIIDrawer&&) = delete;

	// begin/endの間に行ってほしい操作へのプロキシ
	void drawXXXX() { mGraphics.drawXXXX(); }
	void drawYYYY() { mGraphics.drawYYYY(); }

private:
	Graphics& mGraphics;
};
```

```cpp
void test(Graphics& graphics)
{
	RAIIDrawer drawer(graphics);  // DrawerのコンストラクタでbeginDraw

	drawer.drawXXXX();
	drawer.drawYYYY();

	// DrawerのデストラクタでendDraw
}
```
この方法はRAIIオブジェクトをスコープの外に持ち出せるメリットがあります。
が、それゆえに
* RAIIオブジェクトのコピー/ムーブの実装には気を使わないといけない
* RAIIオブジェクトより先にGraphicsの寿命が尽きてしまい不正な参照となる

という危険も存在します。

## ローンパターン
もう一つの解は、[高階関数](https://qiita.com/kobitnex/items/634bc67920570596902a)を使う方法です。

```cpp
// beginDraw/endDrawを隠す
class DrawProxy
{
public:
	explicit DrawProxy(Graphics& g) : mGraphics(g) {}

	// begin/endの間に行ってほしい操作へのプロキシ
	void drawXXXX() { mGraphics.drawXXXX(); }
	void drawYYYY() { mGraphics.drawYYYY(); }
private:
	Graphics mGraphics;
};

void LoanDraw(Graphics& graphics, std::function<void(DrawProxy&&)> f)
{
	graphics.beginDraw();

	f(DrawProxy{ graphics });

	graphics.endDraw();
}
```

```cpp
void test2(Graphics& graphics)
{
    // LoanDrawがbegin/endDrawを呼んでくれる
	LoanDraw(graphics, [](DrawProxy&& proxy) {
		proxy.drawXXXX();
		proxy.drawYYYY();
	});
}
```
良くも悪くもスコープの外に処理を持ち出せないので、その必要のないケースでは安心です。

## Template Methodパターン
継承で解決する方法も考えられます。

```cpp
class DrawerBase
{
public:
	explicit DrawerBase(Graphics& g) : mGraphics(g) {}
	void draw()
	{
		mGraphics.beginDraw();
		drawImpl_();  // Template Methodパターン
		mGraphics.endDraw();
	}

protected:
	// drawImpl_から呼んでもらう用　
	// （ローンパターンにおけるDrawProxyのようにしてもいい）
	void drawXXXX_() { mGraphics.drawXXXX(); }
	void drawYYYY_() { mGraphics.drawYYYY(); }

private:
	virtual void drawImpl_() = 0;
	Graphics mGraphics;
};
```

```cpp
void test3(Graphics& graphics)
{
	class Drawer : public DrawerBase
	{
	public:
		explicit Drawer(Graphics& g) : DrawerBase(g) {}
	private:
		void drawImpl_() override
		{
			drawXXXX_();
			drawYYYY_();
		}
	};

	Drawer{ graphics }.draw();
}
```
こちらは処理の数だけDrawerBase継承を増やさないといけないのがちょっと大がかりすぎますね。

## まとめ

|  | スコープ外持ち出し | 利用側の記述量 | 
|:-:|:-:|:-:|
| RAII  | 〇 | 小 |  
| ローンパターン | × | 小 |  
| Template Methodパターン | × | 大 | 

* スコープ外に持ち出す必要があるならRAII
* そうでなければローンパターンがオススメ

です。
Qiitaって何を書けばいいの？

# 結論

何を書いてもOK!!

<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>


と、言いたいところですがそんなわけはなく。。。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3934352/91e7fcb5-0914-2b0b-4376-6a859f532449.png)

[About - Qiita](https://qiita.com/about)より

# もう少し丁寧に

(ここからは私の解釈も入りますが)

先ほど書いた通り「Qiitaは、エンジニアに関する知識を記録・共有するためのサービス」です。
で、英語の方では「How deevelopers code is here.」と書いていますので、コーディングに関するナレッジ、ノウハウ見たいなものが中心かと思いきやQiitaを少しでも見たことがある人なら<font color="red">「ポエム」</font>というようなタグをつけて色々なお気持ち表明みたいな記事もご存じなのではないでしょうか。

もう一つ、しっかりと守らないといけないものに __ガイドライン__ があります。

https://help.qiita.com/ja/articles/qiita-community-guideline

ここには誹謗中傷はダメ、みたいな当然のこともそうですが「エンジニアにとって再利用性・汎用性の高い情報」を書いてねとあります。

つまり、プログラミング、コーディング、開発全般のナレッジ、ノウハウをはじめとしてエンジニアの働き方やコミュニケーション、健康などなど思ったよりも幅広く書いていい(はず)です！

# 私が記事を書くときに一番悩むこと

Qiitaに限らず私が記事を書くときに一番悩むこと、それは、、、


### 「今書こうと思ったことも、きっと誰かが書いてるんだろうな～～～」

です。

なんなら既に誰かが書いた記事に助けられて、それについてもう少し書きたい！と思ったところかもしれません。
そんなときは、<font color="red">迷わず書きましょう！！！</font>

私がそう考える理由は以下です。
- 情報はすぐに古くなる（特にITの業界は）
- 人によってハマるところは千差万別なので、ちょっとした困ったポイントの情報はいくらあっても困らない
- 説明の仕方や文章の書き方は人それぞれ個性が出るので、同じ内容を説明してても誰かにとって分かりやすい情報になる可能性は十分ある
- なにより、<font color="red">アウトプットは自分のためになる！！</font>

皆さんも調べ物をしたときに、同じような記事をいくつか並べて読んでみて自分にとって分かりやすい表現をかいつまんで理解する、みたいな経験はありませんか？そういうことです。

そして赤字でも書きましたが、アウトプットは自分のためになるんです。
「世界一流エンジニアの思考法」を書かれた牛尾さんも仰っていましたが、言葉でも文字でも人に説明することが自分の理解度に気付けて、さらに理解を深めるとても良い機会になるんです。

だからもう一回書きます。みなさん、どんな些細なことでもエンジニアに関係するトピックで思い当たるものがあれば<font color="red">迷わず書きましょう！！！</font>

<iframe width="560" height="315" src="https://www.youtube.com/embed/vNj6wgUjOLA?si=ePCBKEI00tD8xQzJ&amp;start=317" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
KinoYouTube を使って Livebook 上で YouTube 動画を視聴する

## はじめに

みなさんご存知、動画共有サービス YouTube

https://www.youtube.com/

今回は KinoYouTube を使って、 Livebook で YouTube動画を視聴します

https://github.com/acalejos/kino_youtube

実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/kino/kino_youtube.livemd

## セットアップ

KinoYouTube をインストールします

```elixir
Mix.install([
  {:kino_youtube, "~> 0.1"}
])
```

## 動画視聴

YouTube の URL を指定するだけで動画が視聴できます

```elixir
KinoYouTube.new(
  "https://www.youtube.com/watch?v=2BaHEk5zwTo",
  start: 2,
  controls: 1
)
```

実行の様子

![kino_youtube.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/22d14be0-ab4c-465b-f56a-13c83942bb8d.gif)

オプションについては YouTube のドキュメントを参照してください

https://developers.google.com/youtube/player_parameters?hl=ja#Parameters

ちなみに、視聴したのは [piyopiyo.ex](https://piyopiyoex.connpass.com/) の紹介動画です

<iframe width="560" height="315" src="https://www.youtube.com/embed/2BaHEk5zwTo?si=eolsx9e2zI_0cZ3C" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## まとめ

簡単に Livebook で YouTube 動画が視聴できました

ドキュメントとして Livebook を使うとき、動画を埋め込むのに使えますね
【Django】Mixed Contentエラーになったのは「request.scheme」を使っていたのが原因だった

# 概要
Djangoアプリを使用していたら`Mixed Content`というエラーになりました。
少しイレギュラーな原因でしたが、備忘も兼ねて紹介します。

## Mixed Contentエラー

ブラウザのコンソールに表示されたエラーは以下です。

> Mixed Content: The page at 'https://xxxxx' was loaded over HTTPS, but requested an insecure stylesheet 'http://xxxxx.css'. This request has been blocked; the content must be served over HTTPS.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/ad837310-e075-bf38-570b-e0b06fab0254.png)

該当と思われるDjangoのHTMLテンプレートを確認すると以下でした。

```
<img class="icon" src="{{ request.scheme }}://{{ request.META.HTTP_HOST }}/xxx/images/{{ tag.image_name }}">
```

上記は、現在のリクエストのスキームとホスト名に基づいて、画像の完全なURLを動的に生成するコードです。

・`{{ request.scheme }}`：現在のリクエストのスキーム（httpまたはhttps）を取得
・`{{ request.META.HTTP_HOST }}`：現在のリクエストのホスト名を取得
・`/xxx/images/`：画像ファイルが配置されているディレクトリのパス
・`{{ tag.image_name }}`：tagオブジェクトのimage_name属性を取得

この方法で動的にURLを生成していたのが原因でした。

このアプリはAWSのロードバランサーにより、アプリケーション側がHTTPで返したものをHTTPSに変換するルールが設けられていました。ただ、Djangoアプリケーション自体はHTTPでリクエストを処理しているため、`request.scheme`が`http`のままになります。

その結果、HTML内で生成される静的ファイルのリンクが`http`になり、ブラウザ上でMixed Contentエラーが発生していたのです。

ブラウザ上ではHTTPSなのに、Djangoアプリとしては静的ファイルをHTTPで生成しているので、「Mixed Content」となったということですね。

## 解決方法
Djangoアプリでは`static`テンプレートタグの方がメジャーでしょう。

実際私も今まで`static`テンプレートタグを利用していましたし、これが一般的に推奨されていると思います。
Djangoのドキュメントもこちらですね。

> {% static %} テンプレートタグは、静的ファイルの完全 URL を生成します。

https://docs.djangoproject.com/ja/5.1/intro/tutorial06/
vscodeでのTypeScriptのライブラリ開発とかでJSから参照するとき型を表示させる方法

今回は発見したライフハックを紹介します。
前提として、Visual studio codeに以下拡張機能を入れてください。

https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-next

## TL;DR
TSで作ったライブラリを外部からJSで参照するときは`index.js`と`index.ts`を用意すると型補完(?)ができる

## フォルダ構成
```
dist
- bundle.js
src
- index.ts
- ...
...
```
このような構成のライブラリとかを他フォルダから参照する場合はフォルダ配下に以下を追加します。
```
index.ts
index.js
```
そしてその内容を以下にします。
```js:index.js
export * from "./dist/bundle.js"
```
```ts:index.ts
export * from "./src/index.ts"
```
## 何をしたか
拡張子以外同じJS/TSで同じ内容(バンドルされたもの/生)をエクスポートするようにしました
## 何が良いか
なんとindex.tsでエクスポートした内容がTypeScriptで宣言した型にしたがって補完の所に型が表示されます！

良いJS型ライフを！
LeetCodeを1日1題解いてみる (day15)

15日目に取り組んだ問題はこちら！

# 88. Merge Sorted Array

https://leetcode.com/problems/merge-sorted-array/description/

## 問題文
You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n, representing the number of elements in nums1 and nums2 respectively.

Merge nums1 and nums2 into a single array sorted in non-decreasing order.

The final sorted array should not be returned by the function, but instead be stored inside the array nums1. To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n.

## 僕の回答 (失敗作)
```py
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        point = 0
        del nums1[:-m]
        for i in range(n):
            val = nums2[i]
            while point < m and nums1[point] < val:
                point += 1
            nums1.insert(point, val)
```

## 僕の回答 (GPTに修正してもらったもの)
```py
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        point = 0
        nums1[:] = nums1[:m]
        for i in range(n):
            val = nums2[i]
            while point < len(nums1) and nums1[point] < val:
                point += 1
            nums1.insert(point, val)
            point += 1
            
```

## より効率の良い回答例

```py
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:

        mi, ni, ri = m-1, n-1, m+n-1
        while ni >= 0 and mi >= 0:
            if nums1[mi] <= nums2[ni]:
                nums1[ri] = nums2[ni]
                ni -= 1
            else:
                nums1[ri] = nums1[mi]
                mi -= 1
            ri -= 1
        while mi < 0 and ni >= 0:
            nums1[ni] = nums2[ni]
            ni -= 1
```

### コメント
配列の後ろから操作するというアイデアが浮かばなかった。スライスの使い方を理解できた。

### 次の問題はこちら!
https://qiita.com/h_y_s_d/items/3f6ab9d5b1ac551e79f4
ワイ、Googleカレンダー 「日本の祝日」の誤表示に踊らされる

以前、下記の記事のようなGASのスクリプトを作った。

https://qiita.com/miriwo/items/c1c9b29fb8fc722665ec

記事のタイトル通り、連休（祝日）も考慮したうえで、その週の最終営業日にSlackに通知を行うと言うものだ。
つくったっきり特にメンテもしておらず、毎週いい感じに動作していた。

しかし、本日2024/11/14（木）に突如としておかしい挙動を見せた。
休日前の営業日ではないはずなのに当該のGASが動作してSlackに通知が行われた。

「きっと自分が書いたGASのコードのロジックにバグがあったんだろうな、、」と若干落ち込みながらコードを読んでいた。
ただ、いくら探してもバグが発見できない。
実行しながらコードを見てみると2024/11/15（金）が祝日として判定されていることが分かった。
自宅にある物理的なカレンダーを見ても2024/11/15（金）は普通の平日として表記されている。

Googleカレンダーを見てみると「七五三」が祝日として表示されていた。
「え・・？七五三って祝日扱いだっけ？」と思い調べてみたらやはり祝日ではなさそうだった。

「七五三 祝日」で検索したときに下記の様な記事がヒットした。

https://news.yahoo.co.jp/articles/7aef2d9046a9eb403ffce99b7de7a0f8d44a31da

どうやらGoogleカレンダー側の誤表記らしい。クリスマスや七五三といったイベントが何故か「祝日」のカレンダーにイベントとして登録されてしまっているらしい。

オフィシャルの情報ではないがWeb上の先人たちの情報によればGoogleカレンダーのカレンダーIDによって取得できる情報が異なるらしい。

- `ja.japanese#holiday@group.v.calendar.google.com`: 祝日 + 七五三などのイベント
- `ja.japanese.official#holiday@group.v.calendar.google.com`: 祝日のみ

動作中のGASの祝日取得カレンダーID指定部分を`ja.japanese#holiday@group.v.calendar.google.com`から`ja.japanese.official#holiday@group.v.calendar.google.com`に変えれば問題なさそう。

念の為確認しておこうと下記のようなGASのコードを書いて実行してみた。

```js
function myFunction() {
  const day = new Date('2024-11-15');
  const holidayAndEventCalendar = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
  const holidayCalendar = CalendarApp.getCalendarById("ja.japanese.official#holiday@group.v.calendar.google.com");

  console.log('祝日 + その他の行事カレンダーの2024/11/15のイベント数： ' + holidayAndEventCalendar.getEventsForDay(day).length);
  console.log('祝日カレンダーの2024/11/15のイベント数： ' + holidayCalendar.getEventsForDay(day).length);
}
```

最後のconsole.log部分でエラーになる。なんでだろうと思って遡ってみたら、holidayCalendarがnullになっているっぽい。
どうやら`getCalendarById()`は何らかの理由でカレンダーが取得できなかった場合にnullを返すらしい。（無効なカレンダーIDだったり、権限がなかったり。）

https://developers.google.com/apps-script/reference/calendar/calendar-app?hl=ja#getCalendarById(String)

> カレンダーが存在しない場合は null ユーザーがカレンダーにアクセスできない場合や、ユーザーがそのカレンダーに登録していない場合

自分の環境だと`ja.japanese.official#holiday@group.v.calendar.google.com`のカレンダーIDは使えなかった。。
まあ、自分のGASのコードはただSlackに通知しているだけなのでこのまま誤表示に踊らされっぱなしでも良いかも。

※良く考えたら「誤表示」ではなく「Googleカレンダーの日本の祝日の仕様変更」が正しいかも、、！
[Storybook] インタラクションテストでhooksを使ったらreact-hooks/rules-of-hooksのエラーが出た

## 環境
- Storybook 7.5.3
- React 18.2.0
- eslint 8.53.0

## エラー内容

Storybookでplay関数を使用してインタラクションテストを書く際に、render内でuseStateを使用するコードを書いたら、ESLintの`react-hooks/rules-of-hooks`に関するエラーが出た。

```
React Hook "React.useState" is called in function "render" that is neither a React function component nor a custom React Hook function. 
React component names must start with an uppercase letter. React Hook names must start with the word "use".eslint
```

発生したときのStorybookのコードは以下の通り。

```js

export const ClickTest: Story = {
    render: () => {
        // ESLintのエラー
        const [open, setOpen] = React.useState(false)
        ...
    },
    play: async ({ canvasElement }) => {
    ....
    },
};
 ```


## 解決方法

以下のGitHubのissueを参考に、アロー関数からfunctionに書き換えるとESLintのエラーが解消。

https://github.com/storybookjs/storybook/issues/22593#issuecomment-1552286276

```javascript
export const ClickTest: Story = {
    render: function Render() {
        const [open, setOpen] = React.useState(false)
        ...
    },
    play: async ({ canvasElement }) => {
    ....
    },
};

```
Electron React Boilerplateで、FileProbe(ファイル検索アプリ)作ってみた

## 1. はじめに
#### 目的と背景：

現在参画しているプロジェクトの会社で、すごく便利なファイル検索アプリを使っていたので同じような機能のアプリを作成しました。
以下にインストーラを配置してありますので、常識の範囲でご使用ください。
https://github.com/shouzou-nozaki/FileSearch/tree/main/distribute

## 2. 使用言語等
##### フレームワーク:
Electron、React
#### 言語: 
JavaScript（TypeScript推奨）、HTML、CSS
#### ビルドツール:
Webpack、Babel、Electron Builder
#### ランタイム:
Node.js
#### パッケージマネージャー: 
npm

## 3. アプリの機能設計とディレクトリ構成
#### 作成する機能の概要:

ファイル検索機能
パスコピー機能
#### フォルダ構成：
src/
├── common/
    │   ├── dto/
│   ├── service/
│   └── utils/
├── main/
│   └── utils/
└── renderer/


## 学んだこと：

ElectronとReactの連携やIPC通信の基本的な方法
Electronのセキュリティに関する注意点（contextIsolationやnodeIntegration設定の重要性）

#### 今後の課題や改善点：

ファイル検索の高速化や、非同期処理
GitHubActions 複数の Job で構成する Workflow の実行成否を集約する

GitHubActions で複数の Job で構成される Workflow はよくあるパターンかと思いますが、途中で並列しており、その全ての Job が成功しているか否かの評価を Workflow の一番最後でしたいユースケースがあり、そのときのサンプルを記事として残しておきます。

:::note info
このときは Pull Request のステータスチェックの対象 Job として設定するために作成しました。他にもユースケースはありそうですね。
:::

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2080620/4a0add04-3008-ff69-beef-df1475af1abe.png)

```yml
name: Result check sample

on:
  push:
    branches:
      - "test/**"

jobs:
  initial:
    runs-on: ubuntu-latest
    steps:
      - run: echo "initial done!"

  parallel1:
    needs: [initial]
    runs-on: ubuntu-latest
    steps:
      - run: echo "parallel1 done!"

  parallel2:
    needs: [initial]
    runs-on: ubuntu-latest
    steps:
      - run: echo "parallel2 done!"

  result-check:
    needs: [parallel1, parallel2]
    runs-on: ubuntu-latest
    if: always()
    steps:
      - name: Failure
        if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
        run: |
          echo "Failure"
          exit 1
      - name: Success
        run: echo "Success"
```


### 評価を行う Job

一番最後の **result-check** の Job が評価を行います。
核心部は `if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')` です。

Workflow を構成する Job である initial, parallel1, parallel2 のどこかでエラーまたはキャンセル操作が発生した場合、結果は `Failure` となりエラー終了、全てが成功していると `Success` となり正常終了となります。
この Job は前の Job の成否に関わらず、この Job が必ず実行されるようになっています。

### needs.*.result の評価

`needs.*.result` は、すべての依存しているステップの result プロパティを一覧として取得します。
上記のサンプルでは、`needs.*.result` は [ initialの結果, parallel1の結果, parallel2の結果 ] というリストになります。

### contains(needs.*.result, 'failure') の評価

`contains(needs.*.result, 'failure')` は、リスト `needs.*.result` の中に `failure` が含まれているかどうかを確認します。
依存するステップのうち1つでも `failure` になっていれば、 contains 関数は `true` を返します。
もし、依存ステップのすべてが `success` ならば、この式は `false` になります。

エラー終了したしたとき
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2080620/ad90f349-9181-78cf-e418-2b7a22df2d7e.png)



## ref

- [ワークフロー実行に関するコンテキスト情報へのアクセス - needs コンテキスト](https://docs.github.com/ja/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#needs-context)
【学習】Python3エンジニア認定データ分析試験 


役割と業務内容
---
データサイエンティストの主な業務には、以下のようなものがあります。
- モデルやアルゴリズムの構築
- 新たな解法や新技術の開発や取り組み
- 解決したい課題に対する実務対応
- 分析結果の評価とフィードバック

研究と実務の違い
--

データサイエンティストの役割は、研究分野と実務の場面で重点が異なります。
`研究分野`：新たな解法や新技術の開発が重視されます。
`実務`：解決したい課題に直接向き合い、実務的な解決策の提供が重視されます。

データ分析に使用されるプログラミング言語
--
データ分析のために使用される主な言語には以下があります。
- Python
- R
- Julia
- Excel Visual Basic for Applications（VBA）

Pythonで使用される主要なツール
--
Pythonを用いたデータ分析では、次のようなツールが主に利用されます。
`Jupyter Notebook`：データ分析やモデリングに便利なインターフェイス
`NumPy`：数値計算ライブラリ
`pandas`：データ操作と処理をサポート
`Matplotlib`：データの視覚化ツール
`SciPy`：科学計算向けライブラリ
`scikit-learn`：機械学習のためのライブラリ
ポートフォリオ作成時メモ　part1   ~Laravel Sailプロジェクト作成→Localhost初アクセス~

## はじめに
こんにちは、未経験からエンジニア転職を目指しているものです。
オンラインスクールで本格的に学習して6ヶ月目に入りました。PHP,Laravelを学習しポートフォリオを作成中です。ポートフォリオ作成手順及び、エラー内容を中心に記録していこうと思います。

## PC環境,エディター
- Mac M1チップ　8GB
- Cursor

## 使用技術
**フロントエンド**
- JavaScript
- Tailwind CSS

**バックエンド**
- PHP8.3or8.4 
- Laravel11.23.5

**その他**
- PostgreSQL
- Docker（Laravel Sail）
- Git（Sourcetree）

## ポートフォリオの概要
ポートフォリオタイトル：AcroDance-Comm
AcroDanceCommは、アクロバットやダンスの練習仲間を見つけることができるアプリケーションです。対象ユーザーは20代～30代前半でアクロバットやダンスを始めようと考えている人です。

自身が社会人になりアクロバットとダンスを始めましたが、レッスン会場の大半は子供向けが多く大人が一人で通う事に対して、ハードルがありました。そんな悩みを解決出来るよう、本アプリで練習仲間を見つけられればと考え、作成に至りました。

## Laravel Sailでプロジェクト作成
Docker Desktopはインストール済みであり、Laravel sailを使用。
cursorのターミナル上で、以下のコマンドを入力し新規プロジェクト作成
```
curl -s https:://Laravel.build/AcroDance-Comm | bash
```
無事にプロジェクトが立ち上がり、以下のコマンドを実施しlocalhostへのアクセスを試みる
```
./vendor/bin/sail up
```
しかし、添付のエラーが発生。

![localhost screen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846051/e653974a-0f61-c9a4-f7ae-b306150e5019.png)

## エラー対応
laravel.logに記録された内容を確認。

原因：
Laravelがセッションデータを保存するための「sessions」テーブルをデータベースに見つけられないために発生。Laravelがデータベースをセッションストレージとして使用している場合、sessionsテーブルを事前に作成する必要がある

解決策：
マイグレーションファイルの実行
Laravelにはsessionsテーブルを作成するためのマイグレーションが含まれています。以下のコマンドを実行して、sessionsテーブルをデータベースに作成します。

```
./vendor/bin/sail artisan migrate
```
結果：
添付のようにlocalhostへアクセス出来ました
![laravel acsse successfully.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846051/209adecc-af63-87e1-09c9-e14e00baa18a.png)



## 次回実施内容
- データベース接続設定(PostgreSQL)


最後までご覧いただき本当にありがとうございました！！
初心者プログラミングバイト生活14日目【】

今日は、引き続きの勉強っていう感じで、特に何かしたとかでもないかな。

ただ、プログラミングの速度が上がってるのが分かるのが良い。

初バイトの給料で、冷蔵冷凍庫と服とかを買った。

楽しみ。
The Future of DC Charging: Insights from Industry Leaders


Along with the growth of the EV market, their charging technology is a core determinant in shaping the future of sustainable transportation. So, one of the most significant advancements is a DC charger that has already transformed the way we power up an electric vehicle by drastically reducing its charging time. But what's next for this DC charging technology? In this article, we ask leading industry execs to highlight which upcoming trends and technologies are set to shape electric mobility's next chapter.

Expert Predictions: What's in Store for DC Chargers

Ultra-Fast Charging Speeds
The next generation of DC chargers will push that boundary even further. We are working on prototypes that will be able to pump out as much as possible. Possibly, this is going to bring down the charging time.

     2. Integration with Renewable Energy
In the future, DC chargers will be increasingly fed by renewable energy sources. That means we're building smart DC chargers capable of dynamic adjustment in charging rate according to how much solar and wind feed is available on the platform. This not only reduces the carbon footprint of EV charging but also helps stabilize the grid.

      3. Urban Integration and Aesthetics
As more and more DC chargers are installed within city limits, they will continue to adapt in both form and function. More aesthetically pleasing, space-saving DC chargers will also be able to be integrated into city environments. Think sleek and durable DC charger designs make them more attractive and innovative. 

The Impact on EV Adoption and Infrastructure
These are the advances in DC charger technology that could make all the difference in EV adoption and infrastructure.

Range Anxiety Elimination: Ultra-fast DC chargers will make EVs accessible for all drivers, including those who have no options for home charging.
Expanded Charging Networks: As the times of charging continue DC chargers will be able to serve increasingly large numbers of EVs and allow networks to be more extensive.
Improved sustainability: Renewable energy will provide a considerable reduction in carbon footprint for EV charging. Improved User Experience: 

Conclusion: A Future Powered by Innovation
Bright mornings are changing to bright futures of DC chargers, where innovations continue to make charging quicker, more efficient, and available anywhere. From higher power output and energy efficiency at the station to wireless charging, the roadmap of the evolution of DC chargers will be a leading contributor to the wide-scale adoption of electric cars. With leading companies continually breaking new ground, DC chargers are set to turn a corner in the world's march toward clean, sustainable transportation.

Stay tuned as these breakthrough developments continue to unfold and draw us closer to the complete electrification of the future.
Gigde: Your Go-To Digital Marketing & Top SEO Agency

Gigde: Your Go-To Digital Marketing & Top SEO Agency
Gigde is recognized as a <a href="https://www.gigde.com/blog/top-seo-agency">Top SEO Agency</a>, known for driving measurable success for businesses through tailored digital marketing solutions. With expertise across SEO and content marketing, Gigde ranks among the <a href="https://www.gigde.com/blog/top-seo-agency">Top SEO Firms</a> and is trusted by clients to deliver results that elevate brand visibility, boost traffic, and increase conversions. As a leader in digital marketing, Gigde provides not only the Top SEO Service but also outstanding content solutions, earning its place among the Top Content Writing Agencies.

Gigde’s SEO services focus on advanced keyword strategies, quality link building, and technical optimization that propel clients to the top of search rankings. Their reputation as the Best SEO Service stems from a commitment to transparent, data-driven methods that generate long-term growth. Recognized as one of the <a href="https://www.gigde.com/blog/content-writing-services">Top Content Writing Services</a>
, Gigde also offers comprehensive content marketing, designed to engage audiences and establish authority within any industry.

As one of the Best Content Writing Agency options available, Gigde offers high-quality writing services, from blog content and web copy to product descriptions and social media posts. They are considered a <a href="https://www.gigde.com/blog/content-writing-services">Top Content Firm</a> for their commitment to delivering engaging, optimized content that enhances brand messaging. As a trusted partner for businesses of all sizes, Gigde is known as one of the Best Content Companies, providing end-to-end digital solutions.

For companies seeking both Top SEO Service and quality content, Gigde is the ideal choice. With a proven track record as the Best Content Writing Company and Top SEO Agency, Gigde is dedicated to helping brands succeed in the digital landscape, ensuring each client achieves a strong online presence and sustainable growth.
XLibでマウスの位置を右下に移動する。

# マウスを見えない位置に移動したい！
ラズベリーパイでデジタルサイネージを作ったりすると、間抜けなことにマウスが表示されていることに気づいたので、XLibを使ってマウスを右下に移動するプログラムを作ってみました。

もちろんX-WindowはLinuxベースなので、Linuxベースのシステムであれば動作します。

# 必要なもの
root権限で以下のライブラリをインストール
apt install libx11-dev

# ソース
``` mld.c
#include <stdio.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

int main()
{
	Display *d;
	int wx,wy;
	// Open Display
	d=XOpenDisplay(NULL);

	if (d != NULL) {
		// Get screen width and height
		wx = WidthOfScreen(XDefaultScreenOfDisplay(d));
		wy = HeightOfScreen(XDefaultScreenOfDisplay(d));
		// Move mouse pointer
		XWarpPointer(d, None, DefaultRootWindow(d), 0,0,0,0,wx,wy);
		XFlush(d);
		// Close Display
	} else {
		printf("Can't Open Display!!\n");
		return 1;
	}

	return 0;
}
```

# コンパイル方法
ソースはこれだけなのでMakefileなどは必要ない！

cc mld.c -o mld -lx11

でmldというコマンドが出来上がります。
xwaylandでも動くのかは不明？

誰かやってみた人は、コメントで教えてください！お願いいたします。
スクレイピングした時に表示を待ってから値を取得する

# はじめに

こんにちは、エンジニアのkeitaMaxです。

今日はPythonとSeleniumでスクレイピングをしたいた時の話に、画面が表示されるまで待ちたい時の話です。


# 内容

画面が表示される前に文字列などを探してしまうとエラーになってしまいます。

その時は以下のようにWebDriverWaitを入れるといいです。

```python
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.XPATH, "//div[@class='button']")))
element.click()
```

こうすると表示されるまで10秒待ってくれるので、エラーにならずにスクレイピングができます。

`sleep(10)`
を入れてもいいかもしれませんが、こちらは時間経過で本当に表示されているかの保証がないため、WebDriverWaitを使った方が確実かなと思います。

# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://www.selenium.dev/ja/documentation/webdriver/waits/
もう個人利用は危険？ 生成AIを安全に活用するためのエンタープライズ導入

## はじめに

本資料は、生成AIの導入を検討する企業が、自社の状況に合わせて判断するための材料を提供することを目的とする。
生成AI元年と言われる2023年を経て、生成AIは急速に普及し、私たちの生活や仕事に浸透しつつある。
本資料では、生成AIの概要、エンタープライズ導入のメリット・注意点、主要なエンタープライズ向け生成AIツールなどを体系的に整理し、導入の判断材料となることを目指す。

## 1 現場で起きていること - 生成AIの利用拡大

* 生成AIツール (ChatGPTなど) の利用が急速に拡大
    * 「ググる」感覚でChatGPTを利用する人が急増
* 高度な機能が登場
    * ChatGPT-4oでは**添付ファイル**も利用可能に
    * (画像やPDFなどをChatGPTにアップロードして活用するイメージ)
* 個人利用から業務利用へ
    * ChatGPTを個人で有償契約し、業務用途で利用しているユーザーも
    * (社内アンケート結果などを示す)

## 2 「ググる」を進化させる生成AI - ChatGPTができること

従来の検索エンジンと生成AIの違いを以下に示す。

| 機能 | 従来の検索エンジン | 生成AI (ChatGPTなど) |
|---|---|---|
| 入力形式 | キーワード | 自然言語 |
| 出力形式 | ウェブページのリスト | 自然言語による回答、文章、コードなど |
| 情報収集 | 受動的 (情報を探す) | 能動的 (対話を通じて情報を得る) |
| 利点 | 膨大な情報にアクセス可能 | 人間らしい対話、文脈理解、創造的なタスク |
| 欠点 | 情報過多、ノイズが多い | 精度、倫理的な問題 |

ChatGPTは、まるで「ググる」ように、様々な質問に答える。

* 例：「明日の大阪の天気は？」「円ドルの為替レートは？」「最新のAI技術トレンドは？」

さらに、ChatGPTは「ググる」以上のことができる。

* **自然な文章で質問**: キーワードではなく、自然な文章で質問することができる
* **会話形式で情報収集**: 対話を通じて、より深い情報を得ることができる
* **要約、翻訳、文章作成**: 長文の要約、多言語への翻訳、文章作成などを支援してくれる
* **アイデアの提案**: 新しいアイデアを提案したり、問題解決のヒントを与えてくれたりする
* **コード生成**: プログラミングのサポート、コード生成、デバッグなどを支援してくれる

**具体的な例**

* **従来の検索**: 「大阪 天気」とキーワードを入力
* **ChatGPT**: 「明日の大阪の天気はどうですか？気温や服装のアドバイスも教えてください。」と自然な文章で質問

このように、ChatGPTは従来の検索エンジンよりも、より人間に近い形で情報収集や問題解決を支援してくれるツールと言える。

ChatGPTは、様々な業務で「ググる」を進化させ、効率化を実現する。

* **営業**: 顧客情報や市場動向を迅速に把握
* **マーケティング**: 競合分析、コンテンツ作成
* **カスタマーサポート**: 問い合わせ対応、FAQ作成
* **人事**: 採用情報作成、面接準備
* **開発**: 技術情報収集、コード生成
* **経理・財務**: データ分析、レポート作成
* **法務**: 契約書作成、法令調査

ChatGPTは、単なる情報検索ツールではなく、ビジネスの様々な場面で活用できる可能性を秘めている。
「こんな便利なツールを、業務で使わない手はない。」  
そう考えるユーザーが、今後ますます増えていくことは間違いないだろう。

## 3 エンタープライズ導入のメリット - セキュリティと管理

* **セキュリティ強化**
    * アクセス制御 (IPアドレス制限、多要素認証など)
    * データ暗号化 (保存時/通信時の暗号化)
    * ログ管理 (ユーザーの操作ログ記録)
    * 企業レベルのセキュリティ対策で情報漏洩リスクを軽減
* **コンプライアンス遵守**
    * 個人情報保護法、GDPRなどへの対応
    * 監査証跡の記録、データの保持・削除など
* **管理機能の充実**
    * 利用状況の監視、ポリシー設定、ユーザー管理
    * 企業全体での利用状況を把握し、適切な管理が可能
* **サポート体制**
    * 企業向けのサポート窓口、SLA (サービスレベルアグリーメント)
    * 導入から運用まで、専門家によるサポート

## 4 主要なエンタープライズ向け生成AIツール

* **ChatGPT Enterprise**
    * 高度な自然言語処理、多様な業務への対応
    * エンタープライズグレードのセキュリティ
    * 詳細な管理機能
    * (具体的な機能、セキュリティ対策、価格などを詳しく解説)
* **Copilot for M365**
    * Microsoft 365 アプリケーションとの統合
    * 日常業務の効率化
    * (具体的な機能、Microsoft 365 との連携、価格などを詳しく解説)


## 5 生成AI導入における注意点 - リスクと課題

* **情報漏洩**
    * 機密情報の取り扱い、アクセス制御
* **コンプライアンス違反**
    * 著作権、個人情報保護
* **倫理的な問題**
    * 差別、偏見、フェイクニュース
* **コスト**
    * 導入費用、運用費用
* **人材育成**
    * AIリテラシーの向上
* **精度と信頼性**
    * 生成AIの出力の精度、バイアス、事実と異なる内容の生成
    * (例：存在しない書籍や論文を生成、事実とは異なる歴史を記述)

## 6 生成AI導入の検討ポイント - チェックリスト

* 導入目的、KPI設定、達成目標
* ツール選定 (ChatGPT Enterprise / Copilot for M365)
* 費用対効果の評価
* セキュリティ対策、コンプライアンス
* 従業員教育

## 7 まとめ

* 生成AIは、企業の成長を加速させる強力なツール
* エンタープライズ版導入により、安全かつ効果的に活用

## 参考資料

* ChatGPT Enterprise (2023年8月発表)
* Copilot for Microsoft 365 (2023年11月1日一般提供開始)
* OpenAI のプライバシーポリシー
* Microsoftの利用規約
* 生成AI導入事例

---

**注記**

* 各項目に、図表やグラフなどを効果的に利用して、視覚的に分かりやすくする
* 経営層が理解しやすい言葉で記述
* 最新の情報を盛り込み、信頼性を高める
* 必要に応じて、具体的な事例やデータなどを追加する

---

Powered by Gemini Advanced
GitとGithubについて（関係、違いについて）

先日もGitについて、記事を書いたけど、今回はGitとGithubの関係について、少し理解を深めたくなったのでちょっと勉強しました。

たとえば複数人が一つのPCで作業するときに、Gitを使ってメインからブランチを作成することで、それぞれのブランチで作業して、マージすればメインに統合することができる。インターネットにつなぐ必要がなく、Gitで完了する。

でも、別々の場所で作業（例えばテレワークなど）で一つのPCを共有できないときに、GIthubを使えばオンライン上でGit情報共有できて、オンライン上でブランチを作成し、それぞれのローカルで作業した後、またGithubでマージすればメインに統合できる。

Gitはオフラインでも使うことができ、Gitをオンラインで管理するというのがGithubという認識になりました。GitとGithubは違うもの、ということはわかっていましたが、具体的にどう違う、という説明はうまくできないと思っていたので少し理解が進みました。

Gitが登場した経緯についても知りたくて、バージョン管理ツールの歴史についても軽く調べてみましたが、まだ自分の中でしっくりきていないので、初心者なりに理解できるようになったらまた記事を書きたいと思います。
p.12ファイルが登録できなかった時の解決方法

## 概要
今回、Apple Silicon (M1)のmacでp.12ファイルを登録しようとするとエラーになってしまい登録できない状況になったため、解決した手順を記載します。
![スクリーンショット 2024-11-14 19.32.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2669177/5f91fd69-7141-2c6f-bc2a-31b7b4fd79bc.png)

## 参考記事
- [PKCS #12 個人情報交換ファイルフォーマットについて](https://qiita.com/kunichiko/items/3e2ec27928a95630a73a)

調査の際、
p.12ファイル・証明書について上記のサイトに大変お世話になりました。
ありがとうございます！



## 作業した流れ
### 1. .p12 ファイルを.pem に変換しようとしてみた
下記のコマンドを実行し、.p12 ファイルからプライベートキーを抽出して.pem 形式で保存できるかやってみます。

```bash
openssl pkcs12 -in /hoge/sample.p12 -out /hoge/privatekey.pem -nodes
```

すると、下記のようなエラーメッセージが表示されました。
```bash
Error outputting keys and certificates
008C7CF601000000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:355:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()
```

メッセージ内容的には、RC2-40-CBCアルゴリズムが原因で問題が発生しているとのことです。

### 2. ```-legacy```オプションを使ってみる
pkcs12コマンドで RC2-40-CBCアルゴリズムを避けるために、```-legacy```オプションを使うことで、古いアルゴリズムをサポートすることがあるとのことでした。

なので、先ほどのコマンドの後ろに```-legacy```オプションをつけて、再度実行します。

```bash
openssl pkcs12 -in /hoge/sample.p12 -out /hoge/privatekey.pem -nodes -legacy
```

### 3. pemファイルが生成される
指定したフォルダにprivatekey.pemが生成されたので、こちらをダブルクリックすると無事にキーチェーンアクセスに登録することができました！

## 最後に
上記の作業をされる前に、OpenSSLの設定を見直したりバージョンを最新にしたりするのも、手段の一つとして試してみていただければと思います！
UltralyticsのDiscordで質問したら叱られた話（Ultralytics YOLOv8 imgszについて）

前半はポエムです。
```imgsz```について早く知りたい方は後半からどうぞ。

## UltralyticsのDiscordで質問をしたら、叱られた！
私もいい大人なのに、見事に叱られました。
Ultralytics YOLOv8を利用して、物体検出のアプリを作成しています。

https://qiita.com/calcMCalcm/items/178901c752f6cef481f1

物体検出できている時は良いのですが、学習が不十分なのか、周囲の環境の影響か認識できないこともあり、その場合は検出/不検出とでチラチラと点滅するような挙動になってしまいます。
直前のフレームでは検出できているので時間軸を考慮した検出ができないか？と考えました。
パラメータに```augment```というものがあり、時間という言葉が見えたので時間軸を考慮したものか？と思い試していたのですが、イマイチ効果を体感できません。（処理が遅くなったので動作はしていた）

https://docs.ultralytics.com/modes/predict/#inference-arguments

作成しているアプリでは動画ファイルをフレーム単位で処理対象としていますが、ultralyticsでは動画ファイルそのものを読み込んだり、youtubeのアドレスも処理対象として扱えます。
- もしかしてフレーム単位だとaugmentは機能しないのかな？
- もしそうなら、ultralyticsのDiscordで相談したら、いい案を教えてくれるかも？

と思い、早速ultralyticsのDiscordに参加しました。

質問ややり取りは、google翻訳を利用して言いたいことになってそうなことを確認してコピペ。
augmentについて質問したところ、
「augmentに時間軸というような機能はないよ（意訳）」
ということでした。
私は検出精度をあげかったので、どうすればいいだろう？とアドバイスを求めたところ、どんなコードで検出しているのか？と問われ、
```
results = model.predict(source=rsz_frame,conf=score,device=device,imgsz=int(w*0.5),show_labels=False,show_conf=False,show_boxes=False,augment=False,stream_buffer=False)
```
「入力画像をリサイズしているのか？？なんで？？？ultralyticsが自動でするのに？（意訳）」
いや、その方が処理速度が速かったから・・・
「元の画像の解像度は？（意訳）」
「学習に利用しているデータの解像度は？それもリサイズしてるの？（意訳）」
「学習時の```imgsz```は？」
順に回答する私。
「はー・・・（頭を抱える（想像）」
えーと、わたしはどうすれば・・・

私が行っていた処理は次の通りです。
- 私は2560x1080の画像を50%に縮小し、学習させていました（1280x540）
- ```imgsz```は入力画像の解像度と思っていたので、学習時は```imgsz=1280```としていました
- 物体検出をするフレーム切り出し時は元の解像度（2560x1080）ですが、50%リサイズしたものも準備します
- リサイズした画像をyolov8に渡し、```imgsz```は、元解像度の50%としています（1280）
- yolov8で検出した座標を1/0.5で割り戻して、元の画像に当てます

## Ultralytics YOLOv8 imgszについて
「ok、わかった！キミは次の通りにしろ！（意訳）」
>Don't resize your training dataset
>Don't resize the images you inference with
>Put imgsz=1280 for both training and inference

```imgsz```は、入力画像の解像度だと思い込んでいましたが、**正確にはYOLOv8に取り込む際の解像度**になります。
デフォルト値は```imgsz=640```となっており、**どのような解像度のデータが来ても**、YOLOv8に取り込む際に自動的に640x640にして、学習や推論を行います。
つまり私はUltralytics YOLOv8側でいい感じに縮小処理してくれるものを、わざわざ外で処理していたことになります。
また、学習においてもわざわざ縮小していましたが、これも本来は不要で、処理速度や精度が満足できるだけのimgszを設定するのが正解でした。
例えば、元画像が1024*1024で、処理速度の向上を図りたいのであれば、極端にいえば、```imgsz=100```（100x100）というように縮小した状態で、学習、推論させればいいわけです。
但し```imgsz```を小さくしすぎると、画像は潰れてしまうので検出や学習ができない場合が増えてくるだろうと思います。
元画像の解像度より```imgsz```を大きくするなという話は別のやり取りで見ました。恐らく空白で不足部分を埋めてYOLOv8に渡されるのではないかと思います（確認してません）

私が利用しているのはYOLOv8ですが、YOLOv10やYOLOv11においても同様だと思います。
物体検出以外でもパラメータが```imgsz```であれば、同じような考え方だろうと想像します。

## その他、感想とか。
- Ultralyticsは、使う側に寄り添った痒い所に勝手に手が届く作りになってるなーと思っていましたが、今回の出来事でますますその印象が強くなりました。すごく簡単！
- 自前リサイズと、Ultralyticsにおまかせリサイズでは、Ultralyticsおまかせの方がやや速かったです
- 別のOSSでgithub issueを起票したこともあるのですが、正直自分のスキルレベルから考えるとかなりハードルが高いと感じていました。（英語、内容の正誤、忙しいメンテナ、いつ手をつけるのだろう？直してもらえるのかな？などなど）
Discordでの問い合わせややり取りは、google翻訳の力を借りれば、意外とイけるなと感じました（ただ事前に英語は苦手でgoogle翻訳使ってます、と前置きはしてます）
- いい大人なのに根本的な内容で叱られると結構堪えます。気を付けよう！
GitHub Copilotは何がすごい？

# はじめに
先日、苦戦した「GitHub Education」への申請が完了し、晴れていろんな特典を受け取ることができました。（特典については他の方の記事を参考にしてください。）しかし、``Pro``マークがついても特にやりたいことはなかったので、なんとなく楽しそうな「GitHub Copilot」を使ってみることにしました。
そこで思ったのが、「別にChatGPTとかで良くない？」です。いまいち強みを実感することができなかったので、今回の記事では「GitHub Copilot」の強みをまとめてみました。参考になれば幸いです。
では、まずは概要から紹介していきます。

# GitHub Copilotの概要
GitHub CopilotはMicrosoftとOpenAIが共同で開発した、AIによるコード補完、生成機能をもったAI開発支援ツールです。この２つの機能以外にもチャット機能も持っています。ちなみにですが、あくまでプログラミングに秀でたものなので、ChatGPTのように雑談に対応することはできません。（下のようにふられます。）

![スクリーンショット 2024-11-13 155421.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817741/c9f3e90c-a2da-e11b-de88-3a440121e3f2.png)

:::note info
ただし、 **プログラミングに関連した雑談**（おすすめの言語やプログラミングをするにあたってのお悩み相談など）は可能です。
:::


OpenAIが開発に携わっていることもあり、学習モデルには現時点で最新の大規模言語モデル(LLM)である ``GPT-4``を使用しています。ただ、だからといってChatGPTと同じ中身なのかというとそれは誤りです。
GitHub Copilotは<strong>GitHub上のパブリックリポジトリからも学習しており、</strong>前述したようにコード補完や開発者支援に特化している点がChatGPTとは異なります。
下のように各開発環境用のプラグインが用意されており、それをインストールして、GitHub Copilotの機能を使用することができます。
<ol>
<li>Visual Studio Code
<li>Neovim
<li>IntelliJ IDEA
<li>WebStorm
<li>GoLand
<li>PyCharm
</ol>

# GitHub Copilotの強みとは
### 多くの言語、フレームワーク・ライブラリに対応している
以下に対応しているものをまとめます。
#### 言語
Python、JavaScript、TypeScript
Java、C#、Go、Ruby、PHP、Swift、Kotlin
#### Web開発
HTML、CSS
#### フレームワーク・ライブラリ
* **フロントエンド**
React、Vue.js、Angular、Svelte、Bootstrap、
Material Design、Next.js、Nuxt.js、Gatsby、Tailwind CSSなど

* **バックエンド**
Node.js、Django、Flask、Spring Boot、ASP.NET Core、Laravel、Ruby on Rails、Goなど

* **その他**
機械学習 (TensorFlow、PyTorchなど)、
データ分析 (pandas、NumPyなど)、
DevOps (Ansible、Terraformなど)

それに加えて、定期的にGitHub上の膨大な公開リポジトリを学習データとして更新されていくため、比較的新しいライブラリやバージョンに対応することができます。十分な情報を書けば、ある程度複雑なものにも対応できるそうです。

### コード補完機能が優れている
この記事では「コメントによる指示」、「チャットでの直接的な質問」を取り上げます。
#### コメントによる指示
ソースコード内のコメントに支持を記述するとそれに合ったソースコードを提案してくれます。下のコードは全て補完機能により作られたものです。

![スクリーンショット 2024-11-14 183350.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817741/9bbbbbbe-d08e-2853-1d45-eef4e9c4323d.png)

#### チャットでの直接的な質問
ソースコードを書いていて疑問が生じた際は適宜質問することができます。もちろん、エラー対処にも対応しています。

![スクリーンショット 2024-11-14 184100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3817741/e9996776-10a5-03fb-7ba1-55397c79a4b4.png)

### 補完サポートが強力である
GitHub Copilotは、開発者が利用する言語やフレームワークに応じた補完だけでなく、**複数のモジュールや依存関係を理解し、それらに適したコードを提案する**点で、他のツールと比べて優れています。
たとえば、プロジェクト内の関数やクラス定義を把握し、それに沿った補完を行うため、複雑なコードベースでも的確な補完が可能です。

# おわりに
今回の記事では、GitHub Copilotについて概要を紹介した後、他の類似サービスと比較したときの強みについて扱いました。今回取り上げた点以外にも多くの魅力があるので
、ぜひ使ってみてはいかがでしょうか。
特に、学生の方は「GitHub Education」に登録すればこのサービスを無料で利用できるのですごくおすすめです。
ただ、これは他のサービスでもいえることですが、GitHub Copilotの提案が最適であるとは限らないという点に注意です。自分でやるところはやって、任せられるところはやってもらうという姿勢を大切にしていきましょう。
では、今回の記事はこれで終わりです。最後までお読みいただきありがとうございました。

# 参考

https://docs.github.com/ja/copilot/about-github-copilot/what-is-github-copilot

https://aadojo.alterbooth.com/entry/2024/01/24/182423

https://qiita.com/zutoasa/items/7c5516cb379dddb2b701

https://qiita.com/yoda_naan/items/a5c53acc790586cd4fd9

https://qiita.com/sublime_otsuka/items/f8e3e1e4e576fe150dad
Data+AI World Tour Tokyo 2024.11.14 参加レポート

Databricksのイベントに初めて現地参加させていただいたので、参加レポートを残したいと思います。興味はあるが勇気がなく参加をためらっている方々にとって、不安や懸念の払拭になれば幸いです。内容に関しては、記憶だけを頼りに記載していますので、誤りや理解不足がある可能性があることを予めご了承願います。（録画や録音はNGでした。）

# 参加日時と場所
日時：2024/11/14(木) 10:00～14:30(※)
　　　※私が参加した時間帯です。実際は、懇談会まで含めると20:00までになります。
場所：ANAインターコンチネンタルホテル東京

# 参加セッション・他
### 1. 受付 10:00～
　想像以上に参加人数が多く、10時頃到着すると、受付には長蛇の列ができていました。少し遅れて10時開始のセッションに参加できるかと思いきや、全くそんなことはなく、むしろ自分に割り当てられたプリンターに不具合があったようで、さらに待たされ、結局入場できたのは10:30頃でした。
 
### 2. D-2 データブリックスセッション 10:55～
#### 「エージェントフレームワークを使用した本番品質のGen AIアプリケーションの構築を詳しく見る」
　前段が10分遅れで開始したため、本セッションも10分押していました。セッションの方も想像以上の盛況ぶりで立ち見の方もいらっしゃいました。会場に入るためにQRコードをチェックされるため、ここでも列に並ぶ必要があり、開始時間直前にアクセスしても間に合うオンライン参加しかしたことのない私には新鮮でした。
　さて、肝心の内容です。RAGの課題として、どのように精度をあげたらいいか分からない、そもそも精度をどのように測ればいいか分からないといった課題があり、そこに対してDatabrickは「評価ドリブン」という戦略をとっているというお話でした。作成したRAGアプリをテストし、その結果を評価するための機能が用意されています。評価を実施すると評価データが生み出され、精度が低ければ、そこに対する原因と、より精度をあげるためにはどうすればよいかアドバイスをもらえます。

### 3. ランチタイム 11:30～
　受付するまで知らなかったのですが、イベントではランチボックスが無料で提供されました。一人一枚ランチ券をもらえるので、決められた時間に所定の場所に行けば、サンドイッチやおにぎり等と引き換えることができます。また、マフィンやクッキー等のスイーツや、コーヒーやソフトドリンクの提供もありました。これは嬉しかった！！

### 4. D-4 スポンサーセッション 12:15～
#### 「リコージャパン18,000名の活動を支えるデータ基盤 構想から拡大/定着化までの道のり」
　リコーさんは当初AWSでデータアーキテクチャを組んだものの、ユーザが増加するにつれコストが増大し、そこを解決するために、ETL処理をDatabrickに置き換えたというお話でした。なお、将来的には、BIツールやAIの導入も見据えているということでした。コストを抑えるためにDatabricksをETLツールとして導入するという事例は、あまり考えたことがなかった内容だったので勉強になりました。毎度の基調講演で強みとして紹介されているDatabricksのコスパの良さが生きたのだなと感じました。

 ### 5. K-1 基調講演 13:00～
 　入場時に、同時翻訳スピーカーの貸出がありました。これも初めてだったので新鮮！実際に使用したのは、Databricks COO 様のスピーチの時だけでした。ルネサスの登壇者も海外の方でしたが流暢な日本語でスピーチされていました。スピーカーの使い心地は全く問題なく、ストレスなく内容が聞き取れました。
　
##### ①イオンフィナンシャルサービス株式会社　導入事例
　イオンの登壇者が欠席とのことで、Databricks社長の笹さんが代理で説明されていました。マルチクラウドに散在しているデータをとりまとめ、グループ会社等に提供できるようにしたという内容でした。

##### ②Genieのデモ
　GenieはCopilotのような対話型AIで、ユーザの質問を受けたらデータを探しにいき、必要であれば集計等を行い、適切なデータを回答してくれる機能。今までのDatabricksアシスタントがSQLやコード生成をするまでにとどまる機能だったのに対し、Genieは答えまで出力してくれます。デモでは適切な回答が返され、かなり期待ができる機能ではありますが、Databricksアシスタントが生成するSQLがいまいち惜しいものだった経験を思い出すと、Genieの精度も試してみないと何とも言えないなーというのが感想です。

##### ③NTT株式会社　導入事例
　NTTでは、tsuzumiというLLMを開発・提供しているが、一部にMosaic AIを導入しているというお話でした。tsuzumiプロジェクトでは、１つの大きなLLMを作るのではなく、小さな複数の専門性をもったLLMを作ることを目指しているとのこと。

##### ④AIエージェントとDatabricks Appsの紹介
　AIエージェントは、ユーザからの質問を分析し、必要なファンクションを選択し、それらを組み合わせて適切な回答を作り上げる機能。Gen AI は、LLMのみ→RAG→AIエージェント、と進化しています。
　Databricks AppsはDatabricks初のフロントエンドを提供する機能。Databricks Appsを使用してAIエージェント機能をユーザに提供することができます。

##### ⑤ルネサスエレクトロニクス株式会社　導入事例
　直近10年ほどで多くの企業を吸収・合併したため、各企業それぞれのデータ基盤が寄せ集められ、ユーザ数も増加したため、データ基盤統一のためにDatabricksの導入に踏み切ったというお話でした。要件定義から本番稼働までなんと１年という速さには驚きです。特に力を入れたのは社内ユーザの教育ということです。Databricks社に構築を任せるのではなく、あくまで内部の社員が作るということに重きをおき、Databricks社員にはサポートにまわってもらったといいます。確かに、Databricksを使いこなすのはハードルが高いので教育は必須かもしれません。Databricks社とユーザ企業が直接タッグを組む事例を聞きながら、パートナー企業としての自分には何ができるのか、考えさせられました。。。

### 6. 退場 14:40～
　小学生の息子たちが帰宅してしまうので、ここで退場。初めての現地参加、色々と勉強になりました。ありがとうございました！
watsonx.ai/mistral large2で同義語を生成

```python: test.py
# %%
import sys
from langchain_ibm.llms import WatsonxLLM
from langchain_core.prompts.prompt import PromptTemplate
from langchain.chains.llm import LLMChain

# %%
keyword = sys.argv[1]

# %%
model_id = 'mistralai/mistral-large'
project_id = '<PROJECT_ID>'
url = 'https://us-south.ml.cloud.ibm.com/'
apikey = '<APIKEY>'
params = {
    'decoding_method': 'greedy',
    'max_new_tokens': 16384,
    'min_new_tokens': 1,
    'repetition_penalty': 1.02,
    'stop_sequences': ['
']
}
llm = WatsonxLLM(
    model_id=model_id,
    project_id=project_id,
    url=url,
    apikey=apikey,
    params=params
)

# %%
template = """


### 指示：
あなたは物質材料の専門家です。
質問に対して、形式に従って回答して下さい。

### 形式：
{keyword},類義語1,同義語2,同義語3,同義語4,同義語5,同義語6,同義語7,同義語8,同義語9,同義語10

### 質問：
{keyword}に関する英語の同義語を最大10個まで出力して下さい。



{keyword},"""

# %%
prompt = PromptTemplate(template=template, input_variables=['keyword'])
chain = LLMChain(llm=llm, prompt=prompt)

# %%
response = chain.invoke(input={'keyword': keyword})
answer = response['text']
print(keyword, answer, sep=',')

# %%
```

```bash
$ python test.py アルミニウム
ルミニウム,aluminum,aluminium,Al,aluminous,aluminiferous,aluminic,aluminous
```
特定スキーマ以下のカラムにTAGがついているテーブルを取得する

## やりたいこと
カラムにTAGが付与されているテーブルをリストアップする

~~半分以上は以前のLAST_QUERY_IDをとってUNIONするというネタそのまま~~


TAG状況を確認したい時、カラムレベルのタグを確認する場合は
https://docs.snowflake.com/ja/sql-reference/functions/tag_references_all_columns

こちらの関数で取得することになりますが


この関数はテーブル一つ一つに対して実行するので、複数テーブルの確認をするには少し不便。

毎回テーブルごとにクエリ投げるのも、Snowsightからみるのも手間だったので
スキーマレベルで一括で取得できるストアドを作成しておく
(DBレベルだとちょっとテーブル数多くなりすぎるのでスキーマで切れる様に制限をつける）

### 処理概要

1. スキーマ以下のテーブルをINFORMATION_SCHEMAから取得

1. テーブルを片っ端からTAG_REFERENCES_ALL_COLUMNSにかける
(この際、カラムに付与されているタグ分行が増えるので、ARRAY_AGGでグルーピング)

1. ↑のQUERY_IDをLAST_QUERY_IDから取得し、ARRAYに保存

1. QUERY_IDのARRAYをFLATTENし、行に復元結果をSELECTする

1. QUERY_IDごとにRESULT_SCANしつつUNIONするクエリを作成

1. 実行して結果をTABLEとしてRETURN

### というわけでストアド

```:SQL
WITH GET_TAG_TABLE_ON_SCHEMA AS PROCEDURE ( TARGET_SCHEMA TEXT )
    RETURNS TABLE()
    LANGUAGE SQL
AS
$$
    DECLARE
        TABLE_RESULT RESULTSET;
        --INFOMATION_SCHEMAからテーブル取得するクエリ
        GET_INFO_QUERY TEXT DEFAULT 'SELECT CONCAT_WS(''.'',TABLE_SCHEMA,''"'' ||TABLE_NAME||''"'') as FULLPATH,TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME
            FROM TESTDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ?';
        QUERIES ARRAY DEFAULT [];
        RS RESULTSET;
    BEGIN
        TABLE_RESULT := (EXECUTE IMMEDIATE :GET_INFO_QUERY USING( TARGET_SCHEMA ));
        LET TABLE_CUR CURSOR FOR TABLE_RESULT;
    
        FOR T IN TABLE_CUR DO
            LET TFN TEXT := T.FULLPATH;

            --INFOMATION_SCHEMAから取得したテーブルについてTAG情報を取得
            LET QUERY TEXT := 'SELECT OBJECT_DATABASE,OBJECT_SCHEMA,OBJECT_NAME,COLUMN_NAME,ARRAY_AGG(TAG_NAME) FROM TABLE(TESTDB.INFORMATION_SCHEMA.TAG_REFERENCES_ALL_COLUMNS(''' || :TFN || ''', ''TABLE'')) GROUP BY ALL';
    
            EXECUTE IMMEDIATE :QUERY;
            QUERIES := ARRAY_APPEND(:QUERIES,LAST_QUERY_ID());
            
        END FOR;
    
        IF (ARRAY_SIZE(:QUERIES) > 0 ) THEN
            LET Q_RS RESULTSET := (SELECT VALUE FROM TABLE(FLATTEN( INPUT => :QUERIES)));
            LET Q_CUR CURSOR FOR Q_RS;
        
            LET GET_LIST_QUERY TEXT := '';
        
            FOR QID IN Q_CUR DO
                LET Q TEXT := QID.VALUE;
                IF (GET_LIST_QUERY != '') THEN
                    GET_LIST_QUERY := GET_LIST_QUERY || '\n UNION ALL \n';
                END IF;
    
                GET_LIST_QUERY := GET_LIST_QUERY || 'SELECT * FROM TABLE(RESULT_SCAN(''' || :Q || ''')) ';
    
            END FOR;
            RS := (EXECUTE IMMEDIATE :GET_LIST_QUERY);
            RETURN TABLE(RS);
        END IF;
    END;
$$
CALL GET_TAG_TABLE_ON_SCHEMA('TEST');
```

これを実行すると

![スクリーンショット 2024-11-14 19.15.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150914/9e00a3a1-7d2e-13fe-21b4-adfd62bf3895.png)

テーブルとカラム、付与されてるタグ名が取得できます。
ロジックはviewに書かないで切り出してHelperメソッドで運用する

この記事はプログラミング学習者がアプリ開発中に躓いた内容を備忘録として記事におこしたものです。内容に不備などあればご指摘頂けると助かります。

## 記事投稿の背景
Xのクローンサイトを制作している時に色々と躓いたので、知識整理も兼ねて記事として残すことにしました。

## 実際のコード - 変更前
私が制作していたアプリの場合、あるロジックは1箇所だけでなく、合計で<font color="red">**12箇所**</font color>ありました。
ロジックを切り出す前は変更の度に12箇所全てを修正しており、とても手間が
掛かり、時には変更漏れがあったりしました。
```ruby:list.html.slim
- if current_user.present? # ツイートのユーザーとログインユーザーが共に所属するチャットルームが存在するかをデータベースから検索する
    - room_with_tweet_user = Room.joins(:entries).where(entries: { user_id: [current_user.id, bookmark.tweet.user.id]}).group('rooms.id').having('COUNT(entries.id) = 2').first
```

## Helperとは？
動作を処理する場合にメソッド化して使えるようにRuby on Railsへ組み込まれた機能です。
Helperは既にRailsの中に沢山登録されており、具体的には`link_to`, `form_with`, `image_tag`などが頻繁に使われるHelperとして挙げられます。
また、予め登録されているHelperの他に自分で作成して呼び出すことも可能です。


## 実際のコード - 変更後
Viewファイルから切り出したロジックをHelperでメソッド化
内容を変更したい場合はこの１箇所を変更するだけで対応できる
```ruby:rooms_helper.rb
def check_rooms(tweet_user)
    Room.joins(:entries).where(entries: { user_id: [current_user.id,
                                                    tweet_user.id] }).group('rooms.id').having('COUNT(entries.id) = 2').first
end
```
ロジック部分をメソッドとして切り出しました。
これによりviewファイルは見易くなりました。
ロジックを切り出してからは1箇所だけの修正で済ませられるようになりました。メンテナンス性が格段に上がっています。
```ruby:list.html.slim
- if current_user.present? # ツイートのユーザーとログインユーザーが共に所属するチャットルームが存在するかをデータベースから検索する
    - room_with_tweet_user = check_rooms(bookmark.tweet.user)
```

## まとめ
viewにロジックを書かないでHelperメソッドに切り出すことで二つのメリットを確認できました。

:::note info
1, viewファイルが整理されて短くなることで可読性が上がる

2, 変更する際のメンテナンス性が上がる(変更する場所はHelperメソッド内の1箇所のみ)
:::

逆にロジックをviewに書くことで二つのデメリットが出現します。

:::note alert
1, コード全体が冗長になり、可読性が落ちる

2, 変更する際のメンテナンス性が落ちる(変更する場所はview内の同じロジック全て)
    数が増えるほど大変で変更漏れも起こる
:::

## 参考にした記事
[Rails Viewに〇〇ロジックは書かない (※後日追記)](https://qiita.com/pank24ever/items/f4982a7141c0e7fc19d7)
[【Rails入門】helperの使い方まとめ](https://www.sejuku.net/blog/28563)
【supabase×Vercel】ページの表示がやたら遅い時に確認するべきこと

# はじめに
supabaseとVercelを使ったアプリの開発中にハマった件の共有です。

# 問題
supabaseとVercelを使ったアプリをサーバー上で挙動確認している時に、ページの初期表示が5秒近くかかっていることに気づきました。
確かに今開発中のアプリは割とトップページで色々やっているのですが、ローカルサーバーとローカルのsupabaseだと1秒以内でページが初期表示されるので、サーバーの設定がおかしそうだな、というところまではなんとなく考えてました。

# 解決方法
Vercelのリージョンがおかしかったです。
どうやらVercelの設定では、サーバーのデフォルトのリージョンがワシントンDCに設定されているようで、supabaseのリージョンは東京に設定していたので処理が重かったようです。。（リクエストの度にアメリカと日本を行き来してりゃそりゃそうなりますね…）

↓参考

https://vercel.com/docs/edge-network/regions

というわけで、Vercelのダッシュボードから「Projects」→「Settings」タブ→「Function」から以下の通り設定します。

![スクリーンショット 2024-11-14 19.10.36（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832049/b3e4634b-889e-dc81-deb5-af86fe9e2fae.png)

↑の設定を行った後、「Save」を押下して再デプロイすればリージョンが変わるはずです（ログのリクエストに「Tokyo, Japan (hnd1)」とあればOK）。
ちなみに、supabaseはプロジェクト作成時にリージョンを選択するので、東京になっていることを確認しましょう。

以上で設定は完了です。

# おわりに

上記の設定をしただけで、なんと初期表示が5倍以上の速さになっていました。スゴイ。
最初は発行しているSQLが重いのかな？と思ったのですが、ローカルだと処理が高速で、サーバー上だと重くなっているということでなんとなくのアタリをつけられました。
エラー発生時は闇雲に考えるのでなく、「ここがこうなってるからこうなんだろうな」という想像力を働かせながら対応することが大事ですね！

## JISOUのメンバー募集中🔥
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
気になる方はぜひHPからライン登録お願いします！👇

https://projisou.jp/