OmniAICreator/Qiita-1.07M huggingface dataset:
|2x−5|+|2x+3|<10「21年 青森公立大 1(3)」5行で計算できました。

(2023/08/09)修正版あります。

https://qiita.com/mrrclb48z/items/4bc40e90116687d17d23

# --------------------------------------------------------
オリジナル
標準的な方法　場合分け

https://kamelink.com/blog/2022/04/02/1-3-21aomorikouritudai-1-3/

上と同じです。大学入試数学問題集成＞

https://mathexamtest.web.fc2.com/2021/202111051/2021110510100mj.html#top-0103



# wolframalphaで
グラフがでます。

https://www.wolframalpha.com/input?i=%7C2x+%E2%88%92+5%7C+%2B+%7C2x+%2B+3%7C+%3C+10&key=537gn&lang=ja

# 計算

汎用性がありますか?
場合分けをしないで、数直線上の(-3/2)と5/2からの距離の合計です。
5行で計算できました。
答えは一致しました。

```
|2x-5  |+|2x+     3|<10
| x-5/2|+| x-(-3/2)|<5
5/2-(-3/2)=4
(-3/2)-(5-4)/2<x<(5/2)+(5-4)/2
-2<x<3
```
以下の方がわかりやすいですか?距離の合計が5以下でした。
6行でした。
```
|2x-5  |+|2x+     3|<10
| x-5/2|+| x-(-3/2)|<5
(-3/2)-x + (5/2)-x=5
小さい方のx=-2
x-(-3/2) + x-(5/2)=5
大きい方のx=3
```
絶対値が2個よりも多くても大丈夫のはずです。
いくつあっても一次式のはずです。


# 過去問(絶対値記号を含む1次不等式) 

https://kamelink.com/exam/index.php?%BF%F4%B3%D8I%A1%A6A%A5%C1%A5%A7%A5%C3%A5%AF%A1%F5%A5%EA%A5%D4%A1%BC%A5%C8%A1%A1%C2%E83%BE%CF%A1%A1%A1%F81%CA%FD%C4%F8%BC%B0%A1%A6%C9%D4%C5%F9%BC%B0%A4%CE%B2%F2%CB%A1%A1%A16.%C0%E4%C2%D0%C3%CD%A4%F2%B4%DE%A4%E01%BC%A1%C9%D4%C5%F9%BC%B0
Atmel Studio 7とAVR

久しぶりにAtmel Studio 7でAVRを触ってみました。
数年前までAtmel Studio 6だったのですが、今のPCには開発環境が入ってないので、新たに7をインストール。

なんと7ではDragonが動きません。
2台あるDragonのどちらも動かず。
JTAGICE3 は無事に動いたので、これでの開発です。
Markdownに慣れてないので、[こちらに書きました。](https://yokaton.com/mcu-202301-avr1/)
2023/1/30主にITとかセキュリティの記事

サイバー攻撃で電源オフはNG　時代遅れの日本の教育(1/28)
https://www.nikkei.com/article/DGXZQOUC18CS10Y3A110C2000000/

LINEアカウントが乗っ取られる原因は？被害に遭わない4つの予防策(1/28)
https://news.yahoo.co.jp/articles/dc372d3687ed3b5bab96b845af818caa04752a3c?source=rss

「年金」にまつわる詐欺にはどんなものがある？ 被害にあわないように確認しておこう！(1/28)
https://news.yahoo.co.jp/articles/5edbfbd3435e90e38269b3bed85ccefa4a7b640a?source=rss

ITmedia Mobile人気記事より：スマホのアップデートで「やってはいけないこと」とは？(1/28)
https://news.yahoo.co.jp/articles/5d903dffb705ac14181fa133dd86d6ec3204a133?source=rss

英当局、慈善団体狙うフィッシングとランサムウェアに関する脅威レポート公開(1/28)
https://news.mynavi.jp/techplus/article/20230128-2572358/

Google Ads悪用してマルウェア配布する手口に注意、Google検索上位に悪意あるサイト(1/28)
https://news.mynavi.jp/techplus/article/20230128-2577409/

悪質な「詐欺DM」がTwitterで急増中…その文面が雑すぎる「恐ろしい理由」(1/28)
https://news.yahoo.co.jp/articles/fc79592f1c40d7eb1e3dd5bba1abe8b0fe516c2d?source=rss
他人と自分を比較する意味

# 忙しい人のために
プロジェクトや仕事の中では他人との比較にあまり意味はない。　自分の得意なことで貢献する・貢献できるプロジェクトや職場を探すのが吉。

---
一眠りして頭が冴えた。

職場外のweb勉強会に参加すると、参加されてる方はそれぞれ自分が得意なところで発表をしていて、だからこそ学びがあります。 

# プロジェクトのベクトル空間
ところで、世の中のほとんどのプロジェクトって、完成させるにはコアとなるスキルの他にさまざまなスキルが必要。ふとベクトル空間だとよく表現できるなと思いました。

たくさんの軸（スキル）がないとのプロジェクトの目指す空間を形づくれない。 X方向が得意でもYはそうでもない人、Y方向だけが得意な人、Z方向だけが得意な人、それぞれの人のスキルセットとそのつよつよ度で構成されるのがそれぞれの人ベクトル。

プロジェクトメンバのベクトルを含む空間がプロジェクトの成果物のもと。

# 他人との比較(内積)に意味があるか
人と自分を比較するのは、違う方向を向いている多次元ベクトルの内積をとるようなもので、他人のベクトルと同じベクトルを持っている人でない限り、内積を取る（比較する）すればちっさくなる時がほとんどでしょう。IQ高ければ他人軸で自分を評価しても大きくなることもあるけど、それはそれで。

でも他人軸など特定の方向で比較（自分を評価）する意味ある？ってなる。 （プロジェクトの必要としている軸はそこだけじゃない）違う方向向いてるから比較には意味がないんだと、ここまではなんとなく理解。 

# プロジェクトは外積
神でもいないかぎり、違う方向を向いているベクトル（人）がたくさんいないと多様な軸を必要とするプロジェクト空間を構成できない。、マネジメントが不足している軸を足したり、メンバが学んで軸を増やすこともあるかもしれない。

多くのプロジェクトに必要なのは、違う方向を向いているベクトル（人）の内積（比較。比較後の一つの数字）ではなくて外積（結果の空間、指し示す方向）。（最初に学校で学んだときから外積って何の意味ある？ってずっと思ってたけどここで自分ようやくわかった。時間かかった）

# 自分のベクトルの向きを知る
自分が変わったり、異業種・異職場コミュニケーションするということは新しい軸を足して評価する（興味があるか試してみる）ことになる。新しい軸を足すと、これまでと違うベクトルとの内積が新しくちょこっと生まれてそこのところが案外面白かったり、得意だったりする。 自分では気がつかなくても、他人が「そこいいよ」って教えてくれることも。

自分探しをするとか、世の中に無駄な人間いないとか、勉強会面白いというけど、ベクトル空間でいうとこういうことなんだなと思いました。他人と自分を比較する意味はあまりなくて、特定の軸をためす学校のテストで人間自身が評価されるわけではないことも同じ。

自分の得意なベクトルが何か探していけば（=旅、交流会、バイト、インターンでもいろいろなベクトルと関わって内積してみる＝未知の自分の方向と合っているのかを評価してみる）と徐々に自分のベクトル方向が見つけられる。

Web（に限らず）の社外の勉強会って誰一人同じベクトルをもっていないからこそ広がりがあって刺激もあるし、学びがある。

### 勤め人の愚痴とは
会社員だとなかなか内積試す機会なくて、自分のベクトルがわからずに与えられたベクトルで働くから足りない分(本来発揮できる自分が発揮できてない分）が愚痴になるのでは？　

不満があるのなら、自分がそこでいけてないと思うならフリーランスになれと思ってる人です。ずっと自分のベクトルを探しやすい。　いいマネジメントに出会えればそれもよし。

# ChatGPTにも聞いてみた
ChatGPTに聞いてみるともうちょっとソフトな表現で答えてくれる。　　そもそもAI/機械学習って、多次元空間から力ずくの積和演算の繰り返しでよさげな答えを出してくるというしくみは、人に「いろいろ経験してみて自分見つけて」というのと同じことのように思える。

でも、自分的には自分で解釈する多次元ベクトルの内積と外積がより簡単に世の中を表せそうでしっくりきました。　


# マネジメント
部下自身もしらないその人のベクトルを見極めて伸ばせば人も組織も大きくなる。それが小さな組織のマネジメントの一要素。

# まとめ
他人と自分を比較する意味はほとんどない。

自分のベクトルわかれば、適切な場所（職場・プロジェクトに）自分を高くうれる（営業できる、就職できる）。 

就活生や仕事を探す人に勝手にエール。
いいね機能の非同期化

# １．非同期機能とは
- 画面全体を更新せずに、一部だけ更新すること
- Ajaxという手法が使用されます。

# ２．実装
### ２−１.リンクに`remote: true`を追記する
- これにより、リクエストがhtml形式からjs形式になる
```:app/views/posts/show.html.erb
<% if current_user && @post.favorited_by?(current_user) %>
  <%= link_to post_favorites_path(@post), method: :delete, remote: true, class: "favorite_btn" do %>
  ♥<%= @post.favorites.count %> いいね
  <% end %>
<% else %>
  <%= link_to post_favorites_path(@post), method: :post, remote: true, class: "favorite_btn" do %> #ここ
  ♡<%= @post.favorites.count %> いいね
  <% end %>
<% end %>
```

### ２−２．ボタンを部分をテンプレート化する
- ２−１の部分を切り取り`views/favorites/_favorite.html.erb`というファイルを作成
- 部分テンプレートのファイルではインスタン変数を使用することは適切ではないのでローカル変数で記述する。
```:views/favorites/_favorite.html.erb
<% if current_user && @post.favorited_by?(current_user) %>
  <%= link_to post_favorites_path(post), method: :delete, remote: true, class: "favorite_btn" do %>
  ♥<%= post.favorites.count %> いいね
  <% end %>
<% else %>
  <%= link_to post_favorites_path(post), method: :post, remote: true, class: "favorite_btn" do %>
  ♡<%= post.favorites.count %> いいね
  <% end %>
<% end %>
```

### ２−３．先程の部分テンプレートを呼び出すための記述をする
- ここでは、部分テンプレート自体にidをつけ投稿ごとにいいねをできるようにしている。
- これがないと、すべての投稿に対していいねをおこなってしまう.
```:views/posts/show.html.erb
<div id="favorite_btn_<%= @post.id %>">
    <%= render 'favorites/favorite', post: @post %>
</div>
```

### 2-4.JavaScriptファイルを作成
- `remote: true`の設定により、リクエストがhtml形式ではなくjs形式になっているので対応するファイルを作成する
- 以下を新規で作成

```:views/favorites/create.js.erb
$('#favorite_btn_<%= @post.id %>').html("<%= j(render partial: 'favorites/favorite', locals: {post: @post}) %>");
```

```:views/favorites/destroy.js.erb
$('#favorite_btn_<%= @post.id %>').html("<%= j(render partial: 'favorites/favorite', locals: {post: @post}) %>");
```

以上で、非同期通信を実装できる

# 3.さいごに
- フォロー機能なども同様の手順で非同期化を実装できます。
Waveshare 3.5inch LCD を Raspberry Pi Pico と LovyanGFX で動かす方法

https://www.switch-science.com/products/7330

Raspberry Pi Pico が後ろにがっちゃんこできるようになってて MicroPython とか Arduino から SPI 接続のデバイスとして絵が出せる。

製造元の [Waveshare のサイト](https://www.waveshare.com/wiki/Pico-ResTouch-LCD-3.5)から Arduino や MicroPythoon のサンプルコードがダウンロードできる。

Arudino のコードは [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) を使う前提でそれようのコンフィグが用意されてる。

しかしどうせならより洗練されて高速に動作する [LovyanGFX](https://github.com/lovyan03/LovyanGFX) を使いたい、んだけどデフォルトままでは動作しないし設定ファイルも見つからない、ということで TFT_eSPI 用の設定ファイルを参考に LovyanGFX 用のコンフィグを作った。

バックライトやタッチパネルはちょっといじっただけでは動作しなかったのでとりあえず LCD パネルのみの設定。必要そうになったらまた調べて更新するつもり。

https://gist.github.com/Saqoosha/f2f11dbd4baee371b58aa6b91e528371
Express body-parserってなんなの？

最近Expressを始めた。と言う人の中には 
`body-parser`ってなに？と言う人がいるんじゃないかと思いました。
私も最近まで`body-parser`が何か知りませんでした。 
Expressの記事を読んでいると結構でてくるんですけどね...

## 結論
```js
// 下記2つは全く一緒です。
app.use(express.json())

app.use(bodyParser.json())
```

`Express v 4.16`から標準で`bodyParser`が使えるようになりました。`express.json()`で
書き方は違いますが、同じものを使っているので全く一緒らしいです。
今後は`bodyParser`を自前でインストールする必要はないです。
`express v 4.16`より下のバージョンを使うときのみインストールが必要です。

```js
// もちろん下記も一緒です。
app.use(express.urlencoded({ extended: true }));

app.use(bodyParser.urlencoded({ extended: true }));
```

## 終わりに
私みたいにYoutubeやUdemyでExpressを学習をすると、最近は`express.json()`を使っているものが多いので、`body-parser`に触れることがなく、自分でネットの記事を漁るときに迷っちゃいますね。
DNSサーバ　フルリゾルバ・権威サーバについて

DNSサーバには主に2つの機能がある。
・名前解決検索要求を受け取り、他のDNSサーバに問い合わせを行う「フルリゾルバ」機能（応答結果をキャッシュしておき、キャッシュがあればそれを返すため「キャッシュサーバ」とも呼ばれる）
・自身の管理するドメインの情報を公開する「権威サーバ」機能（「コンテンツサーバ」とも呼ばれる）

キャッシュサーバは自身のキャッシュ（過去の問い合わせ結果）にあればその内容を回答し、なければ名前解決処理を反復して行う。その結果、最終的に名前解決に成功すればIPアドレスを返し、失敗した場合は「存在しない（NXDOMAIN）」などのエラー応答を名前解決の要求元に返答。

コンテンツサーバは自身が管理するドメインに関する問い合わせに対して回答を行う。自身の管理しないドメインに関する問い合わせに対しては「存在しない（NXDOMAIN）」を返答。コンテンツサーバが管理するドメイン情報のことを「ゾーン」と呼び、DNSサーバが読み込むゾーン情報のファイルを「ゾーンファイル」と呼ぶ。

ゾーンには以下の2つの種類。
・正引きゾーン：名前（FQDN）からIPアドレスを検索
・逆引きゾーン：IPアドレスから名前（FQDN）を検索
MIMEタイプって何者？

MIMEタイプについての備忘録になります。

# MIMEタイプとは
Web上ではデータの形式を示すものとして、拡張子の他にもう一つ **MIMEタイプ**（マイムタイプ）があります。
Webサーバとブラウザの間でやりとりする際に、このMIMEタイプを用いてファイルデータの形式を指定します。

# MIMEタイプの形式と種類
MIMEタイプは以下の形式で構成されます。

**`タイプ/サブタイプ`**

「タイプ」がファイルの大きな分類で、「サブタイプ」がファイルの種類を表しています。
主なMIMEタイプの例を記載します。

<table>
  <thead>
    <tr>
      <th>拡張子</th>
      <th>文書の種類</th>
      <th>MIMEタイプ</th>
    </tr>
  </thead>
  <tr>
    <td>.htm <br> .html</td>
    <td>ハイパーテキストマークアップ言語（HTML）</td>
    <td>text/html</td>
  </tr>
  <tr>
    <td>.png</td>
    <td>Portable Network Graphics</td>
    <td>image/png</td>
  </tr>
  <tr>
    <td>.pdf</td>
    <td>Adobe Portable Document Format（PDF）</td>
    <td>application/pdf</td>
  </tr>
  <tr>
    <td>.zip</td>
    <td>ZIP アーカイブ</td>
    <td>application/zip</td>
  </tr>
</table>
※引用

https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types

# MIMEタイプとブラウザ処理
ブラウザがURLにアクセスした際、WebサーバはHTTPヘッダの「Content-type」にMIMEタイプを設定して、レスポンスを返します。
```
Content-Type: text/html; charset=utf-8
```

このとき、Webサーバが指定したMIMEタイプに合わせてブラウザの処理が変わります。
例えば、MIMEタイプに「text/html」を指定した場合、ブラウザはファイルをHTMLとして表示します。

ちなみに、Webサーバ側でレスポンスファイルの形式が定まっていないときの規定値として「application/octet-stream」というMIMEタイプがあります。
上記の場合、ファイル形式が指定されていないとして、ブラウザ側はファイルのダウンロードを行います。

---
参考になれば幸いです。

# 参考文献
・MIME タイプ (IANA メディアタイプ) - HTTP - MDN Web Docs
https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types

・拡張子とMIMEタイプ - とほほのWWW入門
https://www.tohoho-web.com/wwwxx015.htm
Seleniumを用いてkindleハイライトを取り出す。（未完成）

## はじめに
　amazon kindleで本を読んでいる方なら、highlight(強調線)を引くことがたまにあると思う。
　rubyにおいてのkindle-highlights関連ライブラリは、スクレイピングするためにMechanizeを用いているが、 個別で本の情報を取り出そうとなるとasin（アマゾン独自の商品識別番号）が必要となる（多分）。これを改良したいと思い、コードを書いた。
　
　スクレイピング用ライブラリとしてSeleniumを用いてkindleのhighlightを取り出すことが出来たので、皆さんの参考になればと考えている。今回は、すべての本のhighlightを取り出ところまで出来た。今後、書籍名か作者名だけで書籍を特定し、その書籍のhighlightだけを取り出すように改善したい。

## 早速ソースコード

~~~kindle_highlights.rb
require 'selenium-webdriver'

require 'dotenv'

Dotenv.load

EMAIL = ENV['KINDLE_ID']
PASSWORD = ENV['KINDLE_PW']

def main
    #ドライバのインスタンスを生成
    driver = Selenium::WebDriver.for :firefox 
    
    #urlを取り出す。
    driver.get ENV['KINDLE_READ_URL']
    
    #URLからemailとpasswordのボックス要素を取り出し、文字列を入力する。
    email_box = driver.find_element(:name,'email')
    email_box.send_key EMAIL
    pwd_box = driver.find_element(:name, 'password')
    pwd_box.send_key PASSWORD
    
    #POSTを送るボタン要素を探し出しクリックする。
    #サイトのHTMLに<form>..</form>要素が存在するなら、
    # submitメソッドを使ってもよい。
    #その際には、find_element(:xxxx,'formを識別できるclass、idなど')と使う。
    #（多分）
    driver.find_element(:id,'signInSubmit').click
    
    #全ての本のseleniumインスタンス？を取得。
    each_books = driver.find_elements(:class,'kp-notebook-library-each-book')
    
    #ロード時間にドライバを操作させないためにWaitインスタンスを生成。
    wait = Selenium::WebDriver::Wait.new(:timeout => 10)

    book_hash = {}
    each_books.each do |book|
        text_array = []
        
        #各々の本をクリックすることによって、そのハイライトを表示する。
        book.click
        #クリックされた後、ロード時間を待たないでfind_elementを使うと、
        #以降の要素を操作することが出来ず、ElementNotInteractableError
        #が発生する。
        #そのために、h3タグ（書籍の題名）が操作可能になるまで待つ。
        wait.until {driver.find_element(:tag_name, 'h3').enabled?}
        
        #書籍名とテキストを取り出す。後者は配列。
        book_title = driver.find_element(:tag_name,'h3')
        highlights = driver.find_elements(:id,'highlight')

        highlights.each do |highlight_text|
            text_array << highlight_text.text
        end
        book_hash[book_title.text] = text_array
    end
    
    driver.quit
    
    book_hash
    
end

puts main

~~~

　このコードは実際、 wait.until {driver.find_element(:tag_name, 'h3').enabled?} 以外は極めて基本的である。上記されているように、この工程を行わないと、ロードされている間ドライバはh3タグを発見することが出来ないためエラーが出る。

~~~
#エラーが出るコード
book_title = driver.find_element(:tag_name,'h3') # <-ここでエラー
wait.until(book_title.enabled?)
~~~


## 出力
![出力.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2764361/4b5a6a4e-bbb5-b2ff-330f-3c6e32b0df17.png)

## 注意点

何度も繰り返すとamazonさんにばれて人しか認識できない文字の認証をしてくる。それでも繰り返すと利用規約も一緒にポップするので時間をおかなくてはならなくなる。

解決法はブラウザを閉じないこと。重くなるかもしれないが、なぜか何回もチャレンジできた。
Macで使うpeco

完全に自分用のメモですが、よろしければどうぞ的なやつです。
環境は Mac OS Ventura 13.2です。
以下を参考に動かないところは動くように、また自分の好みに少しだけ修正しました。（先人に感謝）
動かなかったのはcdr+pecoです。一番下に修正箇所について記載しておきました。
自分の好みにしたのはhistory+pecoです。コマンドを選択する度に画面がclearされるのが嫌だったので、そこだけ直しました。

[pecoを使って端末操作を爆速にする](https://qiita.com/reireias/items/fd96d67ccf1fdffb24ed)
[zshとpecoでコマンド入力作業を快適に](https://www.wakuwakubank.com/posts/862-mac-zsh-peco/)
[pecoを用いたコマンド履歴出す機能を作るときに調査したことまとめ](https://qiita.com/Teach/items/dab51ea56f04ee70dd7f)

事前にbrewで以下の3つをインストールしておきます。

```zsh
brew install zsh-autosuggestions
brew install zsh-syntax-highlighting
brew install peco
```

~/.zshrcファイルを適当なエディタで開いて以下を追記します。もしファイルがないなら作ります。

```zsh:~/.zshrc
# History設定
HISTFILE=~/.zsh_history
HISTSIZE=100000
SAVEHIST=100000
setopt share_history
setopt hist_ignore_dups
setopt hist_ignore_all_dups
setopt hist_ignore_space
setopt hist_reduce_blanks

setopt print_eight_bit
# -------------------------------------------------

# -------------------------------------------------
# プラグイン有効化
source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh
source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
# -------------------------------------------------

alias distinct='awk '\''!a[$0]++'\'

# -------------------------------------------------
# pecoの活用1
# ctrl + r で過去に実行したコマンドを選択できるようにする。
function peco-select-history() {
    BUFFER=$(\history -n -r 1 | distinct | peco --query "$LBUFFER")
    CURSOR=$#BUFFER
    zle reset-prompt
}
zle -N peco-select-history
bindkey '^r' peco-select-history

# cdr
if [[ -n $(echo ${^fpath}/chpwd_recent_dirs(N)) && -n $(echo ${^fpath}/cdr(N)) ]]; then
    autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
    add-zsh-hook chpwd chpwd_recent_dirs
    zstyle ':completion:*' recent-dirs-insert both
    zstyle ':chpwd:*' recent-dirs-default true
    zstyle ':chpwd:*' recent-dirs-max 1000
    zstyle ':chpwd:*' recent-dirs-file "$HOME/.cache/chpwd-recent-dirs"
fi

function peco-cdr () {
    local selected_dir="$(cdr -l | sed -E 's/^[0-9]+ *//' | peco --prompt="cdr >" --query "$LBUFFER")"
    if [ -n "$selected_dir" ]; then
        BUFFER="cd ${selected_dir}"
        zle accept-line
    fi
}
zle -N peco-cdr
bindkey '^E' peco-cdr
```

cdrですが、Macのsedが古いため-Eオプションが必要です。こちらの情報を参考にしました。
[Macのsedで使える正規表現はPOSIX BRE(Basic Regular Expressions)](https://www.wholenotism.com/blog/2020/05/sedonmacosx.html)

ついでに少しだけ正規表現を（自分にとって）わかりやすく修正しました。

最後に、必要はないと思いますが念の為。修正した.zshrcを起動中のターミナルに反映させるには次のコマンドです。
```zsh
source ~/.zshrc
```
フォームに入力しようとするとトップにスクロールしてしまう

JavaScript初心者です。
初歩的なことかもしれませんが、調べてもなかなか見つからず時間がかかったので書きます。

### 事象
フォームに入力しようとクリックすると、スクロールしてトップに移動してしまいました。
また、モーダルの閉じるボタンをクリックした際に、少し上に行って元の位置に戻るという変な動きをしていました。
SpringBootでもASP.NETでも同様のことが起きました。

### 検索ワード
以下のワードで調べていました。
（過去に検索してそのまま残っていたタブから引用したので順不動です）

ページトップ 無効
スクロール 無効
スクロールトップ 無効
スクロールさせない
入力するとき　画面　移動
入力　画面　位置　動く
form input 選択　移動
入力　フォーカス　位置
入力　位置 固定
入力　位置 ずれる
勝手にスクロールされる
スクロール 上に戻る
背景固定 スクロール

これらのワードにプラスしてjQuery、js、Bootstrap5、SpringBootを入れていました。
jQueryか、BootstrapのjQueryが悪さしているのかなと思っていました。

それで出てくるスクロール無効をやって、スクロールができなくなったり、
特に何も変わらなかったり、
scrollTop()で位置取得も違う、
座標なんか出てきてちんぷんかんぷん。。

何日も調べても分からなくて、諦めて放置していました。

ある日調べてみたら一発で解決しました。

### 解決方法
「event.preventDefault()」です。
イベントの発生元が持つデフォルトの動作を無効化するものだそうです。

最初はinput, select, textarea, buttonクリックで書いていたのですが、
背景をクリックしても動いてしまったのでdivクリックになりました。
ちなみにinputフォーカスではなくクリックでないとききませんでした。

```js
$(function () {
    $('div').on('click', function() {
        event.preventDefault();
    });
});
```
モーダルでもASP.NETでも「event.preventDefault()」で解決しました。

その時の検索ワード
「jquery 入力 scrolltop 無効」

あれ？たいして変わりがない。。
そう、今まで検索していた「スクロール　無効化」で答えは書かれていたのです。
なんか違うだろうってスルーしちゃってたんですね。

今も別件でJavaScript詰まり中なのですが、仕様上できないのか、答えをスルーしちゃっているのか。
たぶん後者だと思うのですが、早くJavaScriptと仲良くなりたいです。

### 本当の原因（2023/8/13更新）
アプリケーションが未完の状態だったので久しぶりに触ってみました。
できていたかと思いきやボタン押下での送信処理ができない状態でした。
ヘッダー以下に```cursor: pointer;```がついていることも気になり開発者ツールでいろいろ見た結果、
```<a href="#">```で囲われていることに気づきました。
どこに記載しているのかファイル検索して、
共通htmlヘッダーのログアウトアイコンに暫定でつけていたaタグが閉じられていませんでした（タグが間違っている）。
くだらないミスなのに、解決まですごく時間がかかってしまいました。
Eclipse上で黄色い線がついていたのに気づかなかったです…
```common.html
<header th:fragment="header">
    <div class="container-fluid">
        <div class="row d-flex align-items-center">
            <!-- 略 -->
            <div class="col-6 order-2 col-md-2 order-md-3 text-end">
                <!-- ここです -->
                <a href="#">
                    <i class="fa-solid fa-arrow-right-from-bracket"></i>
                </button>
            </div>
        </div>
    </div>
</header>
```
【備忘録】自然言語処理AI「GPT-3」アドオンの使用



# １．はじめに
Twitterや下記の記事から、自然言語処理AI「GPT-3」におけるGoogleのドキュメントとスプレッドシートのアドオンを知りましたので試してみました。

https://note.com/masaru21/n/nd07c5d50bfdb

アドオンは「GPT for Sheets™ and Docs™」です。

https://workspace.google.com/u/0/marketplace/app/gpt_for_sheets_and_docs/677318054654

# ２．準備
アドオンを使用するために必要な準備は、上記リンク先に記載があるため、そちらを参考にしました。以下簡単に記載します。
・OpenAIにログインしアカウント作成
・API Keysを作成
・アドオン「GPT for Sheets™ and Docs™」をインストール
・Googleのスプレッドシートを起動し、拡張機能→GPT for Sheets™ and Docs™→API Keyを設定
・拡張機能→GPT for Sheets™ and Docs™→Enable GPT functionsをクリック

# ３．アドオン使用
「GPT」と「GPT_LIST」という関数がありましたので、そちらを使用してみました。下記表は、AIに関する記事のアイディアとそのアイディアを元にした記事を書いてもらった例になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2940692/7873d41d-299b-5e63-47a8-eed0d3aa3109.png)


関数の使用方法については、下記チュートリアルに記載があります。

https://gptforwork.com/gpt-for-sheets/home

# ４．備考
注意点としては、今回アドオンで使用している自然言語処理AIはGPT-3(model:text-davinci-003)になります。
また、自然言語処理AIが生成する文章は、必ずしも正しい答えを生成するわけではないため、生成後の文章はチェックする必要があると考えます。

# ５．参考URL
https://gptforwork.com/gpt-for-sheets/home

https://note.com/masaru21/n/nd07c5d50bfdb

https://liquidjumper.com/google-sheets/googlespreadsheet_connect_to_gpt_3#headline12
optparseについて

 # 経緯
　Rubyでカレンダーアプリを作成する際に,引数に任意の数値を渡すことでmacの`cal`コマンドで表示されるようなカレンダーを表示したかったのでoptparseを使用しました。そこで私なりに`optparse`について調べてみました。
# 役割
- コマンドライン引数
　コマンドライン引数は、ターミナルから実行時に引数を渡して読み込める仕組みです。
- 引数は文字列として出力されます。
### OptionParser
以下
```ruby:sample.rb
require 'optparse'

opt = OptionParser.new
#aに渡ってきた引数をvに格納
opt.on('-a') {|v| p v }
# 真偽値を表示。
opt.parse!(ARGV)
p ARGV

$ruby sample.rb -a foo
# この場合aに引数が渡っていますのでtrueを表示。そしてfooを表示
=>true
["foo"]
```
引数が2つの場合
```ruby:sample.rb
require 'optparse'

opt = OptionParser.new
opt.on('-a') {|v| p v }
opt.on('-b') {|v| p v }
opt.parse!(ARGV)
p ARGV

$ruby sample.rb -a fooe  -b baz
=>true
true
["foo", "baz"]
```
　定義していないオプションを指定すると例外 OptionParser::InvalidOption が発生します。

```ruby:sample.rb
ruby sample.rb -c           
=>sample.rb:3:in `<main>': invalid option: -c (OptionParser::InvalidOption)
sample.rb:3:in `<main>': invalid option: c (OptionParser::InvalidOption)
```
　OptionParser 自体は、どのオプションが指定されたかを記憶しないため、後の処理の方で、オプションによる条件判断を加えるには、 他のコンテナに格納します。
```ruby:sample.rb
require 'optparse'
opt = OptionParser.new
# 引数を格納
OPTS = {}

opt.on('-a') {|v| OPTS[:a] = v }
opt.on('-b') {|v| OPTS[:b] = v }

opt.parse!(ARGV)
p ARGV
p OPTS

$ruby sample.rb -a foo bar -b baz
=>["foo", "bar", "baz"]
  {:a=>true, :b=>true}
```
### ARGV
```ruby:sample.rb
require 'optparse'

option1 = ARGV[0]
option2 = ARGV[1]

puts "Option 1: #{option1}"
puts "Option 2: #{option2}"

$ruby sample.rb foo bar
=>Option 1: foo
Option 2: bar


# またはARGV.getoptsを使う
require 'optparse'

# 引数にオプションa, オプションbを指定
params = ARGV.getopts("a:b:")
p params

$ruby sample.rb -a foo -b bar
=>{"a"=>foo, "b"=>"bar"}
```
　getoptsメソッド使うとワンラインでコードでオプションと引数を複数指定することができ、受け取ったものをHashとして( 例`[a:]`)受け取ることができます。引数が必要なオプションにはコロンをオプションの後ろにつけます。オプションや引数をシンプルに扱うだけであればARGV.getoptsを使うと記述量が少なくて済みます。


# 参考サイト
https://docs.ruby-lang.org/ja/latest/library/optparse.html 

https://docs.ruby-lang.org/ja/latest/class/OptionParser=3a=3aArguable.html
要求分析と要件定義の目的について個人的に納得した考え

# 概要
この記事では、私が要求分析や要件定義に関する本読み、自分なりに納得した要求分析と要件定義の考えた方についてまとめます。
読書感想文的なものです。

# なぜ要求分析と要件定義の本を読んだりしたのか
業務で上流工程のナレッジを共有する機会があり、せっかくなので上流工程を体系的に学習してみようと考えました。
上流工程の実務経験はありますが、自分の知識は企業文化に依存しており、正直、社内で共有するには心もとないと感じていました。
例：仕様書の名前が違う。作らない仕様書がある。スコープが違う。

同僚やCTOのおすすめから以下の本を読みました。
- [要件定義トラブルの予防と対策１３６: 要件定義フェーズでよくある問題の予防と事後対応策がわかる！](https://www.amazon.co.jp/%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%81%AE%E4%BA%88%E9%98%B2%E3%81%A8%E5%AF%BE%E7%AD%96%EF%BC%91%EF%BC%93%EF%BC%96-%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9%E3%83%95%E3%82%A7%E3%83%BC%E3%82%BA%E3%81%A7%E3%82%88%E3%81%8F%E3%81%82%E3%82%8B%E5%95%8F%E9%A1%8C%E3%81%AE%E4%BA%88%E9%98%B2%E3%81%A8%E4%BA%8B%E5%BE%8C%E5%AF%BE%E5%BF%9C%E7%AD%96%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B%EF%BC%81-%E6%9C%AC%E5%9C%92-%E6%98%8E%E5%8F%B2-ebook/dp/B07JFCMD1J/ref=sr_1_8?qid=1675002489&s=books&sr=1-8 "")
- [要件定義のヒアリングリスト４２７: 要件定義フェーズで、今、何を確認すべきかが、具体的にわかる！](https://www.amazon.co.jp/%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9%E3%81%AE%E3%83%92%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0%E3%83%AA%E3%82%B9%E3%83%88%EF%BC%94%EF%BC%92%EF%BC%97-%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9%E3%83%95%E3%82%A7%E3%83%BC%E3%82%BA%E3%81%A7%E3%80%81%E4%BB%8A%E3%80%81%E4%BD%95%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%81%B9%E3%81%8D%E3%81%8B%E3%81%8C%E3%80%81%E5%85%B7%E4%BD%93%E7%9A%84%E3%81%AB%E3%82%8F%E3%81%8B%E3%82%8B%EF%BC%81-%E6%9C%AC%E5%9C%92-%E6%98%8E%E5%8F%B2-ebook/dp/B07JDDP9J3/ref=sr_1_3?qid=1675002489&s=books&sr=1-3 "")
- [図解入門 よくわかる 最新 要求定義の基本と実践](https://www.amazon.co.jp/%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-%E8%A6%81%E6%B1%82%E5%AE%9A%E7%BE%A9%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E5%AE%9F%E8%B7%B5-How-nual-visual-guide/dp/4798068314 "")

※本記事では「要求分析」と「要件定義」は同一のものとして記載します。

# 気づき/得た考え
学習によって得た気づきには以下のものがあります。
なお、本の内容については本を読んだほうが速くてわかりやすいので記載しません。
- 開発可否判断ってやってる？
- 要件定義の目的を勘違いしてたかも
- 資料を作ることを目的にしてない？


## 開発可否判断ってやってる？
今まで色々なプロジェクトに参加してきましたが、
仕事の流れとしては「仕事を受ける」→「要件定義」→「設計」のように仕事を受けた後に要求分析を行っており、
よく「実現無理では…」「スケジュールきつくね?」といった問題が発生していました。

そもそも「システムの要件」が決まっていない状態で開発を開始するべきではありません。
要件があるから見積もりができて、スケジュールを引けるのです。
**見通しの立たない開発は炎上や低品質なシステムにつながります。**

また、システムの品質は要件とシステムの動作がどれだけ一致するかで決まります。
**極端な話「要件」がなければ明らかな異常動作でも低品質とは言えないのです。**

理想は「要件定義の仕事を受ける」→「要件定義」→「開発可否判断」→「開発の仕事を受ける」となるべきです。
「開発可否判断」を行わないプロジェクトに参加した場合はぜひ「開発可否判断をやろう！」と行動してみてください。


##  要件定義の目的を勘違いしてたかも
元々は「システム開発」を行うため次の工程である「基本設計」を行うための基礎となる情報だから、漏れなくやる必要があると考えていました。
しかし「要件定義」の問題を整理すると実はちょっと目的が違ったのではないかと感じ、
今は「開発可否判断」を行うことが目的だと考えています。
- 要件は漏れやすい
- 要件は変わる
- 要件は隠される

顧客は「自分の欲しいシステム」がわかっていないことが多いのです。
ざっくりとしたイメージで話していることが多く、実際にシステムにしてからイメージと違うと問題になることも多々あります。

上記問題を解決するために「要件定義」にて、
顧客が欲しいシステムの要件を明らかにして、
わかりやすい資料に落とし込み、
顧客と認識のすり合わせや考えを共有し、
「このシステム要件が欲しいシステムである。これを開発してほしい」と開発可否判断をさせる/するべきだと思います。

## 資料を作ることを目的にしてない？
「要件定義の目的」は顧客に「開発可否判断」をしてもらうことだとこれまで記載してきました。
そのために資料を作成します。決して「納品のため」ではないのです。

よく「納品さえすればいい」「うちでは作らない」といったお話を聞きますが、
「開発可否判断」ができるのであれば私はどちらでもよいと思います。
ただ、やっていないと言いながらもやっていないのはきっちりとした「要件定義仕様書」の作成であり、それに類する資料や行動をしていることが多いです。

システムにする業務の流れを共有するために業務フローを作成したり、
外部システムとの連携やインプットを明らかにするためにシステム構成図を作成し、
要件に漏れや勘違いがないか。
また、このシステムが実現できるのか開発側での判断を行います。



# 今後
これまで記載した内容を社内で共有したり、開発側と顧客側で「開発可否判断」による合意を意識していきたいと思います。
【備忘】 GA版とRC版それぞれどういう意味なのか調べてみた！

MySQLの環境構築を行なっていて、バージョンに関する知識が必要になった。
バージョンについて、以下サイトを参考に勉強してたところ、GAとRCというワードが出てきて
サイトを読んでけば理解できるかと思ってたが、自分にはイマイチ理解しきれなかったので
それぞれの単語の意味を調べて深掘りしてみた結果を記録として残しておく。

https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0008

この記事は、自分向けのメモに近いのでざっくりとした説明しか書きませんのでご了承ください。
簡単な記事でも誰かのお役に立てれれば幸いです。

## GA(General Availability)版
製品として、完成しているものであり
本番環境で使用することが推奨されているもの。


## RC(Release Candidate)版
プレビュー版的な感じで公開しているもののことを指す。
開発途中の機能なども含まれていたりするので、本番環境での使用しないように制約があったりする。

## 参考
https://e-words.jp/w/GA%E7%89%88.html

https://e-words.jp/w/RC%E7%89%88.html

https://qiita.com/jhonyspicy/items/af4bda78ddb566a2fa30
FluentdでログをGrafana Cloudに転送する

## Fluentdのログを蓄積したい
複数サーバからFluentdでログを収集して分析する場合、ログの投入先としてはelasticsearchが鉄板だった。Fluentdでログを収集してelasticsearchに投入、Kibanaで可視化するEFKスタック。

これに対して最近では[Grafana Loki](https://github.com/grafana/loki)という選択肢がある。Grafana Lokiはログの全文をインデキシングしないので、より低リソースで簡単に運用できるというメリットがある。とはいえ、ログの分析基盤を運用しようと思ったらそれなりに面倒だと考えていたら、Grafana Lokiのマネージドサービスである[Grafana Cloud](https://grafana.com/products/cloud/)があることを知った。Grafana Cloudはフリーアカウントもあり、毎月 10k metrics + 50GB logs + 50GB tracesまで無料で利用できる。個人利用であれば十分なリソースが使える。

このため、ログの収集分析の導入としてGrafana Cloudを利用する。


## ログ転送にFluentdを選択する
Grafana LokiやGrafana Cloudにログ送信する場合、そのログ転送エージェントとして[Promtail](https://grafana.com/docs/loki/latest/clients/promtail/)が推奨されている。PromtailはGrafana LokiまたはGrafana Cloudにログ転送するためのエージェント。このため、Grafana LokiやGrafana Cloudを利用する場合は基本的にPromtailを選択すればよい。

一方で、PromtailはあくまでGrafana Lokiなどを想定しているため、それ以外のログ転送には利用できない。複数サーバから転送することなどを考えるとプラグインが豊富で自由なログ設定が可能なFluentdを選択したくなる。実際のところ、Grafana Lokiは[Fluentd用のOutput Plugin](https://grafana.com/docs/loki/latest/clients/fluentd/)が提供されているだけでなく、[Fluent Bit](https://grafana.com/docs/loki/latest/clients/fluentbit/)や[Logstash](https://grafana.com/docs/loki/latest/clients/logstash/)もサポートされている。このため、まったくログ転送を行ったことがなければPromtailを選択すればよいが、過去の資産を流用したければそれらを継続することができる。

今回は既にFluentdを利用中なため、FluentdからGrafana Cloudにログ転送することを考える。

## Fluentdのログ送信設定
Fluentdの設定は基本的に[Grafana Lokiのドキュメント](https://grafana.com/docs/loki/latest/clients/fluentd/#usage)に従えばよい。ユーザごとに異なる設定としては、url、username、passwordがあり、ここを適切に設定する必要がある。

例えば、urlはGrafana Cloudのアカウントセットアップ時にどこのリージョンに環境構築したかによって変化する。また、Grafana Loki自体には[ユーザ認証の機能はなく](https://grafana.com/docs/loki/latest/operations/authentication/)、nginx等でBasic認証の仕組みを構築する必要がある。Grafana CloudではBasic認証の仕組みを提供してくれており、Fluentdの設定としてusernameおよびpasswordを指定する場合はBasic認証を指定する。

urlやBasic認証情報は[Grafana Cloud Portal](https://grafana.com/docs/grafana-cloud/account-management/cloud-portal/)から確認する。Lokiの詳細を確認するとurlやBasic認証が有効になっているかどうか、usernameやpasswordが確認できる。passwordはAPI keyを利用する仕組みになっており、この画面からでもAPI Keysの管理画面からでも新しく生成できる。権限としてはMetricsPublisher roleを指定すればよい。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14181/6cf23b5d-6de5-53f5-8bff-0c44ecc7cc89.png)
(図はGrafana Cloudドキュメントより引用)

ただし、ここでいうAPI keyとは[GrafanaのAPI key](https://grafana.com/docs/grafana/latest/administration/api-keys/)とは異なり、Grafana Stackで管理するAPI keyを指す。上記ドキュメントなどではGrafanaのダッシュボード上の操作を示しており、そちらでAPI keyを発行しても利用できないし、Grafana Cloud Portalで発行したAPI keyも確認できない。

これらを踏まえて、以下のような設定を行うことでGrafana Cloud上にログ転送できるようになる。

```
<match **>
  @type loki

  # シンガポールリージョンを選択したら以下のURLになった
  url "https://logs-prod-011.grafana.net"
  username "#{ENV['LOKI_USERNAME']}"
  password "#{ENV['LOKI_PASSWORD']}"

  flush_interval 10s
  flush_at_shutdown true
  buffer_chunk_limit 1m

  extra_labels {"env":"dev"}
</match>
```
dbtチュートリアルメモ

# はじめに
dbt下記のチュートリアルをやってみた際のメモ(Chapter 05まで)
非常にわかりやすく、どういった機能があるのかを知ることができるのでおすすめです。

https://zenn.dev/dbt_tokyo/books/537de43829f3a0

# dbt Cloudのセットアップ
- Bigqueryの管理者アカウントのJSON形式の鍵をアップロードすることで簡単に連携できる。
- Githubと連携することで後に実装するモデル開発ファイルやテストファイルを管理しやすくなる
    - 特にdbt cloud上からブランチ作成やpush可能なのが便利

# チュートリアル：モデル開発の基本
- dbtでは、SQLで書かれたデータの抽出を行いテーブルのデータになる処理のまとまりを「モデル」と呼ぶ。
- 左サイドメニューの「initialize your project」を押すことで必要なフォルダ・ファイルが作成される。
    - 2023/01/29時点ではデフォルトでdataフォルダがなく、seedsフォルダがある。
    - models配下にexampleのフォルダがありサンプルが既に存在している。```dbt run```を行うとこのexample配下も実行されてしまうので注意。
- seedsフォルダ配下にcsvファイルを格納して```dbt seed```を実行することでBigQueryにcsvデータが格納されたテーブルが作成される。1つのcsvファイルにつき1テーブル。
- モデルをデプロイするときは```dbt run```。実行するとBigQuery上に作成したモデル(sql)が反映される。
- ```{{ ref(モデル名) }}```とすることで別モデルの結果を参照できる。
- Lineageタブでデータリネージ(モデル間の構造)が確認可能。

# チュートリアル：テストとドキュメント
- ```models/schama.yml```を作成して、内部にテストケースを記載することでスキーマテストできる。
- テスト例としては、対象カラムがuniqueかnot_nullか等を確認できる。また、対象カラムが許容している値かどうかや指定したカラムと結合しているかどうかのテストができる。
- テストは拡張することも可能。[dbt-utils package](https://github.com/dbt-labs/dbt-utils/tree/0.2.4/#schema-tests)のような外部のパッケージされているものも使用可能。
- ```models/schama.yml```に```description```要素を書き足すことでドキュメント化可能。```dbt docs generate```で生成して左サイドメニューの本マーク(view docs)で確認できる。

# チュートリアル：デプロイの設定
- Enviromentを作成して、そのEnviromentに対してジョブが設定できる。
- ジョブは```dbt test```や```dbt run```などdbtコマンドが指定できる。
- スケジュールの設定も可能。
【合格体験記】Pythonエンジニア認定試験（実践）

# はじめに

[過去の投稿](https://qiita.com/Blaster36/items/bad8650d4dce79297289)ではPythonエンジニア認定試験の合格体験を綴りました。
本稿は、その続報です。

https://qiita.com/Blaster36/items/bad8650d4dce79297289

結論から言うと、「**Python3エンジニア認定実践試験**」に無事合格しました。
以下の記事が出回ってから、ずっと受験を狙っていました。

https://www.pythonic-exam.com/archives/news/jissen

Python好きな方、Python関連で資格取得を考えている方、仕事でPython知識が必要な方、、、の少しでもご参考になればと。

# 受験結果

- Python3エンジニア認定実践試験

:::note info
合格評価得点：700／筆者の評価得点：800／結果：合格
:::

![python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685193/966903ae-cf50-619c-df2d-f7eb5ca56b78.png)

日曜プログラマーではあまり触れない分野、「**テストおよびデバッグ**」の正答率が低いですねｗ

# 試験概要

以下の記事が出回った頃からチェックしていました。

https://www.pythonic-exam.com/archives/news/python_jissen

https://www.pythonic-exam.com/archives/news/python-jissen-bata

:::note info
基礎試験およびデータ分析試験と合格ラインは同じですが、受験料金は2千円高いです。（本稿執筆、2023/02/18時点）
:::

- 試験名称：Python 3 エンジニア認定実践試験
- 概要： Pythonを実践的に使っていく上で重要な仕様やライブラリの使い方を問う試験
- 受験料金：1万2千円（外税）　学割6千円（税別）
- 問題数：40問（すべて選択問題）
- 合格ライン：正答率70％（700点）
- 試験時間：75分
- 試験センター：全国のオデッセイコミュニケーションズCBTテストセンター

https://www.pythonic-exam.com/exam/jissen

# 勉強方法

以下、勉強方法です。2つの学習方法を行き来していました。（と言っても、限りなく一夜漬け）

1. Webサイトで学習
2. 書籍サンプルCodeで学習

## 1. Webサイトで学習

メニューは３つ、初級／中級／上級の模擬試験が提供されています。
試験を週末に控えた平日からWebブラウザで初級編からTry、正答率が８０％を超えたら次の段階へ進む、といった流れです。

:::note info
こちらのWebサイトが非常に親切で、学習履歴／正誤表／分野別正答率をチェックできます。
特に、分野別正答率で正答率の低い分野を把握・分析できるのが助かりました。
:::

https://python-basic.com/

## 2. 書籍サンプルCodeで学習

Webサイトでの模擬試験、分野別正答率で正答率の低い分野を重点フォローしました。
ありがたいことに書籍「Pythonエンジニア育成推進協会監修 Python実践レシピ」ではサンプルCodeが公開されており、そちらをDownloadしてサンプルCodeをひたすら眺めました。

:::note info
試験自体はざっくり言うと、Codeから実行結果を推察するもの、実行結果になるCodeの穴埋めするもの、が多いです。
そのため、サンプルCodeおよび実行結果をざっと目にするだけで十二分な知識（≒対策）となります。
:::

https://gihyo.jp/book/2022/978-4-297-12576-9

# おわりに
タイトルこそ合格体験記だが、、、少しでもPython普及のきっかけなることを祈って。。。
最後までご覧いただいた方、ありがとうございます。
【Docker】コンテナからホストにアクセスする方法

## コンテナからホストにアクセスする方法

`host.docker.internal`を使用することでコンテナ内からホストマシンにアクセスできます。

`host.docker.internal`を使用するとホストマシンのIPアドレスを指定する必要がなくホストマシンのIPアドレスを自動的に解決することができます。

ただし`host.docker.internal`はDocker Desktopの開発環境でのみ対応しています。



https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host
二重ハッシュの出力

今日も復習でアウトプットします！


問題.
配列の内部に、複数のユーザーの情報をハッシュとして持つ変数のname値を出力せよ。出力結果は次のようになるものとする。

```ruby:
book_data = [
 {book: {item: {name: 'ten'}}},
 {book: {item: {name: 'chi'}}},
 {book: {item: {name: 'nodo'}}},
]
```

```ruby:出力結果
ten
chi
nodo
```

```ruby:解答
book_date.each do |n|
puts n[:book][:item][:name]
end
```

# 解説
ハッシュから特定の値を取得する場合は、その値に対応するキーを指定。
二重ハッシュから特定の値を取得する場合は、取得したい値のキーまで連続して指定すると取得可能。
```ruby:取得方法
ハッシュ[取得したい値のキー]

#二重ハッシュ
ハッシュ[取得したい値のキー][取得したい値のキー]

#今回はname値取得のため下記となる
ハッシュ[:book][:item][:name]
```



応用で、digメソッドを用いても取得できる。
「digメソッドとは？』
Rubyに標準で組み込まれているメソッドで、多重階層にあるハッシュの値をまとめて取得できる。
```ruby:解答
user_data.each{ |n| puts u.dig(:book, :item, :name) }
```


綺麗なのはdigなのかな。
javaScript async test

自分用の備忘録

```js
async function asyncTest(num) {
    console.log("asyncTestメソッド開始");
    if ( num === 1 ) {
        console.log("渡された引数は 1 だったぜ");
        return "1";
    } else {
        console.log("渡された引数は 1 じゃなかったぜ");
        throw new Error('エラーを返すぜ');
    }
}

asyncTest("s")
    .then( val => {
        console.log("メソッド成功したぜ")
        console.log(val);
    } )
    .catch( err => {
        console.log("メソッド失敗したぜ（エラーを受け取ったぜ）")
        console.log(err);
    });
```
TypeScriptのJSDocからMarkdownでドキュメントを自動生成

## はじめに

この記事では、TypeScriptの[JSDoc](https://jsdoc.app/)（[TSDoc](https://tsdoc.org/)）から、[TypeDoc](https://typedoc.org/)と[typedoc-plugin-markdown](https://github.com/tgreyuk/typedoc-plugin-markdown/tree/master/packages/typedoc-plugin-markdown)を使ってMarkdown形式でドキュメントを自動的に生成する方法を解説します。

この記事の方法を使うと、ソースコードのJSDocから画像のようなドキュメントをMarkdown形式で自動生成できます。
実際に私が自動生成したドキュメントは[ここ](https://github.com/Robot-Inventor/modern-context.js/tree/e70b8624146cca4be6036368981f35a3c8a79cca/docs)から閲覧できます。

なお、ドキュメントを1つのファイルにまとめるオプションは用意されていないようです。

![自動生成されたドキュメントのスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420120/486fce63-b408-db1d-cd46-39d85d5a4555.png)
![自動生成されたドキュメントのスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420120/0dad8928-1cb7-3cc4-d833-f8a4408f3fbd.png)

## この記事で解説しないこと

次の内容については、この記事で扱いません。

- npmやTypeScriptの環境の構築方法
- TypeScriptの書き方
- JSDoc（TSDoc）の書き方

## 始める前に

始める前にまず、TypeScriptの環境を構築しておいてください。また、TypeScriptのソースコードに書かれているJSDocと型情報からドキュメントを生成するため、事前にそれらが整備されている必要があります。

## 依存関係のインストール

依存関係として[typedoc](https://typedoc.org/)と[typedoc-plugin-markdown](https://github.com/tgreyuk/typedoc-plugin-markdown/tree/master/packages/typedoc-plugin-markdown)をインストールします。

```console
npm install --save-dev typedoc typedoc-plugin-markdown
```

## 実行

ここまで来れば、ほぼ完成です。あとはコマンドを実行するだけで``docs``ディレクトリーにドキュメントが自動で生成されます。

エントリーポイントのTypeScriptファイルのパスは、プロジェクトに合わせて読み替えてください。

```console
npx typedoc --plugin typedoc-plugin-markdown "src/index.ts"
```

### オプション

よく使いそうなオプションを簡単に解説します。すべてのオプションとその説明は、``npx typedoc --help``を実行するか、[公式サイト](https://typedoc.org/guides/options/)から閲覧できます。

#### ``--out``

ドキュメントを出力するディレクトリーを指定します。デフォルトは``docs``です。

#### ``--cleanOutputDir``

このオプションを指定すると、出力先のディレクトリーを一度空にしてからドキュメントを生成します。

#### ``--excludePrivate``

このオプションを**指定すると**、privateな変数やメソッドをドキュメントに**載せない**ようにします。このオプションを**指定しなかった**場合は、privateな変数やメソッドも**掲載されます**。

内部向けのドキュメントでは指定せず、ライブラリーなどの利用者向けのドキュメントでは指定するといった使い分けになりそうです。

#### ``--includeVersion``

このオプションを指定すると、ドキュメントにバージョンを記載します。バージョンは``package.json``の``version``の値が使われます。

#### ``--readme``

このオプションを**指定しなかった場合**、プロジェクトのルートのREADME.mdがドキュメントのディレクトリーにそのままコピーされたうえで、目次ページを含むほかのページが自動生成されます。

README.mdの代わりに別のファイルをコピーしたい場合は、そのファイルへのパスを指定します。パスの代わりに``none``を指定した場合は、目次ページが``[ドキュメントのディレクトリー]/README.md``として生成されます。

#### ``--name``

ドキュメントに記載するプロジェクトの名前を指定します。デフォルトでは``package.json``の``name``の値が使用されます。``package.json``の``name``とプロジェクトの正式名称が異なる場合に便利です。

## まとめ

この記事では、TypeScriptのJSDocからMarkdown形式でドキュメントを自動生成する方法を解説しました。この方法は、ソースコードにJSDocコメントを記述するだけで、見やすく整理されたドキュメントを作成できるというメリットがあります。

一方で、ドキュメントにサンプルコードを載せたい場合はJSDocの``@example``を使ってソースコード内に記述する必要があり、コメントが冗長になります。

これらの点を踏まえたうえで、ぜひTypeScriptプロジェクトへの導入を検討してみてください。
unity JSONでデータ保存 備忘録

## セーブとロード機能を実装したクラス
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.UI;

public class SaveManager : MonoBehaviour
{
    string filePath;
    SaveData save;

    void Awake(){
        filePath = GetSecureDataPath();
        save = new SaveData();
        Debug.Log("filePath:"+filePath);
    }

    public void Save(){
        string json = JsonUtility.ToJson(save);
        StreamWriter streamWriter = new StreamWriter(filePath);
        streamWriter.Write(json); streamWriter.Flush();
        streamWriter.Close();
    }
    
    public SaveData Load(){ 
        if (File.Exists(filePath)){
            StreamReader streamReader;
            streamReader = new StreamReader(filePath);
            string data = streamReader.ReadToEnd();
            streamReader.Close();
            Debug.Log("data:"+data);
            save = JsonUtility.FromJson<SaveData>(data);
        }
        return save;        
    }

    private string GetSecureDataPath(){
#if !UNITY_EDITOR && UNITY_ANDROID
        using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (var currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
        using (var getFilesDir = currentActivity.Call<AndroidJavaObject>("getFilesDir"))
        {
            string secureDataPathForAndroid = getFilesDir.Call<string>("getCanonicalPath");
            return secureDataPathForAndroid + "/savedata.json";
        }
#else
        return Application.streamingAssetsPath + "/savedata.json";
#endif
    }
}
```
## 保存するデータを格納するクラス
```cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SaveData{
    public string sample1;
    public int sample1;
}
```
GitHub ActionsでNode 12が非推奨となったのでアップデート

# 事象
GitHub Actionsの実行結果を見ていると以下画像のようなワーニングの注釈が出ていた。

![GitHubActions4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793264/f220ef73-c15d-209f-aa2c-60277db92a52.jpeg)
翻訳するとこんな感じ
***Node.js 12 Actionsは非推奨です。Node.js 16を使用した後継のActionsを使用するために「actions/check@v2」をアップデートしてください。追加情報は、[こちら：https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/](https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/)。***

メールやGitHubのダッシュボード等でお知らせしてもらえれば気づけるけど、サラッとワーニングが出ていているだけじゃ気づかないよ・・・。
完全に使えなくなる前に気づけて良かった！

# アップデート方法
追加情報のサイトにアクセスすると、どのようにアップデートすべきか書いてある[サイト](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-versioned-actions)へのリンクがあるので、その通りに変えるだけ。
結論から言うと`actions/checkout@v2`を`actions/checkout@v3`にするだけよ:grin::bangbang:

```yaml:変更前
- uses: actions/checkout@v2
```

```yaml:変更後
- uses: actions/checkout@v3
```

# 参考サイト
[Marketplace Actions Checkout](https://github.com/marketplace/actions/checkout)
@masato_makino さん著　[GitHub ActionsでNode.js 12のサポートが終了します](https://qiita.com/masato_makino/items/3edde8e5f1a782a5c7ea)
@n0bisuke さん著　[GitHub ActionsでのNode.js利用のアップデートメモ](https://qiita.com/n0bisuke/items/e49b1ab4f54225271d85)
yolov4からYoloxへの移行のための比較

これは、自分用の作ったメモです。

間違った記述がありましたら、ご指摘いただければ修正します。


|項目 | yolov4 | yolox|
|-----|---------|--------|
| 参照したgithub| https://github.com/AlexeyAB/darknet | [yolox](https://github.com/Megvii-BaseDetection/YOLOX)  |
|学習データの形式| yolo形式 | COCO形式|
|上記のフォーマットの解説記事 | [解説記事](https://kagglenote.com/ml-tips/yolov4-training/) | [解説記事](https://qiita.com/harmegiddo/items/da131ae5bcddbbbde41f)|
|アノテーションファイルの流儀 | 1画像1ファイル | traiｎ分で１つのjsonファイル|
|bboxの記述| 中心のx, 中心のy, w, h | 左上のｘ，左上のｙ，ｗ，ｈ|
|bboxの記述| 画像サイズで規格化した座標 | pixel 単位の座標　|
|アノテーションツールの例 | [labelMe](https://github.com/heartexlabs/labelImg) | [CVAT](https://github.com/opencv/cvat) |
|軽量なモデル | yolo-tiny | yolox-tiny|
|設定ファイル(入力サイズなど)| [yolov4-tiny.cfg](https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4-tiny.cfg) | [exps/default/yolox_tiny.py](https://github.com/Megvii-BaseDetection/YOLOX/blob/main/exps/default/yolox_tiny.py) | 
| 設定ファイル(学習用のデータの記載)　|	---| exps/custom/yolox_tiny.py |
| 学習済みの重みファイル |[yolov4-tiny.weights](https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.weights) | [yolox_tiny.pth](https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_tiny.pth)|
|重みファイルの形式 | 独自形式 | pytorch|
|クラスの名称 | obj.names | jsonファイルの"categories"に記載|
|学習開始時に指定する初期値の重みファイル | yolov4 | yolox|
|学習時の画像リスト |train.txtに相対パスで記載 | train用のjsonファイルの"images"に記載（ファイル名だけ）|
|学習中の途中の重みファイル | 未記入 | 例 YOLOX_oupputs/yolox_tinye/epoch_100_ckpt.pth|
|pypi | [tensorflow-yolov4](https://pypi.org/project/yolov4/) | yolox|


付記：
YOLOXではCOCO形式をデータを管理している。データ形式が標準化されているので、検出結果の評価ツールも表示で提供されている。
【Nuxt】script(tsx)のみでlayoutコンポーネント的なものを作る

こんにちは。
今回は備忘録的にNuxtで`<template>`を使用せずに`<script lang="tsx">`のみで開発をしている際に、Reactのlayoutコンポーネント的なものを作る方法を綴ります。

:::note warn
Vueは本来、`layouts/default.vue`を書くことで共通レイアウトを作ってくれるという機能がありますので、通常はそれを使用する方が良いかもしれません。
:::

# 通常の場合
通常の場合、`.vue`は`<script>`・`<template>`・`<style>`の構成で記述されるため、親コンポーネントから子コンポーネントに差し込みを行う`slot`が使用できるので以下のようなシンプルなコードになります。

```vue:子コンポーネント(Layout.vue)
<template>
    <main>
        <slot></slot>
    </main>
</template>
```

```vue:親コンポーネント
<template>
    <Layout>
        <!-- ここに要素が挿入できる -->
    </Layout>
</template>
```

# `<script lang="tsx">`のみの場合
`<script lang="tsx">`のみの場合、すなわち`.vue`を`<script>`のみで構成したいときは、`<slot></slot>`というシンプルな記述を使うことができません。しかし、少し形を変えることだけで同様のことを実現できるようです。

```vue:子コンポーネント
<script lang="tsx">
    export default defineComponent({
        setup(_, { slots }){
            return () => (
                <main>
                    {slots.default && slots.default()}
                </main>
            )
        }
    })
</script>
```

```vue:親コンポーネント
<script lang="tsx">
    import LayoutVue from '~/components/templates/Layout.vue';
    
    export default defineComponent({
        render(){
            return(
                <LayoutVue>
                    // ここに要素が挿入できる
                </LayoutVue>
            )
        }
    })    
</script>
```

# さいごに
以上が`<script lang="tsx">`のみでlayoutコンポーネント的なものを作る方法でした。
Nuxt、Vue共に超初心者ですので、間違っていたらご指摘頂けると幸いです。
Dockerインストール

<a href="#目的">目的</a>
<a href="#環境">環境</a>
<a href="#手順">手順</a>
<a href="#エラー処置">エラー処置</a>

目的
-
UbuntuPCにDocker環境を構築するため、手順を作成しました。

環境
-
Ubuntu 18.04

# 手順
#### Dockerのリポジトリの設定
1.aptパッケージを更新します
```
sudo apt update
```
2.必要なパッケージをインストールします
```
sudo apt install \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg-agent \
     software-properties-common
```
3.Docker公式のGPG公開鍵をインストールします
```
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```
4.ingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88であることを確認します
```
sudo apt-key fingerprint 0EBFCD88
```
5.repository (stable) を追加します
```
sudo add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) \
    stable"
```
#### Dockerインストール
1.aptパッケージを更新します 
```
sudo apt update
```
2.最新版をインストールします
```
sudo apt-get install docker-ce docker-ce-cli containerd.io
```


#### Dockerの動作確認
Dockerが正常に動作しているかを確認します
```
docker info
docker images
```
dockerイメージ取得して実行
```
sudo docker run --rm hello-world
```
dockerイメージ削除
```
sudo docker rmi hello-world
```

#### エラー処理
もし以下のエラーが出る場合、パーミッションを与えることです。
```
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied
```
以下のコマンドを実行します。
```
sudo chmod 666 /var/run/docker.sock
```
以上、Dockerの環境構築の完成です。
Docker：Docker Hubへ自身のイメージを追加する作業

# ローカルのDockerイメージ一覧をチェックする

```warp
docker images
```


# Docker Hubに向けたタグ付け

```warp
docker tag <(あればローカルのディレクトリ名)イメージ名> <Docker ID>/<イメージ名>:<タグ名>
```
左側にローカルのイメージ名、右側にDocker Hubへアップ予定のイメージ名 + タグ名を指定する。
これによってローカルでタグ付きのイメージ情報が出来上がる。
※タグ名は省略可能だそうだが、省略すると自動的にlatestが選択されるらしい。当然だろう。


# Docker Hubに追加（Push）する

```warp
docker push <Docker ID>/<(ディレクトリ名)イメージ名>:<タグ名>
```


# ローカルのDockerイメージを削除（リムーブ）する

```warp
docker image rmi -f <IMAGE ID>
```


# Docker Hubからイメージを取得（Pull）する

```warp
docker pull <Docker ID>/<(ディレクトリ名)イメージ名>:<タグ名>
```
開成中学校の算数の入試問題を力技で解いてみた

# 前置き

一部の雑誌記事（下記）で開成中学校の算数の問題が話題になっています。
こういった話題を見ると力技で全数アタックしてみたくなりますよね？ならないですか。そうですか。
[PRESIDENT Online](https://president.jp/articles/-/66624)

# やってみた

ソースコードは下記に置きました。Pythonを使って解きました。
[kaisei_2023_math_5](https://github.com/kenbunji/kaisei_2023_math_5)

#### 問題

__開成中学校2023年入試問題、算数、大問5 (4)__
1,2,3,4,5,6,7の7種類の数字のみを用いてつくられた整数A,Bについて
A+B=9723になるA,Bの組は何通りか。

#### 解き方

整数Aを0から9723まで愚直に一つずつ確認します。
関数meet_cond()で整数AもしくはBが条件を満たすか検査します。
```Python
cnt = 0
print('#', 'a', 'b')
for a in range(0, 9724):  # aは9723以下
    b = 9723 - a
    if meet_cond(a) is False:
        continue
    if meet_cond(b) is False:
        continue
    cnt += 1
    print(cnt, a, b)
print('条件を満たすa,bの組が' + str(cnt) + '個見つかりました')
```
検査方法です。0,8,9を含むか確認しています。
```Python
def meet_cond(num: int) -> bool:
    """条件に当てはまる数かを検査する（0,8,9を含まない）
    Args:
        num (int): 検査する整数
    Returns:
        bool: Trueなら条件に当てはまる。Falseなら条件に当てはまらない
    """
    for char in str(num):
        if char in '089':
            return False  # 禁止された数(0,8,9)を含む
    return True  # 条件に当てはまる
```

# 結論

やったね。これであなたも4月から開成中学生です。試験会場でPythonが使えればね！
httpd.confの外部設定ファイルに関するディレクティブ

●外部設定ファイルを使用するには

・AccessFileNameディレクティブで外部設定ファイルを指定
デフォルトの外部設定ファイル名は「.htaccess」。

・AllowOverrideディレクティブで外部設定ファイルの利用を許可（または禁止）
AllowOverrideディレクティブで指定するパラメータによって、外部設定ファイルで使用できるディレクティブを制限することが出来ます。なお、AllowOverrideディレクティブは、外部設定ファイルを許可するディレクトリの設定を行う<Directory>セクション内に記述する必要があります。

・外部設定ファイルを許可したディレクトリに外部設定ファイルを配置する
外部設定ファイルの書式はhttpd.confと同じです。使用できるディレクティブが制限されている場合を除き、<Directory>セクションで記述が可能な設定を外部設定ファイルでも設定することが出来ます。

●httpd.confの外部設定ファイルに関するディレクティブ
・AccessFileName　ファイル名　外部設定ファイル名を指定(デフォルトは「.htaccess」」)
・AllowOverride　ぱらめーた　外部設定ファイルによるhttpd.confの上書を許可。
指定できる主なパラメータ
■AuthConfig　認証関係の設定を許可
■Limit　Order、Allow、Denyディレクティブの設定を許可
■All　すべての設定の変更を許可
■None　すべての設定の変更を禁止
【SvelteKit】クライアントサイドとサーバーサイドでのリダイレクトのさせ方の違いについて

# はじめに

### 前提

**SvelteKit**では、
**+page.svelte**や、 **+page.ts**に書くことで<font color="green">クライアントサイド</font>でjsを動かすことができ、
***.server.ts**に書くことで<font color="blue">サーバーサイド</font>でjsを動かすことができます。

**今回やりたかったこと**

* ログインしていればそのまま表示、
* ログインしていないときは任意のパスへとリダイレクトさせる

いつもは<font color="green">クライアントサイド</font>のjsに処理を書いているが、
それだとログインしていなくても一瞬ログイン後の画面が出てしまっていた。
(画面表示後にリダイレクト処理が動くため)

画面表示前に動く<font color="blue">サーバーサイド</font>でリダイレクトさせることでその事象を抑えたかったが、
普段<font color="green">クライアントサイド</font>で書いているやり方ではリダイレクトさせることができなかったのでそのときのメモ。


# <font color="green">クライアントサイド</font>でリダイレクトさせる場合

```vue:+layout.svelte
<script lang="ts">
  import { goto } from "$app/navigation";
  import { onMount } from "svelte";
  import { page } from "$app/store";

  onMount(() => {
    const session = getSession()
	if(!session && $page.url.pathname !== '/auth') {
      goto('/auth')
	}
  })
</script>
```

`app`モジュールの`goto`を使うことでリダイレクトさせることができます。
(当然window.location.href = ""でもリダイレクトできます。)

※ `goto`はonMount内でのみ使用できます。

<font color="red">この場合一瞬ですが、ログイン後の画面が表示されてしまいます。</font>

## `goto`使い方

### 型

```typescript
goto(url: string | URL, opts?: {
    replaceState?: boolean | undefined;
    noScroll?: boolean | undefined;
    keepFocus?: boolean | undefined;
    state?: any;
    invalidateAll?: boolean | undefined;
} | undefined)
```

### 例

```typescript
// example 1
goto('/auth')

// example 2
const base = 'https://hogehoge.com'
const url = new URL('/auth', base)
goto(url)

// example 3
const opt = {
  replaceState: true
}
goto('/auth', opt)
```

こんな感じのようです

# <font color="blue">サーバーサイド</font>でリダイレクトさせる場合

```typescript:+layout.server.ts
import { redirect } from "@sveltejs/kit";
import supabase from "../supabase";

/** @type {import('./$types').PageServerLoad} */
export async function load({ url }) {
  const session = await supabase.auth.getSession()

  if (session.data.session) {
    return session;
  }

  if (url.pathname !== '/auth') {
    throw redirect(301, '/auth')
  }
}
```

`redirect`を使うことでリダイレクトさせることができます。
こちらであれば一瞬画面が表示されちゃうみたいなことはありませんでした。

## `redirect` 使い方

### 型

```typescript
redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,
         location: string)
```

### 例

```typescript
// OK
redirect(301, '/auth')

// NG
redirect('/auth')
redirect(200, '/auth')
```
gpt-indexで日本語PDFを読み込む【Python】

# 概要
gpt-index（llama-index）で、日本語PDFを安定して読めるようにするためのプルリクがマージされたので、使い方を紹介します。

# 使い方

download_loaderで`CJKPDFReader`をダウンロードして使います。

```Python
from gpt_index import download_loader

CJKPDFReader = download_loader("CJKPDFReader")

loader = CJKPDFReader()
documents = loader.load_data(file='data/article.pdf')
print(documents)
```

デフォルトではすべてのページの文字列を結合した結果を返しますが、
ページ単位で分割したい場合は、インスタンス作成時に`concat_pages = False`とします。

```Python
loader = CJKPDFReader(concat_pages = False)
```

# 例
例えば以下の日本語PDFは、gpt-indexのデフォルトのリーダー（SimpleDirectoryReader）だと文字化けします（少なくともMacの場合）。
https://www8.cao.go.jp/chosei/koubun/about/shikumi/g_bun/kenshuu.pdf

```Python
from gpt_index import GPTSimpleVectorIndex, SimpleDirectoryReader
documents = SimpleDirectoryReader('data').load_data() # pdfをdataフォルダに格納しておく
print(documents)
```

```
[Document(text='ެจॻ\u0605ཧ੍\u0c53ʹ͍ͭͯ\n2\u0ee8\u08cd\nᶗ͜Ε·Ͱͷจॻ\u0605ཧͱެจॻ\u0605ཧ๏੍ఆͷഎܠ\n̍ɽ͜Ε·Ͱͷจॻ\u0605ཧʢߦ\u0a53ؔػͷྫʣ\n̎ɽެจॻ\u0605ཧ๏੍ఆͷഎܠ\nᶘެจॻ\u0605ཧ੍\u0c53ͷ֓ཁ\n̍ɽର\u09c5\nʢ̍ʣର\u09c5ؔػʢ̎ʣର\u09c5จॻʢ̏ʣެจॻ\u0605ཧͷ๏\u0f6fɾ\u0a53ྩɾΨΠυϥΠϯ\u0c73ͷ\u070eؔ\n̎ɽެจॻ\u0605ཧ๏ͷϙΠϯτ̏ɽެจॻ\u0605ཧ๏ͷ\u0cba༰\nʢ̍ʣ\u0ee8తʢ̎ʣߦ\u0a53จॻͷ\u0605ཧ\nᶃߦ\u0a53จॻͷ࡞\u0a52  ...
```

`CKFPDFReader`だと以下の通り正確に読めます（コード略）


```
[Document(text='公文書管理制度について\n\n\x0c\n目 次\n\nⅠこれまでの文書管理と公文書管理法制定の背景\n\n１．これまでの文書管理（行政機関の例）\n２．公文書管理法制定の背景\n\nⅡ公文書管理制度の概要\n\n１．対象\n\n（１）対象機関\n（２）対象文書\n（３）公文書管理の法律・政令・ガイドライン等の関係\n\n２．...
```

# 補足
ちなみに、デフォルトのリーダーでも、文字化けしない日本語PDFもあります。
デフォルトのリーダーではPDFの解析に`PyPDF2`を使っており、`PyPDF2`はutf8の文字コードをサポートしているので、日本語でもutf8の場合は読めて、それ以外だと文字化けするのだと思われます。
`CJKPDFReader`は何をやっているかというと`PyPDF2`の代わりに`pdfminer.six`を使うようにしただけです。詳細は以下のプルリクをご確認ください。
https://github.com/emptycrown/llama-hub/pull/35
コード生成のためのユーティリティクラス

`Unity2021.2`から`SourceGenerator`がつかえるようになりました。
しかし`StringBuilder`をそのままつかうと整形がつらくてぽんぽんぺいんなのでシンプルなラッパークラスをつくりました。
既に`SourceGenerator`をゴリゴリつかってるような有識者には役に立つものではないと思いますが、
これから始めたい人向けにシェアしようと思います。

https://github.com/TsukuruHoshikawa/CodeBuilder

C#ファイル1つの小さいコードですので落とすなりコピペするなりして使ってください。

以下のようなコードを記述することで
```C#:サンプル
using Tsukuru;

//~中略~

//インスタンスを作成
var cb = new CodeBuilder();

//コードを記述する
cb.AddCode("//Auto Generated Class");
//改行とインデントを行ったうえでコードを記述する
cb.NewLine("using UnityEngine;");
//スコープの記述
using (new BlockScope(cb, "internal class ExampleGeneratedClass"))
{
    using (new BlockScope(cb, "internal static void ExampleGeneratedFunction()"))
    {
        cb.NewLine("Debug.Log(\"I am auto generated class!!\");");
    }
}

cb.ToString();
```
以下のようなソースコードの文字列を生成できます。

```C#:生成されたコード文字列
//Auto Generated Class
using UnityEngine;
internal class ExampleGeneratedClass
{
	internal static void ExampleGeneratedFunction()
	{
		Debug.Log("I am auto generated class!!");
	}
}
```
`using`による`IDisposable`の自動開放を利用することで生成されるコードと近いスコープ構造で記述できるようにしています。

Unity標準の`GUILayout.VerticalScope`とかに近い手法です。