OmniAICreator/Qiita-1.07M huggingface dataset:
#github.com/go-playground/universal-translatorのエラーの解決

# エラー

#github.com/go-playground/universal-translator
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\import_export.go:221:12: undefined: ErrMissingLocale
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\import_export.go:244:12: undefined: ErrBadPluralDefinition
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:101:11: undefined: ErrConflictingTranslation
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:108:11: undefined: ErrMissingBracket
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:121:12: undefined: ErrBadParamSyntax
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:151:11: undefined: ErrCardinalTranslation
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:158:12: undefined: ErrConflictingTranslation
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:176:11: undefined: ErrCardinalTranslation
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:203:11: undefined: ErrOrdinalTranslation
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:210:12: undefined: ErrConflictingTranslation
C:\Users\user\go\pkg\mod\github.com\go-playground\universal-translator@v0.18.1\translator.go:210:12: too many errors

コンパイルは終了コード 1 で終了しました

# 環境
- GoLand 2024.1.3
- go-playground\universal-translator@v0.18.1

# 解決策

## 1.依存関係をアップデートする

```Bash
go get -u github.com/go-playground/universal-translator
```

## 2.ダウングレードをする
```Bash
go get github.com/go-playground/universal-translator@v0.17.0
```
Raspberry Pi Pico用4bit SDIO接続micro SD基板つくった

![_DSC0697.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108691/6e0b3a9d-8225-0748-d45e-657a98527ba2.jpeg)
初代SPI接続板、二代目SPI/4bit SDIO接続兼用板, Raspberry Pi Picoの図。

Raspberry Pi Picoの背面に取り付けるmicro SDスロットのついた基板をまた作成します。[前回](https://qiita.com/0yama/items/972c77a9e63ff9d9c742)作った基板は、SPI接続で書き込み速度が最大で1.8MB/sec止まりでした。クロック周波数は48MHzまで上げられますが、これ以上の速度向上はちょっと難しい。ということでより高速な4bit SDIO接続する基板を作ります。

## micro SDソケットパーツの編集

今回も[Fritzing](https://fritzing.org)で回路を作ります。micro SDカードソケットは前回購入したSparkFunの[microSD Socket for Transflash](https://www.sparkfun.com/products/127)がまだ余っているので今回も使用します。Fritzingに登録されているパーツはSPI接続のみですが、[データシート](https://cdn.sparkfun.com/datasheets/Components/General/15882.pdf)を眺めると8本の端子はちゃんとSDカードと繋がっているので、配線すればSDIO接続にもできるはず。

既存のパーツを書き出して、端子を増やします。

![sdcard5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108691/7ba47a81-c4b1-c457-dc05-bce8693f62b0.png) ←これが、こうなる→ ![sdcard2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108691/aa33876d-b5a8-a36d-84b8-623fc6cc7d0b.png)

SPI接続する場合と、SDIO接続する場合との両方をラベルに表記します。
あとは配線するだけですが、流石に接続する端子が増えるといきなり複雑さが増します。今回は自動ルーティングが一発では成功しなかったので、パーツの配置を調整して自動ルーティングして〜を繰り返し、なんとかルートを確保。
![sdcard4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108691/b8440d38-b13d-ef8a-0d93-24c30203d345.png)
SPIとSDIOを兼用したかったので、接続するピンの位置を先に決めていたせいもあって、配線が長い。これは良くない。が、遊びなので問題なし。

## 老眼と手ハンダ

7つのプルアップ抵抗と2つのコンデンサをつけるにあたり、配線の自由度を確保できるかなと0603サイズ(0.063 inch x 0.031 inch = 1.60 mm x 0.80 mm)の表面実装パーツを選びました。私の老眼と手ハンダではこのサイズが限界ですね...

![_DSC0700.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108691/fa73d958-c56d-9484-8420-4217a14af798.jpeg)

わかっていたことですが書き込み速度は約4倍速くなり8MB/secくらい簡単に出るようになりました。
PhpStormが思いのほかよくなっていた

# 久しぶりにPHPを使う

皆さんは、PHPを書くとき何を使っていますか？
昔はsakura editorや秀丸を使っていましたが最近はもっぱらPhpStormが多いです。
1ファイルだけのバッチっぽい何かの場合は、VsCodeでちゃちゃっとする事もありますが
ファイル分割が必要な規模は、基本的にPhpStormを使います。

## PhpStormの何が良いのか？

個人的にPhpStormのここが良いと思う所は大ざっぱに以下の様なものになると思います。
・インストールした瞬間PHPで必要そうなものは大体入っている
ものぐさな私からすると必要なプラグイン(似たようなプラグインが山のようにあるので選定するのがつらい)を探さなくてよい事です。
・他言語用の統合環境も一通り揃っており操作感もほぼ同じ(全部のせコースを使っている為)
・地味に機能が豊富（設定周りもかなり充実している）
・ローカル AI による行全体コード補完(NEW)

## ローカル AI による行全体コード補完(NEW)

今回は、この機能について話したいと思います。
この機能は、2024.1のバージョンに実装されたものです。
2023.?に追加されたAI Assistantなるものが追加されましたがこれとは別物です。
AI Assistantは、ChatGPTの様な機能でエディタ費用とは別枠でサブスク料金が発生します。
但し、そこそこ高性能な応答をする感じです。
2023年4月当時にお試しで使用した印象はGitHub Copilotと同性能な印象です。
※「ローカル AI による行全体コード補完」は、エディタ料金に含まれるため別途費用は掛かりません。

で、今回の話したい「ローカル AI による行全体コード補完」についてですが
例えば、以下の様なコードを書いたとして
```php
function dump(string $filename, mixed $msg): void {
	file_put_contents($filename, $msg."\n", FILE_APPEND);
}
```

オブジェクトや配列も面倒なのでダンプするかとなった時の補完です。
```php
function dump(string $filename, mixed $msg): void {
	if (is_object($msg) || is_array($msg)) $msg = json_encode($msg, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
	file_put_contents($filename, $msg."\n", FILE_APPEND);
}
```
1行丸ごと1度の補完ではなく、ifとか$mとか打つと残った部分で最短な補完の提案がでます。
例えば、```$m```と打つと```$msg = json_encode($msg);```の提案がでます。
後は、整形済みにしたいので…
```$msg = json_encode($msg,);```と入力すると```$msg = json_encode($msg, JSON_PRETTY_PRINT);```の補完が出る感じです。
ついでに、エスケープやユニコードも見やすくしたいので…
```$msg = json_encode($msg, JSON_PRETTY_PRINT |);```と入力すると
```$msg = json_encode($msg, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);```という感じの提案がでます。

この行で入力した文字は、```if ( | $m , | |```です。
中々の補完度です。
そして、何よりうれしいのがこの機能はネットワークを使用しない事でしょう。
仕事で使っていると、守秘義務やら何やかんやでソースそのままでやり取りに気を遣う必要がありますがこの機能は、ローカル動作の為、そういう部分は考えないで良いのは非常に助かります。

慣れた言語であれば、この手の補完はあまり恩恵がないのかもしれませんが、慣れていない言語や暫くさわっていないとスペルがうろ覚えだったりしても少し打てばそれっぽいコードを提案してもらえるので非常に助かります。

こういった、高機能・高品質の機能が誰でも簡単利用できるようになり、提供してくれる方に感謝しかありません。
(調査中)powermockで、springmvcのコンストラクタをモックに

## pom.xml

```xml
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.3.3</version>
    <scope>test</scope>
</dependency>
```

## java

```java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(YourController.class) // モックするクラスを指定
public class YourControllerTest {

    @InjectMocks
    private YourController yourController;

    @Mock
    private SomeDependency someDependency;

    @Test
    public void testConstructor() throws Exception {
        // YourControllerのコンストラクタをモックする
        YourController mockController = PowerMockito.mock(YourController.class);

        // コンストラクタの呼び出しをモック
        PowerMockito.whenNew(YourController.class).withAnyArguments().thenReturn(mockController);

        // 実際のコンストラクタ呼び出しを行う
        YourController instance = new YourController(someDependency);

        // モックが呼び出されたことを確認
        PowerMockito.verifyNew(YourController.class).withArguments(someDependency);
    }
}
```
Adobe Acrobat Proのサブスク罠に落ちたっ！

## TL;DR
まずCreative Cloudコンプリートプランにアップグレードし、そして、解約する。これで、当月分のAcrobat Proプラン料金の1980円も一部返金するし、新規購入の7780円も全額返金してくれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73297/b490cb2f-a062-d7eb-5d03-4ac05baa6100.png)

## どんな罠ですか

Adobe Acrobat無料体験期間内に解約し忘れたら、自動的に年間契約のAcrobat Proプランに加入し1ヶ月1980円課金される。しかも解約するには残りの年間契約料金の半分を払わなければいけない。

サブスクの提示はあまり目立たないので、普段IT技術に詳しい人も結構落ちる。

Hacker Newsで3年前にすごい議論されていた。

https://news.ycombinator.com/item?id=26786563

日経新聞も最近こんな記事がありました。

https://www.nikkei.com/article/DGXZQOGN17CR90X10C24A6000000/

法律的には問題ないかもしれないが、罠かどうかは、もう議論する余地がないと思う。

## 返金記録

Adobeのサポートに連絡することも可能ですが、やはり「アップグレード → 解約」が一番早い。すぐにクレジットカードから落とさないかもしれない、3-7日以内に必ず反映できる（私の場合は3日間）。

![IMG_2579.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73297/5d7eb509-33e8-af85-82aa-d63352413d29.jpeg)
【ActiveRcord】SQLとActiveRecordの違い

# SQL（Structured Query Language）
データベースを操作するための標準言語。
データの挿入、更新、削除、検索などを直接行う。
```
SELECT * 
FROM users 
WHERE id = 1;
```

# ActiveRecord

Ruby on Railsで使われるORM（Object-Relational Mapping）ライブラリ。
データベース操作をオブジェクト指向的に行えるようにする。
SQLを書かずに、Rubyのメソッドを使ってデータベース操作ができる。
```
Staff.where(store_id: 2)
```
# まとめ

SQLはデータベースを直接操作するための言語で、
ActiveRecordはRuby on Railsでのデータベース操作を簡単にするためのライブラリ。
どちらもデータベース操作を行うための手段だけど、アプローチが違う。
PowerMockとmockitoを同時に使う

## pom.xml（Mavenを使用している場合）に必要な依存関係を追加

```xml
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.x.x</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.x.x</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.x.x</version>
    <scope>test</scope>
</dependency>
```

## テストクラス

```java
import static org.mockito.Mockito.*;
import static org.powermock.api.mockito.PowerMockito.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(MockitoJUnitRunner.class)
@PrepareForTest({ClassWithStaticMethod.class})
public class ExampleTest {

    @Mock
    private DependencyClass dependency;

    @Test
    public void testStaticMethod() {
        // 静的メソッドのモック設定
        mockStatic(ClassWithStaticMethod.class);
        when(ClassWithStaticMethod.staticMethod()).thenReturn("mocked value");

        // 通常のモック設定
        when(dependency.someMethod()).thenReturn("some value");

        // テストの実行
        String result = new ClassUnderTest(dependency).methodUnderTest();

        // アサーション
        assertEquals("expected value", result);
    }
}
```

## 参考

https://groups.google.com/g/powermock/c/hLLVa3fn6BE?pli=1

https://stackoverflow.com/questions/69896191/powermock-compatibility-with-jdk-17

https://github.com/powermock/powermock/issues/1161

https://github.com/checkstyle/checkstyle/issues/7368

https://medium.com/parallaxtec/spring-boot-java-16-junit4-junit5-powermockito-salad-3c1c3ec7c97b
SwiftTestingで例外処理をテストする

## エラーがthrowされることをテストする

```swift
@Suite final class SampleTests {    
    @Test func throwErrorTest() throws {
        // なにかしらのエラーがthrowされることをテスト
        #expect(throws: (any Error).self) {
            try sample()
        }

        // SampleTestErrorがthrowされることをテスト
        #expect(throws: SampleTestError.self) {
            try sample()
        }

        // SampleTestError.hogehogeがthrowされることをテスト
        #expect(throws: SampleTestError.hogehoge) {
            try sample()
        }
    }
}

```

## associatedValueの中身もテストする
```swift
@Suite final class SampleTests {    
    @Test func throwErrorTest() throws {
        #expect {
            try sample()
        } throws: { error in
            guard let error = error as? SampleTestError,
                  case let .fugafuga(code) = error
            else {
                return false
            }
            return code == 400
        }
    }
}

```
Power Query にて１行上の値と比較するための列を作成する

ある時系列順に並んだデータから、1行上の値と比較を行うためのクエリを考えます。
下記の「Power BI Community Blog」記事を参考にしています。

https://community.fabric.microsoft.com/t5/Community-Blog/Power-Query-Methods-to-Refer-to-Previous-Row-Time-Performance/ba-p/2627639

# 入力データ
入力データはワークシート内で `ROW()` を使って5000行のデータを用意して、クエリで読み込んでおきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/b8b20af0-7426-a17f-9a69-10ee95f8ba02.png)

```PowerQuery:テーブル1
let
    ソース = Excel.CurrentWorkbook(){[Name="テーブル1"]}[Content],
    変更された型 = Table.TransformColumnTypes(ソース,{{"values", Int64.Type}})
in
    変更された型
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/06d4eff1-d7e9-d455-a393-5807fb837103.png)

# インデックスメソッド
オーソドックスな書き方をすると、インデックス列を用いて`{}`演算子で一つ前の行を読み出す方法となりますが、この方法を行うとPowerQueryではO(n^2)ぐらいの時間がかかってしまうため、行数が1000を超えるような場合ではおすすめ出来ません。

```PowerQuery:Table-Index method
let
    Source = テーブル1,
    ZeroIndex = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
    追加されたカスタム = Table.AddColumn(ZeroIndex, "prev.values", each try ZeroIndex{[Index]-1}[values] otherwise null)
in
    追加されたカスタム
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/14e1028a-3395-1aaa-665d-e534fba95b50.png)

# マージメソッド
インデックス列を0始まり`ZeroIndex`と1始まり`OneIndex`で2列作成して、それらをKeyに左結合`Table.NestedJoine`して作成する方法。
処理時間はインデックスメソッドよりかなり改善されて数万行でも十分処理できます。
```PowerQuery:Table-NestedJoin method
let
    Source = テーブル1,
    ZeroIndex = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
    OneIndex = Table.AddIndexColumn(Source, "Index", 1, 1, Int64.Type),
    マージされたクエリ数 = Table.NestedJoin(ZeroIndex, {"Index"}, OneIndex, {"Index"}, "One", JoinKind.LeftOuter),
    #"展開された One" = Table.ExpandTableColumn(マージされたクエリ数, "One", {"values"}, {"prev.values"}),
    並べ替えられた行 = Table.Sort(#"展開された One",{{"Index", Order.Ascending}})
in
    並べ替えられた行
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/dd6f8352-3b3b-20b4-302b-e44a1efc8f14.png)

# リストメソッド
テーブルの各列を一旦リスト型に変換したあと、`List.RemoveLastN`によってラスト1行を削除した列を作成して、再びテーブル形式に戻す方法。
マージメソッドよりも若干高速に処理されますが、M式の大部分を詳細エディタから手打ちして作成する必要があります。
元ネタの「Power BI Community Blog」のlet式は3行ほどで書かれていましたが、分かりやすくするためにステップを分割して作成したクエリが下記になります。この手法ではIndex列は不要ですが、最終結果を他と合わせるために追加しています。
```PowerQuery:List-RemoveLastN method
let
    Source = テーブル1,
    ZeroIndex = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
    toColumns = Table.ToColumns(ZeroIndex), 
    prevValues = {{null} & List.RemoveLastN(ZeroIndex[values],1)},
    columnNames = Table.ColumnNames(ZeroIndex)&{"prev.values"},
    Custom1 = Table.FromColumns(toColumns & prevValues,columnNames)
in
    Custom1
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/b25d5b42-aa0d-2d65-9c69-4f4364ffb31f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/32b4d70a-b31e-76d1-ea36-7a1130826714.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/198ba5ef-a98a-6c48-68cb-6e56544af104.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/bf4b8e2a-5e97-6b3d-0566-73069e1527ef.png)
App Store審査却下😱AI機能搭載アプリは中国で配信規制があるらしい

## はじめに
弊社では、自社プロダクトのスマホアプリをApp StoreとGoogle Playにて公開しています。
先日、最新バージョンのリリースをApp Storeに申請したところ、審査が却下されてしまいました😱
その原因と対策を紹介します。

## 審査が却下された原因
メールから、「**Guideline 5 - Legal**」に引っかかってしまったようです😱

英語でいろいろ書いてありましたが簡単にまとめるとこんな感じ。
> 中国政府はディープシンセシス技術(DST)や生成AIサービス（ChatGPTを含む）に関する規制を強化しているよ。これらのサービスを中国で運営するには、工業情報化部(MIIT)からのライセンス取得を含む許可要件を満たさなあかんで！

> 対応オプションは以下の通りや！
> 1. 必要な変更を行い、AI機能を削除したことを確認して再提出する。
> 2. 中国での配信を希望しない場合は、App Store Connectの設定で中国本土の選択を解除する。
> 3. すでに法令を遵守していると考える場合は、追加情報を提供して返信する。

知らなかったねー！！

検討した結果、「2.中国での配信を希望しない場合は、App Store Connectの設定で中国本土の選択を解除する」の方針で対応することにしました。

## 特定の国をアプリの配信先から除く方法
App Store Connectの`App Store` => `収益化` => `価格および配信状況`ページを開きます。

中盤に`アプリの配信状況`というセクションがあります。
その中の`管理`をクリックすると、アプリを配信している国の一覧ページに遷移します。

上の方に`配信状況を管理`というボタンがあるのでクリックしましょう。

配信先の国を✅で選択できるようなモーダルが表示されます。
このモーダルで、配信したくない国を除けば完了です！
![スクリーンショット_2024_06_27_0_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537832/a3c3f945-de8d-8eee-55ed-15b64d6f0ea6.png)


`次へ`をクリックし、変更を`保存`しましょう。

> 変更は24時間以内に有効になります。

配信国を変更しても、すぐには変更は反映されないようなので注意しましょう🎉

## 終わりに
審査が却下されるのは初めてだったので焦りました😓
スマホアプリでAI機能のリリースを検討するときは、配信国に注意が必要ですね。

### 参考
https://qiita.com/yoshitaka/items/12df9f58baf9e23545db
リリース作業のしくじり

# はじめに
結論から言うと、以下二３点となります。
①リリース作業は業界一年目にやらせるなよw
②ちゃんとダブルチェックはやろうね
③ちゃんと公式アナウンスはチェックしようね

IT業界20年近いですが、なんだかんだずーーっとリリース作業に関わってます。
その経験について少々話します。

とは言っても、あまりにも基本的なことしか記載しません。。
リリース作業の工夫とかテクニカルな記事では一切ございませんので、あしからず。

# 最初の仕事でやらかすリリースミス
業界最初にやったのがリリース作業でした。

今考えると正気の沙汰では無いですが、
客曰くやらせることがなかったから取り敢えずリリース作業を割り振ってみたw
だった気がします。

どうなったかというと、**案の定リリースミスを起こしましたorz**。
エンドの客に納品するソースコードのビルドが通らないと。。

ハッキリ言って渡された手順書もイケてなかったし、ダブルチェックもほとんどしない状態で納品物のまとめ作業も私が担当。。

作業を振る側もどうかと思いますが、振られた私も文句言えなかった私が悪いと言えば悪い。。
でも、配属一年目にそんなん全く判断出来んかったわw

# リリースミス後
その後はリリースチェック表を見直し、何度もレビューしてもらいました。
※そういえば、最初の案件の時は結局最後までほぼダブルチェックしないところでしたね。。

リリース担当は私一人で人に依存していた形になるし、ダブルチェックもろくにやってなかったので、ハッキリ言ってあり得ない体制でしたね。。

# スマフォ向けの案件に携わって
スマフォ向けの開発をやるようになって、自動的にリリース作業も兼任してました。

iOS/AndroidのGoogle play/App Storeへのリリース作業ですね。

ここもなんにもチェック表やダブルチェックしないところだったなー。
無いものは無いので、チェック表や手順書は自分で作成しました。

# リリース予定日前日のリジェクト
ある程度経験年数も経っていたし、リリース作業もこなしてきていた頃でした。
リリース作業後、あとはAppleの審査結果を待つだけ
　※1. 昔はAndroidの審査は無かった
　※2. 昔はApoleの審査は数日から１週間かかることも。。

ところが、ストアリリース前日にApoleからリジェクトをくらう。。
リジェクト内容は約１年前にApple公式に開発者向けにアナウンスされていた対応をしていなかったことが原因。

顧客にすぐに報告し、すぐにアプリ側の対応を行いました。
次にAppleへ超特急モードのアプリ申請を行い、リリース予定日から１日くらい遅れてリリースしました。。
（App Reviewの優先審査リクエスト[request an expedited app review]に該当するはず）

 このしくじりポイントは、<font color="Red">Apple公式のアナウンスを全く把握していなかったこと</font>ですね。。
 スマフォエンジニアとして非常にダサいし、恥ずかしい。。

 # まとめ
 リリース作業で大事なことは以下
 ・リリース作業の手順書やチェック表は大事
 ・ダブルチェックも勿論実施する
 ・使用しているサービスの公式アナウンスは必ず把握しておくこと

 Appleからリジェクトを食らい、いろんな意味で大目玉をくらってから10年くらい経ちます。
 あれから開発者向けのAndroidの公式アナウンス、Appleの公式アナウンスはほぼ毎日のようにチェックするようになりました。
　Android公式：https://developer.android.com/news?hl=ja
 　Apple公式：https://developer.apple.com/jp/news/

未だにあの時のことを思い出すと穴に入りたくなることがあります。
そのため、未だに公式情報はこまめにチェックするようにしています。

以上
modern-screenshotで画質が低い時の対処法

## 対処法

第二引数のオプションに`quality`と`scale`を設定する。

- `quality`は最高品質の1.0に設定
- `scale`は求める画質に応じた値を設定

```js
const dataUrl = await domToPng(element, {
  quality: 1.0,
  scale: 2,
});
const link = document.createElement("a");
link.href = dataUrl;
link.download = filename;
link.click();
```

確認していませんが、domToJpegとかでも同様だと思います。
【Xcode】検索オプションについて

# はじめに
・Xcode15
・Mac OS：14.5 Sonoma

# 検索オプション

### 検索範囲
ナビゲーションエリアの虫眼鏡アイコンを選択し、
検索ボックスの下のプロジェクト名の部分を選択。
![スクリーンショット 2024-06-26 5.47.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/fa834d34-0628-e377-ab61-97507573ea90.png)

そうすると、検索範囲を選択することができます。
Custom Scopes.. を選択し、任意のディレクトリを検索範囲として指定することも可能。
![スクリーンショット 2024-06-26 5.49.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/66b214a3-6edf-357e-8a3e-f8dfdf4bc55d.png)

### 大文字と小文字の区別
Aa　がグレーアウトされている状態
→大文字と小文字を区別しないで検索
![スクリーンショット 2024-06-26 5.47.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/9b89e219-c539-6a30-c672-5425afc003a9.png)

Aa　を選択し、有効な状態
→大文字と小文字を区別して検索
![スクリーンショット 2024-06-26 5.53.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/4b94c46c-3c64-cf5a-c4a0-dfeace06812e.png)

### 検索対象・検索方法
![スクリーンショット 2024-06-26 5.47.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/b406fdd5-d1d2-ba8d-eef5-56d56bbb01f1.png)

![スクリーンショット 2024-06-26 5.56.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/cfbacb1b-2c09-766b-bbb2-bf2f382738b7.png)

・Text
　文字列検索

・Regular Expression
　正規表現

 ・Symbols
 　プロパティ名やクラス名、メソッド名などを対象に検索

 ・Ancestor Types
 ・Descendent Types
 　Protocl, Struct, Classなどを対象に検索し、かつ"Include Properties and Functions"を有効にすることでメソッド一覧を表示してくれる？
  　→ここは詳細が分かり次第あとで記事を更新します
   
:::note info
Apple公式のXcode15のRelease Noteを見てもイマイチ理解できず。。

https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes?changes=_6

 The Find navigator now offers additional symbolic queries that act on types, such as Find Ancestor Types and Find Conforming Types. These find operations replace the functionality of the Symbol navigator, and provide a stable set of results that change only when the query is re-executed. (105622182)
:::

・Call Hierarchy
　メソッド名やプロパティ名の依存関係
 
### 一致条件
![スクリーンショット 2024-06-26 5.59.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/569c9229-d5e8-3b31-09ee-929397fe4461.png)
![スクリーンショット 2024-06-26 5.59.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782130/35054e8e-1cec-fb60-44b8-41f28d29c045.png)

・Containing
　部分一致

・Matching Word
　完全一致

・Starting With
　前方一致

・Ending With
　後方一致

Text を選択することで、一致条件を指定することができる。

# 最後に
・意図した検索をする場合、必ず検索オプションをチェックする癖をつけよう！
課題（js_mdn）

お疲れ様です。

先日提出した、while文、for文を使って祝日を表示する課題は合格をいただきましたので、次の課題に取り組みます:fist:

MDN　https://developer.mozilla.org/ja/<br>を使って、自動で今日の日付を取得し、〇年〇月〇日となるように、 console.log を使って表示する関数を実装させるというものでした。
目標時間は1時間となっておりましたが、一度提出するも見落としがあって再提出となり、二度目の提出で合格しましたが2時間かかりました:sweat_smile:

![最終.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/9f81e0c3-1438-28a4-416f-fce5e8ccd32c.png)

![kekka .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/23ffe9fb-c9f9-f111-91cb-c2afee4b5322.png)
合格をいただいたコードがコメントアウトされていない方のコードです。

![mdn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/e0022056-bab0-c388-d836-b517cede388d.png)

そしてこちらが最初に書いて提出するも、再提出となったコードです。
何がいけなかったのかというと、 **「自動で今日の日付を取得していなかったから」** でした。よく読んでいない証拠です…

再提出となってから、改めてMDNにて「date」で調べた結果のページを上から読んでいましたが、結局最初に書いたコードに引っ張られ、 const today = new Date() を書いてから続かず、課題の質問ページへ行き、更にヒントを見て書き直しました…

![スクリーンショット 2024-06-26 223013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/ecc37ba6-fbf8-5798-e60d-3809a4fc0d40.png)


合格したコードの +1 の部分についてですが、
月が「0～11」を返すようになっているため、 +1 を書かないと5月になってしまいます。それを回避するための +1 ということでした。
課題とは関係ありませんが、配列で length を使う時も、一番始めにあるものを0番目としてカウントするというルールがあったことを思い出したので、Javascriptでコードを書く時には気をつけないとですね。

Date() … 関数として呼び出された場合、現在の時刻と日付の文字列表現を返す。
.getFullYear() … 地方時に基づき、指定された日時の年を返す。
.getMonth() … 地方時に基づき、指定された日時の月を返す。（0～11で返すので注意）
.getDate() … 地方時に基づき、指定された日時の日を返す。
「あ、private repo は操作できないんだ？」と思ったときに確認すべき箇所

:::note
コンテキスト
- GitHub App の installation token を利用して org 配下のリポジトリを操作している
- 適切な権限を付与している（つもり）にもかかわらずうまくいかない:
  -  public repo は操作できる
  -  private repo は操作できない
:::

## 結論から言うと

「public repo は操作できるが private repo は操作できない」ように見えるときには、おそらく下記のいずれかに該当しているので一つずつ見直すとよい。

- a. 適切なトークンを生成できていない
- b. 権限を付与できていない
- c. トークンを利用できていない


いずれも基本的な事項なので大丈夫と思いがちだが、取り組んでいるタスクが、public repo に対しては特別な権限が不要なタスク（例:「issue 作成」）であった場合、原因特定が遅れてしまうことがある。
というのも、上記 `a`~`c` のいずれかに失敗していた場合、権限獲得はまったくできていないにもかかわらず、public repo に対してだけは操作が可能であるため、「この操作は public repo に対しては可能だが private repo では可能なのかもしれない」と勘違いしてしまうからだ。要注意。

## 状況例

- やりたいこと: あるリポジトリの GitHub Actions から、organization 配下の別リポジトリに issue を作る

```
organization
├── issue-creator-repo
├── target-public-repo
└── target-private-repo
```

`issue-create-repo` から、`target-public-repo` および `target-private-repo` に issue を作りたい

- 確認済みの事項:
  - organization の GitHub App に付与している権限: `repo:issue` の 'write' 権限
  - インストール先: `all repositories`

## 見落としパターン 1: 生成しているトークンが全リポジトリ操作用になっていない

[`actions/create-github-app-token`](https://github.com/actions/create-github-app-token) を利用している場合には ["Create a token for multiple repositories in the current owner's installation"](https://github.com/actions/create-github-app-token?tab=readme-ov-file#create-a-token-for-all-repositories-in-the-current-owners-installation) に該当

```yml
on: [issues]

jobs:
  hello-world:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/create-github-app-token@v1
        id: app-token
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.PRIVATE_KEY }}
          owner: ${{ github.repository_owner }}   # この行を忘れていると、生成されるトークンは全く役に立たない
      - uses: peter-evans/create-or-update-comment@v3
        with:
          token: ${{ steps.app-token.outputs.token }}
          issue-number: ${{ github.event.issue.number }}
          body: "Hello, World!"
```

全く役に立たないトークンを使った場合にも public repo だけは操作できているように見えるので気づくのが遅れることがある。

## 見落としパターン 2: 実際に必要な権限を把握できていない

GitHub CLI を使っていると起こりがち

```yml
      - uses: actions/create-github-app-token@v1
        id: generate_token
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.PRIVATE_KEY }}
          owner: ${{ github.repository_owner }}

      - run: |
          # 実は背後で repository.defaultBranchRef の GraphQL クエリが実行されるため `repo:contents` の read 権限が必要
          gh issue create \
          --repo rindrics-sandbox-org/private-repo \
          --title foo \
          --body bar
        env:
          GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
```

実際にはトークンの権限が足りていないのだが public repo だけは操作できているように見えるので気づくのが遅れることがある。

## 見落としパターン 3: 権限を付与したつもりになっている

GitHub App の権限不足に気づき、画面から権限を追加した場合、権限の更新を「承認」する必要がある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235971/b12655d1-7526-3222-9900-a02d3e3b0202.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235971/c11d9a26-a046-4ac5-87b7-342a285e6b37.png)


実際にはトークンの権限が足りていないのだが public repo だけは操作できているように見えるので気づくのが遅れることがある。

---
気をつけましょう
【VSCode】タイトルバーにブランチ名を表示する方法

`window.title` の設定を変更することでタイトルバーにブランチ名を表示できます。

```jsonc:settings.json
"window.title": "{activeEditorMedium}${separator}${activeRepositoryBranchName}"
```

上記のように設定すると現在開いているファイルのパスとアクティブなブランチ名が表示されるようになります。

![スクリーンショット 2024-06-27 0.02.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/2033e564-94a3-c3ff-550f-a511c6a64efa.png)
Sequence Makerのコマンドモニター機能を試す

## はじめに
Sequence MakerはExcelから測定器を制御可能にするアドインです。Sequence Makerには通信コマンドのログを確認可能な「コマンドモニター」という機能があります。今回はコマンドモニターがどんな感じに表示されるのかを紹介したいと思います。Sequence Makerについての詳細は以下の記事を参照ください。

https://qiita.com/sequencemaker/items/8e6a370ab0a793a06a3b

:::note warn
***お断り***
本記事の内容はSequence Maker開発元の公式見解ではなく、あくまでも個人が趣味の範囲内で執筆しているものです。記事の内容について開発元へ問い合わせることはお控えください。ご質問・要望などは各記事のコメント欄へお願いいたします。
:::

## コマンドモニターの表示
コマンドモニターを表示するためにはツールにある「コマンドモニター」をクリックします。
専用のウィンドが立ち上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/1ea4e036-b035-d965-04a1-3a6f56825ce2.png)

## 使用例
今回は以下の記事で使用した通信コマンドの送受信ログを表示してみます。

https://qiita.com/sequencemaker/items/a92cdc47fcdad0ec5bd3

コマンドモニターを表示した状態で通信するとこんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/bc6e6282-58c4-4906-c9dd-55dfa50377dd.png)

コマンドモニターで表示される項目は以下の通りです。

- 年月日
- 時分秒
- インターフェイス設定番号（#1～#6）
- 送信（S）または受信（R）の識別記号
- 送受信したデータ

また、コマンドモニターのウィンドウ上で右クリックするとメニューが表示され、ログを保存したり選択したりクリアーしたりすることができます。保存はテキスト形式です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/3d625e81-e06c-ee54-4cc5-4a0a2c4ca2ca.png)

## 使いどころ
コマンドモニターはSequence Makerで送受信したデータが全て残るので、後から通信内容を解析したり、何かトラブルが発生したときに確認するためのログとして使用できます。

:::note warn
注意
コマンドモニターを表示中は、描画更新などの影響でSequence Makerの処理速度が低下します。速度を優先する場合は使用を控えた方が良いでしょう。
:::

## まとめ
今回はSequence Makerのコマンドモニター機能を紹介しました。コマンドログが手軽に見られるのは便利なので、特にシーケンスを作る際のデバッグなどには活躍すると思います。動作確認ができ、順調に稼働するようになったら非表示にするという使い方が良いかと思います。
modern-screenshotで画像が表示されない場合の対処法

## 状況
`modern-screenshot`を使って画像を生成すると、imgタグの画像が表示されずに画像が生成されてしまう。

### 動作環境
iOS 17.5.1 / Google Chrome

## 結論
画像を生成する前に、何度か画像を生成する。
```js
// 何度か画像を生成する
await domToPng(element);
await domToPng(element);

const dataUrl = await domToPng(element);
const link = document.createElement("a");
link.href = dataUrl;
link.download = filename;
link.click();
```

## 説明
`modern-screenshot`は、ブラウザ環境次第で画像の読み込みを待たずに画像を生成してしまう場合があるようです。
そのため、画像を生成する前に何度か画像を生成することで、内部的に画像がキャッシュされて？画像を読み込むことができるようになります。

自身の場合は、予め一度だけ画像を生成することで画像が表示できるようになりました。

## 備考
画像が表示されない問題は、こちらのIssueで議論されています👇
今回の対処法はこちらに上がっていたものです。

https://github.com/bubkoo/html-to-image/issues/361#issuecomment-1402537176

issue自体は`html-to-image`のものですが、`modern-screenshot`が`html-to-image`のforkなので同様の問題だと思われます。
JavaScriptの単項プラス演算子を知らなかったので笑えなかった人

## 背景

twitterで以下のコードを見た。

```js
('b' + 'a' + + 'a' + 'a').toLowerCase()
> "banana"
```

あ～NaNが関わってるやつね～！わはは！
JavaScriptあるある～！あはは！あは...ん？え？なんで？(疑問)

## 調査

JavaScriptは少し知っているので、NaNが関係しているジョークだとは理解できたが、真ん中あたりのプラスが NaN に置き換わるとした場合、何故 `bananaa`(aが2つ)を返さないのか？

と疑問に思ったため、Chromeで実際に実行してみた。

結果、以下のように `+ ‘a’` の部分が丸々 `NaN` に置き換わり、文字列化して `‘baNaNa’.toLowerCase()` という出力だと理解できた。

```js
+'a'
> NaN
```

では、なぜ +‘a‘ が NaN になるのか？
調べてみると、JavaScriptには単項プラス演算子、というものが存在するようだ。
5年くらい業務で書いていたが全く知らなかった。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Unary_plus

用途は数値変換用。文字列でも変換可能なら数値に変換するとのことだが、数値に変換できない場合はNaNが返る。

```js
+'12345'
> 12345 // 数値に変換してくれる

+'test'
> NaN // 数値に変換できないので NaN が返ってくる
```

単項プラスの優先度は加算より高いため先に処理される。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Operator_precedence

## 結論

単項プラス演算子を知っていれば笑うことができたネタだった。
一つ賢くなった。わっはっは。

```js
('b' + 'a' + + 'a' + 'a').toLowerCase()
-> ('b' + 'a' + NaN + 'a').toLowerCase()
-> ('baNaNa').toLowerCase()
-> 'banana'
```

## 引用元

twitter.com/ryanels4/status/1805439977557225648?s=46&t=Ts9q1dl1k6E85syc_FvwxQ

## 参考文献

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Unary_plus
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Operator_precedence
Mac AWS CLIコマンドを実行できるようにする

## 概要

MacのローカルにてAWSのCLIコマンドを実行できるようにする方法を簡単にまとめる。

## 前提

筆者のMacのローカルのパッケージはHome Brewを使っている。

## 方法

1. 下記を実行してAWS CLIコマンドをインストール

    ```sh
    brew install awscli
    ```

1. `$ aws -h`を実行して下記のように出たら完了

    ```
    $ aws -h
    
    usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
    To see help text, you can run:
    
      aws help
      aws <command> help
      aws <command> <subcommand> help
    
    aws: error: the following arguments are required: command
    ```
Sequence MakerでCO2濃度を測定する

## はじめに
Sequence MakerはExcelから測定器を制御可能にするアドインです。この記事ではSequence Makerからシリアル通信でCO2濃度を測定する方法を解説します。測定器はIODATA製の高精度CO2センサー「UD-CO2S」を使用します。Sequence Makerについての詳細は以下の記事を参照ください。

https://qiita.com/sequencemaker/items/8e6a370ab0a793a06a3b

:::note warn
***お断り***
本記事の内容はSequence Maker開発元の公式見解ではなく、あくまでも個人が趣味の範囲内で執筆しているものです。記事の内容について開発元へ問い合わせることはお控えください。ご質問・要望などは各記事のコメント欄へお願いいたします。
:::

## IODATA製の高精度CO2センサー「UD-CO2S」
UD-CO2Sは高精度なCO2センサーでUSB通信機能を備えています。本来はWindowsの専用アプリを使用してCO2濃度や温度、湿度などを表示可能なのですが、USBは仮想COMポート（シリアル通信）として認識するので、Sequence Makerから値を取得することも可能です。ただし、残念ながら2023年8月に生産終了とのことで、現在は入手困難です。メルカリかヤフオクなどにたまに出品されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/1de7bbc1-90ea-f50e-39d6-36a60d02e2d0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/73027415-760a-c781-9696-a26800082735.png)

（https://www.iodata.jp/product/tsushin/iot/ud-co2s/　より引用）

## 通信確認
### デバイス認識
まずはパソコンにUSB接続してみると「USBシリアルデバイス」として認識します。今回はCOM4でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/0cd4768d-35b3-ee24-825a-00edfc94189b.png)

### シリアルポートの設定
| 設定 | 値 |
|:-:|:-:|
| スピード  | 115200bps  |
| データ  | 8bit  |
| パリティ  | none  |
| ストップビット  | 1bit  |
| フロー制御  | none  |

### 制御方法

| 制御 | コマンド |
|:-:|:-:|
| 測定開始  | STA  |
| 測定終了  | STP  |

測定を開始すると2秒ごとに以下のようなデータが送られてきます。
左からCO2濃度、湿度、温度です。

```
CO2=2701,HUM=56.3,TMP=28.1
```

### Tera Termで確認
途中で息を吹きかけたらCO2濃度が急上昇しました。
```
OK STA
CO2=1182,HUM=52.9,TMP=29.2
CO2=1183,HUM=53.0,TMP=29.2
CO2=1183,HUM=53.0,TMP=29.2
CO2=1183,HUM=53.0,TMP=29.2
CO2=1183,HUM=52.9,TMP=29.2
CO2=1218,HUM=57.4,TMP=29.2
CO2=1270,HUM=66.7,TMP=29.2
CO2=1389,HUM=74.4,TMP=29.3
CO2=1709,HUM=82.5,TMP=29.2
CO2=3362,HUM=86.5,TMP=29.3
CO2=7951,HUM=90.5,TMP=29.4
CO2=13648,HUM=92.3,TMP=29.4
CO2=17392,HUM=93.1,TMP=29.5
CO2=16658,HUM=93.6,TMP=29.4
STP
OK STP
```

## Sequence Makerで測定
### インターフェイス設定
インターフェイス #1でCOM4を選択し、以下のように設定します。スピードだけデフォルト値から変更する必要があるので注意してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/3c32b778-f875-eded-b8a8-6c4bf2c0cd04.png)

### コマンド準備
Excelのワークシートにコマンドを記載していきます。
まずは測定開始のコマンド（STA）を入れ、その後は「UD-CO2S」側から勝手にデータを送ってくるので、受信動作だけをします。Sequence Makerでは受信動作を
```
#READ?
```
と書くだけでOKです。
しばらく受信を続け、最後に測定終了のコマンド（STP）を入れます。

### 測定
STAを選択し、「コマンド送受信」ボタンを押します。
測定が開始し、2秒ごとに送られてくるデータが受信できました。
なお、データはコンマ区切りなので、オプションから「コンマとセミコロンで分割」にチェックを入れておくと、別々のセルに入っていい感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/8e9aa204-6235-f712-9eca-eeaf9d0ecb93.png)

### まとめ
今回はSequence Makerからシリアル通信でCO2濃度を測定する方法を解説しました。シリアル通信のためのプログラミングをしなくても、コマンドを書くだけでデータが取れるのは嬉しいですね。データはExcelのセルに入ってくるので、あとは数値の切り出しをして、グラフ化するなり統計処理するなり自由に加工可能です。
Claude 3.5 Sonnet で遊んでみた

# 事前準備

公式サイトから
https://www.anthropic.com/news/claude-3-family

「Try Claude 3」ボタンを押して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/70157767-bd9c-eb0e-9e0f-443b4841ca21.png)

かっちょいい画面でお出迎えされるので、もう一回「Try Claude」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/d32170a4-85a2-b856-491f-86820850a38c.png)

アドレスを入力して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/1ecef8ba-5e38-3d20-f3fe-ef4abb34bcb4.png)

こんな画面になるのでメールを確認します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/6a036b32-dae3-e674-b1f5-b7bd640ded74.png)

メールに記載のURLで、電話番号認証画面が表示されるので入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/74f54a72-999d-ec22-ac11-40d9672acffe.png)

SMSで受信した番号を入力すると
こんにちは！となるので、名前を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/d58f04a3-4065-02b3-be08-4d6d967460a5.png)

この後注意事項とかが出てくるので、順次同意します。
すると出てきました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/595aa56a-5942-e673-589a-343942fc51a2.png)

誤字ってますが、画面が切り替わって日本語になりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/079018f8-fc0c-ab49-aa54-835544156f99.png)

# 早速遊んでみる

※注意
無料枠には限りがあるようでした！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/8f79b3fe-557a-891d-288b-e098eb744023.png)

具体的な上限値が見つからなかったのですが、ロックされるようです。
（情報見つけ次第更新します！）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/2c1f2daa-7b5d-cbd7-67be-dccb19e57bb9.png)

## 画像で質問

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/b26662e3-6e9b-7ca5-8b53-d57d9582ecc9.png)

おおー！！

## ゲームを作ってみる

ホームに戻ります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/74db8cb3-4f25-8f0a-5f5e-55ee9298f5fa.png)

Artifactsの「Try it out」リンクを押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/ff689abb-0884-3844-079d-6b8087e38345.png)

ONにして、上部の「×」で閉じる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/ad7bb5e7-d153-0a09-fcd9-10271cac9d3c.png)

ゲームを作ってと依頼すると、プログラムが出力された！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/5f99ce56-cc54-25a8-098b-6c72eafbb8e0.png)

今遊びたいんだ！と伝えると言語を変えて、コードが生成され、
自動的にプレビュー画面に切り替わりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/86cf55bd-7d60-ff93-a431-27fd5cd8041c.png)

## おまけ

### 説明読まない民代表の私

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/a39fe225-0472-c6cc-e880-150d6e8524aa.png)

### ボタンが見つからない私とAIさん

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/bbb5d507-5b23-1fbe-cda3-b398c28b8cd1.png)

# 感想

上限であまり遊べてないので、追加記事だします！
速度はめちゃくちゃ早くてびっくり！！

※Cursorで使用した際の記事はこちら
https://qiita.com/Jasmine_teeeeee/items/b443c90f37a10276ff53
共有ファイルサーバーでGit管理する！

お疲れ様です。

タイトルの通り、共有ファイルサーバでGit管理する方法を備忘として残しておきます。
権限の関係で、clone出来ない状況を経験したので、その場合の回避方法も記載します。（あくまで私の解決方法なので、すべての方に適応するとは限りませんので悪しからず）

※前提：Gitクライアントは各人のPCにインストールされていること
→[「git for windows」](https://gitforwindows.org/)入れましょう。

# その1
シンプルにbareリポジトリのみを作成。
プロジェクト開始時に誰かがbareリポジトリを以下手順で作成します。

リモート（中央）リポジトリとして管理したいディレクトリを「current/remote.git」とします。
リモートに乗せたいプロジェクトのディレクトリを「current/local」とします。

1. リモートリポジトリとするディレクトリに、bareリポジトリを作成
2. ReadMeをcommit、pushしておく
2. 第三者がcloneする
2. 終わり

```Bash
$ pwd
// current/remote.git
$ git init --share --bare // 中央リポジトリを作成
$ cd current/local
$ git init // リポジトリ作成
// ReadMe作成してコミットまで実行
$ touch ReadMe.md
$ git add .
$ git commit -m "first commit"
// localリポジトリからremoteリポジトリを設定しpush
$ git remote add origin current/remote.git
$ git push origin master
// 第三者がcloneする
$ git clone /current/remote.git
```

# その2
別の環境で同様の手順を試みたのですが、第三者がcloneする際にエラーにより実行できなかった時のやり方です。

中央リポジトリを「current/bare.git」
リモートに乗せたいプロジェクトのディレクトリを「current/nonbare」とします。
どちらも、ファイルサーバー上のパスになります。

1. ファイルサーバー上にnonbareリポジトリを作成
1. nonbareリポジトリに1commitしておく
1. ファイルサーバー上から、1で作成したnonbareリポジトリをbareリポジトリとしてclone
1. 以下同じ

```bash
$ pwd
// current/nonbare
$ git init
$ touch ReadMe.md
$ git add .
$ git commit -m "first commit"
$ pwd
// current/bare.git
$ git clone --bare current/nonbare
//　第三者がcloneする
$ git clone current/bare.git
```

その2の場合は、hooks作成して、bareリポジトリのmasterにpushされた時に自動で、nonbareにも更新を反映させられると後ほど（多分）便利だと感じる時が来ます。


# 終わりに
ざっと備忘を残しました。誤った認識の箇所あるかもしれませんが、運用は問題なく行えています。日々精進して、正しい構成が判明次第記事をブラッシュアップしていきます。
02_個人でツール作成、つまずいた言語選定

こんばんは、エルシアです。

# 前回の続き
https://qiita.com/ersia/items/0189e71c73c1b3704d83

前回の記事で、
個人でのツール作成で知識をつけたい
①家計簿
②ゲーム特化のタスク管理
という内容を書きました。
要は自分がほしいツールを実際に作ってみようというところです。



# 言語の選定どうしましょう
そもそも各言語の違いについて明確に答えられない。
大きく分割された場合やどこでどんな言語を使うことが向いているのかは調べたらわかりますが
各言語のメリット・デメリットまで、はっきりとしたことは私にはまだ語れません。

そのため、知識のないまま言語の選定を無理に行うのは現時点では厳しいと判断しました。


# 考えすぎても仕方なし、ひとまずWeb系
今回は、2点ともPCで扱える簡単なツールを作成しようと思っていました。
メインで遊ぶのが、PCでも遊べる系のゲームだということ、
スマホはアプリを開くまでの手順が面倒なのであまり好きではありません。
（お恥ずかしながらすっごい面倒くさがりです）

ですがWebで作成していくつもりは正直ありませんでした。
なぜならブラウザ上で動かすアプリにする想定をしていなかったからです。
が、今回は大きなプロジェクトというわけでもありません。
それであれば、色々と言語をつまんで勉強するということもできる、と思いました。
そのため一つのツールでフロントエンド・バックエンドどちらも学べるWEB系のほうが
より効率的に全体を見据えて構築できるのではないかと考えました。

# Web系言語、どれを選ぶか
今回必要なのは、問答無用でHTML・CSS・JS・Javaあたりでしょうか。
どちらもローカルで設定書き出ししたものを再読み込み、という手順でサーバーに負担を食わせたくないという理由があるので、PHPは使わないと思われます。


# キミに決めた！
①家計簿
HTML/CSS/Javascript/Java/Python※
フレームワークについては悩み中。
※ここはJavaのみにするべきかと思いましたが。
　Pythonを併用して家計簿の見返しをする際に、
　データ比較ができそうであれば、導入してみようかと思っています。

②ゲーム特化のタスク管理
HTML/CSS/Javascript/Ruby or Java
フレームワークについては①と同じく悩み中。

興味があるフレームワーク：
React：画面デザインしながら出来るのがサクサク開発できそうで良いと思いました
Vue.js：案件が豊富と見たので触ってみたいと思いました（安直）

# 欲しい機能は書いた。今日はここまで
どちらのツールも私がいろいろなスマホアプリを利用して、
この機能がほしい、これはいらない、これはやりづらいなど感じていたため
ほな自分で作ろか、という勢いで作ろうと思ったツールです。
ほかにもゲーム特化で作られているものはありましたが、使いづらくて・・・。

次回は実際に書いている欲しい機能について記載していこうと思っています。
ここまでお読み頂きありがとうございました。エルシアでした！
CheapSMMPanelでソーシャルメディアの存在感を高めましょう

![ewph35h1cjdxfho3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824946/8bd95ea4-de21-ba9f-ac21-1c19ba62b0c2.jpeg)

今日のデジタル時代では、ソーシャル メディアでの存在感を高めることは、個人にとっても企業にとっても不可欠です。ブランドのリーチを拡大したい場合も、フォロワーを増やしたい場合も、エンゲージメントを強化したい場合も、適切なツールがあれば成功に大きく影響します。ここで CheapSMMPanel の出番です。

CheapSMMPanel とは?

CheapSMMPanel は、ソーシャル メディア プロファイルを高めるためにカスタマイズされた幅広いサービスを提供する総合ソーシャル メディア マーケティング プラットフォームです。フォロワー数の増加から投稿へのいいねやコメントの獲得まで、CheapSMMPanel はコスト効率が高く効率的なソリューションを提供し、ソーシャル メディアのあらゆるニーズに対応します。

高品質のサービス
CheapSMMPanel の際立った特徴の 1 つは、品質へのこだわりです。偽のアカウントや非アクティブなアカウントを提供するプラットフォームとは異なり、CheapSMMPanel はすべてのフォロワー、いいね、コメントが本物のアクティブなプロファイルからのものであることを保証します。これにより、数が増えるだけでなく、ターゲット ユーザー内でのエンゲージメントと信頼性も高まります。

手頃な価格
その名の通り、CheapSMMPanel はさまざまな予算に適した競争力のある価格のパッケージを提供しています。スタートアップ、中小企業、大企業のいずれであっても、サービス品質を犠牲にすることなく、財務上の制約に合ったパッケージを見つけることができます。この手頃な価格により、ソーシャル メディアでの存在感を高めたいと考えているすべての人が利用できます。

ユーザー フレンドリーなインターフェイス
直感的なインターフェイスのおかげで、CheapSMMPanel の操作は簡単です。ソーシャル メディア マーケティングの初心者でも経験豊富なユーザーでも、このプラットフォームは簡単に操作できます。CheapSMMPanel は、プラットフォームの機能を最大限に活用できるように、包括的なガイドとカスタマー サポートも提供しています。

信頼性の高いカスタマー サポート
CheapSMMPanel は、信頼性の高い 24 時間年中無休のカスタマー サポートで顧客満足度を最優先しています。お問い合わせがある場合、問題が発生した場合、またはアカウントに関するサポートが必要な場合でも、専任のサポート チームがタイムリーなソリューションと専門家のガイダンスを提供します。

幅広いサービス
CheapSMMPanel は、Facebook、Instagram、Twitter、YouTube など、さまざまなソーシャル メディア プラットフォームに対応しています。この汎用性により、複数のチャネルでオンライン プレゼンスを強化したいと考えている企業や個人にとって、幅広い選択肢となります。

https://cheapsmmpanel.io/
初心者から見たVue3コンポーネントの実装のしやすさについて Vision.10

# Vue3コンポーネントの実装のしやすさについて Vision.10
Vue3のコンポーネントの実装について、前回はVue3コンポーネントの詳細から、
一方向のデータフローについて、まとめました。

前回：一方向のデータフロー

https://qiita.com/babel_0101/items/2b1a5b72d973343540c8

今回は、propsのバリデーションを以下にまとめます。
## Vue3のコンポーネントの詳細6
公式ページ：[propsのバリデーション](https://ja.vuejs.org/guide/components/props#prop-validation)を読み進めながら、以下のように解釈。

### propsのバリデーション(入力値検証)

一方向のデータフローで記述した通り、コンポーネントではpropsに対する<br>オブジェクトの仕様を定義できます。仕様通りのオブジェクトを指定しない場合<br>propsはバリデーションエラーと扱われ、VueがブラウザーのJavaScriptコンソールで<br>エラーを発します。<br><br>他の人に使ってもらうことを想定したコンポーネントを開発する場合<br>開発者同士のコミュニケーションに寄らず、プログラム側で子コンポーネントへ<br>連携できる値を、一定程度制御できる点が便利です。

propsのバリデーションを指定するには、文字列の配列の代わりに<br>defineProps()を用いてバリデーション仕様を定義したオブジェクトを指定した例が<br>以下になります。

変更点も無かったので、公式ページのコードを抜粋

```typescript:
defineProps({
  // 基本的な型チェック
  // （`null` 値と `undefined` 値は、任意の型を許可します）
  propA: Number,
  // 複数の型の可能性
  propB: [String, Number],
  // 必須の文字列
  propC: {
    type: String,
    required: true
  },
  // 必須だが null になる可能性がある文字列
  propD: {
    type: [String, null],
    required: true
  },
  // デフォルト値を持つ数値
  propE: {
    type: Number,
    default: 100
  },
  // デフォルト値を持つオブジェクト
  propF: {
    type: Object,
    // オブジェクトと配列のデフォルトは、ファクトリー関数を使って
    // 返す必要があります。ファクトリー関数は、コンポーネントが
    // 受け取った未加工の props を引数として受け取ります。
    default(rawProps) {
      return { message: 'hello' }
    }
  },
  // カスタムのバリデーター関数
  // 3.4 以降、全てのpropsが第2引数として渡されます
  propG: {
    validator(value, props) {
      // 値が以下の文字列のいずれかに一致する必要がある
      return ['success', 'warning', 'danger'].includes(value)
    }
  },
  // デフォルト値を持つ関数
  propH: {
    type: Function,
    // オブジェクトや配列のデフォルトと異なり、これは
    // ファクトリー関数ではなく、デフォルト値として機能する関数です
    default() {
      return 'Default function'
    }
  }
})
```
:::note info
TIP
defineProps() の引数の中のコードは、コンパイル時に式全体が外側の<br>関数スコープに移されるため、`<script setup>`内で宣言している他の<br>変数にアクセスできません
:::

### その他の詳細

- required: true が指定されていない限り、propsは**任意項目**です。
- Boolean以外の任意項目のpropsは、値が指定されないと **undefined**値になります。
- Booleanのprops は、値が指定されないと**false**に変換されます。<br>これは`default`を設定すると変更できます。<br>例えば`default: undefined`とすると、非真偽値のpropsとして振る舞います。
- `default`値を設定すると、propsの値がundefinedの場合に初期値として使用されます。propsが指定されなかった場合と、明示的にundefined値が渡された場合も該当します。

#### 開発ビルド時
開発ビルドを使用する場合、propsのバリデーションでエラーになると<br>Vueがコンソールにエラー内容を出力します。

#### 型のみのprops宣言
[型のみのprops宣言](https://ja.vuejs.org/api/sfc-script-setup.html#type-only-props-emit-declarations)を使用する場合、Vueは型アノテーションに基づいて<br>同等のランタイムprops宣言へのコンパイルをベストエフォートで試みます。<br><br>例えば<br>`defineProps<{ msg: string }>`<br>は<br>`{ msg: { type: String, required: true }}`<br>にコンパイルされます。
【UE5】C++ の Tick 内でキー入力判定する方法のメモ

# はじめに
簡単な機能を試したいときなどに、自分でトリガーする手段としてキー入力で判定したかったのでそれのメモ。
今回は例として Y キーをアサインしているが、ここにあるものから自由にアサインできるので参考までに。
ここであげるコードは Tick メソッド内に実装して、動作確認している。

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/InputCore/EKeys

# 押した瞬間の 1 回のみを判定する
```C++
if (GetWorld()->GetFirstPlayerController()->WasInputKeyJustPressed(EKeys::Y)) {
    UE_LOG(LogTemp, Warning, TEXT("Y key is pressed"));
}
```
## 動作ログ
押した瞬間だけ反応し、長押ししようが関係なく 1 回のみ。
```log
LogTemp: Warning: Y key is pressed
```


# 離した瞬間の 1 回のみを判定する
```c++
if (GetWorld()->GetFirstPlayerController()->WasInputKeyJustReleased(EKeys::Y)) {
    UE_LOG(LogTemp, Warning, TEXT("Y key is released"));
}
```
## 動作ログ
離した瞬間だけ反応し 1 回のみ。
```log
LogTemp: Warning: Y key is released
```

 
# 押している間ずっと true 判定する
```c++
if (GetWorld()->GetFirstPlayerController()->IsInputKeyDown(EKeys::Y)) {
    UE_LOG(LogTemp, Warning, TEXT("Y key is pressed"));
}
```
## 動作ログ
押している間ずっと true 判定がでている。(Tick で回る周期で出力)
離した瞬間が分かりやすいように released も仕込んである
```log
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is pressed
LogTemp: Warning: Y key is released
```

# Documents

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/InputCore/EKeys

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/GameFramework/APlayerController/WasInputKeyJustPressed

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/GameFramework/APlayerController/WasInputKeyJustReleased

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/GameFramework/APlayerController/IsInputKeyDown
Git Hooksのpre-commitが動かない

# はじめに
Git Hooksのpre-commitの設定時、うまく動かなかった時の対処方法をまとめました。

# pre-commitとは
「pre-commit」はGit Hooksの一種で、コミットが実際に行われる前に自動的に実行されるスクリプトです。
このhookを使用すれば、コミット時に、コードのチェックを行ったり、特定のファイルをコミット対象から外したりなど、自動で検証を行うことができます。

# pre-commitが動かない時の確認事項
### pre-commitファイルの実行権限
pre-commitに実行権限が付与されていないと動かないので、以下のコマンドで実行権限を付与します
```
chmod +x pre-commit
```

### configファイルの確認
.git/config　の中身を確認して、hooksPathで設定しているパスにpre-commitがあるか確認
```
[core]
	hooksPath = .git/hooks/
```

### コミットプロセスの確認
--no-verify オプションを使用すると、設定しているhookをスキップしてコミットを行います。
このオプションが設定されていないか確認してください。
```
git commit -m "message" --no-verify
```

# 最後に
以上の確認を行って、正しくpre-commitが起動したら幸いです。
Windowsに入れたVSCodeでコーディングして、DockerでGoを動かす方法

## はじめに

以下の教材に取り組む際、Windowsでcurlコマンドを実行しようとするとオプションを変える必要があったりとストレスを感じ、Dockerで開発環境を作成しました。その際の設定を簡単に記録しておきます。

https://techbookfest.org/product/jXDAEU1dR53kbZkgtDm9zx?productVariantID=dvjtgpjw8VDTXNqKaanTVi

## 環境

- Windows10
- Docker Desktop：26.1.1

## ディレクトリ構成

```shell-session
project
├ src
│ ├ Dockerfile
│ ├ go.mod
│ └ main.go
└ compose.yaml
```

## 各ファイル

### Dockerfile

最低限の構成です。将来的にデータベースを入れるのでイメージはGoではなくUbuntuにしています。

主に使いたいのはcurl, gitで、確認用にvim, tree, lsofを入れています。

```Dockerfile:Dockerfile
FROM ubuntu:22.04

RUN apt update && \
	apt install -y golang-go

RUN apt install -y curl git vim tree lsof
```

### compose.yaml

WindowsのVSCodeで開発をし、それを即コンテナに反映させるためバインドマウントしています。

```yaml:compose.yaml
services:
  app:
    container_name: my-go-api
    build:
      dockerfile: src/Dockerfile
      context: .
    tty: true
    volumes:
      - type: bind
        source: ./src
        target: /src
    ports:
      - '18001:8080'
```

:::note
ファイル名は「docker-compose.yml」ではなく「compose.yaml」が推奨されているようです。
また、compose.yamlにバージョンを書く必要もないそうです。
:::

### main.go

動作確認用に簡単なmain.goファイルを作っておきます。

```go
package main

import "fmt"

func main() {
	fmt.Println("Hello, world!")
}
```

## 動作確認

### 起動

```bash
docker compose up --detach
```

:::note warn
Dockerfileを修正した場合は、イメージを作り直す必要があるので`$ docker-compose up --build --detach`しましょう
:::


### 起動確認

```shell-session
docker compose ls
NAME                STATUS              CONFIG FILES
myapi               running(1)          {前略}\project\compose.yaml
```

### main.go実行

まずコンテナに入ります。

```bash
docker container exec `
--interactive `
--tty `
my-go-api `
bash
```

:::note warn
Shellの場合はバックスラッシュ`\`で改行してください
:::

https://qiita.com/wsigma21/items/008aa3e1636f245811c5

一応Goが入っているか確認します。

```shell-session
# go version
go version go1.18.1 linux/amd64
```

main.goを実行します。

```shell-session
# cd src
# go run main.go
Hello, world!
```

## おわりに

このあと教材のサンプルコードに従ってmain.goを作成し、curlコマンドを実行したところ上手くいきました。

## 参考

https://zenn.dev/suzuki_hoge/books/2022-03-docker-practice-8ae36c33424b59

https://qiita.com/m-tmatma/items/3477e2a107c20a33e6f1