OmniAICreator/Qiita-1.07M huggingface dataset:
パーソナライズされた学習体験：ChatGPTが切り開く教育の新時代

教育業界は、常に新しい技術や方法が登場することで進化し続けています。AI（人工知能）技術の発展により、教育の場においてもさまざまな革新が起こりつつあります。その中でも、ChatGPTは教育業界において大きな変革をもたらす可能性を秘めています。この記事では、個別指導やオンライン学習におけるChatGPTの活用方法や、その可能性について解説します。これからの教育業界がどのように変わるのか、そしてAI技術がどのように生徒たちの学びの質を向上させるのか、一緒に考えていきましょう。

## はじめに：教育業界におけるChatGPTの活用ポイント

近年、AI技術は教育業界でも大きな影響を与えています。特に、ChatGPTのような高度な言語モデルは、個別指導やオンライン学習など、教育のあらゆる面で活用されています。この記事では、個別指導でのChatGPTの活用方法に焦点を当て、どのように教育現場で活用できるのかを具体的に解説します。

https://toyokeizai.net/articles/-/667344

## 個別指導でのChatGPTの活用

### 質問への瞬時な回答

生徒が抱える疑問や質問に対して、ChatGPTは素早く正確な回答を提供することができます。これにより、教師は時間を節約し、より多くの生徒に対応できるようになります。また、生徒は自分のペースで学習を進めることができ、質問を恐れずに理解を深めることができます。

### 学習スタイルやペースに合わせたカスタマイズ

ChatGPTは、生徒の学習スタイルやペースに応じて、個別化された指導を提供することができます。例えば、視覚的な学習が得意な生徒には図解を用いた説明を行い、言語的な学習が得意な生徒には文章での説明を提供することができます。これにより、一人ひとりの生徒に最適な学習方法でサポートすることが可能になります。

## オンライン学習におけるChatGPTの活用

### 自動化された学習コンテンツ生成
ChatGPTは、オンライン学習においても大きなメリットを提供します。特に、教材の作成や学習コンテンツの生成が自動化されることで、教師の負担が軽減されます。さらに、最新の情報やトレンドに合わせてコンテンツを継続的に更新することができ、生徒に常に最新かつ適切な情報を提供することが可能です。

### インタラクティブな学習体験の提供
ChatGPTは、オンライン学習においてもインタラクティブな学習体験を提供します。例えば、生徒がリアルタイムで質問に答えることができるクイズ形式の教材を生成することができます。また、生徒同士のディスカッションを促すための質問や議論の材料を提供することも可能です。これにより、生徒は積極的に参加し、学習効果を高めることができます。

### 課題やテストの採点・フィードバック
オンライン学習では、課題やテストの採点が教師にとって大きな負担となりますが、ChatGPTを活用することで効率的に対応することができます。ChatGPTは、生徒が提出した課題やテストの回答を瞬時に採点し、適切なフィードバックを提供することができます。また、生徒が理解できなかった部分に対して個別にアドバイスを行うことも可能で、教師の負担を軽減しながら、生徒にとって有益な学習サポートを実現します。

## 教育業界におけるChatGPTの潜在的なリスクと課題

### データプライバシーとセキュリティ
ChatGPTの活用により、教育業界においてもデータプライバシーとセキュリティが重要な課題となります。特に、生徒の個人情報や学習データが含まれる教育データを適切に保護する必要があります。このため、教育機関や教師は、AI技術を取り入れる際に、データの保護や取り扱いに関する法規制やガイドラインに従うことが求められます。

### AI技術への過度な依存
ChatGPTなどのAI技術は、教育業界に多くのメリットをもたらしますが、過度な依存が生じることも懸念されます。教師がAI技術に頼りすぎることで、独自の教育方針や柔軟な対応が犠牲になる可能性があります。また、生徒がAI技術を使いすぎることで、自ら考える力やコミュニケーション能力が低下する恐れもあります。したがって、適切なバランスを保ちながらAI技術を活用することが重要です。


## ChatGPTを活用した未来の教育ビジョン

Duolingoは、無料で利用できる言語学習アプリで、ウェブサイトとモバイルアプリを通じて提供されています。独自のゲーミフィケーション手法を取り入れた教育プラットフォームで、数十種類の言語を学ぶことができます。
Duolingoは既にGPT-4を活用してロールプレイなど新しい価値を提供しています。

https://openai.com/customer-stories/duolingo


### 教育機関のデジタルトランスフォーメーション
教育機関は、ChatGPTなどのAI技術を取り入れることで、デジタルトランスフォーメーションを進めることができます。これにより、教育プロセスの効率化や質の向上が期待されます。また、データ分析を活用して、教育効果や生徒の学習進捗をより詳細に把握し、個別対応ができるようになります。

### ライフロングラーニングの推進
ChatGPTは、生涯にわたる学習の推進にも寄与します。労働市場の変化や技術の進歩に対応するため、個人は常に新たなスキルや知識を習得する必要があります。ChatGPTを活用すれば、自宅や職場で手軽に学習リソースにアクセスでき、柔軟な学習スタイルが可能になります。


## まとめ：ChatGPTがもたらす教育業界へのインパクト

ChatGPTは、教育業界において多くの可能性を秘めています。機会均等化、ライフロングラーニングの推進、教育機関のデジタルトランスフォーメーションなど、多くの面で教育の未来を変革するインパクトが期待されます。しかし、その活用には適切なバランスが求められ、リスクや課題への対処が必要です。教育業界は、この新たな技術を上手に取り入れることで、より良い未来の教育を実現できるでしょう。
GoogleBardついに日本語対応！かつ聞いた回答がGmailやGoogleドキュメントにワンクリックで転送可能に！早速メールの下書きをBardにお願いしてみた

GoogleBardの解答がワンクリックでGmailにエクスポートできるようになりました！

日本語でも質問できるようになりました。

急な予定が入り明日の予定を変更する必要があります。予定変更をGmailで送ろうと考えています。下書きが思いつかない。。。そんなときはBardに質問です！
「急な予定が入り明日の予定を変更しなければなりません。変更を頼むメールをマネージャーに送りたいので下書きを作ってください」
以下の青い字で囲ってある箇所をクリックしてください。

![スクリーンショット (1109).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291948/7cba6f95-a022-dcc8-65cd-e7a8d1edb8f2.png)


以下のDraft　in　Gmailをクリック。
![スクリーンショット (1110).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291948/0c6b87b6-b3cb-f7ac-cf29-c1a01346dd51.png)
以下のように待機画面が出ます！

![スクリーンショット (1111).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291948/4b651669-42f5-3c72-b86d-8b3bf4eadd9d.png)

あっという間に下書きができました！件名は変えないといけないようですね
![スクリーンショット (1112).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291948/50b24e50-a020-e630-3e8a-896bce3b95de.png)

あとは宛先を入力して、件名を整えて、マネージャーの名前などを変更して修正すればよいですね。

以上GoogleBardの使用感をお伝えしました。メールに革命がおこったのでは？

自社が開発した製品に紐づいていくやり方は今後どの企業もリリースしそうですね。企業同士の製品連携したサービスも出てくるのでは。

これは楽しみですね。
インスタンスメソッド・クラスメソッド

# はじめに
クラスメソッド内でインスタンスメソッドを呼び出す際のロジックが曖昧、、、
そもそもインスタンスメソッド・クラスメソッドではメソッドの違いが曖昧だった


### インスタンスメソッドとは
* 特定のクラスのインスタンスオブジェクトに対して呼び出される
* 特定のクラスのインスタンスに紐づいており、そのインスタンスの状態やデータにアクセスすることができる
* クラス内でselfを用いずに定義されたメソッド
* クラスの中にメソッドを作成するとそれがインスタンスメソッドになる

### 実際の使い方
```person.rb
class Person
  def initialize(name)
    @name = name
  end

  def greet
    puts "Hello, my name is #{@name}."
  end
end

person = Person.new("Alice")
person.greet
```

### クラスメソッドとは
* そのクラスのインスタンス（オブジェクト）ではなく、クラス自体に対して呼び出される
* 特定のオブジェクトの状態に依存せず、クラス全体に関連する処理や操作をすることができる
* クラス内でselfを用いて定義されたメソッド
* メソッド名の前にselfキーワードを付けて作成するとそれがクラスメソッドになる


### 実際の使い方
```person.rb
class Person
  def initialize(name)
    @name = name
  end

  def self.my_class_method
    puts "This is a class method."
  end
end

Person.my_class_method
```

## クラスメソッド内でインスタンスメソッドを呼び出す場合の注意点
* **インスタンスメソッドはインスタンスを介して呼び出す必要がある**
→クラスメソッドはインスタンスに紐づいていないため、インスタンスメソッドを直接呼び出すことはできない。そのため、まずクラスメソッド内でインスタンスを生成する必要がある。


* **クラスメソッド内でインスタンスを生成する場合、適切なコンテキストやデータを与える必要がある**
→インスタンスメソッドは、特定のオブジェクトの状態やデータにアクセスするために使用される。そのため、クラスメソッド内でインスタンスメソッドを呼び出す際には、適切な引数や初期化パラメータを提供する必要がある。

* **クラスメソッド内でインスタンスメソッドを呼び出す場合、インスタンスの返り値や状態を適切に処理する必要がある**
→クラスメソッドは通常、インスタンスを介さずに操作を行うため、インスタンスメソッドからの返り値や状態を適切に受け取って処理する必要がある。

### 実際の使い方
```myclass.rb
class MyClass
  def self.my_class_method
    instance = MyClass.new #まず、インスタンスを生成する
    instance.my_instance_method　#インスタンスを介して呼び出す
  end

  def my_instance_method #インスタンスメソッド
    puts "This is an instance method."
  end
end

MyClass.my_class_method
```

### まとめ
インスタンスメソッド・クラスメソッドの違いを理解することで、クラスメソッド内でインスタンスメソッドを呼び出す場合でも、迷わずロジックが書ける

## 参照
[【プログラミング初心者向け】クラスメソッドとインスタンスメソッドはどう使い分けるべき？](https://blog.jnito.com/entry/2022/07/20/080512)
Oracle Analytics Cloud：データモデルに設定したクエリーのタイムアウト時の動きを見てみる

はじめに
---
Oracle Analytics Cloud ：OACで、Dashboard/Answersの分析や、DataVisualizationのワークブックを実行しているとき、
結果がなかなか返ってこないことがあります。そんなとき、ある一定時間が経過すれば、タイムアウトすることができるのですが、その方法、結果画面について見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/029356fd-d731-9afe-eb9c-d50c9b3aaa4d.png)

タイムアウト時のメッセージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/a78f5c1d-1a6e-b0d3-1eaa-69cdd0063b37.png)



前提
---
本記事では[「Oracle Analytics Cloud インデックスページを作成してみました。」](https://qiita.com/tni38/items/534a39c1231b23c617f4])の以下を実施しています。
・Oracle Analytics Cloud のサービス作成
・お試し用にADWでSHスキーマをもとにSHJPスキーマを作成する。

その他、以下ユーザーが存在
・OACの管理者ロールを付与されたユーザー(oac.user99)がいる
・OACの開発者ロールを付与されたユーザー(oac.user01)がいる

事前準備：タイムアウトさせるためにADWにdbms_session.sleepを利用した関数を用意する
---
データベースアクションや、SQLDeveloper、sqlplusを用いSHJPユーザーで、一定の処理時間を経過させる関数を作成します。以下、dbms_session.sleepを使ったサンプルです。

```
create or replace function f_sessleep(v_time in number) return varchar2 
as
  p_start number;
  p_end number;
begin
  p_start := dbms_utility.get_time;
  dbms_session.sleep(v_time);
  p_end := dbms_utility.get_time;;
  return('Start:'||to_char(p_start)||' - End:'||to_char(p_end));
exception
  when others then
    return sqlerrm;
end;
/
```

Model Administration Toolでデータモデルの作成とタイムアウトの設定の確認
---
以下のような表タイプをSelectにした物理層の表を作成し、サブジェクト領域を作成しています。65秒 sleepします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/b3d20009-928f-bc22-4377-284c70a2600c.png)

タイムアウトの設定をします。管理 - アイデンティティをクリックし、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/48acca57-79ff-0f3c-58bc-8f04caeb8a0b.png)

OACの開発者ロールであるBIContentAuthorをクリックします。※何も表示されない場合は、メニューからロールを手動で追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/91c39f6b-01a1-8ca2-331e-be0555d841da.png)

権限をクリックし、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/2728e85e-b943-21d5-0f37-ff1ba79b124c.png)

ステータス最大時間を「有効化」に変更、最大時間に「1」(分)と入力します。OKをクリックします。次もOKをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/029356fd-d731-9afe-eb9c-d50c9b3aaa4d.png)

保存、整合性チェック実施後、クラウドに公開します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/38fbb069-3d6e-9aae-3048-041cc849e70c.png)

Answersの分析でタイムアウト時の動きを見てみる
---
タイムアウトすると、エラーとなります。詳細を開くと、以下メッセージが出力されているのが確認できます。
「コード: 60009。[nQSError: 60009] ユーザー・リクエストが、実行時間を管理する最大問合せを超えました。」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/6a9f4547-00d3-ed57-c2e7-d357a003a3dd.png)

DataVisualizationのワークブックでタイムアウト時の動きを見てみる
---
タイムアウトが設定されたサブジェクト領域を使ってワークブックを作成します。タイムアウトすると、エラーとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/b1a58a79-6770-dfc3-228e-4077934a0310.png)

詳細をクリックすると、Answersの分析と同様に、メッセージが出力されているのが確認できます。「状態: HY000。コード: 60009。[nQSError: 60009] ユーザー・リクエストが、実行時間を管理する最大問合せを超えました。」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/e3727a40-ebcd-1bf8-33a4-ecbd6c281849.png)

以上
【MT7】記事の表示方法を分ける（外部リンク or 記事詳細）

## はじめに
**MovableType7**
記事の表示方法を分岐する方法。

パターン1：記事の詳細を表示する。（タイトル、本文、日付…などが表示される）
パターン2：「URL」フィールドにURLが入力された場合、そのURLを外部リンクで開く。（詳細ページには飛ばない）

## コンテンツタイプの管理
まｚはコンテンツタイプの管理でコンテンツフィールドを作成します。
ここでは**URL**というフィールドを作成します。

◎ **URL**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/2ec1de44-d5b1-ec83-f45a-b86086bad979.png)
※今後お客さん側で更新することが想定される場合、説明を入力しておくほうが良いです。


## コンテンツタイプ登録画面
登録画面にはこのように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/17c8d71d-315c-e4a8-2a7e-94f2d4599bef.png)



## コード
```
<mt:Contents content_type="お知らせ">
　<li class="news__item">

  　<$mt:setvar name="target_link"$>
    <mt:ContentField content_field="URL">
       <$mt:setvar name="target_link" value='target="_blank"'$>
       <$mt:ContentFieldValue setvar="url_link"$>
     <mt:else>
       <$mt:ContentPermalink setvar="url_link"$>
     </mt:ContentField>

     <a href="<$mt:var name='url_link'$>" <$mt:var name='target_link'$>>
　　　　<p class="title"><$mt:ContentLabel$></p>
     </a>

　</li>
</mt:Contents>
```

## 説明
```
<$mt:setvar name="target_link"$>
```
1）target_linkという変数を作成しています。
外部リンクの有無に使用します。

```
<mt:ContentField content_field="URL">
```
2）コンテンツタイプの管理で作成した「URL」フィールドを指定します。

```
<$mt:setvar name="target_link" value='target="_blank"'$>
<$mt:ContentFieldValue setvar="url_link"$>
```
3）変数target_linkに「target="_blank"」を代入します。
次に「入力値」を変数url_linkとして設定します。
これらの処理は**URLフィールドに値が入力されたときのみ有効**になります。

```
～省略～
<mt:else>
   <$mt:ContentPermalink setvar="url_link"$>
</mt:ContentField>
```
4）次に、**「URL」フィールドに値が入力されていない場合**の処理を記述します。
記事の詳細にアクセスされます。
**・ContentPermalink**：コンテンツデータが公開されているURLを表示する。（＝記事のURLを表示する）

## 参考サイト
[テンプレートタグで利用できる演算関数  | MovableType テンプレートタグリファレンス](https://www.movabletype.jp/documentation/mt6/design/templates/calculation.html)
1の立っているビット数を数える

# 参考資料

- [ハッカーのたのしみ―本物のプログラマはいかにして問題を解くか](https://www.amazon.co.jp/dp/443420159X?tag=hatena-22&linkCode=ogi&th=1&psc=1)
- [その17 ビット演算あれこれ](http://marupeke296.com/TIPS_No17_Bit.html)       
- [ビットを数える・探すアルゴリズム](https://www.nminoru.jp/~nminoru/programming/bitcount.html)      
- [おすすめ書籍｜組込みエンジニア向け | ハングスタック](https://hangstuck.com/recommended-books/)      

# Pythonで確かめる(8ビットの場合のみ)
```python
def count_1s_in_8bits(val):
    val =  (val & 0x55) + ((val >> 1) & 0x55);
    val =  (val & 0x33) + ((val >> 2) & 0x33);
    return (val & 0x0f) + ((val >> 4) & 0x0f);
    
#確認のため別の方法を試す。
#数値を2進数文字列に変えて、数字1の個数を数える。
def sute(val):
    return bin(val).count('1')
    
for i in range(2**8):
    print(i, bin(i), count_1s_in_8bits(i), sute(i))
```

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193936/a9fdf35b-fbe0-768d-0453-ac336fc52515.png)　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193936/213a5091-b72e-8db2-9a50-77f0661e1b3c.png)

# VHDLで実装する(8ビットの場合のみ)
```vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity count_1s_in_8bits is
    port (
        inp: in std_logic_vector(7 downto 0);
        num_1s: out std_logic_vector(3 downto 0)
    );
end entity;

architecture behavior of count_1s_in_8bits is
    signal sute0, sute1, sute2: unsigned(7 downto 0) := (others => '0');
begin
    sute0 <= unsigned(inp);
    sute1 <= (sute0 and x"55") + (( '0' & sute0(7 downto 1)) and x"55");
    sute2 <= (sute1 and x"33") + (("00" & sute1(7 downto 2)) and x"33");
    num_1s <= std_logic_vector(sute2(3 downto 0) + sute2(7 downto 4));
end architecture;
```

## 出来上がった回路
わけの分からないアルゴリズムに見えるが要は全部のビットをツリー形式の加算器で加算しているだけのようである。8ビットの場合は3段で済む。        
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193936/76c37f5c-d7ac-bf6a-65d7-235d74198f09.png)       
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193936/f37f8b5d-5f65-6ba6-8c9a-3f33a9ebd635.png)



## シミュレーション結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193936/bd7d5bc6-513d-29e2-653d-07236709c709.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193936/cda6aa8d-5e0d-3c59-aa40-3ced4783350e.png)
Power Automateで、Power Appsをトリガーアクションにして実行ユーザーを変更したい場合はV2のものを使用する

# 結論
Power Automateでは、Power Appsというトリガーアクションが「無印」と「V2」の2種類あるようですが、フローの実行ユーザーを変更したい場合はV2のものを使用しないと変更できないようです。
# 実際に起きた問題
Power Appsからの操作をトリガーにするPower Automateのフローを作成していました。
そしてそのフローを実行するユーザーを変更しようとしたところ、「実行のみのユーザー」がフローの詳細画面に表示されませんでした。
このままではフローを実行するユーザーを変更できません。
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/37c617ab-233a-9ad4-f321-8c81c42e7c22.png)
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/97814aef-d762-0b41-efb9-3edaf385e338.png)
# 調査
以下の記事を参考にしました。

https://mofumofupower.hatenablog.com/entry/2022/07/17/020755
> ポイントはトリガーに "Power Apps (V2)" を利用することです。無印の "Power Apps" トリガーだと実行専用のアクセス許可を管理できないので今回の方法が機能しません。
# 調査を踏まえての対策
1. フローのトリガーアクションにある3つの点をクリックしてメニューを表示します。
1. 削除をクリックしてトリガーアクションを削除します。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/70557e8d-95a7-2b5d-cbec-96997d43b4cb.png)
1. トリガーアクションを選択するメニューが表示されるため、PowerApps(V2)を探してクリックします。
1. フローを保存します。
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/2747a82d-ae2e-b4f5-6870-5b58bd7a9cc7.png)
1. フローの詳細画面に戻って、「実行のみのユーザー」が表示されていることを確認します。
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/73dd7909-187d-486a-44e8-651993992623.png)
これで必要に応じて実行のみのユーザーを変更できます。
# あとがき
もし「実行のみのユーザー」が表示されず、変更できなくて困っているときがあれば、トリガーアクションを確認すると解決できるかもしれないです！
Ansible PlaybookにおいてYAMLフロー構文を使用する際に、[0]や['key']などが入っているとエラーとなりうる

備忘

例えば、my_listが要素を持つリストの場合、以下は正常に実行可能なtasks

```yaml:OK
- debug:
    var: my_list[0]
```

しかし、YAMLフロー構文を使用した以下はYAML構文レベルのエラーとなった

```yaml:NG
- debug: { var: my_list[0] }
```

エラーの例
```
ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 2 column 1 (char 1)

Syntax Error while loading YAML.
  expected ',' or '}', but got '['

The error appears to be in '/xxxx/playbook.yml': line 9, column 26, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

  tasks:
  - debug: { var: my_list[0] }
                         ^ here
```



これは、[]がリストを表す記号であるため。
以下のように明示的に文字列とすれば問題なく実行可能。

```yaml:OK
- debug: { var: "my_list[0]" }
```
(リンクだけです)「垂心(英:orthocenter)」を調べた。

https://www.deepl.com/ja/translator#ja/en/非常に奥が深そうなので、さわりだけにしました.

# wikipedia

https://en.wikipedia.org/wiki/Altitude_(triangle)#Orthocenter

https://ja.m.wikipedia.org/wiki/%E5%9E%82%E5%BF%83

# WolframAlphaで

https://www.wolfram.com/language/12/plane-geometry/triangle-centers.html.ja

https://www.wolfram.com/language/12/plane-geometry/triangle-centers.html.en?footer=lang

https://www.google.com/search?q=wolframalpha++%E5%9E%82%E5%BF%83&rlz=1CAUHAM_enJP1038JP1038&sxsrf=APwXEdeRqbqmwrsbvdK-56jPJGO1_qm3ig%3A1683770679494&ei=N01cZJDlHZPv-Abuk6SwCA&ved=0ahUKEwjQ3O_Jluz-AhWTN94KHe4JCYYQ4dUDCA8&uact=5&oq=wolframalpha++%E5%9E%82%E5%BF%83&gs_lcp=Cgxnd3Mtd2l6LXNlcnAQAzIFCAAQogQyBQgAEKIEMgUIABCiBDoICAAQogQQsAM6BAgjECc6BwgjELACECdKBAhBGAFQiBVYoztguEBoBHAAeACAAasDiAHND5IBCjAuMTAuMS4wLjGYAQCgAQHIAQXAAQE&sclient=gws-wiz-serp

# sympyで
property orthocenter

https://docs.sympy.org/latest/modules/geometry/polygons.html#sympy.geometry.polygon.Triangle.orthocenter

https://www.google.com/search?q=sympy+%E5%9E%82%E5%BF%83&rlz=1CAUHAM_enJP1038JP1038&oq=sympy++++%E5%9E%82%E5%BF%83&aqs=chrome..69i57j0i546l3.6787j0j7&sourceid=chrome&ie=UTF-8

https://www.google.com/search?q=sympy+orthocenter&rlz=1CAUHAM_enJP1038JP1038&sxsrf=APwXEdeXduYs55KwCC2zu5ZoP0NFijrhog%3A1683770913255&ei=IU5cZOCfD9TbhwOhxLqQBw&ved=0ahUKEwigtKu5l-z-AhXU7WEKHSGiDnIQ4dUDCA8&uact=5&oq=sympy+orthocenter&gs_lcp=Cgxnd3Mtd2l6LXNlcnAQAzIFCAAQogQyBQgAEKIEOgoIABBHENYEELADOgQIIxAnOgcIIxCKBRAnOgUIABCABDoHCAAQigUQQ0oECEEYAFD1BVjhDmCiFGgBcAF4AIABrgGIAZ0DkgEDMC4zmAEAoAEBoAECyAECwAEB&sclient=gws-wiz-serp

 **sympyのLineのprjectionで1点に交わるのを見てみたい。**


# 過去問
垂心＜

https://cse.google.com/cse?cx=a8908fbc24340ebc5&q=%E5%9E%82%E5%BF%83&oq=%E5%9E%82%E5%BF%83&gs_l=partner-web.12..0i512l10.3959.5954.0.9303.4.4.0.0.0.0.223.778.0j2j2.4.0.csems%2Cnrl%3D10...0....1j4.34.partner-web..0.4.777.qtv5iB05bjU

https://www.google.com/search?q=site%3Akamelink.com+%22%E5%9E%82%E5%BF%83%22&rlz=1CAUHAM_enJP1038JP1038&oq=site%3Akamelink.com+%22%E5%9E%82%E5%BF%83%22&aqs=chrome..69i57j69i58.19710j0j4&sourceid=chrome&ie=UTF-8

https://www.google.com/search?q=site%3A%2F%2Fmathmathmass.exblog.jp+%22%E5%9E%82%E5%BF%83%22&oq=site%3A%2F%2Fmathmathmass.exblog.jp+%22%E5%9E%82%E5%BF%83%22&aqs=chrome..69i57j69i58.1239j0j4&client=ms-android-huawei&sourceid=chrome-mobile&ie=UTF-8


# 垂心と正弦定理の違い。 
2024-09-21 追加

垂心と外接円(正弦定理)とつながっていました。wikipedaより
 https://ja.wikipedia.org/wiki/垂心#性質

ChatGPT先生へ
```
三角形の垂心から各頂点への長さの計算式が、正弦定理の式と似ています。
違いを教えて下さい。
```
(省略)
Bardを使ってみた



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/33a226e7-722a-e116-e181-c29eb59b0fe7.png)

https://bard.google.com/?hl=en


2023/05/11 追記
 Google I/O 2023 にて Bardの日本語対応が発表され、実際に日本語で応答可能であることを確認いたしました。

 https://io.google/2023/intl/ja/

Bardは研究段階のプロダクトであり、
上記のリンクから、WaitListに登録することで招待をいただくことができます。
私の場合は、WaitList登録から即日で利用が可能となりました。

# 使ってみた
現時点では、Bardは日本語へは対応しておらず、英語での質問を実施してみました。
Bardはリアルタイムでの情報収集やそれを基にした回答が可能であり、ChatGPTについての質問についても回答いただけました。内容も非常に面白かったので応答結果を下記します。

Q1. ChatGPTについてどう思いますか？
![bard2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/aec3a2bd-8828-ca89-32a6-08ff8c352acd.png)
Q2. ChatGPTとBardはどちらが良いものでしょうか？
![bard1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/6c971399-e1c4-889f-8325-a9eb80213fcd.png)

上記の通り、BardはしっかりとChatGPTとの機能差や活用の機会について差別化できているようです。
実情とあっているかはまだ判定は難しいですが、Bard側から活用の機会提示ができそうであることはそれぞれの強みに繋がっていきそうです。

# ChatGPTとの比較
ChatGPTと比較してみました。ChatGPT3.5/4.0(※)を利用しています。
※ OpenAIにおいて、なぜだか有償プランへの支払いができず AIOne にて試させていただきました。
 
   https://aione.topaz.jp/

なお、GPT4.0でもリアルタイムの情報は扱えず、Bardについての回答も得られませんでした。
・最新のニュースについて教えてください
・GoogleのBardについて教えてください
![gpt4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/28d53c25-76e2-ac83-e01f-dd705417c1bb.png)

### Q. JavaでHello Worldを作成してください
2023年4月21日に、Bardにはコード生成、コードのデバッグ、説明など、プログラミングやソフトウェア開発のタスクを支援する機能追加が行われました。
試したところ、メジャーな言語であれば正しい内容が確認できました。実際に参照先として活用できそうです。
・Bard
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/6f35081e-f15d-b950-38e6-168a14b434d0.png)

・GPT 4.0
![java1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/715226d5-86fe-3941-27c1-3e78ffc44184.png)

### Q. 数独を作問してください
各AIチャットに何かを生成させてみようと思い、クイズやパズルの出題への対応が面白いと耳にしたので、数独パズルの作成をお願いしてみました。
・Bard
![suudoku.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/c537b589-c779-acec-1bb5-725bbd29e9d8.png)
・GPT 3.5
![suudoku2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/120ea9f6-04c3-e76e-726e-afd1e83aec40.png)
・GPT 4.0
![suudoku3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651737/eb817f30-1b3e-9d8c-cd4e-e30fb27f35ab.png)

それぞれ異なった回答が得られ、特にGPT 3.5について興味深い出力が得られました。何度も解答の訂正を求めても正しい回答は得られなかったです。Bardは非常に惜しい回答内容でした。
・Bard: 出題の形式にはなってはいないが、数独としては成立している
・GPT 3.5: 出題の形式になっている。数独としては成立していない
・GPT 4.0: 出題してくれない

## 比較まとめ
### メリット
・リアルタイムの情報を扱うことができる
・解答速度が速い
・参照先や詳しい情報などが確認しやすいようにリンク先が提示されている

### デメリット
・日本語での質問ができない
・解答が正しくない場合がある

# 感想
まだまだ研究段階と明記されているように、実際の会話や質問への応答の中で間違っている内容や少しおかしな文章などが見受けられました。
しかしGPT3.5と比べても回答内容に遜色はなく、解答速度やデータソースの提示/リンク先の拡充など勝る点も多く見受けられました。
今後もさらなる洗練や日本語対応が予定されているとのことで、期待して待ち、リリースされ次第試して発信していきたいです。
jQueryの勉強メモ

# jQueryの基本文法
```jquey:基本文法
$('セレクタ').メソッド(引数)
```

# 使ったことのあるイベント
`hover` : マウスを要素に重ねた時の動き（サイズ変えるとかくらいならcssでも可）
```jQuery:hover
$('セレクタ').hover(

/*マウスを重ねた時の動き*/

    function(){
        $('セレクタ').メソッド(引数);
    },

/*マウスを離した時の動き*/

    function(){
        $('セレクタ').メソッド(引数);
    }
);
```
<br>


`click` : マウスで要素をクリックした時の動き
```jQuery:click
$('セレクタ').click(
    function(){
        $('セレクタ').メソッド(引数);
    }
);
```

<br>

# よく使うメソッド
#### :point_up:使ってみたらチェックしていこうね私

- [ ] .html()
- [ ] .css()
- [ ] .text()
- [ ] .replaceWith()
- [ ] .replaceAll()
- [ ] .remove()
- [ ] .unwrap()
- [ ] .length()
- [ ] .eq()
- [ ] .find()
- [ ] .addClass()
- [ ] .removeClass()
- [ ] .hasClass()
- [ ] .show()
- [ ] .hide()
- [ ] .fadeIn()
- [ ] .fadeOut()
- [ ] .slideUp()
- [ ] .slideDown()
- [ ] .toggle()
- [ ] .fadeToggle()
- [ ] .slideToggle()
- [ ] .fadeTo()
LibertyをOpenShiftで動かしてみた

# はじめに
WebSphere25周年を記念して、自分でもLibertyに触れてみようと思い記事を書いています。

私自身もまだ勉強中ではありますが、[同僚の記事](https://qiita.com/taketomsho/items/c204b62b218837ee0947)を参考に、OpenLibertyをOpenShift上で動かしてみました。


# 実施すること
- OpenShift Developer Sandbox環境取得
- 公開されているコンテナイメージからのデプロイ
- ローカルにあるDockerfileからのデプロイ

# OpenShift Developer Sandbox環境取得
OpenShift Developer Sandbox環境は、さまざまな制限（使用期間：30日間など）がありますが、手軽にOpenShiftを触れるため初学者の方におすすめです。
こちらの記事を参考に取得してみてください

https://qiita.com/ynagashi/items/5b3a6eda057256bb707f

# 公開されているコンテナイメージからのデプロイ
こちらのコンテナイメージを利用します

>ibmcom/websphere-liberty:full-java11-openj9-ubi


開発者向けメニューから「＋追加」から、コンテナイメージをクリック
![スクリーンショット](https://github.com/Yusuke-88/Qiitaimage/blob/main/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-05-11%209.14.13.png?raw=true)

あとはコンテナイメージのイメージ名を記載して、画面のように設定し「作成」をクリックする
![スクリーンショット](https://github.com/Yusuke-88/Qiitaimage/blob/main/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-05-11%209.26.48.png?raw=true)


無事にLibertyがデプロイされたことを確認できた
![スクリーンショット](https://github.com/Yusuke-88/Qiitaimage/blob/main/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-05-11%209.33.40.png?raw=true)

URLを開くと、、
![スクリーンショット](https://github.com/Yusuke-88/Qiitaimage/blob/main/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-05-11%209.33.55.png?raw=true)

# ローカルにあるDockerfileからのデプロイ
まずはDockerfileとSampleアプリを作成した
同僚の記事を参考にSample1.warにはindex.jspを配置している。
```Dockerfile:Dockerfile
FROM ibmcom/websphere-liberty:full-java11-openj9-ubi
COPY --chown=1001:0 ./Sample1.war /config/dropins/Sample1.war
```

oc new-buildコマンドでBuildConfigを作成し、次にoc start-buildコマンドでビルドを開始する
```
oc new-build --name=sampleliberty --strategy=docker --binary
oc start-build sampleliberty --from-dir=. --follow
```

ビルドの成果物としてImageStreamができますので、それを利用して実行します
![スクリーンショット](https://github.com/Yusuke-88/Qiitaimage/blob/main/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-05-11%2010.20.16.png?raw=true)

なんとか問題なく動作した。
![スクリーンショット](https://github.com/Yusuke-88/Qiitaimage/blob/main/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-05-11%2010.22.16.png?raw=true)

時刻が表示される簡単なページを表示できた。
![スクリーンショット](https://github.com/Yusuke-88/Qiitaimage/blob/main/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-05-11%2010.22.45.png?raw=true)

# まとめ
OpenShiftの学習も兼ねてLibertyを簡単に触ってみた
まだまだわからない点が多いが、引き続き勉強しながら、環境を触って学んでいきたい
NeoVim

Vim を使い始めたばかりだが早速 NeoVim というのを使ってみる事にした。GitHub Copilot が NeoVim をサポートしているというのが理由だ。

* インストールには brew を使った。
    * `brew install neovim`
* 今まで白い画面のターミナルを使っていたが、色が見にくいので妥協して Dark Mode にした。
* 起動には `nvim`。neovim コマンドというのは無い。
* 起動スクリプトは `~/.config/nvim/init.vim`
    * .vimrc をそのまま使うとエラーになる。nvim だけで使う設定を書きたい場合は has('nvim') で囲む。

            if has('nvim')
                ....
            endif

* `:terminal`
    * NeoVim には `:shell` コマンドが無い。代わりに `:terminal` がある。こちらの方が良いらしいが結構癖がある。最初使い方が分からなかった。
    * `i`: `:terminal` コマンドの直後コマンド入力出来ない ?! `i` を押して terminal mode に入る。
    * `<C-\><C-N>`: terminal mode から normal mode に戻る。これは覚えにくい。。。

## GitHub Copilot インストールの仕方

[Getting started with GitHub Copilot - GitHub Docs](https://docs.github.com/en/copilot/getting-started-with-github-copilot?tool=neovim) によると、Copilot のインストールには Neovim's built-in plugin manager という物を使えと書いてあるが、Neovim's built-in plugin manager とは何なのかよく分からなかった。結局

```
git clone https://github.com/github/copilot.vim \
   ~/.config/nvim/pack/github/start/copilot.vim
```

を実行する事で良かったらしい。
gitのメモ

```
非常に分かりやすい説明です。
https://www.youtube.com/watch?v=j6sAaOqyk3Y

重要
リポジトリ
PCとペア使います。

コミット⇒ローカルへ
プッシュ⇒リモートへ

実務はTortoiseGit 使用は多いです。

分散開発ツールです

コミット
随時します

マージ
他人開発分を自分のソースへ反映

main >  ブランチの構造です

最終的は全員はmainへ反映する

あくまでリモート作業必要です。ローカルは意味ないです。

● .git
gitの管理情報が入っています
リポジトリ
●クローン
リモートのリポジトリをローカルにコピーすること
TortoiseGit > git クローン > remote url入力 > remote pw 入力
チェックアウト
コミット
プッシュ
フェッチ
プル
コンフリクト
スタッシュ
リベース
リバード
●ログ
TortoiseGit > ログ　さまざまな履歴を見れます
●切り替えチェックアウト
別のブランチを選択するチェックアウト
sikulix2.0.5、Linux環境へのインストール

sikulix2.0.5をLinuxにインストールした際の記事があまり見つからなかったので成功した状況を簡単に残しておきます
-環境：Windows11上のHyper-v

ケース１：Centos7へのインストール
・起動はするもののRPAのスクリプトを実行するとエラーとなり、Javaのバージョンやsikuliのバージョンを色々変えて試しましたが今のところ成功できてません

ケース２：Ubuntu20.04へのインストール
・こちらは比較的すんなり成功しました
・大まかな手順は以下のとおりです

手順
・Ubuntu20.04のインストール
--インストール時に特別な設定などはしてないです
--sikulixは画面を画像でチェックして動作をするので、仮面構成がシンプルなXubuntuにしました

・Javaのインストール
--最新版の安定版をインストール
--sudo apt install default-jdk

・sikulixのダウンロード
--下記のサイトからファイルをダウンロードします
--https://raiman.github.io/SikuliX1/downloads.html
--Download the ready to use sikulixide-2.0.5.jar (SikuliX IDE for all systems)

・起動
--java -jar 保存ディレクトリ/sikulixide-2.0.5.jar

sikulixの画面が表示したら成功です
xrdpで接続した場合画面が正常に表示しない事があるようなのでその場合は
/ets/xrdp/xrdp.iniの　xserverbpp = 24 
の行のコメントアウトを外してxrdpサービスを再起動すると治ることがあります

使用に関する内容は別記事に書こうと思います
カスタム設定(Custom Settings)

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)

-------------------


+ [Apex クラスでのカスタム設定レコードの取得](https://salesforce.oikeru.com/entry/apex_get_cusom_setting#:~:text=%EF%BC%91%EF%BC%8E%5B%E8%A8%AD%E5%AE%9A%5D%20%E3%81%8B%E3%82%89%E3%80%81,%E6%AC%A1%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

数式項目は階層カスタム設定でのみ機能し、リストカスタム設定には使用できません。

```
{!$Setup.CustomSettingName__c.CustomFieldName__c}
```

Apexから呼び出す。何故か苦戦してしまった。

OrgInfo__cはカスタム設定のAPI名、Info001__cはカスタム項目のAPI名


```
//組織レベルで値を取得する場合は、getOrgDefaults メソッドを使用します。
OrgInfo__c mc = OrgInfo__c.getOrgDefaults();
System.debug(mc.Info001__c);
```

# ヘルプ

+ [カスタム設定の制限および考慮事項](https://help.salesforce.com/s/articleView?id=sf.cs_limits.htm&type=5)
サル🐵でもわかるReactのProps【初心者向け】


React（リアクト）のProps（プロップス）は、コンポーネント間でデータを渡すための仕組みです。

子コンポーネントにデータを渡すときに使います。簡単に言えば、親から子へプレゼントを渡すようなものです。🎁
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/1d695aea-17fb-3023-d3b0-0a79e17227be.png)

## Propsの使い方

Propsを使うときは、まず親コンポーネントでデータを用意します。そして、子コンポーネントに渡したいデータを属性（アトリビュート）として書きます。

例えば、こんな感じです。

```javascript
// 親コンポーネント
import React from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
  const message = 'こんにちは、子コンポーネント！';

  return (
    <div>
      <ChildComponent text={message} />
    </div>
  );
}

export default ParentComponent;

```

親コンポーネントで`message`というデータを用意しました。そして、`<ChildComponent>`の`text`属性にそのデータを渡しています。

次に、子コンポーネントでPropsを受け取ります。


```javascript
// 子コンポーネント
import React from 'react';

function ChildComponent(props) {
  return (
    <div>
      <p>{props.text}</p>
    </div>
  );
}

export default ChildComponent;

```

子コンポーネントで`props`という引数を受け取りました。`props.text`で親から渡されたデータを使っています。

## まとめ

ReactのPropsは、親コンポーネントから子コンポーネントへデータを渡すためのものです。親コンポーネントでデータを用意し、子コンポーネントに属性として渡します。子コンポーネントでは`props`で受け取り、使うことができます。
Node.js: OracleDB のデータを削除 (Delete)

## プログラム

```js:oracle_delete.js
#! /usr/bin/node
//
//	oracle_delete.js
//					May/10/2023
//
// ---------------------------------------------------------------
'use strict'

const oracledb = require('oracledb')

// ---------------------------------------------------------------
async function run() {
	console.error("*** 開始 ***")
	const id_in = process.argv[2]
	console.log(id_in)

	let connection

	try {
		connection = await oracledb.getConnection( {
			user		: "scott",
			password	: "tiger123",
			connectString	: "172.17.0.2:1521/XEPDB1"
		})

	const sql_str = "delete from cities where id='" + id_in + "'"
	console.log(sql_str)
	const result = await connection.execute( sql_str,)
	console.log(result)
	await connection.commit()
	console.error("*** 終了 ***")
	} catch (err) {
		console.error(err)
	} finally {
		if (connection) {
			try {
				await connection.close()
			} catch (err) {
				console.error(err)
			}
		}
	}
}

// ---------------------------------------------------------------
run()

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

## 実行コマンド

```bash
./oracle_delete.js t0134
```

## 確認したバージョン

```text
$ node --version
v19.9.0
```
配列とハッシュのどっちを使えばいいの？

rubyを書いていると、「あれ？配列かハッシュのどっちを使ってデータを格納したらいいんだろう？」ということが時々出てきます。結局、どれを使っても書けちゃうんですが、それも一長一短ですね。

| タイプ | ケース | 
|:-:|:-:|
|配列  |繰り返し処理・コレクションをキューやスタックとして扱う場合|  
|ハッシュ|あるオブジェクトから他のオブジェクトへの１対１や多対多の対応が必要な場合| 

# 結局、配列とハッシュのどっちを使えばいいの？

Rubyでは、ハッシュ（Hash）と配列（Array）の両方を使用してデータを格納することができます。ハッシュはキーと値のペアでデータを保持し、配列は順序付けられた要素の集合を保持します。

以下に、ハッシュと配列の特徴と使い分けのポイントを示します。

## ハッシュの使いどころ

:::note
ハッシュの特徴と使いどころ：
- データの格納に`キーと値のペア`を使用します。
- キーを使ってデータを高速に取得できるため、`データの検索や関連付け`に適しています。
- キーは一意である必要があります。
- データの`順序は保証されません。`
- データに関連する属性や情報を表現する場合に適しています。
:::
例:
```ruby
user = { name: "Alice", age: 25, email: "alice@example.com" }
puts user[:name]  # "Alice"
```
## 配列の使いどころ
:::note
配列の特徴と使いどころ：
- データを`順序付けされたリスト`として格納します。
- インデックス（位置）を使ってデータにアクセスします。
- データの順序が保持されるため、`データの順番が重要な場合`に適しています。
- データの`重複を許容`します。
- データの`追加や削除が容易`です。
:::
例:
```ruby
fruits = ["apple", "banana", "orange"]
puts fruits[0]  # "apple"
```

## 使い分けのポイント

- データの関連付けや属性を表現する場合は、ハッシュが適しています。
  例えば、ユーザーのプロフィール情報や商品の詳細情報など。

- データの順序やリスト形式が重要な場合は、配列が適しています。
  例えば、複数のオブジェクトの集合や処理の結果のリストなど。

ただし、特定のケースにおいてはハッシュと配列の両方を組み合わせて使用することもあります。例えば、配列の要素としてハッシュを格納し、それぞれのハッシュが異なる属性や情報を持つ場合などです。

最終的な選択は、データの性質と目的によって異なるため、具体的な要件とコンテキストに基づいて使い分ける必要があります。
ウィンドウ関数を使用してグループ毎の合計との比率を出すSQL

ウィンドウ関数を使う機会があまり多くなく、たまにウィンドウ関数を使った集約のSQLを書こうとして、いつも「ウィンドウ関数ってどうやって使うんだっけ？」と調べるのに飽きたので、自分用メモとして以下にまとめる。

尚、テスト環境はPostgreSQL 12である。

下記のような給与テーブル SAL がある。

|payday|divcd|empcd|salary|
|-|-|-|-|
|2023-11-20|1|1001|9000|
|2023-11-20|1|1002|8000|
|2023-11-20|1|1003|9000|
|2023-11-20|2|2001|7000|
|2023-11-20|2|2002|8000|
|2023-10-20|1|1001|9000|
|2023-10-20|1|1002|8000|
|2023-10-20|1|1003|9000|
|2023-10-20|2|2001|7000|
|2023-10-20|2|2002|8000|


この時、社員毎の給与合計を出すSQLは次のようになる。

```sql:社員毎の給与合計
SELECT
	divcd,
	empcd,
	SUM(salary) AS total_salary
FROM
	SAL
GROUP BY
	divcd, empcd
```

|divcd|empcd|total_salary|
|-|-|-|
|1|1001|18000|
|1|1002|16000|
|1|1003|18000|
|2|2001|14000|
|2|2002|16000|

この結果に、「その部署の給与合計に対するその社員の給与合計の割合」を追加したい。
つまり、各部署毎に発生している給与支払いの合計に対して、各社員の給与がどの程度の割合なのかを知りたい。

出力自体はdivcd+empcd単位なので、GROUP BY句をdivcdにするわけにはいかない。
divcd+empcd単位の処理の中で、divcd単位の処理を行いたい、ということになる。

この時、ウィンドウ関数を使用して次のようなSQLで抽出できる。

```sql:部署毎の給与合計に対する割合を追加
SELECT
	divcd,
	empcd,
	SUM(salary) AS total_salary,
	SUM(salary) / SUM(SUM(salary)) OVER (PARTITION BY divcd) AS salary_ratio
FROM
	SAL
GROUP BY
	divcd, empcd
```

|divcd|empcd|total_salary|salary_ratio|
|-|-|-|-|
|1|1001|18000|0.346153846|
|1|1002|16000|0.307692308|
|1|1003|18000|0.346153846|
|2|2001|14000|0.466666667|
|2|2002|16000|0.533333333|

上記で用いられているウィンドウ関数についてもう少し詳しく解説する。

```sql:ウィンドウ関数の部分
SUM(salary) / SUM(SUM(salary)) OVER (PARTITION BY divcd) AS salary_ratio
```

通常、**SELECT句に表示されるデータは、FROM句、WHERE句、GROUP BY句、ORDER BY句等で抽出・集約・ソートがされた後のデータ**となる。
例えば上記の例でいえば、divcdとempcdで集約（グルーピング）が行われており、divcd+empcd毎に異なる行が出力される。salaryは集約されているので、そのままでは出力できず、「グループ内の合計」を計算する集約関数SUMを使って`SUM(salary)`とすることで出力できる。

しかし今やろうとしているのは、divcd毎のsalaryの合計値を使って割合を計算したい、という話である。これはdivcd+empcd毎のデータではない為、そのままでは表現することができない。

そこで、ウィンドウ関数の登場である。

ウィンドウ関数は、今出力しようとしているデータの並びに対して何らかの単位でまとめて扱う、という機能を持つ。`PARTITION BY divcd`とすれば、divcd単位で結果をまとめて扱う。これはGROUP BY句による集約のさらに上位の集約であるが、SELECT句で出力しようとしているデータ行そのものには影響を与えない仮想的な集約である為、複数のPARTITION BYを指定することができる。

ウィンドウ関数は、まずウィンドウを定義（グループ単位、並び順、範囲等）を指定した後、その範囲に対して何らかの関数を指定する。SUMもそこで利用できる関数の一つである。

ウィンドウ関数で扱うことができる列は、現在のSELECT句で扱える列に限られる。
よって、次のように直接salaryをSUMするウィンドウ関数を書くと、「**salaryがGROUP BYに指定されてないから使えないよ**」と怒られる。

```sql:エラー「salaryがGROUP BYに指定されていない」
SELECT
	divcd,
	empcd,
	SUM(salary) AS total_salary,
	SUM(salary) / SUM(salary) OVER (PARTITION BY divcd) AS salary_ratio
FROM
	SAL
GROUP BY
	divcd, empcd
```

このSELECT句でsalaryを扱いたいのであれば、何らかの集約関数に入れる必要がある。この場合はdivcd+empcd単位の集約結果がSELECT句で扱われる入力データなので（GROUP BY句で指定している為）、その結果をさらにdivcd単位で合計したい、ということならば、SUM(salary)をさらにPARTITION BYでSUMする、という形になる。つまり、

```sql:誤
	SUM(salary) OVER (PARTITION BY divcd)
```

ではなく、

```sql:正
	SUM(SUM(salary)) OVER (PARTITION BY divcd)
```

が正しい。

ここで、`SUM(salary)`自体は、GROUP BY句によってdivcd+empcd単位でグルーピングされる際に計算される集約関数の結果であり、ウィンドウ関数の影響を受けていないことを意識しておくと理解が早まる。
Node.js: OracleDB のデータを更新 (Update)

## プログラム

```js:oracle_update.js
#! /usr/bin/node
//
//	oracle_update.js
//					May/10/2023
//
// ---------------------------------------------------------------
'use strict'
const oracledb = require('oracledb')
// ---------------------------------------------------------------
async function run() {
	console.error("*** 開始 ***")
	const id_in = process.argv[2]
	const population_in = process.argv[3]
	console.log(id_in + "\t" + population_in)

	let connection

	try {
		connection = await oracledb.getConnection( {
			user:		"scott",
			password:	"tiger123",
			connectString:	"172.17.0.2:1521/XEPDB1"
		})

	const sql = `UPDATE cities SET population = :1, date_mod = :2 where id = '` + id_in + `'`
	const row = [population_in, new Date()]
 
	const result = await connection.execute( sql,row)
	console.log(result)
	await connection.commit()
	console.error("*** 終了 ***")
	} catch (err) {
		console.error(err)
	} finally {
		if (connection) {
			try {
				await connection.close()
			} catch (err) {
				console.error(err)
			}
		}
	}
}

// ---------------------------------------------------------------
run()

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

## 実行コマンド

```bash
./oracle_update.js t0135 8952300
```

## 確認したバージョン

```text
$ node --version
v19.9.0
```
Jenkins

## Jenkins

オープンソースの継続的インテグレーションツール（CIツール）

##### Javaで開発されており、多くのプラグインが用意されている
アプリケーションのコードを自動的に
・ビルド
・テスト
・デプロイ
することができる

##### 複数の環境やプラットフォームで動作するため、さまざまなプロジェクトに対応できる
・バージョン管理システム
・コードレビューツール
・アーティファクト管理システム
・デプロイツール
などの機能も提供している
Node.js: OracleDB のデータを読む (Read)

## プログラム

```js:oracle_read.js
#! /usr/bin/node
//
//	oracle_read.js
//					May/10/2023
//
// ---------------------------------------------------------------
'use strict'
const oracledb = require('oracledb')

// ---------------------------------------------------------------
async function run() {

	console.error("*** 開始 ***")
	let connection

	try {
		connection = await oracledb.getConnection( {
			user:		"scott",
			password:	"tiger123",
			connectString:	"172.17.0.2:1521/XEPDB1"
		})

		const result = await connection.execute(
			`SELECT id, name, population, date_mod FROM cities`,
		)
	for (var it in result.rows)
		{
		const unit = result.rows[it]
		var str_out = unit[0] + "\t"
		str_out += unit[1] + "\t"
		str_out += unit[2] + "\t"
		const ddx = unit[3]
		const dd_str = ddx.getFullYear () + "-" + (ddx.getMonth () +1) + "-" + ddx.getDate ()
		str_out += dd_str
		console.log(str_out)
		}
	console.error("*** 終了 ***")

	} catch (err) {
		console.error(err)
	} finally {
		if (connection) {
			try {
				await connection.close()
			} catch (err) {
				console.error(err)
			}
		}
	}
}

// ---------------------------------------------------------------
run()

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

## 実行コマンド

```bash
./oracle_read.js
```
Node.js: OracleDB のデータを作成 (Create)

## プログラム

```js:oracle_create.js
#! /usr/bin/node
//
//	oracle_create.js
//					May/11/2023
//
// ---------------------------------------------------------------
'use strict'

const oracledb = require('oracledb')

// ---------------------------------------------------------------
async function run() {
	console.error("*** 開始 ***")

	let connection

	try {
		connection = await oracledb.getConnection( {
			user		: "scott",
			password	: "tiger123",
			connectString	: "172.17.0.2:1521/XEPDB1"
		})

	const sql_drop = `drop table cities`
	var result = await connection.execute(sql_drop)
	console.log(result)

	const sql_create = `create table cities (id varchar2 (10), name varchar2 (20), population number (10), date_mod date)`
	var result = await connection.execute(sql_create)
	console.log(result)

	const sql = `INSERT INTO cities VALUES (:1, :2, :3, :4)`

const binds = [
	["t0131", "函館", 83156, new Date("1950-10-4") ],
	["t0132", "札幌", 36892, new Date("1950-5-7") ],
	["t0133", "帯広" ,45271, new Date("1950-3-24")],
	["t0134", "釧路" ,21983, new Date("1950-8-17")],
	["t0135", "旭川" ,47614, new Date("1950-9-8")],
	["t0136", "北見" ,27969, new Date("1950-1-13")],
	["t0137", "室蘭" ,12634, new Date("1950-2-21")],
	["t0138", "根室" ,57685, new Date("1950-8-9")],
	["t0139", "稚内" ,31273, new Date("1950-10-2")],
    ]

const    options = {
      autoCommit: true,
      // batchErrors: true,  // continue processing even if there are data errors
      bindDefs: [
        { type: oracledb.STRING, maxSize: 10 },
        { type: oracledb.STRING, maxSize: 20 },
        { type: oracledb.NUMBER },
        { type: oracledb.DATE },
      ]
    }

    
	result = await connection.executeMany(sql,binds,options)
	console.log(result)

	await connection.commit()

	console.error ("*** 終了 ***")
	} catch (err) {
		console.error(err)
	} finally {
		if (connection) {
			try {
				await connection.close()
			} catch (err) {
				console.error(err)
			}
		}
	}
}

// ---------------------------------------------------------------
run()

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

## 実行コマンド

```bash
./oracle_create.js
```

確認したバージョン

```text
$ node --version
v19.9.0
```
IoT（モノのインターネット）の最新動向とエンジニアへのチャンスと課題

IoT（モノのインターネット）はますます普及し、エンジニアに新たなチャンスをもたらしていますが、同時に多くの課題も存在しています。

この記事では、IoTの最新動向を解説し、エンジニアに与えるチャンスと直面する課題を探ります。
IoT技術の進化による新たなビジネスモデルやサービスの可能性、エンジニアが取り組むべきセキュリティやプライバシーの課題などを詳細に解説します。
また、IoTを活用した社会課題の解決におけるエンジニアの役割についても考察します。
IoTに興味のあるエンジニアに向けた情報満載の記事です。

IoT（モノのインターネット）は、近年ますます普及し、多くの業界や分野で利用されています。IoT技術により、様々な機器やセンサーがネットワークに接続され、データの収集や分析、制御が可能になりました。これにより、新たなビジネスモデルやサービスが生まれ、社会に大きな影響を与えるようになりました。

IoTの最新動向としては、以下のようなものが挙げられます。

# １．5Gの普及による高速通信環境の整備
5Gは、従来の通信規格よりも高速な通信を実現することができます。これにより、IoT機器やセンサーからの大量のデータをリアルタイムで処理することが可能になり、新たなサービスやビジネスモデルが生まれることが期待されます。

# ２．AI（人工知能）や機械学習の活用
IoTから得られる大量のデータは、AIや機械学習を活用することで、より高度な分析や予測が可能になります。これにより、IoT機器やセンサーがより効率的に活用され、新たなサービスやビジネスモデルが生まれることが期待されます。

# ３．スマートシティの実現
IoT機器やセンサーを活用することで、都市の様々な問題を解決することができます。例えば、交通渋滞の軽減やエネルギーの効率的な利用などが挙げられます。これにより、より快適で持続可能な都市環境が実現されることが期待されます。

# ４．農業の効率化
IoT機器やセンサーを活用することで、農業の生産性や効率性が向上します。例えば、土壌の状態や気象データをリアルタイムで収集し、農作物の栽培計画を最適化することが可能です。

このようなIoTの最新動向により、エンジニアには新たなチャンスが生まれています。例えば、IoT機器やセンサーの設計・開発、通信プロトコルの開発、AIや機械学習の開発などが挙げられます。また、IoTを活用した新たなサービスやビジネスモデルの開発にもエンジニアの力が必要です。IoTに関するスキルや知識を持つエンジニアは、今後ますます需要が高まることが予想されます。

しかしながら、IoTには多くの課題も存在しています。その中でも最も大きな課題は、セキュリティやプライバシーの問題です。IoT機器やセンサーは、ネットワークに接続された状態で常に稼働しているため、セキュリティ上の問題が発生すると、その影響は大きなものとなります。例えば、IoT機器をハッキングされると、個人情報が漏洩したり、攻撃者による制御を受けたりする可能性があります。

プライバシーの問題も、IoTが普及するにつれて重要性が高まっています。IoT機器やセンサーは、常にユーザーの行動や状態を収集しているため、そのデータが不適切に扱われるとプライバシー侵害につながる可能性があります。

このようなセキュリティやプライバシーの問題に対応するためには、エンジニアによるセキュリティ対策やプライバシー保護技術の開発が必要です。IoT機器やセンサーの設計・開発から、通信プロトコルの設計、クラウドサービスのセキュリティ対策まで、様々な領域でエンジニアの力が必要とされます。

また、IoTを活用した社会課題の解決においても、エンジニアには大きな役割が求められています。例えば、スマートシティや農業の効率化など、IoTを活用して社会課題を解決するためには、エンジニアが現場での課題を理解し、最適なソリューションを提供することが必要です。

IoTに興味を持つエンジニアにとって、今後ますます需要が高まる技術領域であることは間違いありません。しかしながら、IoTに関連する課題に対応するためには、常に最新の知識やスキルを身につけることが求められます。また、IoTの技術だけでなく、セキュリティやプライバシーに関する知識や、社会課題についての理解も必要です。

最近では、IoTに特化したプログラミング言語やフレームワークなども登場しており、IoTに取り組むエンジニアにとっては、これらの技術を学ぶことも有用です。

さらに、IoTに取り組む上で重要なのは、単なる技術開発だけでなく、ビジネスや社会的な視点も持つことです。IoTが生み出す新たなビジネスモデルやサービスを考える際には、ビジネスモデルキャンバスやデザイン思考などの手法を活用することが有効です。

まとめると、IoTはますます普及し、エンジニアにとって新たなチャンスが生まれています。しかし、同時にセキュリティやプライバシーの問題など、多くの課題も存在しています。IoTに取り組むエンジニアには、最新の技術だけでなく、ビジネスや社会的な視点も持つことが求められます。今後もIoT技術の進化に注目し、様々な課題に対応するために必要なスキルと知識を身につけていくことが重要です。

# まとめ
IoT（モノのインターネット）は、近年ますます普及し、多くの業界や分野で利用されています。IoT技術により、様々な機器やセンサーがネットワークに接続され、データの収集や分析、制御が可能になりました。これにより、新たなビジネスモデルやサービスが生まれ、社会に大きな影響を与えるようになりました。

IoTの最新動向としては、5Gの普及による高速通信環境の整備、AIや機械学習の活用、スマートシティの実現、農業の効率化などが挙げられます。

IoTに関連する課題としては、セキュリティやプライバシーの問題があります。これらに対応するためには、エンジニアによるセキュリティ対策やプライバシー保護技術の開発が必要です。

IoTを活用した社会課題の解決においても、エンジニアには大きな役割が求められています。例えば、スマートシティや農業の効率化など、IoTを活用して社会課題を解決するためには、エンジニアが現場での課題を理解し、最適なソリューションを提供することが必要です。

IoTに興味を持つエンジニアにとって、今後ますます需要が高まる技術領域であることは間違いありません。しかしながら、IoTに関連する課題に対応するためには、常に最新の知識やスキルを身につけることが求められます。また、IoTの技術だけでなく、ビジネスや社会的な視点も持つことが重要です。

# 最後に
エンジニアの皆さん、エンジニア未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
【TypeScript】型定義1 (プリミティブ型、リテラル型など)

## はじめに
TypeSctipt勉強中の👶です。
理解を深めるために日々の学びを記事にしています。
初心者の記事なので言い回しや記載に誤りがあるかも知れませんが、暖かく見守っていただけると幸いです。
まだ学習半ばなので、学習進めていく上でこの記事も工事🚧するかもしれません。
<font color="gray">(よろしければ間違いをコメントいただけると学び、励みになります！)</font>

## 学んだこと
- 静的型付け言語とは
- プリミティブ型
- リテラル型
- any型
- ユニオン型


## TypeScriptは静的型付け言語
動的型付け言語けは実行時に初めて決まります。
対して、静的型付け言語はコンパイル時にエラーで出力されるので、おかしな代入をしていたり、変数名を誤字っていたりすると早期発見できます。型定義でバグを事前に防げる点から、型安全性と呼ばれTypeScriptの利点によく挙げられます。

## 変数宣言
型を指定することを型注釈(type annotation; 型アノテーション)といいます。
```ts
const 変数: 型 = 式;
```

## プリミティブ型
```ts
const text: string = "abc";
const num: number = 111;
const isPanda: boolean = true;
const x: null = null;
const y: undefind = undefind;
const bignum: bigint = 9007199254740992n;
const sym: Symbol = Symbol();
```

### BigInt型 (補足)
- 任意精度の整数が対象。小数などは使用不可。
- 大きな整数値を表したい時に使用できる。
- `number型`と併用が不可。
- `number型`より処理が重い。
- 比較的新しい機能で古いブラウザで利用できない。


### シンボル型 (補足)
シンボルとは、一意性を示す値のことです。
下記の場合、同じ`string型`の`"foo"`という値が入っているが、`s1`と`s2`で定義が異なるのでシンボル値の比較`s1===s2`は`false`を返します(型は一緒、値が違う)。
```ts
const s1: symbol = Symbol("foo");
const s2: symbol = Symbol("foo");

console.log(s1 === s1); //=> true
console.log(s1 === s2); //=> false
```

## リテラル型
特定の値だけを代入可能にする型。
```ts
// true以外が代入されるとエラーになる
const isTrue: true = true;
const isTrue: true = false; // =>エラー

// 数値の123以外が代入されるとエラーになる
let num: 123 = 123;
num = 55; //=>エラー
```

## 型推論
型注釈を省略しても勝手に解釈してくれます。型推論できない場合は、`any型`が付与されます(後述)。
```ts
const str = "foo"; // =>’foo’型と推論される
let str = "bar";　 // =>string型と推論される
```

## ユニオン型
2つ以上の型を定義したいときに使用します。`｜`を or みたいなニュアンスで使用できるんですね。
```ts
let numberOrUndefined: number | undefined;
```

## any型
どんな型でも代入できる型。コンパイラーの型チェックから外れます。
文字列型の値に対して数値型のメソッドを使用する、など明らかな矛盾以外はコンパイラーが警告しなくなります。
型を省略して、コンテキストから型推論できない場合も暗黙的に型をanyとして扱います。any型をチェックしたい場合、`tsconfig.json` にて `noImplicitAny: true` を設定することで、TypeScriptが型をany型と推測した場合にエラーが発生するようになります。


## 参考
下記を参考に勉強させていただきました🌱
[TypeScriptの型入門 - Qiita](https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a)
[TypeScript入門『サバイバルTypeScript』〜実務で使うなら最低限ここだけはおさえておきたいこと〜](https://typescriptbook.jp/)
Flutter + NCMB + OpenAIで画像生成アプリを作る（その1: アプリの仕様とNCMBの初期化）

NCMBでは公式SDKとしてSwift/Objective-C/Kotlin/Java/Unity/JavaScript SDKを用意しています。また、それ以外にもコミュニティSDKとして、非公式ながらFlutter/React Native/Google Apps Script/C#/Ruby/Python/PHPなど幅広い言語向けにSDKが開発されています。

今回はコミュニティSDKの一つ、Flutter/Dart SDKを使ってOpenAIの画像生成APIを用いたAI画像生成アプリを作ってみます。まず画面の仕様とSDKの初期化について解説します。

## コード

今回のコードは [NCMBMania/flutter-image-gen](https://github.com/NCMBMania/flutter-image-gen) にアップロードしてあります。実装時の参考にしてください。

## 利用技術について

今回は次のような組み合わせになっています。

- Flutter
- NCMB
- OpenAI API

## 仕様について

今回のアプリは以下のような機能があります。

- チャット画面
- OpenAI APIを使って画像を生成
- 生成した画像をファイルストアに保存
- メッセージとファイル名を紐付けてデータストアに保存

## 利用する機能について

このAI画像生成アプリで利用しているNCMBの機能は以下の通りです。

- データストア
    - データ登録
    - データ検索
- ファイルストア
    - ファイルアップロード
    - ファイルダウンロード
- スクリプト
    - OpenAI APIの実行

## 画面について

現時点で、画面は以下の1つのみです。

### チャット画面

チャット画面は[flutter\_chat\_ui | Flutter Package](https://pub.dev/packages/flutter_chat_ui)を使っています。

![localhost_55761_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/b926061c-2fba-1d61-ea90-a0ed28606d17.png)


### SDK・ライブラリのインストール

利用する各種ライブラリをインストールします。

```
flutter pub add flutter_chat_ui
flutter pub add ncmb
```

## NCMBのAPIキーを取得

[mBaaSでサーバー開発不要！ | ニフクラ mobile backend](https://mbaas.nifcloud.com/)にてアプリを作成し、アプリケーションキーとクライアントキーを作成します。

## 初期化

初期化は lib/main.dart にて行います。

```dart
import 'package:ncmb/ncmb.dart';

void main() {
  // NCMBの初期化
  NCMB('YOUR_APPLICATION_KEY',
      'YOUR_CLIENT_KEY');
  runApp(const MyApp());
}
```

これでNCMBの初期化が完了します。

## 画面の読み込み

チャット画面をChatPageとして、MyAppのbuildで読み込みます（チャット画面は次回作ります）。

```dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Image Gen App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ChatPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}
```

## まとめ

今回はAI画像生成アプリの仕様と画面、NCMBの初期化までを解説しました。[次回はOpenAI APIの呼び出し（スクリプト）について解説](https://qiita.com/goofmint/items/b76f08d149f6ed1e7aec)します。
Playwrightでローカルファイルを読み込む

# Playwrightでローカルファイルを読み込む

:::note info
typescript 5.0.4
playwright 1.32.2
:::

## まとめ

`page.goto(htmlPath)`でHTMLファイルのパスを渡す。

## そもそも

利用しているライブラリが`playwright`ではなく、`@playwright/test`なのであれば設定の`baseUrl`を利用すれば実現できる。

:::note info
`playwright`はブラウザ操作APIで、
`@playwright/test`はその`playwright`を用いたテストランナー
:::

## サンプル

```html
<html>
  <head>
    <meta charset="utf-8" />
    <title>Playwrightでローカルファイルを読み込む</title>
  </head>
  <body>
    <div>
      <p id="p1">hoge</p>
      <p>fuga</p>
      <p>hoge</p>
    </div>
  </body>
</html>
```

```typescript
import path from "path";
import { chromium } from "playwright";

void (async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  const htmlPath = `file://${path.join(__dirname, `../resources/index.html`)}`;
  await page.goto(htmlPath);
  
  const title = await page.title();
  console.log(title);
  const p1 = await page.locator('p#p1').innerText();
  console.log(p1);
  const countOfHoge = await page.locator('p:has-text("hoge")').count();
  console.log(countOfHoge)

  await browser.close();
})();
```

↓実行結果↓

```
Playwrightでローカルファイルを読み込む
hoge
2
```

## 参考

- [Playwright/Test configuration](https://playwright.dev/docs/test-configuration#global-configuration)
- [Node.js/Modules(__dirname)](https://nodejs.org/docs/latest/api/modules.html#__dirname)
- [サンプルコード](https://github.com/rokumura7/qiita_sample/tree/main/playwright_local)
【学習】Ruby on Rails チュートリアル 第7版 - 第2章Toyアプリケーション

5/11 8:10

・scaffoldジェネレータを使用しアプリケーションを生成
＊データモデルを設計
手戻りが防げて便利な為、最初に行う

↓でアプリケーションを生成
rails generate scaffold モデル名 カラム:データ型

↓マイグレート
rails db:migrate


**エラー発生**
rails generate scaffoldでファイルを作成した後に処理をやり直そうとしたらつまづいたのでまとめ。 
 
事象
/usersが開けなかった

原因
scaffoldを作成したときにrouteが自動生成される。
AWSから↑を反映しますか?とポップが出たが、
routeを反映しないを選択してしまった。

エラーが出たときの処理概要
$ rails generate scaffold hoge
$ rails db:migration
$ rails destroy scaffold hoge
$ rails generate scaffold hoge
$ rails db:migrate (エラー)
 
調べてわかったこと
rails generateで作成されたファイルは、rails destroyで削除できるが、削除前にマイグレーションしたかどうかで元に戻す手順が違う。
 
対応策１：マイグレーション前にファイル削除実行
$ rails generate scaffold hoge
$ rails destroy scaffold hoge
 
対応策２：マイグレーション後はロールバックしてから削除
$ rails generate scaffold hoge
$ rails db:migrate
$ rails db:rollback
$ rails destroy scaffold hoge
 
対応策３：先に削除したときはデータベースをリセット
$ rails generate scaffold hoge
$ rails db:migrate
$ rails destroy scaffold hoge
$ rails db:migrate:reset
この場合はデータベースにデータがあったときは消える


2.2.1まで終了

5/11 8:20


5/11 20:00　開始

＊MVC(Model-View-Controller)の挙動確認
*Micropostsリソースをscaffoldでコードを生成
usersと同様の手順

2.3.1まで終了

5/11 20:45　終了


5/12 8:15 開始

・Toyアプリケーションのmodelについて
model内で、バリデーション（validation）を使って簡単に制限を加えることができる。
app/models/micropost.rb

↓マイクロポストの最大文字数を140文字に制限する。
validates :content, length: { maximum: 140 }

*データモデル同士の関連付けをmodel内に表現できる。
1人のUserは、複数のMicropostをもつ
　→has_many :microposts
Micropostは、1人のUserに属する
　→belongs_to :user

演習
1.ユーザーのshowページを編集し、ユーザーの最初のマイクロポストを表示してみましょう。
2.以下を追記した結果、マイクロポストが空でないことを検証できているかどうか、実際に試す。
　presence: true
3.以下を追記し、Userモデルのnameとemailが存在していることを検証
 validates :name, presence: true   
 validates :email, presence: true


*継承
生成したmodel,controllerはそれぞれ↓のように継承されている。
　User < ApplicationRecord < ActiveRecord::Base 
　UsersController < ApplicationController < ActionController::Base

これにより
モデルオブジェクトは、データベースにアクセス
コントローラは、モデルオブジェクトの操作や、送られてくるHTTP requestのフィルタリング
などの機能が実行できる。

・Toyアプリケーションをデプロイ
↓に設定ファイルを作成し、ビルドコマンドを記述。
　bin/render-build.sh

　Renderでデプロイする際、Build Commandに↓を指定する。
　./bin/render-build.sh

第2章終了

5/12 9:15　終了