OmniAICreator/Qiita-1.07M huggingface dataset:
Index signature for type 'string' is missing in type 'XXXX' を即座に解決する

## 結論

- `Index signature for type 'string' is missing in type 'XXXX'` が出たということは、エラーメッセージの文面通り、実際その型にはインデックスシグネチャが定義されていないはずだよ
- **だから、ないなら定義してやればいい**

## もっと詳しく

このエラーメッセージが出たということは、このページに来た人は多分次のようなコードを書いていると思う。インデックスシグネチャ `[key: string]: string;` を定義した型を、何らかのFunctionの引数にしているはずだ。きっとその引数に、何らかのinterfaceを指定しているよね。

```ts
interface DictionaryType {
  [key: string]: string;
};

function logDictionary(dictionary: DictionaryType) {
  console.log(dictionary);
}

interface User {
  name: string;
};

const user001: User = {
  name: "user001",
};

// ---- エラー発生！ ----
// Argument of type 'User' is not assignable to parameter of type 'DictionaryType'.
// Index signature for type 'string' is missing in type 'User'.ts(2345)
logDictionary(user001);
```

このコードだと、logDictionaryの引数 `user001` のところにエラーが出ると思う。エラーの内容は文面そのまま、「この引数にはインデックスシグネチャがないよ！」という意味。

一見するとインデックスシグネチャ `[key: string]: string;` に `name: string;` は違反していないのだから、問題ないはずだって思うかもしれないけど、怒られているポイントはそこじゃない。

あくまで「インデックスシグネチャがないよ！」って言われているのだから、素直にその言葉に従おう。

で、そのインデックスシグネチャの追加方法は２つある。

### インデックスシグネチャの追加方法1. 普通に自分で書く

一つは当然ながら、言われた通りインデックスシグネチャを明示的に追加してやることだ。特別なことは何もない。ただただエラーが出た型 `interface User` を次のように書き換えてやればいい。

```ts
interface User {
  name: string;
  [key: string]: string;
}
```

これでエラーは消える。

でも、これじゃちょっと冗長な感じするよね。それなら次のやり方で書けばいい。

### インデックスシグネチャの追加方法2. interfaceではなく型エイリアス（type）を使う

```ts
type User = {
  name: string;
}
````

これだけでいい。

**「え、これのどこがインデックスシグネチャを追加してるの？？」** って思うかもしれないけど、実は型エイリアス（type）には、「暗黙的なインデックスシグネチャ」が備わっている。だからこれだけでインデックスシグネチャが付与されて、冒頭のエラーが解消されるんだ。

## そのほかのアプローチ

型の修正ではなく、値の取り扱いを変えるだけでもこのエラーを解消できる。

具体的にはスプレット構文で一度別のオブジェクトに展開してやることで、元々の `interface User` としての制約から解き放たれていて、そのためにエラーが解消されるわけだね。

```ts
interface DictionaryType {
  [key: string]: string;
};

function logDictionary(dictionary: DictionaryType) {
  console.log(dictionary);
}

interface User {
  name: string;
};

const user001: User = {
  name: "user001",
};

logDictionary({ ...user001 });
```

## まとめ

`Index signature for type 'string' is missing in type 'XXXX'` が出たなら、次のいずれかでエラーを解消できる。

- エラーになった値のinterfaceに明示的にインデックスシグネチャを追加する
- エラーになった値のinterfaceを型エイリアス（type）に変える
- エラーになった値をスプレッド構文で展開して新たなオブジェクトにしてやる

## おまけ
この件に関しては microsoft/TypeScript のIssue上で過去に議論が白熱したみたい。もっと詳しく知りたい人は、読んでみてね！

https://github.com/microsoft/TypeScript/issues/15300
HTMLだけでinputのrangeの横にnumber入力欄を作る

# 今までやっていたこと
JavaScriptを使ってinputのchangeイベントなどを使い変更時にnumberの値を変更していた
### HTML
```
<input type="range" id="range">
<input type="number" id="number">
```
### JavaScript
```
const range = document.getElementById('range');
const number = document.getElementById('number');

range.addEventListener('change', event => {
  number.value = range.value;
})

number.addEventListener('change', event => {
  range.value = number.value;
})
```

# これからは
formの中身で同期させる
こんな事ができるなんて知らなかった
### HTML
```
<form>
  <input type="range" name="range" min="0" max="100" value="0" oninput="this.form.input.value=this.value">
  <input type="number" name="input" min="0" max="100" value="0" oninput="this.form.range.value=this.value">
</form>
```
# 最後に
初投稿です！
文が全体的に短くなってしまいました
すみません
VimExcelのダウンロード方法

## VimExcelのダウンロード方法
1. VimExcelダウンロードページにアクセスする
https://www.vector.co.jp/soft/winnt/business/se494158.html
2. 「ダウンロードはこちら」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/b4293e67-4dce-5b84-4a48-bfdb08d4db15.png)
3. 「ダウンロードページへ」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/32ba8511-0257-ef81-f0f9-d9738ddd441e.png)
4. 「このソフトを今すぐダウンロード」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/4022ddbd-e590-7c08-ebef-ed5e9c1dba97.png)
5. ダウンロードしたzipファイルを解凍する
6. 解凍したファイルのうち、VimExcel_X.X.X.xlaを下記フォルダに配置する
C:\Users\(あなたのユーザ名)\AppData\Roaming\Microsoft\AddIns
7. ExcelのクイックアクセスツールバーにAdd-insを追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/ea729ca1-b75b-04f7-7a73-8c6f39775f6d.png)
8. クイックアクセスツールバーの歯車のアイコン(Add-ins)をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/e4048bb5-922f-d5c3-5662-4c6df87503e2.png)
9. BrowseでVimExcel_X.X.X.xlaを選択し、[OK]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/9e289179-37f2-350a-e212-e2bfc1e44be1.png)
10. VimExcel_X.X.X.xlaの左側のチェックボックスにチェックが入っていることを確認し、[OK]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/4e04fafd-d23c-eb77-62ce-b3f400be4cae.png)
11. VimExcelが稼働するので、"?"を入力すると下記のようなヘルプが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858605/fdf45404-69f5-3a2b-54b8-d1aa9819d0e5.png)
12. 表示されたヘルプを"Esc"で非表示にする
13. h、j、k、l等入力し、ちゃんとカーソルが動くことを確認する
14. 先にダウンロードした「VimExcel_Introduction_X.X.X.pptx」を参照しながら、自分のやりたいようにやる
15. VimExcelを無効化したい場合には、"Ctrl+m"を押せば、無効化される。
15. 再度VimExcelを起動したい場合にも、"Ctrl+m"を押せばよい
16. あとは、自分の好きなように遊ぶ
Java Gold 例題 ZonedDateTime

```java
import java.time.Duration;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Test {
	public static void main(String[] args) {

		ZoneId tz = ZoneId.of("Asia/Tokyo");
		ZoneId lz = ZoneId.of("America/Los_Angeles");
		
		ZonedDateTime t = ZonedDateTime.of(
				2024, 8, 14,12, 0, 0, 0, tz);
		
		Duration d = Duration.ofHours(10).plusMinutes(20);
		ZonedDateTime at = t.plus(d).withZoneSameInstant(lz);
		
		System.out.println(t);
		System.out.println(at);
	}
}
```
本コードの目的として適切な選択肢は次のうちどれでしょうか。
1つ選んでください。

1. 東京とロサンゼルスの時差を求めたい
1. ロサンゼルスから東京に行った場合の東京の現地時間を知りたい
1. 東京からロサンゼルスに行った場合のロサンゼルスの現地時間を知りたい
1. 東京とロサンゼルスの現地時間を表示したい
1. 東京およびロサンゼルスとの時差が10時間+-20分の地域を調べたい

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

3

「東京からロサンゼルスに行った場合のロサンゼルスの現地時間を知りたい」という目的が適切です。



```java
ZoneId tz = ZoneId.of("Asia/Tokyo");
ZonedDateTime t = ZonedDateTime.of(2024, 8, 14,12, 0, 0, 0, tz);
```

東京時間（Asia/Tokyo）で2024年8月14日12:00に出発する時間を設定しています。

```java
Duration d = Duration.ofHours(10).plusMinutes(20);
```
その後、移動時間として10時間20分を追加しています。
```java
ZonedDateTime at = t.plus(d).withZoneSameInstant(lz);
```
`withZoneSameInstant(lz)`を使って、ロサンゼルス時間（America/Los_Angeles）に変換しています。
これにより、東京からロサンゼルスに移動した場合のロサンゼルスでの現地時間が求められます。


補足

`t`、`d`などの変数名を修正した場合の例
```java
public class FlightArrivalTimeTest {
	public static void main(String[] args) {

		ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");
		ZoneId laZone = ZoneId.of("America/Los_Angeles");
		
		ZonedDateTime departureTime = 
                ZonedDateTime.of(2024, 8, 14,12, 0, 0, 0, tokyoZone);
		
		Duration flightDuration = Duration.ofHours(10).plusMinutes(20);
		
		ZonedDateTime arrivalTimeInLA = departureTime.plus(flightDuration)
                                                     .withZoneSameInstant(laZone);
		System.out.println(departureTime);
		System.out.println(arrivalTimeInLA);
	}
}
```
結果
```
2024-08-14T12:00+09:00[Asia/Tokyo]
2024-08-14T06:20-07:00[America/Los_Angeles]
```

  
Document
[ZoneId](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/time/ZoneId.html)
[ZoneId.of](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/time/ZoneId.html#of(java.lang.String))
[ZonedDateTime](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/time/ZonedDateTime.html)
[ZonedDateTime.of](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/time/ZonedDateTime.html#of(int,int,int,int,int,int,int,java.time.ZoneId))
[Duration](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/time/Duration.html)
[withZoneSameInstant](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/time/ZonedDateTime.html#withZoneSameInstant(java.time.ZoneId))


https://qiita.com/T-ngtj/private/df254aacd05be698199a
ベラルーシ語品詞付与・係り受け解析モデルdeberta-base-belarusian-uposリリース

[UD_Belarusian-HSE](https://github.com/UniversalDependencies/UD_Belarusian-HSE)を使って、ベラルーシ語品詞付与・係り受け解析モデル[deberta-base-belarusian-upos](https://huggingface.co/KoichiYasuoka/deberta-base-belarusian-upos)を試作してみた。UD_Belarusian-HSEには「ZERO WIDTH SPACE」(U+200B)が[ヤタラメッタラ紛れ込んでいる](https://github.com/UniversalDependencies/docs/issues/1010)、という罠があって、正直、トークナイザ泣かせだったりする。でも、ベラルーシ語のUniversal DependenciesコーパスはUD_Belarusian-HSEしかないので、まあ、これで頑張るしかないわけだ。Google Colaboratoryで動かしてみよう。

```
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/deberta-base-belarusian-upos")
doc=nlp("Цяпер мора яшчэ можа быць навідавоку")
import deplacy
deplacy.serve(doc,port=None)
```

「Цяпер мора яшчэ можа быць навідавоку」を係り受け解析してみたところ、私(安岡孝一)の手元では以下の結果が出力された。

```
1	Цяпер	_	ADV	_	Degree=Pos	4	advmod	_	_
2	мора	_	NOUN	_	Animacy=Inan|Case=Nom|Gender=Neut|Number=Sing	4	nsubj	_	_
3	яшчэ	_	ADV	_	Degree=Pos	4	advmod	_	_
4	можа	_	VERB	_	Aspect=Imp|Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin|Voice=Act	0	root	_	_
5	быць	_	VERB	_	Aspect=Imp|Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin|Voice=Mid	6	cop	_	_
6	навідавоку	_	ADV	_	Degree=Pos	4	xcomp	_	SpaceAfter=No
```

![be.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/29ab8259-3ca6-e252-1d95-debc343e840a.png)

うーん、「быць」がcopだとすると、品詞はVERBよりAUXの方が適切な気がする。さて、[対応するオック語の例文](https://qiita.com/KoichiYasuoka/items/679bf7516d5e5988940b)でも、copとVERBの関係が問題になっていたし、むしろesuparそのものを、少し改造した方がいいのかな。
(ベンチマーク)Arduino UNOで素数を求める3...100まで


x 理系フリマ831にあるよ
 
目的
素数を求めて時間を測って遊ぶ
2から開始しする
割るのは、2からn-1まで割る
ちゃんと割ってあまりを求める
z = x / y
a = x - ( z * y )

いろいろ
速いのか遅いのかようわからん


結果

![o_coq315.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/56814371-7362-3f31-8ce5-2880c53ab816.jpeg)




プログラム

```c++

void setup() {

  Serial.begin(9600);

}//setup

void loop() {

  int s[100];
  for (int ii = 0; ii < 100; ii++) {
    s[ii] = 0;
  }//for

  unsigned long time;

  int a=1;//work

  int pp = 0;
  //s[pp++] = 1;//debug
  //s[pp++] = 2;//debug
  Serial.println("START>>");
  time = millis();

  for (int ii = 2; ii < (100 + 1); ii++) {

    //Serial.print('(');  //debug
    //Serial.print(ii);   //debug
    //Serial.print(')');  //debug
    //Serial.println();   //debug

    for (int jj = 2; jj < (ii); jj++) {

      //Serial.print('['); //debug
      //Serial.print(jj);  //debug
      //Serial.print(']'); //debug

      a = ii / jj;
      a = ii - (a * jj);
      if ( a == 0) {
        //Serial.print('*');//debug
        break;
      }//if

    }//for
    if (a != 0) {
      //Serial.print('@');
      s[pp++] = ii;
    }
    //Serial.println();//debug
  }//for

  time = millis() - time;
  Serial.print("millis=");
  Serial.println((int)time);

  int yy = 0;
  while (s[yy] != 0) {
    Serial.print(s[yy]);
    Serial.print(',');
    yy++;
  }//while
  Serial.println();

  Serial.println("<<END");
  delay(3000);
  //while (1) {} //debug
}//loop


```
Self-hosted GitHub Actions runners in AWS CodeBuild

Actions について。

https://aws.amazon.com/jp/about-aws/whats-new/2024/04/aws-codebuild-managed-github-action-runners/

https://aws.amazon.com/jp/blogs/devops/aws-codebuild-managed-self-hosted-github-action-runners/

CodeBuild がサポート開始したということで試す。

Trigger の設定が機能するのかが確認したいポイント。filter で build の起動を制御したい。

## tl;dr

- filter の動きは検証中。正常に動いている場合と、怪しい場合がある。要経過観察。
- その他の Actions 自体の動作に違和感はない。

## CodeBuild との連携

### Workflow

- `runs-on` [^4] の設定変更が必要。
    - `myProject` の部分に build project name を設定する。Actions と連携する build project であることを認識させる。
    - これが間違っていると、GitHub 側の Webhook が失敗する。

```yaml
name: Hello World
on: [push]
jobs:
  Hello-World-Job:
    runs-on: codebuild-myProject-${{ github.run_id }}-${{ github.run_attempt }}    # Add
    steps:
      - run: echo "Hello World!"
```

### プッシュが特定のファイルに影響を与える場合にのみワークフローを実行する [^3]

- Actions の実行履歴を見る限り、 `paths` filter に指定しているものに反応している。
- `branches` filter を追加して様子を見る。

### Console

- `WORKFLOW_JOB_QUEUED` を選択する。

![webhook event](/images/d44d9a52d7fc32-a.png)

## Conclusion

9連休に突入した。

会社の有給取得義務を満たすためやむを得ず。

暇なので、休み中に読める本を探している。最近これといって読みたい本が無い。

「テスト自動化実践ガイド」に興味があるが、買う前に中身に少し目を通したい気持ちもある。

https://www.shoeisha.co.jp/book/detail/9784798172354

「ドメイン駆動設計をはじめよう」にも興味がある。こちらは、意訳が強すぎて、 DDD ではなく別物になっているという話を聞く。

https://www.oreilly.co.jp/books/9784814400737/

8月末に数冊、興味のあるタイトルが発売されるため、それを待てという話ではある。

[^3]: https://docs.github.com/ja/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#running-your-workflow-only-when-a-push-affects-specific-files
[^4]: https://docs.github.com/ja/actions/writing-workflows/choosing-where-your-workflow-runs/choosing-the-runner-for-a-job
Vite×ReactのビルドをDockerで行ったときに出たエラー

前提
フロントとバックエンドのプロジェクトに分割したモノレポのアプリの開発中、Dockerを起動したところ下記のエラーが出た。

```
ront-1  | yarn run v1.22.22
front-1  | $ vite
front-1  | /myapp/node_modules/rollup/dist/native.js:59
front-1  |              throw new Error(
front-1  |                    ^
front-1  | 
front-1  | Error: Cannot find module @rollup/rollup-linux-arm64-gnu.
```

`@rollup/rollup-linux-arm64-gnu`というモジュールが見つからないとのことで、ローカルで依存関係を再インストールしてみたが解消されず。
そもそもpackage.jsonにはこんなモジュールを入れた覚えはなく調べたところ、Viteの依存関係として入ってくるようだった。

LinuxのARM64アーキテクチャに依存するモジュールで、Docker環境がARM64アーキテクチャで動作しているため必要になるらしい。

下記のコマンドで、フロントエンドのコンテナに依存関係をインストールしたら解消された。
```
docker-compose run --rm front yarn install
```

下記ページで他の方法も紹介されています。

https://github.com/vitejs/vite/discussions/15532
pythonでgnuradio その11

# 概要
pythonでgnuradioやってみた。
windows10,windows11に開発環境構築してみた。

# 環境
windows10
windows11

# 手順

- radioconda-2024.05.29-Windows-x86_64.exeをダウンロード

- 実行する。

- radioconda Promptを開く

```
>mkdir python

>cd python
```

- test1.pyを書く

```
#!/usr/bin/env Python3
from gnuradio import gr
from gnuradio import audio
from gnuradio import analog

class my_top_block(gr.top_block):
	def __init__(self):
		gr.top_block.__init__(self)
		sample_rate = 32000
		ampl = 0.1
		src0 = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, 350, ampl)
		src1 = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, 440, ampl)
		dst = audio.sink(sample_rate, "")
		self.connect(src0, (dst, 0))
		self.connect(src1, (dst, 1))

if __name__ == '__main__':
	try:
		my_top_block().run()
	except [[KeyboardInterrupt]]:
		pass

```

- 実行する。

```
>python test1.py

```

以上。
【Javascript】Number型とBigint型の違いを図解で説明する

# はじめに

先日、Javascriptの勉強をしている中で、Number型とBigint型の違いについて学びがあったので、本記事にて共有します。

# Number型とBigint型

Javascriptにて、数値を返却する型として「数値型(Number型)」と「長整数型(Bigint型)」があります。これらの違いや用途について下記で説明します。

### 2つの型の違い

Number型とBigint型の違いは下記の通りです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/26f98082-adce-b813-23bc-cc1063842c30.png" width="500">

上図のように、安全な整数範囲を超えた時の計算結果によって、違いが生じます。

ここで安全な整数範囲とは、**計算が正常に行われる整数の範囲**を表し、最大値が`Number.MAX_SAFE_INTEGER`、最小値が`Number.MIN_SAFE_INTEGER`でそれぞれ表現できます。

```js
// 安全な整数範囲
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991

// Number型の計算
console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992
console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992 ← 正しく計算が行われない

// Bigint型の計算
console.log(BigInt(Number.MAX_SAFE_INTEGER) + 1n); // 9007199254740992n
console.log(BigInt(Number.MAX_SAFE_INTEGER) + 2n); // 9007199254740993n ← 正しく計算が行われる
```

まず、安全な整数範囲は`-9007199254740991〜9007199254740991`までの範囲となり、これは`-(2^53-1)〜(2^53-1)`の範囲となります。
この範囲を超える計算結果になった場合、Number型では正しく計算が行われず、BigInt型では、正しく計算が行われるようになります。また、BigInt型で計算を行う場合は、`BigInt(数値)`もしくは`数値n`とすることで表現可能です。

なぜ`2^53`という数字を用いるかは詳しく解説している記事を見つけましたので、[こちら](https://qiita.com/maiyama18/items/9956bdc3464b7520e04a)をご覧ください。

### それぞれどんな時に使うのか？

Number型とBigInt型では一般的に下記のように使い分けるようにすると良いとされています。

|型の種類|用途|
|:-:|:-:|
|Number型|&#124;`2^53`&#124;を超えない値を用いる|
|BigInt型|&#124;`2^53`&#124;を超えうる値を用いる|

というのも、BigInt型はメモリを多く消費するため、比較的小さめの値を使う場合、Number型を使う方が良さそうです。
【Unity】スコアをリアルタイムに変更してTextMeshProで表示する方法

## まえがき
スコアなど、ゲーム中に値が変動する数字をUIのTextMeshProで表示する方法について説明していきます。

## Textの用意
UI → TextMeshProを作成して下さい。今回は **Score Text** という名前にしておきます。

※プロジェクト内で初めて作成する場合は、TextMeshProを作成すると表示されるタブからTextMeshProをImportして下さい。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333835383133342f65333330363530312d396132342d653862332d656432342d6635653463346563393165372e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/0c607321-7f79-4c83-ffa8-ed0d2fa3375a.png)

:::note info
Assetsフォルダ内にTextMesh Proというフォルダが生成されます。
:::

## Scriptの用意

Assetsフォルダ内に **Score Manager**という名前のScriptを作成して下さい。
続いて、内容を以下のコードに書き換えて下さい。

<details open><summary>Score Manager</summary>



```c#
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class ScoreManager : MonoBehaviour
{
    public int score = 0;
    private TMP_Text scoreText;
    // Start is called before the first frame update
    void Start()
    {
        score = 0;
        scoreText = GetComponent<TMP_Text>();
        scoreText.text = "score:0";
    }

    // Update is called once per frame
    void Update()
    {
        scoreText.text = "score:" + score.ToString();
    }
}

```
</details>

このScriptを先ほど作成したTextMeshProにアタッチして下さい。

## スコアの変更方法
今回はスコアを **GameManager** というScriptから変更できるようにします。(任意のScriptからスコアを変更することが可能です。)

<details open><summary>サンプルコード（open属性あり）</summary>



```c#
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Assertions.Must;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    private GameObject scoreText;
    // Start is called before the first frame update
    void Start()
    {
        scoreText = GameObject.Find("ScoreText");
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            scoreText.GetComponent<ScoreManager>().score++;
        }
    }
}
```
</details>

scoreText変数にTextMeshProのゲームオブジェクトを割り当て、スペースキーが押されたらscoreTextにアタッチされているScoreManagerというScript内のscore変数をインクリメントするという処理のコードです。

よって、実際に使う場合はスコアを増やしたい場所にscoreText.GetComponent<ScoreManager>().score++;という文を挿入しましょう。

:::note warn
scoreText = GameObject.Find("ScoreText")の部分ではScoreTextという名前のゲームオブジェクトを探してscoreText変数に割り当てているので、作成したTextMeshProの名前と一致させる必要があります。
:::

以上で実装は終了です。実際にPlayしてスコアが変更されてUIに反映されていることを確認して下さい。

## あとがき
スコアの実装はゲーム開発でよく行うことなので、慣れておくと良いと思います。
Javaで「先読みと後読みを使ったパターンの記述」の動作を確認してみた

# 概要

Javaで「先読みと後読みを使ったパターンの記述」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/regex/index15.html

# 実装

以下のファイルを作成しました。
```JSample15_1.java
import java.util.regex.*;

class JSample15_1{
  public static void main(String[] args){
    String regex = "smart(?=phone)";
    Pattern p = Pattern.compile(regex);

    String[] target = {"smart", "smartphone", "smartwatch"};

    for (int i = 0; i < target.length ; i++){
      Matcher m = p.matcher(target[i]);
      System.out.print(target[i] + "は");
      if (m.find()){
        System.out.println("マッチしました");
        System.out.println("マッチしたのは " + m.group() + " です");
      }else{
        System.out.println("マッチしませんでした");
      }
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample15_1.java 
$ java JSample15_1 
smartはマッチしませんでした
smartphoneはマッチしました
マッチしたのは smart です
smartwatchはマッチしませんでした
```

# まとめ

何かの役に立てばと。
【Unity】背景をループして動かす方法(2D)

## まえがき
強制スクロールゲームなどを作る際、一定の速さで背景を動かしたいですよね。
ということで実装方法について説明していきます。

## 実装方法

### Canvasの用意
まず、**UI → Image**を作成して下さい。
次に、Imageの親であるCanvasを設定していきます。

Inspectorから、Render Modeを **Screen Space - Camera**に変更し、Render Cameraに **Main Camera** をアタッチしてください。

![スクリーンショット 2024-08-15 031536.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/fd1b63ba-17c4-3ebb-8800-8c899861eb33.png)


また、Order in Layerには背景が一番奥に表示されるような値を設定すれば大丈夫です。

### 背景画像の用意

背景画像を用意し、Assetsフォルダに移動します。

続いて、InspectorからWrap Modeを**Repeat**に変更して下さい。

![スクリーンショット 2024-08-15 031508.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/1efc3241-e69c-7420-fe93-8ea7aaa35e89.png)

### マテリアルの作成

プロジェクトタブで右クリックして、**Creat → Material**でマテリアルを作成して下さい。

続いて、InspectorからShaderを **Unit → Transparent** に変更して下さい。

![スクリーンショット 2024-08-15 032137.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/36d87668-ea5a-d236-d055-e49713f5e37e.png)

### Imageの設定

先ほど作成したImageのInspectorから設定を行います。
Source Imageに設定したい背景画像を、Materialに先ほど作成したマテリアルをアタッチして下さい。

![スクリーンショット 2024-08-15 032625.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/c45f3afb-ad3d-2ea2-6d00-40f97d30956e.png)

### スクリプトの作成

Assetsフォルダ内に**BackGroundMover**という名前のScriptを作成し、以下のコードを貼り付けて下さい。

<details open><summary>BackGroundMover</summary>



```c#
using UnityEngine;
using UnityEngine.UI;

public class BackGroundMover : MonoBehaviour
{
	private const float k_maxLength = 1f;
	private const string k_propName = "_MainTex";

	[SerializeField]
	private Vector2 m_offsetSpeed;

	private Material m_material;
	
	private void Start()
	{
		if (GetComponent<Image>() is Image i)
		{
			m_material = i.material;
		}
	}

	private void Update()
	{
		if (m_material)
		{
			var x = Mathf.Repeat(Time.time * m_offsetSpeed.x, k_maxLength);
			var y = Mathf.Repeat(Time.time * m_offsetSpeed.y, k_maxLength);
			var offset = new Vector2(x, y);
			m_material.SetTextureOffset(k_propName, offset);
		}
	}

	private void OnDestroy()
	{
		if (m_material)
		{
			m_material.SetTextureOffset(k_propName, Vector2.zero);
		}
	}
}
```
</details>

:::note warn
コード4行目の public class BackGroundMover : MonoBehaviour の BackGroundMoverの部分がScript名と一致している必要があります。
:::

このScriptをImageにアタッチして下さい。

背景素材の大きさをSceneから調整し、ImageのInspectorからScript内変数のOffset Speedで背景が動く速さを調整してPlayしてみると、背景がループして動くことが確認できます。

なお、Offset Speedを(X,Y)=(1,0)とした場合、背景画像をx軸正方向に1秒で1ループするようになり、Yについても同様です。

## あとがき
シューティングゲームなどは、自機を移動させなくても背景や他のオブジェクトを移動させるだけでスクロールを表現できます。上手く背景のループ移動を活用しましょう！
Firebase hostingでデプロイ時に画面が真っ白になった/Expected a JavaScript module script but the server responded with a MIME type of "text/jsx".

# はじめに
Firebase hostingで学習用アプリをデプロイしてます
gitHub acrionsを利用してCI/CDを行っているのですが
deployが失敗したので以下の記事を参考に解消しました
https://qiita.com/AK_React/items/05957ddc311d3bc14c28
しかし、私の環境だと、デプロイ自体は完了できても、画面が真っ白になってしまったのでまとめます

# 問題
deployは成功しているの、画面が真っ白
consoleを見ると
```
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/jsx". Strict MIME type checking is enforced for module scripts per HTML spec.Understand this error
```
とのこと
どうやら本来jsxファイルをjsに変換してデプロイしなければいけないところを、jsxのままデプロイしてしまったいる模様
検証ツールのネットワークタブでgetしてるファイルを見ると・・・「main.jsx」君、君が犯人だね
![スクリーンショット 2024-08-15 1.21.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2545942/1c32f6a5-8370-991c-e4a1-d5b6ebe4e455.png)
上にリンクを貼っている記事での対応のように、デプロイする対象を変更したため、余計なファイルまでデプロイしてしまっていそう
やはり、デプロイする対象はbuildで生成されたdistファイルを対象にした方がよさそう

# 解決方法
そもそも、github actionsでbuildしたはずのdistファイルが無いと怒られてたかといえば
buildのjobとdeployのjobが違うために、このjob間で生成物の共有がなされていないためでした
共有するためのやつ、ありました
https://docs.github.com/ja/actions/writing-workflows/choosing-what-your-workflow-does/storing-workflow-data-as-artifacts
上記を参考に
buildのjobで生成されたdistファイルをアップロード
そしてそのアップロードされたファイルをdeployのjobでダウンロード
これでbuildされたdistファイルをデプロイできます
```yml
jobs:
  build:
    steps:
    （略）
    - name: Upload dist
      uses: actions/upload-artifact@v3
      with:
        name: dist
        path: dist

  deploy:
    steps:
    （略）
    - name: Download all artifact
      uses: actions/download-artifact@v3
      # ダウンロード対象を指定しない場合、すべてダウンロードする
```
ちなみに、buildからdeployを同じjobで書けばこの工程を省いてもいけるみたいです

# おわりに
github actionsのエラーで困っている時に、エラー記事通りにしてエラー解消したので
肝心のデプロイ後のページ確認を怠っており、後から気づきました
最終的なページがうまく表示できているか、絶対忘れてはいけないポイントですね
OpenGLでMesh Shaderを使ってみる

インターネットに転がっているMesh ShaderのサンプルはDirectX 12やVulkanが多いが、実はOpenGLでも特定環境ではMesh Shaderが使える。簡単なサンプルとしてMesh Shaderを用いた三角形の描画を行う。

# 描画コマンド
[NV_mesh_shader拡張](https://registry.khronos.org/OpenGL/extensions/NV/NV_mesh_shader.txt)を利用する。NVIDIAのTuring以降のGPUであれば使えるはず。

描画コマンドはCompute ShaderのDispatchに似ており、WorkGroupの数を指定する。
``` c++
void DrawMeshTasksNV( uint first, uint count );
```
Compute Shaderとは異なり、WorkGroupは一次元で、```gl_WorkGroupID.y```と```gl_WorkGroupID.z```は0になる。
```gl_WorkGroupID.x```は [```first```, ```first```+```count```-1] の範囲に設定される。

# シェーダー

``` GLSL
#version 460
#extension GL_NV_mesh_shader : require

layout(local_size_x = 1) in;
layout(max_vertices = 3, max_primitives = 1) out;
layout(triangles) out;

out VertexOut
{
	vec4 color;
} vertexOuts[];

void main() 
{
    // 頂点位置
    gl_MeshVerticesNV[0].gl_Position = vec4(-0.5, -0.5, 0.0, 1.0);
    gl_MeshVerticesNV[1].gl_Position = vec4( 0.5, -0.5, 0.0, 1.0);
    gl_MeshVerticesNV[2].gl_Position = vec4( 0.0,  0.5, 0.0, 1.0);

    // プリミティブのインデックス
    gl_PrimitiveIndicesNV[0] = 0;
    gl_PrimitiveIndicesNV[1] = 1;
    gl_PrimitiveIndicesNV[2] = 2;

    // プリミティブの数
    gl_PrimitiveCountNV = 1;

    // 頂点カラー
    vertexOuts[0].color = vec4(1.0, 0.0, 0.0, 1.0);
    vertexOuts[1].color = vec4(0.0, 1.0, 0.0, 1.0);
    vertexOuts[2].color = vec4(0.0, 0.0, 1.0, 1.0);
}
```
### コードの解説
Mesh ShaderではCompute Shaderのようにスレッド数を設定する。
```GLSL
layout(local_size_x = 1) in;
```
出力する最大頂点数と最大プリミティブ数を設定する。
```GLSL
layout(max_vertices = 3, max_primitives = 1) out;
```
プリミティブのタイプを三角形に指定する。他にもpointsとlinesを指定することができる。
```GLSL
layout(triangles) out;
```
頂点位置の出力
```GLSL
gl_MeshVerticesNV[0].gl_Position = vec4(-0.5, -0.5, 0.0, 1.0);
gl_MeshVerticesNV[1].gl_Position = vec4( 0.5, -0.5, 0.0, 1.0);
gl_MeshVerticesNV[2].gl_Position = vec4( 0.0,  0.5, 0.0, 1.0);
```
頂点インデックスの出力
```GLSL
gl_PrimitiveIndicesNV[0] = 0;
gl_PrimitiveIndicesNV[1] = 1;
gl_PrimitiveIndicesNV[2] = 2;
```
出力するプリミティブ数を設定する
```GLSL
gl_PrimitiveCountNV = 1;
```
独自にデータの出力をして、Fragment Shaderに渡すこともできる。
```GLSL
out VertexOut
{
	vec4 color;
} vertexOuts[];

void main() 
{
    ...
    vertexOuts[0].color = vec4(1.0, 0.0, 0.0, 1.0);
    vertexOuts[1].color = vec4(0.0, 1.0, 0.0, 1.0);
    vertexOuts[2].color = vec4(0.0, 0.0, 1.0, 1.0);
}
```

実行すると以下のような三角形が描画される。
![MeshShader Sample 2024_08_14 19_14_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3861101/fc87812e-4227-fc72-1abf-dd2190e1b0a1.png)

全体のコードはここに置いておきます。
https://github.com/molimolily/GL_MeshShaderSample

# おわり
低レベルなAPIを使用せずとも、Mesh Shaderが使用できるのでめちゃくちゃ楽
気が向いたらモデルの描画とかTask Shaderを用いたcullingについても書くかも

# 参考
https://developer.nvidia.com/blog/introduction-turing-mesh-shaders/
OpenModelicaで接触のモデル化

# 作りたいモデル
Modelicaを使用して質量の跳ね返り計算を行いたい。
モデル化方針としては質量がめり込んでいる間(圧縮)は線形バネとして振る舞い、めり込んでいない間(引張)に関しては力を発生しない要素を作成する。

式で表現すると
要素の相対変位を$x$としたとき、以下のような力$f$を発生させる
$$f=
\left\\{
\begin{array}{cl}
kx & (x<0) \\\\
0 & (x\geq0)
\end{array}
\right.$$

# アイコンのレイアウト
アイコンビューで`Flange_a`と`Flange_b`をレイアウトし、わかりやすい見た目にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/b5a2cb0a-e940-948d-9fae-f25832c7d564.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/011e1064-0dc0-d10d-69f5-89a7844bf48c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/01561e0d-3184-9de0-4727-f213b37349d0.png)

# モデルコード作成
<details><summary>全文</summary>

```c
model nonlinear_spring
  Modelica.Mechanics.Translational.Interfaces.Flange_a flange_a annotation(
    Placement(transformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}), iconTransformation(origin = {-100, -2}, extent = {{-10, -10}, {10, 10}})));
  Modelica.Mechanics.Translational.Interfaces.Flange_b flange_b annotation(
    Placement(transformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}}), iconTransformation(origin = {100, 0}, extent = {{-10, -10}, {10, 10}})));
  parameter Real c(final min=0, start=1, unit="N/m") "Spring constant";
  Real disp(unit="m");
  Real f(unit="N");
equation
  disp = flange_b.s - flange_a.s;
  if disp < 0 then
    f = c*disp;
  else
    f = 0;
  end if;
  flange_a.f = -f;
  flange_b.f = f;
  annotation(
    uses(Modelica(version = "4.0.0")),
    Icon(graphics = {Rectangle(fillColor = {255, 255, 127}, fillPattern = FillPattern.Solid, extent = {{-100, 100}, {100, -100}}), Text(extent = {{-100, 40}, {100, -40}}, textString = "NonLinear
Spring")}));
end nonlinear_spring;


```

</details>


このモデルの本質となる`equation`部分の定義。
```c
equation
  disp = flange_b.s - flange_a.s;
  if disp < 0 then
    f = c*disp;
  else
    f = 0;
  end if;
  flange_a.f = -f;
  flange_b.f = f;
```
`disp`で各フランジ間の相対変位を計算。`disp`が負の値となっていれば線形バネとして振る舞い、`disp`が正の値を取っている場合は力を発生させない。
モデル上はa端からB端に向かう方向を正と考えているため、`flange_a.f=-f`, `flange_b.f = f`と定義している。

# テストモデルの作成
以下のような系で実験。前セクションで作成したモデルは黄色の`NonLinear Spring`として配置している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/524dfbca-763b-4a0b-a82a-4f3c55dfcf01.png)

`flange_a`をfixedで拘束し、`flange_b`には`mass`要素を配置している。

`NonLinear Spring`のパラメータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/d02c44c1-d044-917f-1bb6-cfcaea603d8d.png)

`mass`のパラメータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/d84d99d5-b1a0-efcb-525f-cc5e49ec931d.png)

# 解析結果
`mass`にかかる力と`mass`の速度
`mass`は速度-1で衝突し反力を受けたうえで速度+1として進み続けている。
![f2m.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/193de112-280f-e5cb-152b-f80c655c3acd.png)

# 最後に
このモデルを改造し以下のように応用したい。
* 減衰特性の追加（反発係数の低減）
* $p\text{-}\delta$線図のテーブルデータ入力(ブッシュなどの非線形特性を再現)
flutter Googleログイン フィンガープリントのあれこれで躓いたところ

https://zenn.dev/takumiendoh/articles/42d870436bc9c882bb85

このあたりを参考にデバッグ環境でGoogleログインを実装して詰まった箇所を記録します。

手順通りフィンガープリントを作成しアプリに追加したのですが、ログインを試みると

```
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: [firebase_auth/invalid-credential] access_token audience is not for this project
```

というエラーが発生してしまいます。

google-service.jsonを使用せずfirebaseOptionsで開発と本番の切り替えを行なっているので、更新されたgoogle-service.jsonに必要な情報があるのではないか...?
などと最初は考えていたのですが、特に追加で取り込む必要のあるものはないようでした。<br><br><br>

結果として、firebaseコンソールに出ている
**「このパッケージ名と SHA-1 の組み合わせを持つ OAuth2 クライアントは、別のプロジェクトに既に存在します」**
というアラートを解決してあげることが必要でした。

本番と開発のマイアプリのパッケージ名を同じ名前にしており、同じフィンガープリントを登録していたことでこのアラートが発生したようです。

<br><br>
firebaseコンソール上からフィンガープリントを削除してもGoogle cluod console -> 認証情報 -> OAuth 2.0 クライアント IDに設定が残ってしまっているので開発と本番のどちらかのクライアントIDを削除してあげればOKです。<br><br>

https://support.google.com/firebase/answer/6401008#zippy=%2C%E7%AB%B6%E5%90%88%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B-oauth-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-id-%E3%81%8C%E3%81%A9%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%2C%E7%AB%B6%E5%90%88%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B-oauth-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-id-%E3%81%8C%E3%81%A9%E3%81%AE-google-cloud-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%8F%E3%81%8B%E3%81%A3%E3%81%A6%E3%81%84%E3%81%A6firebase-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%A6%E3%82%82%E3%81%8B%E3%81%BE%E3%82%8F%E3%81%AA%E3%81%84%E3%81%BE%E3%81%9F%E3%81%AF-invites-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B

<br>
パッケージIDは開発と本番で違う名前をつけてあげたほうがよさそうです！<br><br><br>

※追記
releaseとdebugでは違うフィンガープリントを使用しているようでした

https://qiita.com/yass97/items/ee502eba6c8aa5a3b809

こちらの方法releaseのでSHA1を取得してfirebaコンソールに登録する必要がありました。
Windows で Python embeddable のインストールディレクトリを力業で移動させる

## Python embeddable のセットアップ
https://qiita.com/ebifuryai/items/d4df1fcb9bc9b90b3535

## はじめに
諸々の事情があって、Python embeddable でも pip を使用できるようにインストールしている方がいらっしゃると思います。ただこれは問題があって、折角 pip が使えるのにディレクトリを移動させるとうまく動かないことがあるので、無理やり移動先でも動かそうという試みです。

## 原因
もともとのインストールディレクトリが D:\Work\debug\python だったとして、D:\Work\debug\python2 にリネームした場合、Scripts 以下のファイルに絶対パスが仕込まれていて、参照先が見つけられないのが原因です。

````
D:\Work\debug\python2>pip
Fatal error in launcher: Unable to create process using '"D:\Work\debug\python\python.exe"  "D:\Work\debug\python2\Scripts\pip.exe" ': ?????????????

D:\Work\debug\python2>
````

![SnapCrab_Quick Be - DWorkdebugpythonScriptspipexe_2024-8-14_23-37-38_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842880/f64959e4-4fcd-322f-18f5-4e0ae3c64932.png)

厄介なのがリネームではなく単にコピーした場合、元ファイルが残っているので一見挙動が普通で、気が付きにくい事です。私は別PCで動かそうとした場合、あれ？となりました。さらに pip に限らず、Scripts 以下の exe ファイルなのでいやらしい。

## 対処法
パスを無理やり書き換えます（ぉ。複数のファイルを見ると、0x1A602番地から始まっているようです。今回は決め打ちで書き換えますが、Python のバージョンによると思うので、3.12.5 ではない場合は変わっている可能性があります。あまり検証していないので、自己責任でお願いします。

```python:rewrite_path.py
import os

def modify_file(file_path):
    begin = 0x1A602

    with open(file_path, 'r+b') as file:
        file.seek(begin)
        data = file.read()
        
        end = data.find(b'python.exe')
        if end == -1:
            return
        
        file.seek(begin)
        for i in range(0, end):
            file.write(b'\x20')

def rewrite_exe_files(directory):
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith('.exe'):
                modify_file(os.path.join(root, file))
    return

rewrite_exe_files('.\\Scripts')
```

## 使い方
エラーが出たときに、rewrite_path.py を実行します。書き換え後は絶対パスではなく python.exe だけになりますので、python.exe にパスが通っている必要があります。

## 参考にしたサイト
https://qiita.com/koppe/items/7fe62d483d351566d809
脳死でアプデし、脳死でトラブルシューティングした者の末路

# 経緯

## 寝る前
*「macOSのアプデきてるしついでに`brew upgrade`もするかぁ」*

```terminal
$ brew update && brew upgrade
```

*「よし！寝よう！」*
## 次の日

*「よぉし自作Webアプリの開発の続きでもするかぁ..サーバー建てて...ってあれ？」*
*「おかしいな...何もデータが取得されないぞ...」*
*...*

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2097267/d15f1119-9eb1-f459-c0c1-9e29ad5c1a03.png)

**ん?あれ？鯖落ちてる？**
*「...ログイン時になんかの間違いで自動起動できなかったんかな」*

```terminal
$ mysql.server restart
Starting MySQL
... ERROR! The server quit without updating PID file (/usr/local/var/mysql/*****.local.pid).
```

*...*
**「あ、オワタ」**

# 愚かな自分の対応

### 1. 安直にエラー内容でググる
昨日の自分の行動を思い返すこともなく、私はひとまず上に出たエラー文でググりました。

https://zenn.dev/ogakuzuko/articles/1d9d20fb5cbef8

https://qiita.com/carotene4035/items/e00076fe3990b9178cc0

https://labo.kon-ruri.co.jp/error-mysql-pid-file/

https://note.com/maki2862/n/n422d4e50b970


この他にもかなりの量の記事が見つかったので、私はすっかり安心しきってしまいました。

### 2. 記事に書いてある対処を何も考えずに実施

ネット上の情報は大体、

- プロセスの多重起動が原因→停止しろ
- 「ファイルがない」なら自分で作れ→権限設定をせよ
- できなければ再インストール

といった感じでした。

というわけで、記事に書いてある内容をとりあえず試してみました。

ところがどっこい、何一つとして状況は進展しませんでした。
エラー内容は最初と何ら変わりません。

### 3.意気消沈、そして
状況があまりに変わらないので、私はすっかり落ち込み、いっそOSごと環境を再構築することも考えだしました。
そんなこんなで丸1日経過し、これで解決しなければやめようと思った頃、この記事に出会って目を覚ましました。

https://qiita.com/YamKenta/items/a33499a7db7946a43381

この記事は、エラー内容こそ今までにみた記事と同じでしたが、単なるQ&Aではなく、エラー解決までの道のりを一つずつ追っていく形式になっています。

この記事の2. を見てふと気づきました。

**...そういえばログファイル1回も見てなくね？**

トラブルシューティングにおいて最重要、まさに本丸と言える「ログファイルを読む」ということを、愚かなことに私は全くしていなかったのです。
上の記事だけでなく、私が調べた記事の多くで「ログを当たれ」という記述がありました。
私は表面上の解決だけを目指していて、真の原因究明と対応をしようとしていませんでした。

## 原因判明、復活

早速ログファイルを探索します。

```
2024-08-14T14:35:33.142472Z 1 [ERROR] [MY-014060] [Server] Invalid MySQL server upgrade: Cannot upgrade from 80300 to 90001. Upgrade to next major version is only allowed from the last LTS release, which version 80300 is not.
```

冒頭でお気づきの方もいらっしゃると思いますが、そうです。
なんと私は**MySQL 8.0の環境を自分の手で無理やり9.0にしていた**のです。
これでは起動するわけがありません。
早速環境を元に戻します。

```terminal
$ brew uninstall mysql && brew install mysql@8.0
$ brew services start mysql@8.0
$ mysql.server restart
Shutting down MySQL
. SUCCESS!
Starting MySQL
. SUCCESS!
$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
```

というわけで、自分で壊した環境を自分で立て直すのに丸一日費やした愚か者のお話でした。

# 結論

トラブルシューティングをするときは、
-  エラーに遭遇しても、**すぐにエラー文でググらない**
-  たとえ解決したとしても、**何も考えずに調べた操作を行わない**
↓
- まずは直前の操作を**振り返る**
- ログファイルなど、**証拠集め**を万全に行う
- エラー原因を**予想**し、そこからネット・ドキュメントを調べる
- **納得した上で操作**し、解決する

ことが必要だなと思いました。
皆様も私のようにならないよう、ぜひお気をつけください。
RockyLinux 9.xとUbuntu22.xにOpenSSL 3.3.xをインストールする（ソースからビルド）

RockyLinux 9系では標準でOpenSSL 3系がインストールされていますが､あえて最新バージョンをソースからインストールしたい時に利用します。

## 環境

| ソフトウェア | バージョン |
|:-----------|------------:|
| OS  | rockyLinux 9.4 or Ubunt 22.04|
| OS  | OpenSSL 3.3.2|

## 事前準備

予め以下のPerlパッケージをインストールしておく

```
sudo dnf install perl-FindBin
sudo dnf install perl-IPC-Cmd
sudo dnf install perl-Pod-Html
```

### インストール

```
cd /usr/local/src
wget https://github.com/openssl/openssl/releases/download/openssl-3.3.2/openssl-3.3.2.tar.gz
tar xvzf openssl-3.3.2.tar.gz
cd openssl-3.3.2
./config -fPIC --shared --prefix=/usr/local/ssl
make -j 4
make install
```

### シンボリックリンクを張る
今は。ライブラリのパスがlib64になっているので、昔のプログラムだと参照できない可能性がある
```
 ln -s /usr/local/ssl/lib64 /usr/local/ssl/lib
```

以上で、/usr/local/sslに、OpenSSL3.3.xがインストールされます。
「--prefix」を付与しないと、/usr/local配下に直接インストールされるため、デフォルトインストールのOpenSSLとパスの設定によっては競合を起こすので部ディレクトリにインストールすることが望ましいと思います。
httpsを使ったCVAT( on AWS Lightsail )の立ち上げ ~自動アノテーションを添えて~

## やりたかったこと
[CVAT](https://docs.cvat.ai/about/)というアノテーションツールを、部署のみんなが使えるようにAWS上に公開したい。
しかし、普通にやるとhttp://EIP:8080 となってしまうので、https化(https://hogefuga.com) したい。
一方で、公開してもCVATの仕様上、create accountが誰でもできてしまう。
従って、https://hogefuga.com にアクセスしたらbasic認証を通すようにする。

## 前提
CVATの基本的な[インストール方法](https://docs.cvat.ai/docs/administration/basics/installation/)より、http://EIP:8080 でアクセスできるまで。


## 手段
1. aws Lightsailにてインスタンス起動
1. staticIPを付与
1. CVATをgit cloneし、docker compose up -d後、superuser作成（公式通り）
1. "ドメインとDNS"よりドメインの登録とDNSゾーンを作成
1. hogefuga.comをstaticIPに割り当てる
1. DNSレコードに、Aレコードとしてhogefuga.comをstaticIPを登録する
### https化準備
環境変数設定
ACME_EMAILはドメイン登録したときに使用したメアド
```
export CVAT_HOST=hogefuga.com
export ACME_EMAIL=hogefuga@gmail.com
```
### 自動アノテーション
まずversionを確認
```bash
cat components/serverless/docker-compose.serverless.yml 
```
```docker-compose.serverless.yml
services:
  nuclio:
    container_name: nuclio
    image: quay.io/nuclio/dashboard:1.13.0-amd64
```
1.13.0と判明。

```bash
wget https://github.com/nuclio/nuclio/releases/download/1.13.0/nuctl-1.13.0-linux-amd64
```
```bash
sudo mv nuctl-1.13.0-linux-amd64 /usr/local/bin/nuctl
```
```bash
sudo chmod +x /usr/local/bin/nuctl
```
SAMのインストール
```bash
cd serverless && ./deploy_cpu.sh pytorch/facebookresearch/sam/nuclio
```
yoloのインストール
```bash
cd serverless && ./deploy_cpu.sh onnx/WongKinYiu/yolov7/nuclio
```


### basic認証

hash生成
```bash
echo $(htpasswd -nb <yourID> <yourPW>) | sed -e s/\\$/\\$\\$/g
```
docker-compose.https.ymlの編集(to add basic auth部分)
```docker-compose.https.yml
# Copyright (C) 2018-2022 Intel Corporation
#
# SPDX-License-Identifier: MIT

services:
  cvat_server:
    labels:
      - traefik.http.routers.cvat.entrypoints=websecure
      - traefik.http.routers.cvat.tls.certresolver=lets-encrypt

  cvat_ui:
    labels:
      - traefik.http.routers.cvat-ui.entrypoints=websecure
      - traefik.http.routers.cvat-ui.tls.certresolver=lets-encrypt
    # to add basic auth
      - traefik.http.middlewares.cvat-ui-auth.basicauth.users=<yourID>:$$apr1$$<hash>
      - traefik.http.routers.cvat-ui.middlewares=cvat-ui-auth

  traefik:
    image: traefik:v2.9
    container_name: traefik
    environment:
      TRAEFIK_ENTRYPOINTS_web_ADDRESS: :80
      TRAEFIK_ENTRYPOINTS_web_HTTP_REDIRECTIONS_ENTRYPOINT_TO: websecure
      TRAEFIK_ENTRYPOINTS_web_HTTP_REDIRECTIONS_ENTRYPOINT_SCHEME: https
      TRAEFIK_ENTRYPOINTS_websecure_ADDRESS: :443
      TRAEFIK_CERTIFICATESRESOLVERS_lets-encrypt_ACME_EMAIL: "${ACME_EMAIL:?Please set the ACME_EMAIL env variable}"
      TRAEFIK_CERTIFICATESRESOLVERS_lets-encrypt_ACME_TLSCHALLENGE: "true"
      TRAEFIK_CERTIFICATESRESOLVERS_lets-encrypt_ACME_STORAGE: /letsencrypt/acme.json
    ports:
      - 80:80
      - 443:443
    volumes:
      - cvat_letsencrypt:/letsencrypt
```

### 起動
```yml
docker compose -f docker-compose.yml -f docker-compose.https.yml  -f components/serverless/docker-compose.serverless.yml up -d
```
流行りの運試しゲーム作ってみた

## はじめに
最近Reactを勉強し始めたので、アウトプットを兼ねて最近流行りの1/8192を作ってみました。
だいぶ雑な作りですが、暇つぶしに遊んでみてください。

## リンク
https://yuuya-apple.github.io/8192/

## 遊び方
2つのボタンA/Bのお好きな方を押してください。
どちらか一方のボタンが正解のボタンになります。
正解のボタンはクリックのたびにランダムで割り振られます。
13回連続で正解のボタンをクリックできるとクリアになります。
頑張ってください！
AWSでサーバー作ってみた！～初心者でも簡単にできるEC2立ち上げ～(概要編)

どうも！最近ようやく定期的にプログラミングに関する記事をあげている２６歳看護師です。
今回は、AWSでサーバーを作る方法をざっくりと紹介していこうと思います！AWSって聞くと「なんか難しそう…」って思うかもしれないけど、実はそんなこと、、、あります。めちゃくちゃむずかしい。
なので今回は私のイメージ的として捉えるAWSの概要についてまとめてみました！
![6D6E65B5-899B-4E78-88D3-0C208F17063C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/958574b1-badb-805e-3eba-ef06c79170c9.jpeg)

### まずは家を建てる場所を決めよう！

家を建てるときって、まずはどこに建てるか決めますよね？AWSでも同じように、まずは「リージョン」と「アベイラビリティーゾーン」っていう場所を決めます。これが「サーバーをどこに置くか」って話になるんです。リージョンは国や地域、アベイラビリティーゾーンはその中の具体的なデータセンターのこと。大きな場所の枠組みになります！

### 自分専用の敷地を作ろう！

場所が決まったら、次は自分専用の敷地を作りになります。この敷地が「VPC（Virtual Private Cloud）」になります。VPCは他の人から独立した自分だけの空間です。VPCの中をさらに細かく区切ってサブネットを作ることで、敷地内を小分けにして、いろんな家や駐車場（サーバー）を建てられるようになるんだ。

![2517997A-D488-43CD-BFEE-0C451226541A.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/d91db05c-f9b1-3da2-f5f1-32169522f143.jpeg)

（息抜き）ーー最近流行りの地面師たちをエンジニアにさせたら屋外でオフィスワークするイカれた絵ができた

### 設計図から家を建てよう！

次は実際に家を建てます。AWSで家を建てるためには「設計図」が必要で、それが「AMI（Amazon Machine Image）」になります。AMIには、家の大きさとか、WindowsやLinuxみたいなOSの情報が入ってる。これを元にして家（サーバー）を建てます。AWSのEC2というサービスを使うと、この家をインターネット上に建てることになります！

### いざ全世界とつなげよう！

家を建てたら、次は道路とつなげないと意味がないですよね。そのためには「インターネットゲートウェイ」っていう門を設置する必要があリます。そこで、住所にあたるのが「IPアドレス」。これがあれば、誰でもネット上からあなたの家にアクセスできるようになるんです。でも、再起動とかで住所が変わっちゃうと困るから、「Elastic IP」を使って固定の住所を設定するのがオススメ！

### 玄関を作ってセキュリティを強化しよう！

さて、家にドアや鍵がないと誰でも勝手に入れちゃいます。AWSでも同じで、ポートっていう玄関を作ることで、誰がどこから入れるかを決めることができます。このポートの出入りを管理するのが「セキュリティグループ」。これを設定することで、外からの不正アクセスを防ぐことができます。
![IMG_E97FECD68F97-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/1791bf25-ae65-d193-73e7-04f13c6e8967.jpeg)
「このドア以外から入ってはいけません！！」


### 最後に錠と鍵をかけよう！

最後に、家に錠と鍵をかけてセキュリティを強化しましょう。AWSでは「キーペア」っていう仕組みで、家の鍵を管理するんだ。これで、インターネットからあなたの家にアクセスできる人を限定できるんだよ。鍵がないと家に入れないから、ちゃんと管理しておきましょう！
⚠️間違っても秘密鍵は公開しないようにしましょう！


イメージ図
![スクリーンショット 2024-08-09 1.36.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/19085560-7710-f363-52a8-269237d681ed.png)


### まとめ

こんな感じで、AWSでのサーバー構築は家を建てることに例えるとすごく分かりやすかったです。テックキャンプは卒業後も初心者にはわかりづらい機能もきちんと教えてくれます。興味がある人はぜひチャレンジしてみて！自分のアプリを世界に公開する第一歩になるかもよ！
paiza Aランク問題「じゃんけんの手の出し方」を Elixir で解いてみた

## はじめに

paiza A ランク問題を Elixir で解いてみます

## じゃんけんの手の出し方

相手の出す手が全て分かっているとき、開いた指の合計数を指定数に合わせ、最も勝利数が多くなるようにします

https://paiza.jp/works/mondai/a_rank_skillcheck_sample/janken

```elixir
defmodule Paiza do
  def main do
    [n, m] =
      :stdio
      |> IO.read(:line)
      |> String.trim()
      |> String.split(" ")
      |> Enum.map(&String.to_integer(&1))

    # 相手のGCP毎の手数
    f =
      :stdio
      |> IO.read(:line)
      |> String.trim()
      |> String.codepoints()
      |> Enum.frequencies()

    # P(パー)が 0 〜　最大まで、全てのパターンを計算する
    0..(div(m, 5))
    |> Enum.map(fn p ->
      c = div(m - p * 5, 2) # C(チョキ)の数
      g = n - p - c # G(グー)の数
      
      {g, c, p}
    end)
    |> Enum.filter(fn {g, c, p} ->
       # 条件を満たす場合だけを抽出
      g >= 0 and m == p * 5 + c * 2
    end)
    |> Enum.map(fn {g, c, p} ->
      # 勝利数を計算
      g_win = min(g, Map.get(f, "C", 0))
      c_win = min(c, Map.get(f, "P", 0))
      p_win = min(p, Map.get(f, "G", 0))
      Enum.sum([g_win, c_win, p_win])
    end)
    |> Enum.max()
    |> IO.puts()
  end
end

Paiza.main()
```

# 解説

手数と指の合計数が決まっているため、パーの数が決まったとき、残りの指はチョキで賄うしかありません（グーは 0 なので）

パーの数が 0 のときから、最大のときまで、全てのパターンに対して、グーチョキパーの手数を計算します

そのうち、条件を満たすケースだけを抽出し、勝利数の最大値を求めます

## まとめ

パーが決まればチョキが決まる、ということにさえ気付けば単純ですが、途中無駄にややこしく考えてしまいました

最終的に map |> filter |> map |> max になって、パイプがいい感じです（ reduce にすることもできますが）
herokuのEco Dynoプラン登録

# Eco Dynoプランについて

月5ドルの最安値プランです。月末区切りで日割りはなく、月途中でも満額かかります。
アプリはアクセスが無いとスリープし、合計1000時間以内で複数アプリの運用が可能です。

:::note
参考：ごく短時間だけの利用ならBasic Dynoプランの方がお得です
[herokuを短時間だけ試したい時に適したプラン](https://qiita.com/himitune/items/d83418b1a64576ac2aef)
:::

# Eco Dynoの登録手順

:::note warn
前提：支払い用のクレジットカードは登録済みとします
:::

1. herokuにログインして、アカウントメニューから「Account Settings」を選択
1. 「Billing」タブをクリック
1. 「Subscribe to Eco」ボタンをクリック
1. 「Subscribe」ボタンをクリック
1. herokuのロゴをクリックしてアプリ一覧に移動
1. アプリケーションを選択
1. 「Resources」タブをクリック
1. 「Change Dyno Type」をクリック
1. 「Eco」を選択
1. 「Save」ボタンをクリック
PandasからPolarsに移行するときに注意したいこと

# はじめに
いよいよ，遂にデータ分析にPolarsを導入しました．（遅い...）
以前より「速い」「Pandasライクな記法」ということを耳にしてはいましたが，就職活動や学業で時間が取れずに，中々導入を躊躇っていました．

そんな折に，サマーインターンシップに参加させていただく機会を得ることができ，その中で大規模なデータを扱うことになったのですが，Pandasでは中々処理が終わらない......
普段であればアルゴリズムを工夫して計算量を減らすところですが，気まぐれで前々から気になっていたPolarsを導入してみることにしました．

そんなPandasを普段利用する人がPolarsを初めて利用するという事例の1つとして，目を通していただければ幸いです．
困った箇所・詰まった箇所に焦点を当てて，簡単なチュートリアルを記事にしてみたいと思います．

:::note 
ちなみに，参加させて頂いたインターンシップはBIPROGY株式会社様のAI Engineer / Data Scientist向けのもので，これに関連する記事はこちらにもあるので，気に入った方は目を通してみてもらえると幸いです！
:::

https://note.com/yorozuya59/n/n8e0f6689c3a4


# 【困った箇所①】 Polarsって何と読むの？
そもそもですが，何と読むのでしょうか？
これまで，話題に挙がっても「ぽ、ぽーらす...？ぽらーす？」といったように呼ぶ人が多く，私も例に漏れずに確信が持てない状況でした．
これを機に調べてみると，「ポーラス」[^1]が近いのかなと思います．（有識者の方，教えてください！）
→ どうやら「ポラーズ」のようです．（@WolfMoon様ありがとうございます！）[^2]

[^1]: YouTube -> https://www.youtube.com/watch?v=iwGIuGk5nCE&t=66s, Google Translate -> https://translate.google.com/?sl=en&tl=ja&text=polars&op=translate

[^2]: https://qiita.com/Yorozuya59/items/da0243fc8c734f1d4025#comment-f46b075dd994ec024c93

小さな疑問ですが，チームで共有するときに地味に困るので，初めに挙げてみました．


# 【困った箇所②】 古いバージョンの情報が（現時点では）多い
まだまだ発展途上ということなのだと思いますが，バージョンごとに変更点が多く，記事を鵜呑みにするだけではエラーが多発します．
エラーが発生する場合は公式ドキュメントを読みましょう．（この記事の意義を引っくり返すものですが......）

https://docs.pola.rs/api/python/stable/reference/index.html

具体例を挙げておくと

```python
import polars as pl


data = [
    [1, 2],
    [3, 4],
    [5, 6],
    [7, 8],
    [9, 10],
]
df = pl.DataFrame(data, schema=["a", "b"])

# 以下が最新バージョン（1.4）の記法
df_new = df.with_columns(
    (pl.col('a') ** 2).alias('a_squared')
)

# 以下の記法ではエラーが発生（おそらくバージョン0.15以前）
# df_new = df.with_column(
#     (pl.col('a') ** 2).alias('a_squared')
# )
```

みたいな感じです．

また，これに似たようなものとして，生成AIに記述してもらう際にPandasと混ざった回答が返されるというものもあります．

```python
# 以下が最新バージョンの記法
df = pl.DataFrame(data, schema=["a", "b"])

# 以下が誤った記法（生成AIに質問するとこういった回答が得られることが多々ある）
# df = pl.DataFrame(data, columns=["a", "b"])
```

まだまだ，Pandasの記事の方が絶対的な記事の量が多く，また新しい内容なので学習が追いついていないのでしょうね．


# 【困った箇所③】 まだPandasに比べるとサポートされている操作が少ない
大規模データでPolarsを導入したのは良いものの，（Pandasではサポートされているような）少し複雑な操作がサポートされておらず，泣く泣くPandasに変換して処理を行いました．
幸いにも計算量が少ない操作だったので，それで事足りましたが，計算量の多い操作であれば他の方法を検討する必要がありそうです．

ちなみに，PandasからPolarsの変換やその逆は非常に簡単に実装できるので，現時点で致命的な問題になることは無さそうです．

**Pandas to Polars**

https://docs.pola.rs/api/python/stable/reference/dataframe/index.html

**Polars to Pandas**

https://docs.pola.rs/api/python/stable/reference/api/polars.from_pandas.html

なお，Polarsで実装できなかった部分のコードを掲載したいところですが，少し特殊な操作のため，少し書き換えた程度では情報漏洩になりそうなので，割愛させてください．


# 【良いところ】 とにかく速い
Polarsの悪いところだけ挙げるのも悲しいので，最後に良いと思ったポイントを．

:::note
上記で挙げた「困ったところ」は，あくまで**これから使い始める人が気をつけたいポイント**というものです．
私自身，これからもPolarsを使うつもりなので，アピールポイントも紹介させてください！
:::

私の環境で実行時間を計測してみた結果は以下の通りです．（一例くらいに考えてください．）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693436/f855d1f4-e656-3321-470d-fed044ea8dfc.png)

上記の実行時間はランダムな値をN行×5列で生成し，５列の積を計算した時のものです．
大規模なデータになるほど，差が大きくなっていることが分かります．（今回の場合，最大で10倍程度）

なお，group_byなどの操作の方が顕著らしいですが，今回はそこまで検証はしていません．
とはいえ，十分な高速化が達成できているのではないでしょうか？


# 最後に
ふとしたきっかけで導入することにしたPolarsですが，使い所を見極めることができれば，非常に強力なツールになるなと感じました．
今後の研究などの中で使用して知見が溜まってくれば，Polarsについて新しい記事を書くかもしれません．
「ハッキングラボのつくりかた　完全版」droopescanのインストールでエラーが出た件

## 問題

「ハッキングラボのつくりかた　完全版」DC1の攻略時、以下のコードでインストールエラーが発生した。
```
pip install droopescan
```

## エラー内容
```
┌─[user@parrot]─[~]
└──╼ $sudo pip install droopescan
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.
    
    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.
    
    If you wish to install a non-Debian packaged Python application,
    it may be easiest to use pipx install xyz, which will manage a
    virtual environment for you. Make sure you have pipx installed.
    
    See /usr/share/doc/python3.11/README.venv for more information.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
```
## 調査したこと
1:エラー文を翻訳
2:"pip externally-managed-environment"でググった

## 解決方法
以下のコードで仮想環境にインストールする
```
python3 -m venv myenv　# 仮想環境を作成
source myenv/bin/activate　#仮想環境を有効化
pip install droopescan　# droopescanのインストール
```
## 終わりに
最初は"apt install droopescan"をしたがインストールできず..
パッケージ化されていないからそもそもapt installが使えないという当たり前のことを今更ながら認識した。
また、pipxを使う方法も書かれていたがエラーの前半しか読んでいなかったため、試す前に解決してしまった。
解決後pipxをインストールしたがdroopescanのインストールで別のエラーが出た。そちらは"pip drooopescan"でググればすぐに解決手順が出てきた。