OmniAICreator/Qiita-1.07M huggingface dataset:
Reactで承認状態によるアクセス制御

承認機能(ログイン/ログアウト)付きのSPAサービスを開発していて、
Reactでフロントエンドを実装していたのですが、Reactには承認状態でアクセスルートを
制御するようなライブラリなどが無いことを知りました。

ネットで情報を集めてみると、一応自力でできるようですが真似してもうまくいかなったり
どれがベストプラクティスなのかもわからず、参考にしつつ自分で考えてなんとか所望とする動作を実現できたので
メモしておきます。

ログイン状態のみアクセスできるようにするAuthRequierコンポーネントを作成します。
(今回はAuthRequierという名前にしましたが、名前はなんでもいいです。)


```jsx:AuthRequier.jsx
// ログインユーザーのみアクセスできる制限をかける

import { useState, useEffect } from 'react';
import axios from 'axios';
import { Cookies, useCookies } from "react-cookie";


/**  
* ログイン処理の際に、ローカルストレージに200ステータスを保存している。
* cookieに承認トークンを保存しているので、このトークンで承認成功すれば、ログインユーザーのみページのアクセスを許可する。
* トークンでの承認が失敗した場合、ローカルストレージのステータスを401に上書きしてページのアクセスを拒否する。
*/

const AuthRequier = ({ children }) => {

  const [auth_token, setCookie, removeCookie] = useCookies(["token"]);
  const API_TOKEN = auth_token.token;

  useEffect(()=>{
      // cookieに保存されたトークンでauth承認APIにアクセスし、失敗(トークン有効期限切れ)の場合ローカルストレージのステータスを401に上書きする。
      axios.get('http://127.0.0.1:8000/api/auth',{ headers: { Authorization: "Bearer " + API_TOKEN } }).catch((error) => { 
        localstorage.setItem('auth_status', 401);
      });
  },[]);

  const isAuthenticated = localStorage.getItem('auth_status');

  //未承認ユーザーがアクセスした場合はログインページに移動させる
  return isAuthenticated == 200 ? (children) : ( window.location.href = '/login');

};

export default AuthRequier;
```
コードの解説です。
自分のサービスでは、ログイン時に取得したトークンをcookieに保存して管理してます。
また、ログイン状態はlocalstrageで管理していて、ログインしている(トークン有効)の場合は
値に200にセットするようにしています。(ログインしてない場合は401にセットするようになってます)

承認状態を判定するAPIに、cookieに保存されてるトークンでアクセスします。
ここで承認OKならlocalstrageは200のままですが、NGの場合は401に書き換えられます。
このlocalstrageの値を変数"isAuthenticated"に格納しています。

三項子演算で、変数"isAuthenticated"が200なら承認制限つきページ(コンポーネント)を表示し、
ダメなら指定のルート('/'の部分です。ここは自由に変更できます。)へ強制的に移動するようにしてます。


このAuthRequierを使うには下記のようにします。
(react router v6の書き方です。他verだと動きませんので注意。)

```jsx:app.jsx


//AuthRequierをインポート忘れずに
import AuthRequier from './components/AuthRequier';

<BrowserRouter>           
      <Routes>
           //アクセス制御なし
          <Route path="/" element={<Welcome />}/>

           //アクセス制御あり
          <Route path="/mypage" element={<AuthRequier><MyPage /></AuthRequier>} />
      </Routes>
</BrowserRouter>
```

これでアクセス制御できました。
あくまで自己流なのでこれで合ってるかどうかはわかりませんが、何か参考になれば幸いです。
python、bottleの導入方法、使い方

bottleは簡単にアプリが作れるPythonのフレームワーク。

## pythonとbottleの導入方法
### pythonをインストールする(Windows)
①以下のサイトを開く。
https://www.python.org/
②Downloadsにカーソルを合わせ、"Download for Windows"の下のボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/b5aec588-3fc4-ee5d-12da-c1e5a26b62c9.png)
③インストーラを開き、画面下の"Add Python 3.10(バージョン) to PATH"に**必ずチェックを入れる**。
④"Install Now"をクリックしてインストールを開始する。
⑤インストールが終わったら、以下のような画面が出る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/df8db8e0-f765-e9ba-d849-5dd7975f87f2.png)
⑥インストールができているか確認する。
　コマンドプロンプトを開く。（管理者権限でなくて良い。）
　以下のコマンドを実行する。
```
python --version
```
⑦以下のように表示されたらOK。
```
Python 3.11.4(バージョン)
```

### コマンドプロンプトでPythonのバージョンが出ない場合
・Pythonをインストールし直す。
**（インストールする時に必ず、"Add Python 3.10(バージョン) to PATH"にチェックを入れる。）**
・アプリ実行エイリアスをオフにする。
　以下のサイトを参照。
　https://www.out48.com/archives/5720/

### bottleの導入方法
①コマンドプロンプトを開く。（管理者権限でなくて良い。）
②ファイルを保存する場所にフォルダを作成する。
②以下のコマンドを実行する。
```
cd ②のファイルパス
pip install bottle
```
③動作確認をする。
　・②pythonファイルを作成する。（名前は何でもよい）
　　**※必ずbottle.pyと同じ階層にファイルを作成する。**
　・pythonファイルに以下のコードを記述する。
```Python
# -*- coding:utf-8 -*-

from bottle import route, run

@route('/hello')
def hello():
    return "Hello world!"

run(host='localhost', port=8080, debug=True)
```
　・以下のコマンドをコマンドプロンプトで実行する。
```
python 〇〇.py
```
　・以下のURLにアクセスすると確認ができる。
　　http://localhost:8080/hello
　　※Ctrl＋Cで実行が止まる。


## 参考サイト
Pythonの環境構築
https://prog-8.com/docs/python-env-win

コマンドプロンプトでPythonのバージョンが表示されない場合
https://www.out48.com/archives/5720/
https://happy-tenshoku.com/post-6679/

bottleの使い方
https://qiita.com/pulat/items/d401853c2bf1f7b5661b
Azure App ServiceでFlaskアプリケーションを公開する(with AAD認証)

# 目的
ChatGPTアプリをFlaskで作成したので、Azure App Serviceに置きたくなった。
Azure App Serviceならではのハマりポイントがあったのでメモ程度に残しておく

# Flask DanceでAAD認証する

とりあえず必要なパッケージをいろいろ設定する。
```requirements.txt
openai
jinja2
flask
Flask-Dance
```

アプリケーションの作りはこんな感じ

※Flask自身はHTTPで動くためredirect_urlがhttp://~になってしまうため、
class ReverseProxiedを追加してHTTPSで動いていることをFlaskに伝えとく。
ここでかなりハマった。

```app.py
from flask_dance.contrib.azure import make_azure_blueprint, azure

class ReverseProxied(object):
    def __init__(self, app):
        self.app = app
    def __call__(self, environ, start_response):
        scheme = environ.get('HTTP_X_FORWARDED_PROTO')
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        return self.app(environ, start_response)

app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)
app.secret_key = "xxxxxxxx"

blueprint = make_azure_blueprint(
    client_id = "xxxxxxxx",
    client_secret = "xxxxxxxx",
    tenant = "xxxxxxxx",
)

app.register_blueprint(blueprint, url_prefix="/login")

@app.route("/", methods=["GET"])
def index():    
    if not azure.authorized:
        return redirect(url_for("azure.login"))
    resp = azure.get("/v1.0/me")
    assert resp.ok
    ##### 処理いろいろ #####
    return render_template("index.html")

if __name__ == "__main__":
    app.run(debug=True)
```

Azure App Serviceの設定はこんな感じ
App Serviceはデフォルトでgunicorn経由でFlaskを動かすらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609092/69f88a03-e6dc-368b-a595-0953dba12482.png)
スタートアップコマンド
```
gunicorn --bind=0.0.0.0 --timeout 600 app:app
```

AADへのアプリ登録は今のところ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609092/25c7380c-e329-8109-82fe-71375f6f05b5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609092/a56f5f1d-8f38-d180-de9b-a5817229bc79.png)

完成したチャットアプリは今のところはこんな風
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609092/a679eda5-5421-b4b2-3cd6-971a59e182e6.png)
[読書感想分] SIerが「サイロエフェクト」を読んでみた。

# 今回の書籍

今回の書籍は「サイロ・エフェクト　高度専門家社会の罠」です。

https://amzn.asia/d/4qi284Y

前回感想を書いた「失敗の科学」と併せて読みました。

https://qiita.com/satoshi256kbyte/items/4d3f3dc9c060f907f1aa

# 本書の概要

本書は、サイロ化（＝部門間の情報が共有されていない状態）により組織が不利益を被った事例と、サイロ化を乗り越えた事例が述べられています。
しかし、正直なところ、本書はかなり読みづらかったです・・・。
読み込んで行けば理解はできるのですが、込み入った事情が細かく描かれすぎていてわかりづらいです。
作りとしては「失敗の科学」と同じなのですが、あちらは一つ一つのエピソードが比較的短いのと題材に身近なものが多かったのでまだよかったのですが、こちらは読むのがしんどいですね。

# 引き続き残ったキーワード

## 専門外の領域に取り組むハッカソンという仕組み

この本で語られるハッカソンとは、
部門のメンバーと組み、普段の仕事とは無関係のプロジェクトに取り組むことを求める活動です。
全体的にサイロ化の原因を他部門が何をやっているか知らない、やっていることの大変さを知らないということに求めており、私もこの活動はとてもよいものと感じました。

## 各専門が成功ゆえにサイロ化する

このキーワードは医療関係の章で出てきますが、とてもよく共感できます。
ITも技術が複雑すぎて一人で全部学ぶのは無理すぎます。
専門分野に分かれないと半端な人ばかりになってしまい、それはそれで問題になると思います。

## 分類されていないと不安な人もいる

本書の中では既存の枠組みにいる人にとっては、分類されている方が都合がよいという文脈で書かれていますが、私は違う観点で刺さりました。
仮に私が役割が明確に分かれていない現場に投入されたら、どこまで自分がやらなければならないのか不安になるでしょう。

# SIerとしての自分に当てはめてみる

長らくSIerとして生きていますが、個人的にはSIerの現場では本書で語られるようなサイロ化はバリバリ起きていると感じています。
他部門で実績があることを知らずに車輪の再発明をしてしまった！という経験が何度もあります。

部門間の仲がよいというところはなかなかないですね・・・。
部門間で競争関係はないはずなのに、なぜかそれが発生してしまいます。

全体的にスコープを大事にする文化がサイロ化を助長している感じがします。
自分の領域をしっかり決めて、そこをきっちりやる、領域外のことは下手に手をつけないのがお互いのため！みたいな感じです。
でも現場で重宝されるのはそこを飛び越えてチーム同士を繋ぐ人だったりするので、ダブルスタンダードを感じます。
チームではなく、個人レベルでも、SIerのエンジニアは全体的に多忙で余裕がなく、範囲外のことには興味を示さない方が多い印象です。

SIerは医療や防災などと違い単なる営利企業であり、その多くは下請けです。
患者さんのために！のようなわかりやすい大義名分がなく、共有できる価値観がないので、サイロ化の解消の難易度は高そうです。

特に特効薬は思いつかないのですが、本書の中にあったハッカソンが地味に参考になりそうです。
とはいえ、本当のハッカソンは工数的にも難しいでしょうね。

まずは、自部門が何をしているかを日常的に発信すること、もし他部門が発信していたらそれを積極的に聞くことが大事だと思います。
ちなみに、期の節目だけの発信では、期待値があがりすぎてやる方も聞く方も疲れてしまうので、気長に日常的にやるのがよさそうです。
リソースストレージのためにPGSQLをデータベースとして選ぶ理由

### Selefraのポリシーコードツールにおける理想的なデータベースの選択を分析する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3286109/644c5ae4-2bf1-5b79-504a-5758c1c06e58.png)

### はじめに

現代のクラウドコンピューティング環境では、マルチクラウドセキュリティ、コスト分析、組織構造分析などのタスクを達成するために、ポリシーコード（PaC）ツールへの需要が増えています。Selefraは、ポリシーを読み取るためにYAMLを使用し、クラウドサービスリソースを保存するためにPGSQLデータベースに依存している優れたPaCツールです。この記事では、なぜリソースストレージのためにPGSQLが選ばれたのかを探求し、そのようなクエリ分析のPaCツールにおける利点を強調します。

### スケーラビリティ

PGSQLは、優れたスケーラビリティを持つ成熟したオープンソースのリレーショナルデータベース管理システム（RDBMS）です。クラウド環境では、リソースの数や規模が時間とともに増えることがあります。PGSQLのスケーラビリティにより、異なるスケールの環境でのSelefraのストレージ要件を満たすために、大量のデータを処理し、水平および垂直のスケーリングをサポートすることができます。

### データの一貫性

リレーショナルデータベースであるPGSQLは、頑強なトランザクションのサポートを提供し、データの一貫性を保証します。Selefraは、クラウドサービスリソースからデータを読み取り、それに基づいてポリシーチェックを実行する必要があります。PGSQLのトランザクションメカニズムにより、データの整合性と一貫性が複数のクエリや分析操作全体で保証されるため、ツールの信頼性と正確性が向上します。

### 強力なクエリ機能

Selefraでは、クラウドサービスリソースの柔軟で効率的なクエリと分析が必要です。PGSQLは、複雑なSQLクエリ、集計操作、ウィンドウ関数などをサポートする豊富なクエリ機能を提供しています。PGSQLの強力なクエリ機能を活用することで、Selefraはマルチクラウド環境でのリソースの深い分析を簡単に実行し、ユーザーに貴重なインサイトを提供することができます。

例えば:

```sql
SELECT
  DISTINCT(a1.*)
FROM
  aws_s3_buckets a1,
  aws_s3_bucket_grants a2
WHERE
 a1.selefra_id = a2.aws_s3_buckets_selefra_id
  AND a2.grantee :: jsonb ->> 'URI' = 'http://acs.amazonaws.com/groups/global/AllUsers'
  AND a2.permission IN ('WRITE_ACP', 'FULL_CONTROL');
```

### セキュリティ

PaCツールでは、セキュリティは重要な懸念事項です、特に機密データを扱う場合です。PGSQLは、ロールベースのアクセス制御、SSL/TLS暗号化、データの透明な暗号化保存など、多層のセキュリティ機能を提供しています。リソースの保存のためにPGSQLをデータベースとして使用することで、Selefraはこれらのセキュリティ機能を活用してユーザーデータを保護し、機密情報が不正な者にアクセスできないようにします。

![Untitled (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3286109/8c1c7d9c-e119-a4d9-4f2a-ecd12605e494.png)


### 成熟したエコシステム

人気のあるデータベース管理システムであるPGSQLには、大規模で活発なコミュニティとエコシステムがあります。これにより、パフォーマンスチューニング、セキュリティのベストプラクティス、バグ修正に関するサポートやアドバイスを簡単に入手できます。Selefraは、PGSQLコミュニティの知識とリソースを活用し、データベース技術の最新の動向について常に最新情報を得ることができ、必要な場合にサポートを受けることができます。

### 結論

SelefraでリソースストレージのためにPGSQLを選ぶことは賢明な選択です。PGSQLのスケーラビリティ、データの一貫性、強力なクエリ機能、セキュリティ機能、成熟したエコシステムは、クエリ分析に基づくポリシ

ーコードツールにおいて理想的な選択肢となります。PGSQLの利点を活用することで、Selefraは効率的で信頼性の高いクラウドサービスリソースの分析を提供し、マルチクラウド管理においてユーザーに優れた体験を提供することができます。

GitHub: https://github.com/selefra/selefra

Slack: https://selefra.io/community/join

## **おすすめの読み物**

[公開アクセス可能なAWS S3バケットの問題を見つけて修正する方法](https://www.selefra.io/blog/how-to-spot-and-fix-issues-with-publicly-accessible-aws-s3-buckets-cljl5t7ng11971413tqwzdeuzfvm)

[SelefraがGPTを活用したマルチクラウドセキュリティスキャンをどのように組み合わせているか](https://www.selefra.io/blog/how-selefra-combines-gpt-for-multi-cloud-security-scanning-clji608k39978973tqwvuerzhnu)
新しい技術や言語を学習する際に行なっていること3選

#  はじめに
最近は社内でも新しい領域へチャレンジするエンジニアが増えてきているのですが、その際によく聞かれる質問として【新しい技術や言語を学ぶ際にどうやって学習を進めたら良いですか？】というものがあります。
こちらに関していつもお話している回答があるので、こちらを記事にまとめてみようと思います。

:::note warn
完全な初学者向けではありません、すでに技術のベースがある前提で解説を進めております。
:::

# その１：Gitなどに上がっているサンプルプロジェクトやOSSの実装を見る
まずひとつ目が、Gitなどに上がっているサンプルプロジェクトやOSSの実装を見る、というものです。
ひとつ目にしてこの方法がほぼ学習のベースになっているのですが、全てにおいて【できる限り迅速に現場で使える技術として理解する】という点が目的にあります。

新技術を触る状況においては、完全な初学者と違い身につけるスピードが重要となってきます。
掛けられる学習コストが決まっている状況の中で、できる限り無駄なくクオリティの高い学習を進める必要があります。
この状況においてプログラム初学者のように初学者向けの本や動画ではコストがかかり過ぎてしまうことがあります。

そこでオススメしたいのが、学習対象のサンプルプロジェクトやOSSの実装を追い、理解する事です。
このサンプルプロジェクトは多くの場合において、学習対象を深く理解したエンジニアが実装しています。
つまり現場に最も近い環境であり、まさに最高の学習教材です。
上記を理解することで、より実践に近く効率よくスキルが手に入るということになります。

ちなみに当然ではありますが、学ぶ先の言語や技術を使用したプロジェクトが社内にあれば積極的にそちらを参照すべきです。
理解すべきは現場の技術なので、是非こちらをベースに進めていただけたらと思います。

# その2：対象言語の公式ドキュメントを参照する
一つ目がサンプルプロジェクトやOSSを見るということでしたが、二つ目は公式のドキュメントを見るということです。

OSSやサンプルプロジェクトを参照することは身につける上で最短ルートではありますが、その分困難な道とも言えます。
なぜなら参照当初は特に言語や技術への理解が乏しい状況だからです。
まさに茨の道ですが、この茨の道をマイルドにできる方法が公式のドキュメントを参照するというものです。
プログラマをしていたら必ず一度は目にする公式ドキュメントですが、まさに欲しい情報をピンポイントでくれる最高の辞書です。

学習対象を参照している際、その言語や技術特有の単語や機能が満載だと思います。
この不明な点を列挙し知るべき優先順位を付け、公式ドキュメントと順番に照らし合わせていきます。
そして照らし合わせても理解が足りないと感じたものは自身でその機能を使用して検証し、理解を深めていきます。
上記をひたすら繰り返しているうちに言語への理解も深まっていくでしょう。

重要なのは照らし合わせて検証するというこのフローです、後に説明しているラーニングピラミッドの図を見ていただければわかりやすいです。

# その3：Qiitaや社内の勉強会など、何かしらの形でアウトプットする
最後の三つ目は学習した内容をアウトプットすることです。
これはこれまでの2つと方向性としては異なっていますが、インプットしただけではとても理解したとは言えません。
そこで、何かしらの形で学習した内容を自分の言葉でアウトプットすることです。

アウトプットの仕方はなんでも問題ありません、Qiitaに記事としてまとめるのも良いですし、エンジニア間でLT大会でも良いですね。

これはご存知の方も多いかもしれませんが、理解の深さを示したラーニングピラミットという図形が存在します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/a8de2ae8-b539-226a-00bb-93529e06bd95.png" width="330px">

この図形によると読書や講義はほぼ理解したと呼ぶには浅く、デモンストレーションや自ら体験する事でようやく理解をするための準備が整ったような段階です。
理解した内容を他の人に教えるなどアウトプットを行うことで初めて自分の技術として完全なものになるという事です。

是非自分の中でのみ完結させて満足せず、アウトプットを行い自分の技術としてしっかり落とし込んでもらえたらと思います。

# さいごに
何事も新しいことを学ぶことは簡単ではないですよね。
どうせ大変な思いをするのであればできる限り効率よく行うべきだと思いますので、少しでもお力になれていたら幸いです。
【SQL】WHERE句とON句の違い

SQL構文の学習中、ON句を見かけましたが、イマイチ理解していなかったので、調べてみました。

学習の記録として、こちらにまとめておきます。

プログラミング、SQL初学者の方は是非参考にしてみてください。


# WHERE句の使用例
```ruby
SELECT *
FROM employees
WHERE employees_no < 999
```


# ON句の使用例

```ruby
SELECT cat.name, COUNT(book.name) AS num
FROM categories AS cat

INNER JOIN book_categories AS book_cat
ON cat.id = book_cat.category_id

INNER JOIN books AS book
ON book_cat.book_id = book.id
```

# WHERE句とON句の違い
- ON句もWHERE句、どちらも条件指定を行うためのコマンド。
- ON句での条件指定は、結合条件を指定する意味合いで使われる。
- WHERE句での条件指定は、対象データの抽出を行う際に使う。
- 条件を指定したテーブルの結合を行いたいときにON句を使用し、その後の抽出データの条件を指定する際に、WHERE句を用いる。



# 最後に
RubyのフレームワークであるRuby on Railsでは、ActiveRecordによって、SQLを直接指定せずに、データを取り扱うことが可能です。

が、SQLはWeb開発において、どこでも必要な技術であるため、SQLコマンドを習得することはとても大事なことです。

SQLコマンドの練習を日々行い、SQLに対する苦手意識を克服していきたいと思っています。



# 参考サイト

https://style.potepan.com/articles/26226.html
勉強してて思ったこと


初めまして。
統計学や、データサイエンスを勉強して思ったことがあります。
# 統計学
統計学は入門書を何冊かやりました。
・東京大学出版の統計学入門。（通称赤本）
・Excelでできるらくらく統計解析
・入門はじめての統計解析
・完全独習統計学入門
その中で、自分の理解が本質を突いていない、自分の理解の違うところに本当の統計学があると思いました。
統計学は思ったより抽象的で、ガチっと理解することが難しいものなのかなと思いました。

# データサイエンス
データサイエンス的なものは、
・スッキリわかるPythonによる機械学習入門
・東京大学のデータサイエンティスト育成講座
などをやりました。

統計学の勉強の反面、データサイエンスの機械学習は自分の理解でいいと思っていますが、やるべきことが膨大であると思いました。

統計検定3級を2022年6月に取得しました。一か月間（約30時間）かかりました。
まだまだ始めたばかりですが、こういうことについて気をつけて、勉強していきたいと思いました。
統計検定2級には着手しているのですが、公式の教科書にてこずっています。
PyTorch Memo 備忘録

# 1. GPU確認コード

```Python:00.torch_gpu.py
import torch

print("PyTorch version:", torch.__version__)

if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA device object
    print(f"Using {torch.cuda.get_device_name()} for PyTorch")
else:
    device = torch.device("cpu")           # a CPU object
    print("No GPU available, using CPU for PyTorch")
```

```: result
PyTorch version: 2.0.1+cu118
Using NVIDIA GeForce RTX 3060 Laptop GPU for PyTorch
```
Windows11とUbuntu 22.04をデュアルブートするときのメモ

# はじめに
ROSで遊ぶための綺麗な環境を作るためにUbuntuを入れたい。複数ディスクを用意して、デュアルブートしたときのメモです。

同じディスクにデュアルブートは失敗のリスクが大きいという噂を聞いていましたが、今回は複数ディスクがあり、WindowsとUbuntuをそれぞれ別のディスクにインストールできるので、デュアルブートにチャレンジしました。

# PCスペック

- CPU：13th Gen Intel(R) Core(TM) i7-13700F   2.10 GHz
- 実装 RAM：32.0 GB (31.8 GB 使用可能)
- OS：Windows 11 Home バージョン	22H2
- ディスク：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/345e4e77-5975-4cc8-dd44-e1710b54bf60.png)

# インストールメディアの作成
参考にさせていただいたサイト：
- https://tabi-suki.net/ubuntu-jp-usb-install.html
- https://kledgeb.blogspot.com/2022/04/ubuntu-2204-64-windowslinuxmacosubuntu.html

1. "ubuntu-ja-22.04-desktop-amd64.iso" をダウンロード
2. balenaEtcher を起動
3. 8GB以上のUSBにディスクのイメージを作成する

# インストール
参考にさせていただいたサイト： https://blog.kabocy.com/linux/5828/

1. インストールメディア（USB）を挿して電源起動
2. BIOS設定画面を開く(F2)
3. BootオプションでUSBを選択
4. 画面の指示に従ってインストール

![IMG_8188.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/4ebd04df-fc24-7130-2a95-b6f8f70e3c0a.jpeg)

![IMG_8189.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/8e62d7c6-12e1-3634-22fb-0e077ed2d9ce.jpeg)
デフォルトでWindowsとは別にインストールという選択肢があるので、そちらを選択。それ以外を選択してもOK。(Windowsを消してしまわないようにドキドキしながら選択しました。)

![IMG_8190.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/78908eb2-d42e-5aae-029e-69a2c2d1a598.jpeg)

パーティションを適当に区切ります。
![IMG_8192.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/ba3c7684-5e03-e7c5-b37a-8bd88958d487.jpeg)


![IMG_8193.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/f5d3ca97-69b2-0301-ff39-ab23898d8110.jpeg)

![IMG_8194.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/5269c440-83d3-a567-c73e-27de9b316193.jpeg)

![IMG_8195.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599506/e5bf76e8-e66b-f93c-4252-eca04e18c6a2.jpeg)

インストール完了しました！
Pythonノート: Text処理

# 概要
Pythonノート Text処理系

# file open / close

## open()
- open() を使ってファイルを開く

```py
>>> f = open('./xxx.txt')
```

- 第二引数でモードを指定する

|mode|description|
|--|:--|
| 'r'| open a file for reading (default) |
| 'w'| open a file for writing. create a file if it does not exist |
| 'x'| exclusive flag, If the file already exists, the operation fails. |
| 'a'| open for appending |
| 't'|  open in text mode (default) |
| 'b'| open in bianry mode  |
| '+'| open a file for updating(reading and writing) |


- 'r', 'w', 'a', 'x' はどれか1つだけ指定可能
- 'b', 't'もどれか1つだけ指定可能
- '+'は'r', 'w', 'a', 'x' と組み合わせて指定
  - 'r+' :  既存ファイル先頭位置がファイル位置となる。指定した名前のファイルがない場合はエラー
  - 'w+' : ファイル新規作成、または既存ファイルをオープンして内容を削除。ファイル先頭位置がファイル位置
  - 'a+' : ファイル新規作成、または既存ファイルをオープンして追記。ファイル末尾がファイル位置となる
  - 'x+' : ファイルを新規作成してファイル先頭位置がファイル位置になる

'+'指定は読み書き両用。'r' 'w' は読みのみ、書きのみ

- write to text file
```py
>>> f = open('./xxx.txt', mode='w')
```

- write to binary file
```py
>>> f = open('./yyy.bin', 'wb')
```

- 第3引数でエンコードを指定できる (defaultの'utf-8'のままで普通は良い)
  - encoding =  'utf-8' (default) |  'shift_jis' |  'euc_jp' |  'iso2022_jp'

```py
>>> f = open('./regacy.txt' , encode='shift_jis')
```


## f.close()
-　close file object
```py
>>> f = open("<file path>", "r")

...
>>> f.close()
```

# file read / write

- 以下のようなtextファイルを読み込む場合を考える

```py
# file.txt
alice
bob
cherry
```

## f.readline()

- 1行読む（改行文字まで, 改行文字も含む）

```py
>>> f = open('file.txt', 'r')
```

- 1回目=1行目
```py
>>> line = f.readline()
>>> line
'## file.txt\n'
```
- 2行目
```py
>>> line = f.readline()
>>> line
'alice\n'
```
- 3行目
```
>>> line = f.readline()
>>> line
'bob\n'
```

## f.readlines()
- ファイル全体をリスト変数として読み込める
```py
>>> lines = f.readlines()
>>> lines
['# file.txt\n', 'alice\n', 'bob\n', 'cherry']
```

## f.read()
- 引数指定でn文字読む
- 未指定の場合すべてを読み込む
```py
>>> val = f.read()
>>> val
'# file.txt\nalice\nbob\ncherry'
```


## with open (file path) as (variable): 構文
- with表記を用いると close(開放)まで自動で行う

```py
with open ./a.txt as f:
    <処理>
```
- withのインデントを抜けると自動でclose


## f.write()

- `open()`でファイルオープン、以下の文字列を`write()`で書き込む
```py
text = """FILE
ALICE
BOB
CHARLY
"""

with open('new.txt', 'w') as f:
   f.write(text)
```

```txt:出力.txt
FILE
ALICE
BOB
CHARLY
```

# regular expression (re)

## `re` module

正規表現を使うには`re` moduleを用いる

- import
```py
import re
```

### `re.match()`

- match()でマッチオブジェクトを取得
- match('pattern', 'target strings') 
```py
>>> m = re.match('(\w+)\s(\w+)\s\w+',  'aaa bbb ccc' )
```

## match オブジェクト

上記では`m`がマッチオブジェクト

### `groups()`メソッド 

- マッチした要素をタプル形式で取得できる
- 括弧(brace)でマッチした要素はタプルに保持される。

- `groups`メソッドでタプルを表示
```py
>>> m.groups()
('aaa', 'bbb')
```

### `group()`メソッド 

`goutp()`メソッドではパターン内の()でマッチしたそれぞれの要素を引数＝indexで指定して取り出せる

- index=0 はマッチした全体の文字列を表す
```py
>>> m.group(0)
'aaa bbb ccc'
```

- index=1
```py
>>> m.group(1)
'aaa'
```

- index=2
```py
>>> m.group(2)
'bbb'
```

### `re.sub()`

- re.sub('pattern', '置換後のpattern',  string) で置換した文字列を取得する

```py
>>> s = 'aaa_aaa_bbb_bbb'
>>> s_new = re.sub('aaa', 'ABC', s)
>>> s_new
'ABC_ABC_bbb_bbb'
```

- 第4引数で最大置換回数を指定できる

```py
>>> s_new1 = re.sub('aaa', 'ABC', s, 1)
>>> s_new1
'ABC_aaa_bbb_bbb'
```
ABC309 - C - Medicine 自己解法

# 問題

https://atcoder.jp/contests/abc309/tasks/abc309_c

# 考察

飲む薬の錠数がK錠以下になるのは何日目か求めてくださいという問題です。1日目はすべての薬を飲むことになりますが、次第に飲む薬の錠数が減っていきます。1日目から順にシミュレートしていきたいところです。ですが、$a_i$は$10^9$まで値をとるので、計算量的に間に合いそうにありません。そこで、薬を飲む錠数が減る日にちのみに注目してシミュレートするようにしていきましょう。薬を飲む錠数が減るタイミングは各種類の$a_i + 1$日目です。このときに現在飲んでいる錠数から$b_i$錠減らします。これで$K$錠以下になっているかを確かめると良いです。1日目に飲む薬の錠数は各種類の全ての錠数を合計すればいいですし、薬の種類を$a_i + 1$が小さい順にソートさせておけば薬を減らす順に薬を取り出すことができます。
これらによって十分間に合う計算量でシミュレートできそうです。実装していきましょう。
実装によっては1日目で$K$錠以下しか飲んでいないコーナーケースが出てくることもあります。注意しましょう。

# 提出コード(コンテスト後)

https://atcoder.jp/contests/abc309/submissions/43414132

ご不明点などがあれば教えていただけると幸いです。
WSL2をDドライブにインストールする

1. WSL2をインストールします。

    ```powershell
    wsl --install Ubuntu
    ```

1. デフォルトユーザのUIDをメモしておきます

    ```bash
    id -u
    ```

   おそらく1000です。

1. WSL2をエクスポートします。

    ```powershell
    wsl --export Ubuntu D:\Ubuntu.tar
    ```

    ファイルは1GB程度です。

1. WSL2インスタンスを削除します

    ```powershell
    wsl --unregister Ubuntu
    ```

1. WSL2をインポートします。


    ```powershell
    wsl --import Ubuntu D:\wsl D:\Ubuntu.tar
    ```

1. WSL起動時のデフォルトユーザー変更

    1. Windowsキー+Rから `regedit` でレジストリエディタ起動

        - wslの各Distro情報は以下にディストリビューションごとに格納されている
             `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss`

        - DistributionNameで今回入れたUbuntuを特定
            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184382/c0b55d0c-178d-4537-2a3b-d5f6cec74a84.png)

        - DefaultUidの値を変更する（例：0から1000(16進数では3e8)に変更）
            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184382/aafb0460-71ce-5ff7-d0c0-efde4b721e54.png)
UDPマルチキャストで複数台の受信機からの返信を同時受信

## 実現したいこと
・一台のサーバから複数台の受信機に対して同じデータを送信する
・効率の良い送信を行うため，マルチキャストを使用する
・マルチキャストを使い，複数台の受信機に対してほぼ同時にデータを配信した後，それぞれからの返信を受信する．

## 実装
### 実装環境
・本記事では**自身のラップトップをサーバ**とし，複数台のESP32に対してデータ送信行いましたが，どんな環境でもできるはずです．

### 使用するライブラリ

・Threadingライブラリ
簡単に説明すると非同期処理を行うライブラリです．

https://docs.python.org/ja/3/library/threading.html

### 実装方法
サーバから受信機であるESP32に対して，簡単な挨拶メッセージを送り，それに対して個々から返信をもらうプログラムです．おまけに受信時間を記録しています．

今回のコードでは，respond関数をメインスレッドから切り離し，受信機からの返信が到着したタイミングでrespond関数内の処理を行います．
またソケットがタイムアウト(指定秒以内に受信しない)したら，例外処理に移行し，スレッドを閉じることでプログラムが終了します．

```server.py
import time
import socket
import threading

LOCALHOST = socket.gethostbyname(socket.gethostname())
multicast_grp = "239.1.2.3"
PORT = 1234

end_t = []

# ソケットを作成
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((LOCALHOST, PORT))
sock.settimeout(4)

# クライアントからのメッセージを受信して返信する関数
def respond():
    # クライアントからのデータを受信
    while True:
        try:
            data, addr = sock.recvfrom(1024)
            end = time.time()
            end_t.append(end)
        except Exception as e:
            # タイムアウトしたらこのスレッドを終了する
            print(f"error: {e}")
            break


# クライアントに順番にデータを送信し、同時に受信も行うスレッドを作成して開始
start_t = time.time()

respond_thread = threading.Thread(target=respond)
respond_thread.start()

sock.sendto("Hello ESP32!".encode(), (multicast_grp, PORT))


# スレッドが終了するまで待機
respond_thread.join()

print("All Done")
```

※受信機側の処理は省いていますが，マルチキャストパケットを受信したらそれぞれが通常通り返信を行えばいいです．
PHP初心者がつまづきながらもDocker + CakePHPの環境構築をしてみた

どうも、こんにちは。mokomokoです。
インフラを2年間やってから開発現場へ移って3ヶ月がたった新米エンジニアです。
業務ではCodeigniterを触っているのですが、なにか他のPHPフレームワークも触ってみたいと思ったため、Docker + CakePHPで簡単なアプリとDBだけの環境を作ってみます。

# やること

・DockerでCakePHPの環境構築

# ディレクトリ構成

```
 .
├── /docker
│  └── Dockerfile
├── /html
└── docker-compose.yml
```

ラクしたい方は下記コードをそのままシェルにコピペして実行してください
```shell
mkdir docker   
touch docker/Dockerfile 
mkdir html 
touch docker-compose.yml
```

# docker-compose.yml
```yaml
version: "3.7"
services:
  cakeapp:
    build:
      context: ./docker
      dockerfile: Dockerfile
    ports:
      - "8080:80"
    tty: true
    stdin_open: true
    volumes:
      - ./html:/var/www/html

  db:
    image: mysql:5.7
    volumes:
      - "./db:/docker-entrypoint-initdb.d"
    environment:
      MYSQL_DATABASE: database
      MYSQL_USER: mysql000user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
```

# Dockerfile
```dockerfile
FROM php:7.3-apache

RUN apt-get update \
    && apt-get install -y unzip libicu-dev \
    && docker-php-ext-install intl \
    && docker-php-ext-install pdo_mysql \
    && a2enmod rewrite \
    && apt-get clean \
    && rm -fr /var/lib/apt/lists/*
```
# とりあえず構築してみる
```shell
docker compose up -d
docker ps   # コンテナID確認する 
docker exec -it {CONTAINER ID} bash # コンテナ内へ入る

# pharファイルを置いてプロジェクト起動
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php composer.phar create-project --prefer-dist cakephp/app:4.* html
```

<code>http://localhost/8080</code>
>Forbidden
You don't have permission to access this resource.

と、エラーがでた。
コンテナのログを調べると,,,
```shell
docker logs {CONTAINE ID} # ログ出力

> Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.php,index.html) found, and server-generated directory index forbidden by Options directive
```
なんかアクセスしてる場所が違うっぽい。
ディレクトリを見ると最初に作ったhtml配下にCakePHPで作成されたhtmlが入っていたので
<code>http://localhost/8080/html</code>
でオープンできた。
(www/配下でcomposerすればよかっただけ、、)


# DBと接続

app_local.php
```php
'Datasources' => [
        'default' => [
            'host' => 'db', # docker-composeのservice名
            ~~~ 省略 ~~~
            //'port' => 'non_standard_port_number',

            'username' => 'mysql000user',
            'password' => 'password',

            'database' => 'database',
            /*
             * If not using the default 'public' schema with the PostgreSQL driver
             * set it here.
             */
            //'schema' => 'myapp',

            /*
             * You can use a DSN string to set the entire configuration
             */
            'url' => env('DATABASE_URL', null),
        ],
```

これで環境構築おしまい。
対数関数の性質まとめ

# 対数関数とは

対数関数は指数関数の逆関数になります。
いくつか具体例を出します。

```math
\begin{eqnarray}
2^3=8 &\Leftrightarrow& \log _28=3\\
6^2=36 &\Leftrightarrow& \log _636=2\\
4^\frac12=2 &\Leftrightarrow& \log _42=\frac12
\end{eqnarray}
```
logの下に小さく書いてある数を底、右に書いてある数を真数と言います。
日本語で書くと「底の何乗が真数になりますか？」ということを計算した結果ということになります。
また、底にネイピア数 $e=2.718 \cdots$ を使う場合には表記を省略することが多いです。

## 対数関数で成り立つ性質

対数関数の定義と指数法則を使っていくつか定理が導けます。
先に元となる定義から導ける内容と指数法則を紹介します。

### 逆関数であることから分かることと指数法則

それぞれ以下の性質を持ちます。

* 指数関数の逆関数であることから導かれる性質

|番号|数式|
|:-:|:-:|
|1|$a^{\log _ab}=b$|
|2|$\log _a{a^b}=b$|

* 指数法則

|番号|数式|
|:-:|:-:|
|3|$a^ma^n=a^{m+n}$|
|4|$(a^m)^n=a^{mn}$|
|5|$(ab)^n=a^nb^n$|

### 対数の持っている性質、定理

1~5をうまく組み合わせると以下のことが分かります。
詳しい証明は省きますが、方針のみ記載しておきます。

|番号|数式|証明の方針|
|:-:|:-:|:-:|
|6|$\log _aa=1$|2に $b=1$ を代入|
|7|$\log _a1=0$|2に $b=0$ を代入|
|8|$\log _amn= \log _am+ \log _an$|$\log _a(a^{\log _am}a^{\log _an})$ に1を使えば左辺に、3,2を使えば右辺になる|
|9|$\log _am^n=n \log _am$|$\log _a(a^{\log _am})^n$ に1を使えば左辺に、4,2を使えば右辺になる|
|10|$\log _a \frac mn= \log _am- \log _an$|$\frac mn=mn^{-1}$ なので、8と9を組み合わせる|
|11|$\log _ab= \frac{\log _cb}{\log _ca}$|$\log _ca^{\log _ab}$ に対して9を使ったものと1を使ったものとを比べる|
|12|$\log _ab= \frac{1}{\log _ba}$|11に $c=b$ を代入する|

### その他性質

対数関数の計算時によく使う性質たちです。

|番号|数式|補足|
|:-:|:-:|:-:|
|13|$\frac{d}{dx}\log x = \frac{1}{x}$|微分|
|14|$\int \log xdx =x \log x-x+C$|積分、 $C$ は積分定数|
|15|$\log (1+x)=x- \frac12x^2+ \frac13x^3- \frac14x^4+ \cdots$|マクローリン展開、収束半径は1|
|16|$e^x=1+x+ \frac{x^2}{2!} + \frac{x^3}{3!} + \frac{x^4}{4!} + \cdots$|マクローリン展開|
|17|$\lim _{x \rightarrow \infty} \log x= \infty$|極限|
|18|$r>0 \Rightarrow \lim _{x \rightarrow \infty} \frac{\log x}{x^r}=0$|対数関数は無限大で多項式よりも弱い|

## 使いどころ

何かの公式、定理の中に対数関数が含まれている場合はもちろん対数の知識があると良いですが、なんでもないところでこれって対数関数を使うと良いのでは？と目星を付けるタイミングについてです。

個人的には指数関数とセットにして「足し算の世界」と「掛け算の世界」との橋として使うと良いと考えていて、掛け算形式で表されているんだけど足し算として計算したいな、という場合などに有効だと考えています。
※裏には準同型写像の性質があるから橋として使えるということがあります。

例えば非負関数で $f(x)=a(x) \times b(x) \times c(x)$ と3つの積になっているものを解析したい場合、もちろんこのままでも構わないのですが対数を取ると以下のように足し算形式として見ることが出来ます。
※ $a'(x)= \log a(x) \Leftrightarrow a(x)=e^{a'(x)}$ と新しく関数を定義して見やすくしています。
```math
\begin{eqnarray}
\log f(x) &=& \log (a(x) \times b(x) \times c(x))\\
&=& \log a(x)+ \log b(x)+ \log c(x)\\
&=& a'(x)+b'(x)+c'(x)
\end{eqnarray}
```
掛け算形式と足し算形式とのどちらの方が解析しやすいかで、もし足し算の方が楽なのであれば対数をとる価値はあると思います。
例えばAIの線形回帰モデルのように和の形式を前提としたものを使う場合には前処理として対数を取っておくとうまく処理がしやすくなるだろうと思います。

### 参考資料

https://manabitimes.jp/math/2046
https://manabitimes.jp/math/1336
http://kentiku-kouzou.jp/suugaku-sisuuhousoku.html
[Python]Gradioを使ってみた

## SetUp

```
pip install gradio
```

## とりあえずGUIを表示させる

```python
import gradio as gr

# 大文字に変換する関数
def to_uppercase(input_text):
    return input_text.upper()

# Gradioインターフェイスを定義する
iface = gr.Interface(fn=to_uppercase, inputs="text", outputs="text")

# インターフェイスを起動する
iface.launch()

```

## Inputの部分を色々と変えてみる

1. "text" : テキストボックスへの入力を受け取ります。ユーザーが入力する文字列を処理します。
2. "number" : 数値入力フィールドを作成します。ユーザーが数値を入力します。
3. "slider" : スライダーを使って数値を選択します。
4. "checkbox" : チェックボックスを作成します。ユーザーがチェックボックスをオン/オフします。
5. "radio" : ラジオボタンから選択します。ユーザーが複数の選択肢から一つを選びます。
6. "dropdown" : ドロップダウンリストから選択します。ユーザーがリストから一つを選びます。
7. "date" : 日付ピッカーから日付を選択します。
8. "image" : 画像を入力として受け取ります。ユーザーが画像をアップロードします。
9. "sketchpad" : ユーザーがスケッチパッドに描くことができます。ユーザーの描画が画像として入力されます。
10. "webcam" : ユーザーがウェブカメラを通じてリアルタイムの映像を入力します。
11. "microphone" : ユーザーがマイクを通じてオーディオを録音します。


## 入力値を複数にしてみる

```python
import gradio as gr

def concatenate_strings(input1, input2):
    return input1 + " " + input2

iface = gr.Interface(
    fn=concatenate_strings, 
    inputs=[gr.inputs.Textbox(), gr.inputs.Textbox()], 
    outputs="text"
)

iface.launch()

```

## 簡単なチャットボットを作ってみる

オウムガエシのチャットぼっとを作る

```python
import gradio as gr

conversations = []

def echo_bot(user_input):
    response = user_input  # ボットはユーザーの入力をそのまま返します
    conversations.append({"user": user_input, "bot": response})

    # 会話履歴を組み立てます
    conversation_history = ""
    for conversation in conversations:
        conversation_history += f'User: {conversation["user"]}\n'
        conversation_history += f'Bot: {conversation["bot"]}\n'

    return conversation_history

iface = gr.Interface(
    fn=echo_bot,
    inputs=gr.inputs.Textbox(lines=2, placeholder='Type something here...'),
    outputs='text'
)

iface.launch()
```
変数の基礎

## 簡単な四則演算の備忘録
同じことやっても何通りかの書き方がありますよね。自分以外の人が読む可能性もあるのでできるだけわかりやすく書きたいです。そのための書き方の備忘録です。



<h2>変数aに１を足す</h2>
変数aに1を足すだけでも以下の3つの書きかたがあります。

```c
a = 1;
a = a + 1; //aに+1をする
a ++; //aに+1をする
a += 1; //aに+1をする
```

<h2>おわりに</h2>
今は趣味でプログラミングをしているのですが、やがてはシステムエンジニアにでも就職したいと思っています。
コードはチームで共有を行ったり、レビューを受けたりするので他人が読みやすいコードを意識しながら書いていきたいです。
🔰5分だけ努力するGit (4)

## 今回取り扱うGitコマンド
・git stash

初めに作業ブランチの変更を一時的に隠すことができる`git stash`コマンドを試してみます。
このコマンドは「変更内容をコミットしたくないけど別の作業をしたくなったから保存しておきたいな～」という時に使います。
まず、git-studyディレクトリを開きmainブランチから新たにブランチを切っていきます。
折角なので前回試した`git switch`コマンドを使用します。
```
$ git switch -c study/stash
```
study/stashブランチが作成できたらstudy.txtを以下のように変更していきます。
```diff_c
- Hello New Branch!
+ Test For Stash Command
```
保存したらターミナルから以下のコマンドを実行してスタッシュに変更内容を隠していきます。
```
$ git status
On branch study/stash
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   study.txt

no changes added to commit (use "git add" and/or "git commit -a")
→ git statusコマンドでstudy.txtが変更されたことを確認

$ git stash push -m "スタッシュに変更内容を隠すときのメッセージ"
Saved working directory and index state On study/stash: changed the text
→ メッセージが必要ない場合は git stash -u コマンドでも可

$ git status
On branch study/stash
nothing to commit, working tree clean
→ もう一度git statusコマンドを実行すると変更内容が隠されていることが確認できる
```
スタッシュへ変更を隠すことに成功しました。
study.txtも元の文章に戻っていますね。
次に、どのようなスタッシュがあったか、そこにどのような変更内容を隠したかを確認するコマンドを試してみます。
```
$ git stash list
stash@{0}: On study/stash: changed the text
→ スタッシュのリストを出力する

$ git stash show
 study.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
→ スタッシュの変更内容を出力する
```
流石に隠した変更内容の詳細まではわからないようですね。。。
しかし一目でスタッシュの状態を確認することができました。

では、スタッシュに隠した変更を戻してみましょう。
コマンドが2種類あるのですが、違いは以下の通りになります。
```
$ git stash pop
→ 変更内容を戻した後スタッシュのリストから削除する

$ git stash apply
→ 変更内容を戻した後スタッシュのリストから削除しない
```
今回は残す必要がないため`git stash pop`コマンドで変更内容を戻していきます。
実行すると、study.txtが今回変更した内容に戻り、`git stash list`コマンドを実行してもスタッシュリストが空であることが確認できます。

その他にも、`git stash`コマンドには以下のような機能があります。
・直近に保存した変更内容を戻さずにスタッシュリストから削除したい場合
```
$ git stash drop
```

・全てのスタッシュをリストから削除したい場合
```
$ git stash clear
```

・`git stash drop`コマンドや`git stash pop`コマンドなどでスタッシュを指定したい場合
```
$ git stash drop stash@{n}

$ git stash pop stash@{n}
```
nの部分は`git stash list`コマンドで確認可能です。

今回は以上となります。
前のプロジェクトまでTortoiseGitというGitコマンドを使わなくてもボタンぽちぽちしているだけでGitの操作ができてしまう便利なツールを使っていたのですが、コマンドの方が早くできますし何だか格好良くていいですね。笑
個人的によく使っていた「スタッシュへ変更を隠す」という機能も今回紹介したみたいに様々な機能がありましたし、これから勉強できるのが少し楽しみになりました。

ここまで読んでいただきありがとうございました。
1/sinθ-1/cosθ=4/3「2012秋田大学前期医学部【２】」をMathematicaとWolframAlphaとsympyでやってみたい。

(ⅰ),(ⅱ)でした。(1),(2)で、ないです。2023年も同じでした。
(ⅰ)=a。できませんでした。sympy.fuの勉強中です。
(ⅱ）グラフがでます。

オリジナル(youtube) MathLABO 様より

https://youtu.be/KAVfZNKuaP8

上と同じです。大学入試数学問題集成＞【2】テキスト

https://mathexamtest.web.fc2.com/2012/201210101/2012101010100mj.html#top-0107

# Mathematicaで
xxxx(ⅰ)できませんでした。xxxx
```
In:
Clear[\[Theta], f1]
Clear[\[Theta], f2]
f1[\[Theta]_] := 1/Sin[\[Theta]] - 1/Cos[ \[Theta]]
f2[\[Theta]_] := a

Solve[f1[\[Theta]] == f2[\[Theta]] && 
  0 < \[Theta] 0 && \[Theta] < 45/180*\[Pi], {\[Theta]}, Reals]

Out:
{}
```
(ⅱ）
```
In:
Clear[\[Theta], f1]
Clear[\[Theta], f2]
f1[\[Theta]_] := 1/Sin[\[Theta]] - 1/Cos[ \[Theta]];
f2[\[Theta]_] := 4/3;

p1 = Plot[f1[\[Theta]], {\[Theta], 0, 45/180*\[Pi]}];
p2 = Plot[f2[\[Theta]], {\[Theta], 0, 45/180*\[Pi]}];
Show[p1, p2]
LessEqualThan[N[25/180*\[Pi]]][
 N[Solve[f1[\[Theta]] == f2[\[Theta]] && 
    0 < \[Theta] < 45/180*\[Pi], \[Theta]]]]

Out:
{{\[Theta] -> 0.424031}} <= 0.436332
```
プロット点について、勉強中。

![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/26d37412-7ea6-34f1-b1db-43be04859ca2.png)

# WolframAlphaで

わかりにくいグラフがでます。陰関数のプロット？？？

https://www.wolframalpha.com/input?i=0%3C%CE%B8%3C45%2F180*pi%2Cy%3D1%2Fsin%CE%B8-1%2Fcos%CE%B8&lang=ja

ｘ(ⅰ)できませんでした。

https://www.wolframalpha.com/input?i=0%3C%CE%B8%3C45%2F180*pi%2Csolve%28+%281%2Fsin%CE%B8-1%2Fcos%CE%B8%29-a%2C%CE%B8+%29&lang=ja

(ⅱ）

https://www.wolframalpha.com/input?i=0%3C%CE%B8%3C45%2F180*pi%2C1%2Fsin%CE%B8-1%2Fcos%CE%B8%3D4%2F3&lang=ja

解　θ = -2 tan^(-1)(2/3 - sqrt(7)/3)

https://www.wolframalpha.com/input?i=-2+tan%5E%28-1%29%282%2F3+-+sqrt%287%29%2F3%29*180%2Fpi&lang=ja

θ=24.2951889...(ラジアンでの結果)

# sympyで( MathLABO 様の方法を参考に)
**勉強中**

# sympyで(sympy的?安易なやり方)
ｘ(ⅰ)できませんでした
```python
from sympy import *
θ,a=symbols('θ,a',Real=True)
(st,en)=(0,45.0/180.0*pi)
myEq=Eq(1/sin(θ)-1/cos(θ),a)
# ans=solveset(myEq,θ,Interval.open(st,en))
# print("#(ⅰ)",ans)
a_4w3=4/3
ans=solveset(myEq.subs({a:a_4w3}),θ,Interval.open(st,en)).args[0]
print("#(ⅱ）",float(ans/pi*180),ans,float(25/180*pi))
print("#(ⅱ）",float(ans/pi*180)<25 )
print("#(ⅱ）",float(ans/pi*180)>25 )
plot(myEq.lhs,a_4w3,(θ,st,en),ylim=(-5,5))
#(ⅱ） 24.295188945364572 0.424031039490741 0.43633231299858244
#(ⅱ） True
#(ⅱ） False
```
![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/f0b912ae-743a-eebc-3615-047d82156838.png)

# sympyの実行環境
①私の環境は,pycharmです。
②よく聞くのは、Jupyterです。
③web上で、上記のソースを「SymPy Live shell」に、コピー貼り付けでもできました。
黒背景の右上に、マウスを移動すると、コピーマークが発生します。
???　タブレット環境で、コピー貼り付けが実行できませんでした。???

https://live.sympy.org/

# 参考
Mathematica

https://reference.wolfram.com/language/ref/LessEqualThan.html

以下、いつもの?おすすめです。

https://qiita.com/mrrclb48z/items/75904cdc6e84ecef4d03#%E5%8F%82%E8%80%83wolframalpha-%E9%96%8B%E7%99%BA%E7%89%A9%E8%AA%9E
【Unity】CoroutineのWaitForEndOfFrameを用いるwhileループ内ではInputクラスが使えない

ハマったので備忘録です。

# 実行環境
Unity 2021.3.8f1

# 誤ったコード
```cs
using System.Collections;
using UnityEngine;

public class Test : MonoBehaviour
{
    IEnumerator Start()
    {
        while (true)
        {
            if (Input.GetMouseButtonDown(0)) break;
            Debug.Log("Looping");              
            yield return new WaitForEndOfFrame();
        }
    }
}

```
Coroutine内のwhileループにWaitForEndOfFrame()を用いた場合、
クリックしてもCoroutineを抜けられません。

# 修正したコード
```cs
using System.Collections;
using UnityEngine;

public class Test : MonoBehaviour
{
    IEnumerator Start()
    {
        while (true)
        {
            if (Input.GetMouseButtonDown(0)) break;
            Debug.Log("Looping");              
            yield return null;
        }
    }
}

```
nullを用いた場合、クリックするとCoroutineを抜けられます。

# 原因
## Inputクラスの仕様
[Input-GetKeyDown - Unity スクリプトリファレンス](https://docs.unity3d.com/ja/2019.4/ScriptReference/Input.GetKeyDown.html)にて、Inputの説明を確認すると、
「You need to call this function from the Update function, since the state gets reset each frame. 」と書いてあります。
キー/マウス入力したフラグはフレームごとにリセットされるため、Update関数内で用いてください。と書いてありました。
Update関数ではない、コルーチン内では扱いがどうなるのでしょうか？

## Unityのライフサイクル

[イベント関数の実行順序 - Unity マニュアル](https://docs.unity3d.com/ja/2019.1/Manual/ExecutionOrder.html)を参照すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/4383d164-32f6-772b-dc46-211cb2aad523.png)
一番下にyield WaitForEndOfFramがあり、Updateのすぐ下にyield nullがあります。

「if a coroutine has yield previously but is now due to resume then execution takes place during part of the update.」
と書いてあるように、基本的には、yield nullはUpdate関数の一部として実行されるようです。

Inputクラスで入力したフラグがリセットされるのは、恐らくGameLogicの最後なのだと思われます。
そのため、whileループにWaitForEndOfFrameを用いてしまうと入力が受け取れません。

# 備考
```cs
using System.Collections;
using UnityEngine;

public class Test : MonoBehaviour
{
    IEnumerator Start()
    {
        while (true)
        {
            if (Input.anyKey) break;
            Debug.Log("Looping");              
            yield return null;
        }
    }
}

```
Input.anyKey、Input.GetMouseButton()、Input.GetKey()など
Downを伴わない入力を使うとwhileループを抜けられます。
こっちは入力フラグのリセットを行わず、キーを上げる動作を検出するまで
ずっとtrueになっているからなのだと思われます。（使う機会なさそう）

# 参考記事
https://docs.unity3d.com/ja/2019.4/ScriptReference/Input.GetKeyDown.html

https://docs.unity3d.com/ja/2019.1/Manual/ExecutionOrder.html

https://qiita.com/yuki2006/items/b7b5e247e64b6f1e56fe

https://robamemo.hatenablog.com/entry/2017/09/13/111843
【CodePen・CodeSandbox・Asciinema】ブラウザでプログラミング開発・コード共有するツール3選

## この記事の内容

■ 紹介するブラウザツール
**1. CodePen**（HTML, CSS, JavaScritのコーディングエディタ）
**2. CodeSandbox**（プログラミング環境の構築・実行・公開）
**3. Asciinema**（シェルコマンドの録画・公開）

また、これらのツールは、開発したコードやシェルコマンドを、自身のサイトの**HTMLやMarkdowmに埋め込んで綺麗に表示**させることができます。本記事では、その方法について紹介します。


## 1. CodePen

[CodePen](https://codepen.io/) は、オンラインのコーディングエディタで、HTML、CSS、JavaScriptのコードを作成・共有できるプラットフォームです。

**サイトに埋め込む手順**
- CodePenにアクセス"Start Codeing"からコードを書きます
- コードを書いたら右下にある"Embed"ボタンを押します
- 貼り付け用コード（HTMLタグやiframeに対応）が表示されるので、コピペして自身のサイトのHTMLファイルやMarkDownに貼り付ける

![codepen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3469687/c32851fd-3cbb-db1c-19ca-acbed755ef91.jpeg)


**例**
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="YzzNGeR" data-user="JavaScriptJunkie" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/JavaScriptJunkie/pen/YzzNGeR">
  Credit Card Form - VueJs</a> by Muhammed Erdem (<a href="https://codepen.io/JavaScriptJunkie">@JavaScriptJunkie</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


## 2. CodeSandbox

[CodeSandbox](https://codesandbox.io/) は、オンラインの統合開発環境で、ブラウザ上にプログラミンング環境を構築、コーディング、実行ができます。
他のクリエイターが作成したSandBoxの検索は[Dsicover](https://codesandbox.io/discover)から。

**サイトに埋め込む手順**

・共有したいCodeSandboxを開く
・"Shere" ▶︎ "Embed" ▶︎ "Enbed url" の文字列をコピーしてMarkdownに貼り付ける 
![CodeSandbox1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3469687/2eb3ac16-d817-72d4-6783-cd5a44fca76e.jpeg)
![CodeSandbox2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3469687/287013a0-e56a-0908-6629-5c1291d429f9.jpeg)

**例**

https://codesandbox.io/embed/07-final-torus-knot-r3bo1?fontsize=14&hidenavigation=1&theme=dark


## 3. Asciinema

[Asciinema](https://asciinema.org/) は、ターミナルセッションの録画・共有を簡単に行えるオンラインサービスです。録画するにはインストールが必要です。Python環境があればpipで導入可能（`pip install asciinema`）。

https://asciinema.org/docs/installation

**録画・サイトに埋め込む手順**

・録画したいターミナルで以下のコマンドを実行
`$ asciinema rec`

・録画を終了する場合は`exit`を実行もしくは"ctrl-D"をキー入力
・Asciinemaのサイトで閲覧可能なURLが表示されるのでアクセス
・"Share"ボタンから、適切な埋め込みコード(HTML, Markdown)をコピーしてサイトに貼り付ける

![asciinema.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3469687/576dc46d-e173-2bee-120e-7812d769969d.jpeg)

**例**

[![asciicast](https://asciinema.org/a/553356.svg)](https://asciinema.org/a/553356)


## まとめ

ブラウザでプログラミング開発・公開するサービスを3つ紹介しました。

## おまけ

・Qiita公式から["Markdown記法 チートシート"](https://qiita.com/Qiita/items/c686397e4a0f4f11683d) の記事が公開されており、Markdown作成時に便利です。

コードブロックでは、開始の```の右にpython:qiita.pyと書くと以下のようにシンプルなコード表示が可能です、

```python:qiita.py
print("Hello Python!")
```

https://qiita.com/Qiita/items/c686397e4a0f4f11683d#code---%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%8C%BF%E5%85%A5


・同じくQiita公式の["Qiitaで埋め込み可能なコンテンツ一覧"](https://qiita.com/Qiita/items/c686397e4a0f4f11683d) では、Qitaに各種サービスのコンテンツを埋め込む方法が紹介されています。

https://qiita.com/Qiita/items/612e2e149b9f9451c144
Rails カスタムバリデータについて

# はじめに
- バリデーションの理解を深める目的で、注文フォームについて学習中
- 出てきた記述がわからず、「カスタムバリデータ」について調べたため、理解を深めるための記録
- 学習の備忘録です

# 学習している教材
[バリデーションを追加しよう](https://www.udemy.com/course/rails-forms/learn/lecture/33366692#overview)
Udemyの教材です。とてもわかりやすいです。

### 参考
https://railsguides.jp/active_record_validations.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B


# 前提条件
- Orderモデルがある

# カスタムバリデータ
カスタムバリデータとは、好みのバリデータやバリデーションメソッドを作成して使えるようにすること。
ここでは、複数のクラスで使用できるメールアドレスのバリデータを作成。
まず、app/validatorsフォルダを作成し、さらに以下のファイルを作成する。
```ruby:email_format_validator.rb
class EmailFormatValidator < ActiveModel::EachValidator

  def validate_each(record, attribute, value)

    return if /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.match?(value)

    record.errors.add(attribute, "メールアドレスの形式が正しくありません")
  end

end
```

validate_eachメソッドを使い、(record, attribute, value)の3つの引数を設定。
それぞれ、
>record・・・ここではOrderモデルのインスタンス
attribute・・・validate設定時の属性名
value・・・検証するべき値

を表している。

正規表現は、まだまだ理解が浅い。
1つずつ調べてみると、意味は以下の通り。
>\A:　・・・文字列の先頭
[\w+\-.]+:　・・・ @より前の部分を表し、アルファベット、数字、アンダースコア、プラス、ハイフン、ピリオドを含む文字の1つ以上の繰り返しとなる
@: ・・・@を表す
[a-z\d\-.]+: ・・・@より後の部分を表し、アルファベット、数字、ハイフン、ピリオドを含む文字の1つ以上の繰り返しとなる
\.[a-z]+: ・・・メールアドレスのドメインの末尾部分を表し、ピリオドとアルファベットの1つ以上の繰り返しとなる
\z: 文字列の末尾
/i: 正規表現のフラグ

この正規表現にマッチした値（ここでは「test@example.com」のようなメールアドレス）なら、バリデーションの結果をtrueとして返す。
```ruby
return if /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.match?(value)
```
また、一致しない場合、バリデーションエラーメッセージが追加されるようにする。
```ruby
record.errors.add(attribute, "メールアドレスの形式が正しくありません")
```

あとは、モデルで呼び出す。
```ruby:order.rb
  validates :email, presence: true, email_format: true
```

カスタムバリデーターのクラス名を「EmailFormatValidator」としたため、「email_format」で呼び出せる！
これで、汎用性のあるメールアドレスのバリデータが完成！

# まとめ
- ビルトインのバリデーションヘルパー以外にも、好みのバリデータの作成が可能
- バリデーターを使いこなすには、正規表現の理解を深める必要があると言える

⚠️学習4ヶ月目の初学者による投稿です。
⚠️間違いがあるかもしれません。ご容赦ください。
⚠️ご指導、ご教授いただけると幸いです。
[AWS Q&A 365][EI]AWSのよくある問題の毎日5選 #92

# Q1: Amazon Elastic Inferenceとは何ですか？
A1: Amazon Elastic Inferenceは、AWSが提供するサービスで、顧客がAmazon EC2、Amazon SageMakerインスタンス、またはAmazon Elastic Container Service（ECS）タスクに低コストのGPUパワー加速を追加できるようにします。これは、スタンドアロンのGPUベースのインスタンスと比較して、ディープラーニング推論の実行コストを最大75％削減するのに役立ちます。

# Q2: Amazonが顧客にAmazon Elastic Inference（EI）からAWS Inferentiaなどの新しいハードウェア加速オプションへのワークロードの移行を推奨する理由は何ですか？
A2: Amazonは、AWS Inferentiaなどの新しいハードウェア加速オプションが推論ワークロードに対してはるかに良いパフォーマンスをより良い価格で提供するため、顧客にAmazon Elastic Inferenceからのワークロードの移行を推奨しています。AWS Inferentiaは、クラウドでの高パフォーマンス推論を提供し、推論の全体的なコストを削減するように設計されています。

# Q3: Amazon Elastic Inference（EI）への新規顧客のオンボーディング停止により、どのAWSサービスが影響を受けますか？
A3: Amazon Elastic Inferenceへの新規顧客のオンボーディングを停止すると、Amazon EC2、Amazon SageMakerインスタンス、そしてAmazon Elastic Container Service（ECS）タスクが影響を受けます。これは、Amazon Elastic Inferenceアクセラレーターを使用するエンドポイントとノートブックカーネルの両方に適用されます。

# Q4: 2023年4月15日以降に新しいAmazon Elastic Inference（EI）アクセラレーターを作成できますか？
A4: 新規の顧客であり、過去30日間にAmazon Elastic Inferenceを使用したことがない場合、2023年4月15日以降にAWSアカウントで新しいAmazon Elastic Inferenceインスタンスを作成することはできません。しかし、過去30日間に少なくとも一度Amazon Elastic Inferenceアクセラレーターを使用したことがある場合は、新しいアクセラレーターをインスタンスに追加することができます。

# Q5: 現在のAmazon SageMaker推論エンドポイントの代替インスタンスオプションを評価するにはどうすればいいですか？
A5: Amazon Elastic Inferenceから適切なSageMakerがサポートするMLインスタンスに既存のワークロードを移行するための費用効果的なデプロイメントを特定するのに、Amazon SageMaker推論推奨者を使用できます。これにより、現在のエンドポイントに最適な代替インスタンスオプションを選択するのに役立ちます。
[AWS Q&A 365][EI]Daily Five Common Questions #92

# Q1: What is Amazon Elastic Inference? 
A1: Amazon Elastic Inference is a service provided by AWS that allows customers to attach low-cost GPU-powered acceleration to Amazon EC2, Amazon SageMaker instances, or Amazon Elastic Container Service (ECS) tasks. It helps reduce the cost of running deep learning inference by up to 75% compared to standalone GPU-based instances. 

# Q2: Why is Amazon encouraging customers to move workloads from Amazon Elastic Inference (EI) to newer hardware acceleration options such as AWS Inferentia? 
A2: Amazon is encouraging customers to move workloads from Amazon Elastic Inference to newer hardware acceleration options like AWS Inferentia because these options provide better performance at a much better price for inference workloads. AWS Inferentia is designed to provide high-performance inference in the cloud and drive down the total cost of inference. 

# Q3: Which AWS services are impacted by the move to stop onboarding new customers to Amazon Elastic Inference (EI)? 
A3: The move to stop onboarding new customers to Amazon Elastic Inference impacts Amazon EC2, Amazon SageMaker instances, and Amazon Elastic Container Service (ECS) tasks. This applies to both endpoints and notebook kernels using Amazon Elastic Inference accelerators. 

# Q4: Will I be able to create a new Amazon Elastic Inference (EI) accelerator after April 15, 2023? 
A4: If you are a new customer and have not used Amazon Elastic Inference in the past 30 days, you will not be able to create a new Amazon Elastic Inference instance in your AWS account after April 15, 2023. However, if you have used an Amazon Elastic Inference accelerator at least once in the past 30 days, you can attach a new accelerator to your instance. 

# Q5: How do I evaluate alternative instance options for my current Amazon SageMaker Inference Endpoints? 
A5: You can use Amazon SageMaker Inference Recommender to help identify cost-effective deployments for migrating existing workloads from Amazon Elastic Inference to an appropriate ML instance supported by SageMaker. This will help you choose the best alternative instance options for your current endpoints.
UWPのマルチインスタンス対応には TemplateStudio for UWP を利用しよう

## テンプレートスタジオをインストール

VS2022対応のマルチインスタンス対応 TemplateStudio を利用するには以下の拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=TemplateStudio.TemplateStudioForUWP


公式ページで紹介されている `Multi-Instance App Project Templates.VSIX` は VS2022 では利用出来ないようです（2023/06/05 時点）

https://learn.microsoft.com/ja-jp/windows/uwp/launch-resume/multi-instance-uwp

代わりにTemplate Studio for UWPを利用しましょう。

## プロジェクトの作成方法

インストールしてプロジェクト作成を選択した後、プロジェクトテンプレートの選択で「Template Studio for UWP」を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62922/5936c1b1-78fd-4b79-0f63-14a7da13ca25.png)

プロジェクト名を入力して「作成」を押すと以下の画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62922/bb6b51de-1256-dec9-841d-78da7d1155be.png)

マルチインスタンスを有効にしたい場合は、左のタブから「機能」を選択して、「アプリケーションの起動」グループから「Multi-Instance」または「Advanced Multi-Instance」を選択します。

Advanced Multi-Instanceを追加選択した場合は、アプリインスタンスの生成条件やリダイレクト処理が柔軟に書けるようになります。
WSL（Windows Subsystem for Linux）上のUbuntuでSeleniumとChromeDriverを使用してWebスクレイピング

WSL（Windows Subsystem for Linux）上のUbuntuでSeleniumとChromeDriverをセットアップして、PythonからWebスクレイピングする方法を解説します。

## 環境
- OS: Ubuntu 20.04.6 LTS (WSL上)
- Python: 3.8.10
- Selenium: 4.10.0
- Architecture: x86_64
- CPU: AMD Ryzen 5 1600X Six-Core Processor

## 1. 必要なパッケージのインストール
まず、Ubuntuに必要なパッケージをインストールします。以下のコマンドを実行します。

```bash
sudo apt-get update
sudo apt-get install -y libatk1.0-0 fonts-ipafont
sudo fc-cache -fv
```

## 2. Seleniumとwebdriver_managerのインストール
PythonでSeleniumを使用するために、Seleniumとwebdriver_managerをインストールします。

```bash
pip install -U selenium webdriver_manager
```

## 3. Google ChromeとChromeDriverのインストール
Google ChromeとChromeDriverをインストールします。

```bash
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb

wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.zip
unzip chromedriver_linux64.zip
sudo mv chromedriver /usr/bin/chromedriver
sudo chown root:root /usr/bin/chromedriver
sudo chmod +x /usr/bin/chromedriver
```

## 4. Pythonコードの作成
最後に、以下のPythonコードを作成します。

```python
# coding: UTF-8
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options

# Setup Chrome options
options = Options()
options.add_argument("--headless") # Ensure GUI is off. Remove this line if you want to see the browser navigating.

# Set path to chromedriver as a service
webdriver_service = Service(ChromeDriverManager().install())

# Set the driver
driver = webdriver.Chrome(service=webdriver_service, options=options)

# Get website data
driver.get("https://www.google.com")

# Take a screenshot
driver.save_screenshot("screenshot.png")

# Quit the driver
driver.quit()
```

![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/937274/1e7ab8ed-b02d-1bf2-6ec2-2c79e0c0344c.png)


以上の手順により、WSL上のUbuntuでSeleniumとChromeDriverを使用して、PythonからWebスクレイピングが可能になります。特に、文字化け問題やドライバのセットアップ問題を解決したため、日本語のWebページも問題なく取得できます。

この記事が、PythonとSeleniumを使用してWSL上のUbuntuでWebスクレイピングを行う方々の参考になれば幸いです。

上記の記事はあくまで一例であり、実際の環境や要件によって変更が必要かもしれません。適宜、自身の状況に合わせて内容を調整してください。