OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】カタカナ単語リストを使ってしりとりプログラムを作る

## 指定した文字から始まり、「ン」で終わる単語で終了するしりとりの結果を表示するプログラムを実装していきます

今回、ルールは以下の通りとします
1. 同じ単語を使ってはいけない
2. 「ー(長音)」で終わる単語は長音を無視する
3. 清音・濁音・半濁音は別の文字として扱う
4. 小文字で終わる単語は大文字に変換して扱う(ャ→ヤ等)
5. 指定した開始文字でしりとりが終了しない場合はその旨を表示する

※今回のしりとりでは、tango.txt というテキストファイルを使用しています
[tango.txtのダウンロードはこちら](https://drive.google.com/u/4/uc?id=1K3B_h_aHUYmy6KA27GxkERM0WU1IqA8b&export=download)


### 実装の概要
**準備** tango.txtの中身をリストに変換しておく
1. まず、最初の文字をカタカナで入力します
2. tango.txtの中から、最初の文字が一致する単語を探します
3. tango.txtの中の単語でしりとりをします
4. 「ン」で終わる単語を見つけたらしりとりを終了します
5. 入力したカタカナから始まり、「ン」で終わるしりとりの経過を出力します

### それでは実装してみましょう

```python
import copy
import re #正規表現のコンパイル

step = [] #しりとりの経過を入れるリスト

f = open('tango.txt', 'r') #tango.txtの読み込み
data = f.readlines() #リスト"data"にtango.txtの中身を格納
l1 = len(data) #"data"に含まれる要素の数をl1に代入

def trans(strj): #小文字を大文字に変換する関数
    moji = str.maketrans("ァィゥェォャッュョ", "アイウエオヤユツヨ")
    return strj.translate(moji)

def shiritori(start, i, j):
  while i<l1:
    #↓ もしdata内の単語の頭文字がstartと一致し、リストstepに含まれないとき
    if start == data[i][0] and data[i] not in step: 
       l2 = len(data[i]) - 1 #l2に単語の文字数を代入(-1は改行文字分)
       step.append(data[i]) #単語を"step"に追加
       j = i #(最後に)追加した要素のindex
       #print(step) ← しりとりの経過を見たいときに表示
       end = data[i][l2-1] #endに単語の最後の文字を代入
       if end == 'ン': #'ン'で終わるときは1を返す
         return 1
       if end == 'ー': #'ー'で終わるときは1つ前の文字をendに代入
         end = data[i][l2-2]
       if end in 'ァィゥェォャュッョ': #小文字で終わるときは変換の関数を呼び出して代入
         end = trans(end)
       start = end #最後の文字を最初の文字とする
       i = 0 #リストを一から探索するので再初期化
    else:
      i = i + 1 #頭文字が入力と一致しないときは次の要素へ移るのでi++

  if len(step) == 0: #該当するものがなく、リストstepが空の時
    return 0 #終了して0を返す
  else:
    pre = step[len(step) - 1] #preはリストstepに追加した最後の要素

  del step[-1:] #最後の要素をリストから取り出す
  #print(step) ← しりとりの経過を見たいときに表示

  if len(step) != 0: #リストが空でないとき
    #↓ リストdataに含まれるリストstepの最後の要素と同じもののindex(何番目の要素か)をsに代入
    s = data.index(step[len(step)-1])
    #↓ 最後の文字, 最後に入れて棄却された要素の次の要素のindex, 現時点のリストstepの最後の要素のindex
    fl = shiritori(pre[0], j+1, s)
  else:
    #現時点でstepに要素がないので、sは０に設定している
    fl = shiritori(pre[0], j+1, 0)
  return fl #戻る

print("最初の文字(カタカナ)を入力してください")
s = str(input()) #頭文字にしたいカタカナを標準入力
katakana = re.compile(r'[\u30A1-\u30F4]+') #'[\u30A1-\u30F4]+'はカタカナの範囲

if not re.fullmatch(katakana, s) or len(s)>1: #入力がカタカナでない,または二文字以上のとき
  print("エラー：カタカナ一文字で入力してください")

else: 
  flag = shiritori(s, 0, 0) #'ン'で終わるときは1,それ以外は0が代入される
  
  if flag == 0:
    print("「",s,"」から始まるしりとりは「 ン 」で終わりません")
  else:
    Step = ''.join(step) #リスト"step"を文字列に変換
    Step = Step.split() #.split()で改行文字を削除し,リスト化
    print(Step) #結果を出力
```

最初に必要なモジュールのインポート、次にtango.txtの中身をリストに変換をしています。リストstepは、しりとりの経過を入れるリストなので、挙動を確認したいときは表示させてみてください。

### 実行結果

```
最初の文字(カタカナ)を入力してください
ス
['スポーツカー', 'カバー', 'バックミラー', 'ラッシュアワー', 'ワイシャツ', 'ツール', 'ルール', 'ルーズ', 'ズボン']
```

今回は「ス」を最初の文字に設定したのでスポーツカーからしりとりを始め、ズボンで終わりました。
関数shiritoriの挙動が少し分かりづらいですが、どんな動きをしているかコメントを見ながら追ってもらえるといいかなと思います。
アップサート処理のテンプレート（Laravel）

## 初めに
Laravelのアップサートを実装したので、コピペ用として残します。
（モデル使用）

## 環境
| 開発環境   |バージョン    |
|-----------|------------|
| __Laravel__ | 10.1.5 |
| __PHP__ | 8.2.3 |

## 実装
```php:UpsertController.php
use Illuminate\Support\Facades\Log;
use App\Models\Setting;
use Exception;

// ... 略

/**
* アップサートする
* 
* @param  設定情報
* @return エラー有無情報
*/
public function regist($param)
{
    Log::debug(__FUNCTION__);

    // 初期設定
    $is_error    = false;

    // トランザクション開始
    DB::beginTransaction();

    try {

        // 検索情報
        $searchStr = [
            'column_a'  => $params['column_a'] // 検索したいカラム
        ];

        // アップサート情報
        $upsertStr = [
            'column_1' => $params['column_1'],
            'column_2' => $params['column_2'],
            // ... 略
        ];

        // アップサートする
        $result = Setting::updateOrCreate($search_data, $upsert_data);
        if ($result == false) {
            throw new Exception('アップサート中にエラーが発生しました。');
        }

    } catch (Exception $e) {
        Log::error(get_class($this).':'.__FUNCTION__);
        Log::error($e->getMessage());
        $is_error = true;
    
    } finally {
        // エラーが存在する場合
        if ($is_error == false) {
            DB::commit();
        // エラーが存在しない場合
        } else {
            DB::rollback();
        }
    }

    // エラー有無情報を返す
    return $is_error;
}
```

## 最後に
最後まで閲覧いただきありがとうございました。
ご意見、ご指摘ありましたら、コメントお願いいたします。
【VS2022】 Emacs Emulationでtabスニペット挿入の一部を使えるようにした

# 背景
Visual StudioでEmacsキーバインドを使うなら[Emacs Emulations](https://marketplace.visualstudio.com/items?itemName=JustinClareburtMSFT.EmacsEmulation2)一択ですが、この拡張機能は`ctor`, `prop`などのtabキー2回押しのスニペットの挿入に対応していません。

# 行った変更

設定ではどうすることもできなかったので、ソース側を改変しました。
すべてのソースを追えているわけではないですが、おそらくインテリセンスの判定をしている関数にTABINSERTコマンドを追加しています。

https://github.com/nobushi95/EmacsKeys/commit/686a5d1ebbdf8c5d3478d819cbe73d1e97698ea4

# 効果
一部のスニペット(prop, ctorなど)がWindows10のマシンでは使えるようになりました。
が、手元のWindows11のマシンではうまく動作しませんでした…。
設定のせいなのか環境のせいなのか微妙ですが、一部使えるということでこれで、ひとまず様子を見て使ってみます。
【Makefile】インターネット接続時のProxy対策

# はじめに
## この記事の目的
ソースコードのビルドや引数を多用したスクリプトのランナーとして、Makefileは根強い人気を誇っています。
本記事では、インターネット接続を伴う処理を記載したMakefileを、Proxy環境下でも使えるようにする方法を検討します。

## 想定する環境
以下の環境を想定しています。
OS: Linux
Shell: bash
Macの場合は、bashではなくzshを設定すれば動くのではないかと思います。

## 対象とするプロキシ対策
プロキシ対策は、使用するツールの実装により様々ですが、以下が一般的です。
- `http_proxy`, `https_proxy`, `ftp_proxy`, `no_proxy`などの環境変数に`http://<USER ID>:<USER PASS>@<SERVER>:<PORT>`の書式でプロキシサーバの設定を記載する。
- 所定のディレクトリにプロキシサーバの設定を記載したファイルを配置する

本記事では、前者の環境変数を設定するタイプのスクリプトをMakefileの中で実行する場合の対策を示します。

# Makefileの使用方法と設定
## Makefileの使用方法
まず、後述のMakefileを任意のディレクトリに配置し、そのディレクトリへ移動します。
そして、実行したいターゲットが`test`の場合、ユーザは次のコマンドを実行します。

```bash
# 非プロキシ環境下
make test
# プロキシ環境下
make test USE_PROXY=true
  # Configure proxy setting:
  #  USER ID: > aaa
  #  USER PASS: >
```

上記のように、非プロキシ環境下では、単に`test`を指定します。そして、プロキシ環境下では、引数`USE_PROXY=true`を付けます。
そして、プロキシサーバへ接続するためのユーザ名とパスワードはmake実行時に、入力する方式とします。
なお、本記事は、プロキシサーバのホスト名とポート名は事前に分かっているものとして、Makefileの中に記載してしまいます。

なお、プロキシ環境下であっても、すでに環境変数が設定されている場合は、`USE_PROXY=true`を省略できるようにします。

## Makefileの設定
以下では、プロキシサーバのホスト名が`proxy.server.com`、ポート番号が`8080`とします。
なお、プロキシサーバのホスト名が不明で、代わりにIPが分かっている場合は、ホスト名の代わりにIPを記載します。

```Makefile
PROXY_SERVER:=proxy.server.com
PROXY_PORT:=8080
SHELL:=/bin/bash # readコマンドを使用するため、シェルをデフォルトのshからbashに変更します

# USE_PROXYの設定が無い場合は、環境変数が設定されているかを確認しますhttp_proxy
USE_PROXY?=$(shell if [ ! -z $$http_proxy ]; then echo "true"; else echo "false"; fi)

# USE_PROXYがtrueで、かつ、http_proxyが設定されていない場合は、ユーザにIDとパスワードを入力してもらい、http_prox等を設定します。
ifeq ($(USE_PROXY), true)
	ifeq ($(http_proxy),)
		USER_ID:=$(shell echo "Configure proxy setting:" 1>&2; read -p "  LDAP ID: > " tmp; echo $$tmp)
		USER_PASS:=$(shell read -s -p "  LDAP PASS: > " tmp; echo "" 1>&2; echo $$tmp)
		export http_proxy:=http://$(USER_ID):$(USER_PASS)@$(PROXY_SERVER):$(PROXY_PORT)
		export https_proxy:=$(http_proxy)
	endif
endif

# プロキシ設定を活用して、example.comのサイトをダウンロードできるか確認します。
# 接続できない場合は、5秒でタイムアウトします。
test: ## Test connection with internet (connect to http://example.com)
	@if timeout 5 curl -L http://example.com 1>/dev/null 2>&1; then\
		echo "Successfully connected with example.com";\
	else\
		echo "Failed to connect with example.com";\
	fi
```
なお、環境変数はMakefileの中だけで設定され、makeのスクリプトを抜けると上記環境変数は消えてしまいます。

## Makefileで使っているテクニック
### exportによる環境変数設定
`Makefile`で設定した変数は通常、環境変数とは区別されますが、exportを付けると、makeのサブプロセスで実行されるシェル内の環境変数に展開されます。
上記の例では、http_proxyとhttps_proxyをMakefileの記法である`:=`によって設定し、さらに、`export`することで、それ以降のコマンドを実行する際の環境変数に登録しています。

### `?=`代入
`?=`は、変数が定義されていない場合のみ、変数を宣言して値を代入する代入演算子です。
上記の例では、`USE_PROXY`の設定を`?=`による代入とすることで、ユーザが`USE_PROXY`を設定しなかった場合のみ、値を設定しています。
さらに、`?=`代入演算子の右辺で、`$(shell ...)`を使うことで、`http_proxy`環境変数が設定されているか確認し、すでに設定済みの場合は`true`とし、`http_proxy`が存在しないor空の場合は`false`としています。
【WPF】WindowクラスのVisibilityにBooleanをコンバートしてバインドする

# BooleanToVisibilityConverter

bool型をVisibilityに変換するコンバーターとして[BooleanToVisibilityConverter](https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.controls.booleantovisibilityconverter?view=windowsdesktop-7.0)というものがあります。

以下のようにWindow.Resouceに宣言することで、ViewModelなどに定義したbool型の`IsVisiblie`プロパティをVisibilityに変換し、バインドすることができます。
```xml:MainWindow.xaml
<Window x:Class="SampleWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="300">
    <Window.Resource>
        <BooleanToVisibilityConverter x:Key="Bool2Visibility"/>
    </Window.Resource>
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock FontSize="20"
                   Text="Text"
                   Visibility="{Binding IsVisible, Converter={StaticResource Bool2Visibility}, Mode=OneWay}"/>
    </Grid>
</Window>
```

# WindowクラスのVisibilityにバインドする

上記で示した方法だと、Windowの子要素にあたるコントロールには宣言した`Bool2Visibility`を使用することができますが、Windowクラス自体のプロパティには使用することができません。
Windowのプロパティでも使用したい場合はWindowの親にあたる`App.xaml`に宣言を記載する必要があります。（Windowに限らず、親で宣言されたコントロールが使用できると思われます。）

```xml:App.xaml
<Application x:Class="SampleWpf.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:SampleWpf"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <BooleanToVisibilityConverter x:Key="Bool2Visibility"/>
    </Application.Resources>
</Application>
```

下記のようにWindowクラスにbool型の`IsWindowVisible`プロパティをコンバートしてバインドできます。
※ WindowのVisibilityを動的に変更しようとすると、`Mode=TwoWay`でバインドしないとうまく動作しませんでした。（バインディングが外れている？）

```xml:MainWindow.xaml
<Window x:Class="SampleWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Visibility="{Binding IsWindowVisible, Converter={StaticResource Bool2Visibility}, Mode=TwoWay}"
        Title="MainWindow" Height="200" Width="300">
        ...
</Window>
```
RubyでAtCoder ABC280(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC280のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Pawn on a Grid
https://atcoder.jp/contests/abc280/tasks/abc280_a
```ruby:a-280.rb
h, w = gets.split.map(&:to_i)
s = Array.new(h){ gets.chomp }.join
puts s.count("#")
```
## 解説
countメソッドを使って`#`の数を数え上げています。

# B - Inverse Prefix Sum
https://atcoder.jp/contests/abc280/tasks/abc280_b
```ruby:b-280.rb
n = gets.to_i
s = gets.split.map(&:to_i)
a = [s[0]]
(1..n - 1).each do |i|
  a << s[i] - s[i - 1]
end
puts a.join(" ")
```
<追記>
コメントでいただいた別解になります。
```ruby:別解
n = gets.to_i
ss = gets.split.map(&:to_i)

result = ss.each_cons(2).map { _2 - _1 }
puts [ss[0]].concat(result).join(" ")
```
## 解説
例えば、S3=A1+A2+A3=S2+A3であることから、A3=S3-S2となります。この関係式を順に適用していき数列Aを求めていきます。

# C - Extra Character
https://atcoder.jp/contests/abc280/tasks/abc280_c
```ruby:c-280.rb
s = gets.chomp
t = gets.chomp
n = s.size
for i in 0..n - 1
  if s[i] != t[i]
    puts i + 1
    exit
  end
end
puts n + 1
```
## 解説
順に調べていき一致しないところがあればそのindexを出力して終了、最後まで行ければ文字は末尾に挿入されたということなのでs.size+1を出力します。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
ストワで始めるLua第四回のコード

動画はこちら

https://www.nicovideo.jp/watch/sm42080651

https://www.nicovideo.jp/watch/sm42080687


```lua:LPF
x=0
k=0.1
function lpf(prex,low)
	return (1-k)*prex+k*low
end

function onTick()
	local z=math.random()-0.5

	x=lpf(x,z)
	
	output.setNumber(1,x)
	output.setNumber(2,z)
end

```

```lua:モニターのボタン
selectFlg=false
isTouching=false

flagA=false

function isPointInRectangle(x, y, rectX, rectY, rectW, rectH)
    --x,y:input  rectX,Y:LeftUp Rect   rectW,H:size
 	return x > rectX and y > rectY and x < rectX+rectW and y < rectY+rectH
end

function onTick()
	local w,h,x,y,inputX,inputY
	--input
	
	isTouch=input.getBool(1)
	w=input.getNumber(1)
	h=input.getNumber(2)
	inputX=input.getNumber(3)
	inputY=input.getNumber(4)
	
	--Touch display
	if isTouch==true and isTouching==false then
		isTouching=true
		if isPointInRectangle(inputX,inputY,0,0,4,5) then
			flagA=not(flagA)
		end
	end

    --release button
	if isTouch==false then
		isTouching=false
	end
end

function onDraw()
	--display
	local w,h
	w=screen.getWidth()
	h=screen.getHeight()
	
	if flagA then
		screen.setColor(0,255,0)
	else
		screen.setColor(255,0,0)
	end
	screen.drawRectF(0,0,4,5)
	
	screen.setColor(255,255,255)
	
	screen.drawText(0,0,"A")
end
```
追記
動画内で言及するのを忘れていた部分。
引数はローカル変数になるといっていますが、関数の引数にテーブルを使用した場合は、
関数内で値を変更するとテーブル内の値も変わってしまうため注意が必要です。
「定本Cプログラマのためのアルゴリズムとデータ構造」からなぜプログラミングが上達しないかを初心者ながらに考えてみた

# はじめに
定本Cプログラマのためのアルゴリズムとデータ構造から、なぜプログラミングが上達しないのか
その理由を考えてみました。

私もプログラミングの上達が遅いほうなので本で学んだことを忘れないためにも、
記録をすることにしました。

※自分なりの考えなので必ずしもこの記事に書いたことが正解ではありません。

# プログラミングを上達させるために考えるべきこと
プログラミングを上達させるために、プログラミングの広義と狭義を考える必要があります。

定本Cプログラマのためのアルゴリズムとデータ構造(次からは定本と略します)では
プログラミングの広義を次の三つとしています。

>①問題を分析して、何をするプログラムを書くのかを決める(プログラムの仕様決定)
>②どんなアルゴリズム、データ構造を使用すればよいかを選択する
>③実際にプログラムを書く

そして狭義のプログラミングとはこの①②③の個々のことを指しています。

私は自分を含め上達の遅い初心者は③に関する知識を多く知ろうとしていて、
①と②を疎かにしている感じがあると思いました。

定本にはこのように書かれています。
>入門書などによって得られるのは、主として③に関する知識です。これは、狭義のプログラミングとでもいうべきもので、③のみを知っていても、おもうようにプログラムを書くことができないのは当然のことでしょう。

私もこれに思い当たる節があります。だから上達が遅かったのかもしれません。
# どのように学ぶべきか
ではどのように学んだらよいのでしょうか？

「問題を分析して、何をするプログラムを書くのかを決める」というのは自分で
導き出す必要があると思いました。定本でも自分で経験を積むしかないと書いてあります。
なので積極的に多くの課題解決に参加したり、自分でどう問題を実現できるかを考えるしかないと
思っています。私はこういったことを積極的には行ったりしてきませんでした。
そのため問題解決の経験が少なく上達も遅くなったのだと思います。
今後からはより積極的にしなければならないと思えるようになりました。

次にデータ構造とアルゴリズムについてですがこれは情報が多く、ネットで簡単に調べて学ぶことができると思います。
なので一般的に使われているデータ構造とアルゴリズムは意欲があればすぐに上達できると思います。定本でデータ構造とアルゴリズムがなぜ大切かがよく分かったので、しっかりと勉強していこうと思います。
# おわりに
初心者なりに考えたことを書いてみましたがいかがでしたか？

私は定本を読んでかなり無駄な勉強をしていることに気が付いた気がします。
余計な力と時間を使わないようにしっかりと考えることができました。

記事について何かコメントがあるとうれしいです。
# 参考文献
http://www.kondoyoshiyuki.com/books/c-algo/
Curl: GitLab で GraphQL を使う

次のページを参考にしました。
[Command line](https://docs.gitlab.com/ee/api/graphql/getting_started.html#command-line)

## プログラム

```bash:get_name.sh
ACCESS_TOKEN="glpat-********"
#
URL="https://gitlab.com/api/graphql"
#
curl -H "Authorization: Bearer "${ACCESS_TOKEN} \
	-H "Content-Type: application/json" \
	-X POST -d@query.json ${URL}
```

```json:query.json
{"query": "query {currentUser {name location username webUrl}}"}
```

## 実行結果

```text
$ ./get_name.sh | jq
{
  "data": {
    "currentUser": {
      "name": "Uchida Masatomo",
      "location": "栃木県",
      "username": "ekzemplaro",
      "webUrl": "https://gitlab.com/ekzemplaro"
    }
  }
}
```
VsCode のフォーマットに優先順位がある？ フォーマッタを選び直す

# 問題

`setting.json` でデフォルトのフォーマッタに Prettierを指定しているはずなのに
Prettier より Volar という拡張が優先してフォーマットに利用されてしまう

```json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
}
```


![image](https://user-images.githubusercontent.com/13635059/232183666-4ffd00fd-fb2a-4f6d-be09-484789d40d1b.png)

![image](https://user-images.githubusercontent.com/13635059/232183668-54283a58-beeb-411c-a93b-82875d0a3a0a.png)

いちど Prettier でフォーマットされてから、一瞬後に Volar でフォーマットされるような挙動を見せる

# 解決

`setting.json` で 言語単位で `defaultFormatter` を指定することで解決した

```json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
}
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
Solidity入門 CryptoZombies Lesson1

はじめに
-
NFTゲームを作りたいと思い、solidityの勉強を始めることにしました。
まずは、CryptoZombiesで基本的な勉強を行なっていきます。

https://cryptozombies.io/en/lesson/1/chapter/1

Lesson1の学習内容サマリ
-
* Contractとバージョンの記法
* 変数の定義方法
* 算術演算子
* struct(構造体)の定義方法
* 配列
* function(関数)の定義方法
* アクセス修飾子
* 型キャスト
* Events

Contractとバージョンの記法
-
```
pragma solidity >=0.5.0 <0.6.0; //solidityのバージョン定義

//contract定義
contract HelloWorld {

}
```
バージョン定義はおまじないみたいなもので、contract定義はJavaとかでいうところのClass定義ですね。

変数の定義方法
-
```
uint unsignedInteger = 100;
```
他の言語と大差ないですね。
uintはuint256（256ビット符号なし整数）と同義です。
そのほかにもuint8,uint16,uint32など、各ビット数で定義が可能です。

算術演算子
-
```
uint power = 10 ** 2; // equal to 10^2 = 100
```
基本的な算術演算子が利用可能です。
* 足し算: x + y
* 引き算: x - y
* 掛け算: x * y
* 割り算: x / y
* 剰余: x % y (割り算の余りのことです。16 / 3 の場合、5余り1なので、1が結果として返されます)

struct(構造体)の定義方法
-
```
// 構造体定義
struct Person {
  uint age;
  string name;
}
// インスタンス生成
Person person = Person(20, "name");
```
普通の書き方ですね。クラス定義と大差ありませんが、関数の定義が不可です。
構造体のインスタンス生成にはnewは必要ないようです。

配列
-
```
// 固定長配列
uint[2] fixedArray;
// 可変超配列
uint[] dynamicArray;
dynamicArray.push(1);
```
固定長配列と、可変超配列での定義が可能です。
値を追加する場合は、push関数を呼び出します。

function(関数)の定義方法
-
```
function functionName(string memory _arg1, uint _arg2) public {

}
```
グローバル変数と区別するために、引数の変数名は"_"をつけるようです。
アクセス修飾子等が後ろにつくのは個人的に慣れないですね。

アクセス修飾子
-
アクセス修飾子には、関数のスコープを表すprivate,public,internal,externalの４つと、
関数の動作を表すpure,viewの２つがあります。
* private : 同一のcontract内からのみ呼び出すことが可能です。
* public : 同一のcontract、外部のcontract問わずどこからでも呼び出すことが可能です。
* internal(Lesson1未登場) : 同一のcontractと、そのcontractを継承したサブクラスからのみ呼び出すことが可能です。
* external(Lesson1未登場) : 外部のcontractからのみ呼び出すことが可能です。
* pure : 引数のみを利用し、contract内の他のデータを利用しない場合に付与します。
* view : データの参照のみで、更新を行わない場合に付与します。

型キャスト
-
```
uint a = 1;
uint8 b = 2;
// これは型が違うのでエラー
uint8 c = a * b;
// これは型を同じに変換しているのでOK
uint8 d = a * uint8(b);
```
キャストは上記のように変数を型で囲むことで可能です。

Events
-
Eventsは関数呼び出し元のfrontendとやりとりするための機能です。
solidityで定義、発火し、
```
// eventの宣言
event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public returns (uint) {
  uint result = _x + _y;
  // イベントの発火
  emit IntegersAdded(_x, _y, result);
  return result;
}
```
frontendでは受け取って処理を行います。
```
YourContract.IntegersAdded(function(error, result) {
  // イベント受け取り後の処理
})
```

終わりに
-
keyccakやweb3jsなど、一部割愛しましたが、Lesson1で学んだ内容です。
プログラミング経験のある人の場合すんなり理解できると思います。
次回はLesson2を紹介します。
Qiitaの書き方も勉強しながらやっていきたいと思います。
よろしくお願いいたします。
Amazon CodeWhispererをinstallし使ってみた！

## Amazon CodeWhisperer
https://www.publickey1.jp/blog/23/awsgithub_copilotamazon_codewhisperervscode.html

どうやら最近無料で使えるようになったらしいので、使ってみよう。
AIでコードを補填してくれるサービスらしいでっせ。
CodeWhispererですよ。whisperではないですよ。

試したのは、VS code上での使用です。

## How to
公式サイトからアクセス
https://aws.amazon.com/jp/codewhisperer/

HowToのvideo
https://aws.amazon.com/jp/codewhisperer/resources/#Getting_started/

詳しい手順は公式を見てもらった方がいい。
英語わからなくても雰囲気でわかるので。

### ざっくりとやったことは
・vs codeでamazontoolkitのexpantionをinstall
・startするとbrowserが起動し、会員登録を求められる
・メールアドレスで登録し、認証を受けてサービス開始
（完了画面が出てもうまく行かない場合は、エディタの再起動を試してはいかが）
・vs codeの下のbarにcodewhispererが追加され、codeの保管をしてくれるように

5分もかからないぐらいでできたので簡単でしたよ

## 試してみた
試しに、適当なpythonの関数を書いてみると。。。。

![ezgif-3-6a7a28fb1a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274417/db33274d-d4e5-2a0f-a7ce-43566f5b2e6c.gif)


あら不思議後続処理を見越してくれる！

まだ、installしただけなので効果は不明ですが、強力なツールとして活用していければええなぁ〜
Amazon CodeWhisperer on PHP Storm導入


お金払ってでも試しでGitHubCopilotでも入れてみようかなと思っていたのですが、

https://www.itmedia.co.jp/news/articles/2304/14/news096.html

ちょうど同じような機能を持つAmazon CodeWhispererが正式版になり無料で使えるというので、そちらを導入してみました。とりあえず無料で嬉しくて記事を書いた感じです。

https://aws.amazon.com/jp/codewhisperer/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/379ede88-99ae-29ec-86c7-81a7c822bf1e.png)
ぱっと見Available IDEsにも Support languagesにもPHPやPHPStormは書いてなさそうではありますが、下記を見ると対応していますね。

https://docs.aws.amazon.com/codewhisperer/latest/userguide/language-ide-support.html#language-support

基本はJetBrains IDEは共通で入れられそうです。

## AWS Toolkitインストール：PHP Storm

Pluginでこれを入れる

https://plugins.jetbrains.com/plugin/11349-aws-toolkit

→　再起動

## 認証

メアド登録だけで無料で使えますが、その認証が必要です。
英語の動画ですが下記のIntelliJと同じです。

https://aws.amazon.com/jp/codewhisperer/resources/#Getting_started/

というか、VSCodeともほぼ同じですね。

https://qiita.com/masakinihirota/items/52d3fad3aea8300d391f

一応画像を付けて説明
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/95a0af24-56fa-828a-96ea-440825584c1d.png)
IDEに表示されているCodeをブラウザで入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/9d50264a-9c91-20b8-d8ce-b11f0ec63ea6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/7593e144-c0c9-7b6a-7173-f3ef5e99e6f8.png)

メールアドレスの登録。AWSビルダーIDなるもので、普通のAWSとは異なる模様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/f1efcbea-4343-5b02-a085-0ec3d9834eca.png)
パスワードの入力と、あとはメールが届いてコードの入力をして認証すれば登録は完了です。

## 使う

まだ導入段階で、これから触るのでよくわからないところもありますが、例えば下記のような感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/997b3ed1-1028-9218-b761-070c8768ed43.png)

1つ目のテストを書いたなら、2つ目はこうじゃないか？というSuggestionが出ています。
また「Suggestion 1of 2」で「Next」を押すと2つ目を確認できます。

色々指示すればコードをそのまま出力してくれるかもしれませんが、この辺はChatGPTで、こういうコードを書いてって指示したほうが個人的には今のところやりやすいです。

この辺の使い方はこれから探っていこうと思います。

## 怪しい日本語

日本語のコメント補完は不思議な感じのものが生まれます
まずSuggestionが化けててわからない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/ced77e54-05e1-6b08-efda-18aa32f38b28.png)
入力してみると謎の日本語が生まれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140947/028840ee-cdd0-ae06-0d34-c09d5aa72c1c.png)
ChatGPTについて考える (5) 語用論、敬語など

「[ChatGPTについて考える](https://qiita.com/ryokan/items/0e65dfa1cffa2cbd3ddb)」、今回は語用論など言語の高次的な使用について考えます (最初「運用論」と書いていましたが、「語用論」が一般的に使われているようですので、訂正します)。

語用論 (pragmatics) は、言語を、情報を伝えるだけでなく、それによって得られる効果の観点から言語使用を考えます。スピーチアクト理論では、発話者は情報を伝える発話行為 (Speech Act) (狭い意味での発話行為) を行うのですが、それによって得たい効果 発話内行為 (illocutionary act) を分けて考えます。例えば「依頼」、「提案」によって、相手が行動を起こすことを期待しますし、「質問」は相手から情報を引き出すことを期待します。

ChatGPTは、質問に答えてくれますし、「～を作って」とか「～を考えて」というような依頼 (基本的にはテキスト生成としてできるものなのでプログラム作成なども含む) にも応じてくれますので、発話者の明示的に示された意図も理解してくれます。

直接的に意図を含ませるだけでなく、間接的に意図を表現することもあります。よく使われる例では、「暑いね」という発話が「窓を開けてください」ということを示すという場合があります (今だと「エアコンの設定温度を下げてください」の意味かもしれません。

古い話になりますが、1985年つくば科学万博のアメリカ館ではAIをテーマに展示をしていました。そこで上映されていたコンセプト映像でこういうシーンがありました。

電話がかかっている。小さい女の子が出る。電話してきた人は、子どもだということに気づき、「お母さんはいますか」と聞く。女の子は、お母さんを呼びに行く。

この「お母さんはいますか」はただの質問ではなく、「お母さんがいるなら代わってください」という依頼なんですが、小さい女の子でもそれが分かりますが、コンピューターにわかるでしょうか、簡単にできそうにないですよね、という問題提起だった訳です。確かに難しそうですが、ChatGPTではできそうな気がします。

[前回](https://qiita.com/ryokan/items/8e22edae0ab1a7803cd0)、以下のようなやりとりを紹介しました。

Q: この袋に入っている豆は全て白いです。これらの豆はこの袋から取り出されました。これからこれらの豆について何が分かりますか。

ChatGPT: この袋から取り出された豆は全て白いため、この袋に含まれる豆は全て白いことが分かります。ただし、この袋以外の場所から混ざり込んだ白い豆が含まれている可能性はあります。また、この袋に入っている豆の品種や大きさ、形状、質などについては何も分かりません。袋の中に全て白い豆があるということ以外の情報はありません。

これにチャットを続けてみます。

Q: ちょっと説明が長いですね。

ChatGPT: 申し訳ありません。もっと簡潔に説明するよう心掛けます。袋から取り出された豆は、すべて白い豆であることが分かります。

長いと言われたら短くする、というのでたいした例ではありませんが、直接依頼した内容ではなくても対応できていることわかります。

このような対応方法が理論的に整理されている訳ではありませんが、むしろそういう場合に大量のデータからやりとりを学習するAIは強いと思います。

ユーザーが直接発していない意図を理解する例が結城浩さんのツイートで知りました。→ [ChatGPT と結城浩の対話（矛盾や反復を含んだ対話によってAIと人間の識別は行えるか）](https://gist.github.com/hyuki/f7218870ae47847eab066545b8b51d05)

この中で、結城さんは

> そういえば、以前ChatGPTと会話したときには「新しい情報」に答えてもらえなかったり、「言葉遊び」にもとまどう印象があったりしました。

をいった発言と、

> 以前ChatGPTと会話したときには「新しい情報」にもChatGPTは意外にうまく答えることができましたし、「言葉遊び」にも当意即妙な受け答えをしていた印象があります。

のような逆の発言を交互にしています。これに対してChatGPTは、前者には「以前のバージョンのChatGPTではそういうことがありました」と、後者には「AIは進化し続けており、新しい情報に対して適切な推測を立てたり、言葉遊びに対してユーモアやダジャレを含めた回答を提供できるようになってきています」というように、それぞれに適切な例を返します。

ここまではうまくかわしているなと思うのですが、最後のほうで結城さんは、「ここまでの私とあなたの対話で、私の発言の中に矛盾はありましたでしょうか。また、堂々巡りと思われる部分はありましたか。」と聞いています。これに対して、

> 確認させていただいたところ、矛盾に関しては、お話しいただいた「新しい情報」や「言葉遊び」に対する以前のChatGPTとの会話の印象において、肯定的な印象と否定的な印象が交互に現れていました。ただし、これはあなたが私たちAIの進化や限界を試す目的であえて矛盾を含めた発言を行っていたと理解しています。
>
> 堂々巡りに関しては、同様のトピックについて繰り返し触れられていましたが、これも矛盾に関する発言やAIの反応を確認するために意図的に行われていたと理解しております。

「分かっていたけど触れずにおきました」という、神様かとも思える視点が怖いです。

敬語については、ChatGPTに敬語を使うことで結果が良くなるという話があります。

Togetter [AIにも敬意や気遣いが必要…？「ChatGPTに敬語で接すると出力結果が大幅によくなる可能性がある」という話](https://togetter.com/li/2108044)

これまで見てきたように、ChatGPTは直接的情報伝達でない言語の使用も認識しているようにみえます。ChatGPTってもうAGIなんじゃね? という印象が強くなります。
pexpectでサーバコマンドをpythonコードから制御する

# **pexpect**でサーバコマンドをpythonコードから制御する

**pexpect**でサーバコマンドをpythonコードから制御する手順を解説します。

## 注意点

**pexpect**はUnix環境での利用が前提となっています。  
Windows環境用の拡張も行われているようですが、呼出方法が異なったりするようなので
以下ではUnix環境(Linux)での利用を前提とします。  

## **pexpect**のインストール

```text
pip install pexpect
```

## サーバコマンド`ping`の呼出

```python
import pexpect

child = pexpect.spawn('ping 127.0.0.1 -c 10')

while True:
    try:
        child.expect('\r\n',timeout=3)
        print(child.before)
    except Exception as e:
        print(type(e))
        break

```

## オプション

下記のオプション指定が可能です。  
cwd:作業フォルダ  
env:環境変数  

<例>  
下記例では、作業フォルダを`/usr/local/bin`  
環境変数`LD_LIBRARY_PATH`に`.`を指定しています。  

```python
import pexpect

child = pexpect.spawn('some_command'
        ,cwd='/usr/local/bin'
        ,env={'LD_LIBRARY_PATH':'.'})

```

## 👇参考URL

- <https://qiita.com/ground0state/items/cb7db426682e33cbe1e7>
- <https://open-groove.net/python/pexpect-create-password/>
- <http://eng-manima.blogspot.com/2014/09/pexpect.html>
- [pexpect API document](https://pexpect.readthedocs.io/en/stable/api/)
クリップボードの画像イメージから文字列を取り出し翻訳する

# クリップボードの画像イメージから文字列を取り出し翻訳する

Pythonでクリップボードの画像イメージから文字列を取り出し翻訳する手順を解説します。  

## 👇この記事の内容は下記記事の内容を組み合わせて実現します

- [クリップボードからのイメージ取得](https://docusaurus.plant11.com/python/20230308_02_get_clipboard_image)  
- [Tesseractを利用したPythonによるOCR処理](https://docusaurus.plant11.com/python/20230308_03_ocr)  
- [DeepL を利用したPythonによる英文翻訳](https://docusaurus.plant11.com/python/20230309_01_translate)  
- [文字列をクリップボードに格納する(Pythonコード)](https://docusaurus.plant11.com/python/20230309_02_put_clipborad)  

## クリップボードの画像イメージから文字列を取り出し翻訳するコード

```python
import pyocr
import pyocr.builders
import deepl
from PIL import ImageGrab, Image

DEEPL_AUTH_KEY:str = '****************************'

def main_logic():

    tool = pyocr.get_available_tools()[0]

    clip_img = ImageGrab.grabclipboard()
    if isinstance(clip_img,Image.Image):
        
        original_text = tool.image_to_string(clip_img,lang="tessdata/eng",builder=pyocr.builders.TextBuilder())
        print("----- original text ------")
        print(original_text)
        translator = deepl.Translator(DEEPL_AUTH_KEY)
        result = translator.translate_text(original_text, target_lang="JA")
        print("----- translated text ------")
        print(result.text)

    else:
        print("this is not image.")

if __name__ == '__main__':
    main_logic()

```

## 👇参考URL

[クリップボードの画像イメージから文字列を取り出し翻訳する](https://docusaurus.plant11.com/python/20230309_03_image_translate)  

更新日:2023/03/12  

<!--
Pythonでクリップボードの画像イメージから文字列を取り出し翻訳する(ソースコード解説)
詳しく見たい場合は、私のプロフィール -> ホームページ -> Python -> 「クリップボードの画像イメージから文字列を取り出し翻訳する」見て下さい。
 -->
文字列をクリップボードに格納する(Pythonコード)

# 文字列をクリップボードに格納する(Pythonコード)

Pythonでクリップボードに文字列を格納するコードを紹介します。

## クリップボードに文字列を格納するコード

```python
import pyperclip

def main_logic():
    clip_text = "test line1\r\ntest line2\r\ntest last line"
    pyperclip.copy(clip_text)

if __name__ == '__main__':
    main_logic()
```

## 👇参考URL

[文字列をクリップボードに格納する(Pythonコード)](https://docusaurus.plant11.com/python/20230309_02_put_clipborad)  

更新日:2023/03/12
DeepL を利用したPythonによる英文翻訳

# DeepL を利用したPythonによる英文翻訳

**DeepL**を利用してPythonで英文の翻訳を実現する手順を解説します。

## DeepLのアカウント作成及び認証キーの取得

- 下記URLへアクセスし、DeepLのアカウントを作成します。  
<https://www.deepl.com/ja/signup?cta=free-login-signup/>  
- 下記URLへアクセスし、ログインします。  
<https://www.deepl.com/ja/login/>  
- 👇アカウント情報を参照します。  
![image](https://user-images.githubusercontent.com/38905609/223901564-22a169a9-cbbf-4143-bfae-744bf6f2d567.png)
- 👇アカウントタブを選択します。  
![image](https://user-images.githubusercontent.com/38905609/223902065-a54cb2cf-61f7-4bef-bfae-92ab421cd02d.png)
- 👇アカウントタブ下部の[DeepL APIで使用する認証キー]を作成しキー情報を取得します。  
　認証キー作成には、住所及びクレジットカードの登録が必要です。  
  APIフリープランであれば請求は発生しません。  
![image](https://user-images.githubusercontent.com/38905609/223903639-20cea3f9-1834-4e17-94e7-4f83145b9ad8.png)

## **deeplライブラリ**のインストール

**DeepL**をPythonから利用するため、**deeplライブラリ**をインストールします。  

```text
pip install deepl
```

## DeepL翻訳処理

```python
import os
import boto3
import json
import deepl

AUTH_KEY:str = '**************'

def main_logic():

    original_text = "Nice to meet you."

    translator = deepl.Translator(AUTH_KEY)
    result = translator.translate_text(original_text, target_lang="JA")

    print(result.text)

if __name__ == '__main__':
    
    main_logic()
```

## 👇参考URL

<https://www.deepl.com/ja/blog/announcing-python-client-library-for-deepl-api>

[DeepL を利用したPythonによる英文翻訳](https://docusaurus.plant11.com/python/20230309_01_translate)  

更新日:2023/03/12
クロージャについて理解したこと

# はじめに
<!-- 発端や概要を記載 -->
クロージャについて理解したことを備忘録兼ねて投稿します。
# 目次
<!-- タイトルとアンカー名を編集 -->
1. [クロージャとはなにか](#Chapter1)
1. [なぜクロージャが重要なのか、実際の現場でどんなふうに使えるか](#Chapter2)
1. [クロージャの例](#Chapter3)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# クロージャとはなにか
クロージャとは、ある関数の中で、その関数と一緒に使われる変数や関数を、`いつまでも`覚えている機能のことです。つまり、関数の中で使われたものを覚えておいて、また次にその関数が呼ばれたときには、`前回と同じように`使えるようにしてくれる便利な仕組みです。
<a id="#Chapter2"></a>
# なぜクロージャが重要なのか、実際の現場でどんなふうに使えるか
クロージャはJavaScriptにおいて非常に重要であり、外側のスコープにある変数を参照したり、変数のスコープを制限することができます。これにより、`データのプライバシー`や`セキュリティ`を保護できます。また、`メモ化`や`高階関数の作成`にも役立ち、パフォーマンスの向上にもつながります。現場では、これらの機能を活用して、`保守性の高いコード`を開発するために使用されます。

<a id="#Chapter3"></a>
# クロージャの例
<details><summary>サンプルコード</summary>

function makeAdd(x) {
  return function(y) {
    return x + y;
  };
}
const addFive = makeAdd(5);
console.log(addFive(2)); // 7
console.log(addFive(7)); // 12

</details>

このスクリプトでは、makeAdd関数が引数 x を受け取り、それを加算するクロージャを返します。返された関数は、makeAdd関数が呼び出された際に渡されたxの値を保持し、その後に渡された引数yを加算して返します。

このように、makeAdd関数を呼び出すたびに異なるクロージャが生成され、それぞれが異なるxの値を保持します。したがって、makeAdd(5)で生成されたクロージャは、常に5を加算します。

このように、クロージャは、関数をより柔軟に、より高度な使い方ができるようにするために使用されます。例えば、Reactのコンポーネントの状態管理や、APIコール時の認証トークンの保持など、さまざまな場面で使用されます。
<details><summary>Reactのサンプルコード</summary>

import React, { useState } from 'react';

function ButtonMessage() {
  const [message, setMessage] = useState('Hello, world!');

  const handleClick = () => {
    setMessage('Goodbye, world!');
  };

  return (
    <div>
      <p>{message}</p>
      <button onClick={handleClick}>Change message</button>
    </div>
  );
}

</details>

<details><summary>APIコール時の認証トークンのサンプルコード</summary>

const express = require('express');
const app = express();
const jwt = require('jsonwebtoken');

// 認証トークンを取得するエンドポイント
app.get('/login', (req, res) => {
  // ユーザー認証が成功したと仮定して、JWTトークンを生成する
  const token = jwt.sign({ userId: '12345' }, 'secret_key', { expiresIn: '1h' });
  res.json({ token });
});

// 認証が必要なAPIエンドポイント
app.get('/protected', (req, res) => {
  // リクエストヘッダーから認証トークンを取得する
  const authHeader = req.headers.authorization;
  const token = authHeader && authHeader.split(' ')[1];

  // 認証トークンが存在しない場合、エラーレスポンスを返す
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  try {
    // 認証トークンを検証する
    const decoded = jwt.verify(token, 'secret_key');
    const userId = decoded.userId;

    // 認証トークンが正しい場合、適切なレスポンスを返す
    return res.json({ message: `Hello user ${userId}! This is a protected API.` });
  } catch (err) {
    // 認証トークンが無効な場合、エラーレスポンスを返す
    return res.status(401).json({ error: 'Unauthorized' });
  }
});

// サーバーを起動する
app.listen(3000, () => {
  console.log('Server started on port 3000');
});

</details>


<a id="#reference"></a>
# 参考文献
- [クロージャ - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Closures)
Tesseractを利用したPythonによるOCR処理

# Tesseractを利用したPythonによるOCR処理

**Tesseract**を利用してPythonで英文のOCR処理を実現する手順を解説します。

## Tesseractのダウンロード及びインストール

- 下記サイトからTesseractのインストールモジュールをダウンロードします。  
<https://github.com/UB-Mannheim/tesseract/wiki>  
本記事記載時点の最新版```tesseract-ocr-w64-setup-5.3.0.20221222.exe```を例にします。  
- ダウンロードしたインストーラを起動し、画面の指示に従ってインストールを実行します。  
![image](https://user-images.githubusercontent.com/38905609/223639374-4551f78f-a778-44f3-bbbe-3a597c092d07.png)  
![image](https://user-images.githubusercontent.com/38905609/223639699-8d85f335-c1ec-4ca3-8663-79eab15d751d.png)
![image](https://user-images.githubusercontent.com/38905609/223639817-9e4a0bc3-92ab-4f24-a434-a4c40ba994d8.png)

この例ではTesseractインストールフォルダは```C:\Program Files\Tesseract-OCR```になります。  

## 環境変数の設定

- ```PATH```環境変数へTesseractインストールフォルダ(```C:\Program Files\Tesseract-OCR```)を追加します。
- ```TESSDATA_PREFIX```環境変数へTesseractインストールフォルダ(```C:\Program Files\Tesseract-OCR```)を設定します。

## Tesseract 設定確認

下記コマンドで、正常にTesseractが認識されていることを確認します。

```text
tesseract --list-langs
```

👇正常な場合の出力

```text
List of available languages in "C:\Program Files\Tesseract-OCR/" (2):
tessdata/eng
tessdata/osd
```

## **pyocr**のインストール

**Tesseract**をPythonから利用するため、**pyocr**をインストールします。  

```text
pip install pyocr
```

## OCR処理

```python
import sys
import pyocr
import pyocr.builders

from PIL import ImageGrab, Image

def main_logic():
    tools = pyocr.get_available_tools()
    if len(tools) == 0:
        print("No OCR tool found")
        sys.exit(1)

    tool = tools[0]
    print("Will use tool '%s'" % (tool.get_name()))

    langs = tool.get_available_languages()
    print("Available languages: %s" % ", ".join(langs))
    lang = langs[0]
    print("Will use lang '%s'" % (lang))

    txt = tool.image_to_string(
        Image.open("c:/tmp/clipboard.png"),
        lang=lang,
        builder=pyocr.builders.TextBuilder())

    print(txt)


if __name__ == '__main__':
    main_logic()

```

## 👇参考URL

- <https://qiita.com/pon187/items/f9a70fd52cc91ddb4ed7>
- <https://github.com/UB-Mannheim/tesseract/wiki>
- <https://tesseract-ocr.github.io/tessdoc/Installation.html>
- <https://sourceforge.net/projects/tesseract-ocr-alt/files/>
- <https://github.com/UB-Mannheim/tesseract/wiki/Install-additional-language-and-script-models>

[Tesseractを利用したPythonによるOCR処理](https://docusaurus.plant11.com/python/20230308_03_ocr)  

更新日:2023/03/12
クリップボードからのイメージ取得

# クリップボードからのイメージ取得

Pythonでクリップボードからイメージを取得するコードを紹介します。

## pillow のインストール

pillow をインストールします。

```text
pip install pillow
```

## クリップボードからのイメージ取得コード

```python
from PIL import ImageGrab, Image

def main_logic():
    clip_img = ImageGrab.grabclipboard()
    print(clip_img)
    if isinstance(clip_img,Image.Image):
        print("this is image.")
        clip_img.save("c:/tmp/clipboard.png")
    else:
        print("this is not image.")

if __name__ == '__main__':
    main_logic()
```

## 👇参考URL

- <https://note.nkmk.me/python-pillow-imagegrab-grabclipboard/>
- <https://note.nkmk.me/python-pillow-basic/>

[クリップボードからのイメージ取得](https://docusaurus.plant11.com/python/20230308_02_get_clipboard_image)  

更新日:2023/03/12
マウスクリック座標の検出

# マウスクリック座標の検出

マウスクリック座標を検出するコードを紹介します。

## クリック座標検出コード

```python
import pyautogui
import time
import ctypes

def main_logic():

    while True:
        if ctypes.windll.user32.GetAsyncKeyState(0x01) == 0x8000:
            pos = pyautogui.position()
            print(pos)

if __name__ == '__main__':
    main_logic()

```

## 👇参考URL

- [Keycode 定数](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/keycode-constants)

[マウスクリック座標の検出](https://docusaurus.plant11.com/python/20230308_01_detect_click)

更新日:2023/03/12
DCG と良い子悪い子普通の子（演算子を定義してみる編）

# 状況設定

[DCG と良い子悪い子普通の子](https://qiita.com/tadashi9e/items/fa3d9bc42e64ef7a4131) よりもう少し複雑な状況を考えます。

ある学校には、良い子、悪い子、普通の子の三種類の生徒がいます。

- 良い子はいつも正直です。
- 悪い子はいつも嘘をつきます。
- 普通の子は正直なときもあれば、嘘をつくときもあります。

テストの成績はだいたい見当がつくとおり、

- 良い子はいつもいい成績を、
- 悪い子には及第点ぎりぎりの成績を、
- 普通の子は良くも悪くもないそこそこの成績を、

それぞれとります。なので、いつでも成績順は

良い子の成績 > 普通の子の成績 > 悪い子の成績

になっています。

さて、良い子、悪い子、普通の子の三人が集まって話をしているのを小耳にはさみました。

- A は『B の成績は C の成績より高い』と言っていました。
- B は『C の成績は A の成績より高い』と言っていました。
- C も『... の成績は ... の成績より高い』と呟いていましたが、よく聞こえませんでした。

さて、C はなんと言っていたでしょうか。

# 解いてみる

三種類の生徒の成績の良し悪しを比較する演算子として `>` を使ってもよさそうです。
しかし、やってみると DCG で具合が悪いので、代わりに `>>` を演算子として定義しておきます：

```prolog
:- op(700, xfx, '>>').
```

これを使って、状況を以下のように書き表してみます：

```prolog
状況 -->
    % 良い子、悪い子、普通の子の三人がいる。
    % A, B, C のどれがどの子かは不明。
    { permutation([良い子, 悪い子, 普通の子], [_属性A, _属性B, _属性C]),
      A = 生徒('A', _属性A),
      B = 生徒('B', _属性B),
      C = 生徒('C', _属性C) },
    % 言及： A が『B の成績は C より高い』と言った
    言及する(A, 成績(B) >> 成績(C)),
    % 言及： B が『C の成績は A より高い』と言った
    言及する(B, 成績(C) >> 成績(A)),
    % 言及： C が、A, B の成績についてなにかを言った
    { permutation([A, B], [AorB1, AorB2]) },
    言及する(C, 成績(AorB1) >> 成績(AorB2)).
```

それぞれの言及について、内容を検証しつつ文章として組み立てる処理を書くと、こんな感じです：

```prolog
言及する(_生徒, _文)
--> { 検証する(_生徒, _文, _真偽),
      _生徒 = 生徒(_名前, _属性) },
    [_名前, '(', _属性, ')', が, '『'], _文, ['』(', _真偽, ')', と言った, '。\n'].

成績(X) >> 成績(Y)
-->
    { X = 生徒(_名前X, _属性X),
      Y = 生徒(_名前Y, _属性Y) },
    [_名前X, '(', _属性X, ')の成績は', _名前Y, '(', _属性Y, ')の成績より高い'].
```

それぞれが成績順について言及した内容を検証する手続きは、以下のように書けます：

```prolog
検証する(生徒(_, 良い子), _文章, 真) :- call(_文章).
検証する(生徒(_, 悪い子), _文章, 偽) :- \+ call(_文章).
検証する(生徒(_, 普通の子), _文章, 真) :- call(_文章).
検証する(生徒(_, 普通の子), _文章, 偽) :- \+ call(_文章).

% 成績の良し悪しは属性から自動的に決まる
成績(生徒(_, 良い子)) >> 成績(生徒(_, 普通の子)).
成績(生徒(_, 普通の子)) >> 成績(生徒(_, 悪い子)).
成績(生徒(_, 良い子)) >> 成績(生徒(_, 悪い子)).
```

状況を表す文全てを出力する手続きを書くと：

```prolog
解を得る(_一つの文) :-
    phrase(状況, _状況を表す文章),
    atomic_list_concat(_状況を表す文章, _一つの文).
解を表示する :-
    解を得る(_一つの文),
    write('==== 解 ====\n'),
    write(_一つの文),
    fail.  % 失敗駆動ループ
solve :- 解を表示する.
```

# 実行結果

実行すると、こんな解が得られました。

```prolog
?- solve.
==== 解 ====
A(良い子)が『B(普通の子)の成績はC(悪い子)の成績より高い』(真)と言った。
B(普通の子)が『C(悪い子)の成績はA(良い子)の成績より高い』(偽)と言った。
C(悪い子)が『B(普通の子)の成績はA(良い子)の成績より高い』(偽)と言った。
==== 解 ====
A(悪い子)が『B(普通の子)の成績はC(良い子)の成績より高い』(偽)と言った。
B(普通の子)が『C(良い子)の成績はA(悪い子)の成績より高い』(真)と言った。
C(良い子)が『B(普通の子)の成績はA(悪い子)の成績より高い』(真)と言った。
false.
```

なので、C は『B の成績は A の成績より高い』と言っていた、というのが問題の答えです。
[Flutter]ドロップダウンで選択中の文字色だけ変える

# はじめに

Flutterの[DropdownButton](https://api.flutter.dev/flutter/material/DropdownButton-class.html)を利用して、ドロップダウンメニューが表示されているときのみ、選択中のアイテムの文字色を変更します。
下記が今回実装したパーツの動作となります。
![demo_dropdown.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175966/6367b5fc-94c8-ed78-4196-40ab779aed3f.gif)

実装に関してはサンプルコードベースで簡単に実装しました。
Flutterはまだまだ初心者なのでベスプラなどあれば優しくご指摘ください。


# 実装方法

具体的にはDropdownButtonのオプションとして用意されている[selectedItemBuilder](https://api.flutter.dev/flutter/material/DropdownButton/selectedItemBuilder.html)を活用することで実装できます。

※コードは[Flutter公式ドキュメント(DropdownButton<T> classのソースコード](https://api.flutter.dev/flutter/material/DropdownButton-class.html#material.DropdownButton.1)を一部変更する形で記述しています。

```dart:main.dart
import 'package:flutter/material.dart';

const List<String> list = <String>['One', 'Two', 'Three', 'Four'];

void main() => runApp(const DropdownButtonApp());

class DropdownButtonApp extends StatelessWidget {
  const DropdownButtonApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('DropdownButton Sample')),
        body: const Center(
          child: DropdownButtonExample(),
        ),
      ),
    );
  }
}

class DropdownButtonExample extends StatefulWidget {
  const DropdownButtonExample({super.key});

  @override
  State<DropdownButtonExample> createState() => _DropdownButtonExampleState();
}

class _DropdownButtonExampleState extends State<DropdownButtonExample> {
  String dropdownValue = list.first;

  @override
  Widget build(BuildContext context) {
    return DropdownButton<String>(
      value: dropdownValue,
      icon: const Icon(Icons.arrow_downward),
      elevation: 16,
      style: const TextStyle(color: Colors.deepPurple),
      underline: Container(
        height: 2,
        color: Colors.deepPurpleAccent,
      ),
      onChanged: (String? value) {
        // This is called when the user selects an item.
        setState(() {
          dropdownValue = value!;
        });
      },
      items: list.map<DropdownMenuItem<String>>((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(
            value,
            style: TextStyle(
                color: value == dropdownValue
                    ? Colors.redAccent /// 選択中の文字色だけ変更する。
                    : Colors.deepPurpleAccent),
          ),
        );
      }).toList(),
      selectedItemBuilder: (context) {
        return list.map<DropdownMenuItem<String>>((String value) {
          return DropdownMenuItem<String>(
            value: value,
            child: Text(
              value,
              style: const TextStyle(
                color: Colors.deepPurpleAccent, /// ドロップダウンメニューを表示していないときの文字色はselectedItemBuilderで個別に定義する。
              ),
            ),
          );
        }).toList();
      },
    );
  }
}

```

# さいごに

今回はドロップダウンの細かい設定を変える例として、ドロップダウンメニューを表示しているときのみ選択しているアイテムの文字色を変更する方法を紹介しました。
Flutterはまだまだ学習中ですが、簡単にでもアウトプットしていきます。
Try Hack Me のVPN接続が出来なかった話 

## 出てきたエラー
THMを始めようと思い、VPN接続をし、用意されたサーバーにアクセスした。でも、なぜかページがタイムアウトする(´;ω;｀)
原因を探ったところ、VPN起動時にエラーを吐いてた。下記が表示されたエラーである。<br>
` 2023-04-14 22:46:27 ERROR: Failed to apply push options `

## 調べてみたら
使っているOpenVPN2.6は、OpenVPN構成に保存されているオプションが変わるようになったらしいです。
「chier」を「data-ciphers」に置き換えるために、OpneVPN構成ファイルを更新する。

` sed -i 's/cipher AES-256-CBC/data-ciphers AES-256-CBC/' *.ovpn `

***.ovpn**の部分は、自分が保存しているファイルパスを入力

## 接続成功
更新した後にもう一度起動してみると、うまく接続が出来ました。
一応、この作業は応急処置という感じで使用しました。
参考にした資料のソースを貼っておきます。

[参考資料](https://tryhackme.com/forum/thread/62bad83cf1848200429736f3)
プログラマーの悩み事あれこれ

# 概要
プログラマーの悩み事は尽きない。なぜなんだろうか。
プログラミングは、記憶の連続。常に新しい技法を習得してゆかないと陳腐化してしまう。
そこで、困るのは、折角、難しい技法を習得しても、しばらくすると思い出せない。そのソースコードをみてもダメで、メンテナンスが思うようにできない。もちろん、時間をかければ理解できるのだが、そこまでの時間がもったいない。コストもかかる。
そこで、思うのは、そんな難しいテクニックを使ってまで、その技法で実装する必然性があるのかということです。
あとあとのメンテナンス時間を考慮すると、後で理解がすぐできる実装技法の方が品質面でも良いのではないとかということです。
立派な技法でなくても、わかりやすいコードの方がベストなのではと思う。
クラス化やオブジェクト化は優れた技法だが、その使い方を考えないとかえってわかりにくいものになってしまう。プロパティやメソッドはどこまで含めたらいいのかとか。thisの使い方とか。
いつも起こることだが、あとでそのコードを見てみるとわかりづらいコードだと思う。
設計が十分でなく、あまり時間もないので、とりあえず作成しまう。
コードの肥大化は、時間とともに増加してしまう。機能が増えると、やるべきことは操作性をよくしようと思うとともに増えて行く。それは自動化の増加とともに起こる。アクションを減らすことはいいことだが。

# では、どうしたらいいのか。
・むずかしい技法は使わない。
バージョンアップが頻繁な技法は使わない。つねに改修が行われているためか。
・シンプルイズベスト
昔から言われていることだが。だれでも手を入れることができるコード。
・規定(ルール)が細かい技法はつかわない。
規定は少ない方がよい。
・使いなれた技法を使うのがベストか?
慣れない技法で苦労するよりも慣れている確実な技法を使うのがよい。
・新しいことにもチャレンジは必要。
例えば、Webサイトを構築していると非同期処理が必要になります。promiseやasync,awaitなどを使う必要もあります。これには習熟しておく必要があります。
・.fetch()は難しい。
しばらく、.fetch()も使っていましたが、どうもうまく動作しなくて、結局は$.ajaxにもどしました。$.ajaxは安定して使えてます。
・拡張機能もチャレンジしているうちに使い慣れてきました。
拡張機能は特有の個性があり、はじめは戸惑いましたが、作成しているうちに特有の制限もクリアできるようになりました。

話はそれますが、デバッグしていて、エラーメッセージが表示されますが、その意味がわからないことが多いです。具体的なエラー原因を示せないものか。エラーメッセージのためにさらに時間を費やすことはしたくありません。エラーメッセージは早くエラー原因を修正するためにあるとはずですが、かえって難しくしています。

# ひとつ大変なことになった話をします。
退役後に、ある伝手を頼って、ある仕事を請け負うことにしました。いくつかの業者へ経て最終の発注元は国からの仕事です。
仕事はあるビッグデータを処理して解析結果を出力することですが、これがとんでもない結果を生んでしまいました。最終的には途中で断念して中止できましたが、悩みに悩んで鬱を併発しそうになったので、体のことを考え、やめさせてもらいました。
何しろ、自宅で作業していたのですが、毎日、ほとんど深夜まで作業しても終わらない仕事でした。これが連日、数か月続いたため、精神がおかしくなってきました。
どんな作業かといいますと、そのビックデータが正常に整形されていなかったのです。大体は仕様通りのデータ形式になってはいましたが、様々なところで取得していたデータらしく、また、その処理系もいろいろあったのでは思うのですが、データ解析を続けて行くといたるところで整形されていないデータに出っくわし、毎回それらのデータを整形し直しては次の処理へすすみます。なにしろ、ビッグデータですから、いつまでたっても終わらないのです。毎日、これが深夜まで続きます。
いつかは終わるはずですが、実は別に大きな問題があり、それは、請負のような契約で、金額もはっきり決めてなく、スタートしてしまったためです。時間契約ならよかったかもしれませんが、事情で自宅でしか作業ができなく、会社からは出向を依頼されていましたが、こちらの都合で自宅作業していたため、強くは出られない事情もありました。それもあり、毎月の入金がないまま、数か月が過ぎたため、生活の不安もあり、仕事は終わらず、精神がおかしくなりつつありました。それ以上、続けていたらダウンしていたと思われます。その件は、契約のことより、ビッグデータを処理するときの注意です。長い時間をかければ、いつかはデータも整形できるかもしれませんが、その先も新しいデータが追加され、その中に不整形データが混じっていればいつまでたっても終わりません。これは計測データを収集するときは、データの整形をきちんとしてからデータ解析すべきと思っています。
今はもうそのようなことは発生していないことを祈るのみです。
これもプログラマーの悩み事の一つです。


# あとがき
プログラマーの悩み事を解決することは困難を極めます。
つぎから次へと新しい悩み事が出てきます。悩むことで、新しい解決策を習得できるはずですが。
昔から共通化対策として部品化が言われています。ハードウェアではネジ一本でも標準化されています。標準化されたドライバーで標準化されたネジを簡単に閉めたり緩めたりできます。
しかし、ソフトウェアではそのような標準化部品、ツールはあるのでしょうか。ネジもドライバーも寸法が規定されていて、どこの工場でもその寸法通りのネジやドライバーを作れば世界に通用します。

ソフトウェアを見回すと、Webページなどを作成するときに使うのは、HTML,CSS、javascriptやjquery,phpなどの言語です。
これらを部品、ツールと考えれば、確かに標準化されていますが
それは概念が高く広すぎるので、もっと低いレベルで考えると、
標準メソッド、オブジェクト、APIなどでありますが、
これらは、改変や削除が繰り返され、安定しません。いつまでも使い続けることはできません。
使用方法については、仕様書、マニュアル他がありますが、
わかりづらいです。ドキュメントにはあまりコストをかけたくないのか。確かに、我々も、現役の頃、ドキュメントの作成は嫌な作業の典型でした。作ることは勢力的に努力しましたが。なぜ、みんなドキュメント作成は嫌がるのか。作る方は楽しみがあります。完成した時のその達成感は格段に違います。

今回は、プログラミングをしていて、折角、覚えた難しい技法もしばらく時間が経つと忘れて、メンテナンスするにしても再び、理解するまでに時間がかかることが発端です。
その技法をあきらめて、オーソドックスな作り方にもどしました。その方がメンテナンスも効率よく行えます。
あえて、凝った技法を使う必要もないとかと思いました。その方が改造も改修もスムーズに行えます。バグの潜在も減ります。
Julia: GitHub で GraphQL を使う

こちらのプログラムを Julia で書き換えました。
[Curl: GitHub で GraphQL を使う](https://qiita.com/ekzemplaro/items/35f37293cc49cdb09587)

## プログラム

```bash:get_data.sh
export ACCESS_TOKEN="ghp_*******************"
./get_data.jl
```

```jl:get_data.jl
#! /usr/bin/julia
#
#	get_data.jl
#
#						Apr/15/2023
# --------------------------------------------------------------------
# import Pkg; Pkg.add("HTTP")
using HTTP

println(stderr,"*** 開始 ***")
url = "https://api.github.com/graphql"
access_token = ENV["ACCESS_TOKEN"]
query_file = "query.json"

# クエリの内容をファイルから読み込む
query = read(query_file,String)

# HTTPリクエストを送信する
response = HTTP.request(
    "POST",
    url,
    headers = ["Authorization" => "bearer $access_token"],
    body = query,
)

# レスポンスを表示する
println(String(response.body))

println(stderr,"*** 終了 ***")
# --------------------------------------------------------------------
```

```json:query.json
{
 "query": "query { user(login: \"ekzemplaro\") {name location url}}"
}
```

## 実行結果

```text
$ ./get_data.sh | jq
*** 開始 ***
{
  "data": {
    "user": {
      "name": "Uchida Masatomo",
      "location": "Tochigi,Japan",
      "url": "https://github.com/ekzemplaro"
    }
  }
}
*** 終了 ***
```

## 確認したバージョン

```text
$ julia --version
julia version 1.8.5
```
【MVCモデル】Laravelで実装するMVCモデルの基本を図解する

## アジェンダ
* MVCモデルとは何か概念を理解する
* 具体例を用いてMVCモデルを言語化する

## MVCってなんぞ
> Model-View-Controller (MVC、モデル・ビュー・コントローラ) はUIを持つソフトウェアに適用されるソフトウェアアーキテクチャの一種である。
   *「Model View Controller」出典: フリー百科事典『ウィキペディア（Wikipedia）』*

要はソフトウェア開発における設計手法のひとつ。PHPという言語は簡単で自由が故、開発者毎にコーディング規約や設計方針が異なるので、全体おおよそで設計手法を統一して設計するときに使われる考え方のひとつ。

ただやみくもにコーディングしていくのではなく、プログラムを設計する際にパーツを分けて実装していく。その分かつパーツが、**[Model][View][Controller]** で、頭文字をとってMVCモデルと言われる。

例えば掲示板サイトを開発するにあたって、ユーザーに投稿フォームを表示させる画面機能や、投稿されたデータを取得してDBへ登録する処理機能、すでにDBに登録されているデータを何かしらの条件で抽出して取得する機能、取得したデータをユーザーに表示させる画面機能など、ひとつに掲示板サイトを開発するとしても様々な機能開発が必要。

これらをルールに則ること無くドンドコドコドコ実装していくのではなく、ユーザーに画面を表示している部分、データの受け取りと受け渡し及び加工を行う部分、データ取得や保存などDBとのやりとりを行う部分と、役割を分離させて実装させていく事で、保守性や開発効率の向上を期待できる。

一般的には以下。

* **Model**
データ取得や保存などDBとのやりとりを行うパーツ
* **View**
ユーザーに表示させる画面やUIを作るパーツ
* **Controller**
データの受け取りや受け渡し及び加工を行うパーツ

これらの役割分担を行う開発手法であるMVCモデルは、多くのフレームワークで採用されている。PHPで言うところのLaravel、cakePHP、CodeIgniterなど。RubyではRuby on Rails、PythonであればDjango、JavaであればSpring Framework、などなど…
![スクリーンショット 2023-04-15 10.20.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069990/2abd2ac6-1979-bfc5-eafc-d8fddc9efd1e.png)
## 例えば
掲示板サイトを具体例にMVCモデルを視覚化してみる。
#### 前提条件
* keijiban.comという情報投稿WEBサービスが存在する
* 一意のkeijiban.com登録ユーザーがマイページを表示するためにマイページへアクセスする
* **Controller**にはマイページに必要なデータを**Model**から取得するロジックと、**View**へ値を渡すロジックが実装されている
* **View** で制御する **template**にはマイページを表示させるhtmlが実装されている
* **Model**にはユーザー情報が保存されているテーブル、投稿情報が保存されているテーブルとのやりとりを行うロジックが実装されている
![スクリーンショット 2023-04-15 11.05.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1069990/a629b061-dd9b-1473-4214-25ee8eb41795.png)
#### 何が起こっているのか
左側のレクタングルは一意のユーザーで、右側のレクタングルはkeijiban.com内の実装で動いているMVCモデルでのサーバーサイドの処理。
マイページへアクセスすると、まず**Routing**という機能で、クライアントのリクエストによって実行するサーバーサイドの処理を分岐、呼び出す。（※本投稿では説明を一切割愛していますが、簡単な概念は以下でまとめています。）

https://qiita.com/rh8_mp1/items/4e0037e8ab2919c9a4d7

今回のRoutingによって呼び出された**Controller**は、アクセスしたユーザー情報や投稿情報を取得したいので、**Model**からデータ取得を行う。呼び出された**Model**は、DBとのやりとりを実行し、**Controller**へデータを渡す。**Controller**は必要なデータを取得することができる。

その後、**Controller**は**View**へ取得したデータを渡し、ユーザーのマイページを表示させる処理を実行させる。呼び出された**View**は、指示されたtemplateファイルによりマイページを表示させ、取得したデータを受けて正しいマイページを表示させる。
#### 結論
処理の役割を明確に区分することで、冒頭に記載したメリットを享受できるだけでなく、システム内で何が起きているか、どこで処理が実行されているか、データの受け渡しはどのように実施されているかを具体的にイメージすることができる。

これはシステム全体の理解や、データベースの理解につながると思っているので、難しくてもサーバーサイド側の技術を学ぶ上でMVCモデルの概念を理解するのは必須科目だなと感じた。
## おわりに
Laravelで実装している上で、MVCモデルの理解が必須となった理由は、データの受け渡しのロジックを言語化したいため。ほぼ、この世に存在しているWEBサービスはデータの管理をRDBで行っていると想定しているが、データの取得や抽出及び管理には複雑なリレーションの定義が必要。その前提条件にMVCモデルの理解が必要だと思っているのでまとめてみました。

今回はここまで。
お時間頂きありがとうございました。