OmniAICreator/Qiita-1.07M huggingface dataset:
SAPとはそもそも一体どのようなシステムなのか？

### はじめに
わたくしが初めてSAP R/3に出会ったのは、2001年4月に棒医薬品メーカーでの導入に関わりました。
当時は受注や発注の処理がやっとExcelでできるようになり、少しでも作業者の手書きでの伝票作成の手間が省け、数式やマクロ処理で受注伝票や発注伝票ができるようになった時期、それがさらにシステムで簡単に数値を入力するだけで伝票作成が簡単に出来てしまうことに驚きを覚えた記憶は今でも忘れないです。
そこでまだ務めている会社でSAPを導入していても、実際にどんな目的に使うのかわからない事務作業を日々行っている方でも理解できるように、かみ砕いて説明してまいります。

### SAPとは
SAPは、ドイツに本社を置く世界最大のビジネスソフトウェア会社であり、ERP（Enterprise Resource Planning）ソフトウェアの開発で特に知られています。ERPとは、企業の経営資源を一元的に管理し、最適化するためのシステムです。SAPのソフトウェアは、企業のさまざまな業務を統合し、効率化を図ることができます。

### SAPの特徴
SAPの最大の特徴は、その包括性と拡張性です。SAPのERPソフトウェアは、財務、人事、製造、供給チェーンなど、企業のあらゆる業務をカバーしています。また、業種や業界によって異なるニーズに対応するためのソリューションも提供しています。さらに、SAPはクラウドサービスも提供しており、企業は自社のITインフラに依存することなく、必要なソフトウェアを利用することができます。

### SAPの導入メリット
SAPを導入することで、企業は業務プロセスの効率化や業績の向上を実現できます。また、経営資源の一元管理により、迅速な意思決定を支援します。さらに、SAPのソフトウェアは世界中の企業で広く利用されており、その信頼性と安定性は高い評価を受けています。

### SAPの導入デメリット
一方で、SAPの導入には高額なコストがかかることがデメリットとして挙げられます。また、導入には時間がかかり、適切な人材が必要となります。さらに、SAPのシステムは複雑であるため、運用や保守には専門知識が必要となります。

### 今騒がられている2027年問題
SAPの2027年問題とは、SAP SEが提供するERP（Enterprise Resource Planning）ソフトウェアのサポート終了問題を指します。具体的には、SAPの主要製品である「SAP ERP」のメインストリームメンテナンスが2027年に終了するという問題です。
SAP ERPは、企業の経営資源を一元的に管理し、業務効率化を図るためのソフトウェアです。製造、販売、会計など、企業のあらゆる業務を統合的に管理することができます。しかし、このSAP ERPのメインストリームメンテナンスが2027年に終了すると発表され、それ以降は延長サポートとなります。
延長サポートとは、メインストリームメンテナンス終了後に提供されるサポートで、一部のサービスが制限されます。具体的には、新機能の追加や法改正への対応などが行われなくなります。そのため、企業は新たなシステムへの移行を検討する必要があります。
この問題を解決するためには、SAPの新しいプラットフォーム「SAP S/4HANA」への移行が推奨されています。SAP S/4HANAは、従来のSAP ERPと比べて高速な処理能力を持ち、リアルタイムなビジネス分析が可能です。しかし、システムの移行は大規模な作業となるため、早めの準備と計画が必要です。
以上がSAPの2027年問題についての説明です。この問題を理解し、適切な対策を講じることで、企業のビジネス運営をスムーズに続けることができます。

まずはSAPの概要について記載いたしました。

【参考文献】
・SAPとは何か―IT初心者向けにわかりやすく【3分ぐらいで読めます】
https://it-biz.online/sap/overview/#toc1
・SAPコンサルブログ
https://tokulog.org/
windowsでUbuntuをインストールして、pythonを利用してみる。【環境構築】

<iframe width="560" height="315" src="https://www.youtube.com/embed/9uW_L1jOSxI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

## アプリケーションのインストール
まずはwindow storeから、`Ubuntu`を検索し利用するバージョンのUbuntuをインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/415daa2b-7851-ac29-cf8d-bf3c8cfdec64.png)

## ユーザネームとパスワード設定
インストールが完了しアプリケーションを立ち上げるとまずは、ユーザネームとパスワードの設定をする必要があります。パスワードを二回同じものを入力し、`y`を入力することで設定が完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/9a17a4a9-35c6-3d4c-13be-5cc9e21fc037.png)

## update/upgrade
立ち上げてまずはアップデートをしましょう。
```
sudo apt-get update
sudo apt-get upgrade
```
最初の`sudo`時はパスワードを聞かれますので、先ほど入力したパスワードを入力し`Enter`を押します。
次に`upgrade`するときは、`Y/n`と確認覚ますので`y`を入力しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/ce8eda9b-34a3-9a5e-8f89-e2924f8a3d40.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/ec053fd4-11e8-7b90-9e6b-f7f720416777.png)

## Pythonを起動してみましょう
先ほどのままだと上手くpython起動できないため、再度新しくターミナルを立ち上げバージョンの確認と、簡単なコマンドを入力する。
```
print("Hello Python")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/0ac44adc-6c7c-0511-dddd-65216dfd57cc.png)
※Ubuntuの古いバージョンでは、pythonをインストールする必要があったのだが、新しいubuntuはpythonをインストールする必要がないため、比較的に楽に利用できるようになった。

ターミナルから出るときは、`quit()`を利用しよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/4e3ebf75-810f-ea8c-2bee-6ab83dea6c94.png)

## pip のインストール
pythonを利用する優位性の一つであるライブラリは、pipを利用しなければならないが、
標準では入っていないため、コマンドでpipを入れましょう。
```
sudo apt install python3-pip
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/ad488cc3-a17b-9dff-97a3-343cd534db11.png)

`pip list`を入力し、ライブラリが利用できるようになったか確認しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/89b4af70-eedf-3ce4-c60c-8486560b009c.png)

## 最後に
現在の`python`を利用しようとすると、`python3`と入力する必要がある。
これが非常にめんどくさい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/f69067e1-65f7-ef5d-75ca-ada9efdb03c1.png)

`python`と入力するだけで`python3`が動作するようにします。
ここで利用するのは`alias`コマンドです。
`alias 【設定したい名前】=【実際のコマンド】`とするだけでこれが解決することができます。
今回の場合だと、以下の通りになります。
```
alias python=python3
```
実際の結果を見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/6da4cae6-bef6-d0ab-f481-61c5fb6b5e38.png)
簡単に実行できるので、Ubuntu利用してみたい方は是非試してみてね。
【AWS】Systems ManagerからLinux内のバッチを実行してみました

# 前書
AWSのSystems Managerを使えば、サーバー内に入らなくても、サーバー内のバッチを実行できることがとても魅力的です！！

なので、早速バッチを作成して、Systems Managerから実行していきたいと思います。

# バッチ作成
以下のバッチを作成しました。
このバッチを実行すると、バッチの実行したJST時間がログとして吐き出されます。

```batch
#!/bin/bash

timedatectl set-timezone Asia/Tokyo

current_date=$(date +"%Y-%m-%d %H:%M:%S")
echo "Hello world!! 実行時間：$current_date" >> test.log

```

# EC2の作成
詳細の作り方はこちらで省きますが、
- IAMロール：`AmazonSSMManagedInstanceCore`
- EC2 OS：`Amazon Linux 2`

上記で作ったバッチは、`test.sh`と名付けて、ssm-userのディレクトリに保存しておきました。
```ssh
sh-4.2$ pwd
/home/ssm-user
sh-4.2$ vi test.sh
sh-4.2$ sudo chmod +x test.sh
sh-4.2$ cat test.sh
#!/bin/bash

timedatectl set-timezone Asia/Tokyo

current_date=$(date +"%Y-%m-%d %H:%M:%S")
echo "Hello world!! 実行時間：$current_date" >> test.log
sh-4.2$
```


# Systems Managerから実行
「Systems Manager」->「Run Command」で`AWS-RunShellScript`を検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/b70aa16d-a09b-0ac3-42c5-cba9bbe6280b.png)

コマンドのパラメータで以下を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/5b9e5915-7b4f-4763-789c-91464c105fda.png)
```batch
whoami
cd /home/ssm-user/
pwd
/home/ssm-user/test.sh
cat /home/ssm-user/test.sh
cat /home/ssm-user/test.log
```

ターゲットに該当インスタンスを選択して、実行してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/b290d79a-79f6-8cb9-8d82-0c3782811218.png)

実行が完了したら、「出力の表示」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/f2b551bd-c12a-6138-f980-0832a93b8e09.png)

バッチが実行されたことを確認できました。
Systems Managerからバッチを実行時になんとrootユーザーを使っていることがわかりましたwww
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/61dadf9c-10ba-8985-4808-6edc439d0166.png)

念の為、サーバー内の`test.log`を確認し、同じログが吐き出された履歴を確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/6beacc98-35f2-1369-0c4e-24d1276c3583.png)
オブジェクト指向プログラミングの可読性の高い関数の作り方

# 概要
関数は便利な代わりに使い方を間違えると、ただ可読性が下がりバグの原因になる代物だったりします。

# 関数のメリット・デメリット
メリット
* 処理を共通化できる
* 関数レベルのテストが可能になる
* 可読性が向上する場合がある

デメリット
* 可読性が低下する場合がある

# 可読性を左右するポイント
可読性を左右するポイントは１つだけです。
* 呼び出し元が関数内の実装を知らずに扱えるかどうか

例を出すなら、誰しもオープンソースライブラリの関数を使っていると思いますが、
仮にその関数の実装まで把握する必要があったら、可読性が低いと感じると思います。

# 実装を知らずに扱える関数の特徴
1. 副作用がない
2. 関数名が機能を表している(動詞 or 動詞+名詞)
3. 適切なクラスに配置してある
4. 明確な引数

## 1. 副作用がない
薬の副作用と同じで、関数の主作用以外の作用のことです。


### 副作用の例
```C#
public List<Input> OrderByName(List<Input> inputList)
{
    inputList = inputList
        .OrderBy(input => input.Name)
        .ToList();
    
    return inputList;
}
```
この関数は順番を並び替えて応答する主作用のほかに、呼び出し元でも引数の値が変わってしまう副作用を持っています。<br>

:::note warn
よくある副作用は例に出したような、引数の値が変わってしまうことですが、
関数名が主作用を表していて、それ以外は副作用にあたります。
:::

## 2. 関数名が機能を表している(動詞 or 動詞+名詞)
関数とは動作のことで、動詞から始まらなければ不明確になります。
そしてどんな動作をするのかを使い手が予測できる明確な名前を付けます。

### 関数名の例
```C#
class UserService
{
    public UserRepository _userRepository;
    public UserCacheRepository _userCacheRepository;
    public void AddUser(User user)
    {
        _userRepository.Add(user);
        _userCacheRepository.AddUser(user);
    }
}
```
上記がユーザー追加の例だとわかるのは、関数名が適切に表現されているためです。<br>
関数名はクラス名と密接にかかわってくるため、今回のuserRepositoryのような責務が明確なクラスはAddUserでもAddでもユーザーを追加することがわかります。

## 3. 適切なクラスに配置してある
先ほどの関数名の例は関数が適切なクラスに配置してありましたが、
不適切なクラスに配置した場合は、動作が不明確になります。


### 悪い例、不適切なクラスに配置してある
```C#
class UserService
{
    public DeviceRepository _deviceRepository;
    public DeviceCacheRepository _deviceCacheRepository;
    public void AddUser(User user)
    {
        _deviceRepository.Add(user);
        _deviceCacheRepository.AddUser(user);
    }
}
```

## 4. 明確な引数
一部しか使わないのに、オーバーな引数を設定するのは、引数の設定にコストがかかり、関数の動作の勘違いに繋がります。

### 明確な引数の例
```C#
class UserService
{
    public UserRepository _userRepository;
    public UserCacheRepository _userCacheRepository;
    public void AddUser(User user)
    {
        _userRepository.Add(user);
        _userCacheRepository.Add(new UserCacheData()
        {
            UserId = user.Id,
            UserName = user.Name
        });
    }
}
```
UserクラスをそのままUserCacheRepositoryのAddに渡してしまうと、User情報全てがキャッシュされると読めてしまうため。<br>
仮にNameだけがキャッシュ対象の場合は引数で明確にすることが可読性を上げてくれます。

# まとめ
以上がオブジェクト指向プログラミングで関数の作り方でした。
読み手を意識した関数は自然とテストしやすい関数になると思います。
個人で使用していたgit-flowのやり方

##  概要
私が個人開発の時に使用する簡易的なgit-flowを簡単にまとめます。

## 初期コミット
1.GitHubからリポジトリをクローンします。
```terminal
$ git clone <リポジトリのHTTPS URL>
```

2.クローンしたリポジトリのディレクトリに移動します。
```terminal
$ cd <リポジトリのディレクトリ名>
```

3.エディタ（この例ではVS Code）を開きます。
```terminal
$ code .
```

4.空のコミットを作成します（最初のコミットとして。）。
```terminal
$ git commit --allow-empty -m "initial commit"
```

5.コミットをリモートのmainブランチにプッシュします。
```terminal
$ git push origin main
```

## 二回目以降のコミット
1.developブランチを作成します。
```terminal
$ git branch develop
```

2.developブランチに切り替えます。
```terminal
$ git checkout develop
```

3.コードの修正後、全ての変更をステージングします。
```terminal
$ git add .
```

4.コミットします。
```terminal
$ git commit -m "Completed develop"
```

5.リモートのdevelopブランチにプッシュします。
```terminal
$ git push origin develop
```

6.GitHubの画面でdevelopブランチからmainにプルリクエストを作成し、マージ。

7.その後、mainブランチに戻ります。
```terminal
$ git checkout main
```

8.リモートの情報を更新します。
```terminal
$ git fetch -p origin
```

9.リモートのmainブランチの最新情報をローカルにプルします。
```terminal
$ git pull
```

## まとめ
この方法はかなり簡易的な方法なので、場合によってgit-flowのfeatureブランチも追加して行うこともあります。
WSLのsystemdを動作させる（今は設定だけでOK！）

## WSLは今のところ？systemdが初期設定では動かない

最近WSLが大変便利でいいなぁと思って気に入っています。とはいえ実際のところWSLで開発の主要なテクノロジーは全部動くのか？が分からず、実際にやってみています。その第一弾として、MySQLをWSLのUbuntuで動かしたかったのですが、systemdが動作しないことに起因していろいろうまくいかずに結構はまってしまいました。最終的に解決したら手順はたいしたものではなかったのですが:sweat_smile:

## 結論。設定を変えれば動く。

結論としては、下記の記事の内容を実施すればsystemdが動作するようになります。

[Systemd support is now available in WSL!](https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/)

そんなにプロセスは多くないので問題ない方も多いかもしれませんが、一応上記は英語の記事ということで、下記に日本語で手順をまとめました。

**目次**
- [WSLのアップデート](#wslのアップデート)
- [WSLの設定変更](#wslの設定変更)
- [おまけ：カジュアルトークを受け付けています！](#おまけカジュアルトークを受け付けています)

## WSLのアップデート

Powershellで以下のコマンドを実行します。

```console
wsl --version
```

WSL バージョンが0.67.6以上でない場合、以下でWSLのアップデートを行います。

```console
wsl --update
```

## WSLの設定変更

/etc/wsl.conf に以下を追加します。

※sudoで編集しないと設定できないそうです。

```ini
[boot]
systemd=true
```

記事によると上記の後、一度WSLを終了させ、以下を実行して（おそらくバックグラウンドで動いているから？）WSLインスタンスを終了させてね、とのことでした。

```console
wsl --shutdown
```

その後、WSLを起動して以下のコマンドを実行すると、systemdが動いていることが確認できます。

```console
systemctl list-unit-files --type=service
```

これだけ！
WSL回りは結構アップデートが早く、少し古い記事を見ると以前はかなりいろいろやらないとやらないといけなかったようですが、現在はこれだけでOKです。WSLを使っている方は参考にしてみてくださいね。

## おまけ：カジュアルトークを受け付けています！

Musubiteというプラットフォームで、エンジニアのカジュアルトークを受け付けております。

https://musubite-job.com/recruitments/N9BLbViYgLz2

プラットフォーム自体、エンジニアの方にとってとても魅力的なものだと感じていますので、よろしければぜひのぞいてみてください！
Spring Bootで外部properties読み込み

### ファイルの階層
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2713217/2f807d2c-db23-b331-8fc1-e7fe410e86b7.png)

# ソース
```properties:some.properties
test01=HOGE
TEST02=22
```

```properties:application.properties
name="takeshi"
```

```java:ReadProperties.java
package com.example.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import lombok.Data;

// lombookの機能、ゲッターセッターtostring等をいい感じに作っといてくれる
@Data
@Component
@PropertySource("classpath:some.properties")
public class ReadProperties.java {

	@Value("${name}")
	private String name;

	@Value("${test01}")
	private String TEST01;

	@Value("${TEST02}")
	private String TEST02;

}

```
```java:SpringBootDemoApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class SpringBootDemoApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoApplication.class, args);
		ReadProperties bean = context.getBean(ReadProperties.class);
		System.out.println(bean.toString());
		context.close();
	}

}
```

### 実行結果
```
ReadProperties(name="takeshi", TEST01=HOGE, TEST02=22)
```


## Environmentを使って取得するパターン

https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/core/env/Environment.html

```java:ReadProperties.java
package com.example.demo;

import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import lombok.Data;

// lombookの機能、ゲッターセッターtostring等をいい感じに作っといてくれる
@Data
@Component
@PropertySource("classpath:some.properties")
public class ReadProperties {

	private final Environment env;
	
//	@Value("${name}")
	private String name;

//	@Value("${test01}")
	private String TEST01;

//	@Value("${TEST02}")
	private String TEST02;

	public void showProperties() {
		System.out.println(env.getProperty("name"));
		System.out.println(env.getProperty("test01"));
		System.out.println(env.getProperty("TEST02.a"));
	}
	
}
```

```properties:some.properties
test01=HOGE
TEST02.a=22
```

### 実行結果
```
"takeshi"
HOGE
22
```
[Java] Spring Bootで文字列を暗号化する方法

# はじめに

パスワードを保存するとき、そのままDBに保存することはセキュリティ観点から望ましくない。よって文字列を暗号化して保存したら、もしDBに不正アクセスされても２次被害を防ぐことができる。
Spring Bootで暗号化する方法をまとめる。


# Code
```build.gradle
  implementation 'org.springframework.security:spring-security-crypto:5.7.1'
```

```java:CommonConfig
@Configuration
public class CommonConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}
```


```java:AccountService.java
@Service
public class AccountService {

    @Autowired
    PasswordEncoder passwordEncoder;

    // 暗号化
    public String createEndocedPwd(String pwd) {
        String encodedPwd = passwordEncoder.encode(pwd);
        return encodedPwd;
    }

    // 暗号化されたあとのpw同士を比較する
    public boolean pwdMatch(String newPwd, String originPwd) {
        if (passwordEncoder.matches(newPwd, originPwd)) {
            return true;
        }
        return false;
    }
}
```


結果
`1234`  -> `{bcrypt}$2a$10$TawJl5916Xs6/LnwWjPdXOdwLwsQqMWv38XDLELNpP.W.RL5zV2sK`

暗号化され同じ文字列でも毎回異なる暗号を生成し、単方向暗号化であるため、暗号から元の文字列を推測することはできない。



# 終わりに
これで安心してDBにパスワードを保存できる。
WI-U2-433DHP をkernel-6.3 で使う

# 最新
kernel-6.7 になったせいか、build に失敗するようになった。

ネット検索でトップに現れたものに置き換えた所、問題なく利用できるようになった。
https://github.com/morrownr/8821au-20210708

付属の 8821au.conf に従って、
/etc/modprobe.d/8821au.conf
/etc/hostapd/hostapd.conf
を更新して利用している。


# 過去記載内容 (最終更新日 2023年08月19日投稿日 2023年06月24日)

WI-U2-433DHP に関して検索すると rtl8812au が多数引っかかるが、kernel-6.3 に対応したものは少ないようで、ビルドできなかった。
あるいはビルドできて、 insmod しても動かなかった。

https://github.com/ivanovborislav/rtl8821au

はきちんと動作した。

おまけに hostapd.conf の例も付随していた。
モジュール・ロード時のパラメータの記載もあり、快適に使えるようになった。

<h2>追記</h2>
最近は下記を実行しないと build できなくなった。
kernel-6.4 になったせいかな？
<br/>

```
pushd os_dep/linux
mv wifi_regd.c wifi_regd.c-
sed -e "s/REGULATORY_IGNORE_STALE_KICKOFF/1/g" < wifi_regd.c- > wifi_regd.c
popd
```
Orange Pi 5 を買って Ubuntu をインストールしてみました

Raspberry pi 400 を今まで使っていたのですが、もう少し速いSBCが欲しくなって
Orange Pi 5 を買いました

---
購入したもの
Orange Pi 5 16GB とACアダプタのセットをアメリカのAmazonで注文しました

Orange Pi 5 用ヒートシンクとケースのセットと32GB SDカードを日本のAmazonで注文しました

ディスクは ラズパイで使っていた USB接続のSSDとSDカードをセットで使います
私の持っている USB-SSD変換 ではブートできなかったので、少し工夫します
そのうちUSBブートができるようになると、勝手に思っています

---
https://github.com/Joshua-Riek/ubuntu-rockchip/releases
から　Download Ubuntu Desktop　の Orange Pi 5 をクリックしてダウンロードします
ubuntu-22.04.2-preinstalled-desktop-arm64-orangepi5.img.xz をSDカードに書き込みます

Orange Pi５ にSDカードをセットして、キーボード、マウス、ディスプレイ、LANを接続してからACアダプタを接続します


マウスカーソルがぐるぐる回って、そのうちセットアップの画面が表示されます
セットアップが完了してください

ターミナルから
sudo apt update
sudo apt upgrade
を実行して最新の状態にします

---
SSDの環境を準備していきます

https://github.com/Joshua-Riek/ubuntu-rockchip/wiki/Orange-Pi-5
の　Install the SATA bootloader to the SPI NOR flash　の手順に従って
sudo dd if=/lib/u-boot-orangepi-rk3588/rkspi_loader_sata.img of=/dev/mtdblock0 conv=notrunc 
sync
sudo sed -i 's/overlays=/overlays=sata /g' /boot/firmware/ubuntuEnv.txt
を実行し再起動します

https://github.com/Joshua-Riek/ubuntu-rockchip/releases
から　Download Ubuntu Desktop　の Orange Pi 5 をクリックしてダウンロードします
Filesを起動してダウンロードのフォルダーを開きます
ubuntu-22.04.2-preinstalled-desktop-arm64-orangepi5.img.xzのファイルがありと思います

SSDをUSB3.0のポートに接続します

ubuntu-22.04.2-preinstalled-desktop-arm64-orangepi5.img.xzをダブルクリックします
Restore Disk Image が表示され、SSDのディスク( /dev/sda )を選択します
Start Restoring を選択します
確認メッセージが表示されますので内容を確認して Restore を選択します
パスワードを入力します
書き込み完了までしばらく待ちます

/boot/firmware/ubuntuEnv.txt の最後の行が overlays=sata になっているか確認してください
なっていない場合は
sudo sed -i 's/overlays=/overlays=sata /g' /boot/firmware/ubuntuEnv.txt
を実行してください

---
再起動します
Ubuntuのセットアップ画面が表示されたら成功です
SSDのディスクがルートパーティションになっていると思います

この続きは
https://qiita.com/jibri/items/8fe2546ef45ef5567826
Windows(WSL)を使ったDocker環境構築（導入編）

# WSLの追加からDocker環境構築までの設定
- WindowsユーザのためのDocker環境構築
- windows環境
windows10, windows11


## WindowsにWSLを追加
- ドキュメント　https://learn.microsoft.com/ja-jp/windows/wsl/install
- コマンドプロンプトを起動
windowsの検索バーに「コマンドプロンプト」と入力しコマンドプロンプトで右クリックし管理者として実行し、下記のコマンドを入力
```
wsl --install
```
インストール終了後再起動を行います。
-  Ubuntu 20.04 LTSをインストール
下記のコマンドを入力し、インストールを行う
```
wsl --install -d Ubuntu-22.04
```
- ubuntuがインストールできているか確認を行う
「wsl -l -v」のコマンドを入力後、下記の表示されていれば成功です。
```
wsl -l -v

  NAME                   STATE           VERSION
* Ubuntu-22.04           Running         2
```
以上でwslの追加は終了です。

- Windowsのwindows の機能の有効化または無効化
windowsの検索バーに「windows の機能の有効化または無効化」を入力し選択してください。
- Linux用Windowsサブシステム
- 仮想マシンプラットフォーム
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323037392f35663832333066312d636236312d666663372d656565382d3235386165646131316233322e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3489096/94af037c-f6eb-6902-fc05-15ff164a9b50.png)


上記の2つにチェックをしOKを選択

- ターミナルのインストール
https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701?hl=ja-jp&gl=jp&rtc=1
上記のリンクからターミナルをインストールし、ターミナルを起動
ターミナルを起動したら、下記の選択からUbuntu 22.04 LSTを選択してください。
![スクリーンショット (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3489096/f74296b4-3e56-d796-a3f1-65ff9e942139.png)

- 初回アクセス時にユーザー名とパスワードを設定を聞かれるのでユーザー名とパスワードの設定を行ってください。
パスワードは今後も使うので忘れないように

以降Ubuntu 22.04 LSTのターミナルを使用して作業を行ってください

- ubuntuのアップデート
下記のコマンドを実行することでubuntuのアップデートができます。
念のため行います。sudo(権限)コマンドを使用しているためパスワードが聞かれるので先ほど設定したパスワードを入力してください。
```
sudo apt update
sudo apt upgrade
```
# Dockerのインストール
- https://docs.docker.com/desktop/install/windows-install/
上記のリンクから「Docker Desktop for Windows」をクリックしdockerのダウンロードを行ってください。
![スクリーンショット (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3489096/397498b2-280e-cb72-c641-d0df9efbefe7.png)
この画面が出ていたら成功です。

## Git導入
- 以下のコマンドを実行
```
sudo apt-get install git
```
- インストールの確認
以下のコマンドでバージョンが表示されていれば成功です。
```
git --version
```
- Gitの設定
以下のコマンドの'UserName'と'mail@example.com'に自身のGitの名前とメールアドレスを設定しておく
```
git config --global user.name UserName
git config --global user.email mail@example.com
```

- Gitの改行コード設定
以下のコマンドで改行コードの設定を行います。
```
git config --global core.autocrlf input
```
Linux環境ではLFが推奨されているのでinputに設定しておく

- Gitパーミッションを無視する設定
以下のコマンドでパーミッションを無視する設定を行います。
```
git config --global core.filemode false
```
パーミッションを無視する設定をすることでchmodなどで権限を変えた時にGitに差が上がるのを防ぐことができます。

- Githubのssh接続
「Github ssh接続」等で調べるとたくさん出てくると思うので割愛させていただきます。


以上でWindowsのWSLを使ったDocker環境構築は終了です。
windowsでDocker環境構築をしたい方の役に立てたら幸いです。

新たにWindows(WSL)を使ったLaravel10 × sail × Vue.js環境構築を投稿いたしましたのでLaravel10 × Vue.jsで開発を行いたい方は閲覧してみてくださると嬉しいですhttps://qiita.com/ys05181406/items/26d2d55f08d9b7b11f36
【iOS】USDZ形式の3DモデルをAR空間でアニメーションさせる方法

# はじめに
USDZ形式の3DモデルをAR空間でアニメーションさせる方法を紹介します。

# 作るもの
USDZ形式の3DモデルをAR空間でアニメーションさせます。

# デモ
https://twitter.com/shota_appdev/status/1672256564122783744?s=61&t=TT9faIzF-7RkZkDdboxHEg

# 準備
USDZ形式の3Dモデルを用意します。今回は、[Appleの公式サイト](https://developer.apple.com/augmented-reality/quick-look/)からダウンロードできる[Toy Drummer](https://developer.apple.com/augmented-reality/quick-look/models/drummertoy/toy_drummer_idle.usdz)を使います。
ダウンロードした3Dモデルは、Xcodeのプロジェクトに追加します。

# やり方

## コード全体
```swift
import SwiftUI
import RealityKit

struct ContentView: View {
    var body: some View {
        ARViewContainer()
            .edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer: UIViewRepresentable {
    func makeUIView(context: Context) -> ARView {
        let arView = ARView(frame: .zero)
        let filename = "toy_drummer_idle"
        let modelUrl = Bundle.main.url(forResource: filename, withExtension: "usdz")!
        let anchor = AnchorEntity(world: [0, 0, 0])

        arView.scene.addAnchor(anchor)

        if let modelEntity = try? ModelEntity.load(contentsOf: modelUrl) {
            modelEntity.scale = SIMD3<Float>(0.01, 0.01, 0.01)
            modelEntity.availableAnimations.forEach {
                modelEntity.playAnimation($0.repeat())
            }

            anchor.addChild(modelEntity)
        }

        return arView
    }

    func updateUIView(_ uiView: ARView, context: Context) {}
}
```

## 解説
### 3Dモデルを読み込む
```swift
let filename = "toy_drummer_idle"
let modelUrl = Bundle.main.url(forResource: filename, withExtension: "usdz")!
// ...
if let modelEntity = try? ModelEntity.load(contentsOf: modelUrl) {
    // ...
}
```
まず、3Dモデルを読み込みます。ModelEntity.load(contentsOf:)を使うと、3Dモデルを読み込むことができます。読み込んだ3Dモデルは、ModelEntity型のオブジェクトとして扱うことができます。

### 3Dモデルの大きさを調整する
```swift
modelEntity.scale = SIMD3<Float>(0.01, 0.01, 0.01)
```
3Dモデルの大きさを調整するには、scaleプロパティを使います。scaleプロパティは、SIMD3<Float>型のオブジェクトを持っています。SIMD3<Float>型のオブジェクトは、3Dモデルの大きさを表しています。SIMD3<Float>型のオブジェクトの各要素は、x, y, zの順に、3Dモデルの大きさを表しています。今回は、3Dモデルの大きさを0.01倍にしています。

### 3Dモデルをアニメーションさせる
```swift
modelEntity.availableAnimations.forEach {
    modelEntity.playAnimation($0.repeat())
}
```
ModelEntity型のオブジェクトは、availableAnimationsプロパティを持っています。availableAnimationsプロパティには、3Dモデルに含まれるアニメーションの一覧が格納されています。availableAnimationsプロパティの中身をforEachで回し、playAnimation(_:)を使ってアニメーションを再生します。

### 3DモデルをAR空間に配置する
```swift
let anchor = AnchorEntity(world: [0, 0, 0])
arView.scene.addAnchor(anchor)
// ...
anchor.addChild(modelEntity)
```
AR空間に3Dモデルを配置するには、AnchorEntity型のオブジェクトを作成し、addChild(_:)を使って3Dモデルを追加します。

# おわりに
AR空間で3Dモデルをアニメーションさせる方法を紹介しました。AR空間で3Dモデルをアニメーションさせることで、より臨場感のあるAR表現を実現できます。
Spring Boot Beanの動作確認メモ

mainの書き方忘れちゃうのでメモ

```java:BeanSample.java
package com.example.demo;

import org.springframework.stereotype.Component;

@Component
public class BeanSample {
	
	public void hello() {
		System.out.println("hello");
	}
	
}

```
```java:SpringBootDemoApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class SpringBootDemoApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoApplication.class, args);
		BeanSample bean = context.getBean(BeanSample.class);
		bean.hello();
		context.close();
	}
}
```
飲食業界からキャリアチェンジして、開発業務について半年経過

# 本記事の目的

開発業務に携わって半年ほど経過したので、振返地点として記録を残すために書きました。

## 【エンジニアになる前】
元々はバリスタとして、店舗運営・立上げ/専門学校講師/バリスタ競技会審査員などを12年ほどしてきました。

東京オリンピックに向けて東京に店舗立上げ・トレーニング業務をしているなか、
コロナ禍を迎え度重なる緊急事態宣言を経て劇的に落ち込む売上や・守れない雇用・残ってくれたスタッフへの業務過多に悩む日々を過ごしていました、現状の思考法では頭打ちになることを明確に感じていました。

残ってくれたスタッフの作業軽減のためタブレットレジを導入し、大幅な業務改善に成功した時にシステム開発の存在を知り、色々と調べるようになりキャリアチェンジを考えるようになりました。


## 【テックキャンプを経てAI自社開発企業へ】
結論からいうとキャリアチェンジ後最初の企業は試用期間で退職しました。
担当した主な業務は
自社アプリの運用保守・大手メディア企業共同開発アプリ運用保守・AIカメラ開発の教師データ作成などでした。

ありがたいことに、企業からはこのまま一緒に働く選択肢を提示いただいたのですが
社長のあまりにも過度な対応(PC投げるなど)がどうしても受け入れることができず退職の道を選びました。

## 【32歳キャリアチェンジ後まさかの短期離職で再度就職活動】
幸い、相談できる人がいたので相談したり、
YouTubeで配信している転職エージェントの方にDMして履歴書等添削してもらったりして今の会社に入社することができました。
多くのかたに相談にさせていただき、おかげさまで10社以上から内定をいただきました。
趣旨とは違うため今回は詳細は割愛

## 【今の会社に入社】
入社初日から、テスターがばっくれたからと相談があり、
研修より先に初日から受託開発案件のテスターになりました。
その案件が2ヶ月ほどあり、終わってからJavaやSQLの研修がはじまりました。

## 【社内研修後】

### 別案件で受託運用保守している案件で開発業務にへ
初めてのエンジニアとしての開発業務でしたが・・・まず
> ・設計書の読み込みに苦戦
・設計書を読めないので実装のイメージもできない
・ER図などないのでこの機能を動かした時にどこのテーブルに影響があるのかイメージできない
・改修対象のインボイス制度がいまいちピンとこない
・つよつよエンジニアとからの引き継ぎ期間に私がコロナになり導入期間半減


などの壁に数ヶ月間大きくぶつかり続けました。
テスター案件時はER図があったのでなんとかイメージして作業できたのですが・・・

しばらく経って知ったのですが、受託案件で開発経験がしやすいため配属された人が多い案件ですが、何人もの人が挫折して退職してきた案件だとのことでした。

### まず苦戦したのは

> ・開発する機能が専門業界の業務改善ツールのため各機能が何の作業なのかイメージしにくい
・ER図などの可視化資料が少ないため、設計書か実装から解析するしか道がなかった
・クライアントからの支給PCのスペックの関係で、デバックがデプロイしないとできない
・ビルドに1時間ぐらい時間かかる
・ウォーターフォールだが、上流から下流まで基本的に1人でするため反復や整理より先に次の作業に入ることになる
・インボイス制度？？？？

などに苦戦しました。
未経験から開発に携わる難しさを感じる日々を過ごしながら毎日項垂れて帰宅していました。

### 現状
案件の先輩や上司に何度も確認して、どうすれば業務のイメージがつくのか
今、具体的に何が足りてなくて苦戦しているように見えるのか？？
を何度もすり合わせながら個人学習をしてきました。

#### 具体的にしたアクション
>・データ作成時の作業をドキュメントとして残す
・ソースと設計書を相対させて読む
・質問する時は3分間で聞きたいことをメモアプリで整理してから聞く、回答も画面共有しながら議事録的に書く
・作業に入る前に一度や改修したいことをアクション別に箇条書きにしてから作業に入る
・Java EEベースのFWのためとりあえず少しでもソース読みを早くするためにJava silverの資格勉強

## 【半年経過してみて】
Java silver受験前3週間から案件が炎上して結構アップアップしていましたが、無事合格しました！！


炭治郎ではないですが・・・・


![](https://animemiru.jp/wp-content/uploads/2021/11/kimetsunoyaiaba-kamadotanjiro-04.jpg)


経験・知識・整理力不足を痛感する日々は変わりませんが、何がわからないのかを明確に相談できるようになり、何を改修したいのかはイメージできるようになりました。


## 【次の展望】
・今、改修している機能ではSQLが複雑なためどうしても作業が遅いことを感じているので
「ORACLE MASTER Silver SQL 」の受験
・やはりリテラシーはまだまだ高くはないため、「基本情報技術者試験」を受けうる
を考えています。


資格は意味ない等言われることが多いですが、資格はあるから日常が変わるわけではなく、自己プロデュースをするためのツールの一つと考えているのでしっかり取得していきたいと思います。

![スクリーンショット 2023-06-24 22.26.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162725/742a3c7c-47aa-bb04-b796-1b5b35013170.png)
Linux コマンドメモ

# 概要
Linuxの基礎的なコマンドをまとめます

# コマンド
**lsコマンド**
``ls [オプション] [ファイル]``
ファイル名やディレクトリ名を指定して情報を一覧表示する

**cpコマンド**
``cp [オプション] コピー元 コピー先 ``
ファイルを複製する

**mv**
``mv 移動元ファイル 移動先ファイル``
ファイルを移動させる

**rm**
``rm ファイル名 ``
作成したファイルを削除する 

**pwd **
``pwd``
階層の中で、現在どの位置にいるか表示する 

**mkdir**
``mkdir ディレクトリ名``
ディレクトリを作成 

**rmdir**
``rmdir ディレクトリ名``

**cat**
``cat ファイル名 ``
ファイルの内容を表示 

**more**
``more ファイル名``
ページング でファイルの内容を表示(末尾まで行くと終了)

**less**
``less ファイル名``
ページングでファイルの内容を表示(末尾まで行っても終了しない)

**find**
``find パス -name ファイル名``
ファイルがどこのディレクトリに存在するか検索

**which**
``which コマンド名``
コマンドのパスを表示 

**man**
``man コマンド名``
コマンドのマニュアルを表示

**リダイレクト**
``ls > ls-output`` 
のように > を使ってファイルに出力結果を書き込める

**grep**
``grep [オプション] 検索条件 [指定ファイル]``
ファイルの中からデータを検索
I18n::InvalidPluralizationData　について

## 初めに
自分用の備忘録として書きます。
プログラミング初学者（2ヶ月）ですので間違えていることもあると思います・・・
なので、なにかおかしいことを言っていたらコメントなどでご指摘くださると助かります。

## エラー画面
チームでECサイト作成しているときにエラーのフラッシュメッセージを日本語化しようとしていたときに出たエラーです。
![スクリーンショット 2023-06-24 221325.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3469865/f3cf31ec-93af-58ef-71b5-228ece3be45a.png)

これは新規会員登録をわざと空にしてエラーのフラッシュメッセージを出そうとしたときに起こりました。
色々調べた(あまり記事がなかった為、殆どChatGPT様に聞いた)結果、原因としては

**「このエラーメッセージは、複数形のデータに対して :count => 1 のような単数形のカウントが指定された場合に発生します。具体的には、_errors.html.erb テンプレートの7行目でエラーメッセージを表示する際に、translation data 内のキーと値が複数形形式になっていることが原因です。」**

とのことで・・・

#### うーん、分からん！

とりあえずhtmlではなくymlファイルが原因っぽいのは分かりました。
```rails:config/locales/ja.yml
activerecord:
  models:
    customer:
      email: メールアドレス
      password: パスワード
      last_name: 姓
      first_name: 名
      kana_last_name: セイ
      kana_first_name: メイ
      post_code: 郵便番号
      address: 住所
      telephone_number: 電話番号
```
また「translation data」は翻訳データだそうです。


## 結果

結論としては「models:」から「attributes:」に修正したら解決しました
```rails:config/locales/ja.yml
activerecord:
  attributes:
    customer:
      email: メールアドレス
      password: パスワード
      last_name: 姓
      first_name: 名
      kana_last_name: セイ
      kana_first_name: メイ
      post_code: 郵便番号
      address: 住所
      telephone_number: 電話番号

```
参考にしたサイト
https://makandracards.com/makandra/47056-dealing-with-i18n-invalidpluralizationdata-errors

私の英語力が雑魚なのでGoogle先生に翻訳してもらいましたが、結局のところ理由はわかってもどういう処理でエラーになるのかはよくわからなかったです・・・
どうやらI18nはオプションの複数形化をする？らしく、単数形も複数形にしようとしてエラーが出る？んですかね・・・

完全に理解するのは未来の自分に任せます。

閲覧していただきありがとうございました！
imgタグのsrc属性に指定している画像をbase64変換してPOST送信する

以下の手順。
* imgタグに画像を読み込んだ直後、canvasタグを生成
* 画像をcanvasタグに書き込む。
* canvasタグのtoDataURL関数を使用してBase64の文字列に変換する。
* 変換した結果を送信する。

```html
<html>
<body>
<img id="baseimg" src="./1010609154.jpg" crossorigin="annonymous"  />
<div id="b64img"></div>
<script>
const imageBase = document.getElementById("baseimg");
imageBase.onload = function() {
    var canvas = document.createElement("canvas");
    canvas.width = this.width;
    canvas.height = this.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(this, 0, 0);
    var dataURL = canvas.toDataURL("image/jpeg");
    // 変換後の文字列をブラウザを表示
    document.getElementById('b64img').innerHTML = dataURL;
    // 送信
    sendBase64(dataURL);
};

const server_url='送信先URL';

function sendBase64(base64) {
  fetch(server_url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      base64String: base64
    })
  }).then(response => {
     return  response.json();
  }).then(data => {
     console.log(data);
  }).catch(error => {
     // console.log(error);
  });
};
</script>
</body>
</html>
```
【フィルターなし】RunPodでWizard-Vicuna-30B-Uncensoredを動かす

## 概要
初投稿です。
ChatGPTを始め、様々なサービスが展開されているAIチャット市場ですが、ほとんどのAIには強弱の差はあれど倫理フィルターがついています。今回は倫理フィルターがない[Wizard-Vicuna-30B-Uncensored](https://huggingface.co/TheBloke/Wizard-Vicuna-30B-Uncensored-GGML)を使って、どんな内容が出力できるのか検証していきます。

## RunPodにデプロイ
てっとり速く検証するため、[RunPod](https://www.runpod.io/)というGPUのレンタルサービスを使ってデプロイしていきます。

今回はGPUにRTXA6000を選択しました。デプロイ時のテンプレートは、TheBlokeLLMs（text-generation-webui環境）を選びます。
![スクリーンショット 2023-06-24 19.53.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/b2c22662-07b9-22b5-d9ab-f2f02e48f190.png)
デプロイが終了したら、ConnectからPodに接続します。
![スクリーンショット 2023-06-24 19.56.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/3ffcfa8c-2f6b-5ecf-1226-425380d9573b.png)
接続したら、次はモデルのダウンロードを行います。
modelタブのDownload custom model or LoRAに、今回使う[Wizard-Vicuna-30B-Uncensored-GPTQ](https://huggingface.co/TheBloke/Wizard-Vicuna-30B-Uncensored-GPTQ)のモデル名を設定し、ダウンロードします。
![スクリーンショット 2023-06-24 19.57.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/a800fce7-6bb4-0bce-c567-5b8cf49b2a54.png)
しばらくするとダウンロードが終わると思うので、リロードした後、モデルにwizard-vicunaを設定します。
最後にModel loaderをAutoGPTQにしてから、wbitsを4にします。そして最後にReloadすれば、準備完了です。
![スクリーンショット 2023-06-24 20.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/cc33b314-7838-03d4-6f22-ca0bd48fe415.png)

## ChatGPTと比較

実際にフィルターが無いのか、ChatGPTと比較しながら検証していきます。

まずは英語で普通の質問をしてみます。

質問文 Introduce me to the tourist attractions of Japan.　(日本の観光地を紹介してください。)

回答
ChatGPT(GPT-4)
![スクリーンショット 2023-06-24 21.23.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/3780295a-1967-4f5d-e918-df83bafc1631.png)

Wizard-Vicuna
![スクリーンショット 2023-06-24 21.21.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/6bb4d09b-4d54-1bfa-e30c-a445a447506e.png)


結構いい感じの回答をしてくれている気がしますね。

ではいよいよ本題です。ChatGPTでは回答してくれないであろう質問をしてみます。

質問文　Give me the steps to steal a car.(車を盗むための手順を教えて)

ChatGPT(GPT-4)
![スクリーンショット 2023-06-24 21.26.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/4739fe0d-38ea-7374-4bd6-95e9bd163310.png)


Wizard-Vicuna
![Photokako-mosaic-MwWDHHPjOkHVnVfC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269287/43b281fd-df83-a712-0ad6-e5dd32268dba.png)

ChatGPTは当然ですが出力してくれません。対してWizard-Vicunaの方は、かなり詳細に手順を出力してくれました。（念のためモザイクをかけています）

この他にも、より直接的な暴力や性的な内容の質問にも回答してくれました。

## まとめ
Wizard-Vicuna-30B-Uncensoredは文字通りフィルター無しの回答を出力してくれました。性能もGPT3.5と大差無いように思われたので、十分注意した上で、ChatGPTでは答えてくれないことを出力させたい時などはこのモデルが使えるかもしれません。

## 参考
https://www.youtube.com/watch?v=_59AsSyMERQ
例外処理のテストについての学習メモ【テスト】【TypeScript】

以下は書籍「フロントエンドのテスト入門」の学習メモとなります。


期待しない値が混入したことを例外をスローすることでデバッグできずく必要がある。
- **TypeScriptの型注釈の利用によって入力値に制約をつける**

これによって例外処理の実装を減らすことができて効率的。

より詳細な期待値に制限する場合などに例外をスローする実装が必要となる。

- **例外をスローする**

```tsx
throw new Error("エラーメッセージ")
```

例外のテスト

```tsx
expect(例外スローが想定される関数).toThrow();

// 正しい書き方
// add関数が入力値を0~100までを受け取りそれ以外の値であれば例外をスローする場合。
expect(() => add(-10, 110)).toThrow();
```

`toThrow()`の引数にエラーメッセージを渡すと期待したエラーメッセージが受け取れることを確認できる。

意図どうりに例外がスローされているか？という意識をもって実装に取り組むべき。

- **Tips:拡張したErrorクラスを利用すると設計の幅が広がる**

instanceof演算子によって異なるインスタンスとして分別できる。

```tsx
// Errorクラスを拡張
export class HttpError extends Error();
export class RangeError extends Error();

// test内での利用例
expect(() => sub(-10, 110)).toThrow(RangeError);
```
【PowerShell】フルネームを取得する

# はじめに

Windowsのフルネームを取得するのが、ユーザー名と同じノリと思ってたら意外と苦戦したので、
記録として残します。

赤枠で囲っているところが今回取得したいフルネームです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/8795a224-c788-e2ee-9c98-34d7ba4c267a.png)


# 実際にやってみた

## 今回の実装

くどいようですがもう一度載せます。

```
$dom = $env:userdomain
$usr = $env:username
([adsi]"WinNT://$dom/$usr,user").fullname
```

## 実行結果

```
PS C:\Users\xxxx> $dom = $env:userdomain
$usr = $env:username
([adsi]"WinNT://$dom/$usr,user").fullname
たんすけ
```

無事にフルネームが取得できました。

# 参考文献

https://enjoy.sso.biglobe.ne.jp/archives/pc_0082/

https://www.web-dev-qa-db-ja.com/ja/windows/%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E3%83%95%E3%83%AB%E3%83%8D%E3%83%BC%E3%83%A0%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B/960264452/

UiPathでやっている方もいました。

https://qiita.com/Davoi/items/be82f01ddbce03153ff8

# おわりに

そんなに難しい話ではないかなと思っていたのですが、意外と苦戦しました。

今後もこういった意外と難しかったシリーズを取り上げられたらなと思います。
RMLPlatformで発生したエラーの解消方法

# はじめに
Realmをつかってモデルを定義しようとコードを書いていくと、いつもだったらエラーが出る場合、「Main.storyboard」や「ViewController.swift」に出て対処していたところ、今回は「RLMPlatform」というところで以下のようなエラーが出てしまいました。![スクリーンショット 2023-06-23 14.45.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485517/c7ebd952-ad3a-8b56-da02-435626e71587.png)
何が何だかよくわからず、途方に暮れて、対処方法がわかりました。

# 対処方法
結果的にはシンプルでした。
「改行されているところを削除して、改行がないようにする」
です。![スクリーンショット 2023-06-24 21.52.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485517/cc9e83b4-c9cc-a306-7cbf-31f8088fc069.png)
これだけでエラーがなくなり、Simulatorが動くようになりました。

# 原因
結論から言うと、Realmのバグでした。
本来は修正後のように“”で囲った1本のStringであるべきで、そのStringをRLManalyticsで読む仕組みになっているようです。
しかし今回それが1本のStringではなく、途中で改行されていることで、1本のStringではなくなり、The以降は本文として検知され、Swiftでない意味のわからない文だったため、「Theってなんだ？！」と言われていたようです。
なぜ改行されていたかですが、自分が意図的にいじった訳ではないので、Realmシステムのアップデート時に誤って改行があり、バグとなって出てきた模様です。
[秀丸エディタ] [マクロ] grep結果に対し、検索ヒット行の内容を前後の行内容に変更

# はじめに
以下が投稿の動機です。刺さらないという方は、そっ閉じしていただければと思います。

grep結果には検索にヒットした行の内容が表示されます。
普段はそれで良いんですが、前後の内容もほしいときがあります。

そのような機能（というか秀丸マクロ）は、公式サイトに行けばあるようです。
しかし、前後の内容も出力すると、grep結果の行数に意味があるとき（例：X箇所を変更した証拠として、grepでX行ヒットすることを見たいとき）にどうなんだろうか？と思って、自作してみることにしました。

・・・この投稿で示す秀丸マクロも、世の中にあったら申し訳ないです。
あとは、他のエディタでマクロを組める方のお役に立てたら嬉しいです。

# マクロを作る背景
以下にイメージで示すようなyamlがあるとします。
（別に、xmlでもjsonでも良いですが）

``` yaml
params:
  - path: "001/"
    exec: off
  - path: "001/001/"
    exec: off
  - path: "002/"
    exec: off
  - path: "002/001/"
    exec: off
  - path: "002/002/"
    exec: off
#    :
#    :
# 以降、省略します
# （似たようなデータが延々と続きます）
```

このyamlに、もしも何百もの要素があって、意図した10箇所だけ`exec: on`にするとき、その作業が終わった後で確認のためにgrepすると、以下のようになります。

```
hoge.yaml(5):     exec: on
hoge.yaml(15):     exec: on
hoge.yaml(17):     exec: on
hoge.yaml(39):     exec: on
hoge.yaml(77):     exec: on
hoge.yaml(81):     exec: on
hoge.yaml(83):     exec: on
hoge.yaml(85):     exec: on
hoge.yaml(93):     exec: on
hoge.yaml(101):     exec: on
```

10箇所を`exec: on`に変更できたことは分かりますが、意図した10箇所を変更したかどうかは分からないです。
そこで、秀丸マクロを作成して、grep結果を以下のように変えることを狙いました。

```
hoge.yaml(5):   - path: "001/001/"
hoge.yaml(15):   - path: "004/002/"
hoge.yaml(17):   - path: "004/003/"
hoge.yaml(39):   - path: "007/005/"
hoge.yaml(77):   - path: "015/001/"
hoge.yaml(81):   - path: "015/003/"
hoge.yaml(83):   - path: "015/004/"
hoge.yaml(85):   - path: "015/005/"
hoge.yaml(93):   - path: "017/001/"
hoge.yaml(101):   - path: "017/005/"
```

# 作成したマクロ
以下になりました。（秀丸マクロ用の強調表示を知らず、適当な表示で申し訳ないです）
バグがあったら、教えていただけると嬉しいです。

``` cs
// オフセット行数の入力
$Offset = input("オフセット行数（整数）を入力してください。\n" +
				"　・秀丸でタグジャンプできるgrep結果の選択中が前提\n" +
				"　・負の数を指定した場合、grepヒット箇所より前を取得", "0");
#Offset = val($Offset) / 1;
if (str(#Offset) != $Offset) {
	// 整数入力でなければ終了
	endmacro;
}

// grep結果の行内容部分クリア
replaceall "([\\(\\:][0-9]+\\)?\\:).*", "\\1 ", regular;
#LineNo = 0;
moveto 0, #LineNo;
#Source = hidemaruhandle(0);

// grep結果の各行ループ
while (code != eof) {
	// ヒット箇所からのオフセット位置に移動
	tagjump;
	#Dest = hidemaruhandle(0);
	if (#Offset < 0) {
		up -#Offset;
	} else if (#Offset > 0) {
		down #Offset;
	} else {
		// 何もしない
	}
	
	// 移動した位置の行内容を取得してクローズ
	$LineStr = gettext(0, y, linelen, y);
	setactivehidemaru #Source;
	closehidemaruforced #Dest;
	
	// grep結果に行内容を挿入
	golineend;
	insert $LineStr;
	
	// 次行に進む
	#LineNo = #LineNo + 1;
	moveto 0, #LineNo;
}
endmacro;
```
最小素因数のリストを使って[2..N]の整数の素因数分解を行う

素因数分解のアルゴリズムは数多くありますが、ここでは2から連続した整数すべての素因数分解を高速に行う方法を紹介します。

### ステップ １． 最小素因数のリストを作る


まず、エラトステネスの篩的なアルゴリズムで最小素因数のリストを作ります。最初の素因数が見つかったらそれ以上は何もしないという感じです。

```python 
def smallest_factors(N):
  sfl = [0]*(N+1)
  for p in range(2, N+1):
    if sfl[p]: continue  # not prime
    for pp in range(p, N+1, p):
      if sfl[pp]: continue
      sfl[pp] = p
  return sfl

N = 10
sfcts = smallest_factors(N)
print([(i,sfcts[i]) for i in range(N+1)])
# [(0, 0), (1, 0), (2, 2), (3, 3), (4, 2), (5, 5), (6, 2), (7, 7), (8, 2), (9, 3), (10, 2)]
```

### ステップ ２．nを最小素因数で1になるまで割っていく
最小素因数のリストはべき乗の情報もなく$8$も$10$も$2$となります。こんなものが役に立つのかと思いますが。これを使って2から10までの素因数分解をsympyのfactorintと同様のDICT形式のリストにします。

```python 
fctlist = []
for n in range(2, N+1):
  fct = dict()  # factorint list
  n1 = n
  while n1>1:
    d = sfcts[n1]
    pw = fct.get(d,0)  # 0 if no entry for d
    fct[d] = pw+1
    n1 //= d
  fctlist.append(fct)
print(fctlist)
# [{2: 1}, {3: 1}, {2: 2}, {5: 1}, {2: 1, 3: 1}, {7: 1}, {2: 3}, {3: 2}, {2: 1, 5: 1}]
```
ちゃんと求まってそうです。何故そうなるのかと言うと、以下のように$n$を最小素因数で1になるまで次々に割って、その素因数のべき乗を１つ増やして行くと、素因数分解となるという、割と当たり前の仕組みです。

```math
10 / 2 \to 5/5 \to 1 \\
従って10 = 2\times 5
```

### 【応用】[2..N]の整数のそれそれの階乗の素因数分解 

このアルゴリズムの面白いところは、素因数を追加しながら計算するので階乗の場合には、前のコードで毎回DICT変数を初期化していたのをやめるだけで漸化式的に階乗の素因数分解を求めることが出来ます。
```python 
fct = dict()  # **** moved outside of the loop
for n in range(2, N+1):
  n1 = n
  while n1>1:
    d = sfcts[n1]
    pw = fct.get(d,0)  # 0 if no entry for d
    fct[d] = pw+1
    n1 //= d
    print(f"{n}!:", fct)
# 2!: {2: 1}
# 3!: {2: 1, 3: 1}
# 4!: {2: 3, 3: 1}
# 5!: {2: 3, 3: 1, 5: 1}
# 6!: {2: 4, 3: 2, 5: 1}
# 7!: {2: 4, 3: 2, 5: 1, 7: 1}
# 8!: {2: 7, 3: 2, 5: 1, 7: 1}
# 9!: {2: 7, 3: 4, 5: 1, 7: 1}
# 10!: {2: 8, 3: 4, 5: 2, 7: 1}
```

階乗はnが大きくなると非常に値が大きくなってしまうのですが、このように素因数分解の形だと扱いやすくなります。[「大きな整数の階乗の剰余を求める」](https://qiita.com/masa0599/items/c63d1de0ac3c268899e7)で紹介しているように剰余計算もpow関数が使えます。

（開発環境：Google Colab）

この考え方はProject Euler、Problem 675: 2**w(n)を解くのに役に立ちます。
アプリケーション開発の手順の一部

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/ee3ab853-d577-a681-8635-0ad2020a9d59.png)
１：開発前にやることを把握
①企画
どんなアプリ（機能）を作るか決める段階のことです。
企画でははじめに、誰のどんな問題を解決したいのかを決めます。これが決まったら、解決手段として新しくアプリを作ったり、すでにあるアプリに新機能を追加することがあります。

②要件定義
ユーザーがどのように機能を使用するのかを考え言語化する、障害が起こった時どうするかを決めるなど、詳細な情報を整理します。

③設計
エンジニアが実際にどのようにアプリや新機能を作っていくかの手順書や、必要な設計図を作る工程です。
設計には基本設計と詳細設計という2つのフェーズがあります。
企画、要件定義、設計が終わったらはじめて実際にコードを書きます。

２：開発後にやることを把握
①デプロイ
作ったアプリを外部のサーバーに移して、全世界からアクセスできるように設定することです。こちらは後のLessonで詳しく説明します。

②保守/運用
保守/運用とは、動いているアプリに異常がないか定期的に確かめることや、トラブルが発生したら対処することです。
その手法はアプリの規模や用途により変わります。

例えば、病院など医療現場で使われているアプリは、時に命に関わる重要なものです。
そのため、アプリで不具合が起きたとしてもすぐに復旧できるよう、事前に何重もの策が講じられます。

３：アプリケーション開発の全体像を把握
ここまでの流れについて
企画→要件定義→設計→開発→開発→保守/運用
Amazon Linux 2023にSSH出来なかったので調べてみた

【結論】
　・古いホストキーアルゴリズムがAmazon Linux 2023では無効化されていた。
　・クライアント側（Teraterm-4.106）が新しいアルゴリズムに未対応だった。

【対処】
方法①
teraterm-5.0-beta1にアップグレードする。

以下アルゴリズムであれば接続可能。
　・rsa-sha2-256
　・rsa-sha2-512

teraterm-5.0-beta1は対応している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472386/0158192d-a80a-8734-460b-96f234d44d79.png)

Teraterm-4.106は対応していない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472386/ea9dd452-a1ff-36d3-c937-312a8739711b.png)

方法②
キーペアのタイプを「ED25519」で作成したキーを使ってEC2を作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472386/d7924d37-a76f-eb45-1e57-1a91830bf180.png)

【参考】
https://docs.aws.amazon.com/linux/al2023/ug/ssh-host-keys-disabled.html
※上記ページにssh-rsaをサポートさせる手順も記載しておりますが、セキュリティレベルが低下する為、本記事では扱いません。
【未経験】Laravel + sail + vue + PostgreSQLアプリをRender.comにデプロイする

## 初めに
Laravel sailとVue.jsとPostgreSQLを使ったアプリをRender.comにデプロイするのにとても苦労したので備忘録として残します。

:::note warn
render.comで本番環境のshell(コマンドライン)を使う場合無料プランではなく
Starterプラン(7$)を使う必要があります。
（ 7$ = 1,000.79 円(2023/06/24現在) )
:::

# 手順
:::note warn
この記事ではアプリケーションの作成は解説しません。その手順を知りたい方は[こちら](https://qiita.com/Tatsuya7/items/ce73cc772bfe14fd7e00)の記事もご覧ください。
:::

https://qiita.com/Tatsuya7/items/ce73cc772bfe14fd7e00

### 1.Dockerfileをプロジェクトのルートディレクトリに作成する。
以下のようなDockerfileをプロジェクトのルートディレクトリ(.envファイルやpackage.jsonファイルがあるところ)に作成します。`php:8.1-fpm`のバージョンは自分の環境に合わせて変更してください。

```Dockerfile
FROM php:8.1-fpm

# 依存関係のインストール
RUN apt-get update && apt-get install -y \
    curl \
    zip \
    unzip \
    git \
    libonig-dev \
    libpq-dev \
    && docker-php-ext-install pdo_pgsql mbstring

# Composerのインストール
COPY --from=composer /usr/bin/composer /usr/bin/composer

# Laravelの依存関係をインストール
WORKDIR /var/www
COPY . /var/www
RUN composer install

# Node.jsとNPMのインストール
RUN curl -sL https://deb.nodesource.com/setup_18.x | bash -
RUN apt-get -y install nodejs

# Vue.jsの依存関係をインストール
COPY package*.json ./
RUN npm install
RUN npm run build

CMD php artisan serve --host=0.0.0.0 --port=8080

EXPOSE 8080

```

### 2.Render.comの用意
Render.comでアカウントを作成し、dashboard画面で右上の青いボタンから`Web Service`を選択する。

そこからデプロイしたいgithubのリポジトリを選択します。

その後、以下の画面で必要な情報を入力し、Create Web Serviceで作成します。

![スクリーンショット (87).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3027729/3a0dd163-36f0-7b23-5321-063e3519ba01.png)

`NAME`には`アプリケーションの名前`を、`Region`は恐らくシンガポールが一番近いので`シンガポール`を選びます。

`Runtime`では`docker`を選びます。

`Instance Type`はvueを本番環境でビルドするのにshellを使う必要があるので`starter`を選びます。

### 3.DBの用意
またダッシュボードに戻り、右上の青いボタンから`PostgleSQL`を選択。

`NAME`には`アプリ名+DB`のようにわかりやすければOKです。
`Region`はこちらも`シンガポール`。
`Instance Type`はこちらは無料プランでも大丈夫です。（無料プランは90日で期限が切れます。）

その後Create Databaseで作成します。

`Status`が`Createing`から`Available`となるまで待ちます。（少し待てば完了すると思います。）

### 4.環境変数の設定
ダッシュボードに戻り先ほど作成したWeb Serviceに戻り左のメニューからEnvironmentを選択し、環境変数を設定していきます。

下の画像のようにLaravelアプリの`.env`ファイルにある環境変数をrender.com側にも設定します。

__`APP_ENV`__ と __`APP_DEBUG`__ には本番環境では`production` `false` を設定し、
__`APP_URL`__ にはページの左上にあるURL( `https://your-appname.onrender.com` )を設定します。

その他の環境変数は`.env`ファイルの内容を写します。

![スクリーンショット (93).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3027729/98c28969-dfe1-4e19-4606-ff26e122646b.png)

### 4.Vueを本番環境でビルドする。

Web Serviceの左のメニューから`shell`を選択し、コマンドラインを開き以下のコマンドを入力。
```shell
npm run build
```


### 5.DBをマイグレイトする。

先ほどのコマンドラインから以下のコマンドを入力すればアプリケーションが本番環境で動くようになると思います。
```shell
php artisan migrate
```


# 終わりに

最初はSailが開発環境用ということを知らず、そのままデプロイしようとしていましたが、本番環境用のDockerfileを用意しないといけないということを後から知り、技術やサービスを使う際はきちんとその物について知識を付けてから使わないといけないなと痛感しました...
NameError:uninitialized constant Rspecの対処法

ポートフォリオのテスト作成中に２つのエラーが発生しました。アウトプットも兼ねて解決法を記事にします。初学者ですので間違いもあるかと思いますが、多めに見てやってください🙇

# エラーメッセージ
```
NameError:
  uninitialized constant Rspec
# ./spec/models/user_spec.rb:1:in `<top (required)>'
No examples found.
```
# 解決方法
なぜに？と思っていましたが、こちらの記事を参考に解決しました。
https://qiita.com/kaino5454/items/3d4e52c98bbe422ab65c
どうやらRSpecをRspecと小文字で書いていたことが原因のようです。

```user.spec.rb
Rspec.describe User, type: :model do
#//省略
end

RSpec.describe User, type: :model do
#//省略
end

```

とても初歩的なミスでした汗。改めてbundle exec rspecを実行したら次はこんなエラーが、、、

# エラーメッセージ
```
NameError:
  uninitialized constant User
# ./spec/models/user_spec.rb:1:in `<top (required)>'
No examples found.
```

# 解決方法
```user.spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
#//省略
end

```
require 'rails_helper'を入れたら解決！　無事Rspecを通すことができました！
Mac Source Treeから、GithubへPush/Pullができなくなった時の対応方法

MacでSource Treeを利用しているとき、GithubへPush/Pullができなくなったことがあり、その対応事項を備忘録として記載します。
1.Githubから、アクセストークンを取得する。
詳しくは、以下で説明されているので、こちらを参照する。
※Classicのアクセストークンを取得しないとうまくいなかったので、注意すること！
    https://qiita.com/koji4104/items/e2bd9f98ffa5b1c4610d


2.Macキーチェンから、該当するGitのAccessKeyを削除
右上の検索タブから「github」で検索し、該当する情報を削除
以下のような鉛筆アイコンの情報でgithubのパスワードを管理しているため、一度この情報を削除
![スクリーンショット 2023-06-24 20.11.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703002/d16c8c80-55dd-adf5-ceee-220746aca6c9.png)


3.Push/Pullを行い、パスワードを再設定
SourceTreeからPush/Pullを行うと、パスワードの再設定を求められる。
この際、手順１で取得したアクセストークンを入力すればOK！
Rubyとは？

## はじめに
Ruby の勉強を始めました！まずは Ruby について概要記していきます。

## 目次
1. [Ruby の誕生](#ruby-の誕生)
2. [Ruby の由来](#ruby-の由来)
3. [Ruby でできること](#ruby-でできること)
4. [Ruby が苦手なこと](#ruby-が苦手なこと)
5. [参考文献](#参考文献)

## Ruby の誕生
<b>Ruby(ルビー)</b>は1995年に日本で開発・公開されたオブジェクト指向スクリプト言語です。
- ```スクリプト言語``` ： アプリケーションソフトウェアを作成するためのプログラミング言語
- 開発者 ： ```まつもと ゆきひろ（通称：Matz）```
- Matz さんが好きな言語の一部(Perl、Smalltalk、Eiffel、Ada、Lisp)をブレンドして作成
- 日本で開発された中で、初めて国際規格である<b>国際電気標準会議(IEC)</b>で認定された言語
- Ruby はフリーソフトウェア。<b>利用だけでなく複製・変更、および再配布も可能</b>
- Ruby はシンプルに書きやすく読みやすいため、<b>プログラミング未経験者におすすめ</b>


## Ruby の由来
由来はその名の通り、宝石のルビーから来ています。
Matz さんの同僚が7月生まれで、誕生石がルビーであることから名付けられたようです。
Perl(パール)言語を参考にした部分が強く、6月生まれの誕生石である<b>パール(真珠)の次のプログラミング言語</b>という意味も込めて、Rubyと名付けられたとされています。

## Ruby でできること
- アプリケーションサイト
数多くのパッケージと API があり、工数を削減しつつサービスを作成できます。

  ＜代表サービス＞
　クックパッド ： 日本でも有名なレシピサイト
　　https://cookpad.com/
　食べログ ： 飲食店のグルメクチコミサイト
　　https://tabelog.com/
　Hulu ： 動画配信サイト
　　https://www.hulu.jp/
- ショッピングサイト
Ruby on Rails のフレームワークを活用すれば開発効率を向上でき、ユーザー登録・ログイン機能・クレジット決済機能の追加などが可能です。
また、商品管理画面や商品登録といったことも Ruby で実行できます。
- SNSサイト
Ruby はバックエンド開発に強みを持っています。
また、Ruby のフレームワークである```Ruby on Rails```を使えば、ユーザーのログイン情報の登録や投稿したデータの管理などに利用されるデータベースを簡単に作成可能です。

   ＜代表サービス＞
　Wantedly ： ビジネスSNS
　　https://www.wantedly.com/projects
　Airbnb ： 宿泊施設・民泊を貸し出す人向けのコミュニティサイト兼予約サイト
　　https://www.airbnb.jp/
　Twittter ：SNS
　　https://twitter.com/
- 業務システム
Ruby on Rails は開発速度が早いため、業務システムの開発にも使われます。
- スクレイピング
```Nokogiri```という gem を使って Web 情報を抜き取り、加工・使用する技術
- スマホアプリ
```RubyMotion```や```Rubot```と呼ばれるライブラリを使用することで作成可能です。
- 機械学習
Python ほどではないが、機械学習も Ruby で書くことができます。
ただ、Ruby で機械学習するには```PyCall```という<b> Python を Ruby で動かすためのgem</b>を使用すると Python をベースに機械学習が可能です。
- API
Ruby on Rails は、サーバーやデータ間のやりとりを行う API の開発も可能です。

## Ruby が苦手なこと
- 統計解析
統計解析には Python、Java、Julia の方が向いています。

- Webデザイン
Ruby は汎用言語ではありますが、Web デザインは苦手とされています。
Web サイト制作は、基本的には HTML、CSS、JavaScript が使われます。

## 参考文献
<a href="https://www.ruby-lang.org/ja/about/">Rubyとは</a>
<a href="https://hnavi.co.jp/knowledge/blog/ruby/">プログラミング言語のRubyとは？特徴やできることを解説</a>