OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity】スプラトゥーンの弾道を再現してみた

# 概要
Unityでスプラトゥーンの弾道を再現してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/150247b2-4232-df88-048f-c705687c7def.png)

上向きに撃つと射程が少し伸びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/7bc2fd4a-80b8-b6a9-a260-69a26bbd6381.png)

上を向きすぎると射程が短くなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/84d92f9d-141d-a9f1-c408-005ced7ca626.png)

# 詳細
弾が指定した距離まで直進したら、進行方向を下に変化させる実装となっています。
弾道は List\<Vector3> で受け取れるので、LineRenderer に渡して軌道を表示したり、DoTween の DoPath で弾を飛ばしたりできます。

### 引数の説明

|引数名|説明|
|-|-|
|position|発射位置|
|direction|発射方向|
|distance|発射距離|
|out sumMagnitude|戻り値 List\<Vector3> の合計の長さ。DoPath 等で役立ちます|
|【省略可】fallCurveVolume|落下カーブの緩やかさ|
|【省略可】fallCurveDelta|落下カーブの細かさ|
|【省略可】maxFallDistance|カーブ終了後の落下距離|
|【省略可】fallVector|下方向の定義|

# コード
お手持ちの Utility クラスに追加してご利用ください。

``` MathUtil.cs
public static List<Vector3> PseudoParabolaPoses(Vector3 position, Vector3 direction, float distance, out float sumDistance,
            float fallCurveVolume = 1f, float fallCurveDelta = 0.1f, float maxFallDistance = 100f, Vector3? fallVector = null)
        {
            sumDistance = 0f;

            // /* If you want to speed it up even a little, comment it out.
            direction.Normalize();
            fallCurveVolume = Mathf.Max(0.01f, fallCurveVolume);
            fallCurveDelta = Mathf.Max(0.01f, fallCurveDelta);
            // */

            if (!fallVector.HasValue) fallVector = Vector3.down;
            var list = new List<Vector3>() { position };

            position = position + direction * distance;
            sumDistance += distance;
            list.Add(position);

            var diffDirectionRate = Mathf.Acos(Vector3.Dot(direction, fallVector.Value));
            if (diffDirectionRate > 0f)
            {
                // Reciprocal of PI : 0.31830988618f
                var fallLength = diffDirectionRate * 0.31830988618f;
                fallCurveDelta /= fallLength;
                var fallStep = 0f;
                while (fallStep < 1f)
                {
                    fallStep += fallCurveDelta;
                    if (fallStep >= 1f)
                    {
                        fallCurveDelta = fallStep - 1f;
                        fallStep = 1f;
                    }
                    var dir = Vector3.SlerpUnclamped(direction, fallVector.Value, fallStep);
                    var addVector = fallCurveDelta * fallCurveVolume;
                    position += dir * addVector;
                    sumDistance += addVector;
                    list.Add(position);
                }
            }
            sumDistance += maxFallDistance;
            list.Add(position + fallVector.Value * maxFallDistance);
            return list;
        }
```
.familyについて学んでみた!

# familyとは何か?
**こちらが、公式のドキュメント**

https://riverpod.dev/ja/docs/concepts/modifiers/family/
**解説によると**
.family 修飾子の目的は「外部のパラメータをもとに一意のプロバイダを作成すること」です。

といっても、こちらのドキュメントだけでは、理解できませんでした😵
こちらのAPI リファレンスにも書いてあったが、わかりずらかった😵
https://pub.dev/documentation/riverpod/latest/riverpod/FutureProvider-class.html

なので、動くソースコードを使って勉強してみた。
といっても、古いバージョンのソースコードを動くように、書き換えただけですが😅
どんなロジックかというと、enum(列挙型)で定数を作って、その中に4人のメンバーがいて、switch文でメンバーごとに年齢は何歳か戻り値を返すだけですね。
今回使ったのは、family constantというものですね。

**API リファレンスによると**
> 外部パラメーターから値を構築するプロバイダーのグループ。 ファミリーは、プロバイダーがアクセスできない値をプロバイダーに接続するのに役立ちます。

公式のドキュメントにも書かれていたのですが、idを取得するのに、使われていたりするようです。
https://pub.dev/documentation/riverpod/latest/riverpod/FutureProvider/family-constant.html

Widget型のListを作って、その中に、split methodを使って、文字列をpatternにマッチした箇所で分割し、部分文字列のリストを返します。
今回だと、最後のマッチの部分ですね。
この.split最近よく見かける気がする?
で、このコードなんですけど、forEachで書かないと、splitが設定した通りに機能してくれなかったですね!
C#とかPythonでコード書いていた時に、使うことがあってどんな役割があるか知らなくて、調べました😅

## こちらが今回学習用に使ったコードです

**Dartのsplitとは?**
https://api.flutter.dev/flutter/dart-core/String/split.html
```dart:main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

enum Member {
  kboy,
  kayboy,
  sayboy,
  jboy,
}

final familyAgeProvider = Provider.family<int, Member>((ref, member) {
  switch (member) {
    case Member.kboy:
      return 30;
    case Member.kayboy:
      return 20;
    case Member.sayboy:
      return 24;
    case Member.jboy:
      return 33;
    default:
      return 0;
  }
});

class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Widget型の空のListを作る
    final children = <Widget>[];
    // forEachで書かないと、値をとってこれない?
    // for文では、数値が0になる?
    Member.values.forEach((member) {
      final name = member.toString().split('.').last;
      final age = ref.watch(familyAgeProvider(member));
      children.add(Text('$nameさんは、$age歳です.'));
    });

    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: children,
          ),
        ),
      ),
    );
  }
}
```

<img width="400" alt="photo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/9e1548f2-9c39-a634-7faf-e692bf6a4e9e.png">

# 最後に
もっと、すごいのを作りたかったのですが.familyは、意外と難しかった!
なので、他のロジックを考えた時にまた記事を書こうかなと思います。
【Unity】Prefabに関すること総まとめ

プレファブの作成方法
１、project > Prefabsフォルダ作成
２、HierarchieへPrefabにしたい素材をドロップ
３、２を１のPrefabsフォルダへ入れる
4,Hierarchieの素材は消去

プレファブの解除方法
１、Hierarchie > 素材またはファイルを右クリック
２、Prefab < Unpack Completely で解除
(project > Prefabsのプレファブは消えないので安心)

類似するプレファブを複数作成する方法
１、Hierarchie < CreateEmpty < 好きな名前ファイル作成
２、１のファイルへ素材を入れる
３、inspector等を変更
４、１、project > Prefabsフォルダへ格納
５、プレファブの解除
６、フォルダ名変更
７、3から繰り返し
８、Hierarchieから消去
Account Engagement（旧Pardot）勉強方法



Salesforce AccountEngagement（旧Pardot）の勉強方法について解説してみました

今回の内容は動画でも公開しております

https://www.youtube.com/watch?v=-KTXZY-7dII

<iframe width="560" height="315" src="https://www.youtube.com/embed/-KTXZY-7dII" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


## ※Account Engafgement（旧Pardot）って何？


正式名称は
Marketing Cloud Account Engagement　といいます
昔はPardotと呼ばれていた製品です

https://www.salesforce.com/jp/products/marketing-cloud/marketing-automation/

出来ることとして
・質の高いリードの育成を自動化
・営業、サービスと連携し、効率よく案件を成約へ
・マーケティングタッチポイントを最適化しコストを削減

です



まずはサクセスナビをご確認してみてください

https://successjp.salesforce.com/accountengagement/beginner-guide

ここにある
「かんたんPardot初期設定マニュアル」
もよく確認してみてください

サクセスナビで色々と分かると思います


## Account Engagement（旧Pardot）ドリルで勉強しよう

 Account Engagement（旧Pardot） のドリルを確認すれば色々な設定が確認できます
https://quip.com/mvFAA9Q3TM0B#temp:C:OFH280ce46648d3415da2b0301fb

## Trailheadで勉強しよう

Trailheadで Account Engagement（旧Pardot）を学ぶことは可能です
お勧めはこちらです

Pardot Lightning アプリケーションを使用したエンゲージメントの向上とリードの育成

https://trailhead.salesforce.com/ja/content/learn/trails/increase-engagement-nurture-leads-pardot-lightning
Alma Linux VMをHyper-V上で起動するまで 

# 用意するもの

* Hyper-V　※最近のWindowsであればデフォルトでインストールされているはず。 
* Alma Linux image https://ap.edge.kernel.org/almalinux/9.0/isos/x86_64/ 

# 手順 

1. 以下のURLから好きな.isoをDLする。 
    * https://ap.edge.kernel.org/almalinux/9.0/isos/x86_64/
2. ファイルを検証する。　 
    * 検証の仕方は公式を参照 
    * https://wiki.almalinux.org/release-notes/9.0.html#installation-instructions
3. Hyper-Vを起動する。 
    * スタートメニューからHyper-Vを起動する。
4. 画面上、右側のペインから「新規」⇒ 「仮想マシン」を選択する。 
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962888/4db2eb54-5b54-0aec-be52-35783b4fbb58.png)
5. ウィザードの指示に従い設定する。　※ネットワークに接続する場合、スイッチの
選択が必要。 
    * isoを利用するので、インストールオプションは以下を選択。 ※パスは任意
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962888/e37178e0-59b2-1465-a390-e64eecec5b63.png)

6. セキュアブートのテンプレートは「Microsoft UEFI 証明機関」を選択する。 ~~無効にする。　※なぜか有効だと起動できない~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962888/f9daa0a6-a5ff-cdd3-f726-97db8978505a.png)

7. 仮想マシンを起動する。 
8. 仮想マシンに接続する。　※コンソールからSSH接続しても良い。 
9. インストールAlmaLinuxを選択する。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962888/3fd05d34-2e98-d54b-4692-11db517d15cc.png)
10. 言語選択する。 
11. 必要に応じて諸々設定する。 
12. パーティションを設定する。 
    * 「Installation Destination」を押し、 表示された画面真ん中下あたりの「Custom」をチェックして、左上の「Done」を押す。 
13. 「Click here～」をクリックする。　※自動で作ってくれるやつ。 
14. 次の画面で、特に追加で変更がなければ「Done」を押す。
15. 出現したポップアップ右下の「Accept～」を押す。 
## 任意
 * root passwordを設定する。 
    * 「Root password」を押し、パスワードを設定する。 
* Userを作成する。 
* 「Software Selection」を開き、必要そうなツールセットにチェックをする。 
ここでは、「Standard～」を選択した。 

# 確認 

* インストール時に特にエラーが表示されていなければOK。
* 以下のいずれかで、VMにログインする。
    * Hyper-Vから接続
    * コンソールからSSHで接続
* ホストOSとゲストOS間でpingを打つと安心。
[ROS2] rosbagをrecordしてplayする

# [ROS2] rosbagをrecordしてplayする

基本的には公式のこの[リンク](https://docs.ros.org/en/foxy/Tutorials/Beginner-CLI-Tools/Recording-And-Playing-Back-Data/Recording-And-Playing-Back-Data.html)をたどればわかると思います．以下ではもっと簡素に書きます．

## record

以下のコマンドでトピックを`record`します．ここで大事なのが`ROS1`と違って止めるときは`rosnode kill`ではなく`Ctrl+C`で止めます．

```shell
$ ros2 bag record /topic_name1 /topic_name2
```

## play

以下のコマンドでトピックを`play`します．ここで大事なのが`ROS1`と違ってファイルではなくフォルダを指定します．

```shell
$ ros2 play rosbag2_year_month_day-hour_minute_second
```
Ubuntu22.04にPHPをバージョンを指定してインストール

2022.11.12現在
# 環境
1. Ubuntu22.04

この記事ではUbuntu22.04でPHP7.4(を含めた過去バージョン)のインストール方法を示します。

# PHPのインストール
## 通常版
```console:cmd
$ sudo apt install -y php
```
有無を言わさずPHP8.1がインストールされます。

## バージョン指定版
### バージョン7.4の存在確認
```console:cmd
$ sudo apt search php7.4
libapache2-mod-php7.4/jammy-updates,jammy-security 8.1.2-1ubuntu2.8 amd64
  Transitional package
```
何かヒットしますがPHP7.4本体ではない模様

### リポジトリを追加
Ubuntu22.04の標準リポジトリにはPHP7.4がない為、PHP7.4を持っているリポジトリを追加
```console:cmd
$ sudo add-apt-repository ppa:ondrej/php
   :
Press [ENTER] to continue or Ctrl-c to cancel.
# エンター押下
```
### 再びバージョン7.4の存在確認
```console:cmd
$ sudo apt search php7.4
php7.4/jammy 1:7.4.33-1+ubuntu22.04.1+deb.sury.org+1 all
  server-side, HTML-embedded scripting language (metapackage)
```
PHP7.4がある

## PHP7.4をインストール
```console:cmd
$ sudo apt install -y php7.4
```

# おまけ
## リポジトリを削除
リポジトリを追加したけど目的のバージョンがなかった時に原点復帰したい
```console:cmd
$ sudo add-apt-repository --remove ppa:ondrej/php
```
【React】useEffectを使って外部からデータをfetch

## 前提
ランダムな犬の画像が表示されるアプリに、useEffectを使用して初回表示時にDog APIから犬種一覧を取得してみた時の備忘録。
初心者なので間違えてることがあったらお手柔らかにご指摘お願いいたします！！

## useEffectって何がいいの？
>useEffectを利用することでコンポーネントの内容を表示する際に外部のサーバからAPIを経由してデータを取得することやコンポーネントが更新する度に別の処理を実行するということが可能になります。またuseEffectは一つのコンポーネントに複数記述することも可能です。

こちらより引用

https://reffect.co.jp/react/react-useeffect-understanding


## 実際に使ってみる

### まずは今回useEffectを使うDogListContainerコンポーネントをAppコンポーネントに読み出し

```react:App.js
import React from 'react';
import './App.css';
import { Header } from './Header';
import { Description } from './Description';
import { DogListContainer } from './DogListContainer';

export const App = () => {
  return (
    <div className='App'>
      <body>
        <Header />
        <Description />
        <DogListContainer />
      </body>
    </div>
  );
}

export default App;
```

### 犬種一覧データを保持するために、useStateでbreedsとsetBreedsを定義する。
```react:DogListContainer.js
export function DogListContainer() {
  const [breeds, setBreeds] = useState([]);
```
※breedsは犬種

###  useEffectとFetch関数を使って犬種一覧を取得し、用意したstateに格納する
APIのレスポンスから、犬種リストの配列を生成して、breedsに格納する。

```react:DogListContainer.js
  useEffect(() => {
    fetch('https://dog.ceo/api/breeds/list/all')
      .then(response => response.json())
      .then(data => {
        const list = data.message
        setBreeds(Object.keys(list))
      })
  }, []);
```
Object.keys()メソッドは、指定されたオブジェクトが持つプロパティの名前の配列を返す。

外部のサーバのやりとりにuseEffectを利用する場合は第2引数に空配列[]をつける。
でないとコンポーネントの更新のたびにサーバーにアクセスすることになる。

### コード全体
```react:DogListContainer.js
import React, { useState, useEffect } from 'react';

export function DogListContainer() {
  const [breeds, setBreeds] = useState([]);

  useEffect(() => {
    fetch('https://dog.ceo/api/breeds/list/all')
      .then(response => response.json())
      .then(data => {
        const list = data.message
        setBreeds(Object.keys(list))
      })
  }, []);

    return (
        <select name="breed" >
            {breeds.map(breed => (
                <option key={breed} value={breed}>{breed}</option>
            ))}
        </select>
    );
}
```
Laravelのソースコードリーディング第1回

# Modelクラス

Modelクラスの内部のソースを読んでみたいと思います！

こんなコードがあったとします
```php
$user = User::find(1);
```
これはユーザーテーブルからid（primary key）が1のデータを取得するというコードです。
ちなみにfindメソッドは引数に配列を渡して複数取得するとこも可能です。最近知りました。

ここのfindメソッドは静的メソッドとして呼び出されています。ということはModelクラスでstaticで定義されているはずです。
Model.phpのファイルの中を探してみます！
見当たらない、、、

Modelクラスには静的なfindメソッドどころか動的なfindメソッドも定義されていないのです。

これを知った私は、じゃあなんでエラーにならないのか意味が分かりませんでした。

色々調べているうちに`__callStatic`と`__call`というマジックメソッドの存在を知りました。
この2つのマジックメソッドを簡単に説明すると、定義されていない静的メソッドを呼び出した時に通るのが`__callStatic`。
定義されていない動的メソッドを呼び出した時に通るのが`__call`です。

今回の場合だとまず`__callStatic`を通るということです。
では`__callStatic`の中身を見てみましょう！
```php:Model.php
public static function __callStatic($method, $parameters)
{
    return (new static)->$method(...$parameters);
}
```
このように定義されています。
これはつまりこういうことです！
```php
// この2つのコードは同じ意味
(new static)->$method(...$parameters);
(new User)->find(1);
```
このようにして動的なfindメソッドを呼び出しています。
ただこのクラスには動的なfindメソッドもありませんでした。
動的なメソッドが存在しないので呼び出されるのが`__call`です。
```php:Model.php
public function __call($method, $parameters)
{
    if (in_array($method, ['increment', 'decrement'])) {
        return $this->$method(...$parameters);
    }

    if ($resolver = (static::$relationResolvers[get_class($this)][$method] ?? null)) {
        return $resolver($this);
    }

    return $this->forwardCallTo($this->newQuery(), $method, $parameters);
}
```
今回は一番下のreturn文が実行されます。
次は`forwardCallTo`メソッドを見てます。
このメソッドはこのように定義されています。
```php
protected function forwardCallTo($object, $method, $parameters)
{
    try {
        return $object->{$method}(...$parameters);
    } catch (Error|BadMethodCallException $e) {
        $pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';
         if (! preg_match($pattern, $e->getMessage(), $matches)) {
            throw $e;
         }

        if ($matches['class'] != get_class($object) ||
            $matches['method'] != $method) {
                throw $e;
        }

            static::throwBadMethodCallException($method);
    }
}
```
```php
return $object->{$method}
```
これが実行されます。
この`$object`はEloquentのBuilderです。
なのでEloquentのBuilderクラスのfindメソッドが呼び出されることになります。
EloquentのBuilderクラスにはちゃんとfindメソッドがありました！
```php:Builder.php
public function find($id, $columns = ['*'])
{
    if (is_array($id) || $id instanceof Arrayable) {
        return $this->findMany($id, $columns);
    }

    return $this->whereKey($id)->first($columns);
}
```
findメソッドの中身を少し追って見てみましたが、内部ではwhereメソッドが呼び出されてるんですね！
この先が気になる人は続きのコードを読んでみてください！
```php
$user = User::find(1);
```
こんな単純なコードですが結構寄り道してるんだなと思って面白かったです。

英語ですが解説してくれてる動画があるので載せておきます！[YouTube動画](https://www.youtube.com/watch?v=DVDX7wJN08M)

今後も何かしらのメソッドの内部コード解説記事を書けたらなと思います！
ActiveRecord_Relationクラス 配列のように扱える

## 配列のように表示された。
```rb
irb(main):071:0> a = User.where("name LIKE ?", "t%")
  User Load (0.9ms)  SELECT `users`.* FROM `users` WHERE (name LIKE 't%')
=>                                   
[#<User:0x000000010f2a5138 ...    
```
```rb
irb(main):072:0> a
=> 
[#<User:0x000000010f2a5138 
  id: 98,                  
  name: "tarou",           
  email: "aaa@aaa",        
  password_digest: nil,    
  user_image: nil,         
  updated_at: Sat, 01 Jan 2000 00:00:00.000000000 UTC +00:00,
  created_at: Sat, 01 Jan 2000 00:00:00.000000000 UTC +00:00>,
.
.
.
#<User:0x000000010f2a4d50
  id: 103,
  name: "tarou",
  email: "iii@iii",
  password_digest: nil,
  user_image: nil,
  updated_at: Sat, 01 Jan 2000 00:00:00.000000000 UTC +00:00,
  created_at: Sat, 01 Jan 2000 00:00:00.000000000 UTC +00:00>]
```
## クラスは？
```rb
irb(main):073:0> a.class
=> User::ActiveRecord_Relation
```
## 配列のように呼び出せる。
```rb
irb(main):074:0> a[0]
=> 
#<User:0x000000010f2a5138                            
 id: 98,                                             
 name: "tarou",                                      
 email: "aaa@aaa",                                   
 password_digest: nil,                               
 user_image: nil,          
 updated_at: Sat, 01 Jan 2000 00:00:00.000000000 UTC +00:00,
 created_at: Sat, 01 Jan 2000 00:00:00.000000000 UTC +00:00>
```

## 長さを調べることができる。
```rb
a.length
=> 6
```
## joinで文字列の結合もできる。
```rb
irb(main):095:0> a.join(",")
irb(main):096:0*   
=> "#<User:0x000000010f2a5138>,#<User:0x000000010f2a5070>,#<User:0x000000010f2a4fa8>,#<User:0x000000010f2a4ee0>,#<User:0x000000010f2a4e18>,#<User:0x000000010f2a4d50>"  
```
# 感想
これからこれを知っておくことは重要な気がする。
このクラス以下は配列のように扱うのか。
まだ知らないことがたくさんある。
これから勉強だ。
フロントエンドは見えるものをテストしよう

# イントロ

adbentoカレンダー　９日目です。

フロントエンドを実装するにあたって意外と難しいのがテストの設計ではないでしょうか？
何を保証し、どう設計するか？
フロントエンドは、ユニットテストとは違うアプローチが多々必要です。

ここら辺のテストの話を毎回してる気がするのでメモがてら書いていきます。

# 対象者
この記事は、フロントエンドの種類を把握してる人むけに書いてます。
従って、本記事で出てくるテスト手法やツールの詳しい説明は割愛します。

興味がある方は以下の記事などを見てください。

https://qiita.com/KNR109/items/7cf6b24bed318dab5715


# フロントエンドのテストはなぜ難しい?
結論から言えば、曖昧なものを保証しないといけないからです。

バックエンドの最終的な出力はデータなのでそれを検証してテストします。
例えば、 以下のような関数がある場合、返り値が2であることを保証すれば良いです。
```typescript
function two() {
    return 1 + 1
}
assert(tow(),2)
```

しかしフロントのアウトプットは以下の様な画面です。
![スクリーンショット 2022-11-12 13.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179800/11309b9f-2b69-2e5b-c54f-2048e8521d54.png)

画面を構成する要素はCSSはDOM,JSが絡み合っておりとても複雑です。
そのため、完全に正しい画面を保証する場合、テストの種類と量が爆発的に増えてしまいます。

この"正しさ"をROIと勘案しテスト設計を行うがフロントエンドのテストの難しさです。




# 何をテスト対象にするべきか？
フロントエンドの意義はユーザーとシステムを繋ぐインターフェースです。

従って、ユーザーに動作とその結果の表示を検証できれば良いと思います。


* フォームを入力する　 -> ボタンが活性化する。 
* フォームに3000文字以上入れる -> エラーメッセージを出す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179800/21612bd3-5423-36f6-daa2-a52f39c15633.png)

下記のように、機能を発火させる要素とその結果の変化を観測できれば良いです。
従って、以下のような機能発火のトリガー要素はテスト対象に含めましょう。

* ボタン
    * 活性
    * テキスト
* エラー
    * エラーモーダル
    * エラーテキスト
* デザイン
    * デザイン崩れがないか？

# 手法は何を使うべき？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179800/20dfcc84-2835-9b8a-c6f5-add88c2766a6.png)

テストトロフィーに習うと、
インテグレーションテストを厚く書きましょう。

具体的には、以下の2種類で良いと思います。

## componentテスト
react-testing-libaryなど、コンポーネントに対してのテストです。
ユーザーを誘導する要素を検証数ためのテストです。

詳しい内容はこちらを参照

https://zenn.dev/nus3/articles/jest-react-testing-library

## visual regression test.
意図したデザインを保証するためのテストです。

仕組みは非常にシンプルで、変更前と変更後の画像を比較して、その差分を表示してくれます。
よく使われるのは、githubのCIに仕込んでおき、PRと一緒に下記のような画像で変更をチェックする運用です。

下記の画像ですと、紫の部分が変更した差分となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179800/7d8be68b-3e5b-d805-0414-d43f2821555e.png)
引用: https://tech.dely.jp/entry/vis_reg_test


画面の正しさは数式の正しさではなく、人間の主観的な正しさなので、デザイン崩れは、コードベースのテストでは防げません、
従って、人間が目視でチェックするかしかありません。

VRTはこの目視チェックの工程を統一的に表示して補助してくれます。
入れておくことに損はないと思います。
　

# 何から始めるべきか？
ユーザーストーリーの整理から始めましょう。

* どこから始まるのか？
* どこで終わるのか？
* 何が目的か？
* どんな操作をするのか？
    * トリガー -> 結果

上記のように、ユーザーが目的を達するための利用ストーリーを時系列順に書き出しましょう。

グーグル検索であれば
* どこから始まるのか？
    * 検索画面
* どこで終わるのか？
    * 情報が存在するサイト
* 何が目的か？
    * 自分が欲しい情報へ辿り着く
* どんな操作をするのか？
    * 検索フォームに調べたい情報のキーワードを入力
    * 検索結果をクリックして情報がありそうなサイトへ訪問する

このストーリーであれば、下記の情報が得られます。
* 検索フォームが動かないのは致命的なのでテストを書こう
* 複数のサイトを訪問する可能性があるので、検索結果の表示のスピードは計測したほうがいいかも？


このように、
* 致命的ケースは何か？
* ユーザー体験関わる部分は何か？

などを掘り下げながらテストを構築しましょう。


# 最後に
必ずしもテストを書くことが正義とは限りません。
プロダクトや、事業フェーズに応じて、テストの比重は変わります。

そこを勘案しながら設計していきましょう。

それではよきテストライフを
docker環境でgithubへの接続ができなくなった

# docker環境でgithubへの接続ができなくなった
wsl2 / Ubuntu上のdocker container からgit push しようとすると以下のエラーに遭遇
```
Could not resolve hostname github.com: Temporary failure in name resolution
```

github.comの名前解決ができない模様。。。
container内の`/etc/resolv.conf`に以下を追記すると解決。
```/etc/resolv.conf
nameserver 8.8.8.8
```

DNS 8.8.8.8はGoogleが運営するパブリックDNSサービスらしい。
https://www.school.ctc-g.co.jp/sse/columns/ozawa2/ozawa201.html

にしても急にエラーが発生するようになったので根本的な解決ではない可能性あり？？
現状container再起動すると追記内容が消えていしまうためlocalからマウントして対応中。
もっとスマートな解決方法があるはず
ssh接続していると突然画面がフリーズするエラー発生

こんにちは！ヨーヘイです！
Vagrant、Dockerを使用して開発しています。
今回はVagrantをで仮想環境を構築してからssh接続していると突然画面がフリーズするエラーが発生。その後、よくわからないエラー文がターミナルに表示されてssh接続が出来なくりました。

# 1.エラー発生
ssh接続画面がフリーズした後、ターミナルにこんなエラーが表示されました...
````
Message from syslogd@localhost at Oct 27 06:24:29 ...
  kernel:NMI watchdog: BUG: soft lockup - CPU#1 stuck for 631s!
[containerd-shim:3577]
````

# 2.解析
　色々調べてみると、なんかCPUが処理できずにスタックしているとかなんとかと情報がありましたが、これといった解決策がなかなか見つかりません・・・
　諦めかけていましたが、別の作業でVirtualBoxを扱っているときに仮想環境にCPUの割当を調整することが出来るとを発見し、もしかしたらこれで解決できるかも！　と思い即実行に移しました。

# 3.実行したこと
　まずはVirtualBoxの設定画面に移行します。**（設定するときは仮想環境を起動せず、ストップさせた状態にしてください。）**

VirtualBoxを開いて　**設定** を開くと下の画像のように表示されます。
設定を開いたら、**システム**　タブをクリックしてください。
![スクリーンショット 2022-11-12 11.28.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640627/f05c11c7-b89e-ab75-5d37-636c6c0adf40.png)

システムをクリックしたら **プロセッサ** をクリックします。
![スクリーンショット 2022-11-12 11.33.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640627/254e6c22-8faa-1f3c-c722-dc2753ba1338.png)

そしたら、CPUのコア数を仮想環境への割当を調整できます。
自分のは最初1コアしか割当てられてなかったので、4コアまで引き上げました。
![スクリーンショット 2022-11-12 11.38.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640627/0da10122-4425-3115-faba-54ccea37f165.png)


# 3.解決
 その後、 **vagrant up**　コマンドで仮想環境を立ち上げてみたら、見事に解決！！画面もフリーズすることなくスムーズに操作できるようになりました。仮想環境へCPUコア数の割当てが少なくて処理できてなかったのが今回エラーの原因でした。
 このエラーの解決方法についてネットで有益な解決方法が見つからなかったので、今回苦労しました...（泣）自己解決能力の必要性を身にしみて痛感しましたww
それでは皆さん、良いエンジニアライフを!!
Android端末で画面回転のイラッを解決する

# はじめに
スマートフォンで写真や動画を見ているときに、写真や動画の向きを画面にあわせるのにイラッとしたことはありませんか？
そんな時に、スマフォを振るだけで横向き固定・縦向き固定に強制する方法です。
Youtubeアプリでも、動画を横向き再生画面と、縦向きの説明やコメント画面を容易に切り替えることが出来ます。

# 方法
MacroDroid というデバイス自動化アプリを使用します
https://play.google.com/store/apps/details?id=com.arlosoft.macrodroid

以下のようなマクロを２つ登録します
### 画面回転
端末の自動回転が<font color=RED><b>Off</b></font>の時に、端末をシェイクすると
横画面⇔縦画面 のトグルで画面を回転させ固定します。
詳しい設定方法や解説は、ここでは説明しません。
あくまで、「こんな便利なことが出来ますよ」というのが、この投稿の趣旨です。
ただし、少しだけ解説すると縦と横のトグルを実現するために、ユーザ定義変数x(変数名は任意)を定義して実行のたびにTrueとFalseを切り替えて判定に使用しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/c4ce2a3c-7d19-878c-1ab8-a5ee08d9b56d.png)

### 画面固定解除
端末の通知画面の自動回転を<font color=RED><b>On</b></font>にすることで、画面の向きの固定モードを解除するようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/495ece0b-2c7f-c10b-3958-f0238ba26dc1.png)

# 留意事項
固定モードを解除するマクロを用意しておかないと、固定モードを解除することが容易ではないので、あえて画面固定解除のマクロを登録しています。
ubuntu18.04 LTSに「Python3.11」をインストール

## はじめに
Python 3.11の安定板が2022年10月25日(日本時間）にリリースされました。
https://docs.python.org/3/whatsnew/3.11.html
早速、Ubuntuにインストールしてみます。
僕の環境は、Windows11／WSL2のUbuntu 18.04 LTSです。
以下の作業はWindowsターミナルでUbuntuのbashを選択してやってます。

## PPAリポジトリ追加
Python3.11は公式リポジトリにはありません。
まだの場合は、取得可能なPPAリポジトリ（ppa:deadsnakes/ppa）を追加します。
```
sudo add-apt-repository ppa:deadsnakes/ppa
```
実行時の画面イメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962789/7cf295f6-5a58-ae1c-94a5-4833a79d7c1c.png)

## リポジトリ追加後はupdate必須

必ず必要です。
```
sudo apt update
```
実行時画面イメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962789/bf9a673c-194a-a7cd-4b7c-326bd6df6de3.png)

## Python3.11の存在確認

python3.11がインストール可能かリポジトリを確認します。
```
apt search python3.11
```
このようにでてくればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962789/c9d94717-9622-62a7-f800-81bd480c9dc7.png)

## Python3.11のインストール

以下のコマンドでインストールします。
```
sudo apt install python3.11 -y
```
念のため、Python3.11のインストールフォルダを確認しておきます。
```
 which python3.11
```
結果は「/usr/bin/python3.11」でした。
問題ないです。

## 実行は「python3.11」で行います
試しにバージョンの確認をしてみます。
```
python3.11 --version
```
結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962789/d8b4a303-ad34-1f96-5e5f-54e2cb49fd59.png)
OKですね。

## Python3のシンボリックリンクは変更NG
たまに「Python3」でも実行できるよう「update-alternatives」をつかって、Python3のカレントを新しいバージョン（今回なら3.11）にする記事をみます。
でも、やめたほうがいいです。
たしかに、
```
sudo update-alternatives --config python3
```
を実行して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962789/13f59c9c-d33c-9efb-60d8-3d3140c870c6.png)
みたいに切り替えること自体は可能です。
でも、それをやってしまうと、かなりの確率で「apt update」がエラーになります。
以下のようなメッセージを見て、うんざりしたくない人はやめたほうがいいです。

:::note alert
ModuleNotFoundError: No module named 'apt_pkg'
:::

ではでは。
ManicTimeのエクスポートをコマンド（bat）で行いたい

# ManicTimeってなんぞ？

PCの使用履歴を自動で取ってくれるソフト。
↓詳しくはこっち。

https://qiita.com/waokitsune/items/9eeed635ce4327a3c09b

# コマンドでエクスポートしたい

ManicTimeには使用履歴をcsvやxlsxで出力できる機能（画面）がある。
でも画面を開いていちいちマウスぽちぽちするのは面倒。

コマンド（bat）で出力できれば楽だし、定期的に出力していろんな集計、なんかもできる。

今回はそのやり方について。

# ヘルプを見てみよう

まずはどんなコマンドがあるか確認。

```bat:ManicTimeのヘルプを見るコマンド
"C:\Program Files\ManicTime\Mtc.exe" help
```

```export``` っていうコマンドが使えそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/7d9d53c0-8be5-0ca2-6423-60d6dc8a89c2.png)

次にエクスポートのコマンドについて確認。

```bat:ManicTimeのエクスポートのヘルプを見るコマンド
"C:\Program Files\ManicTime\Mtc.exe" help export
```

集計の種類、出力先ファイルパス、期間、拡張子、絞り込み、なんかができるとのこと。
出力コマンドの例も書いてくれてる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9ec7d143-a795-b36b-ddbd-8354cf3eff1d.png)

# バッチコマンドサンプル（基本）

デフォルトはcsv出力。
```/excel``` を付けた時だけxlsxで出力される。

```bat
"C:\Program Files\ManicTime\Mtc.exe" export ManicTime/Applications C:\Users\d\Desktop\mt_test.xlsx /fd:2022-11-12 /td:2022-11-12 /excel
```

# バッチコマンドサンプル（発展）

```bat:出力ファイルパスと集計期間を動的に指定
set time2_=%time: =0%

set file_datetime_=%date:~0,4%%date:~5,2%%date:~8,2%_%time2_:~0,2%%time2_:~3,2%%time2_:~6,2%

set manictime_today_arg_=%date:~0,4%-%date:~5,2%-%date:~8,2%

"C:\Program Files\ManicTime\Mtc.exe" export ManicTime/Applications C:\Users\d\Desktop\%file_datetime_%.xlsx /fd:%manictime_today_arg_% /td:%manictime_today_arg_% /excel
```

例えば2022年11月12日に実行すれば、現在日時を元に…
集計期間『2022年11月12日～2022年11月12日』
ファイル名『20221112_114232.xlsx』
のようになる。

# 参考サイトさん

https://manictime.uservoice.com/knowledgebase/articles/686238-export

https://qiita.com/waokitsune/items/2262b6286c11f2675d91

# バージョン

Windows 10 Home 21H1 19043.2251
ManicTime 5.1.8.0 (64-bit) スタンダード（無料）
Knowledge Import/Export Tools


+ [Invalid file path](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000FxmuC)

私の問題に気づきました。Heroku ツールで試したすべてのエクスポートで、articles.csv の Question 列には、HTML ファイルへのパスではなく、datacategorygroup 情報が含まれていました。Questions 列の値を datacategorygroup 列に移動し、Answers 列の値を Question 列にコピーして、接尾辞を 2 から 1 に変更しました。インポートは成功しました。  


+ [Can I enter an html reference in the .csv file to pull in text?](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000KhbRB)

I figured out the issue.  I was using "backslash" instead of "forward slash" when referencing the html file.  Lesson learned.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/57322e8e-83b1-0d0e-1988-b386f868ad2a.png)

+ [【障害】Error importing images](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007SrA24)
+ [Knowledge Import/Export Toolsが機能していない](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgVG0)

# 文字化け

+ [Encountering problems with the special characters in my German article's title.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T5kvF)

:::note
Thank you Ravendra, updated the encoding as follows and which resolves my issue.

DateFormat=yyyy-MM-dd
DateTimeFormat=yyyy-MM-dd HH:mm:ss
CSVEncoding=UTF-8
CSVSeparator=,
RTAEncoding=UTF-8
DefaultHTMLEncoding=UTF-8
:::




# 関連資料

+ [Create a .csv File for Article Import](https://help.salesforce.com/s/articleView?id=sf.knowledge_article_importer_02csv.htm&type=5)
+ [Import External Content into Salesforce Knowledge](https://help.salesforce.com/s/articleView?id=sf.knowledge_article_importer.htm&type=5)
+ [Error 'The properties file is missing' when you attempt to import an article](https://help.salesforce.com/s/articleView?id=000387800&type=1)
paiza.ioでelixir その66

# 概要
paiza.ioでelixirやってみた。
Scheduler調べてみた。

# サンプルコード

```
defmodule FibSolver do
	def fib(scheduler) do
		send scheduler, {:ready, self()}
		receive do
			{:fib, n, client} ->
			    IO.puts "ok1"
				send client, {:answer, n, fib_calc(n), self()}
				fib(scheduler)
			{:shutdown} ->
			    IO.puts "ok3"
				exit(0)
		end
	end
	defp fib_calc(0), do: 1
	defp fib_calc(1), do: 1
	defp fib_calc(n), do: fib_calc(n - 1) + fib_calc(n - 2)
end

Enum.each 1..3, fn n ->
    IO.puts n
end
(1..3)
|> Enum.map(fn(n) ->
    IO.puts n
end)
spawn(FibSolver, :fib, [self()])
receive do
	{:ready, pid} ->
        IO.puts "ok0"
        send pid, {:fib, 9, self()}
	#{:answer, number, result, _pid} ->
    #    IO.puts "ok1"
end
receive do
	#{:ready, pid} ->
    #    IO.puts "ok0"
    #    send pid, {:fib, 9, self()}
	{:answer, number, result, _pid} ->
        IO.puts "ok2"
        IO.puts result
        send _pid, {:shutdown}
end


```

# 実行結果

```
1
2
3
1
2
3
ok0
ok1
ok2
55
ok3
```

# 成果物

https://paiza.io/projects/LpJhE-nsh51cR_LtzTQ1Dg?language=elixir


以上。
GitHubで自分のプルリクエストをマージできなかった話

結論から言うと、「Require approvals」を見ましょうというお話。
# はじめに
某オウンドメディアの運用のお話です。AWS上にWordPressでサイトを公開して1年ちょっと。今はたまに顧客からの問い合わせを受けたり、カスタマイズの依頼を受けて改修したりしています。
ソースコードはGitHub上で管理していて、カスタマイズの依頼があるとブランチを作ってコードを記述し、プルリクエストを経てからmasterにマージして本番リリースという比較的簡単な運用でやっています。（比較的簡単というのは、リリース時にタグを切ったりしてない・・・という意味で）
# もともとレビュー必須だった
前述のとおり、プルリクエストを経てmasterにマージする手順で運用していて、管理者のみがmasterにマージできるように制限をかけていました。だから開発フェーズでは各担当者はプルリクエストを出して、管理者がレビューしてマージという流れで進めてきて、運用フェーズに移行した後も運用は変えず、担当者が自分一人だけになっても自分でプルリクエストを出して、管理者である自分がレビューしてマージという流れを継承して運用していました。
# あるとき突然に・・・
ある日、いつもと同じように顧客からの依頼でカスタマイズを行い、ステージング環境にリリースするためにプルリクエストを出して、自分でマージしようとしていました。しかし、どうやっても緑色の「Squash and merge」のボタンが出てこない！
「何かコメントを入れなきゃいけないんだったっけ？」とか「気づいてないコンフリクトがあるのかな？」とか色々考えて操作してみたけどどうにもならない。顧客とリリース日を決めてあるし、さて困った・・・
# 一旦回避してリリース
取り急ぎ、リポジトリの管理者になっている他の人に依頼してマージしてもらったのでリリース自体はできましたが、いつも依頼するのも面倒なので調査しました。
`自己レビューでリリースするのは危険なのでは？`というご意見もあろうかとは思いますが、ここではその話は置きます。
# 分かったこと
リポジトリの設定画面に行って、Branchesを選んでブランチ名の所のEditを選ぶとこのような画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102402/dad42874-4380-8fb1-a40a-358e6e1f2a1e.png)
ここでRequire approvelsのチェックがONになっていると[GitHub Docs](https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/approving-a-pull-request-with-required-reviews)に書かれている通り`pull request をマージするには、リポジトリに 書き込み または 管理者 権限を持つユーザーからの指定数の承認レビューが必要`となるのですが、これは同時にこのDocsの一番下に書かれている通り`Pull Requestの作者は、自分自身のPull Requestを承認することはできません`という状態を惹き起こします。つまり自分でプルリクエストを出して自分でマージする運用ができないということになります。
# 疑問として残っていること
今までできていたことが突然できなくなる・・・ということがあっても良いのかどうか、甚だ疑問ではありますが、これはGitHubのポリシーなのであれば仕方ないと思います。しかし、会社から任されてる一人プロジェクトで、自分でプルリクエストを出して、自分で承認してマージという運用は少なくないと思うのに、ググっても`「Require approvals」を外せば行けますよ`という情報が見つけることができませんでした。皆さんどうしてるのだろうかというのが一番大きな疑問です。
あとは「Require approvals」を外したときに、プルリクさえ出せばだれでも勝手にマージできてしまうのではないかという危惧があります。そのあたりはおいおい調べないといけませんね。皆さんはどんな運用をされてるのでしょうか・・・。
GraphFramesを用いたグラフ分析のチュートリアル

[Graph analysis tutorial with GraphFrames \| Databricks on AWS](https://docs.databricks.com/integrations/graphframes/graph-analysis-tutorial.html) [2022/6/9時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

このチュートリアルノートブックでは、グラフ分析を行うためにどのようにGraphFramesを使うのかを説明します。GraphFamesの最適化されたインストレーションが含まれているので、[Databricks機械学習ランタイム](https://qiita.com/taka_yayoi/items/824b507019d3ade7eedc)を使うことをお勧めします。

ノートブックを実行するには:

1. Databricks機械学習ランタイムが実行されているクラスターを使っていないのであれば、[これらの方法](https://qiita.com/taka_yayoi/items/0c7fc7d741aad34bf9d4)を用いて[GraphFramesライブラリ](https://spark-packages.org/package/graphframes/graphframes)をインストールします。
1. KaggleからBay Area Bike Share[データ](https://www.kaggle.com/benhamner/sf-bay-area-bike-share)をダウンロードして解凍します。サードパーティの認証を用いてKaggleにサインインするか、Kaggleアカウントを作成してサインインする必要があります。
1. [Explore and create tables in DBFS](https://docs.databricks.com/data/data-tab.html)で説明されている方法で`station.csv`と`trip.csv`をアップロードします。

    テーブル名は`station_csv`と`trip_csv`になります。

## GraphFramesによるグラフ分析ノートブック

https://github.com/taka-yayoi/public_repo_2/blob/master/graph_analysis/graph-analysis-graphframes.scala

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Power Automate の「タイムゾーンの変換」アクションの「書式設定文字列」にイラっとした話

# 自己紹介
えー、こんにちは。七寺（なでら）と申します。製造業に勤務するサウナが好きな男です。
今回、初投稿です。よろしくお願いいたします。
# 前フリ
先日、社内で Power Automate の勉強会をやったんですよ。
知識は浅いんですが、一応、ボクが講師役で。

そこで、
「日付表記 2022-10-10 ではなく、10月28日 のようにできますか？」
という質問があり、
「タイムゾーンの変換」を使って、軽くサンプルのフローを作ったんです。

いま、冷静に振り返ると
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/fd26e930-4c4d-d8c0-6222-ba7b04cf02ab.png)
が正解なのはわかるんですが、ちょっと欲しがっちゃって、
「もっと簡単な方法で説明したるがな！」と、既定の書式から選ぶことにしました。
（いつもは formatDateTime とかでやっちゃうので実はこのアクション、あんまり使ったことが無かったんですが）
![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/ea9124a7-9e7d-4852-0e04-ba0cc2c47d49.png)
ドロップダウンリストで親切にサンプルまで表示してくれることに感謝しつつ
「月日パターン - 6 月 15 日[m]」を選んだんですが、結果は
![fig5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/d38f4d2c-b3ca-2427-ee70-fb394ce29218.png)
ええ？いやいや、ちゃうやん。
「November」って、なんでスカしてんの？

他の日本表記の書式を選択してみても、「11/10/2022」とか「Saturday, November 10, 2022」とか。
ここでフツーに前述の「MM月dd日」で終われば良かったんですが、残り時間がほどんどない状態に気持ちが焦り、
「出力時に formatDateTime を使えば良いと思います」という謎の説明でタイムオーバー。

いま思い出しても、「うわああああああ」ってなります。

# ここから本題
そんなわけで、「タイムゾーンの変換」の「書式設定文字列」のドロップダウンリストで表示される出力例と実際の出力の違いをまとめました。

|書式|出力例 |実際の出力  |出力例の正誤  |
|---|---|---|---|
|短い形式の日付パターン|2009/6/15  |11/12/2022 |×  |
|長い形式の日付パターン|2009 年 6 月 15 日(月)  |Saturday, November 12, 2022  |×  |
|完全な日時パターン<br>(短い形式の時刻)|2009 年 6 月 15 日(月)午後 1:45  |Saturday, November 12, 2022 8:19 AM  |×  |
|完全な日時パターン<br>(長い形式の時刻)|2009 年 6 月 15 日(月)午後 1:45:30  |Saturday, November 12, 2022 8:19:42 AM  |×  |
|一般の日時パターン<br>(短い形式の時刻)|2009/6/15 午後 1:45  |11/12/2022 8:20 AM  |×  |
|一般的な日時パターン<br>(長い形式の時刻)|2009/6/15 午後 1:45:30  |11/12/2022 8:20:19 AM  |×  |
|月日パターン|6 月 15 日  |November 12  |×  |
|ラウンド トリップ<br>日時パターン|2009-06-15T13:45:30.0000000-07:00  |2022-11-12T08:21:00.6915822  |×  |
|RFC1123 パターン|2009 年 6 月 15 日(月) 20:45:30 GMT |Sat, 12 Nov 2022 08:21:34 GMT  |×  |
|並べ替え可能な<br>日時パターン|2009-06-15T13:45:30  |2022-11-12T08:21:57  |〇  |
|短い形式の<br>時刻パターン|午後 1:45  |8:22 AM  |×  |
|長い形式の<br>時刻パターン|午後 1:45:30  |8:23:04 AM  |×  |
|世界共通の並べ替え可能な<br>日時パターン|2009-06-15 13:45:30Z  |2022-11-12 08:23:30Z  |〇  |
|汎用の完全な日時パターン|2009 年 6 月 15 日(月)午後 8:45:30  |Saturday, November 12, 2022 8:23:51 AM  |×  |
|年月パターン|2009 年 6 月 |November 2022  |×  |

ほぼウソやんか・・・。
初心者を驚かせようって、イタズラ心なんか？
「一般<b>の</b>日時パターン(短い形式の時刻)」と
「一般<b>的な</b>日時パターン(長い形式の時刻)」の微妙な翻訳ズレも気になるし・・・。

ボクが見つけられないだけで、どこかにローカライズの設定方法があるんやろか。

# 結論
社内勉強会の講師をするときは、ちゃんと知識を修得して、残り時間がない時も冷静に対応できるようにしましょう。

# 参考
https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/standard-date-and-time-format-strings#Resources#Resource
paiza.ioでelixir その65

# 概要
paiza.ioでelixirやってみた。
Process調べてみた。

# サンプルコード

```

pid = spawn fn -> 
	IO.puts 5 * 7 
end
self
|> IO.inspect
Process.alive? pid
|> IO.inspect
Process.alive? self
|> IO.inspect
Process.info self
|> IO.inspect

defmodule ProcessTest do
	def do_receive do
		receive do
			{:key, msg} -> 
				"match " <> msg
			{:other, msg} -> 
				"not match" <> msg
		after
			1_000 -> 
				"after 1sec"
		end
	end
end

send self, {:key, "value"}
|> IO.inspect
send self, {:other, "other"}
|> IO.inspect
:erlang.process_info(self(), :message_queue_len)
|> IO.inspect
IO.puts ProcessTest.do_receive
:erlang.process_info(self(), :message_queue_len)
|> IO.inspect

IO.puts ProcessTest.do_receive
:erlang.process_info(self(), :message_queue_len)
|> IO.inspect

IO.puts ProcessTest.do_receive



```

# 実行結果

```
35
#PID<0.92.0>
#PID<0.95.0>
#PID<0.92.0>
#PID<0.92.0>
{:key, "value"}
{:other, "other"}
{:message_queue_len, 2}
match value
{:message_queue_len, 1}
not matchother
{:message_queue_len, 0}
after 1sec
```

# 成果物

https://paiza.io/projects/pmv0M_gzBeqhmR7eu1-KPg?language=elixir


以上。
paiza.ioでelixir その64

# 概要
paiza.ioでelixirやってみた。
Scheduler使ってみた。

# サンプルコード

```

defmodule FibSolver do
	def fib(scheduler) do
		send scheduler, {:ready, self()}
		receive do
			{:fib, n, client} ->
				send client, {:answer, n, fib_calc(n), self()}
				fib(scheduler)
			{:shutdown} ->
				exit(0)
		end
	end
	defp fib_calc(0), do: 1
	defp fib_calc(1), do: 1
	defp fib_calc(n), do: fib_calc(n - 1) + fib_calc(n - 2)
end

defmodule Scheduler do
	def run(num_processes, module, func, to_calculate) do
		(1..num_processes)
		|> Enum.map(fn(_) ->
			spawn(module, func, [self()])
		end)
		|> schedule_processes(to_calculate, [])
	end
	defp schedule_processes(processes, queue, results) do
		receive do
			{:ready, pid} when length(queue) > 0 ->
				[next | tail] = queue
				send pid, {:fib, next, self()}
				schedule_processes(processes, tail, results)
			{:ready, pid} ->
				send pid, {:shutdown}
				if length(processes) > 1 do
					schedule_processes(List.delete(processes, pid), queue, results)
				else
					Enum.sort(results, fn {n1, _}, {n2, _} ->
						n1 <= n2
					end)
				end
			{:answer, number, result, _pid} ->
				schedule_processes(processes, queue, [{number, result} | results])
		end
	end
end

to_process = [27, 32, 12, 26, 24, 10, 9, 8, 7, 6, 5, 17, 30, 11, 13]
Enum.each 1..7, fn num_processes ->
	{time, result} = :timer.tc(Scheduler, :run, [num_processes, FibSolver, :fib, to_process])
	if num_processes == 1 do
		IO.puts inspect result
		IO.puts "no   time(ms)"
	end
	:io.format "~2B   ~.1f~n", [num_processes, time / 1000.0]
end



```

# 実行結果

```
[{5, 8}, {6, 13}, {7, 21}, {8, 34}, {9, 55}, {10, 89}, {11, 144}, {12, 233}, {13, 377}, {17, 2584}, {24, 75025}, {26, 196418}, {27, 317811}, {30, 1346269}, {32, 3524578}]
no   time(ms)
 1   104.6
 2   99.1
 3   99.7
 4   99.0
 5   100.0
 6   101.0
 7   99.1
```

# 成果物


https://paiza.io/projects/zfhAWqZFnYTmp5klpUd64Q?language=elixir


以上。
Elixir refの作り方

[IEx.Helpers.ref/1]: https://hexdocs.pm/iex/IEx.Helpers.html#ref/1
[IEx.Helpers.ref/4]: https://hexdocs.pm/iex/IEx.Helpers.html#ref/4
[Kernel.make_ref/0]: https://hexdocs.pm/elixir/Kernel.html#make_ref/0
[Erlang]: https://www.erlang.org/doc/index.html
[Elixir]: https://elixir-lang.org/
[IEx]: https://elixirschool.com/ja/lessons/basics/iex_helpers
[ref]: https://www.erlang.org/doc/reference_manual/data_types.html#reference

[Kernel.make_ref/0]で[ref]を作ることができます。

例えばテストコードの中でダミー[ref]を作りたい場合にも使えます。

```elixir
make_ref()
```

[IEx]の中で[ref]を作りたい場合は[IEx.Helpers.ref/1]と[IEx.Helpers.ref/4]が便利。

```elixir
iex

iex> ref("0.1.2.3")
#Reference<0.1.2.3>

iex> ref(0, 1, 2, 3)
#Reference<0.1.2.3>
```

https://elixirforum.com/t/how-to-create-dummy-reference-in-elixir/22248?u=mnishiguchi

[ref]に出くわすことはあまりありませんが、例えばIoT開発で他のデバイスとI2Cで通信するときに登場します。

https://github.com/elixir-circuits/circuits_i2c

元氣ですかーーーーッ！！！

https://qiita.com/torifukukaiou/items/17d55cf896c24b13350e

## ご参考までに

https://qiita.com/piacerex/items/e0b6e46b1325bb931122

https://qiita.com/torifukukaiou/items/1edb3e961acf002478fd

https://qiita.com/piacerex/items/e5590fa287d3c89eeebf
Debian 12 (bookworm)にSteamをインストールする

一足早くDebian12でもゲームがしたい！ってことでインストールしたときのメモを書いておきます。

### 環境
Debian 12 (Testing)
GNOME 43.1
nvidia-driver: 390 (legacy)

### 1 - steam-launcherのインストール
公式サイトからsteam_latest.debをダウンロードします。

https://store.steampowered.com/about/

次に、これを上から順に実行してインストールします。

```
~# sudo dpkg --add-architecture i386 (<= Steamを起動してエラーメッセージを表示していない場合)
~# apt update
~# add-apt-repository contrib
~# add-apt-repository non-free
~# apt update
~# apt install ./steam_latest.deb
```

### 2 - 必要パッケージのインストール
本来であれば、そのままsteamを実行すれば自動的に必要なパッケージがインストールされるのですが、自分の場合「既存のパッケージを削除する必要があるけど自動処理だと削除が無効化されてるからできねぇwww」というエラーが表示されてうまくいきませんでした。
なので、手動でパッケージをインストールしました。

```
~# apt install libc6:amd64 libc6:i386 libegl1:amd64 libegl1:i386 libgbm1:amd64 libgbm1:i386 libgl1-mesa-dri:amd64 libgl1-mesa-dri:i386 libgl1:amd64 libgl1:i386 nvidia-legacy-390xx-driver-libs:i386 steam-libs-amd64:amd64 steam-libs-i386:i386
```

インストールが完了したらrootを抜けてsteamを起動しましょう。
```
~# exit
~$ steam
```
Java enum型とは

PHPerがJavaを触る機会をいただけたので備忘録として

## enum型(列挙型)とは
複数の定数を一つのクラスとしてまとめておくことができる型。

enum型はクラスとして定義されるので、フィールドやメソッドも定義できる点が大きな特徴。
enumのインスタンス化は、enum内部で行う１回のみ。
これにより、enumの各インスタンスは、プログラムの中で1つであることが保証される。
なので、enumは定数として利用できる。

## 基本の書式

```enumTest.java
public enum enum型名 {
  定数1,
  定数2,
  定数3
}
```

初期値に数字や文字列の値を定義する場合は、以下のようにフィールドやコンストラクタの定義を行う。

数値の値を定義する場合
```enumSports.java
public enum Sports {
  BaseBall(0),
  Tennis(1),
  HandBall(2),

  private int id; //フィールドを定義
  
  private Sports(int id) {
    this.id = id;
  }//コンストラクタの定義
}
```

文字列の値を定義する場合
```enumFoods.java
public enum Foods {
  Potato("Hokkaido"),
  Tomato("Kumamoto"),
  Spinach("Chiba"),

  private String prefecture; //フィールドを定義
  
  private Foods(String prefecture) {
    this.prefecture = prefecture;
  }//コンストラクタの定義
}
```

enum型を使用する際は、クラスのメソッドのように、enum型名.定義名と記載する

## Javaのenumを使いたい場合

- 定数の種類・数を明確にしたい時
- 戻り値を明確化してプログラムの安全性・確実性を高めたい時
Elixirでダミーpidを作りたい

[IEx.Helpers.pid/1]: https://hexdocs.pm/iex/IEx.Helpers.html#pid/1
[IEx.Helpers.pid/3]: https://hexdocs.pm/iex/IEx.Helpers.html#pid/3
[:c.pid/3]: https://www.erlang.org/doc/man/c.html#pid-3
[Creating a fake or dummy pid in elixir]: https://stackoverflow.com/q/32818549/3837223
[Erlang]: https://www.erlang.org/doc/index.html
[Elixir]: https://elixir-lang.org/
[IEx]: https://elixirschool.com/ja/lessons/basics/iex_helpers
[pid]: https://www.erlang.org/doc/reference_manual/data_types.html#pid

テストコードの中でダミー[pid]を作りたい場合は[Erlang]の[:c.pid/3]が便利。

```elixir
:c.pid(0, 21, 32)
```

[IEx]の中でダミー[pid]を作りたい場合は[Elixir]の[IEx.Helpers.pid/1]と[IEx.Helpers.pid/3]が便利。

```elixir
iex

iex> pid("0.21.32")
#PID<0.21.32>

iex> pid(0, 21, 32)
#PID<0.21.32>
```

https://stackoverflow.com/q/32818549/3837223

https://qiita.com/torifukukaiou/items/17d55cf896c24b13350e

## ご参考までに

https://qiita.com/piacerex/items/e0b6e46b1325bb931122

https://qiita.com/torifukukaiou/items/1edb3e961acf002478fd

https://qiita.com/piacerex/items/e5590fa287d3c89eeebf
shuffle()の使い方

リストをランダムに並び替えることができるメゾット
→「shuffle()」を利用する

ランダム関数 import randomで、ランダム変数を読み込む。そして、リストに格納。
list = ['a','b','c']
listをシャッフルするために、random.shuffle(list)でシャッフル。
そして、書き出すために、print(list)で書き出す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952699/8f8bac5b-70f3-da31-125d-5a25394d30f8.png)

■実行結果

['b', 'c', 'a']
['c', 'a', 'b']
['c', 'a', 'b']

実行を繰り返すと、a,b,cの順序が入れ替わる。
JavaScriptのジェネレーター関数で二つのDateオブジェクトの期間に月ごとの反復処理を施す方法

はいさい！オースティンやいびーん！んながんじゅーやいびーみ？

# 概要

JavaScriptのジェネレーター関数を使って`Date`オブジェクトの期間を月ごとの期間にして繰り返し処理を行う方法を紹介します。

## ジェネレーター関数について

JavaScript開発者の多くはJavaScriptのジェネレーター関数を必要だと感じたことがないのではないでしょうか？

実際、ジェネレーターを使わずにやっていても優秀なJavaScript開発者としてやっていけるのだと思います。

しかし、ジェネレーター関数を自分のコーディング道具箱に加えると、時々助かることがあります。

ジェネレータ関数は、`for...each`構文で使えるオブジェクトを返してくれる関数です。

つまり、**半数処理プロトコル**のオブジェクトを返す関数です。

[半数処理プロトコル](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Iteration_protocols)のオブジェクトで代表的な物をいえば`Array`がもっとも一般に知れているかと思います。

その`Array`と同じような処理ができるオブジェクトを作ってくれるのは、[`Generator`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Generator)なのです。

今回は、二つの`Date`オブジェクトから成る期間の月ごと反復処理を、`Generator`を使って行う方法を紹介します。

# ジェネレーター関数の定義方法

ジェネレーター関数は以下のように定義します。

```javascript
function* myGen(arg) {
  yield "cake";
  yield "is";
  yield "yummy";
  yield arg;
}
```

`function`の後に`*`がついているものはジェネレーター関数になります。`yield`という不思議な単語が出てきますが、これは通常関数の`return`だと考えればいいです。

上記のジェネレーター関数を試しに`for...each`で反復処理してみると以下のような結果になります。

```javascript
const myIterator = myGen(47);

for (const result of myIterator) {
  console.log(result);
}
```

![スクリーンショット 2022-11-12 9.24.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/24a8cd45-fa71-9e3a-1acd-d8fdf21c5b1c.png)

このように簡単にジェネレーター関数が使えます。

ジェネレーター関数の中に`while`構文も、`for...each`構文も使えるので、`yield`ごとになんらかの処理を施してから返すことができます。

今回の記事では触れませんが、[非同期処理のジェネレーター関数](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator)も作れます。

# Dateオブジェクトの月ごと反復処理

あまり時間がないので:sweat_smile: 単刀直入に解決法を紹介します。

```typescript
export function* generateMonthlyInterval(start: Date, end: Date) {
  const startYear = start.getFullYear();
  const startMonth = start.getMonth();
  const endYear = end.getFullYear();
  const endMonth = end.getMonth();
  if (startYear > endYear) throw Error("start year must be less than end year!");
  if (startMonth > endMonth) throw Error("Start month must be less than end month!");
  let currentMonth = startMonth;
  let currentYear = startYear;

  while (currentYear < endYear || currentMonth <= endMonth) {
    const yieldDate = new Date()
    yieldDate.setFullYear(currentYear);
    yieldDate.setMonth(currentMonth);
    yield yieldDate;
    if (currentMonth === 11) {
      currentMonth = 0;
      currentYear++;
    } else {
      currentMonth++;
    }
  }
}
```

これをJavaScriptにコンパイルして以下のようなコードでテストします。

```javascript
const interval = generateMonthlyInterval(new Date("2021/10/1"), new Date("2022/11/12"));

let months = 0;
for (const month of interval) {
  console.log(month);
  months++;
}

console.log("total months: ", months);
```

すると以下のように、開始と終了の`Date`オブジェクトの間の月々の処理ができます。

![スクリーンショット 2022-11-12 9.31.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/5f72c206-ff56-f64e-4820-ea9fb3651e9f.png)

# まとめ

ジェネレーター関数を少し紹介してまいりましたがいかがでしょうか？

Python開発者なら、ジェネレーター関数が日常的に活躍するかと思いますが、JavaScriptでジェネレーターを使う場面はそんなにない気がします。

無闇に使う必要はないのですが、ジェネレーター関数でより簡潔に解決できる課題があるときに、この道具をぜひ活用していただければと思います。
ネットワーク構築 #10(DHCP設定)

# 今回の内容
DHCPサーバーを立てて、IPアドレスを自動取得する。
実施日:2022/10/15～2022/11/12

# 設定
サーバーにDHCPを導入します。
```
sudo apt install -y isc-dhcp-server
```
設定ファイルの編集
```
sudo nano /etc/dhcpd/dhcp.conf
下記を追記
subnet 192.168.6.0 netmask 255.255.255.240 {
   range 192.168.6.2 192.168.6.15;
   option subnet-mask 255.255.255.240; 
   option routers 192.168.6.1;
   option domain-name-servers 192.168.1.1;
}
```
DHCPサーバーの状態確認
```
#設定ファイルの反映
sudo systemctl restart isc-dhcp-server
#DHCPサーバーの状態確認
sudo systemctl status isc-dhcp-server
#Activeの箇所がactive(runnning)になっていれば正常に動作しています。
```
ルーター側の設定
DHCPサーバーの設置しているセグメントが192.168.2.0/29
自動取得したいクライアントPCの設置しているセグメントが192.168.6.0/28
セグメントが異なるため、DHCPサーバの設定だけだとIPアドレスが割り当てられません。
DHCPサーバーとクライアントPCの間を通過するルーターのインターフェースに以下の設定をします。
DHCP Discover(IPアドレス発行依頼)がブロードキャストで送信しているため。
```
(config)#
(config-if)# ip helper address 192.168.2.5
```

設定は以上です。

# エラー対応
上記、設定をし、実際にクライアントPCへIPアドレスを発行されるか確認しました。
クライアント側のPC画面のネットワークアイコンを確認しても地球儀?のマークでネットワークに繋がっていません。
サーバー側で確認するとDHCP DiscoverとDHCP Offerまでは実行されていることが確認出来ました。
その後のDHCP RequestとDHCP Ack以降の履歴がありません。

設定した内容を再確認しても、設定内容に問題はなかったです。
試しにクライアントが接続されているインターフェースをOSPFに紐づけしたところ、問題なくIPアドレスをサーバーから付与されました。
クライアントとそのルーターが直接接続されていただけだったのが原因のようでした。
それだと、そもそもDiscoveryすら実行しないと思うのですが。。。

疎通確認のため、クライアントPCから8.8.8.8へpingを、ブラウザでyahooの画面が表示されました。

今回はここまで。
Gitで誤って異なるユーザで初回プッシュしてしまった時の対処方法


## 課題

### 1
Gitで異なるユーザで初回プッシュしてしまったので、正しいユーザでプッシュし直したい

### 2

ググってみると`git push -f origin HEAD^`を実行しろ、とあるのでやってみるとエラーとなる。

```bash
$ git push -f origin HEAD^:main
error: src refspec HEAD^ does not match any
error: failed to push some refs to 'github.com:hoge.git'
```

## 対処法

以下コマンドを実行する

```bash
$ git update-ref -d HEAD
```

git logをするとログがなくなっている状態となる

```bash
git log
fatal: your current branch 'main' does not have any commits yet
```

ユーザ設定変更する

```bash
git config user.name "hoge"
git config user.email "hoge@hoge.com"
```

変更内容を確認する

```bash
$ cat .git/config

...

[user]
        name = hoge
        email = hoge@hoge.com
```

コミットする

```bash
$ git commit -m "first commit"
```

git logしてみる
Author部分の名前とメールアドレスが変更後のものになっていることを確認

```bash
$ git log
```

プッシュする

```bash
$ git push -f origin main
```

## 参考

https://tamata78.hatenablog.com/entry/2015/08/18/215738

https://www.tweeeety.blog/entry/2017/04/18/000621