OmniAICreator/Qiita-1.07M huggingface dataset:
【Jest】画像ファイルを処理できないエラーの解決方法について

# はじめに
Jestのテストを実行したところ下記のエラーが表示されましたので、こちらの解決方法について共有させていただきます。

```terminal
● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /home/shotaro/jisou-task4/meishi-project/src/images/github-mark.png:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){�PNG
                                                                                      

    SyntaxError: Invalid or unexpected token

      1 | import { Box, Card, CardBody, CardHeader, Heading, Image, Text } from "@chakra-ui/react";
    > 2 | import githubIcon from "../images/github-mark.png"
```
.pngがうまく処理できていません。
画像をjavascriptとして処理しようとするため発生するエラーのようです。

# 解決方法
.pngをモック化します。

```.jest.config.js
moduleNameMapper: {
    "\\.(png|jpg|jpeg)$": "<rootDir>/__mocks__/fileMock.js" // ← こちらを追加
  },
```

```.__mocks__/fileMock.js
    module.exports = 'test-file-stub'; // ﾙｰﾄﾃﾞｨﾚｸﾄﾘにﾃﾞｨﾚｸﾄﾘ、ﾌｧｲﾙ作成しこちらを追記
```

これで.pngもモック化してtest-file-stubを返すようになり、testが成功するようになりました。

# 参考
https://jestjs.io/ja/docs/webpack

https://www.gatsbyjs.com/docs/how-to/testing/unit-testing/

<br>

[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707255/8bfacf61-7d8d-6d27-cb07-98d1f8f27fcd.png"  width=100%>](https://projisou.jp)
【Python】継承のsuper()を使う【プログラミング言語】


## Python継承のsuper()とは？
    
Pythonではあるクラス(子クラス)で別のクラス(親クラス)を継承できます。

継承することで、親クラスのメソッドを子クラスから呼び出すことができます。

その際に使うのがsuper()です。

## super()の使い方

> super().親クラスのメソッド # python3系での標準の書き方

super()を呼ぶことで親クラスのメソッドなどを呼び出すことができます。



### サンプルプログラム

```python

# Description: 継承
class math(object):
    """足し算クラス
    :param object: objectクラス
    """
    def __init__( self , val1 =1 , val2 = 1):
        """初期化
        :param val1: 数値1
        :param val2: 数値2
        """
        self.val1 = val1
        self.val2 = val2
        print( "足し算  val1:" + str(self.val1) + "val2:" + str(self.val2) )

    def calc( self ):
        """計算
        :return: 足し算結果
        """
        return self.val1 + self.val2

class calcuration(math):
    """多重継承
    :param math: mathクラス
    """
    
    def __init__( self , val1 =2 , val2 = 2):
        """初期化
        :param val1: 数値1
        :param val2: 数値2
        super().__init__()で初期化
        """
        super().__init__(val1,val2)
        print( "計算  val1:" + str(self.val1) + "val2:" + str(self.val2) )

# 計算
calc = calcuration()
print( calc.calc())

```

mathクラスにはコンストラクタとcalcメソッドを持っています。

calcurationクラスではmathクラスを継承しています。

calcurationクラスのコンストラクタの中でsuper()を使いmathクラスのコンストラクタを呼び出しています。

### 実行結果

> 足し算  val1:2val2:2
計算  val1:2val2:2
4

![スクリーンショット 2025-02-25 203241.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544972/8e28e25d-1ca8-4d3f-8d97-126a64abb8d1.png)
belongs_to と has_many 

## belongs_to の使い方

```ruby
class Review < ApplicationRecord
  belongs_to :food
end
```

## belongs_to の解説

- `belongs_to` は、**このモデルが別のモデルに属している（関連している）** ことを示す。
- `belongs_to :food` を指定すると、`Review` モデルには `food_id` という **外部キー** が必要になる。
- `Review` のインスタンスから `Food` のデータを簡単に取得できる。

## belongs_to をつけるとできること

- `review.food` で、その `Review` に紐づく `Food` を取得できる。
- `Review` に `food_id` の外部キー制約を設定できる。
- **データの整合性を保ちやすくなる**（関連する `Food` が削除されたらどうするかの設定も可能）。

---

## has_many の使い方

```ruby
class Food < ApplicationRecord
  has_many :reviews
end
```

## has_many の解説

- `has_many` は、**このモデルが複数の関連レコードを持つ** ことを示す。
- `has_many :reviews` を指定すると、`Food` モデルから関連する `Review` の一覧を取得できる。
- `Food` に紐づく `Review` を管理しやすくなる。

## has_many をつけるとできること

- `food.reviews` で、その `Food` に紐づくすべての `Review` を取得できる。
- `dependent` オプションを使うことで、**親データ削除時の動作を制御** できる（例：`dependent: :destroy` で `Food` 削除時に `Review` も削除される）。
- `has_many :through` を使えば **中間テーブルを利用した多対多の関係** も作成可能。

---

## belongs_to & has_many のまとめ

| 関係性 | 記述 | できること |
| --- | --- | --- |
| **1対多の「多」側** | `belongs_to :food` | `Review` から `food` にアクセス可能 (`review.food`) |
| **1対多の「1」側** | `has_many :reviews` | `Food` から `reviews` にアクセス可能 (`food.reviews`) |
requestsで返ってくるステータスコードについて

# はじめに
今日webスクレイピング関係の処理が失敗しているのを見つけ、その原因を探していました。
ログを確認するとステータスコードは200であったため、ページの構造でも変わったのかな？と過去のページ構造に思いを馳せていましたが、結果としてはページ構造は何も変わっておらず、実はリクエストが失敗していたという状況でした。
原因特定に時間がかかってしまった要因の一つとして、requestsの仕様を知らなかったことが挙げられるため備忘録としてまとめておきます。

※ 最終的な原因はサイトのURLが一部変わっていたことでした。

# httpレスポンスについて
httpレスポンスはステータス行、ヘッダー、本体（ボディ）の3つに分かれています。

https://developer.mozilla.org/ja/docs/Web/HTTP/Messages

このときステータスコードはヘッダーの1行目にあります。
私はこのステータスコードだけを見て「リクエストは正しく通っている」と判断をしてしまいました。
```bash
HTTP/1.1 200 OK
```

# requestsの仕様
httpリクエストを送り、responseを受け取るためのコードはざっくり以下のようになっています。
```python
session = requests.session()
url = "~~~"
response = session.get(url)
```
このとき、`session.get`では`allow_redirects=True`がデフォルトとなっており、このオプションが`True`だと300番台のステータスコードが返ってきた際に、自動でリダイレクトを行います。

https://requests.readthedocs.io/en/latest/user/quickstart/#redirection-and-history

そのため、`response.status_code`だけ確認してしまうと、リクエストが正しく処理されていると私のように勘違いし、他のエラー要因に思いを馳せる可能性があります。
レスポンスが通っているか否かを先に把握することで原因の探索時間は大幅に減少すると思います。

# まとめ
- 自分が使っているライブラリの仕様については公式ドキュメントを確認しよう！
AWS SAAに合格した！


## はじめに
2025年の1月にAWS SAAを受験しました。
何とか合格することが出来ました。

## AWS SAAとは？
- AWSを使ったシステム設計や構築に関する知識を問う試験
- 問題数：65問(採点対象の問題はそのうち50問)
- 合格点：720点以上(1000点満点)
- 試験時間：130分
- 受験料：22000円（税込）
- 試験方式：CBT方式

## 著者のスペック
- 情報系の修士卒
- 社会人一年目(機械学習系の案件を担当)
- クラウドの知識はほとんど無し...

備忘録として合格するためにどのような勉強を行ったか紹介していきます

## 受験理由
本資格を受験しようとした理由は以下の通りです。
- 会社の資格手当対象資格だったため
- 案件先の業務でAWSに触れるようになったのでAWSの知識が必要だと感じたから

## 使用したテキストやサイト
①[徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書 第3版［SAA-C03］対応](https://tatsu-zine.com/books/tettei-aws-sa-3ed)
②[https://mondai.ping-t.com/g](https://www.sg-siken.com/sgkakomon.php)

主にPing-tをメインに使用しました。①の黒本はインプット用に使用しましたがPing-tだけでも合格できると思います。

## 勉強時間
70~80時間くらいだと思います

## 勉強法
### 1. 黒本を1周する
流し見で早めに一周しましょう。というのもAWS SAAは範囲が広いので問題を解きながら知識を身に着けていく方が効率的だからです。

### 2. Ping-tの【試験レベル】以外の問題を8割ほどHit状態にする
全ての問題を解く必要はありません。最終的なゴールは試験レベルの問題を解けるようになることなので、ここではインプットとして各システムがどのようなことができるか理解していきましょう。

### 3. Ping-tの【試験レベル】の問題を全てHit状態にする
全ての問題をHit状態にするまで解きましょう。最初はほとんど解けないと思いますが問題をこなすうちにある程度選択肢が絞れると思います。この段階では問題者が重視していることは何かを意識して問題を解いていきましょう。

### 4. Ping-tの【試験レベル】の問題を全てコンボ状態にする
全ての問題をコンボ状態にするまで解きましょう。ここで間違えてしまった問題はPing-tのブックマーク機能を用いて復習問題として記録しましょう。また理解が曖昧な分野は2で解いた問題を復習して理解を深めましょう。

### 5. Ping-tの模試を解きまくる！
【試験レベル】の問題のみ出題されるように設定し、模試を実施しましょう。ここで80%以上の正答率を5回ほど達成すれば合格できる実力が十分身についていると思います。

ちなみに著者のPing-tのスタンプラリーは以下の通りです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4019599/4bb311d7-e551-402e-b61f-22eaf0f3d86c.png)

あと数回ほど模試で80%以上の正解率を出したかったですね...
ただ模試の正解率は低くても75%くらいだったと思います。

## 試験結果
- スコア：776点（合格ライン：720点）
- 結果：合格
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4019599/1502a6b3-64d3-4508-a790-3efbb3478109.png)

試験日の20時に合格通知が届きました。
なんとか合格できました

## 受験の感想
何問かはPing-tで見たことあるような問題でした。それ以外の問題はPing-tで似たような問題がなかったか記憶をひねり出しながら解いていきました。
またスコアの範囲は100~1000点なのですべての問題が間違っていても100点がもらえます。従って１問当たりのスコアは900÷50で18点くらいだと思います(当然問題の比重によって配点は変わると思います。)よって採点対象の問題を7割ほど解ければ合格点に達するかなぁと思います。
全ての問題を見直しして10分ほど余ったのでちゃんとやれば時間通りに終わると思います。

## おわりに
AWSの知識が0でしたが何とか合格できました。夏までにAWSの試験に多く合格しAWSの知識を身に着けようかなぁと考えています。
[VSCode] Github Copilotの提案受け入れをtabキーから変更する

# 概要
VSCodeでGithub Copilotを導入したところ、元々のコード補完のキーバインドがCopilotの提案受け入れのキーバインドと競合してしまった。

# やりたいこと
下図の場合
![250225_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536374/666611d8-0468-42be-aa9a-5109ff711042.png)
現状ではtabキーを押すとCopilotの提案「document.querySelector('h1').textContent;」が入力される。

これを
　tabキー → VSCodeのコード補完
　他のショートカット → Copilotの提案受け入れ
というように選べるようにしたい。

※Copilot提案を一単語ずつ受け入れ（ctrl + →）で「document」だけの入力もできるが、コード補完を今まで通り気兼ねなくガンガン使いたいので今回はCopilotからtabキーを取り戻す方向でいく。


# 普通に設定変更してみる
VSCodeのキーバインド設定を開き（ctrl+K ctrl+S）
検索窓に「copilot」と入力してみると...

![250225_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536374/251f46a8-37eb-4e12-947b-6841211d25f1.png)

tabキーをバインドしている項目が一つも無い。

# 解決方法
Copilot提案受け入れの正しい項目名は
　 - **Accept Inline Suggestion**
　（keybind.json上では  **"editor.action.inlineSuggest.commit"**）
らしいので、それを任意のキーに変更すれば完了。

参考 [Tab completion conflicts [GitHub Copilot] #7036](https://github.com/orgs/community/discussions/7036)

# まとめ
まさかの"copilot"というワードを含まない、エディタ自体の設定という扱いだった。
bundle installしているのにrailsコマンド実行時に Run `bundle install` to install missing gems. と指摘される

同一仮想マシン内で複数のbundlerバージョンが共存しているため発生した。

```
$ gem list | grep bundler
bundler (2.4.22, default: 2.3.26)
```

defaultではない方のbundlerを使用しているプロジェクトでは、railsコマンド実行時に、bundle execをつけるとgemを認識してくれる。
JetBrains社IDE【統合開発環境】を使用して何時も使うコマンドを登録してみよう

## はじめに
皆様は何時も叩くコマンドはコンソールから手打ちしているでしょうか？
いやいや、何時も使うコマンドについては予め登録しちゃいましょう

## JetBrains社IDE【統合開発環境】の良いところ
何時も使うコマンドも登録出来ちゃいます

## 環境
環境は以下の通り(今回はPhpStormを使用します)
PHP：8.0.6
Laravel Framework：8.44.0
PhpStorm：[PhpStorm 2024.3.1.1](https://www.jetbrains.com/ja-jp/phpstorm/)
OS：Windows10

## Laravelで何時も使うコマンドと言えば...
APIをローカル起動するための以下コマンドが有名ですかね  
```
php artisan serve
```
PhpStormでも以下の様にターミナル起動出来るのでコマンドは入力出来ますが...  
PhpStormでコマンドを登録しちゃいましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/6dab8a08-e969-fd7e-cc3c-39260de0141e.png)


## コマンド登録の仕方
1. 「︙」をクリック(①)して「編集」をクリック(②)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/e92136a0-3643-8d78-b711-e1e89dad1f1e.png)
2. 「+」をクリック(①)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/7801f744-a720-4ec5-2990-f9952f0ae194.png)
3. 「PHPスクリプト」をクリック(①)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/1b91d177-5c43-f494-9674-4a64c236306b.png)
4. 設定画面が表示されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/970e1960-dcc0-2ba6-8271-288c9bd798e6.png)
5. 名前には「artisan」と入力(①)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/f8d1aa1b-d133-da8d-f205-7f476427137c.png)
6. ファイルアイコンをクリック(①)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/abcbb5bc-4433-783a-e3b4-da6c385a8202.png)
7. artisanファイルを選択(①)し「OK」ボタンを押下(②)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/f29646fe-5869-49b6-0455-412cf21cda93.png)
8. インタープリターは「PHP8.0 (8.0.6)」を選択(①)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/48ef96f0-079f-d463-b3ae-56e96fb93022.png)
9. 引数には「serve」と入力(①)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/d67921f2-5706-2f5b-ece7-ec0e69180d64.png)
10. 「OK」ボタンを押下(①)します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/2d1e9f72-fa7d-45cb-d8c3-229ef1d34336.png)
11. 「artisan」コマンドが登録(①)出来ました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/855a6e18-7198-96ef-57a8-c8f305cf4688.png)
12. コマンドを実行してみたいと思います。artisanの隣にある「▷」(①)を押下してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/bd3683ab-35ea-4de5-b94a-d0186b60b093.png)
13. localhostでサーバが起動されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117785/ae122b4f-c009-41ff-83b5-1453fbcb2274.png)

## さいごに
こんな感じで何時も使うコマンドについてはコンソールで都度入力せずにGUIで実行出来る様になりました。

今回はLaravelで実行するコマンドで手順を紹介しましたが
他の言語についても同様に応用が効きますので興味を持った方はJetBrains社IDEを使ってみては如何でしょうか？
UnitySampleプロジェクトで解説する依存性の逆転

# はじめに
Unityのチュートリアルプロジェクトを題材に、依存性の逆転（Dependency Inversion）について解説します。本記事では、基本的な概念から具体的なサンプルプロジェクトを用いた説明までを行います。

- [Unityチュートリアルプロジェクト](https://github.com/Unity-Technologies/game-programming-patterns-demo)
- [Unityチュートリアルテキスト E-Book](https://unity3d.jp/game/game-ebooks/level-up-your-code-with-game-programming-patterns/)

# 目次
1. [依存性の逆転とは](#Chapter1)
2. [用語解説](#Chapter2)
3. [どんな場面で用いられる？](#Chapter3)
4. [サンプルプロジェクトでの解説](#Chapter4)
5. [まとめ](#result)
6. [参考文献](#reference)

<a id="Chapter1"></a>
# 依存性の逆転とは
### E-Bookによる定義
依存性逆転の原則（DIP：Dependency Inversion Principle）とは、「上位のモジュールは下位のモジュールを直接インポートしてはならない。両者は抽象に依存するべきである」という原則です。

この定義だけでは少し分かりにくいかもしれません。簡単に言い換えると、

- 下位モジュールは変更されることが多いため、上位モジュールが直接依存すると影響を受けやすくなる。
- そこで、変更の少ない抽象（インターフェースなど）に依存することで、柔軟性と保守性を向上させる。

<a id="Chapter2"></a>
# 用語解説
#### モジュールとは？
モジュールとは、再利用可能な機能のまとまりのことを指します。

#### 上位モジュールと下位モジュールとは？
- **上位モジュール**：アプリケーションの主要な関心事（ダメージ計算など）を扱うモジュール。
- **下位モジュール**：実装の詳細や変更される頻度の高い部分（UIなど）を担当するモジュール。

依存性の逆転の原則では、上位モジュールが下位モジュールに直接依存せず、抽象を介して依存することで、システムの柔軟性を高めます。

<a id="Chapter3"></a>
# どんな場面で用いられる？

上位モジュールが下位モジュールを制御する際、直接下位モジュールに依存するのではなく、抽象に依存することで依存性の逆転を適用できる。
```mermaid
classDiagram

class UI_1
class Logic_1

class UI_2
class Logic_2
class Interface{
<<interface>>
}

Interface <|-- UI_2
Logic_2 --> Interface

Logic_1 --> UI_1



```
<a id="Chapter4"></a>
# サンプルプロジェクトでの解説

### 悪い例（依存性の逆転が適用されていない場合）
```mermaid
classDiagram

class UnrefactoredSwitch{
+ Activate()
}

class UnrefactoredTrap{
 + Enable()
 + Disable()
}

class UnrefactoredDoor{
+ Open()
+ Close()
}

direction TB
UnrefactoredSwitch --> UnrefactoredTrap
UnrefactoredSwitch --> UnrefactoredDoor 
```

この場合、上位モジュールである `UnrefactoredSwitch` が、下位モジュールである `UnrefactoredTrap` や `UnrefactoredDoor` に直接依存しているため、下位モジュールの変更の影響を受けやすくなっています。

### 良い例（依存性の逆転を適用）
```mermaid
classDiagram

class ISwitchable{
  + IsActive : bool 
  + Activate()
  + Deactivate()
}

class Door{
  + Activate()
  + Deactivate()
  + SlideDoor() : IEnumerator
}

class Trap{
  + Activate()
  + Deactivate()
}

class Switch{
  - ISwitchable
  + Toggle()
}

direction TB
ISwitchable <|-- Door
ISwitchable <|-- Trap
direction RL
Switch --> ISwitchable
```

依存性の逆転を適用することで、`Switch` は `ISwitchable`（インターフェース）に依存し、具体的な `Door` や `Trap` に直接依存しなくなりました。
これにより、下位モジュールの変更の影響を受けにくくなり、システムの柔軟性が向上します。


<a id="result"></a>
# まとめ
- 依存性の逆転の原則（DIP）は、上位モジュールが下位モジュールに直接依存せず、抽象に依存することでシステムの柔軟性を高める。
- 下位モジュールは変更されやすいため、直接依存を避けることで保守性が向上する。
- Unityプロジェクトでも、インターフェースや依存性注入を活用することで、DIPを適用できる。

<a id="reference"></a>
# 参考文献
- [Unityチュートリアルプロジェクト](https://github.com/Unity-Technologies/game-programming-patterns-demo)
- [Unityチュートリアルテキスト E-Book](https://unity3d.jp/game/game-ebooks/level-up-your-code-with-game-programming-patterns/)
Github Copilotで自己組織化マップを作ってみた

# 背景
学生時代の研究室でSOMを研究発表したので、数年ほど前になるが、もう一度再現してみようと思ったから。

# 自己組織化マップ(SOM)とは
ざっくりいうと、入力の特徴量を学習して、入力同士の関係を低次元へ落とし込む教師なし学習モデル。
詳しくは以下を参照。

https://ja.wikipedia.org/wiki/%E8%87%AA%E5%B7%B1%E7%B5%84%E7%B9%94%E5%8C%96%E5%86%99%E5%83%8F

# 早速VSCodeで作ってみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3500655/31392f8b-bca4-4a43-8269-3b88d5729ae2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3500655/0d0221bb-be05-4699-b8fd-13b159e5f670.png)

最初のコメントを途中まで入れると、そのあとのコメント、コードをGithub Copilotが自動で作成してくれた！！

## 結果
### 結果1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3500655/b2e50f2c-bbe5-41f3-95cd-696b1eceb982.png)

### 結果2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3500655/e0742e1d-f559-4622-91a6-9bf9e8784e97.png)

### 結果3
学習回数を100→10000にしてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3500655/9da29d01-6d4e-498a-993b-7a3ad266e66d.png)

# 感想
一次元だといまいちわからないから、次回は2次元にしてやってみようと思う。
Github Copilotを使えば、簡単なAIも自作できると思った。
今後も、Github Copilotを使ってSOMなど自作して試してみたいと思った。
サブモジュールのmodified:   .. (untracked content)をなんとかしたい

# はじめに
ルートでまとめてpushしてもサブモジュールディレクトリのステータスが表示されてしまうのでなんとかしたい

# 問題
こんな感じで表示され続ける
```
% git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   ... (untracked content)

no changes added to commit (use "git add" and/or "git commit -a")
```

# 対処
stackoverflowでいくつか対処法が提示されていましたが、1番わかりやすくて手っ取り早そうなものを選びました。以下のコマンドで該当箇所の変更を追跡しないようにできるみたいです
```
% git update-index --assume-unchanged サブモジュールのパス
```
これでmodified:   .. (untracked content)が表示されなくなりました
```
% git status
On branch master
nothing to commit, working tree clean
```

以下のコマンドで再度追跡対象にもできるみたいです
```
git update-index --no-assume-unchanged サブモジュールのパス
```

# おわりに
なんか別の良い対処法がありそう

# 参考

https://stackoverflow.com/questions/50167969/how-to-fix-modified-content-untracked-content-in-git
【イベントレポート】kintone若手交流会～初LTチャレンジ編～ #kintone若手交流会

いつも記事を読んでいただきありがとうございます！
モブエンジニア（[@mob-engineer](https://qiita.com/mob_engineer))です！

今回は2025.02.25（火）に開催した**kintone若手交流会～初LTチャレンジ編～**へ参加しましたので、アウトプットとしてイベントレポートを執筆しました。

初学者でもサクッと読めるように平易な表現で執筆しておりますので、お気軽に読んでいただければ幸いです。

#### イベントページ

https://kintone-junior.connpass.com/event/340880/

:::note info
誤字脱字、わかりづらい表現に関しては極力なくすように心がけていますが、リアルタイムで執筆しているため、もしかしたら誤字脱字があるかもしれません。
:::

:::note info
私もLT登壇していますが、その部分に関しては割愛しております。
:::

# 目次
- イベント概要
- LT
    - 大学時代はヒーローだった
    - KintoneにAIエージェントが来るとしたら
    - アミューズメント事業での法令処理事業で活用してみた
- まとめ

## イベント概要
>＊本イベントはkintoneに関わる34才以下の方を対象にしたイベントです＊
「kintone若手交流会」は同世代のkintone仲間を作りたい方向けに開催している有志イベントです。
「kintoneは触り始めたばかり！」「イベントや勉強会に行ったことがない……」。
そんな方もWelcomeです♪
今回の企画
今回は2025年最初の開催ということで、参加者の方の「初」の機会になればと思いまして……
「kintone LT未経験者限定！ 初kintone LT挑戦企画」をやります！
kintoneに関する社外LTが初めての方限定でお申込みいただけます。
ぜひ「参加枠（LTあり）」でお申し込みください！
＜LTのテーマ例＞
・kintoneを使って思ったこと＆気づいたこと
・初めて作ったアプリについて
・2025年、kintoneでこれやります宣言
※kintoneに関することならなんでもOKです♪
※本イベントはサイボウズ株式会社が開催するイベントではなく、ユーザーやパートナー、サイボウズ社員の有志が企画・開催するイベントです。
※「kintone」はサイボウズ株式会社の登録商標です。
---------------------------------------
こんな方におすすめです
・「同世代のkintone仲間を作りたい！」
・「社外とのつながりを持ちたいけどそういう場に行ったことがなくて怖い……」
・「kintoneに関するに初社外LT挑戦してみたい！」
・「kintoneの話をいろんな人としてみたいけど、経験も浅いし年上の人がいっぱいだと緊張しちゃう……」

## LT

### 大学時代はヒーローだった
- 自己紹介
    - エーエルジェイ所属のエンジニアの方
    - 愚者は経験を学び、賢者は歴史を学ぶ
    - 様々な方とのコミュニケーションを通じて情報共有を行っていく
- Kintoneが提供されたタイミング
    - 2011年に提供された
    - Kintoneとマルちゃん正麺は同じ誕生日
    - 昔はロゴが違っていた
    - 最初のころは時代を感じるサービス
    - 値段に関しても簡単に手が出せる感じではなかった
- アップデート変遷
    - 今の画面（UI）は2014年ごろから始まった
    - モバイル画面は2019年から
- 最後に伝えたいこと
    - 私とお友達になってください👍

### KintoneにAIエージェントが来るとしたら

#### 参考サイト

https://topics.cybozu.co.jp/news/2024/11/07-18881.html

- 自己紹介
    - Kintone歴半年の方
    - 好きなものは生成AI、メタバース
    - 元鳥人間の方
- OpenAI社のOperator利用
    - マウス操作なくKintoneアプリを開発できる
    - 実はKintoneとAIアプリの相性がいいのでは
    - 生成AIを活用してプログラミングができる
    - Kintone AI アシスタントなるサービスもでている
- 私たちの仕事
    - ヒトが外回りする時代になるかも

### アミューズメント事業での法令処理事業で活用してみた
- 自己紹介
    - 株式会社GENDA所属の方
    - Kintone利用歴1年の方
    - カラオケBanBanなどのアミューズメント事業を展開している
- 法令処理は
    - 法律に基づいて実際に運用していく取り組み
    - 風営法、消防法対応など
- 課題
    - 本部で行っている作業負荷が高い
        - 作業工数削減のために複数システムの統合を実施
    - 業務進捗管理の効率化
        - トヨクモ製品とKintone製品を組み合わせてアプリ開発を実施
- 現状
    - 一部店舗で運用を行っている
    - 継続的に運用を行っていく予定

## まとめ

Kintoneについては本LTを通じて触ってみたのですが、やはり面白い機能がたくさんあるなぁと思いました。そのうえで、本LTイベントを通じて、Kintoneをもっと触ってみたいと思いました！！

最後までお読みいただきありがとうございました！
CloudFront経由でAmplifyとS3にアクセス

# 目的
CloudFrontを利用して、パスの振り分けをやる。
今回は、移行中のWebサービスがあり、一部のパスをAWSアカウントAのAmplifyに他のパスをAWSアカウントBのALBに振り分ける。
またアカウントAにおいて、画像はS3で管理しており、画像はCloudFront経由で取得する。

この記事では、CloudFrontでAmplifyへの連携とS3アクセスの部分について触れる。

大事なポイントを3つ記載する↓

# ビヘイビアのオリジンリクエストのHostヘッダー

Amplifyは内部にCloudFrontを持っているめ、CloudFront→Amplifyというアクセスの際、Hostヘッダーを送ると、自身からリクエストと勘違いしてループする。

これに対して2つの対応方法がある。

| 方法 | 詳細 |
|:-:|:-:|
| HostヘッダーをAmplifyに送らない  | これは事例としていくつか見つかる。シンプルだが、Amplifyの中でリダイレクトなどがあると問題になる可能性があるらしい。ビヘイビアのオリジンリクエストポリシーで以下を選択するとできる。Managed-AllViewerExceptHostHeader
Hostヘッダーにオジリンのドメインで送る | これはあまり情報がないのでリスクがあるかも？あまり記事がないが、カスタムヘッダーを用いるとできるっぽい？



# キャッシュポリシー

Amplifyにも内蔵されたCloudFrontがあり、そこでもキャッシュは働いているはずなので、Amplify用のCloudFrontは、`Managed-CachingDisabled`　としCloudFrontではキャッシュしないようにする。実際、CloudFrontを活用することでさらに細かい制御ができると思うが、まずはシンプルにということでこの方法を選んだ。

・その他
Amplify用のキャッシュポリシーで以下がある。
- `Managed-Amplify-StaticContent`

- `Managed-Amplify-ImageOptimization`
ただしこれらは、キャッシュヘッダーとして　Hostヘッダーが含まれている。

そのため、Hostヘッダーをオリジンリクエストで送るなら(Hostヘッダーにオジリンのドメインで送るを選択した場合）使えるがそうでない場合は使えない。
最終的にAmplifyオリジンを持つCloudFrontビヘイビアの設定は以下のようになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52335/c5190a7c-f60c-45f6-af30-8b1d6f8c3d68.png)


# マルチオリジンとシングルオリジン
今回、CloudFront経由にするのはAmplifyとS3。それをマルチオリジンかシングルオリジンとして扱うか。


#### マルチオリジンのケース(今回は採用しなかった)
1つのCloudFrontでAmplifyとS3をオリジンとして登録

→ビヘイビアに問題あり。画像はNext.jsの配下に/images/publicで存在するめ単純に /*.jpeg などでS3のオリジンに振り分けてしまうと、Next.jsの画像を見に行けなくなる。S3とNext.jsでパスを事前に分けておけば良いが、現時点でS3の構成を見直すのは影響が大きくなりそうなので避けたい。

#### シングルオリジン(こちらを採用)

二つのCloudFrontを作成
- Amplifyをオリジンとして持つCloudFront
- S3をオリジンとして持つCloudFront

CloudFrontは二つになるがシンプルになる。用途としてもAmplifyをオリジンとしてもつCloudFrontはあくまで振り分け用として使うことで分ける意味はありそう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52335/20cdf8b2-cd9b-4cfb-9c7d-650b0fa544e4.png)


参考にした記事
https://www.skyarch.net/blog/cloudfront-amplify-%E6%A7%8B%E6%88%90%E3%81%A7%E3%81%AF-host-%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%82%92%E8%BB%A2%E9%80%81%E3%81%97%E3%81%A6%E3%81%AF%E3%81%84%E3%81%91%E3%81%AA%E3%81%84/
小道具：macOS用ファインダー向けディレクトリ国際化

たとえば日本語ディレクトリ

```console:
% ls -1F
サンプル/
```

をファインダーでは見かけ上変化しないディレクトリ構造

```text:
sample.localized
   + .localized
      + ja.strings
          内容: "sample" = "サンプル";
```

に変更したいとき、コマンドラインで

```console:
% python3 ja2loca.py サンプル sample
```

として簡単に済ませるためスクリプトです。

処理内容

1. 元ディレクトリに ".localized" ディレクトリを追加
1. ".localized/ja.strings" ファイルを作成
1. ディレクトリ名を変更

動作確認は macOS 15.3 で行っています。

:::note warn
エラー発生時の回復処理は行いません。ゴミが残ったり壊れた状態になることが予想されます。
:::

```Python:ja2loca.py
#!/usr/bin/env python3

import argparse
import os
import sys
from os.path import stat


def noop(*_args, **_kwargs):
    pass


message = noop
verbose = noop


def xstat(path):
    try:
        return os.stat(path)
    except OSError:
        return None


class Failed(Exception):
    pass


def main():
    parser = argparse.ArgumentParser(description='macOS用ファインダー向けディレクトリ国際化')
    parser.add_argument('-q', '--quiet', action='store_true')
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('SRC', help='表示（旧ディレクトリ）名')
    parser.add_argument('NEW', help='ASCII名（.localized が追加される）')

    args = parser.parse_args()
    flag_quiet = args.quiet
    flag_verbose = args.verbose

    message = noop if flag_quiet else print
    verbose = message if flag_verbose else noop

    def warning(msg):
        message(f'warning: {msg}')

    def write_text(path, text):
        verbose(f'write: "{path}"')
        with open(path, 'w') as fp:
            fp.write(text)

    dot_loca = '.localized'

    def islocalized(path):
        return path[-len(dot_loca):] == dot_loca

    src_path = args.SRC.rstrip('/')
    src_stat = xstat(src_path)
    if not src_stat:
        raise Failed(f'"{src_path}" は存在しません')
    if not stat.S_ISDIR(src_stat.st_mode):
        raise Failed(f'"{src_path}" はディレクトリではありません')
    if islocalized(src_path):
        raise Failed(f'"{src_path}" の後置名が "{dot_loca}" です')
    ja_name = os.path.basename(src_path)

    new_path = args.NEW.rstrip('/')
    if islocalized(new_path):
        cut_path = new_path[:-len(dot_loca)]
        warning(f'"{new_path}" から "{dot_loca}" を削除した "{cut_path}" を使用します')
        new_path = cut_path
    new_stat = xstat(new_path)
    if new_stat:
        warning(f'"{new_path}" が存在します')
    en_name = os.path.basename(new_path)

    if en_name == ja_name:
        raise Failed(f'元と先が同じ名前 "{ja_name}" です')

    loc_path = f'{new_path}{dot_loca}'
    loc_stat = xstat(loc_path)
    if loc_stat:
        raise Failed(f'"{loc_path}" が存在します')

    str_path = f'{src_path}/{dot_loca}'
    str_stat = xstat(str_path)
    if not str_stat:
        verbose(f'mkdir: "{str_path}"')
        os.mkdir(str_path)
        str_stat = os.stat(str_path)
    if not stat.S_ISDIR(str_stat.st_mode):
        raise Failed(f'"{str_path}" はディレクトリではありません')

    write_text(f'{str_path}/ja.strings', f'"{en_name}" = "{ja_name}";\n')

    verbose(f'rename: "{src_path}" → "{loc_path}"')
    os.rename(src_path, loc_path)
    return 0


try:
    sys.exit(main())
except Failed as e:
    print(f'error: {e}')
    sys.exit(2)
```
slice(1) × forEach() でスマートに配列処理！

高2の僕が「配列の要素を出力するだけでしょ？」と油断したら、思わぬ落とし穴が…。
for 文でループしたら、余計な値まで出力されてしまった！
解決策は slice(1) × forEach() のコンボ。これがシンプルで強い！

**NG例**（失敗コード）
```js
rl.on('close',() => {
    for (let i = 0; i < lines.length; i++) {
        console.log(lines[i]);  // n（最初の要素）まで出力されてしまう！
    }
});
```
**OK例**（改善コード）
```js
rl.on('close',() => {
    lines.slice(1).forEach(num => {
        console.log(num);
    });
});
```

**ポイント**
✅ slice(1) で最初の要素（n）を除外
✅ forEach() でシンプルにループ処理

**学んだこと**
💡 slice(1) は、2つ目の要素から最後までの新しい配列を返す
💡 forEach() は、配列の要素ごとに処理を実行するのに便利
💡 意図しない出力を防ぐには、データ構造をしっかり理解することが大事！

僕の失敗談と解決話→ [Paizaで基本マスター](https://paizabeginner.wordpress.com/2025/02/25/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bcslice-x-foreach-%e3%81%a7%e3%82%b9%e3%83%9e%e3%83%bc%e3%83%88%e3%81%ab%e5%87%ba%e5%8a%9b%ef%bc%81/ )
ABC380~389の振り返り集

ABC380(正確には386)からABC389までの振り返りへのリンク集です(次のまとめ記事が出るまでピックアップにしておきます)
[ABC386](https://qiita.com/friedrice/items/ef0db2177e5904fd2425)
[ABC387](https://qiita.com/friedrice/items/1e6327792ecc3ebe302f)
[ABC388](https://qiita.com/friedrice/items/c1abb3a639d11698afb4)
[ABC389(AHC041も含む)](https://qiita.com/friedrice/items/c80a926ddcd2e3d39e2a)
Windows98環境のために

# Virtaul BoxでWindows98が動くCPUに限界がある？
どうも最近のIntel CPUにVirtual Boxを入れてWindows98を入れてもまともに動かないようです。
（設定を工夫すると動くようではありますがまともではない！）
手持ちのPCで第11世代以降（第10世代は持っていないのでわからない）のCPUにLinuxをいれてVirtual BoxでWindows98を動かそうとしたところエラーが出ます。
なので、第２世代以降から第７世代までのPCは大切にしたほうがいイイかもしれない。
古い環境のサポートができなくなるので・・・
Go言語のnewとmakeを完全解説！違いと使い分けを徹底的に理解しよう

## はじめに 
Go言語でメモリを確保する際に使われる`new`と`make`。どちらも初学者には混同しがちですが、それぞれの役割は大きく異なります。本記事では、それぞれの機能や使い分けについて、具体例を交えて分かりやすく解説します。


## `new`と`make`の基本的な違い

### `new`
- **目的**: メモリを割り当て、ゼロ値で初期化する。
- **戻り値**: 割り当てられたメモリへのポインタ。
- **対象**: 値型（例: `int`, `struct` など）。

`new`は単純にメモリを確保するだけで、複雑な初期化処理は行いません。

```go
package main

import "fmt"

func main() {
    p := new(int)          // *int型のメモリを確保
    fmt.Println(*p)        // => 0 (ゼロ値)
    *p = 42                // 値を代入
    fmt.Println(*p)        // => 42
}
```

### `make`
- **目的**: スライス、マップ、チャネルを初期化する。
- **戻り値**: 初期化されたスライス、マップ、またはチャネル（ポインタではない）。
- **対象**: 参照型（スライス、マップ、チャネル）。

`make`は、これらの参照型を初期化し、利用可能な状態にします。

```go
package main

import "fmt"

func main() {
    s := make([]int, 3)    // 長さ3のスライスを作成
    fmt.Println(s)         // => [0 0 0]
    
    m := make(map[string]int) // 空のマップを作成
    m["key"] = 100
    fmt.Println(m)         // => map[key:100]
}
```

## 使い分けのポイント

`new`と`make`は役割が明確に分かれているため、使い分けを覚えるのは簡単です。

1. **値型や構造体を初期化する場合** → `new`を使用
   - ポインタが必要な場面で便利。
   - `struct`の初期化にも使えるが、通常はリテラルの方が簡潔。

```go
   type Person struct {
       Name string
       Age  int
   }

   func main() {
       p := new(Person)       // *Person型
       fmt.Println(p.Name)    // => "" (ゼロ値)
       p.Name = "Alice"
       fmt.Println(p)         // => &{Alice 0}
   }
```

2. **スライス、マップ、チャネルを初期化する場合** → `make`を使用
   - `make`が必要なのはこれらの参照型だけ。
   - 初期化されていないスライス、マップ、チャネルは`nil`であり、操作するとパニックが発生する。

```go
   func main() {
       var m map[string]int  // nilのマップ
       // m["key"] = 1       // パニック発生
       m = make(map[string]int)
       m["key"] = 1          // 正常に動作
       fmt.Println(m)        // => map[key:1]
   }
```

## 注意点とベストプラクティス

1. **構造体の初期化はリテラルを優先**
   `new`を使うよりも、構造体リテラルを使う方が読みやすく、簡潔です。

```go
   p := &Person{Name: "Alice", Age: 30} // 推奨
```

2. **参照型は必ず`make`で初期化**
   特にマップやチャネルでは、`make`を使わずに操作しようとするとエラーが発生します。

3. **パフォーマンスを意識した選択**
   - スライスの容量を明示的に設定する場合は`make`を使うことで効率的なメモリ割り当てが可能です。


## `new`と`make`の違いをまとめる

| 特徴               | new                     | make                    |
|--------------------|-------------------------|-------------------------|
| 対象               | 値型、構造体            | スライス、マップ、チャネル |
| 戻り値             | ポインタ                | 初期化済みのオブジェクト |
| 初期化の深さ       | ゼロ値のみ              | 完全な初期化            |
| 主な用途           | メモリ割り当てとゼロ値   | 参照型の初期化          |

## おわりに

`new`と`make`の違いを正しく理解すれば、Go言語のメモリ管理を効率的に行うことができます。本記事を参考に、それぞれの関数を適切に使い分けて、より明確で安全なコードを書いていきましょう！
【Tips】【WinSCP】サーバーのパスワードを忘れた時は・・・

## はじめに
こんにちは。こんばんは。エンジニアの長谷川と申します。
今回はWinSCPの小ネタを備忘を兼ねて記載します。

### 環境
WinSCP　ver.6.3.6（6.1.1でも確認）

### WinSCPとは
Windows上で動くリモートサーバーとのFTP、SFTP、SCPなどをGUIで操作できるクライアントツールです。

### ありがちな困ったこと
リモートサーバーへの接続に必要なパスワード、忘れることはありませんか？
WinSCPでは接続先ごとにパスワードを保存しておくことができます。
（セキュリティ上の是非はおいておきます。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/5c2b3667-a872-47d1-9a33-dd77c67ba6ef.png)

しかし、保存しているが故に覚えておらずTeraTermなどのターミナルツールでアクセスしようとしたときに困ることがあります。

### 保存したパスワードの確認
WinSCPでは保存されたパスワードを確認することができます。
手順は下記の通りです。

１．パスワードを確認したいサーバーを選択し、管理メニューを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/a79761f5-c66f-4f98-8376-6d602c2e4023.png)

２．セッション URL/コードの生成を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/dbe8660c-9460-4243-935e-8d5912719aac.png)

３．表示された内容からパスワードを確認
・URLタブの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/0a0e0c3c-a794-48b3-b05d-405d9df53da5.png)

・スクリプトタブの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/6ee1f488-2f02-496b-87fb-c574d22cd2de.png)

・.NET用コードタブの場合
前述の通り

## 終わりに
現場でWinSCPを使用していてパスワードの保存をしている方、忘れてしまった場合の助けになれば幸いです。

:::note warn
パスワードの保存を勧めるものではありません。
:::

以上、長谷川でした。
Create React Appが非推奨になった件について

こんにちは！最近、Reactプロジェクトを始める際の定番だった「Create React App（CRA）」が公式に非推奨（deprecated）になりました。長年React開発の入り口として親しまれてきたツールですが、2025年1月にFacebook（Meta）のチームが正式に非推奨宣言を行いました。

この記事では、この変更が何を意味するのか、そして代わりにViteを使ってReactプロジェクトを始める方法について、初心者にもわかりやすく解説します。

## Create React Appが非推奨になった理由

CRAは長い間、Reactの学習を始めるための素晴らしいツールでした。しかし、時間が経つにつれていくつかの問題点が目立つようになりました：

- 開発サーバーの起動が遅い
- ビルド時間が長い
- 設定のカスタマイズが難しい（ejectしないと内部設定を変更できない）
- 最新のReact（React 19）との互換性問題

GitHubのプルリクエスト[#17003](https://github.com/facebook/create-react-app/pull/17003)で、CRAの開発者たちは「本番環境での使用を推奨しない」と明言し、代わりに[React公式サイト](https://react.dev/learn/start-a-new-react-project)で紹介されている代替ツールの使用を勧めています。

## Viteとは？なぜ良いのか？

[Vite](https://vitejs.dev/)（ヴィート、と発音します）はVue.jsの作者であるEvan You氏によって作られた、モダンなフロントエンド開発ツールです。Reactだけでなく、Vue、Svelte、Vanilla JSなど様々なフレームワークに対応しています。

Viteの主な利点：

1. **超高速な開発サーバー**: ホットモジュールリプレイスメント（HMR）が非常に速く、開発体験が格段に向上します
2. **短いビルド時間**: 本番用ビルドもCRAと比べて大幅に高速です
3. **シンプルな設定**: 必要に応じて簡単に設定をカスタマイズできます
4. **最新技術への対応**: ES Modules、React 19など最新の技術に対応しています
5. **軽量**: 必要なものだけを含むため、プロジェクトが軽量です

## Viteで新しいReactプロジェクトを始める方法

それでは実際に、Viteを使ってReactプロジェクトを始める方法を見ていきましょう。コマンド一つで簡単にセットアップできます！

### 1. プロジェクトの作成

以下のコマンドを実行するだけです：

```bash
# npm を使う場合
npm create vite@latest my-react-app -- --template react

# または yarn を使う場合
yarn create vite my-react-app --template react

# または pnpm を使う場合
pnpm create vite my-react-app --template react
```

TypeScriptを使いたい場合は、`react`の代わりに`react-ts`テンプレートを指定します：

```bash
npm create vite@latest my-react-app -- --template react-ts
```

### 2. プロジェクトフォルダに移動

```bash
cd my-react-app
```

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

```bash
npm install
# または yarn、pnpm
```

### 4. 開発サーバーの起動

```bash
npm run dev
# または yarn dev、pnpm dev
```

これだけで、高速な開発サーバーが起動し、ブラウザで`http://localhost:5173/`（デフォルト）にアクセスすれば新しいReactアプリが表示されます！

## Create React AppからViteへの移行

すでにCreate React Appで作ったプロジェクトがある場合、Viteへの移行は少し手間がかかりますが、それほど難しくありません。

主な手順は：

1. Viteプロジェクトを新規作成する
2. `package.json`から必要な依存関係を新しいプロジェクトに追加する
3. `src`フォルダの内容を新しいプロジェクトにコピーする
4. 一部のインポートパスやコードを調整する（CRAとViteでは若干の違いがある）

詳細な移行手順は必要に応じて別の記事で解説しますね！

## まとめ

Create React Appが非推奨になったことは、React開発の新しい時代の始まりを意味します。Viteを使うことで：

- 開発速度が格段に向上する
- 最新のReactの機能をすぐに使える
- シンプルで軽量なプロジェクト構造を維持できる

特に初心者の方にとって、Viteの方がCRAよりも使いやすいと感じるかもしれません。設定が透明で、カスタマイズも簡単なので、Reactの学習に集中できます。

これからReactを学び始める方、新しいReactプロジェクトを始める方には、ぜひViteを試してみることをおすすめします！

みなさんのViteでの開発体験はいかがですか？コメントで感想やTipsを共有していただけると嬉しいです。

## 参考リンク

- [ViteのReactガイド](https://vitejs.dev/guide/)
- [React公式の新しいプロジェクトの始め方](https://react.dev/learn/start-a-new-react-project)
- [Create React App非推奨のGitHubプルリクエスト](https://github.com/facebook/create-react-app/pull/17003)
AWS SavingsPlansの試算・購入について（EC2）

今回はSavingsPlansの概要、試算から購入までの手順を紹介します。
※以降SavingsPlansはSPsと記載します。


# AWS SavingsPlansとは？
予め利用する金額（USD/時間）をコミットすることにより最大72%の割引が受けられます。
特定期間（1年または3年）利用する前提で月額利用料が割り引かれます。
※コミット額に到達しない場合でも必ず支払いが発生します。
※キャパシティ予約はされません。オンデマンドキャパシティ予約を割り当てている環境でも購入したSavings Plansが適用されます。

#### つまり...
1年または3年の縛りはありますが、事前に購入することでオンデマンド料金より安価に利用できる可能性があるというサービスです。
※SPsを購入することで必ずしも安くなるというわけではありません。
※インスタンスの稼働率によってはオンデマンド料金の方が安価になる場合があるため購入前に試算することを推奨します。


#### EC2の場合、SPs購入は2種類から選択が可能
2つのプランの特徴
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001100/7a434efe-8797-49ae-a0e6-e68216fdf4e3.png)

#### まとめると...
| SPsタイプ |適用範囲| 割引率|  
|:-----------|------------:|------------:|
| Compute SavingsPlans| 購入後の変更可能| 低め|
| EC2 Instance SavingsPlans  | 指定した条件のみ適用| 高め|

| 支払い方法 |支払い時期| 割引率|  
|:-----------|------------:|------------:|
| 全額前払い| 購入時に全額支払い| 高め|
| 一部前払い | 購入時に半分、残りは毎月支払い| 中くらい|
| 前払いなし | 毎月支払い| 低め|


# ①実際に試算してみましょう

試算する際は、AWSのサイトに記載の試算ツールまたは、AWS Pricing Calculatorを利用してみてください。

#### 今回はAWSサイトに記載の試算ツールを利用していきます。
（例）m5.xlarge
| インスタンス |OS|リージョン|テナンシー| 期間| 支払い|
|:----------|------------:|------------:|------------:|------------:|------------:|
| m5.xlarge| Linux|東京|共有| 1年|全額前払い|


#### Compute SavingsPlansの試算結果

<dl>
  <dt>SPs料金</dt>
  <dd>時間単価：USD0.185</dd>
  <dd>年額　　：USD0.185×730h×12mos=USD1620.6</dd>
  <dt>オンデマンド料金</dt>
  <dd>時間単価：USD0.248</dd>
  <dd>年額　　：USD0.248×730h×12mos=USD2172.48
    <dt>削減率：25％</dt>
</dl>

※1か月=約730hと想定
※12mos=12か月

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001100/cbc24ee1-1165-451c-9bee-db28479b0540.png)

#### EC2 Instance SavingsPlansの試算結果

<dl>
  <dt>SPs料金</dt>
  <dd>時間単価：USD0.146</dd>
  <dd>年額　　：USD0.146×730h×12mos=USD1278.96</dd>
  <dt>オンデマンド料金</dt>
  <dd>時間単価：USD0.248</dd>
  <dd>年額　　：USD0.248×730h×12mos=USD2172.48
<dt>削減率：41％</dt>
</dl>

※1か月=約730hと想定
※12mos=12か月

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001100/6f57f5ea-d2e4-4ac8-b438-cc998983d1c0.png)

このようにしてSPsの時間単価や年額を試算することができます。



***
■AWSサイトの試算ツール
引用：
https://aws.amazon.com/jp/savingsplans/compute-pricing/

■AWS Pricing Calculator（CPU、メモリ、EBSなどを含めたい場合はこちらを利用します）
引用：
https://calculator.aws/#/

***


# ②AWSコンソールにて購入してみましょう
1.AWSコンソールにログイン
2.[Billing and Cost Management]の[Savings Plansの購入]をクリック
3.購入画面に以下の購入情報を記載する
　・SPsタイプ（Compute SavingsPlans/EC2 Instance SavingsPlans）
　・期間（1年/3年）
　・時間単位のコミットメント
　・支払いオプション（前払いなし/一部前払い/全額前払い）
　・開始日（日時指定の予約購入が可能）
4.購入内容を確認後、[カートに追加]をクリック
5.すべての購入内容に問題がなければ[注文書の送信]をクリック

【補足】
　・SPsタイプが同じであればコミット額合計での購入が可能です。
　・開始日時の設定を行う際はUTC（協定世界時）で設定してください。

# 最後に

AWS利用料のコストの最適化を検討されている方、ぜひSPsの購入を検討してみてはいかがでしょうか。
Intel 13世代/14世代CPUの不具合に対するドスパラの対応がすごかった件

最近、Intelの**13世代/14世代CPU**を搭載したPCで、不具合（主にブルースクリーンやソフトのクラッシュなど）が発生するという報告が散見されます。  
今回は、私の所有する **GALLERIA（ドスパラ製）** のPCで実際に不具合を経験し、ドスパラのサポートを利用したところ、思いのほか素早く丁寧な対応をしてもらえたので、その経緯を共有します。

---

## 1. Intel 13世代/14世代CPUの不具合について

私の環境で確認した主な症状は、以下の通りです。

- ゲーム中や高負荷時に突然ブルースクリーン（Stopエラー）が発生
- アプリケーションの異常終了（クラッシュ）

特にEscape from Tarkovを始めてからというもの頻発するようになってしまいました。
これらはCPUやマザーボード、BIOS、ドライバなど多岐にわたる要因が考えられ、ネット上でも同様の報告がいくつか上がっています。

---

## 2. 不具合が起きたPCに対して行ったこと

不具合が発生した際、まずは**自力で原因を特定**するために、以下の対策を実施しました。

1. **メモリの整合性チェック（Windows標準機能）**  
   - OS標準のメモリ診断を実行するも特に問題なし。
1. **ミニダンプ（miniDump）の確認**  
   - ブルースクリーン発生時に作成されるダンプファイルを解析。  
   - 不具合の原因アプリ（主にbattlEyeやRiot Vangard）を特定し、アンインストール→再インストールを試みる。
1. **ゲーム自体のアンインストール/インストール**  
   - 不具合が起きていたゲームソフトを再インストール。  
   - 安定せず、再度ブルースクリーン発生。
1. **BIOSアップデート**  
   - マザーボードベンダーが提供する最新版に更新。  
   - 明確な改善は見られず。
1. **ドライバのアップデート**  
   - チップセットドライバやグラフィックスドライバなどを最新版に。  
   - 効果はなし。
1. **memtest86の実行**  
   - Windows標準のメモリチェックだけでは不安だったため、memtest86で詳細診断。  
   - **エラーなし**で物理的なメモリ不良は否定。

上記の手順を踏んでも症状が継続して発生したため、ハードウェア面に問題があると考えました。

---

## 3. ドスパラの対応方針

最終的に自力で原因を特定できなかったため、PCメーカーである**ドスパラ**（サードウェーブ）に問い合わせました。サポート窓口のやり取りは以下のような流れです。

- 状況のヒアリング  
  （どのような操作時にどれくらいの頻度でブルースクリーンが発生するか）
- 既に試した対処法の確認  
  （メモリチェック、ドライバ更新、BIOS更新など）
- ウェブサイトから製造番号を入力してIntelの不具合の対象であることを確認

受付時点でヒアリングがとても丁寧で、こちらの話をしっかり聞いてもらえたため好印象でした。

---

## 4. 送ったあとに気づいたこと

サポートにPCを送ってから判明したのですが、**私のPCにはGALLERIA向け純正BIOSではなく、ASUSのBIOSが適用**されていました。  
「これはサポート外扱いになってしまうかもしれない…」と内心不安だったのですが、結果的に問題なくサポート対応してもらうことができました。

---

## 5. CPUの交換＋BIOS更新がされた状態で返却

ドスパラから返送されたPCには、以下の修理・更新が施されていました。

- **CPU交換**（検証の結果、CPUが不具合の一因と判断された模様）  
- **BIOSをGALLERIA向け最新バージョンに更新**

その後PCを使ってみても、ブルースクリーンなどの不具合は発生せず、安定して稼働しています。

---

## まとめ

- **Intel 13世代/14世代CPU**を搭載したPCでブルースクリーンやクラッシュが起きる場合、まずはドライバやBIOSの更新・メモリチェックなど基本的な対策を試す。  
- それでも改善しない場合、ハードウェア側に問題がある可能性が高い。  
- **ドスパラ（サードウェーブ）のサポート**は受付から修理・報告までスムーズかつ丁寧だった。  
- メーカー推奨外のBIOSを適用していても、誠実に対応してもらえる場合がある（ケースバイケース）。  
- 結果として、**CPUの交換と純正BIOSの更新**によって問題は解消された。

不具合で悩んでいる方の参考になれば幸いです。特に、**自前でいろいろ対策しても直らない場合は、一度メーカーサポートを利用してみるのがおすすめ**です。

---

### 参考情報

- [Intel公式サポート](https://www.intel.co.jp/content/www/jp/ja/support.html)  
- [ドスパラ サポートページ](https://www.dospara.co.jp/support/)  
- [memtest86 公式サイト](https://www.memtest86.com/)

何かご質問やご意見があれば、ぜひコメント欄にてお聞かせください。ご覧いただきありがとうございました！
【OutSystems】ExcelToRecordListにおける空白行・空白セルの扱い

## はじめに
Excelファイルからデータを取り込むことは多々あります。
OutSystemsではExcelToRecordListを利用してExcelファイルを読み込み、Listに変換することができます。しかし、Excelファイルに空のデータが含まれている場合、どのように変換されるのでしょうか？
気になったので検証してみました。

## 動作環境
- OutSystems（バージョン 11）

## 検証
OutSystemsでExcelファイルをアップロードし、List化されたデータをJSONに変換して表示するシステムを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945506/41b4c572-a4cb-45a6-875a-c85c7458f372.png)

以下の4つのパターンを検証します。
1. 空白行の場合
2. 先頭列が空白セルの場合
3. 先頭列以外に空白セルがある場合
4. 読み込み対象外の列のみに値がある場合

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945506/b85fe86f-5a62-4227-89f3-a7a7417c35f1.png" width=50%>


### ■ ① 空白行の場合
空白行を含むファイルをアップロードしました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945506/aef2f8bc-8234-4b08-a827-3894a73a158a.png" width=50%>

結果は以下の通りです。空白行はスキップされ、後続行が読み込まれています。
```json
[
  {
    "St_Employee": {
      "Id": 1,
      "Department": "総務",
      "Name": "田中"
    }
  },
  {
    "St_Employee": {
      "Id": 2,
      "Department": "人事",
      "Name": "高橋"
    }
  }
]
```

### ■ ② 先頭列が空白セルの場合
先頭列を空白セルにした行を含むファイルをアップロードしました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945506/a35d2d74-28e4-4b57-9bc9-87c048026f7a.png" width=50%>

結果は以下の通りです。2行目はスキップされずにIdが空の状態で読み込まれています。
```json
[
  {
    "St_Employee": {
      "Id": 1,
      "Department": "総務",
      "Name": "田中"
    }
  },
  {
    "St_Employee": {
      "Department": "人事",
      "Name": "高橋"
    }
  },
  {
    "St_Employee": {
      "Id": 3,
      "Department": "営業",
      "Name": "佐藤"
    }
  }
]
```

### ■ ③ 先頭列以外が空白セルの場合
先頭列以外の読み込み対象列に空白セルがある行を含むファイルをアップロードしました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945506/2bcdd8b9-55e6-4c34-973e-dc602f6bb8d0.png" width=50%>

結果は以下の通りです。3行目はNameが空の状態で読み込まれています。
```json
[
  {
    "St_Employee": {
      "Id": 1,
      "Department": "総務",
      "Name": "田中"
    }
  },
  {
    "St_Employee": {
      "Id": 2,
      "Department": "人事"
    }
  },
  {
    "St_Employee": {
      "Id": 3,
      "Department": "営業",
      "Name": "佐藤"
    }
  }
]
```

### ④ 読み込み対象外の列のみに値がある場合
読み込み対象外の列のみに値がある行を含むファイルをアップロードしました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945506/9816dd74-4d8c-4810-bd30-c763838711bc.png" width=50%>

結果は以下の通りです。3行目はスキップされ、後続行が読み込まれています。
```json
[
  {
    "St_Employee": {
      "Id": 1,
      "Department": "総務",
      "Name": "田中"
    }
  },
  {
    "St_Employee": {
      "Id": 3,
      "Department": "営業",
      "Name": "佐藤"
    }
  }
]
```

## おわりに
読み込み対象列に値がある行はすべてListに変換されますが、読み込み対象列に値がない行や空白行はスキップされ、Listには追加されません。 
ExcelToRecordListを使用する際は、この動作を理解し、適切な対応行う必要があります。
Rustはとっつきにくい

## Rustの難しさ

Rustの難しさは、よく所有権システムということだと言われるが、やってみると、所有権で難しくなるようなプログラミングは、他の言語でも難しかったり、いろいろ問題が起きたりするので、難しいのですが、プログラミングが難しいことを要求しているだけで、言語が難しいのではないと思います。

実際プログラミングをしてみると、違うところが難しいなと思いました。

## enumが独特な仕様

enumというのは、列挙型ということですが、他の言語では、定数を列挙する形になります。

```
enum AAAA {
ONE,
TWO,
THREE
}
```

みたいに、定数を列挙する形になります。
Javaみたいにクラスみたいなこともできたりすることもあるのですが、基本は、定数を選ぶということだけです。

ところが、Rustでは、Enumに構造体のようなものを定義できる。

```
enum AAA {
ONE(String),
TWO(String,String),
THREE
}
```

のような形にできる。

## 構造体の継承ができない

他の言語にあるclassはないです。別に構造体structで似たようなものは作れます。
ただclassのように直接メソッドを定義できず、imp文でメソッドを定義します。

まあ、面倒くさいと言えば面倒なのですが、他の言語のclassの実装は、
同じような形に分解しているはずなので、ハードウエアに近い形であると思います。

しかし、classと違って、継承ができない。traitで、他の言語のinterfaceみたいなことはできるのですが、
特に構造体のメンバを拡張するみたいなことはできません。

なので、継承ではなく、所有という形で構造体を拡張する必要があります。

```
pub struct Base {
 hoge: u8,
}

impl Base {
 pub fn new(hoge: u8 ) -> Self {
   Self {
     hoge,
   }
 }
}

trait Trait {
  fn get_hoge(&self) -> u8;
}

impl Base for Trait {
 pub fn get_hoge(&self) -> u8 {
     self.hoge
 }
}
pub struct Child {
  base: Base,
}

impl Child {
  pub fn new(hoge: u8) -> Self {
    Self {
      base: Base::new(hoge)
    }
  }
}

impl Child for Trait {
 pub fn get_hoge(&self) -> u8 {
     self.base.get_hoge()
 }

}
```

みたいな感じに書かないといけないです。

## 継承を使わない形に実装する

無理やり、他の言語の継承のコードをそのまま持ってくると、めちゃくちゃ面倒なことになります。
しかし実は、Rustの場合は、前述のenumを使うと、継承をenumで書き換えて、
他の言語のように実行時にクラスの状態から関数を呼び出すような（仮想関数）コードではなく、
コンパイル時にコードを決定することができます。

継承されたChildをenumに直接定義します。

```
enum hogehoge {
  Base(u8),
  Brother(u8),
  Sister(u8),
}


```

そしてmatch文で直接コードを書きます。
必要であれば、Baseと同じコードにし、
特殊処理が必要であれば、別に書き換えます。

```

match fuga {
    hogehoge::Base(piyo) => {
    //親
    ///aaa
    }
    _ => {
    //子
    }
}

```

実際ハードウエア的には、こういうふうに実装した方が、コンパイル時にバグがわかるし、
実際の書き出されたコードも高速なコードを出力します。

要するに、既存コードをRust化するには、頭の中で、高速化をイメージして、
そのイメージをコードに直すと、Rustのコードになると思います。

この辺のコード変換は、結構経験がいりそうな感じで、いろいろ経験が必要かな。
formatDate メモ

function formatDate(dateString) {
    if (!dateString) return "未設定"; // null, undefined, 空文字の対策

    let date = new Date(dateString);

    // `Invalid Date` のチェック（無効な日付なら "未設定"）
    if (isNaN(date.getTime())) {
        return "未設定";
    }

    // 年・月・日を取得して `YYYY/MM/DD` の形式に変換
    let year = date.getFullYear();
    let month = String(date.getMonth() + 1).padStart(2, "0"); // 0始まりなので +1
    let day = String(date.getDate()).padStart(2, "0");

    return `${year}/${month}/${day}`;
}
SPSSで変数を集約する

　SPSSで複数の変数を同一の変数に集約するシンタックスの書き方の覚書です。
# はじめに
　SPSSでアンケートの集計をするときに、同じ設問が複数の設問にわかれてしまうことがあります。これを SUMMARIZE で集計するとき、以下のように性別のようなカテゴリ変数は列になります。

| | 変数１ | 変数２|合計|
|---------|---------:|---------:|---------:|
| 回答数  | 100|200|300|
| 構成比  |33.3|66.7|100.0|

　しかし、カテゴリ変数を行に配置したい場合もあります。このことを実現するには VARSTOCASES （var to cases）というコマンドを使います。
# やりたいこと
　一つのレコード（例えば事業所データ）に性別の人数（例えば従業員数）が gender_male, gender_female, gender_other の３つの変数に分かれて集計されていたとします。このデータを集約して全ての事業所の性別の人数を SUMMARIZE で集計する場合、デフォルトでは性別の合計が列方向になりますが、これを行方向にします。
# シンタックスの書き方
　VARSTOCASES というコマンドでで複数の変数を gender_count　という変数に集約します。

```:SPSS Syntax
VARSTOCASES
  /MAKE gender_count FROM gender_male gender_female gender_other
  /INDEX Gender.

VALUE LABELS Gender
    1 男
    2 女
    3 その他.

SUMMARIZE 
  /TABLES= gender_count BY Gender
  /TITLE='ケースの集計'
  /FORMAT=NOLIST TOTAL
  /MISSING=VARIABLE
  /CELLS=SUM.    
```
すると、以下のようにカテゴリ変数を行方向に展開することができます。

|Gender|合計|
|---------|---------:|
|男| 290|
|女| 200|
|その他|10|
|合計|500|
【応用情報】損益分岐点計算

こんにちは、新人エンジニアの三上です。

今回は、応用情報技術者試験の勉強をしている際に、損益分岐点分析の問題で分かりやすい考え方を見つけたので共有させていただきます。

## 損益分岐点
損益分岐点に関連する各費用をまとめて示す。

| 売上高 | 変動費 | 固定費 | 営業利益 |
|---:|---:|---:|---:|
| 2000 | 800 | 900 | 300 |

売上高の計算式は以下となる。

売上高 = 変動費 + 固定費 + 営業利益
　　　 = 変動比率 * 売上高 + 固定費 + 営業利益


---

### 売上高グラフ

| 売上高 | 収益 |
|---:|---:|
| 0 | 0 |
| 2000 | 2000 |

x軸に売上高、y軸に収益をとったときの売上高グラフの式は以下となる。
y = x ・・・①

---

### 総費用グラフ

| 売上高 | 収益 |
|---:|---:|
| 0 | 900 |
| 2000 | 1700 |

※収益の差分が変動費と同額となる。

総費用のグラフの式は以下となる。
y = Sx + b ・・・②
　S：変動比率 = 800 / 2000
　b：固定費 = 900

① と ② のグラフの交点Aが損益分岐点となる。（総費用と売上高が釣り合う点）

① = ②
x = Sx + b
x(1-S) = b
x = b / (1-S) ・・・(<font color="Red">A</font>)

上記が損益分岐点売上高となる。（Aとする）
※1-S：限界利益比率

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/021477d8-5542-480d-9ed2-369b814a1207.png)

---

仮に売上高が x' としたとき、売り上げに対して損益分岐点が占める割合は以下の式で求められる。

R = A / x'
  = b / (1-S) / x' * 100
上記が損益分岐点率となる。

損益分岐点と売り上げの差が、売り上げのうちどれだけに相当するか
P = (x' - A) / x' * 100
  = (x' - b / (1 - S)) / x' * 100
上記が安全余裕率となる。


https://www.ap-siken.com/kakomon/01_aki/q77.html

## まとめ
以上のようにグラフの交点座標を求めるように、数学的に考えることで理解しやすいと思います。

以上、三上でした。
GPS(AT6558, AT6668)にエフェメリスを投入!!

エフェリメスを投入するとより多くのGNSSを受信できるかも?(あんまり受信できてないときに)
# 対象の機器
・AT6668→M5Stack GPS v1.0 v1.1
・AT6558(R)→Air530Z
# 方法
エフェリメスデータをダウンロードします。
そのデータを**直接UARTのRx**に書き込みます。
# ダウンロード先

https://wiki.luatos.org/chips/gnss/air530z.html#ephemeris-information

これの一番上のものをダウンロードしてください。
# 書き込み
dat形式ファイルをそのまま書き込むのでフォーマットが変化しないようにしてください。
できればGnssToolKit3を使って書き込んだほうがいいです。
（ソフトのダウンロードは自分で判断してください）
### GnssToolKit3
設定から下のSend fileからダウンロードした選択して左下のSendを押します。
# 結果
GPSと北斗のエフェメリスデータが注入されて多くの衛星が使用できます。
# 注意点
もともとはAir530Z向けのものをAT6668でも使用いています。なのでこれが正しいのかは不明です。
フォーマットがわかりません(独自のフォーマット?)
一度ダウンロードしたファイルを使いまわすことは出いないので、その都度ダウンロードしてください。
→ダウンロードしてから1時間利用可能です。つまり、一日(1時間以上)とか立つと期限が切れて使えなくなります。
とりあえずWebアプリを作りたい素人による最小限に近い環境構築

「Webアプリを作りたい！！でもサーバとか何もわかんない！！あと難しいことはやりたくない！！」という状態から、とりあえずデータベースを用いた動的な？Webアプリを公開できる小さい環境を作ったのでよければ参考にしてください。

個々のサービスや技術について詳細は書かないので、あくまで全体感を掴むのに役立てていただけるとうれしいです。

まだこの環境でWebアプリを公開したわけではないので絶対ちゃんと運用できるとは言えませんが、よろしくお願いします。

# 概要
早速全体像をば。
まずさくらVPSというレンタルサーバにUbuntuというOSを乗っけて、そこにMySQLでデータベース、Node.js+expressでWebサーバをつくりました。

ざっくり下の図のとおりです。本当は厳密な記法とかがあるんでしょうが、イメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/985818/b25b7156-d874-4165-ab76-c550cae79216.png)


調べると大体APサーバがどうとかミドルウェアがとか出てきますが難しいのは嫌だったので無視しました。多分なくてもWebアプリを作って公開することはできると思います。

初心者なので「サーバ」という言葉のイメージが難しかったですが、イメージ的には今回はさくらVPSという物理的なサーバの上に、MySQLサーバ、Webサーバという仮想的なサーバを立てた感じだと思います。まぁさくらVPSも読んで字の如く仮想サーバなんですが。あくまでイメージの話です。

では各要素について見ていきましょう。
# さくらVPS
詳しいことは知りませんが、ある程度自由度がありそうで安かったので選びました。
とりあえず一番安いメモリ512MBのSSD25GBにしてます。

これはVPSですがレンタルサーバっていうのもあるみたいです。でもそっちは制約が多いらしく、MySQLとかNode.js使うならVPSみたいな感じだったのでVPSにしました。

https://vps.sakura.ad.jp/guide/?gad_source=1&gclid=CjwKCAiAzvC9BhADEiwAEhtlN09n3H7MtejcOGuUzekE5_VIarE-CLZulH4IwI9BkMHM0ZlWHMdu4xoC07wQAvD_BwE

最初はbubble.ioというノーコードサービスを使っていたのですが、アプリを公開するのに最低月4500円ほど飛んでいくっぽくてやめました。無料版を3日ほど触りましたが、開発速度はバケモン速かったです。なんせ環境構築いらずでノーコードなので初心者には最高です。でも高いです。

クラウドサービスっていうのも考えましたが何ができるかよくわかんなかったのと、料金体系が複雑だったちょっと高かったりしたのでやめました。

契約するときにOSも選べるのですが、以前から名前を知っていたUbuntuにしました。多分結構一般的なOSで、情報もある程度ネットに転がってるんでUbuntuでいいと思います。

# ファイルの転送
プログラムやhtmlなどはローカルで作りたいので、
ローカルとさくらVPSとの通信が必要になります。

調べた感じ通信方式はsshとftpがあります。そして補助的なツールとしてgithubがあるという感じです。

今回は難しいことをしたくなかったのでftpを使いました。gitとかgithub使い慣れてる人はsshでgithub使うのがいいのかな？

# MySQL
データベースは知名度的にこれ一択でした。
ので他との比較は全くしてないです。

今回はメモリ512MBの雑魚環境なので、MySQLサーバを起動しようとするだけでメモリがオーバーフローしました。
なんでSwap領域を設定して半ば無理やりMySQLを動かしてます。普通にもっとメモリに余裕を持たせた方がいいと思います。

調べ物をするときはバージョンや乗ってるOSによる違いが少し多いのでご注意ください。

OSの上にMySQLサーバを立てて、それにクライアントとしてログインする形式です。ライブラリやフレームワークのイメージでいたので少し理解に手間取りました。

# Node.js
javascriptの実行環境です。今回はWebサーバもやらせました。

一般的にはWebサーバにはNginxやApacheというのを使うらしいです。
しかしどちらにせよNodo.jsは必須っぽいんで、システムを肥大化させたくなかったのでNode.jsにWebサーバもやらせました。

Node.jsをWebサーバにする場合、expressというフレームワークが一般的なようなので使いました。

# まとめ
とりあえず自分はこうしたよってやつなので、詳しくは調べてみてください。