OmniAICreator/Qiita-1.07M huggingface dataset:
Java silver向け 例題 継承 ポリモーフィズム 2

次のコードの出力結果を答えてください

```java
abstract class Fish {
	String name = "SAKANA";
	abstract void setName(String na);
	abstract String getName();
}

class SABA extends Fish{
	String name = "";

	void setName(String na) {
		name = na;
	}
	String getName() {
		return name;
	}
}

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

		Fish fish1 = new SABA();
		SABA fish2 = new SABA();
		
		fish1.setName("Tarako");
		fish2.setName("Maguro");
		
		System.out.println(fish1.name);
		System.out.println(fish1.getName());
		
		System.out.println(fish2.name);
		System.out.println(fish2.getName());
	}
}


```
答え<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓

```java
SAKANA
Tarako
Maguro
Maguro
```

fish1.setName("Tarako")により、サブクラスのsetNameメソッドが呼び出されサブクラスのnameフィールドが"Tarako"に設定されますが、fish1.getName()が呼び出される際には、Fish型の変数のためFishクラス(スーパークラス)のnameフィールドが参照されるため、"SAKANA"が出力されます。

fish2.setName("Maguro")により、サブクラスのsetNameメソッドが呼び出されサブクラスのnameフィールドfish2のnameフィールドが"Maguro"に設定されます。SABAクラスのgetName()メソッドはSABAクラスのnameフィールドを返すため、"Maguro"が出力されます。

サブクラスSABAのnameフィールドメンバがない場合
```java

abstract class Fish {
	String name = "SAKANA";
	abstract void setName(String na);
	abstract String getName();
}

class SABA extends Fish{
	// フィールド name を削除
	void setName(String na) {
		name = na;
	}
	String getName() {
		return name;
	}	
}

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

		Fish fish1 = new SABA();
		SABA fish2 = new SABA();
		
		fish1.setName("Tarako");
		fish2.setName("Maguro");
		
		System.out.println(fish1.name);
		System.out.println(fish1.getName());
		
		System.out.println(fish2.name);
		System.out.println(fish2.getName());
	}
}

```
出力結果

```java
Tarako
Tarako
Maguro
Maguro
```
fish1.setName()によりサブクラスのメソッドが呼び出されますが、
サブクラスのフィールドnameが無いため、スーパークラスのフィールドnameに"Tarako"が代入されます。
データサイエンティスト、機械学習エンジニア、データアナリストの区別とは？

私は以前、IT業界は建築業界に似ており、職種の構造も似ていると考えていました。建築設計士が設計をして大工さんが家を建てるというように、IT業界もSEが設計をしてプログラマーがコードを作るというように分業しています。SEが顧客に近い立ち位置にあります。

具体的には、データサイエンティストはSE（設計士）のような役割であり、機械学習エンジニアはプログラマー（実装者）のようなものだと考えていました。

| 建築業界 |IT/DX業界   |分析/AI業界          |
|:--------|:----------|:----------------------|
| 建築設計士|SE        | データサイエンティスト |
| 大工     |プログラマー| 機械学習エンジニア    |

近年では、IT業界とAI業界が接近しており、「DX/AI」という用語が使われるようになりました。ほとんどのDXプロジェクトにはAIが必要です。

一方、データアナリストはどこに位置するのでしょうか。私は、データ解析の仕組みを倉庫から工場へのトラック輸送に例えてみました。データはデータウェアハウスという倉庫に保管されています。データウェアハウスから工場へとデータを運ぶトラックが分析装置です。トラックはデータを運び、解析結果という工場へ到着して荷物を下ろします。

![DataAnalyst_MLEngineer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734194/c45c3532-ca8e-9eda-a6eb-8566bf3a3605.png)

機械学習エンジニア、AIエンジニア、AIデベロッパーなどは、AIプロダクトを開発するので、DX/AI開発者の方に入るのでしょう。しかし、データサイエンティストという職種の立ち位置はあいまいで、開発者にもなりうるし、分析者になりうるので、両方の意味でつかわれる感じがします。

これはある側面から分類したものなので、他の分類などありましたら、コメントください。
再帰関数, 可変関数, 無名関数

## はじめに

再帰関数, 可変関数, 無名関数について整理する。

### 再帰関数

ある関数が自分自身を呼び出すこと。
階乗計算のように同種の手続きを繰り返し呼び出すような処理を短いコードで表現できる。

例えば5!を計算する場合、

```php:recursive.php
function fuctarial(int $n): int
{
    if($n !== 0){
        return $n * fuctarial($n - 1);
    }else{
        return 1;
    }
}

print fuctarial(5); // 120
```
のように書ける。

### 可変関数

「$変数名()」の形式で呼び出せる関数。
変数に応じて対応する関数を検索＆実行できる。

高階関数を利用することで、枠組みとなる機能だけを実装しておき(myArrayWalk)、詳細な機能(showItem)は関数の利用者が決めるという、より汎用性の高い関数を設計できるようになる。

```php:higher_order.php
function myArrayWalk(array $array, callable $func): void
{
    foreach ($array as $key => $value) {
        $func($value, $key);
    }
}

function showItem(mixed $value, int | string $key): void
{
    print "{$key}: {$value}<br />";
}

$data = ['杉山', '長田', '杉沼', '和田', '土井'];
myArrayWalk($data, 'showItem');

// 0: 杉山
// 1: 長田
// 2: 杉沼
// 3: 和田
// 4: 土井
```

### 無名関数(クロージャー)

名前が不要で特定の機能だけを定義したい際に使う関数。
高階関数呼び出しのコードに関数を直接埋め込める。

(上記では、myArrayWalkに渡すための関数としてshowItemのような関数を定義した。
しかし高階関数を渡すことを目的としたこれらの関数はその場限りでしか使わない。
使い捨ての関数に名前をつけるのは無駄なのでなくしたい。
そこで、無名関数が使える。)


```php:closure.php
function myArrayWalk(array $array, callable $func): void
{
    foreach ($array as $key => $value) {
        $func($value, $key);
    }
}

$data = ['杉山', '長田', '杉沼', '和田', '土井'];
myArrayWalk($data, 
    function (mixed $value, int | string $key): void {
        print "{$key}: {$value}<br />";
});

// 0: 杉山
// 1: 長田
// 2: 杉沼
// 3: 和田
// 4: 土井
```
Hexabase TypeScript SDKの使い方（認証状態の永続性）

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業においても安心して利用できるBaaS（Backend as a Service）を提供しています。多くのBaaSがそうであるように、主にフロントエンド開発者に利用してもらいたいと考えています。そこで現在、TypeScript SDKの開発が進められています。

この記事ではHexabase TypeScript SDKのインストールと、認証を永続的にする方法を解説します。

## インストール

インストールはnpmやyarnを使って行います。

```bash
# npmの場合
npm install @hexabase/hexabase-js

# yarnの場合
yarn add @hexabase/hexabase-js
```

## インポート

インポートすると、 `HexabaseClient` というオブジェクトが取得できます。

```jsx
import { HexabaseClient } from "@hexabase/hexabase-js";
```

## 初期化

HexabaseClientを初期化します。

```jsx
const client = new HexabaseClient();
```

## 認証の永続性について

認証データは以下の4パターンで管理できます。

- 何もしない  
ブラウザを再読込すると、認証情報が消えます。
- セッション  
ブラウザのタブごとに認証情報が管理されます。ブラウザのタブを閉じると認証情報が消えます。
- ローカルストレージ  
ブラウザのlocalStorageに認証情報が保存されます。ブラウザを閉じても認証情報が残ります。
- Cookie  
ブラウザのCookieに認証情報が保存されます。ブラウザを閉じても認証情報が残ります。

## 永続方式を指定する

`client.setPersistence` を使って、永続方式を指定します。

```jsx
// LocalStorageを使う
await client.setPersistence(localStorage);

// SessionStorageを使う
await client.setPersistence(sessionStorage);
```

Cookieの場合は `js-cookie` を使って設定します。

```bash
npm install js-cookie
```

```jsx
import Cookies from 'js-cookie';

// Cookieを使う
await client.setPersistence(Cookies);
```

Node.jsの場合は、 `node-localstorage` を利用します。

```bash
npm install node-localstorage
```

```jsx
import { LocalStorage } from 'node-localstorage';

// LocalStorageを使う
await client.setPersistence(new LocalStorage('./scratch'));
```

### 他のライブラリを使う場合

もし他の場合を使う場合には、以下のインタフェースがあれば利用できます。

```js
// LocalStorage/SessionStrage系
interface Persistence {
	getItem(key: string): Promise<string | null> | string | null;
	setItem(key: string, value: string): Promise<void> | void;
	removeItem(key: string): Promise<void> | void;
}

// Cookie系
interface Persistence {
	get(key: string): Promise<string | null>;
	set(key: string, value: string): Promise<void>;
	remove(key: string): Promise<void>;
}
```

## 認証

後はメールアドレスとパスワードを使って認証します。 `Persistence` を指定していれば、トークンを保存します。

```jsx
await client.login({email, password });
```

## 認証の復元

認証情報は `await client.setPersistence` を実行したタイミングで復元されます。その後は `client.currentUser` でユーザー情報を取得できます。

```jsx
await client.setPersistence(localStorage);

// ユーザー情報を取得
const user = await client.currentUser;
```

## デモ

以下は、Cookieを使って認証情報を永続化する例です。

[Cookieデモ](https://glowing-agreeable-antelope.glitch.me)

LocalStorageやSessionStorageを使う場合は、以下のデモを参照してください。

[LocalStorageデモ](https://jsfiddle.net/goofmint/yms8xzrd/8/)

## まとめ

認証情報を永続化することで、アプリケーション操作がスムーズになります。Hexabase TypeScript SDKを使って、使いやすい業務システムを構築してください。

Hexabaseには他にもバイナリファイルのアップロードやデータストアなどの機能があります。それらの機能も利用してください。

[Hexabase \| 新規事業向け開発・競争領域でのDX実現をサポート](https://www.hexabase.com/)
App Service にデプロイした .NET アプリの応答遅延を分析する その２

# はじめに

https://qiita.com/georgeOsdDev@github/items/166d9ed85c1effc648e8

のつづきです。

前回の記事では、Thread.Sleep による遅延をプロファイラトレースを用いて特定しましたが、この記事では別のパターンも試してみます。

# 外部依存への遅延が発生しているパターン

実アプリではデータベースや、外部の API などを利用しているケースが多いと思います。
今回は、外部の Rest API を呼び出し、そこで遅延しているパターンを見てみます。

https://httpstat.us/ というサイトがあり、指定した時間だけ遅く応答を返してくれるので便利です。

https://httpstat.us/

呼び出し元の実装は以下の通り

https://github.com/georgeOsdDev/SampleBuggyApp/blob/main/dotnet8app/Controllers/SlowRequestController.cs#L43-L74

## Application Insights を見る

今回は HTTP リクエストを外部に投げているので `dependency` テーブルに記録されます。

### Live Metric

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/92a99d74-1cdd-60d6-f415-e3e31c0d74de.png)

### トランザクションの検索

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/bc36cce2-8fbf-90b4-0d9e-cdb9ab30a141.png)

### `operation_Id`

ログで見るなら `operation_Id` でまとめて見れます。

```sql
(requests | union dependencies | union traces)
| where operation_Id == "cf225e217322a0e7f1d8e0334049c2eb"
| project timestamp, itemType, name, id, operation_ParentId, operation_Id,message
| order by timestamp asc
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/9aadd0b6-bd07-94b6-6aeb-3df5466af434.png)

https://learn.microsoft.com/ja-jp/azure/azure-monitor/app/transaction-search-and-diagnostics?tabs=transaction-search

## 問題の診断と解決

### Availability and Performance > 要求の実行が遅い

こちらも Application Insights の情報を引っ張ってきてくれてますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/8c8137ef-f8df-5493-3c2f-d44b15f89f51.png)

### Diagnostic Tools >Collect .NET Profiler Trace

`System.Net.Http.HttpClient.Default.ClientHandler Message:Sending` から `ystem.Net.Http.HttpClient.Default.ClientHandler Message:Received` までで時間がかかっていることがわかりやすいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/621f058b-1c4b-b72d-5cfd-126a6f3606f6.png)

### その他

今回は .Net アプリの遅延にスコープを当てているので対象外としますが、そもそも Connectivity の問題であれば、「Collect a Network Trace」や 「Network Troubleshooter」も活用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/d13cfbcb-9eb6-0ff8-15c7-029a7dc1fe0b.png)

https://azure.github.io/jpazpaas/2024/02/29/Troubleshoot-20Network-20Connectivity-20issues-20using-20Network-20Troubleshooter.html
Go言語における構造体（struct）の基本

### 構造体とは？

go構造体は、異なるデータ型の変数を一つにまとめるための複合データ型です。例えば、名前、年齢、住所を一つの「人」型としてグループ化することができます。これにより、データの管理と操作が容易になります。

### 構造体の宣言

構造体は`struct`キーワードを使用して宣言されます。以下に簡単な構造体の宣言例を示します。

> type キーワードで構造体をひとつ作るということは、struct で定義された新しい型 (type) を定義する、ということになります。

```go
type {struct_name} struct {
   filed1 type
   filed2 type
   ...
}
```
例

```go
type Person struct {
    Name string
    Age  int
    Address string
}
```

この例では、「Person」という名前の構造体を定義しています。この構造体には、Name、Age、Addressという3つのフィールドが含まれています。


### 構造体の利用

構造体のインスタンスを作成し、そのフィールドにアクセスして変更することができます。以下に例を示します。

```go
var p Person
```

```go
p := Person{}
```

構造体の作成時に初期化できます。

```go
p := Person{
	Name: "山田太郎",
	Age: 30,
    Address: "東京都",
}
```

フィールド名は省略できます。

```go
p := Person{
	"山田太郎",
	30,
    "東京都",
}
```

例

```go
package main

import "fmt"

type Person struct {
	Name    string
	Age     int
	Address string
}

func main() {
	var p Person
	p.Name = "山田太郎"
	p.Age = 30
	p.Address = "東京都"
	fmt.Println(p)
}

```

コード：https://go.dev/play/p/mI1M2DWx03C

### 構造体にメソッドを追加

Go言語では、構造体に対してメソッドを定義することができます。これにより、オブジェクト指向プログラミングのような機能を実現できます。

```go
func (p Person) Greet() string {
    return "こんにちは、" + p.Name + "さん！"
}
```

コード：https://go.dev/play/p/QPZxC61TkQr


### 無名構造体とネストした構造体

構造体は、無名で定義することも、他の構造体の中にネストして定義することもできます。これにより、より複雑なデータ構造を柔軟に表現できます。

```go
type Employee struct {
    Person
    Position string
}
```

この例では、「Employee」構造体が「Person」構造体を含んでおり、追加で「Position」というフィールドがあります。


```go
package main

import "fmt"

type Person struct {
	Name    string
	Age     int
	Address string
}

func (p Person) Greet() string {
	return "こんにちは、" + p.Name + "さん！"
}

type Employee struct {
	Person
	Position string
}

func main() {
	var e Employee

	e.Person = Person{
		Name:    "山田太郎",
		Age:     30,
		Address: "東京都",
	}
	fmt.Println(e.Person.Greet())
}
```

コード：https://go.dev/play/p/pueTJ0QMav6

### 構造体のエクスポート

他のパッケージから構造体やそのフィールドにアクセスするためには、構造体名とアクセスしたいフィールド名を`大文字`で始める必要があります。

```go
// personパッケージ内
package person

// Person 構造体は外部パッケージからアクセス可能
type Person struct {
    Name    string // 外部パッケージからアクセス可能
    age     int    // ageは小文字で始まるため、personパッケージ外からはアクセス不可
    address string // addressは小文字で始まるため、personパッケージ外からはアクセス不可
}
```


### まとめ

Go言語の構造体は、複数の異なる型のデータを一つにまとめ、管理しやすくするための強力なツールです。


最後に、弊社の採用情報にご興味をお持ちの場合は、ぜひカジュアルな面談をお申し込みください。

- [【バックエンドエンジニア】3万人以上の理系学生が利用する就活サービスの開発担当](https://hrmos.co/pages/techocean/jobs/1827530328848072705)
- [【インフラエンジニア】3万人以上の理系学生が利用する就活サービスのインフラ担当](https://hrmos.co/pages/techocean/jobs/1827530328848072707)


参照
- Go言語公式ドキュメント: [A Tour of Go](https://go.dev/tour/welcome/1)
- Effective Go: [Effective Go](https://go.dev/doc/effective_go)
【画像あり】Sandbox: rsync.samba(96984) deny(1) file-write-create のエラー対処法

# 対処法
①実行しようとしているファイルを選択
![スクリーンショット 2024-04-11 20.27.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/c1bf1c3a-4d76-de16-29d6-7d50583b72b5.png)

②Build Settingsを選択
![スクリーンショット 2024-04-11 20.27.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/3a2fa8e0-84ae-d73e-599e-49b35db6cd9b.png)


③Userv Script SandboxingをNoに変更
![スクリーンショット 2024-04-11 20.27.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/49545e22-05d0-266e-ca29-c091beddf04a.png)

※User Script SandBoxingが見つからない場合
　ALLを選択してみてください。
 
 ![スクリーンショット 2024-04-16 21.31.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/e6d2bda3-5ae6-d3c6-75ad-1ba992d702f1.png)
AWS Amplifyを使って日本語のログイン画面を作るとユーザー名のプレースホルダが英語になる

## Amplify UIのログイン画面
Amplify UIを使えば画像のようなログイン画面が簡単につくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/e890de5e-179d-c05a-be20-8ab3bea7d605.png)

この画面の作り方は公式にも、いろんなサイトにも載っているので今回は割愛します。

公式はこちら

https://ui.docs.amplify.aws/react/connected-components/authenticator/configuration

## Amplify UIを日本語にしようとしたら一部だけ英語のまま
このUIに対して、I18nというモジュールを使えば日本語化することができます。
しかし、ユーザー名のプレースホルダだけ「Enter your Username」で英語のままになります。

https://docs.amplify.aws/react/build-a-backend/utilities/i18n/#pageMain

## 原因
英語と日本語のマッピングファイルは下記に置いてあり、日本語化するときにこのファイルを使っています。

https://github.com/aws-amplify/amplify-ui/blob/main/packages/ui/src/i18n/dictionaries/authenticator/ja.ts

しかし、「Enter your Username」とすべきところを「Enter your username」としてしまっており、参照できずに英語のままになってます。（usernameの"u"が小文字になってます）

これについては既に見つけている方がおり、プルリクを出していました。

https://github.com/aws-amplify/amplify-ui/pull/5054

## 対処法
プルリクが出されているのでいずれ修正されると思いますが、対応方法としてはモジュールの中身のマッピングファイルを直接直すか、下記の記述を追加することで回避できます。

```
I18n.putVocabularies(translations);
I18n.setLanguage('ja');

// 下記を追加
I18n.putVocabularies({
  ja: {
    'Enter your Username': 'ユーザー名を入力',
  },
});
```
【Mac】Git環境構築

# 本記事の目的
ターミナルからGitHub上のリポジトリへコードをプッシュするための環境構築を行う

# Git環境構築
Git環境構築として、下記を行う。
- SSH公開鍵の作成
- SSH公開鍵アップロード
- 動作確認

## SSH公開鍵の確認
SSH公開鍵はデフォルトで`~/.ssh`ディレクトリに`.pub`の拡張子を持ったファイル内に記載がある。
下記コマンドより、公開鍵が作成済みか確認する。

```bash:terminal
$ ls ~/.ssh/*pub
/Users/username/.ssh/id_[文字列].pub
```

### SSH公開鍵がすでにある場合
→次章の「SSH公開鍵アップロード」へ進む

### SSH公開鍵がない場合
公開鍵を作成する
```bash:terminal
$ ssh-keygen
```

## SSH公開鍵アップロード
[アカウントへの新しい SSH キーの追加](https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account#adding-a-new-ssh-key-to-your-account "Github公式のドキュメント")に従い、SSH公開鍵をGitHubにアップロードする
※⑤のキーの種類は「Authenticate」を選択する。

## 動作確認
下記コマンドをターミナルで打ち込み、レスポンスが帰って来れば成功。

```bash:terminal
$ ssh -T git@github.com
Hi [登録済みのGitHubユーザー名]! You've successfully authenticated, but GitHub does not provide shell access.
```
NestJSとPrismaでクエリログを出力する

## はじめに
業務の関係でNestJS + Prismaの構成を触っていた際にクエリログを見たくなりました。
公式ドキュメントには`new PrismaClient()`の宣言時に設定できるような記述はあるものの、NestJSでの利用時にはコンストラクタに`PrismaService`を記述して利用するため`new PrismaClient()`の記述がありません。

#### 参考
https://docs.nestjs.com/recipes/prisma#use-prisma-client-in-your-nestjs-services

そのため、方法が分からず困ったのですが、無事に解決したのでメモしておきます。

## 前提
以下の環境で試しています。
- nest: 10.2.1
- prisma: 5.7.0
- @prisma/client: 5.7.0

## 方法
`prisma.service.ts`を以下のように編集することでログ出力が可能です。

```typescript
import { Injectable, Logger, OnModuleInit } from '@nestjs/common'
import { Prisma, PrismaClient } from '@prisma/client'

@Injectable()
export class PrismaService extends PrismaClient<Prisma.PrismaClientOptions, 'query'> implements OnModuleInit {
  private readonly logger = new Logger(PrismaService.name)
  constructor() {
    super({
      log: [
        {
          emit: 'event',
          level: 'query',
        },
      ],
    })
  }

  async onModuleInit() {
    this.$on('query', (event) => {
      this.logger.log(
        `Query: ${event.query}`,
        `Params: ${event.params}`,
        `Duration: ${event.duration} ms`,
      )
    })
    await this.$connect()
  }
}
```

### 出力例
```
[Nest] 2616  - 2024/04/11 14:25:20     LOG [PrismaService] Query: SELECT `develop`.`reservations`.`id` FROM `develop`.`reservations` WHERE `develop`.`reservations`.`id` IN (?,?)
[Nest] 2616  - 2024/04/11 14:25:20     LOG [PrismaService] Params: ["cltwbp5qr001sfi7r0vpstbz4","cluc8lp9b000e132hgz9pwkee"]
[Nest] 2616  - 2024/04/11 14:25:20     LOG [PrismaService] Duration: 1 ms
```

## 参考
https://stackoverflow.com/questions/67509194/logging-with-prisma-2-and-nestjs-dependency-injection-problem
DockerでMySQLコンテナ起動してDBクライアントで接続しようとしたら大変だった話

## 前提
下記の環境で作業していました。

OS:Windows 10
DBクライアント：DBeaver

## DockerでMySQLコンテナを立ててテスト環境を作ろうとした
今回単にDockerで軽くMySQLコンテナを立てようとしたらエラーに次ぐエラーで大変だったので備忘録。

今回利用したdocker-compose.ymlは次でよくある平凡な定義でした。

```
services:
  db:
    image: mysql:8
    command: --collation-server=utf8mb4_0900_bin
      --transaction-isolation=READ-COMMITTED
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      TZ: Asia/Tokyo
    ports:
      - 13306:3306
```

## 1個目のエラー
```
Host xxx is not allowed to connect to this MySQL server
```

よくある接続しようとしているユーザーの権限にリモートで接続する権限がないんだなと思いました。
下記GRANTコマンドで権限付与を試してみることに。

```
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
```

## 2個目のエラー

すると、次のようなエラーが・・・

```
you are not allowed to create a user with grant
```

権限的にGRANTが実行できない。
なんで？と思ったけど、docker-compose.ymlに次のように追記すれば、最初からリモートから接続できるみたいで、こちらを試してみることに。

```
environment:
  MYSQL_ROOT_HOST: '%'
```

## 3個目のエラー
よし、これでリモートから接続できるようになったはず。
もう1度DBクライアントから接続してみようとしたところ、またまたエラー・・・

```
Public Key Retrieval is not allowed
```

これは見たことない。
ググってみると、有志の方が記事に残してくれていた！

https://qiita.com/noy__/items/f53e9e6210e02233d414

「allowPublicKeyRetrieval」をtrue、「useSSL」をfalseにするみたい。

これを実行すると、無事接続できました！！

## さいごに
単純にMySQLコンテナ立てて外部から接続しようとしただけなのに、こんなに複雑なことになるっけ？と思いつつ単純な作業だけに同じような事象に見舞われる方もいると思うので備忘録として残します。
セマンティック バージョニング：ソフトウェアバージョン管理の明確化

ソフトウェア開発における「依存性地獄」という言葉を耳にしたことがあるでしょうか？これは、複数のパッケージやライブラリに依存しているソフトウェアプロジェクトが、バージョン管理の不明瞭さによりアップグレードが困難になる状況を指します。この問題の解決策として登場したのが、セマンティック バージョニング（SemVer）です。

# セマンティック バージョニングとは？

セマンティック バージョニングは、ソフトウェアのバージョン番号を割り当て、更新する際のルールセットです。形式は `メジャー.マイナー.パッチ` と表され、以下のようにバージョン番号が更新されます：

- **メジャーバージョン**：APIの変更に互換性がない場合
- **マイナーバージョン**：後方互換性があり、機能性が追加された場合
- **パッチバージョン**：後方互換性を保つバグ修正が行われた場合

加えて、プレリリースやビルドメタデータといったラベルを利用することも可能です。これにより、バージョン管理をより柔軟に行うことができます。

# なぜセマンティック バージョニングが必要なのか？

ソフトウェア開発が複雑化する現代において、明確なバージョン管理は非常に重要です。セマンティック バージョニングを採用することで、開発者はソフトウェアの変更内容を一目で識別でき、依存するライブラリやパッケージの更新による影響を容易に判断できます。これにより、依存性地獄を避け、ソフトウェアプロジェクトの安定性と持続可能性を高めることが可能になります。

# SemVerの適用方法

SemVerを適用するためには、まずパブリックAPIを明確に定義する必要があります。このAPIの変更に伴い、上記のルールに従ってバージョン番号を適切に更新することで、ソフトウェアの利用者に対し、その変更がどのような影響をもたらすのかを明確に伝えることができます。

# セマンティック バージョニングの利点

- **明確なコミュニケーション**：開発者と利用者の間でソフトウェアの変更点を明確に伝えることができます。
- **依存性管理の容易さ**：依存するライブラリやパッケージの適切なバージョンを簡単に特定できます。
- **更新プロセスの効率化**：バージョン番号から互換性の有無を判断できるため、更新プロセスがスムーズになります。

# 結論

セマンティック バージョニングは、ソフトウェア開発におけるバージョン管理を明確化し、

プロジェクトの進行をより安全かつ効率的にするための重要なツールです。このシステムを理解し、適切に適用することで、開発者と利用者はより信頼性の高いソフトウェア環境を構築することができます。

# 参考記事

より深くセマンティック バージョニングについて学びたい方は、公式ウェブサイト [SemVer.org](https://semver.org/) を参照してください。このサイトでは、SemVerの詳細な仕様とその背後にある思想について解説されています。
Laravel6でSassを使う手順

## 目標
Laravel6でSassを使いたい

## 方法
https://newsite-make.com/laravel-mix/#laravel_mix

### 上記サイトと異なる点(自分用)
#### ⓪以下コマンドをプロジェクト作成時にしているなら次の①~⑤は不要
```
ターミナル
composer require laravel/ui
php artisan ui bootstrap --auth
npm install
npm run dev
```
①~⑤は済んでいる。

#### ①Node.jsのインストール
いつも通りなら「インストール」されている

#### ②Laravel Mixのインストール
これ不要

#### ③webpack.mix.jsの編集
いつも通りなら「変更後」になっている

#### ④app.scssは作成も不要
いつも通りなら作成されている

#### ⑤「public」フォルダの下に「css」フォルダ作成もふよう
いつも通りなら作成されている

#### ⑥resources > sass > app.scssに独自cssを書き込む
変更ごとに以下コマンドを打つ
```
ターミナル
npm run dev
```
TextMeshProのコンテンツサイズを可変にする際の備忘録

# この記事について
TextMeshProのコンテンツサイズを、テキストに応じて可変にした際に
分かりにくかったところを備忘録としてまとめます。

# テキストに応じて可変にする
|![スクリーンショット 2024-04-11 17.22.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/7071e67f-94aa-a348-0301-13711d811349.png)|![2888f61d1758d4914ca18d30c80fb542.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/90c4c2e3-dde5-4379-7457-ff3bff54ccbd.gif)|
|--|--|

コンテンツを可変にするだけなら、ContentSizeFitterをアタッチして
Preferred Sizeを指定するだけで良い。とても簡単。

## レイアウトグループに組み込む
さて、コンテンツサイズを可変にしたいという事は、大抵の場合レイアウトグループに入れる事になると思います。
そうするとContentSizeFitterに下記のような警告文が出ます
```
Parent has a type of layout group component.
A child of a layout group should not have a Content Size Fitter component.
since it should be driven by the layout group.

親がレイアウトグループタイプのコンポーネントを持っています。
レイアウトグループの子は、ContentSizeFitterを持つべきではありません。
なぜなら、ContentSizeFitterはレイアウトグループによって駆動されるべきだからです。
```
## 警告に従ってみる
警告に従い、TextMeshProの方からはContentSizeFitterを削除し
LayoutGroupの方にContentSizeFitterをアタッチしてみる
|![スクリーンショット 2024-04-11 17.56.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/bbbb6d86-56bd-1f78-043d-38526dda5099.png)|![53484852a9a4298ce864987ec2c70704.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/ab27f6b9-48a2-b34c-1874-cf11701d6101.gif)|
|--|--|

TextMeshProのコンテンツサイズが変化しなくなった。悲しい。

## ContentSizeFitterはレイアウトグループによって駆動されるべきだからです
言い換えると、親が子供のサイズを制御すべき。
なるほど、つまり Control Child Size を使えばいい。
|![スクリーンショット 2024-04-11 18.49.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/5670338e-be7b-e07b-ad15-21ca9e68130d.png)|![be1a5b250b9620c6a935309cc0aabb59.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/77e7217d-4dc4-688c-ae04-a59740d10b6d.gif)|
|--|--|

# まとめ
 - コンテンツサイズを可変にするにはContentSizeFitterを使う
 - LayoutGroupを使う場合は、LayoutGroupにContentSizeFitterをアタッチする
 - Control Child Sizeにチェックを入れる
Goを勉強してみた part1

# はじめに
最近Go言語を勉強し始めたので、メモとしてGo言語の特徴をメモしていく

# package
Goではソースコードの最初にpackageで名前空間を定義する必要がある
importの際にはこの名前空間でimportする

```go
package main // <- 名前空間

import ("fmt") // <- importするパッケージ

func main() {
    //実行したい処理...
}
```

自作モジュールを読み込みたい場合はGOROOTで指定されたPATHにあるsrcから読み込まれる
GOROOTは`go env GOROOT`で確認ができる

# 変数
Goでは整数型や実数型、文字列型など他の言語と同じような型を利用する
変数の定義や値の代入は以下のようにvarで定義する
```go
var int32 num // 変数の定義
num = 1000 // 変数の代入
```
また、変数の定義と代入は同時に行うことができ、その場合は以下のように記載する
定義と代入を同時に行う場合には型の定義を省略することもできる
```go
var int32 num = 1000 
var num = 1000 // 型の省略
```
上記の定義はよりシンプルに利用することができる（短縮変数宣言と呼ぶ）
```go
num := 1000
```

型のキャストも同様に行うことができる
```go
var num1 int32 = 1000
var num2 int64 = int64(num1)
```
※ **なおGoでは暗黙の型変換がされないので必ず型変換を行う必要がある**(他の言語ではint32->int64に変換されるとき型変換をしなくても自動で変換される)

文字列を数値型にキャストすることはできないので、`strconv`というパッケージの`Atoi`関数や`Itoa`関数を利用する

また、Goでは宣言した変数は必ず利用する必要がある
利用していない変数があるとエラーが発生する

定数は`const {定数} = {値}`で定義する

`_`で定義した変数は利用しないこともできる

# 制御構文
ifやswitch, forなど他の言語と同じように利用できる

`c++`のような書き方はGo言語ではステートメントになっており、演算子ではないため、単体で記載する

# 配列
以下のように定義する

```go
var arr [ 100 ] int32
or
var arr [ 2 ] int32 { 1, 2 }
```
配列の要素数は固定になり、最初に定義した数から増やすことはできない

# スライス
配列と類似しているが、要素が固定化されておらず、後から操作することができる
初期化は以下のように行う
```go
sli := []int{10, 20, 30}
```
値を取り出す際には`変数 := 配列[開始：終了]`で取り出す

スライスは配列の参照を行なっているだけであり、スライスを変更すると元になった配列も変更される

スライスは`変数 = append(スライス, 値1, 値2)`という形式で要素を追加することができ

なお、関数の引数として渡す際などに`スライス...`と渡すことでスライスを展開することができる

# Map
名前を使って値を管理したい場合に利用する
以下のように初期化する
```go
var m map[string]int
m: 変数
string: キー型
int: 値型
```

マップは順番を保証しないため、for文などで順に表示した場合実行時に結果が異なる場合がある

# 関数
以下の形式で記載する
```go
func 関数名(引数) 戻り値 {
    実行する処理
}
```
この部分`func 関数名(引数) 戻り値`を関数のシグニチャという

また、戻り値を複数指定することもでき、その場合は以下のように戻り値を括弧でまとめ、returnで返す方はカンマで区切る
```go

func 関数名(引数1, 引数2) (戻り値1, 戻り値2) {
    実行する処理
}

----
return 値1, 値2
```

また、名前付き戻り値を利用でき、戻り値に引数と同様に名前をつけることができる
その場合はreturnで変数を返す必要がなく、returnのみを記述する
```go
func kansu(a int, b int) (s int){
    s = a + b
    return <- sの値が返される
}
```

可変長引数も利用でき、その場合は以下のように定義する
```go
func 関数名(変数 ...型)　戻り値　{
}
```
関数内で読み込む際には`変数...`でスライスとして展開して読み込む
※ 可変長引数は最後に利用する必要がある

Goでは関数は値である
そのため、関数を変数に入れて利用することができる
```go
f := func(arr []string) ([]string, string){
    return arr[1:], arr[0]
}
```
引数や戻り値に関数を利用することもでき、そういった関数は"高階関数"と呼ばれる
JavaでJettyをMavenプロジェクトに組み込む方法

開発中のWebアプリケーションを簡単にテストするためには、組み込みHTTPサーバーが非常に便利です。Jettyは、軽量で使いやすい組み込みHTTPサーバーおよびサーブレットコンテナの一つです。この記事では、MavenプロジェクトにJettyを組み込む方法をステップバイステップで説明します。

# 前提条件

このチュートリアルを始める前に、以下の条件を満たしていることを確認してください：

- JDK 17 以上がインストールされている
- Mavenがインストールされている

# ステップ1: `pom.xml`の編集

プロジェクトが作成されたら、`pom.xml`ファイルを開いて、Jettyの依存関係とプラグインを追加します。

## 依存関係

Jettyサーバーを組み込むために、以下の依存関係を`<dependencies>`セクションに追加します。

```xml
<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.0.0</version>
    <scope>provided</scope>
</dependency>
```

## プラグイン

Jettyを起動し管理するために、`maven-jetty-plugin`を`<plugins>`セクションに追加します。

```xml
<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>11.0.20</version>
    <configuration>
        <scanIntervalSeconds>10</scanIntervalSeconds>
        <webApp>
            <contextPath>/</contextPath>
        </webApp>
    </configuration>
</plugin>
```

このプラグイン設定では、Jettyサーバーのスキャン間隔を10秒に設定しています。これは、ファイルの変更を10秒ごとにチェックし、変更があった場合に自動的にリロードすることを意味します。`contextPath`はアプリケーションのベースURLを指定します。ここではルート（`/`）に設定しています。

# ステップ2: アプリケーションの実行

`pom.xml`に必要な設定を追加した後、次のコマンドを使用してJettyサーバーを起動し、アプリケーションを実行します。

```bash
mvn jetty:run
```

このコマンドを実行すると、Jettyサーバーが起動し、指定したポート（デフォルトは8080）で待機します。ブラウザを開き、`http://localhost:8080`にアクセスして、アプリケーションが正しく動作していることを確認できます。

# まとめ

この記事では、MavenプロジェクトにJettyを組み込み、Webアプリケーションを簡単に開発およびテストする方法を説明しました。Jettyプラグインを利用することで、開発中のアプリケーションの起動やデバッグが容易になります。これにより、開発プロセスがスムーズに進み、より迅速にアプリケーションを構築できます。

JettyとMavenの組み合わせは、JavaでWebアプリケーションを開発する際の強力なツールです。この設定を利用することで、開発者は効率的に作業を進めることができるでしょう。
Linux備忘録

1. ダウンロードする
    
    `wget <ダウンロードするディレクトリ・ファイル名>`
    
2. zipの解凍
    
    `unzip <解凍するzip>`
    
3. フォルダの作成
    
    `mkdir <作成したいファイル名>`
    
4. ファイルの移動
    1. 拡張子の見分け
        
        `mv *.txt  <移動させたいフォルダ名>`
        
    2. ファイル中身の見分け
        
        `grep -rl *<探したい文字列> | xargs -I {} mv {} <移動させたいフォルダ名>`
        
        `grep` : 中身の検索  例）`grep <検索文字列> <検索対象ファイル名>`
        
        `-r` : カレントディレクトリ以下のすべてのファイルが検索対象になる
        
        `-l` : ファイル名を出力する
        
        `|` : 前の出力を後の入力にする
        
        `xargs` : 標準入力から1つずつ引数を取り出し，指定したコマンドを実行する
        
        `I {}`  : 標準入力から取り出した各引数を`{}`で置き換える.
        
5. ファイルを読む
    
    `more <ファイル名>` : そのまま下に書き出される
    
    `less <ファイル名>` : 別ページに書き出される　閉じる時は`q`
    
6. rockの解除
    1. 権限の確認
        
        `ls -l`
        
    2. 権限の変更
        
        `chmod 755 <フォルダ・ファイル名>`
        
        権限について
        
        `ls -l` で現在，各ファイル，フォルダに与えられている権限を見ることができる．
        
        出力は
        
        `-rwxr-xr-x  1 <ユーザー名> <ユーザーの分類>  <日付> <ファイル名>`
        
        といった形になる．
        
        では，r,w,xとはどういう意味なのか？
        
        r,w,xといった記号はファイルへの操作権限の種類を示している．
        
        操作は「読み取り」，「書き込み」，「実行」と3種類ありそれぞれ「r」「w」「x」の記号で表現される．
        
        | 記号 | 意味 |
        | --- | --- |
        | r | 読み取り(read) |
        | w | 書き込み(write) |
        | x | 実行(execute) |
        
        よって先程の**-rwxr-xr-x**の権限一覧表は
        
        | ユーザー種別 | 読み取り | 書き込み | 実行 |
        | --- | --- | --- | --- |
        | オーナー(rootユーザー) | 許可 | 許可 | 許可 |
        | rootグループに所属するユーザー | 許可 | 禁止 | 許可 |
        | その他のユーザー | 許可 | 禁止 | 許可 |
        
        では，`chmod 755` の755とは？
        
        「所有者」「グループメンバー」「その他」の権限を表している．
        
        権限に対しての数字は以下の通り．
        
        | 意味 | 数値 |
        | --- | --- |
        | 読み取り(r) | 4 |
        | 書き込み(w) | 2 |
        | 実行(x) | 1 |
        
        これらを足し合わせることで権限を表現している．
        
        具体的には，読み取り、書き込み、実行権限全てを付与したい場合は4+2+1=7となる．
        
        読み取り、実行権限のみであれば4+1=5となる．
        
        したがって**rwx r-x r-x**は **7 5 5**となる．
        
7. 隠しディレクトリを探す
    
    `ls -a`
    
8. ファイルに書かれている特定の単語の回数を数える
    
    `grep -o <検索文字列> <ファイル名>  | wc -l`
    
9. よく使うコード
    
    ファイルを消す
    
    `rm <ファイル名>` 
    
    `-d <ディレクト名>`
    
    前に使ったコードの履歴を見る
    
    `history`
Bootstrapで画像をレスポンシブ&枠の中で綺麗に表示する

## 目標
![スクリーンショット 2024-04-11 18.53.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726068/77d26255-01ba-3c93-bb54-0b66445199f9.png)

右上のアイコンのようなものを表示したい

## 方法
```header.blade.php
<div class="container-fluid bg-dark mb-3">
    <div class="container">
        <nav class="navbar navbar-dark">
            <span class="navbar-brand mb-0 h1">Daily Budget Tool</span>
            <div>
                <button class="btn btn-success">予算</button>
                <button class="btn btn-success">予算管理</button>
                <button class="btn btn-success">支出登録</button>
                <div class="profile-picture">
                    <!-- ⭐️↓ここ img-fluid -->
                    <img class="img-fluid" src="/assets/sample.jpg" alt="Profile Picture">
                </div>
            </div>
        </nav>
    </div>
</div>
```

### img-fluidについて
max-width:100%;, height:auto; で表示され、親要素と同じ大きさになるように画像に適用される

## 参考
https://v4.bootstrap-guide.com/content/images

## 独自CSSも一応記載
```style.css
.profile-picture {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  overflow: hidden;
  vertical-align: middle;
  display: inline-block;
}
```
グーグルのGemini 1.5 Proに耳が付いた

本記事は[lifehack](https://lifehacker.com/tech/googles-gemini-15-pro-can-now-listen-to-audio-files)により翻訳されたものです。
![QQ20240411175245.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2298092/c9096422-ab03-d39c-46fb-ae6b04fcf371.png)

グーグルのAIの最新バージョン、Gemini 1.5 Proがユーザーの声を聞くことができるようになりました。

Geminiは、以前はBardと呼ばれていたGoogleのリブランディングされたボットであり、Gemini 1.5 Proは、今年の2月に限られた開発者に利用可能になったモデルの最新のイテレーションである。Gemini 1.5 Proは、テキスト、コード、ビデオ、そして（現在では）アップロードされたオーディオストリームを処理する能力を持っていて、聞き取り、分析、対応する書き起こしのない情報を抽出することができます。

実際、音声ファイルのサポートは、ユーザーがGemini 1.5 Proを使用して、決算説明会から情報を収集したり、録音されたインタビューを書き起こしたり、音声付きビデオを分析したりできることを意味します。このAIは、1時間のビデオ、11時間のオーディオ、30,000行のコード、または700,000以上の単語を含むプロンプトを1つのストリームで処理することができます。

グーグルはまた、Vertex AIにアクセスできる人向けにGemini 1.5 Proをパブリックプレビューとして公開していますが、パブリックベータテストはまだ予定されていません。今のところ、ほとんどのユーザーはGeminiチャットボットを通じてグーグルのAIと関わっています。

以上、グーグルのGemini 1.5 Proに耳が付いたという情報について紹介しました。ほかのAI製品に関心を持つ方に、AIをベースに人物写真を[AI 似顔絵](https://vanceai.com/ja/toongineer-cartoonizer/)への変換を実現できるToongineerや、[ぼやけた画像をくっきり](https://vanceai.com/ja/sharpen-ai/)させるAI搭載のサイトーーVanceAI画像鮮明化を試すのをおすすめします。
ｓｔｙｌｅｓｈｅｅｔを読み込ませてCSSを反映させたい

## cssが読み込みされない！！
テキストを何度か見直しましたが原因がわからなかった。

AIに聞いてみたところで解決。
`<%= stylesheet_link_tag "test", media: "all" %>`
stylesheetを読み込ませる記述をviewページの該当箇所に記載する。
（上記に書いてある"test"は読み込ませたいviewファイルの名前をかく。）

#### 忘れると思うので備忘録として
[![Image from Gyazo](https://i.gyazo.com/d1641fd818b76943e1c78ee52f09a344.png)](https://gyazo.com/d1641fd818b76943e1c78ee52f09a344)

今回は`ktests`というフォルダを作ったためkitesを読み込むためにapp>asets>stylesheetsの中にktests.cssを作る必要がある。

その後`<%= stylesheet_link_tag "test", media: "all" %>`を読み込ませたいページに記入すると無事読み込み完了。
タイ語トークナイザの「精度」をUD_Thai-PUDのtestセットで測る

CoNLL 2018 Shared Taskの[Evaluationページ](http://universaldependencies.org/conll18/evaluation.html)を横目に、タイ語モデルにおけるトークナイザの「精度」を測るプログラムを書いてみた。Google Colaboratoryだと、こんな感じ。

```
!pip install transformers sentencepiece spacy-alignments
models=["KoichiYasuoka/roberta-base-thai-syllable","scb10x/typhoon-7b","openthaigpt/openthaigpt-1.0.0-7b-chat"]
ud="UD_Thai-PUD"
!test -d $ud || git clone --depth=1 https://github.com/universaldependencies/$ud
!cp $ud/*-test.conllu test.conllu
from transformers import AutoTokenizer
from spacy_alignments import get_alignments
for mdl in models:
  tkz=AutoTokenizer.from_pretrained(mdl)
  gold=system=correct=0
  with open("test.conllu","r",encoding="utf-8") as r:
    for k in r:
      if k.startswith("# text ="):
        txt=k[8:].strip()
        frm=[]
      elif k.strip()=="":
        g=[(t[0],t[-1]+1) for t in get_alignments(list(txt),frm)[1]]
        s=[t for t in tkz(txt,return_offsets_mapping=True)["offset_mapping"] if t[0]<t[1]]
        gold+=len(g)
        system+=len(s)
        i=j=0
        while i<len(g) and j<len(s):
          if s[j][0]<g[i][0]:
            j+=1
          elif g[i][0]<s[j][0]:
            i+=1
          else:
            correct+=g[i][1]==s[j][1]
            i+=1
            j+=1
      else:
        t=k.split("\t")
        if len(t)==10 and t[0].isdecimal():
          frm.append(t[1])
  print("\n***",mdl)
  print("Precision",correct/system if system else 0.0)
  print("Recall   ",correct/gold)
  print("F1 Score ",2*correct/(system+gold))
```

私(安岡孝一)の手元では、以下の結果が得られた。

```
*** KoichiYasuoka/roberta-base-thai-syllable
Precision 0.4651299687083682
Recall    0.6725651823313323
F1 Score  0.5499368120295244

*** scb10x/typhoon-7b
Precision 0.35939561475152354
Recall    0.5125436788818206
F1 Score  0.4225201270404018

*** openthaigpt/openthaigpt-1.0.0-7b-chat
Precision 0.37973561490731106
Recall    0.44140310008063793
F1 Score  0.4082537446394166
```

もちろん、[UD_Thai-PUD](https://github.com/universaldependencies/UD_Thai-PUD)における単語分割が完璧というわけではないし、[2020年6月16日の日記](https://srad.jp/~yasuoka/journal/639768/)に書いたとおり問題点も散見される。このあたり、いいテストセットを作るべきなのだろうけど、合意を取るのが大変そうだなぁ。
365 日後に〇〇する社畜の成長日記

# 



## 概要

IT 企業に就職した新米社畜が 3 人で日々の成長日記を綴っていきます!  
息抜きを兼ねて、1 年間研修や業務を通して得た学びや成長を記録していくので温かく見守っていただければ幸いです。

内容は以下のようなものを予定してます！

- AWS 学習
  - SAA 合格への道
    - SAAの学習中に学んだ単語などについて紹介していきます！
    - SAA合格後はより上位の資格も…？
- 社会人への道
  - 社会人のマナーについて紹介＆勉強！
- paiza挑戦記録
  - Paizaで学ぶ中で初めて知ったことや、詰まったところについて
- 先輩エンジニアに聞いてみた
  - 先輩方へのアンケート結果の公開

## 社畜紹介

### 社畜 S

> - 21歳、情報系の専門学校卒です！趣味はユーフォニアム！
> - 現在JavaScriptと格闘中！少しずつわかるようにはなってきましたが、モデルとかまだわからないことがたくさんあります。  
> **~~専門学生時代に学んだはずのSQLとJavaは半分ぐらい頭から吹き飛びました~~**  
取得資格はITパスポート、セキュリティマネジメント試験、基本情報技術者試験です。  
あとはその他諸々。応用情報３連敗中。
> - 目標 SE 像はどんな言語でもできる超エンジニア…にも少しあこがれますが、一番は趣味と仕事どちらも両立できるような **~~社畜~~** エンジニアになりたいです！  
そのためにもまずは基礎から身に着けて、これからの業務を少しでもスムーズに進められるようにしたいと思います！
> - **最後に一言！**  
Qiitaの皆さん、はじめまして！新米社畜のひとり、**社畜S**です！  
他二人がなかなかカオスな自己紹介を繰り広げていて肩身が狭いですが、**同調圧力**には屈さず、他二人に適度にツッコんでいきたいと思います。  
新卒社員ということで、まだわからないことも多くありますが３６５日後には立派な**~~社畜~~**エンジニアになれるよう、これからがんばっていきます！

### 社畜 M

> - 年齢  
22歳・専門学校卒  
>
> - 習得済み言語  
>Java    
>
> - 学習中言語  
JavaScript 、Python、C言語  
>
> - 目標  
学び続け、柔軟性を持ち、協力し合いながら問題解決に努める新米システムエンジニアが現状の目標です！
>
>- 自己紹介  
やめて！資格取得やpiazaの勉強で、モチベーション・ザ・ライトニングを焼き払われたら、  
闇のEラーニングでモンスターと繋がってる社畜Mの脳まで燃え尽きちゃう！  
お願い、倒れないで社畜M！  
あんたが今ここで倒れたら、SやLとの活動はどうなっちゃうの？  
やる気はまだ残ってる。ここを超えれば、paizaに勝てるんだから！  
>  
>**次回「社畜M真の社畜になる」デュエルスタンバイ！**


### 社畜 L

>- 年齢、職歴  
27歳,医療系  
>  
>- 学習状況  
>   - paiza A取得済み言語 　
java,pyton,javascript  
	ただし取っただけ…開発経験0  
>  
>- 資格  
基本情報のみ  
>  
>- 目標とするSE像  
>  - 第一目標  
SEとしてまずどのような知識が必要なのか知る
>
>  - 第二目標  
経験不足でも立派にチームに貢献できると証明する
>  
>- 自己紹介  
俺は前職医療系の、超新米SE。  
勢いで転職活動を決め、なんだかんだで基本情報の勉強を始めた。  
資格勉強に夢中になっていた俺は、そのほかの知識を入れる必要に気づかなかった。  
俺は基本情報だけ取って、気が付いたら……転職できてしまっていた。  
基本情報以外の知識がないと会社のヤツらにばれたら、命を狙われ、周りの人間にも危害が及ぶ。  
博士の助言で正体を隠すことにした俺は、同期に名前を聞かれてとっさに……  
「**社畜 L**」  
と名乗り、仕事に必要な情報をつかむために、エンジニアに関する知識を記録・共有するサイト「Qiita」に転がりこんだ。  
>  
>たった一つの真実見抜く見た目はおじさん、頭脳は高卒、その名は、**迷探偵社畜L**。  
	
## 終わりに  
これからはこの三人で一週間ずつ交代しながら記事を書いていきます。  
まだまだ新米の私たちですが、同じ初心者の方からベテランの方まで…幅広い人たちに私たちの成長記録を楽しんでいただけるよう、努力し、成長していきます！  
### これからよろしくお願いします！

 by社畜S
超初心者が記事を書いてみました

## はじめに
私は先日このような記事を目にしました

https://qiita.com/Sicut_study/items/4e4f49aefb5a1b134582

内容はざっくり「初心者だから書けることあるよね！」というものなのです
そして「勉強においてアウトプットが大切」ということも
そしてこの記事を読んで5分後、この下書きページを開いています
今の時点ではこの記事を公開することができるか、不安ですが…

## 何の超初心者なのか
私は文系大学を卒業して今年の4月から社会人生活が始まった**新卒**です
特に技術職なわけではないのですが、いつかはなれるよう目指している最中です

具体的にはCS50の日本語版カリキュラムを受講している最中です

https://cs50.jp/

つまり独学をしている最中なのですが、**独学**はその文字にもある通り孤独です
プログラミングやAIのスキルを身に付けるための道を独りで歩くには、あまりにも過酷に思えます

そこで先述した記事を見つけたという訳です

## 記事を書く動機
**学習はアウトプットが大事**というのは多くのメディアで目にします
私もその重要性を理解しながらも、アウトプットの場を見つけられずにいました

Qiitaは以前から登録しており、Googleにおすすめされた記事を眺める程度でした
何度か**記事を書いてみたい**と思ったことはありましたが、なかなか勇気が出ず…

その理由として、記事に間違ったことを書いたら四方八方から批判が来るんじゃないか…？
という誇大妄想的な不安があったからでした

しかし先述した記事を読んだ後、
**詳しい人から直接訂正を貰えるのってめっちゃいいじゃん**
という考え方に変わりました

そして超初心者のときに記事を書いておけば、後から見返して当時行き詰っていたところを思い出せる
そして他の超初心者の方の支えにもなる（かもしれない）
と思ったわけです

そういった経緯を経て現在、
**Markdown記法 チートシートとにらめっこしながら**この記事を書いています

## 何を書いていくのか
私がプログラミングを独学していくなかでの肌感としては
**納得する前に進めて、後から納得する方がいい**と思いました

もっと具体的にいうと**体系的に学ぶ前に、断片的に学ぶ**ということです
この学び方自体も間違っているかもしれませんが

つまり何が言いたいかというと、**断片的に学んだ知識を記事にしてアウトプットを行う**
ということです

そうすれば記事を書いている最中に自分の中で納得できる瞬間があるかもしれないし、
記事に付くコメントで教えてもらえるかもしれない

ということなので、私流の「これってこうだよね？」というのを発信していくので、
ご指摘なりご訂正なり頂ければと思っております
よろしくお願いします

よし、記事を書ききった
公開！
別のスプレッドシートのスクリプトをライブラリとして使用する方法【備忘録】

Googleスプレッドシート「サンプルA」で作成したスクリプトを、
同じくGoogleスプレッドシート「サンプルB」で使用したい時の設定方法です。
頻繁に使わないと忘れてしまいそうだったので、備忘録を作成しました。

# サンプルAの中身
例：サンプルAの[シート]に記載されている値を取得する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/fa049fe0-e4b0-7e88-5aa2-6e4a01da408a.png)

```Javascript: GAS
function getItem() {
  
  // サンプルAのデータを取得する
  const ss = SpreadsheetApp.openById('サンプルAのId');
  const sheet = ss.getSheetByName('シート');
  
  // 期待値は"★取得したい内容★" 
  let item = sheet.getRange(2,2).getValue();

  return item;

}
```

# サンプルBで使用するための準備
## サンプルAのスクリプトIDを取得する
プロジェクトの設定を開いて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/43b57c6e-901f-6e8b-131e-e93bf884fa47.png)

この表記の下がスクリプトIDなので、これをコピーする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/54d7b28c-f16b-223e-85fc-dab58565f28c.png)

## サンプルBでライブラリの設定をする
ライブラリを追加から
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/eff54b81-1148-b6ef-c08c-5bebba8af796.png)

さっきコピーしたIDを貼り付けて「検索」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/8481bf48-abe5-f08e-d587-91caa1b0d9ec.png)

IDを設定して「追加」（好きな良い感じのIDでOK）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/90d29fa5-1185-bbe0-5c49-06f8ac1e50d1.png)

:::note warn
IDを設定しないで「追加」するとエラーになります
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/ed1d41c6-5fc9-2523-e88f-e1f69cc18715.png)

:::note warn
しかも厄介なことに、その後IDを設定して「追加」してもまたエラーになります
:::

その時は、またプロジェクトの設定を開いて
”「appsscript.json」マニフェスト ファイルをエディタで表示する”を有効にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/46bc2a38-fb07-0e54-592c-23c3076e04e1.png)

さっきの残骸はここにいるので、不要なデータを削除します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/fecd298b-9a63-0d8c-6867-4a2a8c051763.png)

この場合だと、これが不要なので削除して保存
```
{
    "userSymbol": "",
    "version": "0",
    "libraryId": "*****",
    "developmentMode": true
},
```
設定したIDがライブラリに表示されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/aabd3c75-ec79-078c-a946-048313c22550.png)

# サンプルBの中身
```JavaScript: GAS
function myFunction() {

  const ss = SpreadsheetApp.openById('サンプルBのId');
  const sheet = ss.getSheetByName('表示するシート');

  // ライブラリを呼び出し
  let item = test.getItem();

  sheet.getRange(5,5).setValue(item);
  
}
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726019/4cfad4a0-ddec-f7b5-3332-d780dbf66407.png)

# さいごに
とても便利だったので、備忘録としておきました。
自動切り抜きを使ってYoutubeチャンネルを立ち上げる話

# 生配信の切り抜きAIを使ってYoutubeチャンネルを運営してみたい。(現在進行系)
こんにちは、Webサービスを開発中のrkですX: [@e2eXszEiBC32827](https://twitter.com/e2eXszEiBC32827)。
最近、私は自動でYoutubeのLive配信を切り抜きサービスの開発に取り組んでいて、開発の一環として、実際にYouTubeチャンネルを作ってみて需要が本当にありそうか確かめています！
自動切り抜きサービスの詳細は[こちら](https://qiita.com/rikuya11212001/items/cb9c7878c2feb962503c)
## 
良ければどのようにYoutube チャンネルを運営してるかの参考になると思うので、SNS関連のURLを貼らせていただきます。
[Youtube](https://www.youtube.com/channel/UCCyUrLXOucf-o7MCuqOFYvA)
[twitter](https://twitter.com/mu_ye99437)
[TikTok](https://www.tiktok.com/@toshio_hozonko)
## 切り抜く生配信者

選んだのは、岡田斗司夫さんのYouTubeチャンネルです。岡田さんのチャンネルは、映画やアニメ、人生相談など幅広い分野に関しての配信をしており、的を得たような自分でもハッとしてしまう発言が世間で話題になっています。
また、御本人が切り抜き自体を許可しており、正規の手続きを踏めば誰でも切り抜きができてしまうのが特徴です。

手順は、[こちらの動画](https://www.youtube.com/watch?v=z4c9vOSMpwg)に詳しく説明されています。切り抜きを開始する前に、必ず動画の指示に従い、適切なフォームに情報を入力してください！

## 切り抜き動画の伸ばし方の戦略

現在進行系でYoutubeチャンネル:[としお動画保存庫](https://www.youtube.com/channel/UCCyUrLXOucf-o7MCuqOFYvA)を運営する上で、チャンネル登録者を増やすため、いくつかの戦略を練っていきます。

1. **動画の量**: Youtubeのアルゴリズムでは活発なチャンネルがおすすめに出やすく、また様々な動画を上げることで検索に引っかかりやすくなるのを狙います。
2. **サムネイルの作成**: ほとんどの視聴者がサムネイルから判断して動画を見に来ていると考えているので、より惹きつけられるサムネイルを作っていきます。
3. **複数のソーシャルメディアでの共有**: TwitterやtiktokからもYoutubeチャンネルに誘導することで登録者を伸ばします。
4. **コミュニティとのエンゲージメント**: 視聴者との積極的なコミュニケーションを行い、フィードバックを取り入れることで、コミュニティを成長させます。

以上のポイントを踏まえ、私たちの自動切り抜きサービスを活用して、岡田斗司夫チャンネルの素晴らしいコンテンツをより多くの人に届けることができればと思います。

#### 備考

特にtiktockでは短期間で視聴回数自体は増えたのでかなり効果的かと、、、

---

生配信の盛り上がりポイントを自動で探し出す「切り抜きAI」をつかったYoutubeチャンネル運営、なにかご意見等あれば、Xまでお知らせいただけると嬉しいです。今後もこの記事の方更新していくのでよろしくお願いします!
Terraformのtfstateをconsulで管理して冗長化を試みる

## 概要
tfstateを冗長化するためにtfstateの保管先(backend)をデフォルトのlocalではなくconsul serverを指定する。
consul serverは複数台建ててクラスタを組み、クラスタ間でデータを同期させる。
<img width=67% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123008/a080d95b-819b-559a-f597-c193fa7e09ad.png">


## 仮定
- ホスト1,ホスト2,ホスト3: Consulのdockerを起動するホスト
- ホスト4: terraform を実行するホスト

## 手順
### Consul serverを準備する
1. consul serverのDockerイメージを確認する
    ConsulのDockerイメージは2つあるが、今後はhashicorp/consulの方を更新していくらしいので、そちらを使用する
    - https://hub.docker.com/_/consul
    - https://hub.docker.com/r/hashicorp/consul //こちらを使用する

2. docker-compose.ymlとserver.jsonを各ホスト（ホスト1~3）に作成する

    docker-compose.ymlの例：
    ```
    services:
      consul-server:
        image: hashicorp/consul
        container_name: consul-server
        restart: always
        volumes:
          - ./server1.json:/consul/config/server1.json:ro
        network_mode: "host"
        command: "agent -bootstrap-expect=3 -server -bind=<ホストのIPアドレス> -ui"
    ```
    server1.json or server2.json or server3.json の例：
    ```
    {
            "node_name": "consul-server1",
            "retry_join": [<ホスト1のIP>,<ホスト2のIP>,<ホスト3のIP>],
            "server": true,
            "ui_config": {
                    "enabled": true
            },
            "data_dir": "/consul/data",
            "addresses": {
                    "http": "0.0.0.0"
            }
    }
    ```
### 実際にConsul serverをbackendに指定したTerraformをテスト実行させる
1. ホスト4上にterraformをinstallする
    ```
    apt install gpg
    wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
    echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
    sudo apt update && sudo apt install terraform
    ```

2. terraformを実行する
    とりあえずnginxを建てる簡単なtfファイルのbackendをconsulにしてテストしてみる
    main.tfの例：
    ```
    terraform {
      required_providers {
        docker = {
          source  = "kreuzwerker/docker"
          version = "~> 3.0.1"
        }
      }
      backend "consul" {
        address = "<consul server1のIPアドレス>:8500"
        scheme = "http"
        path = "backendtest/state"
      }
    }
    
    provider "docker" {}
    
    resource "docker_image" "nginx" {
      name         = "nginx"
      keep_locally = false
    }
    
    resource "docker_container" "nginx" {
      image = docker_image.nginx.image_id
      name  = "tutorial_2"
    
      ports {
        internal = 80
        external = 8000
      }
    }
    
    ```
3. `<consul server1のIPアドレス>:8500`にアクセスしてみて、tfstateがアップロードされていれば成功

## 参考サイト
- https://rick-kemery.medium.com/load-balance-a-consul-cluster-using-docker-compose-nginx-and-consul-template-f690d3b4d4b8
- https://knowledge.sakura.ad.jp/2524/
- https://developer.hashicorp.com/terraform/language/settings/backends/configuration
- https://developer.hashicorp.com/consul/tutorials/docker/docker-compose-datacenter
- https://developer.hashicorp.com/consul/tutorials/day-0/docker-container-agents
map, compactMap, flatMapについて

### mapの挙動
配列の全ての要素を参照して新しい配列を返す.
```swift
let intNumberList: [Int] = [1, 2, 3, 4, 5]

let stringNumberList: [String] = intNumberList.map { "\($0)" }

print(stringNumberList) // ["1", "2", "3", "4", "5"]
```

### compactMapの挙動
nil以外の要素を参照して新しい配列を返す.

```swift
let optionalStringNumberList: [Int?] = [1, 2, nil, 4, 5]

let intNumberList: [Int] = optionalStringNumberList.compactMap { $0 }

print(intNumberList) // [1, 2, 4, 5]
```

### flatMapの挙動
多次元配列を参照し, 一次元配列に変換する.

```swift
let intNumberList: [[Int]] = [[1, 2, 3], [1, 2, 3]]

let intNumberListWithFlatMap: [Int] = intNumberList.flatMap { $0 }

print(intNumberListWithFlatMap) // [1, 2, 3, 1, 2, 3]

```

### 併用
flatMapとmapを併用できる.
```swift
let intNumberList: [[Int]] = [[1, 2, 3], [1, 2, 3]]

let stringNumberListWithFlatMap: [String] = intNumberList.flatMap {  $0.map { "\($0)" }

print(stringNumberListWithFlatMap) // ["1", "2", "3", "1", "2", "3"]

```
[Google Tasks API(V1)] Javaでタスクリストから完了したタスクを全て削除する

Google Tasks API V1(Java)を使用して、
タスクリストから完了したタスクを全て削除する方法
についてご紹介します。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Google Tasks API(V1)] JavaでTasks APIを使う](https://qiita.com/doran/items/8a3b7e24d9e0417a7f9a)
を参照ください。
:::

|No||目次|
|---|---|---|
|1||[タスクを全て削除](#1-タスクを全て削除)|
||1|[スコープ](#11-スコープ)|
||2|[実行](#12-実行)|
||3|[レスポンスの内容](#13-レスポンスの内容)|

## 1. タスクを全て削除
指定したタスクリスト内の完了したタスクを全て削除します。

### 1.1. スコープ
このAPIを実行するには、以下のスコープを指定してください。
```
TasksScopes.TASKS
```
[⧉[Google Tasks API(V1)] JavaでTasks APIを使う(2.2 Tasksインスタンスを取得)](https://qiita.com/doran/items/8a3b7e24d9e0417a7f9a#22-tasksインスタンスを取得)
でスコープを指定してください。

### 1.2. 実行

```java
public static void main(String[] args) throws Exception{
    Tasks tasks = getTasks();
    Tasks.TasksOperations op = tasks.tasks();
    
    Tasks.TasksOperations.Clear clear = op.clear("タスクリストID");
    
    clear.execute();
}
```
#### 1.2.1. HTTPリクエスト
POST:　https:\//tasks.googleapis.com/tasks/v1/lists/{タスクリストID}/clear
が実行されます。

#### 1.2.2. クエリパラメータ
クエリパラメータはありません。

#### 1.2.3. リクエストボディ
リクエスボディはありません。

### 1.3. レスポンスの内容
レスポンスはありません。
削除に失敗した場合、例外が発生します。

<br>
<br>
おしまい。。
フォントファイルをサブセット化して軽量化したい

お久しぶりです。
アドベントカレンダー以外での投稿です。

とある案件で時間を表示するWebアプリを作っていたのですが、その時に独自のフォントを使うことになり、
これがなかなかのデータサイズだったのでフォントのサブセット化を行いました。

その時に調べたことをまとめます。

## 作っていたアプリ

数字で時間を表示するアプリです。
ここに独自のフォントを当てます。

| イメージ図 |
| --- |
| ![スクリーンショット 2024-04-11 16.21.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96450/d8d895a5-d8cc-200c-da31-c7894da21331.png) |

使用するフォントは以下の通りです。
`0123456789:`

## サブセット化前のサイズ

とりあえずサブセット化しない状態で、使ってみます。
※ 案件で使っているフォントは見せられないので、 [たぬき油性マジック](https://tanukifont.com/tanuki-permanent-marker/#toc5) で代用します。

| 計測 |
| --- |
| ![スクリーンショット 2024-04-11 15.59.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96450/286f7006-da6b-27a8-f366-2f0dd4acddc8.png) |

時計を表示するだけなのに フォントファイルだけで **`8.8MB`** あります。
デカすぎる。

## サブセット化

フォントのサブセット化を行います。
[fonttools](https://github.com/fonttools/fonttools) というものが良さげだったのそれを使うことにしました。

### インストール

poetry でインストールします。

```bash
$ poetry add fonttools
```

### サブセット化したフォントファイルを作成

fonttools のコマンドでサブセット化を行います。

```bash
$ poetry shell
$ pyftsubset ./TanukiMagic.ttf --text=0123456789: --layout-features='*' 
// TanukiMagic.subset.ttf というファイルが生成される
```

## サブセット化後のサイズ

サブセット化したフォントファイルをWebアプリに当てて再度計測します。

| 計測 |
| --- |
| ![スクリーンショット 2024-04-11 16.09.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96450/2e07f5e3-abc6-2027-6b5e-81da73f71ae2.png) |

サブセット化後は `8.8MB` から **`6.6KB`** になりました。
いい感じです。

## さらなる高みへ

サブセット化したフォントファイルをさらに圧縮することもできます。
woff2 に変換をすることでファイルサイズをさらに小さくすることが可能です。

### インストール

fonttools と別途 `brotli` をインストールします。

```
$ poetry add fonttools
$ poetry add brotli
```

### サブセット化したフォントファイルを作成(woff2)

サブセット化しつつ、 woff2 に変換します。

```bash
$ poetry shell
$ pyftsubset ./TanukiMagic.ttf --text=0123456789: --layout-features='*' --flavor=woff2
// TanukiMagic.subset.woff2 というファイルが生成される
```

### woff2 化後のサイズ

woff2 化したフォントファイルをWebアプリに当てて再度計測します。

| 計測 |
| --- |
| ![スクリーンショット 2024-04-11 16.10.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96450/04a1c2fd-8172-bc1f-6d55-efd9c3e77b31.png) |

**`3.2KB`** とかなり軽量になりました。

### woff2 の注意

一部ブラウザやバージョンによっては woff2 がサポートされていない場合があるので、その辺りは確認しておくと良いです。
参考: https://caniuse.com/?search=woff2

## まとめ

フォントのサブセット化を行うことでフォントファイルを軽量化することができました。
また、さらに woff2 に変換することでファイルサイズをさらに小さくすることができました。
フォントサイズにお困りでしたら、ぜひ試してみてください。

## 参考

* https://fonttools.readthedocs.io/en/latest/subset/
* https://acro5piano.com/post/2022-09-28-pyftsubset/