OmniAICreator/Qiita-1.07M huggingface dataset:
Vue.jsでinputタグを用いた入力文字の字数カウント

# Vue.jsでinputタグを用いた入力文字の字数カウント

## ① v-onディレクティブの利用

v-onディレクティブを用いることで、イベント発火時の JavaScript の実行が可能になります。
例えば
```
//v-on:イベント="関数"
<button v-on:click="hello()">ハローボタン</button>
```
と記述すると、ボタンクリック時にhello関数が実行される。

## ②イベントにkeyupイベントを記述する
keyupイベントは**keyが離されたタイミングで発火するイベント**です。
→テキストに文字が打たれてキーが離れたタイミングでイベントを発火させるのに利用します。
```
<input @keyup="hello()"></input>
```
※@は「v-on:」の代わりに使えるものです
　keyupイベントによく似たものにkeydownイベントがあります。そのイベントはkeyが押されたタイミングで
　イベントが発火します。



## ③文字数をカウントし、表示する関数を作成する
実際に文字数をカウントし、表示する関数を「countWord」という名前で作成してみましょう。
```
//関数の書き方はvue.jsのmethod内の書き方で記述しています
1  countWord:function(){
2      const inputElement = document.getElementById("word");//inputの要素を取得する
3      console.log(inputElement.value.length);//入力されている文字数を表示する
4    }
```

## ④inputタグと先ほどの関数を合わせる
```
HTML側
<input id="word" @keyup="countWord()"></input>
```
```
vue側
1　countWord:function(){
2      const inputElement = document.getElementById("word");//inputの要素を取得する
3      console.log(inputElement.value.length);//入力されている文字数を表示する
4    }
```
WWW（World Wide Web）

インターネットに接続する場合は、ほとんどの人が```インターネットプロバイダ```と呼ばれる接続事業者を利用する。
インターネットで使いたい機能のほとんどは```WWW```。
インターネットは```Webブラウザ```を使ってWebサーバから文字や画像、音声などさまざまな情報を得ることができる。
# Webサーバに、「くれ」と言って表示する
WebサーバとWebブラウザが欠かせない。
WebサーバとWebブラウザから必要なファイルを取り出すリクエストを送るとレスポンスが送られる。
このやりとりには```HTTP```のプロトコルが使われる。
## Webとは？
```正式名称を「World Wide Web」```といい、文字や画像、動画等を簡単に扱うことができるサービスです。掲示板のようなものと考えると分かりやすいでしょう。しかし、紙に書かれた掲示板と異なり、ネットワークを通じて見るWeb は、```「Webサーバ」と呼ばれるデータの保存場所に情報公開者がデータを保存```する（これを「アップロード」といいます。）ことで、世界中の人に情報を公開することが可能になります。このシステムを用いて```インターネット上で公開されている文書を「Web ページ」```と呼びます。
出典 https://www.kyoto-su.ac.jp/ccinfo/use_web/index.html

### 気づき
```Web＝WWW（サービス）```なのか。
サービスを利用するにはWebサーバとWebブラウザを使う。
Webサーバの中にWebページがあるのか。

## HTTPの特徴
* さまざまなファイルを扱える。
* 拡張も用意
* データを整形したり、特別な処理を加えない。
* 複数回のやりとりを追跡できないことにもなります。 このため買い物サイトなどでは、 別途cookieなどの技術を組み合わせて使うことで複数回のやりとりを追跡しています。
    出典　https://www.nic.ad.jp/ja/basics/terms/http.html

# WebページはHTMLで記述する
Webページは```HTML```と言う言語で記述されている。

## HTMLの書式
```タグと呼ばれる予約語```をテキストファイルの中に埋め込む。
アンカーというタグをつけると```他の文書へのリンクを設定```することができる。

タグの種類はたくさんある。出典元を見てください。
出典 http://html-coding.co.jp/annex/dictionary/html/

# URLはファイルの場所を示すパス
Web上で取得したいファイルの場所を指し示さなくてはならない。

### 例
```https://qiita.com/tags/%e5%88%9d%e5%bf%83%e8%80%85```
```https:```はプロトコル
```qiita.com```はドメイン名
```tags```はディレクトリ名
```%e5%88%9d%e5%bf%83%e8%80%85```はファイル名
意味は
```Https```のプロトコルを使って```qiita.com```と言うネットワークの```WWW```と言うWebサーバーが公開している```tags```ディレクトリの```%e5%88%9d%e5%bf%83%e8%80%85```と言うファイル

# Webサーバと外部プログラムを連携させる仕組みがCGI
* Webブラウザからの要求に応じて、Webサーバ側で外部プログラムを実行するために用いる仕組みに```CGI(Common Gateway Interface)```がある。

* NCSA HTTPDなどＷｅｂサーバが提供する機能の一つです。この機能によって、```Ｗｅｂブラウザからの入力をＷｅｂサーバを通してサーバが処理```し、何かを保存したり読みとったり、```Ｗｅｂサーバを通して、情報をＷｅｂブラウザに返したりできます```。
出典 http://www3.u-toyama.ac.jp/furuta/qa-cgi.html

```インタラクティブ（対話的）```なページを作ることができる。

出典 キタミ式イラストIT塾　基本情報技術者　令和03年
UnicodeDecodeErrorを回避する方法

【muiの記録】
現在、Djangoを使用してWebアプリケーションを作成しております。
データの処理でUnicodeDecodeErrorが出た際、回避方法を考えましたので共有します。

1、デコード時のユニコード判定してエラーを回避。
2、エンコード時に元のユニコードを指定。

###forms.py
```python

from django import forms

class UploadForm(forms.Form):
    #フォームから選択されたファイルを格納
    testfile = forms.FileField()

```
###views.py
```python

from django.shortcuts import render
from application.forms import UploadForm
import pandas as pd
import chardet

def url(reuest):
    if request.method == 'POST':
        upload = UploadForm(request.POST, request.FILES)
        if upload.is_valid():
            form_data = upload.clearned_data
            file = form_data['testfile']
            
            read_file = file.read()#ファイルの読み込み
            result = chardet.detect(read_file)#ユニコードの判別
            enc = result['encoding']#resultは辞書型なのでそこからencodingを取り出す。

            file_data = pd.read_csv(io.StringIO(read_file.decode(enc)),delimiter=',')#decode

            #処理

            after_file = #処理後のファイル
            type_data = 'text/csv; charset=' + enc
            response = HttpResponse(content_type=type_data)
            response['Content-Disposition'] = 'attachment; filename="result.csv"'

            after_file.to_csv(path_or_buf = response, encoding = enc, index=False)#encode

            return response
            

```

データが短いとchardetの精密性が損なわれてencにnoneが返されるのでそちらの解決が必要になります。
shift-jisとcp932のユニコードを使用してテストしてみるのもありです。
'foo@example.com'.match(/\x{email}/)

https://twitter.com/kazuho/status/1558592627234447361

文字クラス拡張すると車輪の再発明防げるかなと思い拡張してみました。

https://github.com/GitHub30/cc-regex

[![npm version](https://badge.fury.io/js/cc-regex.svg)](https://badge.fury.io/js/cc-regex)

## 使い方

### メールアドレス

```javascript
'foo@example.com'.match(/\x{email}/g)
// ['foo@example.com']
```

### URL

```javascript
'https://example.com/foo/bar'.match(/\x{url}/g)
// ['https://example.com/foo/bar']
```

### 都道府県

```javascript
'島根県にパソコンなんてあるわけないじゃん'.match(/\x{都道府県}/g)
// ['島根県']
```

### IPアドレス

```javascript
'127.0.0.1'.match(/\x{ip}/g)
// ['127.0.0.1']
```

### FQDN

```javascript
'example.com sub.example.com'.match(/\x{fqdn}/g)
// ['example.com', 'sub.example.com']
```

### 場所

```javascript
const str = '時どき私はそんな路を歩きながら、ふと、そこが京都ではなくて京都から何百里も離れた仙台とか長崎とか――そのような市へ今自分が来ているのだ――という錯覚を起こそうと努める。'
await str.matchAsync(/\x{場所}/g)
// ['京都', '京都', '仙台', '長崎']
```

### 人物

```javascript
await '昨日、ジョンと山田太郎は松のやでカツ丼を食した。'.matchAsync(/\x{人物}/g)
// ['ジョン', '山田太郎']
```

## インストール

```bash
npm install cc-regex
```

### ブラウザ

```html
<script src="https://github30.github.io/cc-regex/index.js">
```
PhpStormの重さ改善

# 概要
PhpStormが重く、フリーズすることが多いので改善方法を調査しました。
結果、割り当てるメモリを増やすことでフリーズなく動作するようになったので、改善手順を記載します。
# 環境
OS：Windows
PhpStormのバージョン：2022.1.3
# 手順
1. [ヘルプ]>[メモリ設定を変更]を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015414/b75aa8da-5af6-debe-cdfb-272aaca6ecfe.png)
2. [最大ヒープサイズ]を増やし、[保存して再起動]を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015414/1b1c917c-c887-6c80-57ed-f940eb199ffe.png)
SWRを用いてDynamoDBを操作してみた

## 概要
> fetch ポリフィル developit/unfetch など、任意のライブラリを使用してデータのフェッチを処理できます：

(引用元: [SWR-データフェッチ](https://swr.vercel.app/ja/docs/data-fetching))
とのことらしいのでDynamoDBの操作をSWRからやってみた、という記事です

## 環境
- Next.js: 12.2.5
- swr: 1.3.0
- @aws-cdk/client-dynamodb: 3.145.0

動作検証用にSWRと親和性の高いNext.jsを採用しています。またローカル環境での動作チェックのためDynamoDB-LocalをDockerコンテナ上で走らせることを想定しています。

## DynamoDBの操作

サンプルとして、IDが主キーになっているTODOリストから特定のIDのみを取得するQueryを実装します。DynamoDB-Localを用いているので、credentialsは適当なデータにしておきます。

(この実装方法だとリクエストを飛ばすたびに`DynamoDBClient`を生成しているのであまりよくない。。。)

```TypeScript
import { DynamoDBClient, QueryCommand, QueryCommandOutput } from "@aws-sdk/client-dynamodb"

const queryWrapper = async (id: number): Promise<QueryCommandOutput> => {
  const client = new DynamoDBClient({
    endpoint: "http://dynamodb-local:8000",
    region: "ap-northeast-1",
    credentials: { accesskeyId: "dummy", secretAccesskey: "dummy" },
  })

  const command = new QueryCommand({
    TableName: "posts",
    KeyConditionExpression: "id = :id",
    ExpressionAttributeValues: {
      "id": { N: String(id) },
    },
  })

  return await client.send(command)
}
```

## SWRを用いて叩く例
`useSWR`に渡す`fetcher`では、従来のような`fetch`を叩くのではなく`queryWrapper`を叩くようにします。取得したデータは`QueryCommandOutput`というDynamoDB特有の型になっているので適宜変換をしておく必要があります。(この例ではやってません)

```typescript
import useSWR from "swr"
import type { QueryCommandOutput } from "@aws-sdk/client-dynamodb"

interface FetcherInput {
  id: number
}

const postList = () => {
  const fetcher = ({ id }: FetcherInput) => queryWrapper(id)

  const { data } = useSWR<QueryCommandOutput>({ id: 1 }, fetcher)

  return data
}
```

## まとめ
~~いかがでしたか？~~

DynamoDBの操作をSWRを用いて行うことによって、リクエストのキャッシュなどのSWRのメリットを享受出来るようになりました。SWR側で細かい設定をすることなく、任意のデータフェッチ関数を渡すことでよしなに扱ってくれる点はSWRの良い点だと思ってます。

是非皆さんも使ってみてください！
terraformインストール

# terraform_0.12.20 インストール

```
curl -OL https://releases.hashicorp.com/terraform/0.12.20/terraform_0.12.20_linux_amd64.zip
unzip terraform_0.12.20_linux_amd64.zip
cp ./terraform_0.12.20_linux_amd64/terraform /usr/local/bin/
```
[WSL] Windows側のPATHもサーチするので注意

IDEでwsl連携して、アプリケーションを起動したときに、node実行部分で以下のエラーがでる

※適当にマスキングしてます(xxx)

```
Command 'npm xxx xxx' returned non-zero exit status 127.

> Process 'command 'aws'' finished with non-zero exit value 255
```

nodeでやっているところはawsとの連携設定なので、nodeから呼び出されたawscli部分で失敗してると推測。awscliのdefaultプロファイルの設定に問題がないか、認証できているかなど切り分けてくが、問題は見当たらない。

最終的に、原因はwslのPATHの設定で、Windows側のnpmが呼ばれていたこと。windows側のnpmが呼ばれた場合、Windows側のawscliが呼ばれていそう。そちらでは認証設定がwslと異なるので、npmが連鎖的に失敗する。

気づいたのは、wsl側で一度npmをアンインストールした状態で```which npm```を実行したら、Windowsにインストールしたnpmのパスが返ってきたこと(ちなみにnpmはもともと nvmで入れてて、最近asdfに鞍替えした)。

メモってないんだけど、以下のような感じ

```
$ which npm
/mnt/c/Program Files/node
```

で、PATHをよくよくながめてみると、たしかにWindows側のパスをサーチする設定が中盤以降に結構入ってる

```
PATH=/xxx/xxx:/xxx/xxx:/xxx/xxx/:.............
/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:
...............
```

Windowsの標準的なパス以外にも、Windows側にインストールしたIDEやソフトウェアのパスも結構入ってる。
Windows側のPATH見てみると、なるほどシステム環境変数側のPATHが網羅的にセットされてるみたい。

で、今回の場合は以下のトラブルをたぶん踏んだ

- IDEの実行環境をwslにする
- アプリケーションを起動してnpmが呼び出される
- wslにnpmはインストールされているのだが、パッケージマネージャでインストールしたnpmのパスが認識されていない
    - ここは切り分け甘いのだが、asdfやnvnでインストールしたnpmはユーザのホームディレクトリ配下にインストールされ、PATHが通されるが、そのPATHの指定の仕方(.bashrc, profileなど)によってはIDEのwslでセットされないため、見つからない
- PATHのサーチ順に従って、Windoows側のnpmが見つかり、呼び出される
- npmで(おそらくWindows側の)awscliが呼び出されるが、Windows側のawscliでは設定や認証が足りない
- awscliのエラーがでて、npm側にスローされる
- npmのエラーとして記録される

で、対応としては、npmを[degitalocean](https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04-ja)記載の手順でサーバにインストールした。こうすると/usr/bin/nodeに格納されるので、PATH周りのトラブルを回避しやすいと思う。
ただ、実行環境はasdfで統一したいのと、今後の使い方でWindows側でもnodejs必要になるかもしれないので、wsl周りの安全で独立した実行環境整備したい..


ということで、Windows, WSL両方でアプリケーション実行環境を立てているような使い方をしている場合注意が必要というお話でした
【Git】現在のブランチ名を取得する方法

以下のコマンドでカレントブランチ名を取得できます。

## `git rev-parse`
```:ターミナル
$ git rev-parse --abbrev-ref HEAD
main

$ git rev-parse --abbrev-ref @
main
```
detached HEADの場合にはHEADと出力される。


## `git symbolic-ref`
```:ターミナル
$ git symbolic-ref --short HEAD
main
```
detached HEADの場合には`fatal: ref HEAD is not a symbolic ref`と表示され異常終了する（終了コード: 128）。


## `git branch`
```:ターミナル
$ git branch --show-current
main
```
detached HEADの場合には何も出力されず正常終了する。

## `git name-rev`
```:ターミナル
$ git name-rev --name-only HEAD
main

$ git name-rev --name-only @   
main
```

detached HEADの場合にもブランチを取得できる。
HTMLのselect文、データベースから値を取り出して選択済みにする

Flaskを使用して店舗情報を管理するWEBアプリケーションを作成していた際、
データを打ち間違えた際、アップデートページを作りたいと思いました。
しかし、<select>タグで複数の値を扱っていた為、また初めから選択していると元々入力していた値を忘れてしまいます。
そこで、元々入力していた値を忘れないように初期値としてデータベースから取り出す方法を探し出しました。

最終的にたどり着いた答えはselectタグの中で一つづつ確認させるという方法です。
データベース(data)から取り出してきた初期値にしたいカラムを(list)とすると、
###update pageのHTML(jinja2)
```html
<form>
    <label>リスト</label>
    <select name="list" multiple>
        <option value="北海道" {% if "北海道" in data.list %}selected{% endif %}>北海道</option>
        <option value="青森県" {% if "青森県" in data.list %}selected{% endif %}>青森県</option>
        <option value="岩手県" {% if "岩手県" in data.list %}selected{% endif %}>岩手県</option>
        <option value="宮城県" {% if "宮城県" in data.list %}selected{% endif %}>宮城県</option>
        <option value="秋田県" {% if "秋田県" in data.list %}selected{% endif %}>秋田県</option>
        <option value="山形県" {% if "山形県" in data.list %}selected{% endif %}>山形県</option>
        <option value="福島県" {% if "福島県" in data.list %}selected{% endif %}>福島県</option>
           ・・・・・・・・・・・・・・・・
    </select>
</form>
```
とすると、元々選択していた値を忘れずに初期値として選択された状態にします。
リスト型に対応していないSQLAlchemy(sqlite3)で取り扱う方法

FlaskでWEBアプリケーションを作成している最中にデータベースにリスト型で格納したいと思い、方法を探していたところに「sqlite3はリスト型に対応していない」という記事を目の当たりにしました。。。

データベース変えようかなとも思いましたが、
request.form.getlist('___')というコードが存在していた為方法を模索した結果、、、、

1,getlist('')のみだと文字列型のリストとなり、HTML上でfor文を使用して回した際一文字づつの表示となってしまう。
2,JSONを使用した場合に関しても、JSON文字列のリストになる為、for文で回した際一文字づつの表示となってしまう。

最終的に、ワードを繋げたり離したりが可能なjoin,splitを使用しました。

###app.py(格納,取り出し)
```python

@app.route("/create", methods=['GET','POST'])
def create():
    if request.method == 'POST':
        
        name = request.form['name']
      #getlistで複数のデータを取得
        list_before = request.form.getlist('list')
      #データをカンマで繋ぐ
        list = ",".join(list_before)
        
        data = List(name = name, list = list)
        db.session.add(data)
        db.session.commit()
        return redirect('/')

@app.route("/detail")
def detail():
    #今回はデータベースの中身をすべて取り出す
    data_all = List.query.all()
    return render_template('detail.html', data = data_all)

```
###detail.html(for文で回す)
```html
<!--インスタンスを回す-->
{% for i in data %}
    <!--リスト名を表示-->
    {{ i.name }}
    <!--カンマ区切りで取り出し、listに代入-->
    {% set list = i.list.split(',') %}
    <!--代入したlistを回す-->
    {% for l in list %}
        <!--list内の複数のデータを順番に表示-->
        {{ l }}
    {% endfor %}
{% endif %}

```
以上です。
joinとsplitはセットで覚えておくといいかもです！
非常に重宝します。。
【Git】ブランチを削除する方法

## ローカルブランチを削除する
削除したいブランチ以外のブランチに移動します。
```:ターミナル
$ git checkrout main
```

以下のコマンドを実行してローカルブランチを削除します。

```:ターミナル
$ git branch -d 削除するブランチ名
```

## リモートブランチを削除する
以下のコマンドでリモートブランチを削除できます。
```:ターミナル
$ git push リモート名 --delete 削除するブランチ名
```
【JavaScript】イベントが突然発火しなくなった？documentでくくってみよう。

## はじめに
この記事にたどり着いた方はなんかボタンクリックしてもJSでイベントが発火しないというエラーを解決したくて訪れる人が多いかと思います。

自分も実務でこの通常時はイベント発火するのになぜかイベントが発火しない時があるというエラーに2回も遭遇しました。結構よくある事象なのかと思いここに備忘録として残しておきたいと思います。

## 実際にあった事例
1.非同期で切り替えた時（期間指定やチェックボックス選択時）に、JSで実装していたCSVダウンロードボタンが機能しなくなっていた。
2.投稿フォームの投稿ボタンに対しクリックイベントを追加していたが、投稿ボタンクリック時に他のエラーが非同期で発動した後、クリックイベントが発火しなくなった。

## 結論
``(document).on("click", element``にして動的に追加したDOMに対してもJS発火するよう修正すればイベント発火が問題なくされる。

```sample.js
//Before
$(".open-csv-modal").on("click",() => {
  //イベント内処理//
});

//After
$(document).on("click", ".open-csv-modal", () => {
  //イベント内処理//
});
```

### ところでDOMってなに？
HTMLをプログラムで色々操作するための仕組みのこと。
今回だとこのボタンを押したらこういった動きをさせるようDOM操作を行うみたいな感じ。

基本HTML上のクラスやid、あとは普通のタグを指定、それに対しどういった操作をするかをJavaScriptで記述していく。他にも文字の色を変えたり、文字をサイト上に挿入したりDOM操作で色々できる。

参考

https://eng-entrance.com/what-is-dom

## あとがき
今回は日付選択した後やフォーム投稿時に非同期でエラーが出た後など、非同期後でもクリックイベントなどのイベント発火がされるようどう記述したらいいのかを備忘録として残しておきました。

今後通常時は動くのに何故かイベント発火しなくなったなどあればこれを疑うのも良いかもしれません。
SciPyのMILPソルバーを簡単に実行するための関数を実装した

※更新履歴

- 2022/08/15 Githubのソースコード修正、それに伴う記事内のサンプルコード修正
    - @nariaki3551 さんに最適化結果をpulpにデコードする関数を実装していただきました。簡潔でとても便利です。ありがとうございます！
    - @nariaki3551 さんにReadMeのサンプルコードのバグを修正していただきました。ありがとうございます！
- 2022/8/17 ソースコード修正(v0.1.2)、[改善点](https://qiita.com/rtonoue/items/a6c73f8690083c98812f#%E6%94%B9%E5%96%84%E7%82%B9)の更新
    - pypiにアップロードしたので、```$ pip install pulp2mat```でインストールできるようになりました。
    - 最大化問題に対応、ただし目的関数の値の正負が反転します。
- 2022/8/21 ソースコード修正(v0.1.3)、それに伴う記事内のサンプルコード修正
    - @nariaki3551 さんにpull requestいただきました。以前は変数を辞書形式で定義する必要がありましたが、pulp.LpProblemのオブジェクトからとってこれるようになり、使いやすくなりました。

## 参考にしたもの

- [SciPyのMILPは使えるのか？？（SciPy==1.9.0の新機能の検証）](https://qiita.com/s-inoue-git/items/5e4c16fc125ab9e3fbd5)
- [scipy.optimize.milp](https://scipy.github.io/devdocs/reference/generated/scipy.optimize.milp.html)

## 背景

[SciPyのMILPは使えるのか？？（SciPy==1.9.0の新機能の検証）](https://qiita.com/s-inoue-git/items/5e4c16fc125ab9e3fbd5)によると、ScipyのMILPソルバーが高速だが、使いにくいとのこと。確かに変数の種類が複数あると、行列表現するのは大変そう。だが、

> 実務MILPを解く場合は、GurobiやCPLEXを使うしかない。

こう言われてしまうと実務家として頑張りたくなってしまったので、pulpの定式をscipyの入力に変換する関数を自作することにした。引用元ではpyomoを使っているが、pyomoは使ったことがないので今回はpulpを用いた。

## 実装したもの

Github:

https://github.com/rtonoue/pulp2mat

Pypi:

https://pypi.org/project/pulp2mat/

## 使い方

```$ pip install pulp2mat```でインストールできる。

~~ReadMeに書いてあるが、使い方の注意点として、**すべての変数を辞書形式で定義する必要がある**。~~
※ 2022/8/21 修正: v0.1.3から、変数の持ち方は特に問わないような実装に変更した。

例えば1次元ビンパッキング問題の場合、以下$x$, $y$を定義する。

$x_{ij} \in 0,1$: アイテム$i$をビン$j$に詰め込むか否か

$y_{j} \in 0,1$: ビン$j$にアイテムが入っているか否か

pulpでの実装はこのようになる。
```python
import pulp as pl
import numpy as np

item_sizes = np.array([7, 3, 3, 1, 6, 8, 4, 9, 5, 2])
num_items = len(item_sizes)
num_bins = len(item_sizes)
bin_size = 10

# Variables * must be defined as dictionaries
x = {
    (i, j): pl.LpVariable("x_{}_{}".format(i, j), cat=pl.LpBinary)
    for i in range(num_items)
    for j in range(num_bins)
}
y = {
    j: pl.LpVariable("y_{}".format(j), cat=pl.LpBinary)
    for j in range(num_bins)
}

problem = pl.LpProblem()

# Bin size constraint for each bin
for j in range(num_bins):
    problem += (
        pl.lpSum(
            x[i, j] * item_sizes[i] for i in range(num_items)
        )
        <= bin_size * y[j]
    )
# One-hot constraint for each item
for i in range(num_items):
    problem += pl.lpSum(x[i, j] for j in range(num_bins)) == 1

# Objective: minimize number of bins used.
problem += pl.lpSum(y[j] for j in range(num_bins))
```

```pulp.LpProblem``` オブジェクトを```scipy.optimize.milp```への入力に変換するために、```pulp2mat.convert_all()```関数を用いる。

```python
import pulp2mat
from scipy.optimize import milp
c, integrality, constraints, bounds = pulp2mat.convert_all(problem)
result = milp(c, integrality=integrality, constraints=constraints, bounds=bounds)
```

## 改善点
- ~~まだ最大化問題には対応していない。最大化問題の場合は、目的関数の正負を反転させる必要がある。~~ **2022/8/17対応済み**
- 問題サイズが大きい場合や反復実行する場合は、変換の速度が問題になりそう。
- ~~```pip install```できるようにする~~ **2022/8/17対応済み**
- まだビンパッキング問題でしかテストしていないので、バグなどのご指摘を歓迎します。
XQ-BT44のBand 8を有効化できるか挑戦中

# ポイント

* 潰されたBandを有効化するにはSoC内のNVMを書き換える必要がある
* NVMを書き換えるには、rootを取ってDiagモードでPCと接続する必要がある
* rootを取るにはBootloaderのアンロックが必要
* BootloaderのアンロックをするとTA領域とpersistが書き換えられる
* TA領域にはDRMキーが格納されている
* DRMキーが削除されると、動画再生時の高画質処理、カメラのノイズ低減処理、WideVine L1が採用されるサービスが使用できなくなる
* TAとpersistをバックアップをするには一時root取得の状態で以下のようなコマンドを実行する
  ```
  su
  dd if=/dev/block/bootdevice/by-name/TA of=/sdcard/ta.img
  dd if=/dev/block/bootdevice/by-name/persist of=/sdcard/persist.img
  ```
* 一時rootが可能な端末は脆弱性をついていることがほとんどのため一部機種、バージョンに限られる
    * XQ-BT44 は今のところできない

# TAバックアップ/リストア
* TAは[newflasher](https://github.com/munjeni/newflasher)でもバックアップできる
    * バックアップ
        * flashモードで接続後、newflasherを起動
        * n > s > y でバックアップ開始
        * 同じ階層に`tadump\tadump_2.ta`ができる
    * リストア
        * `tadump\tadump_2.ta`にnewflasherをコピー
        * flashモードで接続後、newflasherを起動
        * n > s > n でリストア開始(ここに別の.taファイルがあったりするとそれも書き込まれるため注意)
* リストアされたファイルの概要
    * [このあたり](https://github.com/munjeni/newflasher/blob/99179a8762368dbc8bcda69cd1bee1d6da23f6f2/newflasher.c#L2485-L2491)を見ると分かる
    * ここ、continueしているため、XDAでリリースされている実行ファイルでは書き込まれないはず。
* コード編集の上自分でビルドしたければgit cloneしてmakeすればOK
    * wsl(Ubuntu)からexeをビルドする場合
        * `make newflasher.exe`
        * エラーになる場合は`mingw-w64`をapt でインストール
        * その他のエラーは臨機応変に。

# Bootloaderアンロック

> 参考 : https://blog.h2o-feeling.com/?p=547

# root取得

> 参考 : https://blog.h2o-feeling.com/?p=547

# Diagモード
* ドライバ入手 [HTC_Diag_x64.zip](https://forum.xda-developers.com/t/htc-diag-x64-driver.801570/)
* infファイル内の`[Models.NTamd64]`セクションを`USB\VID_05C6&PID_90DB&MI_00`に書き換え
```
adb shell
su
setprop persist.usb.eng 1
```
* USBデバッグを OFF/ON
* ドライバを当てる

> 参考 : 
> https://saki-sss.blogspot.com/2014/02/xperia-z-c6603.html
> https://tek2tech.com/install-drivers-without-signing-on-windows10/

# NVM書き換え

> 参考 : https://andmem.blogspot.com/2013/11/mobilebandchange.html
RSA暗号について触って確かめられるものを作ってみました

株式会社POLでサーバサイドエンジニアをやっております岩井です。

業務の中でAWSのEC2などにログインできるように設定するために、「公開鍵を教えてください」とお願いすることがたまにあるのですが、それをお願いする相手が必ずしもエンジニアではない場合もあり、「言われるがままに教えたけど、"鍵"を渡しても大丈夫なのか？」などと不安に思わせていたらまずいかなと思い、「公開鍵は〜ということで公開しても大丈夫です」という感じのことを説明するものを、勉強がてら作ってみました。

https://waiiwai.github.io/articles/publicKey/

「公開鍵で暗号化した場合、公開鍵で復号化はできない」といったことを確認できるようなサイトが見当たらなかったので、そういったギミックをつけています。
鍵の計算に関しては、数学力が至らなくて数学的には説明不足の点もあるかと思いますが、うまく説明できるようになったら追記する予定です。

今のテクノロジーは、先人たちの努力の上に「正確に知らなくても使える」ことが成り立っているので、それに乗っかるのも良いですが、改めて調べてみると全然わからず使っているものがあるなと思い知らされますね（RSA暗号とその周辺の数学知識について数ヶ月調べていますが、まだあまりわかった気がしていません）。

大嘘を書いていたらご指摘いただけると幸いです。
AIビジネスのダブルハーベスト: 戦わなくても勝ち続けてしまうループ?

## はじめに

「僕は技術者なので、ビジネスはわかりません」
「僕は技術者ではないので、技術のことはわかりません」

AI時代に淘汰されてしまう人の特徴を、
[『ダブルハーベスト 勝ち続ける仕組みをつくるAI時代の戦略デザイン』](https://www.amazon.co.jp/%E3%83%80%E3%83%96%E3%83%AB%E3%83%8F%E3%83%BC%E3%83%99%E3%82%B9%E3%83%88-%E5%8B%9D%E3%81%A1%E7%B6%9A%E3%81%91%E3%82%8B%E4%BB%95%E7%B5%84%E3%81%BF%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8BAI%E6%99%82%E4%BB%A3%E3%81%AE%E6%88%A6%E7%95%A5%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-%E5%A0%80%E7%94%B0-%E5%89%B5/dp/4478111014)
の著者である堀田創さんは、このように指摘されています。

ダブルハーベスト、すごい!
でも、本質がよく理解できない、どう行動すればよいかピンとこない。

## ダブルハーベスト(多重収穫)とは

- ただ稼ぐのではなく、何重にも稼ぎ続ける、次なる時代の勝ちパターン
- ベゾスがAmazon創業前にメモ書きした『戦わなくても勝ち続けてしまうループ』
- AIを活用して企業の戦略デザインを行ったり、DXを推進する為にも欠かせない考え方や仕組み

と、本に述べられています。

真剣に理解したいが、技術者なので(言い訳)ビジネスシーンが思い浮かばない。。。

## 技術者がダブルハーベストを理解するには

ダブルハーベストは、機械学習の一種である`強化学習`と似ているようです。
例えば、囲碁AIが打ち手を学習するとき、
様々な対戦データから`勝ちパターン`を見つけ、さらに自分を強化していく。

- 強化学習(RL: Reinforcement Learning)とは
    - 機械学習手法の一つで、システム自身が試行錯誤しながら探索し続け、最適なシステム制御を実現する機械学習手法
    - 長期的な目標に向けた最適化を行いつつ、短期的な決定を下すこともできる
    - 行動に対するフィードバック(報酬/罰)をトレーニングデータとし、報酬(スコア)の最大化を目的に行動を学習
        - 犬のしつけでお座り命令で犬がお座りできたら報酬として餌をあげる
        - 何度も繰り返しトレーニングするうちにお座りを学習できる
    - 学習データの正解(ラベル付けされたトレーニングデータ)がない場合も、複雑な動作を学習可能
        - 教師あり/教師なしと並ぶ学習手法の一つである
    - 利用シーン
        - 将棋AI/囲碁AIなどゲームAIが打ち手を学習
        - 自動運転における状況判断の学習
        - 自律制御ロボット

`強化学習`を経て、さらに難しい局面で自己対戦を繰り返す、
より高度な勝ちパターンを身に着けていく。。。
これで、勝ち続けるループの仕組みが出来上がる?

## おわりに

自分なりに、ダブルハーベストを理解してみました(理解できたかはさておき)。

AI時代に求められるのは`リーダーシップ`と`俯瞰力`とのことです(by 堀田創さん)
※ 引用元: https://careerhack.en-japan.com/report/detail/1558

組織としても個人としても、どのようにAI時代に生き残るか。
ダブルハーベストの仕組みを理解し、戦略を立てることがカギになりそうです。
Kali Linux を Mac風 にする方法（かんたん）

# 概要
デフォルトはカクついているのでMAC風にする。

# 手順
## apt Update and Upgrade
`$ sudo apt update && sudo apt upgrade`　

## GNOMEをインストール
`sudo apt install kali-desktop-gnome -y`

しばらくすると画面が出てくるのでgdm3を選択

## 再起動
`$ sudo reboot`

# 参考資料
https://linuxconfig.org/how-to-install-gnome-desktop-on-kali-linux
STM32G031と液晶、ACM1602K-NLW-BBWで3分タイマー(74HC164)(mbed)


x 超超重要 なぜか秋月STM32G031J6M6がうり切れていた。注意!!(2022/8/27現在)


x 過去ログを見よ!!

x 原因は、わからないが液晶がちらつく場合は、ウェートを調整してね!!
  (電源-GND間のパスコン(47μF～100μF...するといいらしい)

x STM32G031とは、秋月で売っているSTM32G031J6M6の事


目的
パラレルLCDのテスト


STM32L010でMbedを使い16文字2行液晶に3分を
表示するプログラム

74hc164シフトレジスターを使用した。
液晶とのピン数を節約した。信号線10本から
信号線3本に減らした。

1 CLK クロック端子(緑色)
2 RSDATA RS端子とデータの共有端子(黄色)
3 E 読み込み書き込み同期信号(青色)

秋月電子
キャラクター液晶 [ACM1602K-NLW-BBW] 通販コード　P-10185
半固定ボリューム１０ｋΩ [TSR-065-103-R] 通販コード　P-06063
CD74AC164E　通販コード　I-11356

アイテンドウ
8ビットシフトレジスタ [HD74LS164P]　www.aitendo.com/product/12485


![o_con679.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/efcc9722-ba6c-a21f-20f8-df8c486a40f5.jpeg)



![o_con678.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e791704a-1b9d-6370-1268-d1adc0a8dab0.jpeg)





参考


https://qiita.com/caa45040/items/974d5145a3357783f962




```c++


// gpio_P_LCD_3min_031_1


#include "mbed.h"

//*          *****  *****       ***  * *
//*         *       *    *     *   * * *
//*         *       *    *     *   * * *
//*         *       *    *     *   * * *
//*         *       *    *     *   * * *
//********   *****  *****       ***  * *

#define swclk1  PA_11    //
#define swdio1  PA_12    //
#define en1     PB_7     //

DigitalOut swdclk(swclk1);
DigitalOut swdio(swdio1);
DigitalOut en(en1);

int kk;
#define oun_min() for(kk=0;kk<60;kk++){wait_us(1000*1000);}

void seg1(int v,int rs)
{
    for(int jj=0;jj<8;jj++){
        if( (v<<jj) & 0x80 ){      
                swdio=1; //ビットが1
        } else {
                swdio=0; //ビットが0
        }//endif
        swdclk=1;swdclk=0; //clk
    }//for

    swdio=rs;
    en=1;    wait_us(1000);
    en=0;
}

//文字列の表示 nana_seg
int ns_printf(char *str1) {

    //文字の中身がゼロか
    while(*str1){

        //一文字出力
        seg1( *str1 ++ , 1  );

    } //while

    //戻り値
    return(0);
}//ns_printf

int lcd_int[]={
  0x30,0x30,0x30,0x38,0x08,0x01,0x06,0x08+0x04
};//lcd_init

int main() {

    // 3s wait  not delete
    wait_us(3*1000);

    //GPIOの初期化
    en=0;

    //液晶の初期化
    for(int ii=0;ii<8;ii++){ 
        seg1( lcd_int[ii] , 0);wait_us(2000);
    }//for

    seg1( 0x80+0x00 , 0  ); //1ライン目にカーソルを移動
    ns_printf( (char *)"START" ); wait_us(500*1000);
    
    //画面クリア
    seg1(   0x01  , 0  ); 
    wait_us(5*1000);

    ns_printf( (char *)"0," );
    oun_min()
    ns_printf( (char *)"1," );
    oun_min()
    ns_printf( (char *)"2," );
    oun_min()
    ns_printf( (char *)"3" );

    while(1){} //無限ループ

}//main



```
小道具：素数表（エラトステネスの篩）

指定した上限で素数表を出力します。アルゴリズムはエラトステネスの篩なので遅いです。

```python:pntab.py
#!/usr/bin/env python3

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('N', type=int, help="上限")
args = parser.parse_args()

pntab = lambda N: (set([2] + [o for o in range(3, N + 1, 2)]) -
                   set(a * b
                       for a in range(3, (N + 2) // 3, 2)
                       for b in range(3, (N + a - 1) // a, 2)))

m = ''
for d in sorted(pntab(args.N)):
    m += '%d,' % d
    if len(m) > 72:
        print(m)
        m = ''
m and print(m)
```

```console:実行例
$ python3 pntab.py 1000
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,
103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,
199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,
313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,
433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,
563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,
673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,
811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,
941,947,953,967,971,977,983,991,997,
```
PIC32MX開発環境2022-2024

PIC32MXの開発環境の一覧です。

* MPLAB X - Windows,Linux,Mac

本家Microchip製の開発環境です。無料です。Win7にv5.45を入れてありますが、重いのであまり使いたくありません。もちろんすべてのPIC32MXが開発できます。これ書くためにページを見たら6.00になってました。

* PlatformIO - Windows,Linux,Mac

オープンソースのプロジェクトでCLI,GUIのIDEがありますchipKITという開発ボードが主要なターゲットで、Flashが大きいものになります。CLI版はMacでは正常に使えますが、Linux版をFreeBSDのエミュレーションで使うとエラーが出ます。

* Pinguino Project - Windows,Linux

オープンソースのArudinoライクなプロジェクトです。昔はMac版もあったのですが、無くなってました。PIC32MX220F032からサポートされてます。

* Arduino IDE - Windows,Linux,Mac

ボードマネージャーで追加して開発が可能なようです。

自分は当初ネットで調べたPinguinoのコンパイラーを使っていたのですが、Microchipの提供するファイルが必要でした。そのため、Platformioには移せませんでした。いろいろ調べてみたところ、Microchipの提供ファイルと同等のものがgithubのレポジトリにあったので、Pinguinoのバイナリと、そのレポジトリのファイルでビルドできるようになりました。

書き込みはchipKitではブートを操作して特別な機器が必要なくUSBで書き込めますが、素のチップの場合PicKit2や3などが必要になります。これらはもう販売されていないので、Microbridgeを使うのがお勧めです。

https://qiita.com/yamori813/items/c08e460f962dc939ef32

半導体不足といわれていますが、秋月電子に潤沢に在庫がありますから、あなたもPIC32MXを始めてみませんか？

海外ではいろいろ開発ボードがあるようですが、国内ではあまり見かけません。@h_nariさんが配布しているボードが安価でお勧めです。

https://shop.humblesoft.com/products/detail/8

ユニバーサル基板で作るのであればchipKIT DP32がお勧めです。

https://chipkit.net/diy-chipkit-board-using-a-through-hole-spdip-pic32

PIC32MX250F128Bは秋月にあります。bootをどうやって書くかの問題はありますが、bootを書いてしまえばPGMボタンを押してUSBプラグすると書き込みモードになるので、platformioのuploadで簡単に焼けます。

2022/8現在、秋月の取り扱いでPIC32MX220F032Bが330円なのですが、これよりflashが大きい、PIC32MX230F064Bが270円と逆転していて、お得なようです。PIC32MX220F032は取り扱い最初からあり、最初は220円でしたが値上げを繰り返して、その後入ってきたPIC32MX230F064Bの仕入れ値の方が安かったのかもしれません。DeadStockになっているので、処分品も出てますし、すべてDigikeyより安いです。
yum install nodejs | Error: Package: 1:nodejs-16.15.0-3.el7.x86_64 (epel)

3ヶ月ぐらいに触れていなかったプロダクトアプリ立ち上げるために`docker-compoer up -d`しましたとさ。
以下のエラーがでましたとさ。

```
Loaded plugins: ovl, priorities
240 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
---> Package nodejs.x86_64 1:16.15.0-3.el7 will be installed
--> Processing Dependency: nodejs-libs(x86-64) = 1:16.15.0-3.el7 for package: 1:nodejs-16.15.0-3.el7.x86_64
--> Processing Dependency: libuv >= 1:1.43.0 for package: 1:nodejs-16.15.0-3.el7.x86_64
--> Processing Dependency: openssl11 >= 1:1.1.1 for package: 1:nodejs-16.15.0-3.el7.x86_64
--> Processing Dependency: libbrotlidec.so.1()(64bit) for package: 1:nodejs-16.15.0-3.el7.x86_64
--> Processing Dependency: libbrotlienc.so.1()(64bit) for package: 1:nodejs-16.15.0-3.el7.x86_64
--> Processing Dependency: libnode.so.93()(64bit) for package: 1:nodejs-16.15.0-3.el7.x86_64
--> Processing Dependency: libuv.so.1()(64bit) for package: 1:nodejs-16.15.0-3.el7.x86_64
--> Running transaction check
---> Package brotli.x86_64 0:1.0.7-5.el7 will be installed
---> Package libuv.x86_64 1:1.39.0-1.amzn2 will be installed
---> Package nodejs.x86_64 1:16.15.0-3.el7 will be installed
--> Processing Dependency: libuv >= 1:1.43.0 for package: 1:nodejs-16.15.0-3.el7.x86_64
---> Package nodejs-libs.x86_64 1:16.15.0-3.el7 will be installed
---> Package openssl11.x86_64 1:1.1.1g-12.amzn2.0.9 will be installed
--> Finished Dependency Resolution
Error: Package: 1:nodejs-16.15.0-3.el7.x86_64 (epel)
           Requires: libuv >= 1:1.43.0
           Available: 1:libuv-1.23.2-1.amzn2.0.2.i686 (amzn2-core)
               libuv = 1:1.23.2-1.amzn2.0.2
           Available: 1:libuv-1.39.0-1.amzn2.i686 (amzn2-core)
               libuv = 1:1.39.0-1.amzn2
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest
```

該当箇所は以下でしたとさ。

```Dockerfile
# APIドキュメント管理出力ツール
RUN yum install -y sudo \
    && sudo yum install -y nodejs \
    && npm install -g aglio --unsafe-perm
```

ピンポイントでは`sudo yum install -y nodejs`の部分で失敗してる...　と。

まぁググってもなかなか出てこないエラーだったので誰かが似たような検索したときに記事にでもしておけばヒットするだろうと残しておくことにしましたとさ。

Dockerfile内のaglio installする前にリポジトリがnode12に対応するようにしてたんだけどさ

```Dockerfile
RUN curl -sL https://rpm.nodesource.com/setup_12.x | bash -
```

現時点のLTS14だから入れ替えたらaglioも無事installできたとさ。

```Dockerfile
RUN curl -sL https://rpm.nodesource.com/setup_14.x | bash -
```

npmとnodeってamazonlinuxにどうやっていれるんだっけって調べてたら以下の記事見つけて。

https://qiita.com/leomaro7/items/2c3a767bbbb6cc535b19

そのまま`curl -sL https://rpm.nodesource.com/setup_10.x | bash -`実行したらLTSがなにかサジェストしてくれてたので最新のLTSに差し替えればいけるじゃないかということで解決に至りましたとさ。

```
   * https://rpm.nodesource.com/setup_12.x - Node.js v12 LTS "Erbium"
   * https://rpm.nodesource.com/setup_14.x - Node.js v14 LTS "Fermium" (recommended)
   * https://rpm.nodesource.com/setup_16.x - Node.js v16 "Gallium"
```
2022/8/15主にITとかセキュリティの記事

シスコがサイバー攻撃受け不正侵入、きっかけは従業員の個人Googleアカウント悪用(8/13)
https://news.mynavi.jp/techplus/article/20220813-2423685/

［社説］サイバー防衛の強化へ行動を速やかに(8/12)
https://www.nikkei.com/article/DGXZQODK093GW0Z00C22A8000000/

サイバー戦で中国の攻撃を日本はなぜ防ぐことができないのか？(8/12)
https://news.livedoor.com/article/detail/22667718/

ニチリン、データ流出確認されず　米子会社サーバーのウイルス感染問題で(8/12)
https://www.kobe-np.co.jp/news/keizai/202208/0015550301.shtml

36％の企業が「人的資本経営」を優先度が高い事項として議論
取り組み・検討上位は「人事情報基盤の整備」と「社員エンゲージメントの把握」(8/12)
https://prtimes.jp/main/html/rd/p/000000054.000082530.html

Azure ADとは？料金プランや機能・メリットをわかりやすく解説(8/13)
https://and-engineer.com/articles/YaOaSBIAACAAjdJi

GitHub、怪しいアクションを見つけて報告する防御機能を開始(8/13)
https://news.mynavi.jp/techplus/article/20220813-2423844/

Zoom for Mac v5.11.3より前のインストーラーにroot権限昇格の脆弱性が発見されたとして、Zoomがアップデートを呼びかけるも、再び問題が確認される。(8/13)
https://applech2.com/archives/20220813-zoom-for-mac-root-privilege-escalation.html

Windows 11ミニTips 第106回 任意のアプリをショートカットで「常に手前に表示」する(8/13)
https://gunosy.com/articles/ayX9h

UEFIブートローダに脆弱性、セキュアブートをバイパスしコードを実行(8/13)
https://news.mynavi.jp/techplus/article/20220813-2423729/

ラズパイでメッシュネットワークを作成する　構築編その1(8/13)
https://www.itmedia.co.jp/news/articles/2208/13/news037.html

Gitとは？GitHubとの違いやメリットをわかりやすく解説！(8/13)
https://and-engineer.com/articles/Yt4s9BAAACEA700C

オランダ捜査機関「Tornado Cash」関与の疑いで29歳の開発者を逮捕(8/13)
https://bittimes.net/news/130194.html

Goerliテストネットで「マージ」が正常に完了、9月19日予定のマージに向け前進(8/11)
https://jp.cointelegraph.com/news/sept-19-ethereum-merge-date-on-track-as-goerli-test-merge-successfully-finalized
Ubuntu22.04 nginxを設定する nginx+gunicorn+Django

## 概要
リモートサーバのUbuntu22.04にインストールしたnginx1.22.0をgunicornと連携できるように設定します。さらに、Django+DRFのAPIサーバへの連携も行い、作業用PCのブラウザからアクセスできるようにします。nginx、gunicornはインストール済み、Django+DRFのAPIサーバは完成済みの状態です。

https://qiita.com/lustm5/items/222e952ec74c7b52f867

https://qiita.com/lustm5/items/d1959eda1a8f3b97e1e6

環境(開発環境)
Ubuntu22.04 IP 192.168.88.15
作業用PC Windows10 Pro IP 192.168.88.1
nginx 1.22.0 ポート80番
gunicorn 20.1.0
Python 3.10.6
Django 3.2.15 ポート8000番
DRF 3.13.1

## 設定するにあたって
ubuntu標準ではなくリポジトリ追加してnginxをインストールしたので、[参考にさせてもらった情報](https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-22-04)とは/etc/nginx内のファイル・フォルダ構成が違いました。具体的には、sites-availableやsites-enabledフォルダがなく、proxy_paramsファイルがありませんでした。こちらのページを見させていただき、違うことに気づきました。

https://qiita.com/ekzemplaro/items/e9454cf997d9dbfece83

そこで、nginxのメインの設定ファイル(/etc/nginx/nginx.conf)を見ると、
```/etc/nginx/nginx.conf 抜粋
include /etc/nginx/conf.d/*.conf;
```
と記述があり、デフォルトでは/etc/nginx/conf.dフォルダ内の.confファイルを読む設定になっていました。/etc/nginx/nginx.confにinclude /etc/nginx/sites-enabled/*;を追記して、sites-availableやsites-enabledフォルダなどをmkdirで作成する方法もありましたが、デフォルトの方法で進めようと思います。

/etc/nginx/conf.dフォルダ内に.confファイルを作成して、80番ポートへのアクセスをソケットに投げるの内容などを設定ファイルに書いていきます。もともとあった/etc/nginx/conf.d/default.confはバックアップを取って消しました。

## 設定
/etc/nginx/conf.dにnginxの設定ファイル(apitest.conf)を作成します。
```
$ sudo nano /etc/nginx/conf.d/apitest.conf
```
```/etc/nginx/conf.d/apitest.conf
server {
    listen 80;
    server_name 192.168.88.15;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/lustm5/solution;
    }

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}
```
nginxとgunicornを再起動します。
```
$ sudo systemctl restart nginx
$ sudo systemctl restart gunicorn
```
nginxがエラーで再起動できない場合は、以下のコマンドで原因を探ります。
```
$ sudo systemctl status nginx
```
ufwのポート80を開けます。
```
$ sudo ufw allow 80
```

## 確認
ブラウザで192.168.88.15と入力してアクセス。無事表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/802fa0ec-6872-de39-ac79-6d062f7b311d.png)
管理サイトの表示が崩れてしまっているので、今後設定ファイルを書き換えて直します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/17241f03-f589-f7db-68e5-f15dbb7573dc.png)

## さいごに
一旦連携して動かせるようになりました。次は、管理サイトとの表示の件もあるのでnginxの設定ファイルをもう少し書き換えて本番環境に近づけていきたいと思います。
【Rails】turbolinksが原因で、一度リロードしないとjsが反応しない

# はじめに
[【Rails】javascriptで入力フォーム(textarea)の高さを自動で変えたい](https://qiita.com/vaza__ta/items/4a8895889ed8da683845)
上記の記事で書いたものが、一度ページをリロードしないとjsが動かない（高さが変わらない）ことが起こった。
これを改善するために、turbolinksを修正していく。

# 環境
| No |    項目     |   内容    |
|---:|-------------|------------|
| 1  |      OS       |   Mac     |
| 2  |       Ruby      |   2.6.3   |
| 3  |       rails      |      6.0.4 |
| 4 |     turbolinks|      5.2.0 |
| 5  |      webpacker      |      4.0.7 |

# 実装
[【Rails】リロードしないとJavaScriptが動かない！【簡単に解決】](https://qiita.com/shibata0406/items/861df68467f3bee22a94)
[【Rails】初心者向け！画面遷移の高速化を行うTurbolinksについて図を用いて詳しく解説](https://techtechmedia.com/turbolinks-rails/)
同じ悩みを抱えてた記事があったため、参考にした。
どうも、turbolinksの使用で、jqueryが発火しなくなるみたいです。turbolinksをオフすることで、回避することにした。
```
...
<li><%= link_to "投稿", new_post_path, data: {"turbolinks" => false} %></li>
...
```
# おわりに
これでリンク飛ぶと早速jsが反応するようになった。
チュートリアル記事を丁寧に追った結果起こったHeroku Build failed "Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 255"

# はじめに
Docker によって Laravel 環境を構築し、Heroku にデプロイするこちらのチュートリアル記事

https://qiita.com/roughstorm/items/f9f86a7048c06c7d6544


を参考にして取り組んでいたところ、Heroku での自動デプロイに失敗しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916638/579bae00-8edf-f67f-a7d0-5b15e85c901b.png)

> Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 255

上記のエラーは View build log で出てくるログの最後の方にあるエラー文の抜粋です。


この記事では初学者なりに格闘した内容を書きます。

# 単刀直入に言うと
**PHP のバージョンが Heroku でサポートされているバージョンではなかった。**

冒頭のサイトでは php:7.2-fpm ですが、2022年8月14日現在 PHP 8 以上が推奨されていました。

こちらのサイトで PHP の対応バージョンが記載されています。
一次情報は大事。

https://devcenter.heroku.com/articles/php-support#php-runtimes

2022年8月14日現在
> Heroku’s PHP support extends to applications using the latest available releases in the **PHP 7.4, PHP 8.0** and **PHP 8.1** series.


> PHP 7.4 is in security-only maintenance mode and will be fully end-of-life at the end of 2022.

「PHP 7.4 は（中略）2022年末に完全にサポート終了」とのことで **PHP 8** を使うことが推奨されています。

## 現在の PHP バージョンの確認方法
docker-compose を使ってる方は現在の PHP バージョンは
```:powershell
$ docker-compose exec app php --version
```
で確認できます。

# PHP のバージョンを上げる方法

Dockerfile の記載を更新します。
```:Dockerfile
FROM php:8.0-fpm
```
そのあとコンテナを更新します。
```:powershell
$ docker-compose up -d --build
```

-d はバックグラウンドで実行するオプション。
--build はすでに同じ image が build されていても省略せずに build を強制するオプションです。

# 解決？
私が当エラーに当たったときはエラー文のコピペ検索でこちらに行きつき、PHPのバージョンアップを行う前にこのページの対応をしました。もしかしたら、PHPバージョンアップの後にこのページの処置が必要になるかもしれません。

https://stackoverflow.com/questions/50840960/script-php-artisan-packagediscover-handling-the-post-autoload-dump-event-retur


https://www.itsolutionstuff.com/post/solved-laravel-8-target-class-databaseseeder-does-not-existexample.html



# 経緯
ここからは私と同じ状況に陥った方が、よりこの記事にたどり着きやすくなるように私がエラーに陥った経緯を説明します。

冒頭で紹介した記事を上から丁寧に追っていった際、**デプロイ** で失敗していたことに気づかずに素通りし、

**APP_KEYの設定** の章で最初に躓きました。
```:powershell
$ heroku run php artisan key:generate --show -a <アプリ名>
$ heroku config:set APP_KEY='{ここに上記で生成されたAPP_KEY(base64から始まる文字列)をコピペ}' -a <アプリ名>
```
コマンドを実行しても、最初のコマンドで
> bash: php: command not found

のエラーが出ました。この時点で Heroku の Build が失敗しています。
しかし web 検索で「.env に書かれている内容をコピペする」という対症療法を見つけ、その場はクリアして**しまい**ました。

その次の**DBのマイグレーション・シーディング**でも

```:powershell
heroku run php artisan migrate --seed -a <アプリ名>
```

同様のエラーでどうしてもマイグレーションが行えず、さきほどの Stackoverflow などを試していました。

# まとめ
参考にする記事の古さの確認（界隈や分野によっては1年前の記事は全然古く感じないかもしれませんが）、1次情報を見ることの大切さ、バージョンの確認など基本のキを改めて叩きつけられたような思いです。少しでも同じような箇所でつまずいた方の力になれば幸いです。
Kotlin 基本構文

[kotlinのプライグラウンド](https://developer.android.com/training/kotlinplayground?hl=ja)を使って基本文法の学習

## Kotlinの変数

### よく使う変数の型の種類
| 型名 | 概要 |
|:-:|:-:|
| String | 文字列型 |
| Char | 文字型 |
| Int | 整数型 |
| Double | 浮動小数点型 |
| Boolean | 真偽型 |

### コレクション型

```kotlin
// Array型：List, Map, Set などのデータの集合を扱うインターフェースが用意されている
val 変数名 : Array< 型 > = arrayOf( 値, 値, 値 )
// List型　：順序のあるコレクション
val 変数名 : List< 型 > = listOf( 値, 値, 値 )

// Set型　 ：順序のないコレクション、重複する値は削除される
val 変数名 : Set< 型 > = setOf( 値, 値, 値 )
// Map型 　：辞書型、キーと値をセットで保持するコレクション
val 変数名 : Map< キーの型, 値の型 > = mapOf( key to value , key to value)
```

### オプショナル型(Optional)

nullの可能性があるなら`?`
nullでないことが保証されるなら`!!`
```kotlin
// OK
var text :String = null
// NG
var text: String? = null
```
![スクリーンショット 0004-08-15 1.39.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420303/8fe5942a-4b48-ae9b-29ee-1c79fe1f3d84.png)

## Kotlinの変数の宣言方法

```kotlin
val greeting:String = "Hello, world"
(定数宣言) (定数名):(型) = "定義する値"

var greeting:String = "Hello, world"
(変数宣言) (変数名) = "定義する値"...
```
![スクリーンショット 0004-08-15 2.01.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420303/e2f79138-96b7-6ceb-8f82-3d5ce2372aab.png)


## FizzBuzz問題
![スクリーンショット 0004-08-15 2.17.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420303/4bc55ec3-3717-1596-643c-5a268f0dab1e.png)

## 参考
[Kotlin入門](https://kotlin.keicode.com/lang/)
すぐに実行環境が整う仮想サーバー

# Amazon EC2
**Amazon Elastic Compute Cloud**(**Amazon EC2**)は、コンピューティングキャパシティを提供するサービス。要は、**サーバーに必要なもの一式をクラウドで借りられる。**
レンタルサーバーではサーバーマシンやサーバー機能を借りる一方で、
**クラウドの場合は、借りた道具を使って自分でサーバーを作るイメージ**。
ハードウェアの構成やOSの組み合わせを弾力的に選ぶことができ、構築が手軽。
**EC2は「アンマネージドサービス」**
サーバーやネットワークの運用はAWSが担当するが、
インストールするソフトウェア全ての運用は自分で行う。
# ボタン一つで最適なサーバーを作成できる
## 従来のサーバー構築
物理的マシンを用意し、OSやソフトのインストール、ネットワークやセキュリティの設定が必要
そのために、サーバー構築の知識がある技術者を手配する必要がある。
## EC2でのサーバー構築
サーバーを自分で作るといっても、マネジメントコンソールからボタンひとつで作成できるため、サーバーに関する技術的知識はあまり必要としない。**多種多様なサーバーマシンの組み合わせ**（インスタンスタイプ）**やOSのソフトウェアの組み合わせ**（AMI）**が用意されているのでそれを選択するだけ**。また、物理的マシンを必要とせず、初期投資を抑えられる。
## EC2でサーバーを作成するメリット
**誰でもすぐに使える**
* ボタン一つで作成できる→マネジメントコンソール
* 用意されたものを選ぶだけ→AMI、インスタンスタイプ
* あとで変更しやすいので、とりあえず始められる→マネジメントコンソール、インスタンスタイプ

**いろいろ選べる**
* CPUやメモリのスペックが色々用意されている→インスタンスタイプ
* OSやソフトウェアの種類が色々用意されている→AMI
* 連携させたい機能も充実→他のAWSサービス

**その他**
* バックアップが取りやすい→仮想化技術
* どこからでもアクセス→クラウド
* 物理的に異なる複数の場所に置くことができる→リージョンとアベイラビリティゾーン
# すぐに作れるすぐに壊せる
EC2は専門知識がなくても簡単にサーバーが作れ、１つずつイントールしないから手間も省ける。

**すぐに作れる・すぐに壊せることのメリット**
* 壊れた場合：同じサーバーを複製しやすいので、すぐに復帰できる
* 負荷が大きくなった場合：同じ構成のサーバーを複製し、負荷分散させやすい
* アクセスが減った場合：サーバーのスペックをスケールダウンさせ、コストを下げやすい
* 一時的に使いたい場合：開発時テストやキャンペーンサイトなどの一時的使用ができる
# マシンタイプやOSが選べる
EC2は選択の幅が広く、サーバーを作成するときは、サーバーマシンを**インスタンスタイプ**で選んで構成する。また、どんなOSを使い、ソフトウェアをインストールするのかは、**AMI**を使って決める。
* あらかじめインストールする内容を選べる
OS・ソフトウェアともにインストールされているもの
OSがインストールされた状態から、自分でソフトウェアをインストールし設定する
* マシンスペックを選択できる
高スペック
低スペック
* 周辺の組み合わせを選べる
EC2しか使わない
周辺技術もAWSも使う
GoのAPIGatewayでslackのslashコマンド発行時にリクエストを検証するサンプル


## 説明
- Bodyの中の`token`を使うこともできるが、非推奨とされている
- HMACを利用して自身のSlackから送信していることを検証できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/59702e7c-a77b-3dc2-5a1f-8ce7feb8f40e.png)


## イメージ
1. `v0:<X-Slack-Request-TimeStamp>:<body>`の文字列に対して、`Signin Secret`で復号する
1. 1の値を`X-Slack-Signature`を比較して一致しなければ、リクエストから落とす


## サンプル

```go
func CheckSlackSignature(request events.APIGatewayProxyRequest) error {
	slackVersion := "v0:"
	slackTimestamp := request.Headers["X-Slack-Request-Timestamp"]
	slackSignature := request.Headers["X-Slack-Signature"]
	slackBody := request.Body

	// Defend ReplayAttack
	now := time.Now()
	n, err := strconv.ParseInt(slackTimestamp, 10, 64)
	if err != nil {
		fmt.Printf("%d of type %T", n, n)
		return err
	}

	if (now.Unix() - n) > 60*5 {
		fmt.Println("replay attack")
		err = errors.New("replay attack error")
		return err
	}

	// Check Signature
	sigBasestring := slackVersion + slackTimestamp + ":" + slackBody
	secret := os.Getenv("SIGNINGSECRET")
	fmt.Println("sigBasestring : " + sigBasestring)
	fmt.Println("secret : " + secret)

	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(sigBasestring))
	sha := hex.EncodeToString(mac.Sum(nil))
	sha = "v0=" + sha

	log.Println("---------- check signature ----------")
	log.Println(sha)
	log.Println(slackSignature)
	if sha != slackSignature {
		fmt.Println("signature mismatch")
		err = errors.New("signature mismatch error")
		return err
	}
	return nil
}

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

	// Check Signature
	err := CheckSlackSignature(request)
	if err != nil {
		return events.APIGatewayProxyResponse{}, err
	}

	return events.APIGatewayProxyResponse{
		Body:       string(request.Body),
		StatusCode: 200,
	}, nil
}

func main() {
	lambda.Start(handler)
}

```


## 参考
- https://cipepser.hatenablog.com/entry/2017/05/27/100516
- https://sysrant.com/building-a-slack-slash-command-bot-with-golang-and-kubernetes/
- https://api.slack.com/authentication/verifying-requests-from-slack
CloudFront概念まとめ

CloudFrontを勉強してみたので各概念の関係性をまとめてみた
    主要概念は、Distribution、Behavior、Originの3つ。

```mermaid
classDiagram



class Distribution {
<<主要概念>>
+代替DomainName
+カスタムSSL証明書
}

class Behavior {
<<主要概念>>
+pathPattern

}

Distribution o-->"*" Behavior
Behavior -->"1" CachePolicy
Behavior -->"0..1" OriginRequestPolicy
OriginGroup --|> Origin
Behavior -->"1" Origin

Distribution o-->"*" Origin
Distribution -->"0..1" WAF


class CachePolicy {
+TTL設定
+キャッシュキー設定
}

class OriginRequestPolicy {
+headers
+queryStrings
+cookies
}

Origin <|-- CustomOrigin
Origin <|-- S3Origin

class Origin {
<<主要概念>>
+originDomain
+originPath
}

class CustomOrigin {
+protocol
}

class S3Origin {
+useOAI
}
S3Origin -->"0..1" OAI
```

* Distribution
    * CloudFrontのインスタンス。ここを起点に様々な設定をする
    * カスタムドメインとSSL証明書はDistributionに設定する
* Origin
    * CloudFrontから転送する先のサーバー。
    * S3に転送する場合は、OAIなどの専用の設定ができる
    * APIGatewayに転送する場合は、カスタムドメインとして汎用的な設定を適用する
    * 複数のOriginをまとめてOriginGroupを作ると、Originの代わりに使える
* Behavior
    * パスごとに、どのOriginに転送するかの設定
* CachePolicy
    * CloudFrontのキャッシュの振る舞いを決める
    * TTL(Time To Live): キャッシュの保持期間
    * キャッシュキー設定: 同じパスでもクエリーパラメータの値ごとにキャッシュを分けることもできる
    * 「Managed-CachingDisabled」など出来合いのものも用意されている
* OriginRequestPolicy
    * どのヘッダー、クエリーパラメータ、CookieをOriginに転送するか
    * 「Managed-CORS-S3Origin」など出来合いのものも用意されている。
Oreの定理の証明に関するメモ



北大 井上先生の[講義ノート](https://eprints.lib.hokudai.ac.jp/dspace/handle/2115/28239)を教科書としてグラフ理論を勉強中。

[Oreの定理](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%BC%E3%83%AC%E3%81%AE%E5%AE%9A%E7%90%86)の証明がよくわからなかったので調べていたところ、motchy氏のわかりやすい証明を見つけたのだが、一箇所難しいところがあったのでメモを残す。
https://motchy99.blog.fc2.com/blog-entry-40.html

> 然るに定理の仮定から$n(A)+n(B) \ge n$であるので$A$と$B$は共通部分を持つ,すなわち、**ある$i (0 \le i \le k-1)$が存在して$u_i$は$u_k$の隣接接点で、$u_{i+1}$は$u_0$の隣接接点である。**

(太字強調は筆者による)
に関しては、太字部分が仮に成立しないとすると、Bに含まれる点はAの点の隣には置けないので、$n(A)$個だけ候補となる点が減って、$n(B) \le k-n(A)$となる。一方で$n(A)+n(B) \ge n \ge k+1$より$n(B) \ge k-n(A)+1$であるから矛盾するため、太字部分は成り立つ。
開発用Macのセットアップ

## はじめに
開発用にM1のMacを買ったので、やるべきことをまとめました。
参考に筆者はwebエンジニアで、PHP、JavaScript、Node.js、Python等を使います。

## 実行環境
MacOs：M1チップ Monterey 12.4

## 本体設定
- OSアップデート
システム環境設定 → ソフトウェアアップデート
- Dockをカスタマイズ
よく使うアプリを設定し、いらないアプリを消す
- Dockの設定変更
  - システム環境設定
    - Dockとメニューバー
サイズ調整
拡大をチェックし、大きさ調整
「ウィンドウをアプリケーションアイコンにしまう」にチェック
「Dockを自動的に表示/非表示」にチェック
「最近使ったアプリケーションをDockに表示」のチェックを外す
- バッテリーの%表示
システム環境設定 → Dockとメニューバー → バッテリー → 割合を表示にチェック
- デフォルトのwebブラウザをGoogle Chromeに設定
システム環境設定 → 一般 → デフォルトのwebブラウザ

## 必須アプリケーションのインストール
### ブラウザ
- Google Chrome
https://www.google.com/intl/ja_jp/chrome/
以下の記事に拡張機能をまとめました。
https://qiita.com/shott/items/c804bcc27d153900c624

### ターミナル
- iTerm2
https://iterm2.com/
- warp
https://www.warp.dev/

### エディタ
エディタは便利な拡張機能が豊富にあり、カスタマイズ性が十分にあるVSCode一択です。
- VSCode
https://code.visualstudio.com/download
拡張機能は以下の記事にまとめました。
https://qiita.com/shott/items/92f68e8ab050d99fc749

### チャットツール
クライアントやチームメンバーによって使い分けるため、複数インストールします。
- Slack
https://slack.com/intl/ja-jp/downloads/mac
- Discord
https://discord.com/download
- ChatWork
https://go.chatwork.com/ja/download/

### web会議ツール
クライアントやチームメンバーによって使い分けるため、複数インストールします。
- zoom
https://zoom.us/download
- Microsoft Teams
https://www.microsoft.com/ja-jp/microsoft-teams/download-app
- Google Meet
https://meet.google.com/

### SQLクライアント
- TablePlus
https://tableplus.com/

### FTPクライアント
- FileZilla
https://filezilla.jp.uptodown.com/mac

### パッケージマネージャ
- Homebrew
Macのパッケージ管理ツールで、コマンド一つでパッケージを管理できます。
Macで開発するには必須のツールです。
https://brew.sh/index_ja

### その他
- Postman
APIのレスポンスを確認するアプリケーションです。
https://www.postman.com/
- Docker Desktop
今やローカルの開発環境に必須だと思われます。
https://www.docker.com/products/docker-desktop/

## Homebrewでパッケージをインストール
- git
デフォルトでApple gitがインストールされていますが、Homebrewで新しくインストールします。
手順は以下の記事に記載しました。
https://qiita.com/shott/items/ec9d8fe95cae1d9eb9d8
- Node.js
複数バージョンが管理できるので、nodebrewを用いてインストールします。
- Python
複数バージョンが管理できるので、pyenvを用いてインストールします。


## おわりに
基本的には個人的なメモですが、誰かの参考になれば幸いです。
ディレクトリをgitの管理下に置いてブランチを作成するまでの流れ

　Gitで管理していないディレクトリを`git init`でGitの管理下に置く場合、最初にコミットをしておかないとブランチが作成できない。ただコミットする中身はまだないので、空のコミットを行う。空のコミットというのは、ステージに何も変更がないのにコミットをするということ。そのような状態では通常コミットは出来ないけど、`--allow-empty`をつければ出来る。

``` bash
# ディレクトリを作成
$ mkdir git-practice

# 作成したディレクトリに移動
$ cd git-practice/

# まだ.gitはない
$ ls -a
./  ../

# ディレクトリをGitの管理下に置く
$ git init
Initialized empty Git repository in hoge/git-practice/.git/

# .gitが出来ている
$ ls -a
./  ../  .git/

# 何も表示されない
$ git branch

# ブランチの作成に失敗してしまう
$ git branch sample
fatal: Not a valid object name: 'master'.

# --allow-emptyなしでコミットしようとしても出来ない
$ git commit -m"init"
On branch sample
nothing to commit, working tree clean

# 空のコミットをする
$ git commit --allow-empty -m"init"
[master (root-commit) abc125d] init

# コミットが履歴に追加されている(結果は割愛)
$ git log

# ブランチの一覧が見られるようになった
$ git branch
* master

# sampleブランチを作成
$ git branch sample

# 一覧に追加されてる
$ git branch
* master
  sample

# ブランチをsampleに切り替え
$ git checkout sample
Switched to branch 'sample'
```
【Unity】オブジェクトを初期位置・初期回転に戻す

### オブジェクトを初期位置・初期回転に戻す
少しうっかりしていてハマってしまったので戒めとして。
以下のようにTransformコンポーネントを取得しておくことでオブジェクトの位置・回転の初期化を実装しようとしていた。

```C#
private Transform _initialTransform;

void Start()
{
    // 初期位置の取得（のつもり）
    _initialTransform = gameObject.transform;
}

// 初期化関数
public void Reset()
{
    gameObject.transform.position = _initialTransform.position; // 位置の初期化（のつもり）
    gameObject.transform.rotation = _initialTransform.rotation; // 回転の初期化（のつもり）
}
```

これだとTransformコンポーネントを取得しておいたに過ぎないので、そのPositionやRotationの値は随時変化してしまう。
正しく初期化を行うには以下のようにPositionとRotationの初期値をそれぞれ別々に取得しておき、その値を使って初期化する。

```C#
private Vector3 _initialPosition; // 初期位置
private Quaternion _initialRotation; // 初期回転

void Start()
{
    // 初期位置・初期回転の取得
    _initialPosition = gameObject.transform.position; 
    _initialRotation = gameObject.transform.rotation; 
}

// 初期化関数
public void Reset()
{
    gameObject.transform.position = _initialPosition; // 位置の初期化
    gameObject.transform.rotation = _initialRotation; // 回転の初期化
}
```