OmniAICreator/Qiita-1.07M huggingface dataset:
cscの作法 その335

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
sqliteでsqlを直接、実行するツールを作れ。


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/7b74fcf7-6c3e-704d-b9ff-4bea3d1fc0fb.png)


# サンプルコード

```

using System;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.Data.Common;
using System.Transactions;
using System.Data.SQLite;

class form1: Form {
	private Button sButton = new Button();
	private TextBox bo1 = new TextBox();
	form1() {
		Text = "SQLite";
		ClientSize = new Size(400, 300);
		bo1.Location = new Point(20, 20);
		bo1.Text = "DELETE FROM fruit WHERE id = 3";
		bo1.Width = 360;
    	bo1.Height = 200;
		bo1.Multiline = true;
		sButton.Location = new Point(300, 240);
		sButton.Text = "submit";
		sButton.Click += new EventHandler(SButton_Click);
		Controls.AddRange(new Control[] {
			bo1,
			sButton
		});
	}
	private void SButton_Click(object sender, EventArgs e) {
			SQLiteConnectionStringBuilder ConnectionStr = new SQLiteConnectionStringBuilder();
			ConnectionStr.DataSource = "db0.sqlite";
			using (SQLiteConnection Connection = new SQLiteConnection(ConnectionStr.ToString()))
			{
				Connection.Open();
				using(SQLiteCommand Command = new SQLiteCommand(Connection))
				{
					Command.CommandText = bo1.Text;
					Command.ExecuteNonQuery();
				}
			}
			Console.WriteLine("ok0");
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}





```
以上。
devise nameカラム追加


## ゴール
nameカラムが追加された状態でdevise導入

## 背景
deviseを導入する時毎回「devise nameカラム」でググるので、覚える為に書きました。

# 手順
## １、gemインストール
```ruby:Gemfile
gem 'devise'
```
`$ bundle`

## ２、初期ファイル、Userモデル、viewファイル作成

`$ rails g devise:install`

`$ rails g devise user`

`$ rails g devise:views `

## ３、マイグレーションファイルを編集して、nameカラムを追加する

```db/migrate/〇〇_devise_create_users.rb
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name,              null: false, default: "" #追加
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

  ~省略~

  end
end
```
`$ rails db:migrate`

## ４、新規ユーザー登録画面のフォームにname欄を追加
```app/views/devise/registrations/new.html.erb
<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field"> #追加
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true %>
  </div>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>
  
  ~省略~

  end
end
```
## ５、パラメーターの許可
```app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller? #追加

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end
end
```

以上です。

### おまけ
・画面にログイン、ログアウト、新規登録リンクを表示
```app/views/layouts/application.html.erb
  <header>
    <ul class="menu menu-vertical lg:menu-horizontal bg-base-100 rounded-box">
      <li><%= link_to "ログイン", new_user_session_path %></li>
      <li><%= link_to "ログアウト", destroy_user_session_path, data: { turbo_method: :delete } %></li>
      <li><%= link_to "新規登録", new_user_registration_path %></li>
    </ul>
  </header>
```
Java Optional

ChatGPT(GPT-4)に聞いてみた。


Java 8から導入された `Optional` クラスは、値がnullの可能性をあらわす型であり、nullチェックを明示的に行うことなくnull安全なコードを記述することを可能にします。これにより、nullに関連するランタイムエラー（`NullPointerException` など）を避けることができます。

以下に、`Optional` の基本的な使用方法を示します。

```java
import java.util.Optional;

public class OptionalExample {
    public static void main(String[] args) {
        String str = null;

        // Optionalを使ってnullをラップする
        Optional<String> optional = Optional.ofNullable(str);

        // ラップした値がnullかどうかを判断する
        if (optional.isPresent()) {
            System.out.println(optional.get());
        } else {
            System.out.println("値が存在しません");
        }

        // ラップした値がnullの場合にデフォルト値を返す
        System.out.println(optional.orElse("デフォルト値"));

        // ラップした値がnullの場合に例外をスローする
        try {
            System.out.println(optional.orElseThrow(NullPointerException::new));
        } catch (NullPointerException e) {
            System.out.println("例外がスローされました");
        }
    }
}
```

メリット：
- Nullポインターエクセプションを防ぐことができます。これにより、ランタイムエラーを減らすことができます。
- Nullチェックが明示的に行われるため、コードが読みやすくなります。そのため、コードのメンテナンス性が向上します。

注意点：
- Optionalをフィールド、配列の要素、またはコレクションの要素として使用するのは推奨されていません。その理由は、Optionalが設計された目的は、メソッドの戻り値としてnullを明示的に表現することであり、フィールドや配列、コレクションの要素に使用するとその意図が曖昧になるからです。
- Optionalの`get`メソッドは、ラップしている値がnullでないことを保証しないため、呼び出す前に`isPresent`メソッドでチェックを行うべきです。さもなければ、`NoSuchElementException`がスローされる可能性があります。
- `Optional` は可能な限り関数型のアプローチを使用するべきです。つまり、`isPresent` と `get` の組み合わせよりも、 `map`, `filter`, `flatMap`, `orElse`, `orElseGet`, `orElseThrow` などのメソッドを使う方がより望ましいです。
Pythonの文字列操作 覚え書き

# 文字列操作の基本

「退屈なことはPythonにやらせよう 第2版 ―ノンプログラマーにもできる自動化処理プログラミング」 https://amzn.asia/d/gMU3h2f
より抜粋してメモ化。例の関数など、適宜改変を加えてある。節番号が表記してあるので、原典を参照されたし。

## escape文字 (6.1.1.2)

- 表6-1

|escape文字|意味         |
|---------|------------|
|`\'`     |シングルquote |
|`\"`     |ダブルquote  | 
|`\t`     |tab         |
|`\n`     |改行         |
|`\\`     |バックスラッシュ|


## raw 文字列 (6.1.1.3)

quote文字列の前に`r`をつけると、raw文字列を表す。
raw文字列では、文字列中のエスケープ文字が無視される。
正規表現のように、たくさんのバックスラッシュを含むときに便利。

```
>>> print(r"That is Taro\'s cat.")
That is Taro\'s cat.
```

## 三連quoteによる複数行文字列 (6.1.1.4)

エスケープ文字`\n`でも文字列に改行を入れられるが、複数業の文字列をまとめて扱う場合は、三連quoteが便利。

```
>>> print("""Hello!
2nd line
    3rd line
    See you!
""")
Hello!
2nd line
    3rd line
    See you!
```

##  複数行コメント (6.1.1.5)

`#`で1行ずつコメントアウトできるが、まとめてコメントアウトしたい時には、三連quoteが使える。

```Python3:
def hogehoge():
    """
    This is the function to do hogehoge.
    You can execute the function by `hogehoge()`
    """
    print("Hello!")

hogehoge()
```

得られる出力は、
```
Hello!
```

## 文字列のなかに文字列を挿入する (6.2)

`%`演算子を用いて、文字列中のマーカーを後ろに並べた値に置き換えることができる。
文字列補完の利点は`str()`で数字を文字列に変換する必要がない点。

```Python3:
name = "Taro"
age = 20
print("My name is %s. I am %d years old." % (name, age))
```

得られる出力は、
```
My name is Taro. I am 20 years old.
```

さらに、Python3.6以降では、**f文字列**が使えるようになった。
その場合は、`%s`ではなく、`{}`をつかってその中に式を直接かく。
raw文字列のように、引用記号の前に`f`をつける。

```Python3:
name = "Taro"
age = 20
print(f"My name is {name}. Next year, I will be {age+1}.")
```

得られる出力は、
```
My name is Taro. Next year, I will be 21.
```
kotlinでヘッダーなしのcsvをPOJOにマッピングしたい

`build.gradle`に依存関係を追加(**バージョンは必ず揃えてください**)

```build.gradle
dependenies{
  implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.15.1"
  implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.15.1"
}
```

クラスを定義します。
`@JsonPropertyOrder`を宣言しないと、csvの要素をアルファベット順の項目にマッピングしようとします。

```Customer.kt
@JsonPropertyOrder("id", "name", "age")
data class Customer(
    val id: Int,
    val name: String,
    val age: Int,
)
```

Javaと異なり、`registerKotlinModule`を行う必要があるので、注意。

```hoge.kt
fun hoge(){
    val mapper = CsvMapper().registerKotlinModule()
    val csv = "1234,Taro,23\n2345,Jiro,35"
    val customers = mapper.readerFor(Customer::class.java)
        .with(CsvMapper().schemaFor(Customer::class.java))
        .readValues<Customer>(csv)
        .readAll()
    println(customers)
}
```

以上で、CSVをPOJOへマッピングできました。
脆弱なセッション管理が起こすインシデントの仕組み（webセッションについて２）

前回、[WEBアプリケーションにおけるセッション管理（１）](https://qiita.com/Kosuke0906/items/45bdef6efae3797a2d2f)ではセッションが何故必要なのかを学習をして来ました。

この記事ではシステム要件定義者や各企業WEB担当者に向けたアーキテクトの基礎について学習していく記事になっています。

またエンジニア経験者でもっと自分ができる事を増やしたい方、若しくは全くの未経験の方でも学べる様に分かりやすく解説して行きます。


## １、セッションが企業やサービスにもたらす危機的なダメージ

前回の記事ではセッションとしてどんなデータを保持するのかで終わりました。

・取り組み中の業務データ
・ログイン情報

上記のデータ管理の仕方で重大な事件を引き起こす恐れがある事をお伝えします。

### １−１、セッションの盗難によるインシデント
インシデントとは事故のことです。

![Screenshot 2023-05-26 at 15.57.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/806bc827-002c-c5f5-a52b-46033dd57d92.png)

ここで盗まれるのがcookieに格納されたセッションになります。

このセッションをクラッカーが自分の通信に乗せてサーバーにアクセスをすれば、ログインが出来てしまいます。

![Screenshot 2023-06-04 at 17.11.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/dc042470-78c2-16ac-6e11-0e725dd7ed5f.png)

クラッカーがユーザーのセッションIDを使うことによって個人情報の流出が起こってしまいます。

またセッションIDはChromの検証ツールで確認が出来ます。
![Screenshot 2023-05-30 at 20.30.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/221206fb-3f86-9a3d-c2f0-e820308c0e03.png)

セッションIDは赤く塗りつぶしている部分になります。

検証ツールでのセッション確認の仕方はこちらから確認してください。
（ページ作成中）

### １−２、セッションの管理が招く性能の低下

一つのアプリケーションはスケールアウトと言ってサーバーを複製して性能アップを図ることがあります。

![Screenshot 2023-06-04 at 17.33.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/207c77fd-370d-fb0e-f535-43ae5b110942.png)

サーバーを複製してアクセスを分散させます。

![Screenshot 2023-06-04 at 17.36.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/d8cf1463-3c02-dd0c-eec6-8b78fcee6ca0.png)

そこで発生する問題は、セッションの管理の仕方によってアクセス時の負荷が増えてしまうと言う点です。

![Screenshot 2023-06-04 at 17.46.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/9aca81fc-4cc3-4259-3d71-e61e46e9f1df.png)

セッションをサーバーで管理する場合、各サーバーでセッションのレプリケーションが必要になります。

それがボトルネックになり性能の向上が妨げられと言う状況です。

![Screenshot 2023-06-04 at 17.49.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/2354d9e9-eff1-bfda-7e72-ac2cc7d81823.png)

### １−３、まとめ

![Screenshot 2023-06-04 at 17.58.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485403/9c6df7a3-5b2a-bd93-33b5-70f6c700d15e.png)

## このセッションでのまとめ問題
・セッションが漏れることによって個人情報が漏れる仕組みは？
・サーバーアクセスの負荷低減で取り組むサーバーの複製をなんて言う？
・セッションをAPサーバーで管理することによって生じる負荷を説明してください。

ぜひ質問や聞いてみたいことがあればコメントを貰えると嬉しいです。

次は今日説明した問題を解決するためのセッション管理を学んで行きます。
（インシデントを避けるセッション管理方：作成中）
___

この記事のソフトウェアエンジニアリングに関わるすべての人の最低限の知識のトップページは以下のURLになります。
[（改良中）ソフトウェアエンジニアリングに関わる全ての人の最低限の常識を再度学習してみた（１）](https://qiita.com/Kosuke0906/items/e4718c024eb0d077dc1a)
Raspberry PiでのIPアドレスの固定化

# はじめに
**Raspberry Pi**を初めて使う方に向けて、IPアドレスの固定化の方法を解説します。固定化することで、常に同じIPアドレスからRaspberry Piを操作できるようになり、使いやすさが向上します。また、ルーターのIPアドレスの確認方法も合わせて説明します。

# 1.Raspberry PiでのIPアドレスの固定化方法
まずはじめに、使用しているネットワークインターフェースを確認します。Raspberry Piのターミナルを開き、`ifconfig`と入力します。すると接続されているネットワークインターフェースの一覧が表示されます。有線接続の場合は"eth0"、無線接続の場合は"wlan0"がそれに該当します。

その後、IPアドレスの固定化の設定を行います。以下の手順に従ってください：
1.1. `sudo nano /etc/dhcpcd.conf`と入力し、dhcpcd設定ファイルを開きます。
1.2. ファイルの中には以下のような記述があります。
```
# Example static IP configuration:
#interface eth0
#static ip_address=192.168.0.10/24
#static routers=192.168.0.1
#static domain_name_servers=192.168.0.1
```
1.3. 固定IP設定を有効にするためには、これらの行の先頭から'#'記号を削除します。'#'記号はその行がコメントアウト（無効化）されていることを示しています。

1.4. `"interface"`の後ろの`"eth0"`をあなたのネットワークインターフェース名に書き換えます。先程確認した`"ifconfig"`コマンドで表示されたものを使います。

1.5. `Ctrl+X`を押し、`Y`を押し、最後に`Enter`を押して変更を保存し、エディタを終了します。

1.6. Raspberry Piを再起動して新しいネットワーク設定を適用します。`sudo reboot`と入力します。

# 2. ルーターのIPアドレス（ローカルネットワークのゲートウェイアドレス）の確認方法
ルーターのIPアドレスはネットワークのトラブルシューティングに有用です。その確認方法は以下の通りです：

2.1. Raspberry Piのターミナルを開きます。
2.2. `route -n`と入力します。
2.3. 表示される結果の中の`"Gateway"`と書かれた列がルーター（ゲートウェイ）のIPアドレスを表しています。

# まとめ

この記事では、初心者でも簡単にRaspberry PiのIPアドレスの固定化とルーターのIPアドレスの確認ができる方法を解説しました。これにより、Raspberry Piの利便性と安定性がさらに向上します。

私の経歴は[こちら](https://qiita.com/yutut/items/c55e7a9fcb514f624172)のページで詳しく説明しています。PythonやRaspberry Piの利用で一歩進みたい方は、ぜひご覧ください。
brew install php@7.4とコマンド実行しても  Error: php@7.4 has been disabled because it is a versioned formula!と表示される

# 事象
zsh: command not found: phpエラーを解決するため、PHPをインストールしようとしましたが、
```
$ brew install php@7.4
```
とコマンド実行しても
```
Error: php@~ has been disabled because it is a versioned formula!
```
上記エラーが表示されました。

# 解決方法
```
$ brew install php
```
上記コマンドによって、Homebrewが利用可能な最新バージョンのPHPをインストールすることで、phpコマンドが使えるようになりました。
No application encryption key has been specified.を解決する[laravel]

# 事象
Laravelで環境構築している際、http://localhost:8888/ にアクセスすると、
'No application encryption key has been specified'
というエラー画面が表示されました。

![スクリーンショット 2023-06-04 17.07.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1092461/4038939b-17f0-51fc-263d-44554b0ffad3.png)

# 調査と試したこと
この記事を読む前に先にこちらの記事を参照されることをおすすめします。
https://qiita.com/tamakiiii/items/0a82ed09e8bced5cd898
https://qiita.com/ponsuke0531/items/197c76fcb9300d7c5f36

既存記事を参考にして、暗号化キーが未設定であることが直接原因のようだとわかり、
下記コマンドを実行するものの、色々とエラーが出てしまいました。
```
$ php artisan key:generate
```
エラー：
```
TypeError: Carbon\Carbon::setLastErrors(): Argument #1 ($lastErrors) must be of type array, bool given
Symfony\Component\ErrorHandler\Error\FatalError: Uncaught Whoops\Exception\ErrorException: Using ${var} in strings is deprecated, use {$var} instead
```
調べた結果、Composerを使用してCarbonライブラリの最新バージョンにアップデートした方がよいとのことで、
下記コマンドを実行。
```
composer require nesbot/carbon
```
それでも、同じようなエラーが出てしまいました。

# 解決方法
GUIから'Generate app key'を押下することで無事に暗号化キーを作成することができました。
FastReport プレビュー画面から印刷 or PDFエクスポートする

プレビュー画面から印刷 or PDFエクスポートする

## 印刷

  frxReport1.PrintOptions.ShowDialog := False;
  frxReport1.PrintOptions.Printer := ’ぷりんた名’;
  frxPreview1.Print;

  このときプリンタなどの設定は、frxReport1で行う。
  frxPreview1は、プレビューで使っているコンポーネント。

## PDFエクスポート

  frxPDFExport1.FileName := "ファイル名.pdf";
  frxPreview1.Export(frxPDFExport1);

  frxPreview1は、プレビューで使っているコンポーネント。


##
このページは、以前作成していたブログをQiita用に書き直したものです。
Delphiマイグレーション記録　VBReport

## VBReport

弊社オリジナル開発での使用実績はないが、他社が開発したもののマイグレーション案件で数社使用されていることが確認された。
VB-Report (ActiveX版)使用のプログラムを、Delphi2007へマイグレーションを実施。
サポートに連絡することにより、Delphi2007用パッケージファイルをもらうことができた。

こちらは、メーカーが今でもサポートしてくれているよう。
~~http://www.adv.co.jp/support/product/support_vb-report2007.htm~~
特に旧版で問題は出てなかったようだが、最新の、Dllを取得する。

(2017.1.11追記)
dllのバグ修正は、今も継続いるようです。
~~http://www.adv.co.jp/download/download-confrm.php?skey=54A&amp;ftype=U~~

(2023.6.4)
残念ながら、2023.6.4現在、サポートは終了した旨の記述を見つけた

## 終わりに
このページは、以前作成していたブログをQiita用に書き直したものです。
Delphiマイグレーション記録　GKit

## GKit SPREADSHEET

弊社オリジナル開発での使用実績はないが、他社が開発したもののマイグレーション案件で数社使用されていることが確認された。
Borland Edtionというのが提供されていたようだ。製品サイトを確認すると、DelphiVer6あたりまでサポートされていたようである。
(注：2023年時点このサイトは、なくなっていた）

このソフトを使ったは、システムのマイグレーション先は、Delphi2007であったので、次の方法で対応した。

このプログラムはActiveX(OCX)なので、ActiveX(OCX)からタイプライブラリを作成。
このタイプライブラリから、GKitを呼ぶことで対応した。
ただし、いくつかプロパティやメソッドの修正が必要となったり、実行時使えないものがあったので若干のソース修正が必要になった。
このあたりの確認は、生成された、タイプライブラリの確認が必要となる。

## 雑感

GKitの使用感は、高機能であるけど。。。費用（工数）の余裕があるなら、他のものに変えたほうが良いのかな。という感じ。
(これはマイグレーション時(2013年ごろ)の感想です)

## 終わりに
これは、以前作成していたブログをQiita用に書き直したものです。
内容はちょっと古いです。
[DOM操作] .append('テキスト') ←なぜテキストが直接入れられるのか疑問に思った


## はじめに
DOM操作の学習をしている際に、.appendの引数に渡せるものとしてオブジェクトとテキストが紹介されていました。　　
想定通りに動くのでいいのですが、なぜテキストはこんなにシンプルに渡せるようになっているのかが疑問に思っていました。


## 結論　　
先に結論としては、テキストで渡したとしても、内部でTextオブジェクトを作成して追加しているため、オブジェクトを引数に渡しているのと同じことだからでした。

## 確認

```html:index.html
<body>
    <p>パラグラフ</p>
    <script src="app.js"></script>
</body>
```

```js:app.js
const span = document.createElement('span');
span.innerText = 'span';

const p = document.querySelector('p');
p.append(span);

p.append('テキスト');
```


span要素のオブジェクトを.appendに渡すと、以下のようにブラウザに表示されます。
![s2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3340708/8d8c07ae-25d7-507f-a72f-6270d6347d5c.png)
このときのp要素をchromeのコンソールで確認してみます。  

```js  
const p = document.querySelector('p')
console.dir(p)

▼ p
accessKey: ""
align: ""    
...
childNodes: NodeList(3)
0: text
1: span
2: text
length: 3
[[Prototype]]: NodeList
...
```

childNodes内に追加されているのがわかります。

つまり、下記２つの方法は結果に違いはなく、それゆえ簡単な方法１が紹介されていたのですね。

```js
// 方法1 : 直接テキストを渡す
p.append('テキスト');

// 方法2 : オブジェクトにしてから渡す
const text = document.createTextNode('テキスト');
p.append(text);
```

ただ、Textオブジェクトに対して何か操作したい場合には、先にオブジェクトを作ることに意味が出てくるかと思うので、テキストはそのままで引数に渡すもの、と思わずに済んだのは良かったと思います。
新卒一年目エンジニア AWS JumpStart 2023 潜入レポート！

本記事は、2023 5/31~6/2まで開催されていたAWS JumpStart 2023に一年目の新米エンジニアが参加してきたレポートです。

 今回のAWS JumpStart 2023は大きく3つの構成で行われました。

- 講義パート
- ハンズオンパート
- アーキテクチャ検討パート 

の３つです。
***
ここから各内容を記載していきます。<br />
**講義パート**
講義パートでは、以下の内容を講義形式で学びます。（抜けてたらごめんなさい。。）
- [Amazon EC2](https://qiita.com/tiger3046/items/f12f40274210c2d0bf74)とは？
- [Amazon　ESC](https://qiita.com/tiger3046/items/5c82e1905cb06f0765e0)とは？（基礎的なコンテナ化とはという基礎的な内容を含む）
- ALBとは？ 
- Amazon Auroraとは？
- Amazon Lambdaとは？

実際にSA（ソリューション　アーキテクト）をされている方から、実例を踏まえて学べるので非常にわかりやすく濃い内容でした。

**ハンズオンパート**
講義パートでは、以下の内容を実際に手を動かしながら行います。（抜けてたらごめんなさい。。）
- Amazon ECS + [AWS Fargate](https://qiita.com/tiger3046/items/05a65a4cf4ca465f555d) +AWS RDS
- Amazon　ES2 + AWS RDS
- Amazon Lambda +AWS DynamoDB

上記には、記載してないですが、InternetGateWayやPublic Subnet、Private Subnet、SSMなどの設定も行います。

**アーキテクチャ検討パート**
　出されたお題に沿ってアーキテクチャ図を作成していきます。ここまでで学んだECSやFargate、RDSをDesign for Failure（単一障害点をなくす）の観点などをもとに冗長性やスケーラビリティー、さらにはトイル撲滅といった部分に配慮したアーキテクチャ設計を行なっていきます。最終日には、上記の内容に加えてAWS CodeBuildやAWS CodeDeployなどを使ったCI/CD設計など+αの内容を行なって行きました。
　講義やハンズオンがあったおかげで知識レベルの高い状態でこのパートに臨むことができました。そして、このパートを通してそれぞれのツールの仕組みの理解や私の属しているSaaSベンダーやWeb系企業などのクラウドを利用している事業者がどのようにユーザーにサービスをデリバリーしているのかを学べた濃い時間でした。

***

最後まで読んでいただきありがとうございました。
AWSの各サービスの概要を知らない状態から、自社のサービスではどのように活用できるのかという粒度まで考えられるようになるほど成長できた３日間でした。この研修を開いて下さったAWSのSAの皆様には感謝の念が尽きません。
上記のサービス（ECSやEC2など）の概要に関しては他の記事をアップする予定ですので、興味のある方がいらっしゃいましたら、是非ご覧下さい。
terraform importを使ってTerrafom管理化する

# はじめに
業務でGCPを使っているのですが、
すでに作成済みのリソースをTerraform管理化した際の流れをまとめます。


# terraform importの使い方
```
terraform import [リソースタイプ.リソース名] [取り込み対象のID]
```
IDに関しては公式ドキュメントの対象リソースのページの一番下に書かれています。

https://registry.terraform.io/providers/hashicorp/google/latest/docs

# 手順
以下のような手順でインポートすることができます。
1.　取り込み用のTerraformファイルの作成　
2.　`terraform import`コマンドでインポート
3.　`terraform plan`で差分確認
4.　差分があったらTerraformファイルを修正
5.　差分がなくなるまで`terraform plan`をする
6.　差分がなくなったら`tarraform apply`する
7.　stateファイルを確認して取り込まれたことを確認する

具体例として画面上から作成した`my_bucket_name`という名前のgcsのバケットを
Terrafom管理化する方法を以下にまとめます。

## 取り込み用のTerraformファイルの作成　
```tf:gcs.tf
resource "google_storage_bucket" "my_bucket" {
  name          = "my_bucket_name"
  location      = "asia-northeast1"
  force_destroy = true
}
```

## `terraform import`コマンドでインポート
```
terraform import google_storage_bucket.my_bucket my_bucket_name
```
参照：

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket#import

## `terraform plan`で差分確認
```
terraform plan
```

## `terraform apply`で反映
```
terraform apply
```

## sate確認
stateファイルの中身を確認して対象のリソースがあるかを確認します。
また、`terraform state list`を使うとTerrafom管理されているリソースの一覧を取得することができます。
UnityでGitHubからのAsset追加するときsshだとうまくいかない、ただしWindows

UnityでPackageManagerからGitHubで公開されているアセットを追加しようとしたら、エラーが出てできなかった。あまり同じ状態の人はいなさそうですが、少しでも参考になれば。根本的な解決方法があったら教えてください。

# 前提
* Windows 10
* Unity 2021.2.4f1（2020.3.22f1でも同じエラー）
* GitHubにsshを利用している

# エラー詳細
```
[Package Manager Window] Cannot perform upm operation: Unable to add package [https://github.com/xxxx/yyyy-zzzz.git?path=path/path/]:
  Error when executing git command. git@github.com: Permission denied (publickey).
  fatal: Could not read from remote repository.

  Please make sure you have the correct access rights
  and the repository exists.

  You may need to set up an SSH authentation agent
  like `ssh-add` or `Pageant` if your private key is
  passphrase-protected. [NotFound].
UnityEditor.EditorApplication:Internal_CallUpdateFunctions ()
```

```
[Package Manager Window] Error adding package: https://github.com/xxxx/yyyy-zzzz.git?path=path/path/.
UnityEditor.EditorApplication:Internal_CallUpdateFunctions ()
```

# 対応方法
結局色々試したがsshでの接続する際に権限を与える方法がわからず、最終的には一時的にsshでの接続にならないように.gitconfigに入れてあったinstedOfの設定を外して、httpで接続させることでエラーを回避した。

# 他にやったこと
## ssh-add
ssh-addしろとエラーにでているので以下はやってみた。

1. eval `ssh-agent`
2. ssh-add ~/.ssh/xxxxx.key
3. ssh-add -l

ssh-add -lして権限が追加できているところまで確認できたが、結局Unityを含め他のconsoleで開いた時もうまく権限を付与できていなかった。うまく行く時といかないときがあるのだが何が違うのかわからなった。

## バージョン変更
最初Unityのバージョン問題かと思って、2021、2020の両方で試したが、両方ダメだった。原因を考えたらそれはそうか。

## Mac
同じような設定を入れているMacだとうまくいく。Windowsならではの問題なのか？
GitHub Codespacesのポートフォワーディング（Public指定）が面倒なとき


LINE Bot開発などをする際には開発サーバーをローカル起動させるだけではなく、起動したサーバーに外部のインターネットからリクエストをもらう必要があるため、ngrokなどでトンネリングする必要がありました。

GitHub Codespacesを使うことで、開発環境自体がクラウドになるためローカルPCのトンネリングは要らず、ボタンを押すだけで公開状態のサーバーを作ることができます。

...が

## 毎回Publicに変更するのが面倒

`node app.js`などでプログラムを起動させた際にローカルサーバーを起動すると、GitHub Codespacesが自動的にアドレスを発行してくれます。このURLをLINE Bot開発の際には管理画面のWebhook URLのアドレスとして利用します。

> `https://n0bisuke-xxxxxx-xxxxxx-xxxxx-3000.preview.app.github.dev`のようなURLが発行されます。
> ![](https://i.gyazo.com/0a58adad7c45bd80ed2be320ab25306d.gif)

ただこの際に、 
**`右クリックでメニュー表示 -> ポートの表示範囲 -> Publicを選択`を毎回やらないといけません。**

ローカルサーバーのプログラムを起動した際に自動で立ち上がるフォワーディング（ポート転送）の設定が毎回Privateがデフォルトになっているため、コードを直した際に毎回これをやらないといけません。

**クソ面倒ですね。**

> ![スクリーンショット 2023-06-04 16.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/57f7f190-1d65-7773-438e-fc10ffd9b7a9.png "スクリーンショット 2023-06-04 16.32.59.png")

## 自動転送ではなく自身で指定することで回避

`ポートの追加`を自身で一度設定しておくことで回避できました。
（デフォルトをPublicにするような設定もどこかにありそうですが今の所調べられてません）

### プログラムを起動する前にポートを指定

`node app.js`などでプログラムを起動させる前に、ポートタブから`Forward a Port`のボタンを押し、`3000`などの数字を指定します。

> ![](https://i.gyazo.com/73532dba4a64dd662a28f91735fa93e2.gif)

そして`表示範囲をPublic`に指定しましょう。

> ![スクリーンショット 2023-06-04 16.45.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/991d4218-ad12-e70d-7ffc-6d9d813eb004.png "スクリーンショット 2023-06-04 16.45.27.png")

これをやることで、配信元の項目が`ユーザーによる転送`になります。

（ちなみにプログラムを先に起動させるやり方だとここが"自動転送"になっていて、自動転送だとプログラム編集のたびにPrivateに戻ってしまうようです。）

あとはプログラムを起動させればOKです。
このやり方だと **プログラムを修正して再起動してもURLはPublicになったまま**なので、毎回Publicにしなおさないといけない手間から解放されます。

## まとめと補足

結論としては、 **ポート指定を先にしてから、開発をしはじめると良い**です。

授業でよくこの辺を実施していて、ngrokを使っていた時代はngrokプログラムを起動しっぱなしで公開URLやその設定も変わらずだったので便利でしたが、インストールでそもそもこける人が多かったりしてトラブルが多いポイントでもありました。

最近はGitHub Codespacesでの開発にすることでトラブルは激減しましたが、意外と手間な部分もあるんだなと感じたのが今回でした。結構地味なポイントで気付きにくいポイントだったので実際に触ってみるのはやはり大事ですね。

サーバーもエディタ（VS Code）もGitやGitHub周りも統合された環境なので全て把握できるかというと難しいところはありますが、かなり便利なので使い方をもっと調べていきたいところです。

※ちなみにコードはこちらの記事で利用しているものを使っています。

https://qiita.com/n0bisuke/items/750b11b12269f9af20c1
【つくってみた】店舗ごとのシフト管理サービスをリリース

# 作ったもの
複数店舗のシフト管理サービス

https://smakerapp.com/

# 作った経緯
* 仕事では企画的なことやお客様との調整ごとが多く、開発することから離れつつあった
* 昔、学生時代にバイトしてた頃、シフトが紙媒体だったので、面倒だった
* 既存のシフト管理サービスは有料のものが多かったので、無料でサービス提供できないか試したかった

一番は単純に開発がしたかったのが大きかったですね。

# システム構成
## 構成図
![構成図.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181487/e14da490-2feb-c732-2f9e-810a5bbdd930.png)
結構、スタンダードな構成かと思います。

## 言語/ライブラリ
* JavaScript
* React
* Bootstrap
## 主要なAWSサービス
* Route 53
ドメインのDNSレコードの管理が出来るサービス。
CloudFrontにルーティングするために利用。
お名前ドットコムで取得したドメインを登録。
(AWSでもドメインは取得できますが、お名前ドットコムの方が安い気がします)
* Certificate Manager
SSL/TLS証明書を簡単に発行、管理できるサービス。
HTTPS通信を行うために利用。
ボタンをポチポチすれば、勝手にいい感じにやってくれます。
* CloudFront
CDN(Content Delivery Network)サービス。
HTTPS通信とコンテンツの配信のために利用。
OAC(Origin access control)でS3へのアクセスをCloudFrontに制限する。
以前はOAI(Origin access identity)というやり方がありましたが、今はOACでやることが推奨されているようです。
* S3
ストレージサービス。
Reactでビルドしたフロントの資材を配置。
Webサイトとして利用する際は単体ではHTTPS通信が出来ないので、CloudFrontと併用。
静的ウェブサイトホスティングを無効のまま、CloudFrontからの通信を許可するバケットポリシーを定義します。
* Cognito
ユーザーの認証/認可が素早く構築可能なサービス。
ユーザーを作成した際にメールで自動通知が可能です。
API Gatewayの認可として利用。
* API Gateway
APIの作成および諸々の管理が出来るサービス。
lambdaと組み合わせて、APIを構築するために利用。
店舗を管理する管理者と一般ユーザで出来ることが異なるので、認可処理を組み込めます。
* lambda
プログラムを定義しておき、サーバーレスで実行できるサービス。
アプリケーションのメインとなる処理部分の構築で利用。
前回の実行から時間が経つと、待機状態になるため、タイムアウトの設定は考慮する必要があります。
* RDS
データベースのセットアップ、運用、およびスケールを簡単に行うことのできるマネージド型サービス。
シフト関連情報を保持するために利用。 

# 機能
* 店舗管理
* 従業員管理
* シフト管理
* シフト作成
* シフト参照

こだわったところはシフトの描画のところで、マウス操作でシフトの開始、終了時間を変更出来るようにしました。
描画はJavaScriptの「canvas API」を利用しています。

# 苦労したところ
フロントエンドについては、あまり詳しく無いので、常に調べながら作成してました。
特にデザイン部分は奥が深く、もっと勉強が必要だなと思いました。

# 終わりに
さすがクラウドは本番環境に反映、公開までがとても早いと感じました。
AWSの各サービスを利用方法はググれれば出てきますし、とても便利な世の中になったなと実感しています。
また、サービスとしてはまだ、改善の余地や機能の拡充はあると思いますので、これから引き続き、作っていこうと思います。

https://smakerapp.com/
【Java】 HashSetの使い方ガイド | 初心者向けチュートリアル

# はじめに
HashSetはJavaのコレクションの一種で、重複のない要素の集まりを表現します。
配列に似ていますが、順番を持たないため一意の値を入れることしかできません。
たとえば、果物の種類を格納する場合は、重複する要素は自動的に取り除かれることが大きな特徴です。

## HashSetの基本的な使い方

HashSetを使用するために必要なimport文を追加し、インスタンスを生成します
```java
import java.util.HashSet;
import java.util.Set;

class Sample {
    public static void main(String[] args) {
      
       //String型の要素を格納するHashSetのインスタンスを作成する場合
       //Set<型> 変数名 = new HashSet<型>();
      Set<String> set = new HashSet<String>();
    }
}
```
###  要素を追加する
```java
Set<String> set = new HashSet<String>();

set.add("apple");
set.add("banana");
set.add("orange");

//例外は発生しないが、すでに値が保存されているため追加で保存されない
set.add("banana");
```
ashSetは重複する要素を自動的に削除します。つまり、同じ要素を複数回追加しても最終的には1つの要素しか残りません。

### 要素の存在を確認する
```java
// 指定値が存在すればtrueを返却する
// 指定値が存在しない場合falseを返却する

if (set.contains("apple")) { 
    System.out.println("HashSetにはappleが含まれています。");
}

```
### コレクションの中身を一括で複数確認する
```java
Set<Integer> set = new HashSet<Integer>();
set.add(1); // [1]
set.add(2); // [1, 2]
set.add(3); // [1, 2, 3]
set.add(4); // [1, 2, 3, 4]
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
// [1, 2]の全てが含まれています
set.containsAll(list); // true
// listに要素を追加
list.add(150);
// [1, 2, 150]の内、100が含まれていません
set.containsAll(list); // false
```

### 要素を削除する
```java
set.remove("banana");
```

### 配列に変換する
```java
Set<Integer> set = new HashSet<Integer>();
set.add(1); // [1]
set.add(2); // [1, 2]
set.add(3); // [1, 2, 3]
// 配列に変換して返却します
// set.sizeはHashSetに保存した要素の数を返します。
Integer[] array = set.toArray(new Integer[set.size()]); // {1, 2, 3}
```

### 要素を保持しているか確認する
```java
Set<Integer> set = new HashSet<Integer>();

//要素を保持しない場合はtrue
set.isEmpty(); // true

//保持している場合はfalse
set.add(100);
set.isEmpty(); // false
```
### 拡張for文による繰り返し
```java
Set<String> set = new HashSet<String>();

set.add("apple");
set.add("bananas");
set.add("grapes");

// { }内の処理に入る度にvalueに要素が代入されます
// HashSetは順番を持たないため、実行するたびに順番は前後する場合があります

for (String value : set) {
    System.out.print(value + " ");
}

// 出力結果　bananas grapes apple
```

### forEach文による繰り返し
```java
Set<String> set = new HashSet<String>();
set.add("apple");
set.add("bananas");
set.add("grapes");

// valueに要素が入る
set.forEach(value -> {
    System.out.println(value);
});

// 出力結果
// apple
// bananas
// grapes

```

## まとめ

HashSetは重複要素のない集合を扱うためのコレクションです。
重複要素を自動的に削除するため、必ず一意の要素のみを格納することができます。
また、高速なデータ操作が可能ですが、要素の順序は保証されません。

詳細な使い方や応用的な使用例については、記事を通じて詳しく解説しています。お役に立てれば幸いです。
EC2 増え続けていく、見えないストレージ容量

## 現象
1. しばらくすると容量が100%で、ファイル・ディレクトリの作成などのコマンド実行時に以下のエラー

```
No space left on device
```
1. 不要なファイルを削除しても、1週間ほどでまた容量が100%に達する。

## 結論
プロセスが、削除済みのファイルをつかんでいる。
以下のコマンドで、削除済みのファイルに絞り込んで検索できます。
```
# lsof -| grep deleted
```

### 原因
今回の場合、ログローテーション後のhttpd再起動コマンドの記述ミスです。
ローテーションによって削除されたファイルにhttpdがログを書き込み続けている。

以下で、一旦消えますが、再起動コマンドの修正をしないとまた100％に達します。

```
# service httpd reload
```


## 容量の確認方法
システム内の空き容量の確認

```
$ df -h 
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/nvme0n1p1  40G   40G   0   100% /
```

フォルダ容量確認
```
$ du -h /
~ ~ ~ ~
20G	.
```

ん、、20GB なのに、100%???

du と df の結果が違う。。

## 原因
ログローテーション設定ファイルの、httpd再起動コマンドの修正
私が担当する前にサーバーの移行作業があったようで、
OSのバージョンアップに伴い、再起動コマンドの書き方が変わっていました。

が、容量がいっぱいになるまで誰も気が付かず100%に。という状態です。

## 対処法

・httpdの再起動後、ログローテション設定ファイルを書き直し。

## 修正後の確認事項
今回の場合は以下の項目を確認し、問題なければ大丈夫だと思います。

* ログローテーションファイルに記載したhttpd再起動コマンドで、httpdが再起動されることを確認
* 容量の確認。
* ローテンション後の容量の確認。
【プログラミングクイズ】JavaScript オブジェクトフィルタリングの問題

# 問題
あなたは次のような構造を持つ配列を操作することになりました。


```js
const categories = [
  {
    categoryName: 'Fruits',
    isDisplay: true,
    subCategories: [
      {
        subCategoryName: 'Apples',
        isDisplay: true
      },
      {
        subCategoryName: 'Bananas',
        isDisplay: false
      }
    ]
  },
  {
    categoryName: 'Vegetables',
    isDisplay: false,
    subCategories: [
      {
        subCategoryName: 'Carrots',
        isDisplay: false
      }
    ]
  },
  {
    categoryName: 'Dairy',
    isDisplay: true,
    subCategories: []
  }
];
```

この配列から、isDisplay: true のカテゴリとそのサブカテゴリだけを抽出した新しい配列を作成する関数を作成してください。
ただし、カテゴリが isDisplay: false の場合、そのサブカテゴリも非表示とみなします。

## ルール
- 配列やオブジェクトの元の構造は維持すること。
- 元の配列やオブジェクトは変更しないこと。

## 期待する出力結果
```js
[
  {
    categoryName: 'Fruits',
    isDisplay: true,
    subCategories: [
      {
        subCategoryName: 'Apples',
        isDisplay: true
      }
    ]
  },
  {
    categoryName: 'Dairy',
    isDisplay: true,
    subCategories: []
  }
]
```

# 回答例
```js
function filterCategories(categories) {
  return categories
    .filter(category => category.isDisplay)
    .map(category => {
      return {
        ...category,
        subCategories: category.subCategories.filter(subCategory => subCategory.isDisplay)
      };
    });
}

console.log(filterCategories(categories));
```

### 処理の解説
基本的にfilterとmapを利用して問題解決を行なっています。

1.最初の filter() メソッドは配列 categories から isDisplay プロパティが true のカテゴリを抽出します。これにより、非表示のカテゴリは新しい配列から除外されます。

```js
categories.filter(category => category.isDisplay)
```

2.次に map() メソッドを用いて、上記のフィルタリングされたカテゴリそれぞれについて次の処理を行います。
```js
.map(category => {
  return {
    ...category,
    subCategories: category.subCategories.filter(subCategory => subCategory.isDisplay)
  };
})
```
この .map() メソッドのコールバック関数内では、スプレッド構文（...）と filter() メソッドを使って新しいオブジェクトを作成しています。
スプレッド構文を利用してオブジェクトを生成しているので、元のオブジェクトには影響を与えません。
【プログラミングクイズ】配列に登場する過半数を占める数字の出力(多数決アルゴリズム)

# 問題
あなたには配列が渡されます。その配列には必ず過半数（つまり、配列の長さの半分を超える）を占める数字が1つだけ存在します。配列に登場するこの過占数の数字を出力する関数を作成してください。

例えば、以下の配列が渡されるとします

```js
const nums = [2, 1, 1, 2, 3, 2, 2];
```
この場合、2を出力してください。

## ルール
配列の要素は正の整数です。
配列の長さは1以上で、必ず過半数を占める数字が1つ存在します。

# 回答例
## 過半数を超える数字を出力する方法
数字の登場回数をオブジェクトに記録して、過半数を占める数字を出力する方法です。

```js
const nums = [2, 1, 1, 2, 3, 2, 2];

function findMajority(nums) {
    const counts = {};
    const halfLength = nums.length / 2;

    for (let num of nums) {
        if (counts[num]) {
            counts[num]++;
        } else {
            counts[num] = 1;
        }
    }

    for (let num in counts) {
        if (counts[num] > halfLength) {
            return Number(num);
        }
    }
    
    return -1;
}

console.log(findMajority(nums));  // 2
```

## 最も出現回数の多い数字を返す方法
過半数を占めると言うことは、もっとも出現回数が多いと言うことです。なので登場した数字でもっとも出現回数の多い数字を出力する方法です。

```js
const nums = [2, 1, 1, 2, 3, 2, 2];

function findMajority(nums) {
    const counts = {};

    for (let num of nums) {
        if (counts[num]) {
            counts[num]++;
        } else {
            counts[num] = 1;
        }
    }

    let majority = null;
    let maxCount = 0;
    for (let num in counts) {
        if (counts[num] > maxCount) {
            maxCount = counts[num];
            majority = Number(num);
        }
    }

    return majority;
}

console.log(findMajority(nums));  // 2
```

## 多数決アルゴリズムを使用する方法
最後に多数決アルゴリズムを利用する方法を紹介します。
多数決アルゴリズムはBoyer-Moore投票アルゴリズムとも言われます。配列の中で過半数を占める要素を見つけ出す、まさに今回の問題にドンピシャで使えるアルゴリズムになります。

[多数決アルゴリズムの詳細](https://www.techiedelight.com/find-majority-element-in-an-array-boyer-moore-majority-vote-algorithm/)

これを知識として身につけておけば、配列の中で過半数を超える要素を出力するのに最も効率的な方法を取ることが出来ます。

```js
const nums = [2, 1, 1, 2, 3, 2, 2];

function findMajority(nums) {
    let count = 0;
    let candidate = 0;

    for (let num of nums) {
        if (count == 0) {
            candidate = num;
        }
        if (num == candidate) {
            count += 1;
        } else {
            count -= 1;
        }
    }

    return candidate;
}

console.log(findMajority(nums));  // 2
```

こちらのアルゴリズムは以下のように作用します。
アルゴリズムは以下のように動作します：

1. 最初に、配列の最初の要素を「候補」（candidate）として選択し、その出現回数（count）を1とする。
2. 次に、配列の次の要素を確認する。その要素が現在の候補と同じ場合、出現回数を1増やす。それが現在の候補と異なる場合、出現回数を1減らす。
3. 出現回数が0になった場合、次の要素を新たな候補とする。
4. これを配列の終わりまで繰り返す。
5. 配列をすべて見終わった時点での候補が、過半数を占める要素である。

---
以上が回答例になります。他にも効率の良い回答例があればコメントお待ちしております。
LaravelでのDuskテストのバッチ処理と定期実行

## 記載していること
この記事では、Laravel Duskをバッチで利用する方法について説明する。
Duskは、ブラウザ自動化テストで、処理の仕方が決まっている。

https://qiita.com/yun-yzrh/items/3d995c83f0b58009c61f

このduskをコマンドで実行するように、定期的に実行する方法を記載した。

## 準備
Duskインストール
```
composer require --dev laravel/dusk
php artisan dusk:install
```

Duskテストの作成
```
php artisan dusk:make TestName
```

コンソールコマンドの作成
```
php artisan make:command RunDuskTestsCommand
```
app/Console/CommandsディレクトリにRunDuskTestsCommand.phpが作成される。


## 作成例
1.RunDuskTestsCommand.phpを編集
作成したコマンド内で、handleメソッドに、Artisan::call('dusk')などと記述してDuskテストを実行。
```php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;

class RunDuskTestsCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'run:dusk-tests';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Duskのテスト';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        //
        $this->info('Running Dusk tests...');
        Artisan::call('dusk');
    }
}
```

以下のコマンドが生成され、**php artisan list**で確認できる。
コマンドのファイル修正で、リアルに反映される。(Laravel5.4以降にそうなったらしい)
```
 run
  run:dusk-tests          Duskのテスト
```

以下のコマンドのバッチ実行で、**php artisan dusk**と同じ結果になる。
```
php artisan run:dusk-tests
```


※上記の手順をスケジュール登録して実行する場合は以下の手順を追加で行います。
2.スケジュールの設定
app/Console/ディレクトリにあるKarnel.phpに以下を追加
```
protected function schedule(Schedule $schedule)
{
    $schedule->command('run:dusk-tests')->daily();
}
```
ここでは schedule メソッド内に run:dusk-tests コマンドを daily として追加している。

3.crontab -eで以下を追加
path-to-your-projectは作成したプロジェクト
```
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

```

## まとめ
Laravelのバッチ処理処理機能を、dusk、スケジュール登録を例に記載した。
Vue.jsでfaviconとアイコンの画像を設定する方法

ChatGPTに聞いても解決できず自己解決したので、共有しておく

# 概要
Vue.jsでfaviconとアイコンの画像を設定する方法

# 条件
Node.jsのバックエンドアプリのディレクトリの直下にVue.js3のプロジェクトを配置している

# ディレクトリ構成
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601978/d5816a04-165e-e6e5-c3f9-6fe476476f00.png" width="60%">

# 結論
- 画像のパスを通す必要があった
- 以下の通りにしたらできた

## my-app/vue/vue.config.js
```js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  publicPath: '/vue/dist/'
})
```

## my-app/vue/public/index.html（ビルド前）
``` html
<link rel="icon" type="image/png" sizes="32x32" href="<%= BASE_URL %>favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="<%= BASE_URL %>favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="<%= BASE_URL %>apple-touch-icon.png">
```

## my-app/vue/dist/index.html（ビルド後）
``` html
<link rel="icon" type="image/png" sizes="32x32" href="/vue/dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/vue/dist/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/vue/dist/apple-touch-icon.png">
```

## my-app/app.js
``` js
app.use('/vue/dist/', express.static(__dirname + '/vue/dist/'));
app.use('/', indexRouter)
```

# つまづいた点
- 以下のコードだと、ビルド後のindex.htmlの中の画像のパスがhref="/favicon-16x16.png"になる。app.jsのapp.use('/', indexRouter)が適応されるのでパスが通らなった。
## my-app/vue/vue.config.js（修正前）
```js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  publicPath: '/'
})
```
## my-app/app.js（修正前）
``` js
app.use('/', indexRouter)
```
ChatGPTに高度な図を書かせる

# はじめに

@sakaki_developerさんの記事を参考にさせて頂き、ChatGPTで図を作成してもらっています！
MermaidJSを学び、高度な図形を描いてもらう方法がわかったので、共有したいと思います。


https://qiita.com/sakaki_developer/items/09babe95b7f32397dbe1

# 高度な図形作成

下記文章に、必要であればSubgraphを使用してくださいと付け足すだけです。

<b>上記の用語について、mermaidJSで図解して説明してください
必要であればSubgraphを使用してください</b>



以下を入力しました
```sh
AWS
- リージョン
- アベイラブルゾーン
- VPC
- サブネット

上記の用語について、mermaidJSで図解して説明してください
必要であればSubgraphsを使用してください
```

### 結果
```mermaid
graph LR
    AWS[AWS]
    subgraph "リージョン1"
        R1[リージョン1]
        subgraph "アベイラブルゾーン1"
            AZ1[アベイラブルゾーン1]
            subgraph "VPC1"
                V1[VPC1]
                subgraph "サブネット1"
                    S1[サブネット1]
                end
                subgraph "サブネット2"
                    S2[サブネット2]
                end
            end
        end
        subgraph "アベイラブルゾーン2"
            AZ2[アベイラブルゾーン2]
            subgraph "VPC2"
                V2[VPC2]
                subgraph "サブネット3"
                    S3[サブネット3]
                end
            end
        end
    end
    AWS --> R1


```

```scss
graph LR
    AWS[AWS]
    subgraph "リージョン1"
        R1[リージョン1]
        subgraph "アベイラブルゾーン1"
            AZ1[アベイラブルゾーン1]
            subgraph "VPC1"
                V1[VPC1]
                subgraph "サブネット1"
                    S1[サブネット1]
                end
                subgraph "サブネット2"
                    S2[サブネット2]
                end
            end
        end
        subgraph "アベイラブルゾーン2"
            AZ2[アベイラブルゾーン2]
            subgraph "VPC2"
                V2[VPC2]
                subgraph "サブネット3"
                    S3[サブネット3]
                end
            end
        end
    end
    AWS --> R1


```


# 最後に
以上、高度な図の作成方法でした。
他に方法などあれば教えてください！！
cscの作法 その334

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
datagridviewで右詰めせよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/38f1279d-b608-cb9a-2594-9f60a120c40a.png)


# サンプルコード

```
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing;
using System.Data.OleDb;
using System.Data;

class form1: Form {
	DataGridView dataGrid1;
	TextBox bo1 = new TextBox();
	form1() {
		Text = "DataGridView";
		ClientSize = new Size(500, 300);
		dataGrid1 = new DataGridView();
		dataGrid1.Location = new Point(50, 50);
		dataGrid1.Width = 400;
		ClientSize = new Size(600, 400);
		bo1.Location = new Point(150, 20);
		Controls.AddRange(new Control[] {
			bo1,
			dataGrid1
		});
		dataGrid1.ColumnCount = 3;
		dataGrid1.Columns[0].HeaderText = "ID";
		dataGrid1.Columns[1].HeaderText = "商品";
		dataGrid1.Columns[2].HeaderText = "個数";
		dataGrid1.Rows.Add(new Object[] {1, "みかん", 100});
		dataGrid1.Rows.Add(new Object[] {2, "りんご", 300});
		dataGrid1.Rows.Add(new Object[] {3, "バナナ", 200});
		dataGrid1.Rows.Add(new Object[] {4, "すいか", 300});
		dataGrid1.Rows.Add(new Object[] {5, "いちご", 200});
		dataGrid1.Rows.Add(new Object[] {6, "メロン", 100});
		dataGrid1.CellEnter += new DataGridViewCellEventHandler(dgvControl_CellEnter);
		dataGrid1.Columns[0].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
		dataGrid1.Columns[2].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
	}
	void dgvControl_CellEnter(object sender, DataGridViewCellEventArgs e) {
		DataGridView grid = sender as DataGridView;
		Console.WriteLine(grid[e.ColumnIndex, e.RowIndex].Value.ToString());
		bo1.Text = grid[e.ColumnIndex, e.RowIndex].Value.ToString();
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}

```


以上。
WSL2 Ubuntu22.04 で GUIを使用するpython開発環境を構築

WSL2で、GUIへの出力もする開発作業をpythonで始める人向け。


# WSL2セットアップ
省略。
MicrosoftStoreでUbuntu22.04をインストールし、Ubuntuを起動

# Ubuntuにpythonをセットアップ
Ubuntu22.04ならばPython3.10がデフォルトでインストールされている。
ためしにHelloworldを実施



# GUIを使用するための環境構築
Xserver(windows上で表示するためのアプリ)をWindowsに導入することで、WSL上で実行したGUIがwindowsに表示されるようにする。
以下のページを参考にした。
 https://stackoverflow.com/questions/43397162/show-matplotlib-plots-and-other-gui-in-ubuntu-wsl1-wsl2

## VcXsrvを導入/起動
VcXsrvはXserverの一種。ほかにもお気に入りのものがあればそちらを。
以下のサイトからダウンロードし、windowsにインストールする。
https://sourceforge.net/projects/vcxsrv/

C:\Program Files\VcXsrv\xlaunch.exe を起動する。
以下の選択肢を指定してFinish。（ほかはたぶんお好み）
> Start no client
> Disable access control


## GUIが表示されるか確認
PythonでGUI画面を表示する処理を実行し、動作確認する。
他の方法でもよし。
以下、すべてubuntu側での操作

まずはpipが入っていなければインストール実施する。
```
$ sudo apt install python3-pip
<省略>

$ pip -V
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)
```

Tkinter(PythonでGUIを開発するためのライブラリ)を導入する。
```
sudo apt-get install python3-tk
```

Tkinterのバージョンを確認
```
$ python3
Python 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter
>>> tkinter.TkVersion
8.6
```

matplotlibをインストール
```
$ pip install matplotlib
```

環境変数を設定し、WSL2からVcXsrvに対して画面が出力されるようにする。
```
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0 export LIBGL_ALWAYS_INDIRECT=1
```

起動したら必ず設定されるように、bashrcに記載してもよい
```
$ vi ~/.bashrc

# 末尾に以下を登録して保存
# Show GUI to windows from WSL2
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0 export LIBGL_ALWAYS_INDIRECT=1
```

GUIにHelloWolrdと表示するPythonスクリプトを作成。
``` test.py
from tkinter import *

root = Tk()
a = Label(root, text ="Hello World")
a.pack()

root.mainloop()
```

`$ python3 test.py`でスクリプト実行。
以下のようなwindowが表示されたら成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547333/fd1414a6-e168-71e7-76e4-372b9278c82a.png)
リストのforループで頭に入れておくこと

paizaをやるにあたって覚えておきたいことをメモする

下記のコードはエラーが出てしまう


```Python
data_list = ['lion','tiger','cat','dog','human']

for i in data_list:
    print(data_list[i])
# TypeError: list indices must be integers or slices, not str

```

forループでinの次にリストを置いた場合、iはその要素そのものを表すため、わざわざリストを使い呼び出す必要がない

従って、

```Python
data_list = ['lion','tiger','cat','dog','human']

for i in data_list:
    print(i)
# lion
# tiger
# cat
# dog
# human
```

または

```python
data_list = ['lion','tiger','cat','dog','human']

for i in range(len(data_list)):
    print(data_list[i])
# lion
# tiger
# cat
# dog
# human
```
こうすることで表示できる
import hoge from @/hogeの@記号の理解と活用(パスエイリアス)

# 初めに

最近、ReactやTypeScriptのコードを見ていて、
```javascript
import hoge from '@/hoge'
```
のような形式のインポート文を見かけたり、フォルダ名が『@hoge』というプロジェクトを見ることがありました。
この@記号は一体何を意味しているのか、いまいち理解できていなかったので、わかりやすくまとめてみました。


# 結論
@は、パスエイリアス（Path Aliasing）と呼ばれるテクニックです。
特定のディレクトリへのパスを短縮したり、より読みやすくしたりするために使用されます。

実際に、使用方法を確認してみます。


### パス一覧

```
root
├─ @interfaces
│    └─ user.d.ts
├─ e2e
├─ src
│    ├─ utils
│    │   ├─ common
│    │   │   └─ common.ts
│    │   └─ user
│    │       └─ user.ts
│    └─ server.ts
└─ index.ts
```



src/utils/user/user.ts
```javascript:src/utils/user/user.ts
// タイプエイリアスがない場合
import { IUser } from "../../../@interfaces/user";
// タイプエイリアスがある場合
import { IUser } from "@interfaces/user";

export const isUsersNameJesse = (user: IUser): boolean => {
  return user.name === "Jesse";
};
```

src/server.ts
```javascript:src/server.ts
import express from "express";
import { message } from "./utils/common/common";

// タイプエイリアスがない場合
import { IUser } from "../@interfaces/user";
// タイプエイリアスがある場合
import { IUser } from "@interfaces/user";

const app = express();

app.get("/", (request, response) => {
  const user: IUser = { name: "Jesse", age: 31 };
  message("Sending User");
  response.send(user);
});

export default app;
```

特に前者の例（src/utils/user/user.ts）だと、
コードの記述を大幅に短縮することができるため、可読性が上がるのがわかると思います。

タイプエイリアス(@)を使わないと、コードは読みづらく、保守も困難になることがあります。これは、相対パスが長く、複雑になるためです。一方、絶対パスを使うと、ファイルの移動やリファクタリングが容易になります。相対パスを使うと、ファイルの位置が変わるたびにインポートパスも更新しなければならず、これがエラーを引き起こす可能性があります。

# ファイル名に@をつける理由

今回の例で言うと、 @interfaces ディレクトリのように一部＠がつくディレクトリを見かけることがあります。
これは、『このディレクトリはパスエイリアスに利用しています』と言うのを視覚的にわかりやすくするためのものであり、@をつけたからといって特になんらかの機能が付け加えられるわけではないそうです。
「コーディング規約の一種」と捉えて差し支えないそうです。


# パスエイリアスの設定方法

TypeScript、Webpack を例に見ていきます。

### TypeScript

jsconfig.json または tsconfig.json でパスエイリアスを設定

```javascript:tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "." ,
    "paths": {
      "@interfaces/*": ["@interfaces/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}
```

※TypeScript 4.1以降、"baseUrl" を明示的に設定する必要はなくなりました​。その場合、デフォルト値は tsconfig.json のあるディレクトリを参照します。

### Webpack
webpack.config.js でパスエイリアスを設定

```javascript:webpack.config.js
const path = require('path');

module.exports = {
  // その他の設定
  resolve: {
    alias: {
      '@interfaces': path.resolve(__dirname, '@interfaces/'),
      '@utils': path.resolve(__dirname, 'src/utils/')
    }
  }
};
```

今回は以上です。


















# 参考文献
https://betterprogramming.pub/how-to-configure-path-aliases-with-typescript-8586dc0aa214

https://qiita.com/tatsumin0206/items/fbcac2be2892ecbaec77
【Java】  重複しない配列を扱う|HashMapの使い方ガイド

# はじめに
HashMapはキーと値のペアを操作するためのコレクションを使用するためのAPIです。
この記事では、HashMapの基本的な使い方と操作方法について解説します。
初心者の方にも分かりやすく説明するため、具体的なコード例を交えながら説明します。

## HashMapとは
HashMapはキーと値のペアを格納するためのデータ構造です。
キーは一意であり、値と対応付けられます。これにより、効率的なデータの検索や取得が可能となります。

### HashMapの宣言と要素の追加
HashMapの宣言は以下のように行います。

```java
import java.util.HashMap; 
import java.util.Map;

// 任意の名称ででコレクションを作成します　今回は"map"にしてあります
Map<Keyのデータ型, 値のデータ型> map = new HashMap<Keyのデータ型, 値のデータ型>();

```

HashMapを使用する場合、Mapも同時にインポートする必要があります。
Mapを明示的に指定しない場合、コンパイルエラーが発生するため注意が必要です。

### コレクションの追加と上書き
```java
map.put("apple", "りんご");  // appleのキーにりんごのvalueがセットされる
map.put("grapes", "ぶどう"); // grapesのキーにぶどうのvalueがセットされる
map.put("apple", "林檎"); // すでに関連付けられていた場合は置換されます

// 置換専用のreplace()メソッドも有効です
map.replace("apple", "リンゴ");
```

### 値の取得
```java
String list1 = map.get("apple");  // りんごが返ってきます
String list2 =  map.get("grapes"); // ぶどうが返ってきます
String list3 =  map.get("orange"); // 存在しないキーの場合 nullが返ってきます
```

### キーの削除
```java
map.remove("apple"); // appleというキーの要素を削除します
```

## キーの一覧を取得する
```java 
import java.util.HashMap; 
import java.util.Map;
// Setをインポートする
import java.util.Set;


// 返り値は配列でいうところの[apple, grapes]のようになっています
Set<String> keys = map.keySet();
// 以下のような繰り返しも可能
for (String key : keys) {
    System.out.println(key);
    // 次のようにgetメソッドの引数としてkey指定を行い要素取得もできる
    // map.get(key);
}

/**
 * 出力結果)
 * apple
 * grapes
 */
```

## 要素数を取得する

```java
map.size(); // 今回の場合は"2"が出力される
```

## 要素が空か判定する

```java
Map<String, String> fruits = new HashMap<String, String>();
fruits.isEmpty();  // true
fruits.put("orange", "みかん");
fruits.isEmpty();  // false
```

## 繰り返し処理でキーと値を取得する

```java
Map<String, String> name = new HashMap<String, String>();
name.put("いしかわ", "石川");
name.put("たなか", "田中");
name.put("さとう", "佐藤");
// key, valueはput()メソッドの第一引数、第二引数が入る
name.forEach((key, value) -> {
    System.out.println(key + ": " + value);
});
/**
 * 出力結果)
 * いしかわ: 石川
 * たなか: 田中
 * さとう: 佐藤
 */
```

## まとめ

本記事では、HashMapの基本的な使い方について解説しました。
HashMapを宣言し、要素の追加や取得、削除、存在確認、要素数の取得などの基本的な操作方法について説明しました。

HashMapは、キーと値のペアを格納するための便利なデータ構造であり、様々な場面で活用されます。例えば、データのインデックスとしてキーを使用し、それに対応する値を効率的に取得することができます。

また、HashMapは他のデータ構造と比較して高速な検索が可能であり、大量のデータを効率的に管理することができます。

以上でHashMapの基本的な使い方の解説を終わります。

もし何か疑問点や追加の情報が必要な場合は、公式ドキュメントや他の参考資料も活用してください。
Rails でメモリが右肩上がりに増えて最終的に落ちるのでなんとかしてきた

# 解決策

puma_worker_killer を入れた
https://github.com/zombocom/puma_worker_killer

ひとことで言うと、worker を殺して回る gem
なので定期的にメモリを解放してくれる

# 手順

1.Gemfileに以下を追加します：

```ruby
gem 'puma_worker_killer'
```

2.Bundle installを実行します：

```bash
bundle install
```

3.Pumaの設定ファイル（通常は`config/puma.rb`）に以下を追加します：

```ruby
before_fork do
  require 'puma_worker_killer'

  PumaWorkerKiller.config do |config|
    config.ram           = 1024 # total RAM available
    config.frequency     = 5    # how often to check
    config.percent_usage = 0.98 # percent of RAM to use before killing
    config.rolling_restart_frequency = 12 * 3600 # 12 hours in seconds
  end
  PumaWorkerKiller.start
end
```

## puma_worker_killer の設定値の解説

`config.ram = 1024`: アプリケーションが利用可能なRAMの総量

`config.frequency = 5`: メモリの使用状況をどのくらいの頻度でチェックするか。5秒ごとにメモリ使用状況をチェックする。

`config.percent_usage = 0.98`: メモリの使用率がどの程度になったらワーカーを終了（kill）するか。メモリ使用率が98%に達したらワーカーを終了する。

`config.rolling_restart_frequency = 12 * 3600`: 定期的なワーカーの再起動を行う間隔。12時間ごとにワーカーを再起動する。

# 起こったことを時系列で

## ユーザーがいないサーバーが落ちる

render.com （ホスティングサービス）を使用してデプロイしたRailsアプリケーションが時間が経つと落ちるという奇妙な現象に遭遇しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516893/b8737e79-9ecf-f526-3542-cfeaf123fca0.png)

メモリ使用量が急落してきれいに崖になっている部分で落ちています。
リスタートがかかってメモリが解放されたようです。

## 調査

やったこと：
malloc というのが悪さをしているらしいので、MALLOC_ARENA_MAX=2 という環境変数を設定して監視してみる

結果：
うまくいかなかった。変化無し

やったこと：
mallocの代わりにjemallocを使ってRubyをコンパイル

結果：
サーバーは落ちなくなった。でもメモリ使用量が高いまま。
どうやら定期的に worker を再起動しているぽい。（なぜ jemalloc にして落ちなくなったのかは不明。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516893/774ebc15-6a7d-959f-8262-fd464e7a19d0.png)

やったこと：
puma_worker_killer を導入（冒頭の解決策、手順に同じ）

結果：
メモリ使用量めちゃくちゃ減った
これで一安心だけど、レスポンスは悪くなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516893/38067f62-f082-bb8f-5179-b25dba0015d8.png)


## 感想

worker 殺して回るのはちょっと抵抗あるけど調査難航しそうだし、パフォーマンスもそこまでシビアではないので当分はこれで凌ぐ予定