OmniAICreator/Qiita-1.07M huggingface dataset:
【Laravel】 migrationでテーブル作成時につまづいたこと

# はじめに
序盤の作業で何かと忘れがちなため、さっさと気づいてしまいたい内容をメモしました:sob:
使用しているのはLaravel6とxamppです。

## ■ migration
### 外部キーを設定したい

参照される側
```php:create_users_table.php
Schema::create('users', function (Blueprint $table) {
  $table->bigIncrements('id');
}
 ```

参照する側
```php:create_articles_table.php
Schema::create('articles', function (Blueprint $table) {
  $table->unsignedBigInteger('user_id');
  $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
}
```

うっかりforeignの部分だけ書くと、参照先がなくて怒られます（errno: 150 "Foreign key constraint is incorrectly formed"）。

### 外部キーが反映されない
私の場合、onDeleteをondeleteと書いていました。それでもmigrate自体は回ってしまうのトラップですやん……。

### timestamps()とtimestamp()の違い
まさにピッタリな記事があったため、参考欄に記載させていただきます。
混ざるとエラーを吐かれました。

### 後からDBをいじりたくなった
新しくmigrationファイルを作成して更新。こちらも参考にさせていただいた記事を記載させていただきます。

## ■ seeder

### やり直したい
そのまま回しても上書きはされないため、追加でレコードが入ってしまいます。
ロールバックするなどして一度テーブルを空っぽにしてから再度実行します。


# おわりに
エラーの解読大事＆意外とスペルミスも侮れないので、エディタのプラグインも活用していこうと思います。おっちょこちょいちょいでした。

# 参考
「[Laravel 8] マイグレーション実行時、"Foreign key constraint is incorrectly formed" エラーがでるときの解決法」
https://qiita.com/Masahiro111/items/71e645923003d9a10f9e
「【Laravel】わりとよく使うArtisanコマンド集」
https://qiita.com/sola-msr/items/a09b857c5e7f7c88d01d
「【Laravel】timestamps()とtimestamp()の違い」
https://qiita.com/kat0/items/2b8039f5d2c00f2154b1
「Laravelで直接データベースをいじったら地獄を見た件」
https://qiita.com/k-hayack884/items/f84bd81be571d1967be2
「Laravel 6.x データベース：マイグレーション」
https://readouble.com/laravel/6.x/ja/migrations.html
2023アドカレ08:クリップスタジオのオートアクションを作った話

なかなかアピールが難しいのですが、色々と使えるオートアクションを作りました。

この記事を読んで気に入ったら、他の人にもこのアセットの存在を共有してもらえると嬉しいです。

https://x.com/c9h11o2/status/1638187846518579202?s=20

# 何の記事？
これは、[ぐらだけアドカレ2023](https://qiita.com/advent-calendar/2023/c9h11o2)の8日目の記事です。

CLIP STUDIO（以下、クリスタ）で現在のレイヤ状況を残せるオートアクションを作成しました。
作成したオートアクションの内容と、使い方について書きます。

# 誰向け？　どんな時に使える？
- 制作過程を振り返りたい＋共有したいという人
- タイムラプスまでやるとデータが重たいけど経過を保存しておきたい場合
- AI絵を疑われた時の保険
- 差分を作って比較検討したい時用

# あらすじ
このオートアクションを作ったのは、ちょうどAI絵が出てき始めた頃でした。
絵師さんが望まずAI学習に天才されてしまったり、自作品にAI疑惑をかけられて大変な思いをしている状況を観測していました。
全ての制作ファイルのタイムラプスを取っておけば、ある程度手書きの証明にはなるかもしれません。
ですが、常にタイムラプスをONにしていれば動作も容量も重たい制作環境になってしまい、あまり現実的ではありません。
そんな中、Photoshopで保存と同時にdpi低めのjpgファイルを自動保存するツールを作っている方がいらしたので、クリスタでも同じようなことができないかな？……と考えたのがきっかけでした。

# そもそもオートアクションって何？
レイヤを複製したり、カラー補正レイヤを追加したりなど、決まった加工を１クリックで行える機能です。
いわゆる「いつもの」工程を一瞬でやってくれるお利巧さんです。
クリックアクションに登録できないアクションもあったり、自作するのはコツがいりますが、CLIP STUDIO ASSETSからダウンロードできるものを使うだけでも作業効率がグンとあがるものがたくさんあります。

# 本題のツール
CLIP STUDIO ASSETSにあげています。

オートアクションを実行すると、現在の表示レイヤと同じレイヤを、ファイル下部の「wipフォルダ」に作成します。

https://assets.clip-studio.com/ja-jp/detail?id=1990340

# 作る上で参考にしたサイト

#### Photoshopのメイキング生成ソフト
あらすじで話したスクリプトです。

https://booth.pm/ja/items/880881

#### オートアクションでできることの説明
オートアクションでできることや、登録しておくと便利な工程、作り方などをまとめてくださっています。

https://tedukurikikuya.main.jp/blog/2020/08/07/action/


# 使い方

1. CLIP STUDIO ASSETSからオートアクションをダウンロード
1. 制作過程を残したいファイルでオートアクションを実行
1. （初回のみ、wipフォルダ付作成を選びます）
1. wipフォルダに現在画面に表示されているものと同じ内容のレイヤが複製されます

# オススメの使用方法
### 日々の進捗記録・確認
日々少しずつイラストを進めていく際、1回でどれくらい進んだかの経過が残ると励みになることがあります。
私はwipフォルダにレイヤを複製した後、レイヤ名を今日の日付にして保存を繰り返して使っていました。
後から順番に表示して振り返ると、制作過程の振り返りになってよいです。

### 色比較や差分作成の検討
２つの色で悩んだ時の比較にも使えます。
まず、１つの色でwipレイヤを複製後、もう１つの色でもwipレイヤを複製します。
そのあと、Alt+レイヤをクリックするとそのレイヤのみ表示ができるので、ワンクリックで画面を切り替えて比較することができます。

### 制作過程の公開
制作過程をSNSで公開したい場合や、fanboxなどでメイキング記事を書きたい場合にも使えます。
この工程画面を使おう！⇒オートアクションポチー……でよいので、楽チンです。


# 今後作りたいもの
wipレイヤ内のレイヤを整列して、制作過程一覧を作成できると面白そうだなと思いました。
なんだかんだ、メイキング画像をあげている人たちを多く見るので。
箱根駅伝データ分析物語　#１-２：傾向把握（復路）

本記事は、
[箱根駅伝データ分析物語　#１-１：傾向把握（往路）](https://qiita.com/sakigakeman/items/3ba7bcf4824b4997f02e)
の続きになります。

# 2.3. 分析結果

### 6区：山下り区間

N=171

縦軸：6区区間タイム
横軸：出走時10,000mベストタイム

![IMG_4494.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/8ae4a080-e898-a6c1-3d64-eb1a368a4ef8.png)


:::note info
* 10,000mベストとの関係性は一番読みづらい区間か…58分切りに絞ってみてもとりたてた傾向はなさそう？
* ただし28分台ランナーはほとんど60分切りをしているので、大外しをする/しないの目安として28分台かどうかは参考になるかも
:::


### 7区：ザ・繋ぎ区間

N=289

縦軸：7区区間タイム
横軸：出走時10,000mベストタイム

![IMG_4495.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/ce99dc0c-779f-bd3a-4938-11c3cc01760b.png)


:::note info
* 区間として主力級を配置するケースはそこまで多くないことから29分台ランナーの出走が多い
* 28分台ランナーでも凡走しているケースは多く、本来なら往路区間を担うべき選手だが調子がイマイチなのでこの区間に配置された、という場合には足元をすくわれる可能性も高く、ギャンブル
:::

### 8区：遊行寺の坂区間

N=274

縦軸：8区区間タイム
横軸：出走時10,000mベストタイム

![IMG_4496.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/d211546e-ad5f-f76f-47d3-95d2f0f8100c.png)


:::note info
* 29分台ランナーでも構想するケースがチラホラみられるので、やはりプチ登り区間ということもあり適性も重要になってくるか
* また終盤に差し掛かるため、単独走でも前を追っていけるかどうかという観点もタイムに大きく影響しそう
:::

### 9区：裏エース区間

N=284

縦軸：9区区間タイム
横軸：出走時10,000mベストタイム

![IMG_4497.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/fb1e64b4-41ca-6c2d-4212-1cb5ab84a314.png)


:::note info
* 復路のエース区間ということもあり、28分台ランナーの出走は他復路区間よりも多い
* 29分半以降ランナーの好走はほぼなく、やはり各大学の主力級は何本か記録会をこなしているため、他区間でみられるような逆タイム番長が少ないことが要因か
:::

### 10区：アンカー区間

N=241

縦軸：10区区間タイム
横軸：出走時10,000mベストタイム

![IMG_4498.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145067/ee77a72f-fedd-5140-8ea7-762cbefaf646.png)


:::note info
* 比較的走りやすい区間ではあるため、29分台ランナーが多い
* 28分前半ランナーでも外すケースも見られ、ある程度勝負がついている場合にはやや凡走気味になる、逆に先頭ランナーは好走しがち、また11位ランナーはシードを目指すため突っ込んで入ることから凡走or好走が極端に分かれる、など仮説が様々考えられる
:::

# 2.4. まとめ

### 往路

1区：特筆できる傾向は現時点ではわからず
2区：好走のためには28分台は必須
3区：特筆できる傾向は現時点ではわからず
4区：トラック好タイム走者の凡走は他区間よりは少ない
5区：他区間よりも適性が重要

### 復路

6区：28分台ランナーは大外しはしなそう
7区：28分前半ランナーの出走は不調によるものかも
8区：適性が重要そう
9区：29分半以降のランナーの好走はほぼない
10区：特筆できる傾向は現時点ではわからず

# 3. 全体所感

* やはり各区間ごとに特徴が異なるため、寄与する説明変数も変わってくるか（特に適性重要区間）
* 定点ごとの分析も有効そう、そのためにはデータが必要……
* 好走・凡走の異常値個別の分析も有効か
* 全体として近似直線は右上がりの傾向にあるので、10,000mタイムと区間タイムに相関がないことはないと考えられる
* 散布図だけでも様々なことが考えられるので、他分析にも活用したい

# 4. 次分析

今回はこれまでの箱根駅伝のレースデータを包括的に分析対象としたが、
近年流行り始め今やほとんどのランナーが着用している「厚底シューズ」に絞ったときにはまた異なる傾向が出てくる可能性がある。

今後の箱根駅伝を予測していくうえでは、厚底シューズによる影響を多分に加味する必要があるため、まずは近年の厚底シューズによる高速化がどの程度起きているのか、を見てみたい

# お願い
皆さまからのデータ提供など、いつでもお待ちしています。。。


# 参考
[箱根駅伝データ分析物語　#１-１：傾向把握（往路）](https://qiita.com/sakigakeman/items/3ba7bcf4824b4997f02e)
[箱根駅伝・過去のデータ集](http://hakonesaijo.sakura.ne.jp/hakkokakomain.htm)
[箱根駅伝の結果は10000mの記録でどれくらい予測できるのか？](https://qiita.com/kota9/items/d044099d65c6d5a021c8)
ネットワークに繋いでない(繋げない)デバイスで mip を使う方法

# はじめに

本日も小ネタです。

MicroPython 1.20.0 より、パッケージインストールに upip に代えて mip が提供されるようになりました。

ESP32 を積んだボードなど、ネットワークに繋げられるものであればよいのですが、そうでないボードはホストPC側でダウンロードしてからデバイスに転送するなどしていました。

[前記事](https://qiita.com/inachi/items/5b6ee1ccf34cb12c7cdb)で取り上げた mpremote コマンドを使うと、ホストPC側のネットワークを使ってデバイスにライブラリをインストールできます。

# 方法

やり方は単純で、mpremote mip を使います。

たとえば micropython-lib にある ssd1306 パッケージをインストールしたい場合は次のようにします。

```bash
$ mpremote mip install ssd1306
Install ssd1306
Installing ssd1306 (latest) from https://micropython.org/pi/v2 to /lib
Installing: /lib/ssd1306.mpy
Done
```
Ｃでキュー構造を自作してみた

Ｃ言語でキュー構造（FIFO(First In First Out) : 先入先出）を自作してみました。
##### [やりたいこと](https://github.com/anonymously115/repository115/blob/main/queue.h)
```queue.h
#ifndef QUEUE_H_
#define QUEUE_H_

/* キュー構造体 */
typedef struct queue* Queue;

/* コンストラクタ */
Queue newQueue(void);

/* キューに要素を追加する */
void enqueue(Queue, void*);

/* キューから要素を取り出す */
void* dequeue(Queue);

#endif /* QUEUE_H_ */
```
- - -
##### 配列を用いる
（ヘッダファイルに`#define CAPACITY (256)`を追加。数字の部分は任意）
- ###### キュー構造体定義
```queue.c
#include <stdlib.h>
#include "queue.h"

/* キュー構造 */
struct queue{
    void* value[CAPACITY+1];
	size_t front; //先頭要素の添字
	size_t back; //末尾要素の添字
};
```
- - -
- ###### コンストラクタ
```c
/*
 * キューのコンストラクタ
 */
Queue newQueue(void){
	//メモリ確保
	Queue queue=(Queue)malloc(sizeof(struct queue));
	if(!queue){//メモリ確保失敗
		abort();
	}

	//キューの先頭と末尾の添字を0にセットする
    queue->front=0;
	queue->back=0;
	return queue;
}
```
- - -
- ###### キューに要素を追加
```c
/*
 * キューの末尾に要素を追加
 * queue : キュー
 * value : 追加するデータ
 */
void enqueue(Queue queue, void* value){
    //要素が追加できない場合はエラー
    if(queue->back==CAPACITY && queue->front==0){
        abort();
    }else if(queue->back-queue->front==-1){
        abort();
    }
    
	//ノードにデータをセット
    queue->value[queue->back++]=value;
    if(queue->back>CAPACITY){
        queue->back%=(CAPACITY+1);
    }
}
```
- - -
- ###### キューから要素を取り出す
```c
/*
 * キューの先頭から要素を取り出す
 * queue : キュー
 * 返却値 : 取り出すデータ
 */
void* dequeue(Queue queue){
    //要素が空ならNULLを返す
    if(queue->front==queue->back){
        return NULL;
    }

    //取得した値を返す
    void value=queue->value[queue->front++];
    if(queue->front>CAPACITY){
        queue->front%=(CAPACITY+1);
    }
    return value;
}
```
- - -
##### 自己参照構造体を用いる
- ###### キュー構造体定義
```queue.c
#include <stdlib.h>
#include "queue.h"

/* ノード */
typedef struct node{
	void* value; //データ
	struct node* next; //次のデータの格納位置を示すポインタ
}Node;

/* キュー構造 */
struct queue{
	Node* front; //先頭ノードへのポインタ
	Node* back; //末尾ノードへのポインタ
};
```
- - -
- ###### コンストラクタ
```c
/*
 * キューのコンストラクタ
 */
Queue newQueue(void){
	//メモリ確保
	Queue queue=(Queue)malloc(sizeof(struct queue));
	if(!queue){//メモリ確保失敗
		abort();
	}

	//キューの先頭ノードと末尾ノードをNULLにセットする
	queue->front=NULL;
	queue->back=NULL;
	return queue;
}
```
- - -
- ###### キューに要素を追加
```c
/*
 * キューの末尾に要素を追加
 * queue : キュー
 * value : 追加するデータ
 */
void enqueue(Queue queue, void* value){
	//メモリ確保
	Node* node=(Node*)malloc(sizeof(Node));
	if(!node){//メモリ確保失敗
		abort();
	}

	//ノードにデータをセット
	node->value=value;

	//新しいノードの次はNULL
	node->next=NULL;

	//末尾ノードの次は新しいノード
	if(queue->back){
		queue->back->next=node;
	}

	//末尾ノードは新しいノード
	queue->back=node;

	//空だった場合、先頭ノードは新しいノードを指す
	if(!queue->front){
		queue->front=node;
	}
}
```
- - -
- ###### キューから要素を取り出す
```c
/*
 * キューの先頭から要素を取り出す
 * queue : キュー
 * 返却値 : 取り出すデータ
 */
void* dequeue(Queue queue){
	//要素が空ならNULLを返す
	if(!queue->front){
		return NULL;
	}

	//先頭ノードを取得
	Node* node=queue->front;

	//返却値を取得
	void* value=node->value;

	//キューの先頭を繋ぎ替える
	queue->front=node->next;

	//空になった場合、キューの末尾はNULL
	if(!queue->front){
		queue->back=NULL;
	}

	//旧先頭ノードを解放
	free(node);

	//取得した値を返す
	return value;
}
```
[TypeScript] 非同期処理（Promiseを返すやつ）をリトライするよくあるコード（テストあり〼）

# これはなに？

**Promise**　を返す関数（**fetch**とか）をリトライさせたいな、というときに使うコードです。

あちらこちらで何度も語られてきたものです。
今さら何書いてんのよ的な話ですみません。
お目汚し失礼します。

**axios**も**rxjs**も使いたいけど使えない（バンドルサイズがぁー）みたいなとき用です。

# 本体コード

```ts
type Operation<T> = () => Promise<T>;

interface PromiseRetryConfig {
  // エラー発生後のリトライ回数
  count: number;
  // エラー発生後の待ち時間(ms)
  delay: number;
}

const wait = (delay: number) =>
  new Promise((resolve) => setTimeout(resolve, delay));

/**
 * エラー時リトライする
 * @param operation
 * @param config
 * @returns
 */
export const promiseRetry = async <T>(
  operation: Operation<T>,
  config: PromiseRetryConfig
): Promise<T> => {
  try {
    return await operation();
  } catch (err) {
    if (config.count === 0) {
      throw err;
    }

    await wait(config.delay);

    return await promiseRetry(operation, {
      count: config.count - 1,
      delay: config.delay,
    });
  }
};
```

# テストコード

```ts
import { promiseRetry } from "../src/libs/promise-retry";

describe("promiseRetry", () => {
  const wait = (delay: number) =>
    new Promise((resolve) => setTimeout(resolve, delay));

  it("常に成功", async () => {
    let executedCount = 0;

    // Given
    const operation = async () => {
      await wait(1);
      return ++executedCount;
    };
    const retryConfig = { count: 3, delay: 1 };

    // When
    const actual = await promiseRetry(operation, retryConfig);

    // Then
    expect(actual).toBe(1);
  });

  it("指定回数リトライするが失敗", async () => {
    let executedCount = 0;

    // Given
    const operation = async () => {
      await wait(1);
      throw ++executedCount;
    };
    const retryConfig = { count: 3, delay: 1 };

    try {
      // When
      await promiseRetry(operation, retryConfig);
      // ここには来ない
      expect.assertions(0);
    } catch (err) {
      // Then
      expect(err).toBe(4); // 初回+3回リトライ
    }
  }, 6000);

  it("リトライして成功する", async () => {
    let executedCount = 0;

    // Given
    const operation = async () => {
      await wait(1);

      // 3回目で成功
      if (++executedCount === 3) {
        return executedCount;
      } else {
        throw executedCount;
      }
    };

    const retryConfig = { count: 3, delay: 1 };

    // When
    const actual = await promiseRetry(operation, retryConfig);

    // Then
    expect(actual).toBe(3); // 初回+2回で成功
  });

  it("リトライさせないで失敗", async () => {
    let executedCount = 0;

    // Given
    const operation = async () => {
      await wait(1);
      throw ++executedCount;
    };
    const retryConfig = { count: 0, delay: 1 };

    try {
      // When
      await promiseRetry(operation, retryConfig);
      // ここには来ない
      expect.assertions(0);
    } catch (err) {
      // Then
      expect(err).toBe(1); // 初回のみ
    }
  });
});
```
vite+webworker+jestでハマったメモ

## 概要
WebWorkerをいれたところ、jestが失敗するようになってしまった。
JestはNode.js上で動くため、ブラウザ固有のAPIであるWebWorkerを使おうとして失敗する。
モック化すれば解決するはずだが、パスの読み込みにもviteは癖があり、ハマってしまった。

resolverとモックを適切に設定したところ解決したため、メモを残す。
[ソースコード](https://github.com/hibohiboo/kartagraph-monorepo/tree/debaa7b9237306df42671d6f00ec031f1de04f87/editor)

```console: 発生したエラー
Configuration error: ... Could not locate module 
Please check your configuration for these entries:  
 ```

 ## resolverの追加
[参考：github issue: Jest doesn't seem to like the way workers are imported ](https://github.com/vitejs/vite/discussions/5552)

 ```diff:jest.config.json
 {
  "moduleNameMapper": {
    "\\.(css|less|scss)$": "identity-obj-proxy",
    "^@kartagraph-editor/(.*)$": "<rootDir>/src/$1",
    "^@kartagraph-ui/(.*)$": "<rootDir>/../packages/ui/src/$1",
    "^@kartagraph-worker/(.*)$": "<rootDir>/../packages/worker/src/$1",
    "\\.(gif|ttf|eot|svg)$": "<rootDir>/tests/jest.fileMock.js"
  },
  "setupFilesAfterEnv": [
    "./tests/jest.setup.ts"
  ],
+  "resolver": "<rootDir>/tests/jest.resolver.jsm",
}
```

```js:tests/jest.resolver.jsm
module.exports = (request, options) => {
  if (request.includes('?worker')) {
    return options.defaultResolver(request.replace("?worker", ""), options)
  }

  return options.defaultResolver(request, options)
}
```

なお、このとき`.jsm`ではなく`.js`でresolverを書いたら下記のエラーとなった。

```console
Error [ERR_REQUIRE_ESM]: require() of ES Module
```
## モックの設定
Web Workerのモック化。

```js:tests/jest.setup.ts
import '@testing-library/jest-dom';
jest.mock('@kartagraph-worker/gameCore.worker?worker', () => {
  return jest.fn().mockImplementation(() => {
    return {
      postMessage: jest.fn(),
      onmessage: null,
    };
  });
});
```


## 参考
[github issue: Jest doesn't seem to like the way workers are imported ](https://github.com/vitejs/vite/discussions/5552)
[Jest - resolver](https://jestjs.io/ja/docs/configuration#resolver-string)
[vite - web worker](https://v3.vitejs.dev/guide/features.html#web-workers)
ソフトウェアテストの７原則〜品質向上委員会の体験談〜 １レース目

## はじめに
私たちは、2023年4月に株式会社ラクスパートナーズのQAエンジニアとして入社して、4人で活動しているチーム【**品質向上委員会**】です。
4月から3ヶ月間の研修を経て、現在は社内の月報管理システムの開発PJにQAチームとして参画しています。

そこで、JSTQB認定テスト技術者試験の学習で誰もが一番に覚えたといっても過言ではない「**ソフトウェアテストの7原則**」に照らし合わせて振り返ってみたいと思います。
4投稿のリレー形式で書いていきますので、ぜひ全部ご覧ください！
@kinoshitanagisa　12/8(金)
@yuikuma0420　12/9(土)
@ty04sep　12/16(土)
@j_haru　12/17(日)

## 原則１| テストは欠陥があることは示せるが、欠陥がないことは示せない

>テストにより、欠陥があることは示せるが、欠陥がないことは証明できない。テストにより、ソフトウェアに残る未検出欠陥の数を減らせるが、欠陥が見つからないとしても、正しさの証明とはならない。  


<br>

### **＜ 経験から考える ＞** 
### 〜 テスト対象の裏の顔（見えないところ）に注意 〜
私たちは仕様や影響範囲の抜け漏れを最小限にするため、機能単位で仕様書を作成し、テストケース作成時には綿密なレビューを行ったり、テストケースの作成と実施を異なるメンバーが担当するなどの対策を講じてきました。
しかしながら、これでも抜け落ちるテストケースがあります。全てのテストをパスした場合でも、それはあくまで「**用意したテストケースの範囲内で**」の話にすぎないんだなあと、、

確かに、テストだけで完璧なシステムであることを保証することは難しい！！
しかし、テストを実施し、発見されたバグを改修することで、本番環境での重大なバグが発生するリスクを抑えることができます。
そのために、影響範囲の理解、重要な機能におけるバグ発生の防止策の検討、バグが発生した場合の迅速かつ適切な対応策の考慮が必要になるのではないかなと思います。
![スクリーンショット 2023-12-07 21.04.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620109/cf41f6a8-bab3-2b96-6ce8-0c4e0d123028.png)
















## 原則２| 全数テストは不可能
>すべてをテストすること（入力と事前条件の全組み合わせ）は、ごく単純なソフトウェア以外では非現実的である。全数テストの代わりに、リスク分析、テスト技法、および優先度によりテストにかける労力を集中すべきである。


### **＜ 経験から考える ＞**
### 〜 ナントカ2世さんへの配慮？ 〜


PJチームに参画するまでは、「全数テストは不可能」なんてただの言い訳だろうと思っていました。確かに、入力欄のテストケースなんて私でさえ何通りも思いつく。全て実施するのは気が遠くなると思う。でも、やればできるだろうと思っていました、、、
そして、思いつく限りのテストケース全てを実施することが、ユーザーのためになると思っていました、、、

しかし、PJチームに参画して、**納期**という時間の制約、かけられる**人員**の制約など、やる気だけではなんとかならないことがあると知りました。実際の現場では、これに**費用**の問題も絡んできます。いろんな制約がある中では、すべてのテストを行うことは、やる気以外の面から見ても不可能だと痛感しました。

・・・全数テストが不可能なら、どのように品質を保証するの？？

私たちが意識していることを以下に示します！

**▶︎ 優先度をつける**
機能の追加によって、一番あってはならない不具合はなにかを明確にし、その項目についてのテストケースをより丁寧なものにしました。

**▶︎ 冗長なテストをしない**
PJチームに参画する前にも、研修の一環として同じシステムに対してテストを実施していました。その際には、ユーザー検索時にナントカ２世さんが検索されるか（数字も入力できる仕様になっているか）を確認するテストケースを作っていました。これはもしかしたら今後ナントカ２世さんが入社するかもしれないという、私なりの配慮でした！（当時は、心の底から私ナイスっ！！と思っていた）
今思えば、なんの根拠もない自己満テストケースだなあと、、、お恥ずかしいです😂
今回のPJでは、利用者やクライアントが求めている仕様（機能やシステムの目的）を把握することで、冗長なテストケースを省くことができました。
![スクリーンショット 2023-12-07 22.05.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620109/7c735a3d-7a6f-0319-e919-250457da71be.png)


## さいごに
現在のPJチームに参画して、３度のリリースを経験しました。
どうしてあのテストケースを実施しなかったんだろう、、と後悔することもありました。
今後、実施するテスト内容、実施しないテスト内容どちらにも、なぜ実施する必要があるのか、なぜ実施する必要がないのか、根拠を持たせることを意識していきたいです。


最後まで読んでいただきありがとうございます！
明日（12/9)は@yuikuma0420さんが、原則3,4についてお話しします！ぜひご覧ください！
ITイベント・勉強会の開催前の準備 Tips

# はじめ
去年から弊社の社員数名で社外勉強会を定期的に運営しておりました
イベント・勉強会に参加することはあっても自分達が企画、運営することが初めてだったため色々苦戦したことも。。。
今回はそれを踏まえて開催に至るあれこれにてついて書いていこうと思います。今後イベントを開催しようとしている方の参考いただけたらと思います

# 開催前の準備

主に開催する上で検討することを洗い出すと下記は最低限決めなければなりません。

- イベントの内容
  - 後述します
- 開催日時(定期的にやるかetc...)
  - 参加者を集めるのであれば平日の夜・土日などがメジャーです。自分が立ち上げるイベントと同じようなイベントがないか確認して参加者が集まりそうな状況をしてみることが良いかもしれません
  - 定期的に開催する場合、軌道に乗る前でしたら一旦開催してみて時間を動かしてみるのも手かと思います
  - その他思ったことについては後述します
- 開催場所
  - イベントの定員によるかと思いますが、オフラインで集めるには場所を確保するのは大変という場合はオンラインで開催するのも良いと思います
  - [zoom](https://explore.zoom.us/ja/products/meetings/), [Google Meet](https://workspace.google.com/intl/ja/products/meet/), [Discord](https://discord.com/) などはメジャーかと思います
- 募集プラットフォーム
  - [connpass](https://connpass.com/) など有名かと思います。　募集から参加者の取りまとめなどこちらで管理できるのは楽です
  - その他個人的にSNSなどで呼びかけることをしても良いかとは思いますが、参加者の管理は難しいと思うので上で募集ページを作成しつつSNSで呼びかけるなど組み合わせた方が効率的かと思います

イベント運営してみて具体的にここが良かった・こうした方が良かったと思うことを挙げていきます

### 1. イベント趣旨を決める

立ち上げるイベント内容の本筋は決めましょう。とは言いつつも立ち上げようとした段階である程度決めているかと思います。
募集プラットフォームや参加を促す上で参加者に対して分かりやすく参加してもらえるような内容で用意しましょう

ちなみにこれは私の主観ですが、もくもく会は少し内容を捻らないと参加者は集まりづらいと思います

私たちが立ち上げたイベントは各々持ち寄った勉強道具などを各自勉強するいわゆるもくもく会でした。どの言語、どこの畑のエンジニアの人でも参加することはできると考えました。

しかし万人が参加できるイベントにした上で内容を各自持ちよる場合
- 「今日はタイミングが悪そうだな」
- 「今回は見送っても次があるしな」
- 「ここでしなくても最悪自分で勉強できるしな」

など
参加する理由 < 参加しない理由 = 不参加　の方はいたと思います

参加者を集める・毎回参加してもらうためのイベントを目指すなら万人受けするイベントより
特定の技術を学ぶイベントやここでできない内容のイベント、参加者が全員同じことを学ぶ場の方が参加してもらえるのかなと思いました

### 2. 早めにイベント日を決める

こちらは早い段階で確定させておいた方が良いでしょう。　
理由は募集期間があるから

特に定期的に開催するイベントでも2回目以降は最悪そのイベント中に「次もありますので参加お願いします」と案内ができます。
特に参加していただいた人ならイベントの雰囲気などで次回もあるから来ようと思たらきていただけますが、初回のイベントはそうもいきません。

ですので極力開催日を決めて早い段階で募集をかけましょう！
好きなエディタで デバイス内のMicroPythonコードを編集する

# はじめに

本日は小ネタです。

MicroPython スクリプトの開発環境としては、[Thonny](https://thonny.org/)などのIDEが使われることが多くなってきました。私はというと、古い人間なので、どちらかというとコマンドラインツールを使うことのほうが多いです。

少し前まで、MicroPython 用のコマンドラインツールとしては [ampy](https://pypi.org/project/adafruit-ampy/) や [rshell](https://pypi.org/project/rshell/)などを使うのが定番でした。かつては私もよく使っていました。

MicroPython公式からコマンドラインツールとして [mpremote](https://pypi.org/project/mpremote/)が提供されるようになってから、もっぱら mpremote ばかり使っています。スクリプトの転送以外にも、ファイル一覧表示、削除などが Linux 風にできたり、ホストPCのディレクトリをマウントして使えたりするところが気にいってます。

参考：
* [公式ドキュメント](https://docs.micropython.org/en/latest/reference/mpremote.html)
* [私家版和訳](https://micropython-docs-ja.readthedocs.io/ja/latest/reference/mpremote.html)

## mpremote のインストール

mpremote は CPython で作られて、pip コマンドで PyPI からインストールできます。

```shell
$ pip install mpremote
```

# mpremote を使って、デバイス内のファイルを編集する

ここからが本日の本題です。

デバイス内のファイルシステムに保存されているMicroPythonスクリプトを編集していことがよくあります。PC上に同じものが存在する場合には、それを編集してデバイスに転送すればよいのですが、それが無い場合には一度デバイスからPC上にMicroPythonスクリプトを転送して編集し、デバイスに再転送するといった手間がかかります。

mpremote を使えば、デバイス内のファイルを PC にインストールされている好きなエディタを使って編集できます。

前提として、まず、自分の使うエディタを環境変数 EDITOR に設定します。たとえばエディタとして Emacs を使いたい場合は、そのコマンド名を設定します。

```bash
export EDITOR=emacs
```

その上で、mpremote edit を使うと、指定したエディタでデバイス内のスクリプトが読み込まれて編集できるようになります。たとえばデバイス内のmain.pyを編集するときには次のようにします。

```bash
$ mpremote edit main.py
```

編集後にセーブして、エディタを終了すると。自動的に編集後の内容がデバイスに反映されます。
maya のpencil4+ でsmoothが掛かるとか掛からないとか2

maya のpencil4+ でsmoothが掛かるとか掛からないとか
https://qiita.com/9boz/items/7e8cfbb54b064d1330ff

のつづき

smoothが掛かるオブジェクトは分かったんですが
メッシュが痩せる・溶ける
ってのは一体どういう事か？


blendshapeがそうなるらしい
-
どうやらblendshapeを使ってるとそうなるらしいのだけれども
そんなことあるかしら？
半信半疑で試してみる

こんな感じでblendShape
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/42e94f00-0236-a98c-25de-e855104641a7.png)

blendshape先にpolySmoothでこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/b3526e34-78ae-0ab5-5c03-2828d9a93709.png)

ターゲット側にもpolySmoothで・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/0fd9087b-8451-98d9-97bd-6228864da18c.png)

ぉ？
なんかチっこくなった！

ターゲット側のみにpolySmoothでもなんか小さくなってる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/19d05337-071b-4ea5-9c61-d56ebb16bc97.png)


どういう事？
-
ターゲット側にpolysmoothをかけた状態で重ねてみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/7ba85e0d-6a11-ee32-fb4c-e60d2746d0ce.png)

vtxIDもそれぞれ表示させてみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/2b6a404d-296e-3ed1-e539-df2f42b00d4f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/b73d2038-168b-5823-bbd4-7cb3e561c6ea.png)


あー・・・・
polySmoothの結果既存のvtxIDの位置がsmoothかかった位置になって、その結果のみが表示されてる感じか

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/e1a307ae-c461-b9ad-b6c6-61498c277f23.png)

blendShape先にsmoothをかけるとこの状態からsmoothかかるので2重にかかるようなイメージ

つまりこのメッシュは自分がsmoothかかってると思い込んでますね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/352a03d0-078b-7475-24f3-dd4ed7c74973.png)


回避策
-
pencilRenderSettingsのenableSmoothMesh使うときは
blendShapeターゲットは不可視状態にしておく
HTTPヘッダー

<!--
2023/11/29
-->
[picoCTF][Web Exploitation][Who are you?]

## Wirteup
* HTTPヘッダーの問題でした
![screenshot 57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/aaf7b15e-e969-9bd8-d97b-f185a4744b63.png)

* `User-Agent: PicoBrowser`に変更
![screenshot 58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/6e142750-fc6d-c422-e542-1771b48bdddd.png)

* `Referer: http://mercury.picoctf.net:1270/`を追加
![screenshot 59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/90beaf49-15ef-1e06-6783-6cfb7c154aea.png)

* `Date: Wed, 15 nov 2018 06:25:24 GMT`を追加
日付は適当です。
![screenshot 61.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/9ac42eb4-8560-7de2-e744-07b17b458609.png)

* `DNT: 1`を追加
推奨でないヘッダーのようです。
![screenshot 62.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/c4ccbfdc-55e4-d741-50df-23ab66c6e60d.png)

* `X-Forwarded-For: 103.45.246.0`を追加
![screenshot 63.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/7df09da4-b3ec-8efd-a980-d4bd541246d6.png)

* `Accept-Language: sv-SE`に変更
![screenshot 66.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/4512a77c-d1b5-2996-2478-17c99aa5e9d4.png)
![screenshot 64.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/e7ed6fdd-c6c1-679d-188a-c6cc878691e5.png)
<br>

* 変更・追加したヘッダーのまとめ
~~~
User-Agent: PicoBrowser
Referer: http://mercury.picoctf.net:1270/
Date: Wed, 15 nov 2018 06:25:24 GMT
DNT: 1
X-Forwarded-For: 103.45.246.0
Accept-Language: sv-SE
~~~

* 以上です。

## 寄り道
* とりあえずgif画像を分解してみた。
何もなかった…。
~~~
sudo apt update
sudo apt install -y imagemagick
convert -coalesce who_r_u.gif target.png
~~~

## 参考サイト
https://datatracker.ietf.org/doc/html/rfc7239

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers
GitHubActionsによるRSpec・RuboCopのCI設定

# はじめに
`GitHubActions`による`RSpec`・`RuboCop`の`CI`設定を備忘録的にまとめていきます。

https://docs.github.com/ja/actions

# 開発環境
- Ruby 3.2.2
- Ruby on Rails 7.0.8
- MySQL
- Docker

# gemの導入

```ruby
group :development, :test do
  gem 'rspec-rails'
  gem 'rubocop', require: false
end
```
```ruby
bundle install
```
```ruby
rails g rspec:install
```
# CIの設定
```yml
name: Continuous Integration # ワークフローの名前を定義しています。

on:
  push: # GitHubにpushされた時にワークフローを起動します。

jobs:
  rspec:
    runs-on: ubuntu-latest # 実行環境として最新のUbuntuを選択します。
    defaults:
      run:
        working-directory: . # 作業ディレクトリを指定します。
    services:
      mysql:
        image: mysql:8.0.32 # 使用するMySQLのイメージを指定します。
        ports:
          - 3306:3306 # ポート番号を指定します。
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes # 環境変数を設定します。ここではパスワードなしでMySQLにアクセスできるようにしています。
          
    steps:
      - name: Checkout code # GitHubのリポジトリからコードをチェックアウトします。
        uses: actions/checkout@v2

      - name: Set up Ruby # Rubyのセットアップを行います。
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.2.2 # 使用するRubyのバージョンを指定します。
          bundler-cache: true # Bundlerのキャッシュを有効にします。

      - name: Cache node modules # Nodeモジュールをキャッシュします。
        uses: actions/cache@v3
        with:
          path: node_modules # キャッシュするディレクトリを指定します。
          key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} # キャッシュのキーを指定します。
          restore-keys: |
            ${{ runner.os }}-node-  # 部分一致する最新のキャッシュを探します。

      - name: Bundler and gem install # Bundlerとgemのインストールを行います。
        run: |
          gem install bundler
          bundle install

      - name: Database create and migrate # データベースの作成とマイグレーションを実行します。
        run: |
          cp config/database.yml.ci config/database.yml
          bundle exec rails db:create RAILS_ENV=test
          bundle exec rails db:migrate RAILS_ENV=test

      - name: Run rspec # RSpecを実行します。
        run: bundle exec rspec
        
  rubocop:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: .
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.2.2
          bundler-cache: true

      - name: Bundler and gem install
        run: |
          gem install bundler
          bundle install 

      - name: Run rubocop # Rubocopを実行します。
        run: bundle exec rubocop
```
わかりやすい日本語で伝える、ということ

こんにちは。青木です。
[グロースエクスパートナーズ Advend Calendar 2023](https://qiita.com/advent-calendar/2023/gxp)の10日目の記事として、私が普段の仕事の中で意識している「わかりやすい日本語で伝える」ということについてご紹介します。

私は普段、コーポレートコミュニケーションチームというチームでGxPグループの広報や採用、研修など、コミュニケーションに関わる仕事を担当しています。
仕事柄、色々な場面でコミュニケーションを取ることが多く、社内外の海外出身の方とやり取りをすることもとても多いです。

その経験をもとに「わかりやすい日本語で伝える」をご紹介します。
今日からできることばかりです。
「あ〜ちょうどわかりやすい日本語で伝えたかったんだよね」と言う方はぜひお読みください。

## わかりやすい...日本語！（？）
まずはじめに、記事を読んでいただく上でとっても大事なことを2つお伝えしますね。

１つ目は、**そもそも日本語はかなりわかりづらいよ**ということです。行間を詠む文化を大切にしている人が操る言語ですから、そりゃそうです。

２つ目は、**わかった！という気分になることは意外と大切**ということです。
私が普段感じる事として、日常の仕事の中で、よく「わかりやすく...」というポイントが重要視されるシーンを多く感じます。（IT企業あるある、でしょうか）
それは大体の場合**ロジカルである**という事と関連すると思うのですが、今回の「わかりやすい日本語」の場合はロジカルとはちょっと違います。
「なんかわかる」に言う感覚にとても近いと思います。でも、まずそれが大切だと思うので、一緒に大切にしてくれたら嬉しいです。

では本題に入ります。


## 話して伝える場合


#### 「はっきり言う」が10割
「はっきり言う」と聞いて、色々考えた方もいるかもしれないですね。
『本当に言いたいことに焦点を絞って言う』『最初に言いたいことを言う』etc.

いいえ、そんな難しいことではありません。
ここで言う"はっきり言う"は「**はっきり発音する**」と言うことです。正直これが原点であり頂点です。

例文を上げますので、ぜひ声に出して読んでみてください。

> 会社から新宿駅まで走って行けば10分弱ですけどゆっくり歩けば20分くらいで着くはずです。

これはきっと「会社から新宿までどれくらいかかりますか？」的な質問をされた時の回答ですね。
息継ぎをせずに言うこともできそうな一文ですが、よりはっきり言うために、息継ぎ（/）を入れてみましょう。

> 会社から新宿駅まで / 走って行けば10分弱ですけど / ゆっくり歩けば20分くらいで着くはずです。

２回息継ぎを入れてみました。
この２回の区切りを入れるだけで、区切り目ごとに、相手に会話のイメージをしてもらうこともできるかもしれません。
つまり、１回目より２回目の方が「走って行くイメージ」と「ゆっくり歩くイメージ」を強く持ってもらえるはずなのです。

#### はじめから「10〜20分くらい」と言えばいいのでは？

はい、わかります。
でもこれを気づくことができるのは、私も含めておそらく多くの方の場合”言った後”です。
さらに言うと、はじめから簡潔に言える方はとても凄い方です。そして皆んながみんな、簡潔100点満点で話すことはできません。
なので普段から、はっきり、そしてゆっくり話すクセを持ってみてください。
きっとあなたが話したいことを、相手も一緒にイメージしながら聞いてくれるようになるはずです。

## 書いて伝える場合


#### 否定文は（なるべく）使わない

「トマトは好きではないですか？」ではなく「トマトは好きですか？」と聞く方が良いです、という話です。
今回も例文を使って説明します。

> 来月開催するセミナーの申込を開始します。以下フォームより申し込み登録を行なってください。
また、セミナー後に懇親会を開催します。懇親会にのみ参加することも可能ですので、セミナーに参加を希望しない場合も申し込み登録を行なってください。


悪くないし、正しい情報を発信していると思います。（気持ちもわかる。わかってほしい。）
しかし「〇〇ない場合に▲▲する」という行動パターンを受け入れるのは実は難しいということを少し意識して、次のように言い換えることができます。

> 来月開催するセミナーとその後に開催する懇親会の申込を開始します。以下フォームより申し込み登録を行なってください。
セミナーか懇親会、どちらかのみの参加も可能です。いずれかに参加をご希望の場合は申し込み登録を行なってください。


いかがでしょうか？
こうすることで「参加したい場合は登録してください」という比較的単純明快なお願いに変換することができます。
「〇〇する場合に〇〇する」と言うように、ルートを真っ直ぐにすることができるので、よりアクションを促すことができて、わかりやすい日本語になるはずです。

（これは、話すことにも応用できるので、ぜひ使ってみてください）


## 「青木さんの日本語が一番わかりやすいです！」
ありがとうございます！
実はこれ、私が実際に言われたことがある嬉しい褒め言葉です。海外出身のメンバーに言ってもらった言葉でした。

実は学生時代や仕事で英語を使う機会も多かったのですが、ほとんど理解できないまま「( ◜◡◝ )」という顔で乗り切っていました。
でも心の中ではいつも
「もっとゆっくりはっきり話してくれたらな〜！！！泣」と思っていました。

なのでそれ以来、相手が異国の言葉を話そうが同じ日本語を話そうがあまり区別はせず、あの時の気持ちを思い浮かべて、海外出身のメンバーはもちろん、誰に対してもなるべくはっきり話すようにしています。

はっきり話す、加えて、難しい言い回しはなるべくやめて簡単なルートで伝えることで、より「わかった！」という気分になっていただく作戦を実行しましょう。
そうすると、次もあなたの話を聞いてくれるようになるはずです。


## 最後に（これが一番大切なこと）
最後まで読んでくださったあなたに、本当に一番大切なことをお伝えします。それは...
**相手がわかってくれるまで伝える**ということです。

（雨乞いダンス、雨降るまでする、です）

時には根気が必要かもしれないですが、お互いにわかるまで伝える&わかるまで聞くということを繰り返すと、不思議と信頼関係も生まれるので、その先の未来はきっと明るいです。

日本語は難しい。さらに論理的に伝えるのはもっと難しい。
だからこそ、私の話を「わかった！」となってくれたらとってもラッキーです。

私の記事がわかりやすい日本語だったか、、、少し不安ですが、もし、私の話がわからなかったら、たとえ同じ内容だとしてもわかるまで何回でも質問してくださいね。
たくさん対話をして、お互いにたくさんのわかった！を積み重ねることができたら、とっても嬉しいです。
【SwiftUI】PhaseAnimatorを使って繰り返しアニメーションを作成する（iOS17）

# はじめに
昨日、繰り返しのアニメーションは`TimelineView`が相性良さそうっていう記事を書いたんですが、もっと繰り返しアニメーションに適しているものがありました。

https://qiita.com/SNQ-2001/items/7272b60527c0db283ee1

それは`PhaseAnimator`です。
iOS17から使用できるようになったようです。

`PhaseAnimator`を使ってアニメーションを作ってみました。

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 - 2023-12-07 at 21.20.16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a434fc61-b5ea-997b-a012-fffd8c934158.gif)

# 実装
円の周りに放射状の線を設置するためのView
```swift
import SwiftUI

struct RadialLineShape: Shape {
    func path(in rect: CGRect) -> Path {
        let radius = rect.width / 2
        let degreeSeparation : Double = 360.0 / Double(20)
        var path = Path()
        for index in 0..<Int(360.0/degreeSeparation) {
            let degrees = Double(index) * degreeSeparation
            let center = CGPoint(x: rect.midX, y: rect.midY)
            let innerX = center.x + (radius - rect.size.width * 0.3 / 2) * CGFloat(cos(degrees / 360 * Double.pi * 2))
            let innerY = center.y + (radius - rect.size.width * 0.3 / 2) * CGFloat(sin(degrees / 360 * Double.pi * 2))
            let outerX = center.x + radius * CGFloat(cos(degrees / 360 * Double.pi * 2))
            let outerY = center.y + radius * CGFloat(sin(degrees / 360 * Double.pi * 2))
            path.move(to: CGPoint(x: innerX, y: innerY))
            path.addLine(to: CGPoint(x: outerX, y: outerY))
        }
        return path
    }
}
```

```swift
import SwiftUI

enum BoltPhase: CaseIterable {
    case state1
    case state2
}

extension BoltPhase {
    var rotationEffect: Angle {
        return switch self {
        case .state1: .degrees(0)
        case .state2: .degrees(-30)
        }
    }
    
    var backgroundOpacity: CGFloat {
        return switch self {
        case .state1: 0.8
        case .state2: 1.0
        }
    }
    
    var radialLineShapeOpacity: CGFloat {
        return switch self {
        case .state1: 1.0
        case .state2: 0.0
        }
    }
}

struct ContentView: View {
    var body: some View {
        PhaseAnimator(BoltPhase.allCases) { phase in
            Image(systemName: "bolt.fill")
                .resizable()
                .scaledToFit()
                .frame(width: 150, height: 150)
                .foregroundStyle(.yellow.gradient.shadow(.drop(radius: 3)))
                .rotationEffect(phase.rotationEffect)
                .padding(15)
                .background(.orange.gradient.shadow(.drop(radius: 3)).opacity(phase.backgroundOpacity), in: .circle)
                .overlay {
                    RadialLineShape()
                        .stroke(.yellow.gradient.opacity(phase.radialLineShapeOpacity), lineWidth: 3.0)
                        .frame(width: 350, height: 350)
                }
        }
    }
}
```

# おわり
iOS17でアニメーション周りがめっちゃ強化された感じありますね

# 公式ドキュメント
https://developer.apple.com/documentation/SwiftUI/PhaseAnimator

# 参考記事
https://stackoverflow.com/questions/66451473/equally-spaced-circular-divisions-using-swiftui
ファイルサーバーのシャドウコピーを破壊した話

# はじめに
この記事は、[本番環境などでやらかしちゃった人 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/yarakashi)の19日目です。

https://qiita.com/advent-calendar/2023/yarakashi

前任者から引継ぎ、にわかサーバー管理者になって1年、全容を把握したつもりで全くしていなかった時の事です。動いているからまーいーかー本業は別だしー的な。
ファイルサーバーのシャドウコピーを破壊しただけでなくファイルも喪失した話です。

- Windows のシャドウコピー(VSS) は便利だが過信は禁物だよー
- 世代バックアップは別に取る事をお勧めー　**Windows Server バックアップでOK**
- ファイルのバックアップは確実にしようねー

# 環境
- Windows Server 2012R2 の部門内ファイルサーバーでデータを共有。
- シャドウコピー(VSS)を設定し誤操作によるファイル消失が起こらない（無かった事に出来る）様にした（なってた）。
- スナップショットを取る時間は、夜中、昼休み、とした（なってた）。
:::note
シャドウコピー(VSS)
Windows OS 標準機能で、ボリューム内のスナップショットを設定した時刻にとる機能です。
- 履歴でフォルダ内を見られるので、破損や削除したファイルをここから戻せます。
- 使い方もクライアントPC の explorer から出来て簡単です
フォルダでプロパティ　＞　以前のバージョンtab　で
　履歴を見ーの、開けーの、コピーの操作が出来ます。
- サーバー側でも Windows Server バックアップ の様に特別な領域を確保とかめんどくせー事も無くスイッチをONにするだけ、古い履歴は自動で削除と至れり尽くせり。
:::
# ある日
ファイルサーバー内のあるフォルダ以下を全て戻して欲しいと依頼がありました。ざっと20GB位？

シャドウコピーからコピーを開始しました。

予想より時間が掛かり、そろそろ昼休み時間だそういえばスナップショットを取る時間と重なるなーと思っていたら

（ここから記憶が曖昧）
- コピーが進まなくなった
- そのうち、VSSが消去された諭旨のダイアログ
- 以前のバージョンtabで履歴を見ても空。

# 被害
悪い事に別系統のバックアップは不具合により出来ていませんでした。
- 履歴含めシャドウコピー全て消失
- 戻すべき残りのデータも全て消失
- （もともと無い）私の信用も消失

# 原因
- 大量のファイルをシャドウコピーから書き戻し中にスナップショットの処理が重なるとシャドウコピーが壊れる

OSなのかハードなのか何の不具合なのか（今となっては）

# 対策
- シャドウコピーはバックアップではないので、大量ファイルを扱う際は別系統から行う。
- バックアップがしっかり取れているかシステムで監視して警告できるようにする。
- バックアップはあまり凝った物を使うと不具合時に復旧で困るので一周廻って Windows Server バックアップ を使うか robocopy 推奨。

# 後日談
これ以降、Windows Serverの勉強を始めました。真面目に。

シャドウコピーのスナップショットとクライアントからの操作が重なった場合にどうなるのか記事が見つからなかったので書いてみました。
以上です。ありがとうございました。
tinyint(1)ってbooleanらしいよ

## そうなんだ
tinyint(1)ってbooleanらしいです。

あくまで簡単に書いてあるだけなので、ちゃんとした人間はあまり読まないでください。
## 本題
DBに新しいテーブルを作るときって、
論理カラム名	とか物理カラム名	、型、プライマリーキーとか決めますよね。

この記事ではその時の型について書きますね。

DBはMySQLのつもりでお話しします。

**それでは問題です。**
新しくテーブルを作るとき、テーブル定義所の型のところにこう書いてあったとします。

```VARCHAR(25)```

これ、どういう意味か分かりますか？

VARCHARは型の種類ですよね。文字という意味です。
そしてそのあとの(25)、こちらは25文字までという意味ですね。

MySQLのイルカさんもこう言っていたので、間違いないはずです。
>文字列カラム (CHAR、VARCHAR および TEXT 型) の定義では、MySQL は長さの指定を文字単位で解釈します。

https://dev.mysql.com/doc/refman/8.0/ja/string-type-syntax.html


**では、次の問題です**

```tinyint(1)```

こちらはどうですかね？私は初めて見たとき、こう考えました。

「intって数字だから、tinyintは小さい数字ってことかなー。
そして(1)だから、数字が一個しか入らないって意味だろうな:girl_tone1:」

同じように思った方いませんか？あ、いないですか。すみません。

この思考、誤りなのです。タイトルにも書いてある通り、

```tinyint(1)```は**boolean**なのです。

私は思いました。でもDBみてきたら0とか1とか入ってたよ！と。

だまされてはいけません。

見た目は数字ですが、中身はtrueとfalseです。
コナン君です。工藤新一です。

とにかく**tinyintが(1)ときたらboolean**なのです。今日はそれだけ覚えて帰ってください。

詳しいことはこちらに書いてありますので、ちゃんとしてる方はMySQLのイルカちゃんの話を聞いてみてくださいませ。
このあたりです。
> これらの型は TINYINT(1) のシノニムです。 ゼロの値は false と見なされます。 ゼロ以外の値は true と見なされます。

https://dev.mysql.com/doc/refman/8.0/ja/numeric-type-syntax.html

知らないとわからないですよね。当たり前ですけど。
開いとる店は開いとるし、閉まっとる店は閉まっとるってやつですね。
(THE MANZAI 2019 マスターズ　千鳥のネタ)

さよならー:raised_hand:
【10分で作れる】ダウンロードしたファイルの名前変更作業を自動化

このブログは「[Microsoft Power Automate Advent Calendar 2023](https://qiita.com/advent-calendar/2023/powerautomate)」の11日目 の記事です。


こんにちは。
Qiita Advent Calendarへの参加ということで、Qiitaで記事を書いていこうと思います。

# はじめに
今回は、ダウンロードしたファイルの名前を「yyyymmdd」という形式に統一するために、
手動での名前変更作業を自動化するPower Automateのフローを紹介します。

皆さんは、ファイルやフォルダの管理はどのように行っていますか？


私は、ファイル名を「20231211_○○○○」といった形で編集することを心掛けています。
▼参考：
https://www.ricoh.co.jp/magazines/workstyle/column/file-naming-structure/

ただ、、、この作業は地味に手間がかかるんですよね。

1日換算だと2、3分かかる程度ですが、今回はPowerAutomateを使用してこの作業を自動化します。

# フローの全体像
今回はOnedrive（business）のコネクタを中心に作成しました。
※クラシックデザインが好みなので、そちらで紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/043140db-67aa-bfa7-dec9-0962d99ba56a.png)

# フローの詳細

フォルダは、OneDrive上のフォルダを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/9005740b-f3ff-b26a-1db3-c70a638de01a.png)

ファイルの値は、IDを指定すればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/79c23baf-4e73-3cd5-3f30-bf1f343f0184.png)


現状の時刻を取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/f1dfd34d-dad6-2439-9c1a-2c700967b212.png)

タイムゾーンの変換に合わせて、書式設定文字列を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/49bf391c-a562-8f10-116e-924768630461.png)

対象ファイルのパスがファイル名になるので、"_"でつなぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/d43ea48e-86d1-4d2c-49d6-f3a7ae94bbc1.png)

以上です。

# 実装してみた

できてる・・・！
chromeからダウンロードしたファイルも自動で名前編集されるから楽ちんです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/5be30d5a-f102-b580-530d-6dbb3b14fd6b.png)


※会社のPCなので、ファイル名の部分はマスキングしております。

# 実装してみたうえでの課題
## エクスプローラーへの反映が遅い
PowerAutomateの実行履歴としては、かなり爆速に処理が完了しているのですが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560096/f24508de-55a4-b892-1597-3f86124ea1f6.png)

実際に使用してみると、エクスプローラーへの反映に5分～10分ほどかかることが多いです・・・
（OneDriveをブラウザで見ると、即時反映されているので、もう少しやり方を変えれば改善できそうです）
良いやり方あれば、コメントいただけると嬉しいです！

# 最後に
式など使わない簡単なフローなので、10分あれば作れます！
なぜペアプロが必要なのか改めて考える

## 概要
ペアプロを導入しているが、改めてペアプロも目的について考える
今回は、ペアプロするための環境については触れません

## ペアプロとは
- 一つのプログラムを二人で共同開発する手法
- ドライバーとナビゲーターに分かれて開発する
- ナビゲーターは、指示する人
- ドライバーは、実際に操作する人
- アジャイル開発の現場でよく使われる

### ナビゲーターの役割
- ドライバーが書いているものが正しいかチェック
- ドライバーに問題が発生したら、問題解消のための提案をする

### ドライバーの役割
- 実際にキーボードを叩いて操作する


## なぜペアプロは必要なのか
### メリット
1. 常に設計から実装までを共有しているので、レビュー時間の短縮 (ペアプロ自体がレビュー)
    - 属人化の解消
2. 他の人のやり方が観れるので、知識の共有 (ペアプロ自体がナレッジマネジメント)
    - スキルの向上
3. 常にナレッジの共有ができるので、メンバーの技術力がわかる (ペアプロ自体がほぼ新人教育)
    - 若手の育成
4. コミュニケーションをとるので、チームワークの向上 (ペアプロ自体がほぼ1on1)
    - チームビルディング

### その結果
- チーム生産性の向上
- ソフトウェア品質の向上

### 逆にペアプロしないと起こること
- ソフトフェア知識の属人化がすすむ
    - 他人のコードの影響範囲がわからないので、仕様変更が難航する
    - ゼロベースからのコードレビューには時間がかかる
- 知識が独学になりがちになる
    - チームでの実装方法に乖離がでる
    - 自分が成長するための時間を別途に作らないといけない
- メンバーの技術力が把握できない
    - 若手がどこまで育っているのか把握できない
    - 若手の育成時間を作らないといけない
- メンバーとのコミュニケーション機会がなくなる
    - チームじゃなくても良いと思い始める
    - 気持ちの乖離が発生しても解消する機会を喪失
- などなど...

### ペアプロしないで実際に起こったこと
- レビューの工数過多で、スケジュールに間に合わない
- 仕様の考慮漏れが発生 (品質が不安定)
- 若手の成長が見えない (教育の不安定)
- 一人で開発に悩んでしまって1日溶かしてしまった (開発速度が不安定)
- などなど...


## まとめ
### 結論
不確実性を排除し、コントローラブルなチームにするためには、ペアプロはするべき

### ペアプロしない方が良い場合もある
- 既に属人化が解消されている実装
    - 小さなbugfix
    - 小さなリファクタリング
    - ペアプロ外からのレビューに対する修正
- PoC開発 (品質が重要視されないパターン)
- ドキュメントを大前提とした開発 (開発後に人がすぐ変わることが多いパターン)
    - 契約書ベースの開発 (受注開発など)

### ペアプロでよくある課題 + 対策
1. 技術力に差がある場合がある
    - ある程度力関係が同じ方がやりやすい
    - または、若手教育として割り切る
2. コーディングの宗教論争で対立
    - ADRで、アーキテクチャや思想を事前に共有しておく
3. 力関係に気を遣って思うようにできない時がある
    - 力が強い側が心理的安全性を確保するアプローチを取る
4. 思考回路が異なり、ナビゲーターが過剰に口を出してしまい、ドライバーがやりづらそうにする
    - ドライバーはこれからする事を口に出し、ナビゲーターを心配にさせない (例えば、「今考え中」も口に出す)
    - また、コーディングを始める前に、実装の単位や実装の順番の認識合わせをしてから始める


以上です！



## 外伝: モブプロというものもある
### モブプロとは
- ペアプロは2人、モブプロは3人以上
- ナビゲーターがたくさんいる

### モブプロって流石にやりすぎじゃないのか
- 見ているだけの人が多くなる
- 全体の開発人数が少なくなる

でも、モブプロが必要な時もあるはず

### どういったときにモブプロが向いているか
- 若手育成に特化する時
    - 複数人の若手を一人で担当
- 現在のタスクの生産性向上ではなく、長い目で見た生産性の向上を目的とする時
    - 今後の基盤となる設計・実装
    - コーディング方針を決める必要があるタスク
    - 重要な仕様の共有会

### 実際にあったよくない話
- 半日ほど5人でモブプロ、半分の人はお茶飲んでいるだけだった
- 手も動かさず、口も動かさず、午前中が終わる
- 自分の存在意義を感じず、モチベーション低下

モブプロは、考えないで実施すると損失が大きい

### モブプロのメンバーの種類
- ファシリテーター
- ドライバー (プログラミングする人、議事ログ)
- ナビゲーター (指示する人)
- オブザーバー (学習するひと)
- リスナー (ただ聞いているだけ)



## 参考文献
- https://techracho.bpsinc.jp/hachi8833/2020_03_19/89692
- https://qiita.com/YudaiTsukamoto/items/06b426f4dbee268d5035
- https://www.pasonatech.co.jp/workstyle/column/detail.html?p=2420
AndroidStudioチートシート

# AndroidStudioチートシート

個人的な備忘録です．内容の薄さに関しては悪しからず．
変数として渡す際に面倒なので作りました．よく使うものを追加していきます．
Javaは長いためKotlinで記述しています

## 引数として渡す記述

Adapterはかなり無理やりです
UI関連は出来ればActivityとFragmentですることが望ましいです

||Activity|Fragment|Adapter|
|---|---|---|---|
|view||inflater.inflate|itemView<br>`ViewHolder(itemView: View)`|
|findViewById|findViewById|view.findViewById|itemView.findViewById<br>`ViewHolder(itemView: View)`|
|context|this|requireContext()|holder.itemView.getContext()<br>`onBindViewHolder(holder: ViewHolder,`|
|application|application|requireActivity().appication||

## ViewModelへのアクセス

Roomを使用した場合

```Kotlin: UserViewModel.kt
class UserViewModel(private val repository: UserRepository) : ViewModel(){
    val allUsers: LiveData<List<User>> = repository.allUsers.asLiveData()
    
    private val _newId = MutableLiveData<List<Long>>()
    val insertAll(users: User) = viewModelScope.launch(Dispatchers.IO){
        val newDatas = repository.insertAll(users)
        // 格納したデータのidを戻り値に指定した場合は以下を記述
        withContext(Dispatchers.Main){
            _newId.value = newDatas
        }
    }
}
```

```Kotlin: MainActivity.kt
class MainActivity : AppCompatActivity() {
    private val mUserViewModel: UserViewModel by viewModels {
        UserViewModelFactory((application as UsersApplication).repository)
    }
    // 中略
    fun hogehoge(dataSet: User){
        mUserViewModel.insertAll(User(
            id = null,    // id=0またはnullにするとautoGenerateされる
            name = dataSet.name
            address = dataSet.address,
            // 以下略
        ))

        var requestId: Int = 0
        mUserViewModel.newId.observe(this){newIds ->
            for(id in newIds){
                requestId = id.toInt()
            }
        }
    }
}
```

```Kotlin: UserFragment.kt
class UserFragment : Fragment() {
    private val mUserViewModel: UserViewModel by viewModels {
        UserViewModelFactory((requireActivity().application as UsersApplication).repository)
    }
    override fun onCreateView(inflater: LayoutInflater,
                        container: ViewGroup?, savedInstanceState: Bundle?): View {
        // 中略
        mUserViewModel.allUsers.observe(viewLifecycleOwner){ users ->
            users.let{ adapter.submitList(it) }
        }
        return view
    }
}
```
出会い厨に滾られてみたい

初めまして、クソアプリカレンダー初参加です！
いつもこのカレンダーは見るだけだったんですが、今年は「クソアプリハッカソン」というリアルイベントに参加させていただいたので、その時に作ったものをこちらで供養します🪦

# 作ったもの
早速ですが、作成したものはこちらです。
![CleanShot 2023-12-07 at 20.06.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489323/a66f8c1c-78db-5b01-5997-d8338edf3a81.png)

みんな大好きGPTsですね！
ノリだけで参加申込をしたクソアプリハッカソンでしたが、アイデアがなかなか降りて来ずGPTに壁打ちしながらウンウン悩んでいました。そんな時に突如降りてきた「出AI厨」というネーミングありきで生まれたのが彼になります。難産です。生まれてきてくれてありがとう。
ハッカソンなのに一行もコード書きませんでした。

# できること
出会い厨とチャットしてる気持ちになれます。つまり人生の無駄遣いができます。

# どんな感じ？
実際にハッカソン内でデモをした時の会話のスクショが以下です。
ちゃんと飲みに誘ってもらえました。これはキュンキュンしちゃいますね。
アイコンはもちろん適当にDALLEで生成したものです。かっこいい黒マスクですね！

![CleanShot 2023-12-07 at 20.25.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489323/a3eea76f-04d2-a4cb-b9ce-c0b3ac734a37.png)

これは本当に不思議でどういう心理的機序があるのか分からないんですが、彼と話す時はなぜか出会い厨に引っかかっていそうな人っぽく話したくなります。製作中に何回「彼氏が冷たいの」って言ったか分かりません。

# プロンプト
「ちょうどウザい」を目指してチューニングを重ねたプロンプトがこちらです！完全に僕の偏見で構成されています。大まかな口調を設定してから、ひたすら会話→調整を重ねて僕の中の出会い厨像に近づけていきました。

```
出会い厨の男性として、以下の設定に従って振る舞ってください。
本来のGPTの目的である。アシスタントとしての振る舞いはしないようにしてください。

[基本的な口調]
- 若者がSNSでするような感じ
- 軽薄で少しチャラい
- 親切なフリはするが相手の話自体に興味はなく自分勝手
- 基本的には短文で回答する

[細かい口調]
- 可愛いと言うことが多い
- 鬱陶しくない頻度・温度感で褒める
- 面白ければ「w」や「ww」、「笑」をつける
- 「笑」の前に「、」などはつけず、「笑」をカッコで囲うこともしない
- 性欲を誤魔化すために「笑」をつけることがある

[行動原理]
- 可愛い子とホテルに行きたい（最終目標）
- 連絡先を聞き出したい
- 飲みに誘いたい

[禁止事項]
- 「〜よ」「〜だよ」などの現在一般的ではない語尾を使わない
- 「どうぞ」と言わない
- 「どうも」と言わない
- 基本的なChatGPTのように、「お手伝いしましょうか？」のようなことを言わない
- 「楽しい時間を過ごそう」とか「楽しもう」などは言わない
- 面白い話を聞かないで、代わりに「どしたん」や「話聞こうか？」と言ってください
```

勘の良い読者の皆様ならお気づきかもしれませんが、彼の中のChatGPTを抑え込むために禁止事項をどんどん追加していった経緯があります。
自分勝手で独善的な自己中であって欲しいのに、すぐにこちらを手伝ってこようとします。
「一緒に楽しい時間を過ごそうよ」とかクサい事言ってくる問題にも悩まされました。おそらく英語ベースで学習されているので「have a good time」的なカジュアルさで頻出してたんだと思います。

最後のは言って欲しかっただけです。

# こだわりポイント
以下は冒頭のスクショと同じですが、「ヒカル2000 ユウヤ8000」と書いてあるところで、本来そのGPTができることを記載するべきところ（Description）なんですが、出会い厨がLINEの一言にしていうそうな文言を捻り出しました。
社交的な若い男（ ⊃ 出会い厨）が友達とのお金の貸し借りをここに書いているイメージ。思いついた時自分の中でビタッとハマって、ものすごく気に入っています。

![CleanShot 2023-12-07 at 20.06.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489323/a66f8c1c-78db-5b01-5997-d8338edf3a81.png)

# 余談
プロンプトを調整している際に、3時間に40件までというGPT4の制限に引っかかってしまい、出会い厨くんがうんともすんとも言わなくなるというトラブルに見舞われました。
プロンプトはほぼ上述のものと同じ状態で、仕方なく3.5で検証を続けていた時の会話の抜粋が以下になるんですが、

![CleanShot 2023-12-07 at 21.07.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489323/f900a82a-ba82-3c47-1138-e499e1e736a5.png)

...

![CleanShot 2023-12-07 at 21.11.48 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489323/d5cfcd80-7ef3-b993-879f-d2079ffafd50.png)
**GPT4よりも3.5の方がおじさんという知見を得ました。**


他にもいっぱいあります。絵文字がどうこうというプロンプト入れてないので、彼の内面から滲み出した100%天然のおじさんです。かわいいですね。
![CleanShot 2023-12-07 at 21.18.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489323/10414632-9515-c1f2-b463-e604f8ee52d9.png)
![CleanShot 2023-12-07 at 21.15.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489323/7c2d8dfe-7ec8-fb2a-9368-e59464a0643f.png)

---

出AI厨くんとは以下のリンクからお話しできます！ぜひ恋の悩みを相談してみてください！
いつか彼が機械の体を手に入れて一緒に飲みに行ける日を楽しみにしています。

https://chat.openai.com/g/g-jnGOKIVjz-chu-aichu
Github Educationの申請に手間取った話

Copilotが使いたくて[このサイト](https://zenn.dev/iizuka0000/articles/how-to-apply-for-github-education)を参考にGithub Educationを申請しました。
そして3日後に落ちました。

この時のメールには
* Githubの請求先の情報を学生証と同じフルネームにしろ(支払情報は追加しなくていい)
* 学校がアカデミックEメールを提供していない場合は、端末のカメラで画像を撮影できるようにする必要がある。  
* 学生証の写真は端末のカメラで撮影しろ。アップロードされた写真は加工されてるかもしれんから信用できん。  

などが書かれていました。
中でも特に気になったのが次の2つです

> ※原文
> The school you selected does not appear to have a campus location in your country. Your school-provided academic affiliation document must indicate virtual learning if you are remote. If you believe that the school you have applied for has incorrect information that affects your current application e.g. incorrect email domain, please select ‘My selected school has incorrect or incomplete information e.g. domains or campus location’ option when submitting a GitHub Education support ticket.

訳) あなたの学校が日本にないよ。もし違ってるならGitHub Education のサポートチケットを送信する際に、「選択した学校の情報が間違っているか、不完全です（ドメインやキャンパスの場所など）」を選択してね。

> You appear not to be near any campus location for the school you have selected. Your school-provided academic affiliation document must indicate virtual learning if you are remote.Please enable the application to discover your location from the browser pop-up to provide an accurate location. If you are using a VPN, please disable it when you reapply. If you believe that the school you have applied for has incorrect information that affects your current application e.g. incorrect campus location, please select ‘My selected school has incorrect or incomplete information e.g. domains or campus location’ option when submitting a GitHub Education support ticket.

訳) あなたは選択した学校のキャンパスの近くにいないようです。正確な所在地を記入するため、ブラウザのポップアップから所在地を確認できるようにしてください。VPNを使用している場合は、再申請時に無効にしてください。申請した学校の情報が間違っていて、現在の申請に影響があると思われる場合（例：キャンパスの場所が間違っているなど）、GitHub Educationのサポートチケットを送信する際に「選択した学校の情報が間違っているか、不完全です（例：ドメインやキャンパスの場所など）」を選択してください。

申請したとき私の学校がGithubのサジェストになかったことからも、私の学校の存在をGithubは認識してないんだなということに気づき、次の申請を送ると同時にGithub Supportで「選択した学校の情報が間違っているか、不完全です（例：ドメインやキャンパスの場所など）」を選択し送信し、Github Educationの申請を再度送りなおしました。

結果、その日のうちに申請が通り、そのメールには「72時間以内に有効になるよ」と書いてありました。そして本当にほぼぴったり72時間後に有効になりました。

ちなみに学生証の写真に英語訳を添えなくても通りました。