OmniAICreator/Qiita-1.07M huggingface dataset:
Secret Managerと連携しているRDSのマスターユーザーにログインできなくなった

# おこったこと

Secret Managerで認証情報を管理しているマスターユーザーがいる。ある日、そのアカウントに対してログインを試行したところ、パスワード不一致でログインできなくなっていた。

※以降、マスターユーザーのユーザー名を`admin`とします

# 時系列はこんな感じ

1. Mysqlにて、接続可能なホストを制限するために`admin@%` -> `admin@192.168.1.1`という変更を加えていた
2. Secret Managerのパスワードがローテーションした
3. ログインができなくなった

# 原因 
Secret Managerがデフォルトで対象とするのは`admin:%`というユーザーであるため、`admin@192.168.1.1`というユーザーは別のユーザーとして認識された。

またローテーションのタイミングで`admin@%`が再生成されていた。

# 対応策
セキュリティグループの設定で接続可能なIPアドレスを制限し、MysqlのユーザーではIPアドレスの指定をしないようにする。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Overview.RDSSecurityGroups.html
自然順にソートする

## 自然順とは
自然順とは数字に見えるものは数字として並べた順です。
具体的にはエクスプローラーで名前順にした時の順です。

https://ja.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E9%A0%86

通常、文字列をソートすると文字コード順になりますが、Windows APIを使う事で自然順にする事が出来ます。

## サンプルコード
```c#:C#
//Array.Sort(strArray, new LogicalStringComparer());でstrArrayをソート

public class LogicalStringComparer : IComparer, IComparer<string>
{
    [System.Runtime.InteropServices.DllImport("shlwapi.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode, ExactSpelling = true)]
    private static extern int StrCmpLogicalW(string x, string y);

    public int Compare(string x, string y)
    {
        return StrCmpLogicalW(x, y);
    }

    public int Compare(object x, object y)
    {
        return Compare(x.ToString(), y.ToString());
    }
}
```
```vb:VBA
'LetsSort(strArray)でstrArrayをソート

Declare PtrSafe Function StrCmpLogicalW Lib "SHLWAPI.DLL" (ByVal lpStr1 As String, ByVal lpStr2 As String) As Long
Public Sub LetsSort(ByRef arrayToSort() As String)
    Dim i As Long
    Dim j As Long
    Dim temp As String
    For i = LBound(arrayToSort) To UBound(arrayToSort)
        For j = i To UBound(arrayToSort)
            If StrCmpLogicalW(StrConv(arrayToSort(i), vbUnicode), StrConv(arrayToSort(j), vbUnicode)) > 0 Then
                temp = arrayToSort(i)
                arrayToSort(i) = arrayToSort(j)
                arrayToSort(j) = temp
            End If
        Next j
    Next i
End Sub
```
20時間でAWS SAA取得してみた

# これを読むとわかること
- 効率よく無課金でAWS SAAを取得する方法
- 怠惰な人間がAWS SAAを取得する方法

# 受験時のステータス
- 新卒文系インフラエンジニア
- 普段はAzure勢、たまにAWSも触る
- 取得済みの資格
    - AZ104
    - LinuC1

# 資格勉強法
## 教材
- [Ping t](https://mondai.ping-t.com/g/question_subjects#content-large_category_2)
## 勉強方法
1. 前半の10時間で、サービスに関する問題を解く
    1. サービスに関する解説を読む
    1. そのサービスに関する問題を10問解く
1. 後半の10時間で、試験相当の問題を解く(9割の確率で正答できるようにする)
    1. 1問を解く度に答え合わせをする
    1. 解説を読む

# 受験中
- 問題の難しさとしては以下の感覚
    - 全体の問題の50%は、自信を持って回答を1つに絞れる
    - 全体の問題の30%は、回答を1つに絞れるが、自信があまりない状態
    - 全体の問題の15%は、回答を2つに絞れる
    - 全体の問題の5%は、回答を3つに絞れるor見当がつかない

# 感想
- 正しい勉強法（ハンズオンなど）ではないため、後輩には勧められない
- 正しい怠惰では無い
- でも合格した時のやり遂げた感はいい感じ
- 技術系の記事を書けるようになりたい
TypeScriptのコードを書く環境をさくっと構築する

## この記事について
TypeScriptのコードを書いて試せる環境を作成する手順を記載します。
お使いのPCに、Node.jsの環境があることを前提とします。
TypeScriptのコードが書ける環境を作成します。初心者なので、細かく書いていきます。
パッケージマネージャはnpmを使う前提で書いていますが、お好きなものに置き換えてください。

## 手順
1. ディレクトリ作成
（仮にディレクトリ名をhello-tsとします）
    ```
    mkdir hello-ts
    ```
        
    <br>
    

1. プロジェクトの作成
    hello-tsの下で以下コマンド実行
    ```
    npm init
    ```
    コンソールに質問が出てきます。全部Enterキー押下で問題ありません（実験用なので）。
        
    <br>
    


1. TypeScriptを導入する
    hello-tsの下で以下コマンド実行
    ```
    npm install typescript
    ```
        
    <br>
    

1. TypeScriptの設定ファイルを作る
    hello-tsの下で以下コマンド実行
    ```
    npx tsc --init
    ```
    コマンドを実施すると、tsconfig.jsonというファイルが作成されます。
        
    <br>
    
ここまでで最低限の設定完了です。お疲れ様でした。

### 補足
TypeScriptのコードをトランスパイルし、JavaScriptのファイルを生成するには次のコマンドを実施します。
```
npx tsc (TypeScriptファイルのパス)
```
生成されたJavaScriptファイルを実行するには、次のコマンドを実施します。
```
node (トランスパイルされたjsファイルのパス)
```
これで、書いたプログラムを動かすことができるようになりました。

<br>


TypeScriptのプログラムを書いてみて、動きを確かめる作業を何度も行うと、いちいちトランスパイルするのが面倒になってきます。そこで、ts-nodeというライブラリを使ってTypeScriptのプログラムをサッと実行できるようにします。

```
npm install ts-node
```

package.jsonに`ts-node`が追加されていることを確認してください。

ts-nodeを利用して、TypeScriptをサッと実行するコマンドはこちらです。
```
npx ts-node TypeScriptファイルのファイルパス
```
Laravel + Inertia + precognition ファイルデータを含んだリクエストをPUTやPATCHで送ると、Laravel側でデータが取得できない問題を解決

# どんな現象か
`laravel-precognition-vue-inertia`の`useForm`を使って、ファイルデータを含めたリクエストをputやpatchメソッドで送ると、Laravel側でリクエストデータが取得できません。

コードは下記のような感じです。（この記事では、フロントエンドをVue.jsで書いています）
```vue
<script setup>
import { useForm } from 'laravel-precognition-vue-inertia'
const id = 1
const form = useForm(
    'put', // putメソッドを設定
    `/users/${id}`,
    {
        name: '',
        thumbnailFile: null // ファイルを格納する
    }
)

const submit = () => {
    form.submit({
        preserveScroll: true,
    })
}
</script>

<template>
    <form @submit.prevent="submit">
        <label>Name</label>
        <input v-model="form.name" />
        <label>File</label>
        <input @input="form.thumbnailFile = $event.target.files[0]" type="file" />
        <button :disabled="form.processing">更新</button>
    </form>
</template>
```

LaravelのWeb.phpでデバックすると、うまく取得できていないことが確認できます。
```php
Route::put('/users/{id}', function(Request $request) {
  dd($request->all(), $request->file('thumbnailFile'));
});
```
![名称未設定1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046681/bb287a07-c503-48c9-4830-9652214423e3.png)


# 解決方法
useFormのメソッドをpostに設定して、リクエストに`_method: 'PUT'`を含めるだけでリクエストデータが取得できるようになります。
```vue
<script setup>
import { useForm } from 'laravel-precognition-vue-inertia'
const id = 1
const form = useForm(
    'post', // postに変更
    `/users/${id}`,
    {
        _method: 'PUT', // リクエストデータに含める
        name: '',
        thumbnailFile: null
    }
)

const submit = () => {
    form.submit({
        preserveScroll: true,
    })
}
</script>

<template>
    <form @submit.prevent="submit">
        <label>Name</label>
        <input v-model="form.name" />
        <label>File</label>
        <input @input="form.thumbnailFile = $event.target.files[0]" type="file" />
        <button :disabled="form.processing">更新</button>
    </form>
</template>
```

リクエストデータが取得できます。
![名称未設定2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046681/1fd4916f-c5e7-44a3-06c0-15d12f2a68bd.png)


# 原因
PUTやPATCHを使ってファイルアップロードすることを、Laravelがサポートしていないため発生するようです。

気になる方は以下のページを確認してみてください。

https://inertiajs.com/file-uploads

https://stackoverflow.com/questions/77864431/inertiajs-file-upload-doesnt-work-with-put-method
数値型の種類

Kotlinの数値型はByte、Short、Int、Long、Float、Doubleの6種類ある。

整数であれば、異なる型でも計算が可能。
```kotlin
val i: Byte = 30
val j: Int = 20
i + j
// 50
```

少数の場合も計算できるが減算や、型が異なると誤差が生じる。BigDecimal型を使用する。
```kotlin
val i: Double = 0.2
val j: Double = 0.634
i + j
// 0.734

val l: Float = 0.2F
val m: Double = 0.634
l + m
// 0.8340000029802322

val o = 1.2
val p = 0.4
o - p
// 0.7999999999999999
```

型の最大値以上、最小値以下の数値を代入することはできず、計算して実行した場合は数値が反転する。
``` kotlin
val i: Int = 20000000000
// The integer literal does not conform to the expected type Int

val j: Int = 2147483647 + 1
println(j) // -2147483648

val k: Int = -2147483648 - 1
println(j) // 2147483647
```

・型推論
整数は基本Int型、少数の場合はDouble型が定義される
```kotlin
val i = 2
val j = 58
val k = -496
val l = 94568
// 全てInt型

val p = 10000000000
println(p::class.simpleName) // Long
// Intの最大値を超えるとLong型になる

val s = 100000000000000000000
// The value is out of range
// Long型より大きい数値は代入不可

val n = 0.1
val o = 0.0000043
// 基本Double型
```

#### 参考
https://web-knowledge-info.com/wp/kotlin2/
ぷよぷよプログラミングAI学習用まとめ

![スクリーンショット 2024-10-09 22.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/da43f670-1b19-3994-4855-b8363d06365a.png)


![puyopuyo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/1fdf8221-96c5-fcfa-3a52-383422a6fdc3.gif)


　ぷよぷよプログラミングAI学習システムは、中高生の自己調整学習に向けて開発されました。
　どうやって、Chromebookで、１０分で、素敵な人工知能を作れるのでしょうか？
　秘密は、３つ。
　１　jupyter liteで、webクライアントがpythonコードを実行
　２　超軽量な機械学習フレームワークdezeroを採用
　３　ぷよぷよのstageとactionがコンパクト

<br>
　チュートリアルが終わったら自分で工夫して、人工知能を作ってみよう！

# 最初にやってみよう
以下のサイトを開きます。

https://lunanaedu.github.io/puyopuyo-kai/

画面が出てから、2秒程待ち、Sampleボタンを押して見ることができます。


![agent_learn.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/7eb87aab-b285-6e8f-1a69-28a65db3edea.gif)

JupyterLiteを開き、チュートリアルをやってみよう。

https://lunanaedu.github.io/jupyterlite-puyopuyo/lab/index.html


### Github&X(Twitter)

https://github.com/Lunanaedu/jupyterlite-puyopuyo

https://github.com/Lunanaedu/puyopuyo-kai

https://twitter.com/educationai_ai

# チュートリアル
Step1

https://qiita.com/educational-ai/items/836945e577b4d05f31e7

残りはこちら

https://qiita.com/educational-ai/items/88feaf91bdda0b5e0d25

チュートリアルが終わったら、以下のサイトを開き、「ファイルを選択」をクリックし、作ったagent_learned.zipを選択し、loadします。

https://lunanaedu.github.io/puyopuyo-kai/

# 自己調整学習
学習環境デザイン研究室のサイト

https://noyuri.jp/domain

残りはこちら

https://qiita.com/educational-ai/items/d92e6a0ed3dac4022b80

# python
インストール方法についてのサイト

https://udemy.benesse.co.jp/development/python-work/python-install.html

残りはこちら

https://qiita.com/educational-ai/items/219939e278fccef42842


# jupyter
インストールと基本的な使い方についてのサイト

https://qiita.com/ktr_ch/items/f3ddc4d6a9cac9fa2b89

残りはこちら

https://qiita.com/educational-ai/items/4967f2af6cdf996106d9

# dezero
ゼロから作るDeep Learning３　フレームワーク編　斎藤康毅　著
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/883cac2c-9c47-17e1-a64d-faeba97de39f.jpeg" width=50%>

残りはこちら

https://qiita.com/educational-ai/items/510b172be499c0f79542

# ぷよぷよプログラミング
ぷよぷよeスポーツ×プログラミングの公式サイト

https://puyo.sega.jp/program_2020/

残りはこちら

https://qiita.com/educational-ai/items/e582eb9fdb4e2104f807

# 深層強化学習
深層強化学習の基礎についての説明サイト

https://avinton.com/blog/2017/10/basic-deep-reinforcement-learning/

残りはこちら

https://qiita.com/educational-ai/items/a29e6aa1aaa0e4a3f6e5

# ぷよぷよsteam版でAIを動かしたい
ぷよぷよsteam版でAIを動かしたいサイトはこちら

https://qiita.com/educational-ai/items/a474449f2ca2093ca778
開発メンバーがほぼ自分ひとりだけのシステムを保守してきて思うこと

# はじめに
今の保守プロジェクトは開発メンバーが僕一人だけです。
（正確には、サポートとしてプロパーの方が1名、PMとしていらっしゃいますが、実作業を担当しているのは僕一人です）

色々なエンジニアブログや記事を見ていて思っているのが、
5～10人規模でチーム開発しているケースが多い と感じたことです。
実際、一人で開発しているプロジェクトってどのくらいいらっしゃるのでしょうか？

今回は、一人で保守プロジェクトをしていて思っていることをつらつらと書いていこうと思います。

:::note warn
本記事で書かれている内容は、あくまで個人の感想です。
:::

# 今やっていることの簡単な紹介
僕自身は、SESとして派遣先で作業をしています。
（プロパーがPMとして1名、開発に僕1名）


保守しているシステムをざっくり話すと、Androidアプリの保守をしています。
ただ、アプリをインストールする端末が少々特殊で、Android API Level 17のアプリです。
（Android 4.2です。ちなみに現時点でのAndroidOSの最新バージョンは15。かなり古い・・・）

[Andoid Developersガイド APIレベル表](https://developer.android.com/guide/topics/manifest/uses-sdk-element?hl=ja#api-level-table)

僕がやっていること
* 機能追加要望を整理して、機能仕様レベルまで落とし込む
* 機能追加にかかる工数の見積もり
* 開発スケジュールの策定
* 開発作業
  - 機能設計
  - 詳細設計
  - 実装
  - 単体テスト（ユニットテストを採用しています）
  - 結合テスト（テスト仕様書を作って実際にシステムを動かしてテストする）
* リリース作業
（結合テスト以降のテストは、別のチームで実施しています）

工数見積もりの結果によってはスポットで1名メンバーが入ることはありますが、
基本的に僕一人で開発しています。

各開発作業での成果物は、PMとレビューしています。

# メリット
## 裁量権があるので仕事が進めやすい
一番のメリットだと思います。
ある程度、自分で仕事をコントロールできている感じがあります。

実際に作業するのは自分なので、工数見積り時と作業時で大きなズレも起こりづらいです。
スケジュール策定も、ある程度自由に組めます。
作業メンバーが一人なので、WBSを引くのがすごく楽です。
（ほかメンバーの担当実装が終わらないと、次に進めない みたいな事がない）

実装でもクソコードが目についたらサクッと修正したりできるのもいいですね。
（ほかメンバーにコンフリクトが起きないか、いちいち確認する必要がない）

## コーディング時にコンフリクトが起きない
ソースコードのバージョン管理はGitHubを使っているのですが、
複数人で開発をすると避けられないコンフリクトですが、こいつに悩まされることがないのは大きいと思います。

## ストレスが少ない
これは人によるかもしれません。
僕の場合、誰かと一緒に作業することにある程度のストレスを感じる人間です。
その人とどうしても気が合わなかったり、作業分担でどっちが難易度の高いタスクをやるか牽制し合ったり、

クラス設計と一緒で、関心を持つクラス（相手）が多いと複雑になってきますしね・・・。

人間関係がストレスフリーなのは、かなり大きいと思います。

# デメリット
## 複数メンバーでのチーム開発経験が詰めない
個人的に一番のデメリットだと思っています。

チーム開発独特の問題・課題があって、
それをどうやって解決したか、克服したか、
また、ほかメンバーとのコミュニケーションだったり
そういった経験が積めないのはキャリアとして不利なのでは？と思ってしまいます。

でも、ある意味一人での開発では出てこなかった問題に直面するので、
ストレスは増えるかもしれませんね。
ただ、間違いなく自分の糧にとなる経験になると思います。

## 尊敬できるメンバーがいない
一人で開発しているので、他の人の作業内容が見えません。
他の人が書くコードを見る機会も少ないので、他人からの刺激が少ないと感じています。

特にコーディングに関して、技術的な話ができる人がいないとさみしいですね。

## 実装・バグで困った時に頼れる人がいない
これも大きなデメリットだと思います。
このあたりで躓くと、かなり技術的な部分なのでPMのサポートも受けづらいです。

今はChatGPT等のAIによるコーディング支援を受けられるので、
AIが出てくる前と比べて楽になりましたが、一人でもある程度の問題を解決する力が問われると思っています。

# 最後に
一人で開発する期間が長くなってきたので、自分のキャリア振り返りの意味も込めて書いてみました。
結局、個人開発・チーム開発どっちがいいか は人それぞれだと思います。

チーム開発だと人と関わる機会が増えるので それがモチベーションになる人もいれば、ストレスに感じる人もいます。

ただ、どちらにも言えるのが、1つのプロジェクトに長くとどまっているとどうしてもマンネリ化してしまうことですね。
個人的には、今使っている開発環境がかなりレガシーなので 新しいものに触れたいとは思っています。
（最低でもJava8で開発したい・・・）

ここまで読んでいただき、ありがとうございました！
Scratch ライブラリ（疑似3Dスクロール）

# Scratch ライブラリ（疑似3Dスクロール）

[G14 Great Fighter Jerrydog](https://qiita.com/Kray-G/items/9308c72311d642628509) では疑似 3D スクロールを使ってダイナミックな動きを実現してみました。After Burner だし。また、先日 [Time Trial On Edge](https://qiita.com/Kray-G/items/58a1b26dc22132cc1bab) という 3D レーシングも試しに作ってみました。ということで、ライブラリ化できたら似たようなもの量産できそう、という期待に胸を膨らませて、ライブラリ化です。

上記 2 作品はある意味試行錯誤だったのですが、その知見を踏まえ、かなりシンプルに仕上がってます。計算量も少なめにし、より使いやすくしました。

# 疑似3Dスクロール

## プロジェクト

ここにあります。

https://scratch.mit.edu/projects/1064104424/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579271/6516fd00-f3d4-899e-2f4c-ffd63627e363.png)

> Scratch 上だと英語の人が多いので、基本英語のプロジェクトにするようにしました。日本語での説明はこの Qiita の記事で。むしろこっちの方が情報量多いですし。

## ライブラリ概要

以下、実現できます。Jerrydog でやってたことですね。しかもさらにシンプルな実装で。

* スムーズな疑似 3D スクロール
* 地面の回転
* 任意のオブジェクト配置
* 水平線位置（高さ）の動的な変更
* スクロールスピードも変更可能

## 使い方

### 基本

グローバルに定義してある変数をコントロールします。詳細は「[変数・リスト](#変数・リスト)」参照。

## 各種情報

### 変数・リスト
> In: 他スプライト管理の値を参照／Out: 本スプライトで設定

| 変数名 | In/Out |        概要        |
| ------ | :----: | ------------------ |
| `BG Horizon Angle` |   In   | 水平線の傾き |
| `BG Horizon Line` | In | 水平線の Y 座標(Angle = 0 時) |
| `BG Speed` |   In   | スクロール速度 |

### イベント

特になし

### コスチューム

オブジェクトをスクロールに乗せる場合、コスチュームとして用意し、Add Object ブロックを使う。詳細は以下のサンプルとコード参照。

オブジェクトはこんな感じで用意。オブジェクトの下端が中心に来るように。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579271/1a46c3c0-60cf-683c-e09a-0a72159df236.png)

Add Object ブロックは以下の定義となっている。goal x は最下段での X 座標で、どこに向かっていくかを指定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579271/d42f3dcb-098a-c90b-3845-1207aa3a026c.png)

サンプルでのコードはこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579271/67383503-1113-7806-19f2-19177f2ab7c2.png)

---

技術的な仕組みは別途触れる予定なので、ここでは省略（近々予定）。

---

> [Scratch ライブラリと Scratch Tips 目次へ戻る](https://qiita.com/Kray-G/items/e1900d5b6c6dcfbe5321/)
ChatGPTと一緒にJavaScriptをゼロから勉強する記録【JSの関数】#02

![スクリーンショット 2024-10-02 1.26.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881103/762156dd-ad15-9501-d18e-a9cd08fcaaa3.png)
# はじめに
こんにちは。web開発未経験からwebアプリケーションエンジニアになるため、勉強を始めようと思い記事にいたします。
私のこれまでの経験はC言語を嗜む程度であり、コンピュータサイエンスに関する知識がゼロのところからのスタートとなりますので暖かく見守っていただけると幸いです。最終的にはReact、Next.jsとモダンなweb開発?へと繋げていけたらと思います。また、初学者の方は、私の記事と一緒に勉強していけたらと思います。
よろしくお願いいたします！

# 1. アロー関数（簡潔さが命！）
アロー関数はコードを短く、シンプルに書けるから、実戦ではよく使われるらしい。特にコールバック関数や、関数の中でシンプルな処理をしたいときに便利だと。

例えば、配列の各要素を2倍にするなら、アロー関数でこんな感じに書ける：

```js
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(num => num * 2);
console.log(doubled);  // [2, 4, 6, 8]
```

アロー関数のおかげで、無駄なく簡潔に書ける。returnを省略できるのがポイント。


# 2. デフォルト引数（めんどくさい処理を回避！）
実戦では、関数に引数を渡さないときもあるかも？そんなときに役立つのがデフォルト引数。

```js
const greet = (name = 'Guest') => {
  return `Hello, ${name}!`;
};

console.log(greet());        // "Hello, Guest!"
console.log(greet('Luna'));  // "Hello, Luna!"
```
引数を忘れてもデフォルトで処理してくれるから、コードの頑丈さが増す。これで引数を渡し忘れた初心者にも優しいコードが書ける。

# 3. 即時関数（IIFE）
「この関数、すぐに実行したいけど、外に影響を与えたくない！」ってとき、即時関数（IIFE）が役立つ。ブロックスコープを持ちながら、一度だけ実行されるのが特徴。

```js
(function() {
  console.log('This runs immediately!');
})();
```
グローバルスコープを汚さないし、使い捨ての処理を書くときに超便利。だから、他のコードと衝突することがなく、クリーンな設計ができる。

# 4. 高階関数（関数を返す、または引数に関数を取る）
関数を引数に取ったり、関数を返す高階関数は、実戦でかなり強力なツール。例えば、何度も同じ操作をするけど、ちょっとだけ処理が違う場合に便利。

```js
const multiplier = (factor) => {
  return (num) => num * factor;
};

const double = multiplier(2);
console.log(double(5));  // 10

const triple = multiplier(3);
console.log(triple(5));  // 15
```
こんな風にカスタマイズ可能な関数を作れる。プロジェクトの中で使い回しできる関数を作るときは、こういう柔軟性が必要。

# 5. コールバック関数（非同期処理の親友）
非同期処理（例えばデータベースやAPIとのやりとり）では、コールバック関数が大活躍。例えば、データの読み込みが完了した後に処理を行うことができる。

```js
const fetchData = (callback) => {
  setTimeout(() => {
    const data = 'Sample data';
    callback(data);
  }, 2000);  // 2秒後にデータを取得
};

fetchData((result) => {
  console.log(`Fetched: ${result}`);
});
```
これで、時間のかかる処理が終わったタイミングで後続の処理を行える。

# 6. クロージャ（Closure）
クロージャは、関数が定義されたときのスコープを保持する特殊な機能だ。クロージャを使うと、関数外からでも関数内の変数にアクセスできるようになる。

```js
コードをコピーする
function outer() {
  let count = 0;

  function inner() {
    count++;
    console.log(count);
  }

  return inner;
}

const counter = outer();
counter();  // 1
counter();  // 2
counter();  // 3
```
inner関数がouter関数のcount変数にアクセスできる。このように、内部関数が外部関数の変数を覚えている状態をクロージャという。
これがむずいな。
`const counter = outer();`では`outer`が呼ばれて、`return inner`が起こることによって、次回以降の`counter`では`inner`だけが呼ばれてるんだな。はえー。

# おわりに
網羅などできちゃいませんが、一旦触れてみました。ChatGPTのみだと、情報の正確性や、網羅性を担保することができないので、しっかり体型的に勉強するにはプロンプトを工夫するか、本やドキュメントを活用しないとなと思います。
それでは失礼します。
ジョブカンの出退勤を行うAPIの作成【Google Cloud Functions】

## やりたいこと

iPhoneのショートカット機能を使ってジョブカンの出退勤を行いたかったのでメモ


## 流れ
iPhoneのショートカット機能でPOST送信を行う
引数として
・ジョブカンID
・パスワード
・出退勤パラメータ

以上を受け取り、ジョブカンのスクレイピングを行い
出退勤処理を行う

無料で使いたかったのでデプロイ先はGoogle Cloud Functionsとした

## コード

```Node.js
const puppeteer = require('puppeteer');
const dayjs = require('dayjs');
const localeData = require('dayjs/plugin/localeData');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');
require('dayjs/locale/ja');

dayjs.extend(localeData);
dayjs.extend(utc);
dayjs.extend(timezone); 
dayjs.locale('ja'); 

exports.scrapeUrl = async (req, res) => {
  const { email, password, action } = req.body;

  if (!email || !password || !action) {
    return res.status(400).send('Missing parameters');
  }

  const result = await scrapeJobcan(email, password, action);
  return res.status(200).send({ 'result': result });
};

async function scrapeJobcan(email, password, action) {
  let browser = null
  try {
    // Puppeteerでヘッドレスブラウザを起動
    browser = await puppeteer.launch({
      executablePath: puppeteer.executablePath(),
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });

    const page = await browser.newPage();

    // ジョブカンのログインページにアクセス
    await page.goto('https://id.jobcan.jp/users/sign_in');

    // ログインフォームに入力
    await page.type('#user_email', email);
    await page.type('#user_password', password);

    // ログインボタンをクリック
    await page.click('input[name="commit"]');
    await page.waitForNavigation();

    // 勤怠管理ページにアクセス
    await page.goto('https://ssl.jobcan.jp/jbcoauth/login');
    await page.waitForSelector('#working_status');

    // 勤務状態を取得
    const workingStatus = await page.$eval('#working_status', el => el.textContent?.trim() ?? '');

    let currentTime;

    if (action === 'punch_in') {
      if (workingStatus === '勤務中' || workingStatus === '退室中') {
        return '既に出勤中か退勤済みです';
      }

      // 出社時の処理

      currentTime = dayjs().format('HH:mm');
      return `成功: 出勤時間(${currentTime})`;
    } else if (action === 'punch_out') {
      if (workingStatus === '未出勤' || workingStatus === '退室中') {
        return '出勤していないか退勤済みです';
      }

      // 退勤時の処理

      return `成功: 退勤時間(${currentTime})`;
    }

    return '不明な操作';
  } catch (error) {
    console.error(error);
    return `失敗: ${error.message}`;
  } finally {
    if (browser) {
      await browser.close();
    }
  }
}
```

## デプロイ
```
gcloud functions deploy scrapeUrl \
--runtime nodejs16 \
--trigger-http \
--allow-unauthenticated \
--memory 512MB
```
【GithubActions】TODO to Issueの使い方

# TODO to Issueとは
コード内のTODOコメントをIssueに書き出してくれるActionsです。

https://github.com/marketplace/actions/todo-to-issue


![スクリーンショット 2024-10-02 20.56.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/51335594-2e69-767a-c78a-5936a050efa6.png)

コードを修正した後に、TODOコメントを消してPUSHするとIssueはcloseされます。
![スクリーンショット 2024-10-02 20.59.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/f8043baa-b027-41b0-e50a-4b8ffbda1451.png)

# 設定
GITHUBTOKENに書き込み権限を付与します。

Setings>Actions>General>Workflow permissions
![スクリーンショット 2024-10-02 21.02.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/fa3dd737-d457-ad6f-4d93-0f1707f0334a.png)

下記のURLでサポート言語を確認しましょう。

[supported-languages](https://github.com/marketplace/actions/todo-to-issue#supported-languages)

Setupのスニペットをコピペしてワークフローを作成しましょう。

[setup](https://github.com/marketplace/actions/todo-to-issue#setup)

Github Actionsの説明は割愛します。

https://docs.github.com/ja/actions/writing-workflows/quickstart

ステップでIssue createdが出ていれば成功です。

![スクリーンショット 2024-10-02 21.08.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/401a984a-bae3-d3cb-d7a0-87ddd2475002.png)
AWS WAFの運用と考察

# 概要

AWS WAFを運用していて感じた事、こうした方がいいことのまとめ

# CountモードとBlockモード

**Countモードの使い方**

Countモードを使えばWAFルールの挙動をテストできるが！！！！
使うとほぼ絶対にそのままにしてBlockモードにしないのであまり使うのはオススメではないです。

とはいえ、どのリクエストがブロックされるか調査する必要はあるので原則期間限定でかつテスト用途で公開してるシステムには使わないことがベターと思います。

**Blockモードの使い方**

基本はBlockモード前提です。
システムのリリース前であれば適応する全てのルールをBlockモードでテストを回して不具合がないか確かめた方が後々Blockモードにするより敷居が低いのでオススメ。
リリース後にWAFを導入する場合も少なくはないと思いますが、その場合はDev・Stg環境でBlockモードを導入してテストしてから本番環境に入れるなどのやり方が比較的導入しやすいです。

**カウントモードでWAFを入れてると言い張るパターンもありますが、それはもはやWAFが入ってるとは言えない状況なので注意しましょう（実体験）**

# WAFのアラート運用

WAFを入れた後と言えばルールの見直しなどもありますが、悩ましいのがアラートの設定です。
定番だとBlockされた場合通知などもあるのですが、それだと実運用をした際に段々見なくなってしまいます。。
そこで考えたのが、許可された通信を監視する手法です。Blockされた通信は基本的にBlockされているので誤検知をのぞいて問題ないのですが、WAFを貫通した攻撃をされた場合侵害に気がつくことができないので被害が大きくなってしまいます。
そこで使用したのがCloudWatch Logのログ異常検知機能です。これは指定期間のログを学習して異常と認識されたログをピックアップしてくれるので、全部の通信を人が見ずに怪しそうなログだけを監視することができます。

実際の運用ではまだまだWAFのBlockアラートなど減らせていないところもあるのですが、効果を試してみながら切り替えていきたいところですね。

# まとめ

AWS WAFの運用って難しい上に知見が全然ネットに落ちてないんですよね・・・。
その中で事例やAWSのドキュメントを参考にうまく運用する難しさと楽しさがWAFには詰まってると思います！
実際WAFだけでも無限に触ってられる気がする！！
今回のWAFのお話少しでも皆様のお役に立てば幸いです。

# 参考
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/LogsAnomalyDetection.html
https://aws.amazon.com/jp/blogs/news/analyzing-aws-waf-logs-in-amazon-cloudwatch-logs/
重複したロジックを減らすには

# はじめに
みなさんは普段コードを書いていて、「この処理、他の場所にも書いたな...」という経験はありますか？私はたくさんあります()
重複したコードが増えてくると、後からその箇所を修正するときに対応箇所が増えてしまうため、できれば重複したコードは避けたいです。
オブジェクト指向では、こういう課題を解決するために、データとそのデータに関係するロジックは同じクラスに入れるという考え方をします。

# ロジックをクラスに入れる
例えばセット商品の合計金額の計算の処理を書いていたとします。
セット商品はメイン商品とサブ商品から構成されるとします。
```calc.scala
def calcTotalPrice(mainPrice: Int, subPrice: Int) = {
    mainPrice + subPrice
}
```
この処理はさまざまな場面で利用される予定です。
そこで、次のようにクラスに入れます。
``` ProductPrice.scala
case class ProductPrice(mainPrice: Int, subPrice: Int) {
    def calcTotalPrice = {
        mainPrice + subPrice
    }
}
```
このようにクラスに入れることで、合計金額を計算したいときは、このクラスのメソッドを呼び出せばよくなります。
これにより、合計金額の計算ロジックはProductPriceクラスに閉じ込められ、ロジックの重複を防ぐことが出来ます。

# さいごに
重複したロジックを減らすには、オブジェクト指向ではクラスのメソッドとして定義する方法を紹介しました。
次回はクラスの中身が大きくなってきた場合はどうするかについて紹介する予定です。

この記事はシステム設計について学習中のエンジニアが書いたものです。
間違い・質問などありましたらお気軽にコメントください。
正規表現のOR検索をするとSubMatchesが期待通りの出力にならない

# 実例
正規表現でMM/ddの形式の日付から
ddの部分を抽出したい。
以下のようなコードを書いたとする。

```VB:
Sub RegexTest()
    Dim regex As Object
    Dim match As Object
    Dim targetStr As String

    targetStr = "10/23"
    
    ' 正規表現オブジェクトを作成
    Set regex = CreateObject("VBScript.RegExp")
    regex.Pattern = "([1-9]|1[0-2])/([1-9]|[12]\d|3[01])"
    regex.Global = False

    ' 一致を検索
    If regex.test(targetStr) Then
        Set match = regex.Execute(targetStr)(0)
        MsgBox match.SubMatches(1)
    End If
    
End Sub
```

# コードの雑な説明
regex.Patternで `1~12の数字 / 1~31の数字 `になるように正規表現を書き
メッセージボックスに1番目のSubMatch、(日付の方)を出力する。

今回の例だと、`targetStr`に"10/23"を代入しているので
23 が出力されるはずだ。

# あれ？
実行してみると、メッセージボックスに表示されるのは「2」だった。

# 解決法
正規表現は、左から右に向かって「初めにヒットした条件」を基準に返している。
今回だと`[1-9]`の条件に"2"がヒットするので、出力が「2」になってしまうのだろう。

なので条件の順番を以下のように変えれば期待通り「23」になる。

`regex.Pattern = "(1[0-2]|[1-9])/(3[01]|[12]\d|[1-9])"`
サークルでQiitaのOrganizationを作ってみた！！いままでの記事をOrganizationに紐づける方法

# はじめに
みなさん、こんにちは！

今回は、サークルで Qiita Organization を作成した際に気づいた、知っておくと便利な情報を紹介します。具体的には、これまで個人アカウントで書いていた記事を Organization に紐づける方法についてお伝えします。

# 紐づける方法
はじめに左上の自分のIconをクリックし，メニューバーを出し，所属のOrganizationをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748983/0edfb2cf-6106-19d8-6900-c01c6bba6b6a.png)

すると，Organizationのページに飛びますので，サイドバーか記事一覧のしたいにあるOrganization個人設定を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748983/44c07dc5-20f5-ae14-7b1a-52cf7f39ac4f.png)

最後に，するとこのような画面があるので，
紐付け元・先のOrganization欄に適切なものを選択し，変更するを押したら終了です！


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748983/26a763d4-3ba9-c0b4-9379-939f90defc0c.png)

> - 元々Organizationに所属されていない人の場合
>
>  | 紐付け元 | 紐付け先 |
>  |:-:|:-:|
>  | 紐付けなし  |  現所属企業（団体） |
>
>  - 元々Organizationに所属されている人の場合
>
>  | 紐付け元 | 紐付け先 |
>  |:-:|:-:|
>  | 旧所属企業（団体)  |  現所属企業（団体） |


:::note alert
一括で紐付けられるので，紐付けたくない記事がないか**必ず**確認しましょう
:::


# 私たちについて
最後に、私たちの団体について簡単にご紹介させていただきます。

私たちは
**立命館コンピュータクラブ**
通称 ***RCC*** という団体です！

立命館大学のBKC、OICで活動する学術部公認の「コンピュータサークル」であり、
特定の分野に縛られることなく、
**「自由なアイデアと活動」** をモットーに活動を行っております。

技術が好きな方や技術力を向上させたいという志を持つメンバーが集まっており、コンピュータに関わることであれば **なんでも** 活動しております。

今後もメンバーが記事を投稿していく予定です。ご興味がおありでしたら、ぜひご覧ください！

それではみなさんよいエンジニアライフを〜👋
ForeignKeyで紐付けた子モデルのオブジェクトをテンプレートで表示させる方法

## 背景

### 作りたいもの

→ スニペットやブログのコメント欄を作成したい。

### わからなかったこと

→ views.pyファイルで一つのモデルを指定しているため、同じテンプレート内で他のモデルを指定できるのか、できるとしたらどう書けばいいのかわからない。



## 作成したモデル


```python:models.py

# スニペットモデル
class Snippet(models.Model):

    title = models.CharField('タイトル', max_length=128)
    code = models.TextField('コード', blank=True)
    description = models.TextField('説明', blank=True)
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name="投稿者",
        on_delete=models.CASCADE
    )
    created_at = models.DateTimeField("投稿日", auto_now_add=True)
    updated_at = models.DateTimeField("更新日", auto_now=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):

        return self.title

＃コメントモデル
class Comment(models.Model):
    text = models.TextField('コメント', blank=False)
    commented_to = models.ForeignKey(Snippet, on_delete=models.CASCADE) # 参照元のスニペットが削除されたらコメントも削除される。
    commented_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name="コメント投稿者",
        on_delete=models.CASCADE
    )
    commented_at = models.DateTimeField('投稿日', auto_now_add=True)

    def __str__(self):
        return self.text
```

スニペットモデルとコメントモデルは、一つのスニペットに対して複数のコメントが紐づけられた１対多のリレーションのため、ForeignKeyを用いた。

ここではスニペットモデルを親モデル、コメントモデルを子モデルと呼称することとする。


## 解決策

**親モデル.子モデル_set.all** と記載することで子モデルのオブジェクトを取り出す事ができた。



```html:snippet_detail.html

<!-- スニペット部分は省略 -->

<br><br>
{% if snippet.comment_set.all %}
<h2>コメント一覧</h2>
<div class="comment_list" style="background-color:#EDF7FF;" >
    {% for comment in snippet.comment_set.all %}
    <div class="comment-text">
        <p>◆{{ comment.text }}　by {{ comment.commented_by }}　{{ comment.commented_at}}</p>
    </div>
    {% endfor %}
</div>
{% endif %}

```


実際の完成品がこちら。
デザインのセンス、HTMLの理解がなさすぎて見た目は酷いものだがなんとか出す事ができた。

<br></br>

![Djangoスニペットコメント機能.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1090582/fabe69e0-445d-a4d3-6552-75cc21703614.png)



## おわりに

次の投稿ではForeignKeyで紐づけていないモデルでも一つのテンプレートで表示する方法をご紹介します！


また、別の方法を紹介されている方の記事も見つけたのでこちらも参考にしてみてください。

「ForeignKey　子モデル　逆参照」とかで検索すると結構出てきます。
けど日本語だとやはり情報が少ないですね、、

https://qiita.com/ponponmaru1012/items/65538795b39646327847
LaravelでBasic認証をかける方法

# はじめに

こんにちは、エンジニアのkeitaMaxです。

今回は、Laravel１０でBasic認証のかけ方を記事にします。

# middlewareの作成

以下のコマンドでBasic認証ようのミドルウェアを作成します。

```
php artisan make:middleware BasicAuthMiddleware
```
作成された`BasicAuthMiddleware`を以下のように編集します。

```php:BasicAuthMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class BasicAuthMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if (config('app.is_basicauth')) {
            $username = $request->getUser();
            $password = $request->getPassword();

            if ($username == config('app.basicauth_user') && $password == config('app.basicauth_password')) {
                return $next($request);
            }
            header('WWW-Authenticate: Basic realm="Sample Private Page"');
            header('Content-Type: text/plain; charset=utf-8');
            abort(401, "Enter username and password.");
        } else {
            return $next($request);
        }
    }
}

```

今回は、`.env`ファイルにパスワードとユーザー名、ベーシック認証をかけるかどうかを設定できるようにしました。

# .envファイル

.envは以下を追加しました。

```
IS_BASICAUTH=true
BASICKAUTH_USER=user
BASICAUTH_PASSWORD=pass
```

# routeの修正

以下のように作成したミドルウェアで定義しているルーティングを囲います。

```
Route::group(['middleware' => 'basicauth'], function () {
    // ここに他のルーティングを定義
})
```

# カーネルに追加

作成したミドルウェアをカーネルに登録します。

```php:Kernel
    protected $middlewareAliases = [
        // ~~~
        'basicauth' => \App\Http\Middleware\BasicAuthMiddleware::class,
    ];
```

これで準備完了で、アクセスをするとBasic認証がかかっているかと思います。

# おわりに

これで環境ごとにBasic認証をかけるかどうかを変えることができるようになりました。

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://qiita.com/nozaki-sankosc/items/dc666433d7b92137a48e
自律型リカバリサービス（RCV）について

## Base DatabaseのデフォルトバックアップはRCVに
OCI (Oracle Cloud Infrastructure) の**Base Database**のバックアップはRMANの機能で自動取得できますが、少し前までは「差分増分バックアップ」になっていました。
（週次でフル、日次で差分増分バックアップを取得し、オブジェクトストレージに保管）
ただ、ここ最近はバックアップ取得先として「**自律型リカバリサービス（RCV）**」が選べるようになり、今では**デフォルト**になっています。（推奨でもあります）

## RCVとは
![RCV.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23861/15aa13d2-0c38-0248-467c-14e752d4cdf7.png)

RCVはオンプレミスで提供されている **「Zero Data Loss Recovery Appliance」の機能をクラウドで利用できるもの**になります。
以前からあった「増分更新バックアップ」と同様に永久差分増分を実現できるのですが、大きな違いとしてフルバックアップへのリストア(マージ)はおこないません。
**RCVの中で独自形式で増分バックアップが格納され、それらを合わせて仮想的なフルバックアップが作れるような仕組み**になっています。

## RCVのメリット
仮想的なフルバックアップが作れるので、リストア時に増分バックアップのリストア作業が不要になります。
また、増分更新バックアップと異なりリストア(マージ)をしないので、過去に戻すこと(PITR)も可能になっています。
これまでの**差分増分バックアップ、累積増分バックアップ、増分更新のデメリットを解決**していますね。

|方式|デメリット|
|---|---|
|差分増分|リストア時にフルバックアップ以降の全ての増分バックアップファイルの適用が必要|
|累積増分|増分バックアップファイルサイズがだんだん大きくなる|
|増分更新|リストア(マージ)以前には戻せない|

※RCVのバックアップが格納されている場所はOSからは見えない領域ということで、最近はランサムウェア対策もメリットとしてアピールされています

## ZRCVとは
RCVの設定時に「**リアルタイムデータ保護**」というチェックがあり、これにチェックをつけると「**Zero Data Loss RCV (ZRCV)**」になります。
いくらバックアップをしていてもオンラインREDOログが失われてしまったらその分のデータを失うことになりますが、ZRCVにすると**オンラインREDOログもバックアップされるようになり、「Zero Data Loss」が実現**できます。（値段は少しあがります）
　
　
なお、RCVの課金体系は少しややこしいです
（参考：https://speakerdeck.com/oracle4engineer/zrcv-overview?slide=13）
CodeWars オススメ問題 #5

# はじめに

個人的に好きなアルゴリズム学習サイト「CodeWars」の問題をシェア。

週1くらいのペースで、全10回を目指す予定。

:::note
CodeWarsはいいぞ！の紹介は[こちら](https://qiita.com/kohki_takatama/items/2ae2808b931e943262b8)

CodeWarsの始め方は[こちら](https://qiita.com/javacommons/items/7c473cda7825ab99e08c
)
:::
# オススメ問題

https://www.codewars.com/kata/517abf86da9663f1d2000003/javascript

### 問題
書式の変換問題です。エンジニアには馴染み深い問題ですね。
今回は、`ケバブケース`・`スネークケース` から `キャメルケース` に変換します。

```
"the-stealth-warrior" -> "theStealthWarrior"

"The_Stealth_Warrior" -> "TheStealthWarrior"

"The_Stealth-Warrior" -> "TheStealthWarrior"
```
### 難易度
分類は 6kyu です。
アルゴリズム問題に慣れてきた方にオススメです。

# オススメの回答
「評価が高い回答」の中から、学びの多い回答をピックアップしてご紹介。
・・・今回は、私の解答を紹介させていただきます。

:::note warn
<details><summary>解答のポイント</summary>

主に2つのアルゴリズムが必要です。
1. `-``_`を取り除く
1. 大文字にする

また「大文字にする」アプローチは以下の2種あります。
- 単語の塊ごとに分けて、先頭を大文字にする
- `-``_`に続く1文字を大文字にする

直感的なのは「単語の塊ごとに分けて、先頭を大文字にする」のように見えます。
しかし、「単語の塊に分けた内、最初の塊は大文字化しない」という例外があり、「単語ごとに分ける」という処理もひとつ挟まるため、結果として長いコードになると言えます。

どちらを取るかは、フィロソフィーによると思います。私はコードが短いほうが好きです。
</details>
:::

:::note
<details><summary>単語の塊ごとに分ける</summary>

```js
const toCamelCase = (str) => {
  return str
    .split(/[-_]/)
    .map((e, i) => {
      return i === 0 ? e : e.replace(/^[a-z]/, w => w.toUpperCase())
    })
    .join('')
}
```

単語ごとに分け（`split(/[-_]/)`）、最初の塊以外の先頭を大文字化（`map(~)`）、最後につなげる（`join`）

</details>
:::

:::note
<details><summary>-_に続く1文字を大文字化する</summary>

```js
const toCamelCase = str => str.replace(/[-_]./g, w => w[1].toUpperCase())
```

![スクリーンショット 2024-10-02 20.07.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457770/f205a214-dbce-079f-d2ad-e26cb6cce027.png)

1行で書いてみました。
正規表現`/[-_]./g`は、「`-`もしくは`_`に続く1文字」にマッチします。

これを、2文字目（`w[1]`）の大文字化したもの（`toUpperCase`）に置き換え`replace`します。

`"the-stealth-warrior"`であれば、`-s`と`-w`にマッチするわけですね。
その後、`-s`を`S`、`-w`を`W`に置き換えます。

結果として`"theStealthWarrior"`を返します。

工程が少なく、私は好みです。

</details>
:::

# おわりに
以上、CodeWarsオススメ問題でした。

オススメ問題・解法など、ぜひコメントお待ちしております！

# 参考記事

https://www.blog.itosae.com/posts/2022092

https://zenn.dev/usamik26/articles/regex-lookahead

https://qiita.com/ichironagata/items/091f8cd629b82b0dcbf8
独り身で「おかえり」もなく寂しいので、玄関で歓声を浴びることにした

## 家に帰っても返事はありません
私は独り身のため、家に帰って「ただいま」と言っても、「おかえり」は返ってきません。
そこで、家に帰ったタイミングでテンションが上がるように、玄関で歓声を浴びることにしました。

HC-SR04という超音波センサー（写真上側）を用いて距離を測ることで、玄関を通ったかどうかを判断しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682615/e921acef-7cfa-50b4-d3e0-a962d10bd688.jpeg" width=450>

## 作成したもの
obnizに超音波センサーを繋いで、一定の距離より近くを通ると音声ファイルが自動的に流れるものを作成しました。

イメージは以下の通りです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682615/38db2693-baff-e545-388a-8bda98e3054e.png" width=450>

**obniz**とは、Wi-Fi経由で専用のクラウドに接続、インターネット経由で電子部品を操作できる開発ボードになります。

https://docs.obniz.com/ja/reference/board-1y/

流す音声はリンク先にある「スタジアムの歓声1」です。

https://soundeffect-lab.info/sound/voice/people.html


## 実装

<details>
<summary>コードまとめ</summary>

```obniz.js
const Obniz = require("obniz");
const { exec } = require("child_process");
const obniz = new Obniz("ID"); // 自分のIDを入れます

obniz.onconnect = async function () {
  // 超音波測距センサを利用する
  const hcsr04 = obniz.wired("HC-SR04", {
    gnd: 0,
    echo: 1,
    trigger: 2,
    vcc: 3,
  });

  // ディスプレイ
  obniz.display.clear(); // クリア
  obniz.display.print("Hello obniz!");

  // setIntervalで一定間隔で処理
  setInterval(async function () {
    // 距離を取得
    let distance = await hcsr04.measureWait();
    // 距離(mm)をターミナルに表示
    console.log(distance + " mm");

    // obnizディスプレイに表示
    obniz.display.clear();
    obniz.display.print(distance + " mm");

    // 距離が1000mm未満かどうかの判定
    if (distance < 1000) {
      // 1000mm = 100cm 以下の場合

      // 音声ファイルを再生 (MacOS用に修正)
      exec("afplay sound.mp3", (error) => {
        if (error) {
          console.error(`音声再生エラー: ${error}`);
        }
      });

      // obnizディスプレイに近接していることを表示
      obniz.display.clear();
      obniz.display.print("Too close!!");
    }
  }, 1000); // 1000ミリ秒 = 1秒おきに実行
};

```

</details>

### 準備
obnizのライブラリをインストールしておきます。
```
npm install obniz
```

### モジュールのインポート
IDには自分のObniz IDを入れてください。
```javascript
const Obniz = require("obniz");
const { exec } = require("child_process");
const obniz = new Obniz("id");
```

### 超音波センサーの接続設定
超音波距離センサ「HC-SR04」をObnizに接続します。gnd, echo, trigger, vcc のピンが、それぞれ指定された番号に対応して接続されます。
```javascript
const hcsr04 = obniz.wired("HC-SR04", {
  gnd: 0,
  echo: 1,
  trigger: 2,
  vcc: 3,
});
```

### 距離の測定と表示
超音波センサーを用いて距離を測定し、測定した結果をターミナルとディスプレイに表示されます。
```javascript
setInterval(async function () {
  let distance = await hcsr04.measureWait();
  console.log(distance + " mm");
  obniz.display.clear();
  obniz.display.print(distance + " mm");

```


### 距離が1000mm未満の場合音声ファイルを再生
測定した距離が1000mm（100cm）未満かどうかを判定し、距離が近い場合に音声ファイルを再生します。
距離が1000mm未満の場合は「Too close!!」という警告をディスプレイに表示します。
```javascript
if (distance < 1000) {
  exec("afplay sound.mp3", (error) => {
    if (error) {
      console.error(`音声再生エラー: ${error}`);
    }
  });
  obniz.display.clear();
  obniz.display.print("Too close!!");
}
```


## まとめ
今回始めてobnizを使って見ましたが、普段ハードを触らない私でも、思っていた以上に簡単にできました。超音波センサー以外にもLEDや温度センサーなども使用できるので、触ってみようと思います。
日本語入力中にターミナルがクラッシュする問題を解決する方法

## 概要
WSL2のubuntuで日本語入力中にターミナルが落ちる(クラッシュ)する問題が起き、本記事では、その手順と解決する方法を紹介します。

## バージョン
Ubuntu 22.04.3 LTS
Windows 10 Home
バージョン: 22H2

## 原因
「以前のバージョンのMicrosoft IMEを使用する」設定が原因

## 手順

1. **`Windowsキー + I`** で **Windows設定アプリ** を開く
2. **「時刻と言語」** を選択
3. 左側のメニューから **「言語」** を選択
4. 言語の追加から **「日本語」** を選択し、**「オプション」** をクリック
5. **「Microsoft IME」** のセクションで、次の操作を行う:
   - **「キーボード」** → **「Microsoft IME」** → **「オプション」**
6. **「全般」** タブで:
   - **「以前のバージョンのMicrosoft IMEを使う」** を **オフ** に設定

## 参考
https://github.com/microsoft/terminal/issues/14349
amplify v2のStorage機能を使ってS3に配置した記事データを配信するまで


## はじめに

ポートフォリオ予定地作りました。
作って2か月放置しちゃったんですが最近エンジニアらしい業務がないので開発を再開したいとは...
本番（仮）：https://zoe-chin.com/
開発：https://dev.zoe-chin.com/

## ディレクトリ

特定のディレクトリ配下のmdファイルをそっくりS3にアップロードして、記事一覧画面や記事詳細画面で表示したい。
その機能検証という感じ。

```text
root
├ public 
│  └ markdowns // この配下にmdを配置する
├ src // nextjsの中身
以下略
```

## 機能の概要

- リポジトリのpublicフォルダ配下にmdファイルを配置する
  - 同じディレクトリ構造でS3にも配置し、画面に表示する際はS3経由で表示する
    - [未検証]アップロードは、publicフォルダに変更がある場合のCD時に実行する

## 使用技術

- nextjs v14.2.4
- [amplify Gen2](https://docs.amplify.aws/nextjs/)
  - バックエンド連携機能のうち、Storage機能を使ってS3と連携していきます

## 手順

既存のnextjsプロジェクトにAmplfy Gen2を連携していきます。
AWSのクレデンシャルが必要です。いい感じに設定ください。

- amplify Gen2の初期設定
  - プロジェクトルートで`npm create amplify@latest`
    - amplifyという名前のフォルダが作成されます。
- Storage設定
  - 基本的には[ドキュメント](https://docs.amplify.aws/nextjs/build-a-backend/storage/set-up-storage/)に書いてある通りで良い。
- S3から取れるようにする
  - [Storageのアクセス設定](https://docs.amplify.aws/nextjs/build-a-backend/storage/authorization/#access-types)はguestなユーザーに`read`権限付与
  - [mdは以下でダウンロード](https://docs.amplify.aws/nextjs/build-a-backend/storage/download-files/#get-the-text-value-of-downloaded-file)
    - パスの組み立てで
- 記事一覧画面では静的なファイル（JSON）を読み込んでいます。これで記事の一覧取得にAPIを使わず済みます。JSONの生成はS3にアップロード・更新するタイミングで行います。

## 詰まった点

### amplify.yml更新するのを忘れてた

背景として、amplifyでCDするプロジェクトのルートにamplify.ymlを配置してCD時の処理を記述できます。
私の場合は既存のAmplifyプロジェクトにバックエンド連携機能を追加したので、上記のStorage設定をデプロイする記述が不足していました。
[`npx ampx pipeline-deploy ......(略)`](https://github.com/aws-samples/amplify-next-template/blob/main/amplify.yml)を追加したら反映された

### `Amplify.configure`するベストな箇所がわからない!!

結局今もベストプラクティスはわかってなく、動くようにしただけなことは注意が必要。

【状況】

- Amplify.configureはルートエントリポイントに記述するもので、App router以降のnextjsならルートの`layout.tsx`がそれにあたる認識だった。
- ただ、上記の箇所だと、CSRな画面（`'use client';`）でAmplify.configureが実行されないぽい

【対策】

- `'use client;'`な画面のルートの`layout.tsx`にも個別に書く
なぜ全角スペースはダメなのか、使わない方がいいのか


# なぜ全角スペースはダメなのか
Ans: 日本のガラパゴスな概念だから。

たとえるなら、すでにメートル(Meter)という単位があるのに、「2 メートル分という単位があった方が便利だから **ニメートル(Nimeter)という単位をつくるよ**」ようなもの。

たしかに慣れたら便利かもしれないし、国内で通用するなら使わない理由はないかもしれないが、うーん、ガラパゴス。もちろん諸国はニメートルなどというガラパゴス単位など知りもしないし、配慮するつもりもないので通用しない。

メートルを使おうや。

# 使わない方がいいのか
Ans: ITとガッツリ携わりたいなら、はい。

## 1: 標準は半角スペースだけ
IT は英語をベースとしてつくられている。特に [Ascii 文字](https://e-words.jp/w/ASCII%E6%96%87%E5%AD%97.html)は、原子みたいなもので根幹を成す部分。ここでは半角スペースは使われているが、全角スペースはない。

## 2: 日本語圏ではスペースの切り替えがしづらい
日本語圏では、文字入力に IME を使うが、ここで半角スペースと全角スペースが交じる。

入力モードを切り替えたら制御できるが、ややこしい。また、IME の設定で「常に半角スペースにする」こともできるが、こんなマニアックなことは一般人はしない。知りもしない。

## 3: プログラミングやコマンドなど IT の作業中に全角スペースが混ざると死ぬ
IT の作業では Ascii 文字を使って、英語ベースの言語や単語を打つ。半角スペースも使う。

書いたコードやコマンドを処理するプログラムも、当然ながら半角スペースのみを想定する。なので **全角スペースが混ざっていると狂う**。で、日本語圏では 2: のとおり、全角スペースが混ざる率はかなり高い。

## まとめ
百害あって一利なしなので、使わない方がいい。IME の設定で今すぐ常に半角スペースにしてください。

# Q&A

## Q: 全角スペースにもニーズはあるよ？便利なところはあるよ？
あっ、はい。

IT においてウザい存在なので使わない。それだけっす。

それ以外の世界で、便利なら別に使えばいいと思う。たとえば日本語の小説を書くときは、空白は全角スペースで空けるのが作法。そもそも縦書きやその他日本語で出版する界隈では欠かせない存在の一つな気がする。よーわからん。興味もない。

## Q: 昔のワープロでは～～
昔の話はいいです。

# おまけ: レイアウト整えるのに使うやつ
メールやテキストファイルにおいて、空白を上手く入れてレイアウトを整えたいときにも全角スペースを使う人も多い。

あれは **諸悪の根源** の一つだと思っている。あれをするのに必要だから、全角スペースを捨てられない。あんなダサいことはしなくていいし、やるにしても半角でいい。そもそもプレーンテキスト上で神経質にレイアウトを整えようとすること自体がダサい。IT 音痴ですと言っているようなもので、恥ずかしいのでやめましょう。

ただし、この感覚は IT エンジニアやオタク側のものであり、そういうのが気にならないなら引き続き使ってもいいでしょう。
WordPressのmeta_queryでカスタムフィールドの空の初期値を取得する方法

## 【これを書くに至った経緯】

wordpressカスタムフィールドの真偽のチェックボックスですが、チェックボックスを管理画面から設定で追加した際のチェックボックスをデバッグしてみると初期値は空、チェックした場合は1、チェックを外すと値は0になります。そこで、meta_queryの絞り込みで、チェックボックスに対して、チェックをした状態や外した状態の、0と1は取得できますが、何も設定していないときの初期値である空の状態は、valueを""やNULLで指定しても取得することができませんでした。。

## 【結論から言うと】

WordPressの `meta_query` では、真偽のチェックボックスの初期値が空（未設定）の状態を取得するために、`compare` に ***`NOT EXISTS`*** を使用する必要があります。これにより、メタデータが保存されていない投稿も取得できます。

## 【なぜvalueを""(空文字)で指定してるのに初期値を取得できないか】

チェックボックスが空の状態、つまり未設定の場合、WordPressはそのメタキーをデータベースに保存しないことがあります。したがって、`meta_query` で `value` を空文字や `NULL` としても、該当する投稿が取得できません。この問題を解決するためには、`compare` に `NOT EXISTS` を指定して、メタキーが存在しない投稿を取得する必要があります。

## 【解決方法】

次のコードを使用することで、チェックボックスが `1`（チェックされている）、`0`（チェックが外されている）、またはメタキーが存在しない（初期値が空）投稿を全て取得できます。

```php
$args = array(
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key'     => 'display_flag',
            'value'   => '1',
            'compare' => '='
        ),
        array(
            'key'     => 'display_flag',
            'value'   => '0',
            'compare' => '='
        ),
        array(
            'key'     => 'display_flag',
            'compare' => 'NOT EXISTS'
        )
    )
);
$query = new WP_Query($args);
```
このコードでは、次の条件に基づいて投稿を取得します：

1. チェックされている投稿 (display_flag = 1)

2. チェックが外されている投稿 (display_flag = 0)

3. 初期値が空の投稿（メタキーが存在しない）

## 【まとめ】

カスタムフィールドでの真偽のチェックボックスが空（未設定）の状態を取得するには、**NOT EXISTS** を使用してメタキーが存在しない投稿も絞り込む必要があります。これにより、初期値が空の投稿を含めて検索結果に含めることが可能になります。
オープン系開発者がIBM iの環境構築から始めてみた①

### オープン系開発者がIBM iの環境構築から始めてみた①

投稿者の中の人はオープン系での開発経験が3年あるが
IBM iでの開発経験はいままでない

運用時代のヘルプデスクで軽く操作をしていた程度である。

今回色んなご縁もあり　IBM iを利用している
若手向けの交流会に参加することになり。チームでAIを使用した
FFRPGを使用したプログラム生成について研究することになった。

ふとこういう感情になった👇

### AIに生成してもらったコードをそのまま利用できるの(・・?

AI　＝　人工知能　色んな知識を吸収し学習した生命体みたいな認識の為
悪意のあるプロンプトエンジニアリングを学習した場合は
悪い部分も加味してAIは回答.....　

と描き続けると時間が足りないので割愛します。


#### さて、検証すると言ったものの・・・

### 企業毎に社内環境でのIBM i使用NGのケースもあることが判明！！


## じゃあ...社内環境を使わずになにか良い案はないものか??

### 個人開発用のPUB400ってものがあるらしいです。 これ使ってみては? （アドバイザーMさん）

# といった経緯で早速PUB400をインストール！！

検索上位に表示されました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/da1de698-57dd-a9dc-686f-fefb8bc16eb6.png)
サイトのページに入ってみると
登録しましょう！・パスワード忘れちゃった?　はわかるが...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/0de6a871-e283-2cbe-c9f3-53424ae39cb9.png)
わからないときは翻訳！翻訳！（若干変な日本語になるのはご愛嬌）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/de63c600-7fee-4ad1-11c2-bc5ad004612d.png)

左下のStart!をクリックすると別タブに遷移し下記の画面が表示

至ってシンプルな登録画面で
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/0f2ba88f-0f47-b8f7-148f-724a0a531f39.png)
ユーザー名も自由に選択できるようなので入力し登録！っと・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/e4e8a4db-449c-f773-0a15-72e138702846.png)

### あっ...(^_^;)やはりユーザー名の重複チェックで引っかかりますよね～
### サイト登録時あるある（ネーミングセンスが問われる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/3cafebcc-0641-b64f-f1bb-019c658dc368.png)
### 誰も使用していないと思うネーミングセンスが問われます！修正して送信！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/25a06fb7-bd0e-a8a2-dad1-e6d34df45d08.png)
### 左下に小さく「登録できたぜ！メール送るから今すぐこのページを閉じて」と表示されていますね。
### まずはユーザー登録が完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/e41cc1f1-7832-9e8f-e0d7-e9d42ae85743.png)
登録後すぐにメールがPUB400から送信されてきました。
（状況によっては翌営業日に送られてくるとのネット情報があったので思いの外、早い返信でした）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3872367/6a80563e-5c41-23e3-a2c2-fcabe53e3d30.png)


To Be Continue...
習慣化のための３つのポイント

![習慣.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3896079/a8a8f4db-755d-fbc3-86c7-b937e98f32ea.png)


# はじめに

こんにちは！！@hibiki_5166です！！
私はReactを学習中の駆け出しエンジニアです。
プライベートの時間で学習していますが、なかなか習慣化できずにいました。
そんな私が**３ヶ月継続**できて、習慣化することができた方法を皆さんにお伝えしたいと思います！
**<font color="red">習慣化は、勉強以外でも強力なパワーを発揮します。</font>**
日々の成長を加速させる要因になるので、ぜひ取り入れてみてほしいです！

# なぜ、習慣化が必要か

まず皆さん、次の質問について考えてみてください。

### これまで継続が失敗した原因はなんですか？

* 急に忙しくなって継続が困難になった
* 最初はモチベーションが高かったが、次第にモチベーションが下がって継続しなくなった
* なんかやる気でない

上記は一例ですが、当てはまった人もいると思います。
**私が考える継続失敗の原因は、<font color="red">モチベーションに頼ってしまっていることです。</font>**
何度も継続しようとして、失敗して、たどり着いた答えがこれです。

モチベーションは不安定な要素です。上がるか下がるかなんて分からない。
この不安要素に頼って継続をしようとしていることは、**<font color="red">運が良ければ継続できる</font>といっているようなものです。**

### ではどうすれば継続ができるか

**結論、習慣化することです。**
習慣化の最大のメリットは、<font color="red">**モチベーション関係なく行動できるという点**</font>です。
そして一度習慣化できれば、**やろうと考えていないがやっている、という状態がつくれます。**

文字だけ見ると意味わからない状態ですよね笑
でもこれは、3ヶ月継続してみて一番感じていることです。
最初はモチベーションと戦いながら、継続しようとやっていました。
試行錯誤しているうちに、**ある３つのポイント**にたどり着いて自然と習慣化できていました。


# ３つのポイント

### 1. 毎日手をつける
### 2. 開始時間を固定する
### 3. 集中できる環境でやる 

<br>こんなんで？と思った皆さん、、、こんなんでいけます！</br>
「こんなんで」というハードルが低いのも重要です。
それだけ日々の生活に取り入れやすいということです。
1つずつ解説していきますね。

# 1.毎日手をつける

毎日やるのきつくない？と思った人も多いと思います。
安心してください！
**<font color="red">「毎日手をつける」ことで重要な点は、「時間の長さは気にしない」ということです。</font>**

例えば、「今日は1時間やらなきゃ！」って思うと、忙しい日や疲れている日にハードルが高くなっちゃいますよね？
それで「今日はやらなくていいか」ってなっちゃう。
↑　このような経験ありませんか？

大切なのは、**たとえ5分でもいいから毎日手をつけること**
時間はあとでいくらでも伸ばせる、まずは毎日。
これは脳の仕組みにも関係していて、繰り返すことで脳がその行動を覚えて、どんどんやりやすくなる。
<font color="red">**短くてもいいから毎日やる。**</font>これがポイントです。

# 2.開始時間を固定する

次に2つ目は「開始時間を固定すること」。これもめちゃくちゃ重要です。

**皆さん、何かをやろうと思っても、「今日のどのタイミングでやろうかな？」って考えてるうちに、結局やらなかったことありませんか？**

これは、「今日のどのタイミングでやろうかな？」って考えた時点で、他のことを優先してしまった。
**嫌な言い方になりますが、<font color="red">楽な選択肢に逃げたんです。</font>**

では、**逃げないためにどうすればいいか。** 
**<font color="red">考えること自体をなくすことです。</font>**


そのためには、開始時間の固定です！

開始時間を決めると、「いつやろう」と考える必要がない。
時間が来たら始める、これだけです。

私の場合、平日は19時から、休日は朝８時と決めています。
これだけで、余計なことは考えなくなります。
**やる時間を固定する**、おすすめです。

# 3.集中できる環境でやる

**皆さんどこで作業していますか？**
<font color="red">家でやろうとしている人は注意が必要です。</font>
家はリラックスする場所なので、どうしても集中しにくくなりがちです。
**リラックスしたい自分と戦いながら、集中して作業できますか？**

ここで、
私のおすすめは、、、<font color="red">**カフェです！**</font>

何も特別ではないように見えますよね。笑

**ここで重要なのは、<font color="red">「自分が集中できる環境」という要素を満たしていることです。**</font>
なので、この要素を満たしていれば、正直どこでもいいと思います。

この **「自分が集中できる環境」には下記のような複数の要素が関係していると私は考えています。**
* 周りの音
* 人の量
* 落ち着き度合
* 視界に入るもの

私の場合、これらのちょうどいいバランスがカフェだっただけです。
皆さんも、自分に合う集中できる環境を探してみてください。

# まとめ
今回紹介したポイント、「毎日手をつける」「開始時間を固定する」「集中できる環境でやる」
これはシンプルですが、効果抜群だと思っています。
とくに、普段なまけてしまっているなと感じる人にはおススメです。
**シンプルなルールで、あとは行動するだけ。**
**<font color="red">シンプルさが習慣化を成功させるカギです。</font>**


# 最後に

習慣や継続はとても地味です。
どうしても心が折れる瞬間もあると思います。
逃げたいとき、どうでもよくなるとき。
そんなときに思い出してほしい言葉があります。
最後にこちらを紹介します。

これは、私が好きな漫画「宇宙兄弟」の主人公、南波六太の名言です。


### 一位と最下位との差なんて大したことねーんだよ
### ゴールすることとしないことの差に比べりゃ

~南波六太~


最下位でもいいんです、まずはゴールしましょう。

![ゴール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3896079/86bc761e-afa4-ce2c-7526-ad7a860302aa.jpeg)
クラスとインスタンスとオブジェクトの違い


# おことわり
- ざっくりとしたイメージを書きます
- 「JavaScript においては……」みたいなオタクなことは書きません

# クラス、インスタンス、オブジェクト

## クラスは設計図
**クラス（Class）** とは設計図のこと。

ただの設計図なので、これだけでは何の実物も生まれない。

英単語の意味を追いかけると「授業の単位」「分類」が出てくるが、ここでは関係ないので無視していい。

## インスタンスは設計図からつくった実体
**インスタンス（Instance）** とは設計図からつくった実物のこと。

設計図にしたがってつくったら、基本的に常に同じ実物がつくられる。ただし設計図には「パラメーター」という設定の余地があって、ここを変えることで違うものをつくれる。

**インスタンスの元は、必ずしもクラスではない** ことに注意する。プログラミングでは「クラス」から「インスタンス」をつくる構図だが、他のジャンルではそうとは限らないのだ。たとえばクラウドのインフラでは、実際につくったサーバー一台一台をインスタンスと呼ぶが、これの元はクラスとは呼ばない。元に対する名前は無いか、あるいは「イメージ」や「起動テンプレート」だったりする。

## オブジェクトは実体
**オブジェクト（Object）** とは実物のこと。

オブジェクトのうち、設計図からつくったものをインスタンスという。つまり **インスタンスはオブジェクトの一種**。

# 数式でたとえるのがわかりやすい
y = f(x) = ax + b を考える。

- クラスとは、ax + b という式のこと
    - a や b は内部の仕様として決まっている
    - ここでは a = 10、b = 5 にしよう
    - つまり、ここではクラスとは 10x + 5 という式
- インスタンスとは、x というパラメーターに何か入れてつくった値のこと
    - x = 1 を入れた場合、15 がインスタンス
    - x = 100 を入れた場合、1005 がインスタンス
    - x = 1 を 3 回入れたら、15 というインスタンスが 3 回出来上がる
- オブジェクトとは、数字のこと
    - a や b、あるいは x のときに使った数字ではない
    - 何らかの式から計算された数字のこと

# おしまい
イメージはこれくらいで良い。

あとはそれぞれの文脈でどう定義され、どう対応しているかをちゃんと勉強する。
RCONでPythonからMinecraftサーバーを停止させる

# RCONでPythonからMinecraftサーバーを停止させる
起動中にサーバーを停止したいとのことでRCONでPyからサーバーを停止させてみた

## 前提条件
- Pythonを導入していること
- Minecraftサーバーを設置していること

## MCRCONのインストール
```
pip install mcrcon
```

## server.properties
- server.properties
```properties
enable-rcon=true
rcon.password=(設定するパスワード)
rcon.port=25575
```

## 停止用スクリプト

- stop.py
```py
from mcrcon import MCRcon

# アドレス、パスワード、ポートの定義
ADDRESS = "localhost"
PASSWORD = "(設定したパスワード)"
PORT = 25575

def main(address, password, port):
  with MCRcon(address, password, port) as rcon:
    # stopコマンドを送信する
    rcon.command("stop")

if __name__ == '__main__':
  main(ADDRESS, PASSWORD, PORT)
  
```

## stop.py実行用batファイル
- stop.bat
```bat
python stop.py
pause
```