OmniAICreator/Qiita-1.07M huggingface dataset:
[UE4]文字列がWidgetからはみ出した時に省略表示する（複数行編）

# はじめに

Widgetで文字数が多い時に、指定したサイズ内に収まるように一部を「...」で省略させる方法の備忘録です。
力技で解決しているので、もっと良いやり方があれば教えてください。

#### Before：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/831c2cf5-69d9-cc44-3124-3d991197bda1.png)
#### After：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/f591d758-ae1e-27ab-a9c3-29682b73859b.png)

改行しないバージョンはこちら

https://qiita.com/abricheese/items/55a18bc2891f91d3a8df

# 環境

Windows10
UE4.27.2

# 事前準備
RichTextBlockの「Auto Wrap Text」をTrue、「Wrapping Policy」を「Allow Per Character Wrapping」に変更して、文字数に応じて改行するようにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/d94235ae-a523-e17c-3fcb-5be5176bfb9d.png)


# 実装
ざっくり解説すると、指定したサイズ内に収まるまでループ内で1文字ずつ減らしています。（力技）

注1）TextBlockの大きさで判別しているため、CanvasPanel直下等、文字数に応じてTextBlockの大きさが変わる状態でないと使えないと思われます。
注2）Widgetを表示（Add to Viewport等）したのと同じフレームで実行すると上手くいかないようです。Delayを入れるなどして別フレームで実行してください。（原因までは追えていません）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/42122a81-8824-e920-cd2c-99d50cc712b6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/85d64533-a388-f2f8-daf3-ba5af7660e25.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/3109f314-c65f-3547-e815-c407fa0932a5.png)
jest でスタブする方法まとめ

基本的には `jest.spyOn()` だけでほとんどのユースケースをカバーできる。

## グローバル関数のスタブ

```javascript
const spy = jest.spyOn(global, 'parseInt')
            .mockReturnValue(10)
```

## クラスメソッドのスタブ

```javascript
const spy = jest.spyOn(Date, 'now')
            .mockReturnValue(1577804400000);
```

## インスタンスメソッドのスタブ

```javascript
const spy = jest.spyOn(MyClass.prototype, 'myMethod')
            .mockReturnValue('mocked');
```

メソッドが getter/setter の場合、第 3 引数に `get`　or `set` を指定する。

```javascript
jest.spyOn(MyClass.prototype, 'myMethod', 'get')
```

### 特定のインスタンスのメソッドのスタブ

↑ は MyClass の全てのインスタンスが対象なのに対して、特定のインスタンスに絞ってメソッドをスタブする。

```javascript
const ins1 = new MyClass();
const ins2 = new MyClass();
const spy = jest.spyOn(ins1, 'myMethod')
            .mockReturnValue('mocked');

ins1.myMethod();  // スタブされている
ins2.myMethod();  // こちらはスタブされない
```

## プロパティのスタブ

インスタンスの getter メソッドのスタブ方法と同じで、第 3 引数に `get` を指定してやる必要がある

```javascript
const spy = jest.spyOn(HTMLElement.prototype, 'offsetTop', 'get')
            .mockReturnValue(10);

const element = document.querySelector('div');
element.offsetTop;  // 10
```

## export default / named export のスタブ

スタブ対象のモジュール

```typescript:myModule.js
export function foo() { ... }
export default function() { ... }
```

スタブの方法。ES Module の場合 `import *` する必要がある。

```javascript
import * as myModule as fn from './myModule';

// named export の Stub
const spy = jest.spyOn(myModule, 'foo')
            .mockImplementation(() => 'mocked');

// export default の Stub
const spy = jest.spyOn(myModule, 'default')
            .mockImplementation(() => 'mocked');
```
[UE4]文字列がWidgetからはみ出した時に省略表示する（1行編）

# はじめに

Widgetで文字数が多い時に、指定したサイズ内に収まるように一部を「...」で省略させる方法の備忘録です。
力技で解決しているので、もっと良いやり方があれば教えてください。

#### Before：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/e13b0c20-189e-2137-a5da-e278bde043aa.png)
#### After：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/7be8fb9a-d7a4-8c51-a9d0-8362865847cf.png)

改行ありのバージョンはこちら

https://qiita.com/abricheese/items/6398016413f948e144a0

# 環境

Windows10
UE4.27.2

# 実装
ざっくり解説すると、指定したサイズ内に収まるまでループ内で1文字ずつ減らしています。（力技）

注）TextBlockの大きさで判別しているため、CanvasPanel直下等、文字数に応じてTextBlockの大きさが変わる状態でないと使えないと思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/f16ef2bc-68aa-c9b7-6f7f-b146896aa1f7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/62cec7df-af16-33b9-09ef-d9c8c9801422.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/7943c9cb-8edc-bfc1-be5b-d9f5b20bce97.png)
[UE4]ScrollBoxやListViewでスクロールバーの下まで背景色を表示させる

# はじめに

ScrollBoxやListViewでスクロールバーの下まで背景色を表示させる方法の備忘録です。
（UEのデザイナー画面はコメントが入れられないので、どういう意図で設定していたのかすぐ忘れてしまうため。）

https://twitter.com/abricheese/status/1588439211996491782

# 環境

Windows10
UE4.27.2

# 実装

リスト（ScrollBoxやListViewを持つWidget）とリスト内に表示する要素のWidgetの2つに分けて説明します。

### リスト

リスト（ScrollBoxやListView側）の階層は下記のようにします。
SizeBoxの子要素にScrollBoxを配置、SizeBoxは後に説明するクリッピング用なので、別のものでも大丈夫です。
リストが埋まっていないとき用にダミーの背景を配置するために、GridPanelの子要素にBorder（今回は濃いグレーと薄いグレーを交互に配置）を入れています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/07cff085-532f-117d-e54e-fb1a77db116e.png)


SizeBoxとGridPanelは同じ位置に重なるように配置します。
（分かりやすいようにPreConstructでScrollBox内にコンテンツを4つ置いています。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/8858f2d0-7f82-1884-cf96-9dbeea58e9ab.png)

今回重要になるのがScrollBoxとその親要素のクリッピング設定です。
まずScrollBoxのクリッピングを「Inherit」に設定して、スクロールバーの下まで背景色をはみ出させるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/628265ac-7ade-605c-fc4f-f8377f932339.png)

そのままでは横方向のはみだし（スクロールバーの下の部分）だけでなく、ScrollBoxの上下方向へのはみだし（ScrollBoxの子要素の分だけ上下にリストが伸びる）も発生してしまいます。

https://twitter.com/abricheese/status/1588439575059660800

これを防ぐために、ScrollBoxの親要素であるSizeBoxのクリッピングを「Clip to Bounds」に設定して、SizeBoxからはみ出した部分は表示しないようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/87b6fa10-1f3c-02a2-7825-86bdf6589112.png)

### リスト内の要素

リスト内の要素側の階層は下記のようにします。
背景色表示用とクリック検知用に2つのBorderを入れています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/b5c0e608-9ff4-ab9b-7247-82ebe6fd1c23.png)

背景色とクリック検知で分けたのは、スクロールバーのところまで要素の当たり判定があると、スクロールしようとしても要素がクリックされてしまい、スクロールすることができなくなるからです。

https://twitter.com/abricheese/status/1588440045593432066

青色の部分がクリック検知用のBorder（実際には透明色にしておく）で、そこからスクロールバーの幅の分だけはみ出している赤色の部分が背景色用のBorder（青色と重なる部分にも配置してある）です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/0fcab840-efbe-cef6-7a3e-e27f67d757f6.png)

背景色用のBorderは、Visibilityを「Not Hit-Testable」に変更して、当たり判定を無効化しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/3ff12bef-e282-0efa-0016-27c76f18ce31.png)

背景色に関しては、今回は2色の縞々にしたかったので、「スポーン時に公開」にチェックを入れたInt変数を用意して、偶数か奇数かで色を変えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/770da309-5e90-5153-b44e-2acbc55d82aa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/8019abbd-127c-2525-153c-841604d2909f.png)

ちなみにリストの要素数は、ScrollBoxに追加する際に、Get Child Countノードで取得しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/3c787125-65f2-61f5-714a-6cb43ce0f873.png)
【C#】Listの中央値、最頻値を求める

# 中央値
### リストの要素が奇数個の場合
```c#
var list1 = new List<int> { 1, 2, 5, 4, 3 };
int median1 = list1.OrderBy(x => x).ElementAt(list1.Count() / 2);
Console.WriteLine(median1); // 3
```
### リストの要素が偶数個の場合

```c#
var list2 = new List<int> { 1, 2, 5, 4, 3, 6 };
double median2 = list2.OrderBy(x => x).Skip((list2.Count() / 2) - 1).Take(2).Average();
Console.WriteLine(median2); // 3.5
```

# 最頻値
### 最頻値が一つのみの場合
```c#
var list3 = new List<int> { 1, 2, 5, 4, 3, 2 };
int mode = list3.GroupBy(x => x).OrderByDescending(g => g.Count()).Select(g => g.Key).First();
Console.WriteLine(mode); // 2
```

### 最頻値が複数個存在する場合
```c#
var list4 = new List<int> { 1, 2, 5, 4, 3, 5, 2 };
var groups = list4.GroupBy(x => x).Select(g => new { Value = g.Key, Count = g.Count() }).ToList();
int maxCount = groups.Max(g => g.Count);
var modes = groups.Where(g => g.Count == maxCount).Select(g => g.Value).ToList();
Console.WriteLine(string.Join(" ", modes)); // 2 5
```
Arduino IDE のパス

# Windows

| 項目 | パス | 備考 |
| - | - | - |
| Arduino IDE ルート | C:\Program Files (x86)\Arduino\ |
| Arduino IDE バイナリ | C:\Program Files (x86)\Arduino\arduino.exe |
| ボード | %USERPROFILE%\AppData\Local\Arduino15\packages\ |
| Arduino 公式ボード | %USERPROFILE%\AppData\Local\Arduino15\packages\arduino\ |
| Arduino Core for ESP32 | %USERPROFILE%\AppData\Local\Arduino15\packages\esp32\ |
| ライブラリ | %USERPROFILE%\Documents\Arduino\libraries\ |
| スケッチ | %USERPROFILE%\Documents\Arduino\ |
マーカーの画像を動的に切り替える方法

この記事は Mapbox Advent Calendar 2022 の記事です。
中の人も何名か参戦されるようなので、良い方法があればあわよくばアドバイスしてもらえないかというセコい思いで書かせていただきました(笑)

mapbox上に多数のマーカーをセットする場合など、[マーカー群をレイヤーとして追加する方法](https://docs.mapbox.com/mapbox-gl-js/example/add-image/)もありますが、
今回は少数のマーカーをリアルタイムに移動させたり画像を差し替えたりしたかったので、今回は[カスタムマーカーを追加する方法](https://docs.mapbox.com/jp/help/tutorials/custom-markers-gl-js/)を選択しました。

一度セットしたマーカーの位置を変更するには```.setLngLat()```で場所を変えてあげればよいのですが、
セットしたマーカーの画像を変更する方法が見当たらず、試行錯誤の上、次のようになりました。

# マーカー作成の際、divエレメントを保存しておく
```
const el = document.createElement('div');
el.className = _classname;
var marker = new mapboxgl.Marker(el);
marker._el = el;
```
# エレメントのクラス名を直接書き換える
```
g_marker._el.className = 'cMarke'+g_iconType;
```

もっと良い方法を知っている方がおりましたら教えてください。


# 実行結果

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

# ソースコード
同じ階層にimgフォルダがあり、icon0.png,icon1.pngが入っていることを前提としています。
![icon1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/748c4d69-a701-e7d0-e0f9-96fdc45745f6.png)![icon0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/b5fdd01a-4ca1-deb4-172d-9284c6ce6a8f.png)

```
<!DOCTYPE html>
<html>
<head>
<title>Marker test</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"></script>
<style>
    body { margin: 0; padding: 0; }
    #map { position: absolute; top: 0; bottom: 0; width: 100%; }
    .cMarke0, .cMarke1{
        background-image: url('./img/icon0.png');
        background-size: cover; width: 64px; height: 64px; border-radius: 0%; cursor: pointer;
    }
    .cMarke1 { background-image: url('./img/icon1.png'); }
</style>
</head>
<body>
<div id="map"></div>
<script>
    var g_reqAnimId = 0;
    var g_previousMillis=0;
    var g_marker = null;
    var g_iconType = 0;
	mapboxgl.accessToken = 'YOUR_ACCESS_TOKEN';

    const map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/light-v10',
        center: [139.75,35.67],
        zoom: 12
    });

    map.on('load', () => {
        g_marker = addMarker(map, map.getCenter(),'cMarke0');
        g_reqAnimId = window.requestAnimationFrame(_update);
    });

    _update = function(_nowMillis){
        var deltaMillis=(_nowMillis-g_previousMillis);
        if(deltaMillis>=1000){
            g_iconType=((g_iconType==0)?1:0);
            g_marker._el.className = 'cMarke'+g_iconType;
            g_previousMillis = _nowMillis;
        }
        g_reqAnimId = window.requestAnimationFrame(_update);
    }

    addMarker = function(_map, _homeLngLat, _classname){
        const el = document.createElement('div');
        el.className = _classname;
        var marker = new mapboxgl.Marker(el);
        marker._el = el;
        marker.setLngLat(_homeLngLat).addTo(_map);
        return marker;
    }
</script>
</body>
</html>
```
ROS2+Turtlebot3 動作テスト(実機) SLAM／Navigation

## はじめに
TurtleBot3(waffle pi)をROS2で動かした際の忘備録(3)です
本ページでは実機を使ってSLAM／Navigationをテストします
https://qiita.com/pez/items/1d3d15b3911d5dab1702

【下記の状態からを想定しています】

・ホストPCにVirtualBox＋Ubuntuが導入済み（下記別記事参照）
https://qiita.com/pez/items/a3ef1855f7e1e0ed3dfd
・ホストPCにROS(ROS2 Foxy)がインストール済み（下記別記事参照）
https://qiita.com/pez/items/1df36628524ff40a3d93
・TurtleBot3セットアップ済み（下記別記事参照）
https://qiita.com/pez/items/1d3d15b3911d5dab1702

## 環境
##### ホストPC (Panasonic Let's Note CF-FV)
・OS: Windows11 Pro (64bit)
・VirtualBox: 6.1.38 (Ubuntu20.04.5, GUI環境)
・ROS: ROS2 Foxy

##### ロボット
・TurtleBot3 waffle pi (Raspberry Pi 3B+)
　または
・TurtleBot3 burger (Raspberry Pi 3B+)


## SLAMのテスト
TurtleBot3にSSH接続して立ち上げます
```ruby:
$ ssh ubuntu@[(例)192.168.**.** （turtlebotのIPアドレスを調べて接続）
※接続できたら
$ ros2 launch turtlebot3_bringup robot.launch.py
```
別のターミナルを立ち上げてロボットの操作を行えるようにします
teleop（キーボード操作）を使う場合は下記
※自分で作った my_teleop や my_gamepad を使ってもよい 
```ruby:リモートPCにて
$ ros2 run turtlebot3_teleop teleop_keyboard
```

動かせるようになったら下記で地図作成を開始します
```ruby:
$ ros2 launch turtlebot3_cartographer cartographer.launch.py
```
ロボットを動かしながら周辺地図を作成していきます．
ロボットの種類・その他環境によるかもしれませんが，かなりゆっくり動かさないとうまく作成できないかもしれません．


地図の保存
```ruby:別のターミナルにて
$ ros2 run nav2_map_server map_saver_cli -f ~/map
```
※mapの部分は任意の名前でOK，「~/」を入れるとホームディレクトリ直下に保存される


## ナビゲーションのテスト
※SLAMで地図が保存された後を想定しています

ナビゲーションノードを立ち上げる
```ruby:
$ ros2 launch turtlebot3_navigation2 navigation2.launch.py map:=$HOME/map.yaml
```
※map.yaml の部分はmapを保存した時の「自分でつけた名前」.yaml とする．

操作方法
1.「2D Pose Estimate」ボタンをクリック
2. 現在ロボットのいる位置をクリックして緑色の矢印をロボットが向いている方向に合わせる
3.「Navigation2 Goal」ボタンをクリック
4. ロボットを移動させたい位置をクリックして緑色の矢印を最終的にロボットに向かせたい方向に合わせる

ロボットが目的地に動いたら成功
HTML/CSSのみで追従するスプリットスクリーンレイアウト実装

## スプリットスクリーンレイアウト
画面全体をバチコーンと分割したレイアウトをスプリットスクリーンレイアウトといい、オシャレなサイトでよく使われている印象です。
スプリットレイアウトと言われているときもあり正式名称は謎です。

## 実装
今回は画面を二分割した上で、片方のコンテンツがスクロールしている間、もう片方はページ上部にくっついているものを実装してみました。
SP幅（とりま749px以下）では１カラムにし、PC表示ではタイトルとテキストエリアを交互にしています。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="bGKegza" data-user="IKEMAKI" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/IKEMAKI/pen/bGKegza">
  Untitled</a> by MAKI I (<a href="https://codepen.io/IKEMAKI">@IKEMAKI</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

（１カラム表示になる場合は、0.5xにするかCODEPEN上でご覧くださいm(_ _)m）

文章が入ることでHTMLが見づらいかもしれませんが、
```html
<h2>ページのタイトル</h2>
<ul>
    <li><h3>タイトル</h3><p>テキスト</p></li>
    <li><h3>タイトル</h3><p>テキスト</p></li>
</ul>
<div>空のセクション</div>
```
内容はこれだけです。

ポイントとしては以下のような感じです。
- `position:sticky`と`top:0`でくっつける。heightを指定しないとくっつかない
- 横並びはflexbox
- `order`でPCとSPの並び順を変える


PCの偶数行は左右を入れ替えたく、本当は余計な入れ子を増やさずflexやgridでうまくできないかなーと思ったのですが、
orderを使うには指定しないといけないしなーということでリスト要素にしました。
より賢いやり方があれば教えてくださいませ。

## 終わりに
stickyが普通に使えるようになって、jsを使わなくてもこういう表現ができるようになったのはとってもハッピーですね。
前後のセクションなど他の要素に干渉しないのも好印象です。

次はjsと組み合わせて、スクロールによってアニメーション発火するさらにオサレな感じでやってみようかと思います。

それでは！👋
セーフィー株式会社のインターン参加ブログ

こんにちは。
この記事はセーフィー株式会社のサマーインターン(8/3~5)に参加してやったこと、得たことを綴ったものです。
新しい経験で言語化できていないことも多く、長文です。

# セーフィー株式会社とは
セーフィー株式会社は、カメラの映像をクラウド化して、監視カメラや映像のデータ化などを行っている会社です。
 簡単に言うと、カメラの映像を使っていろんな業界のいろんな課題をDXで解決しようとしている会社です(たぶん)。
[セーフィーHP](https://safie.co.jp/)

# なぜセーフィーのインターンに参加したのか
 私がセーフィーさんを知ったのは、サポーターズの1on1面談でセーフィーさんと面談させていただいたことがきっかけでした。
 その時お話しさせていただいた感想としては、「なんか映像とかカメラでいろいろやってる会社なんだなー」くらいに思っていて、特にインターン参加しようとかめちゃめちゃ興味があったわけではありませんでした。

その後、なぜかスペシャルオファーをいただいて、なんかイベントに参加したりするとお金がもらえるらしいし、インターン開催するらしいから申し込んでみるかという超軽い気持ちで申し込みました。

 私はエンジニアを目指している学生で、インターンもエンジニア系のインターンを探していたのですが、セーフィーさんのインターンは受ける前は概要がよく分からず、受かった後にエンジニア系ではなくビジネス系のインターンだと知りましたw

 勝手にエンジニア系のインターンだと思ってて、面接でもビジネス系とか意識せずに技術やチーム開発の話をしたので、合格の電話と概要の話を聞いた時は、普通になんで受かったのか分からなかったですし、エンジニア系のインターンじゃないことに驚きましたw

まあ何事も経験ですし、オフライン開催と聞いて東京にも行ってみたかったので、承諾して参加する運びとなりました。

# インターンの概要
今回のインターンは、セーフィーさんにとって初めてのインターンらしいです。

概要は、3日間で6人グループでお題について話し合い、最終日にCEOやCFO、執行役員の方々にプレゼンするというものです。
お題は「__他社との協業を通じて解決すべき課題の設定と、その解決案を立案する__」というものでした。
セーフィーさんは、カメラ・映像を使って様々な業界の課題を解決している会社であるため、アライアンスという協業先がいます。

セーフィーさんのカメラや映像・AIの技術を用いることで、その協業先の課題を解決し、将来的にはその業界や社会課題を解決するという事業展開となっています。

参加者は3日間で、どのような業界のどのような課題を解決するのか、そのためにどんな協業先を選んで、どんな打ち手(解決策)を講じるのかを話し合い、最終日にプレゼンを行いました。

私たちのチームは業界を「観光業界」とし、課題や協業先、打ち手を考え、プレゼンしました。
結果的に、最優秀賞はとれませんでしたが、とても楽しく学びの多いインターンでした。

## よかったこと

#### ビジネス系のインターンの経験できた
エンジニア系のインターンは基本コードを書いていますが、ビジネス系のインターンではコードも書かず、グループでワークをするという新しい体験が、とても新鮮でよい経験となりましt。

#### 職種が違う学生との出会い・交流できた
私は基本小さいコミュニティ内で生きています。工業大学なので基本私の友達はエンジニア学生ばかりです。
今回のインターンでは、理系学生はいましたが、多くがエンジニアを目指す学生ではありませんでした。
私と全然違う思考回路というか、考え方や話し方など私が今まで会ったことのない人たちでとても新鮮でした。
今まで会ったことはあったかもしれませんが、とても濃い3日間で、3日間とは思えないほど仲が良くなったので、深い部分を知ったからかもしれません。
とにかく、私はめちゃめちゃ驚いて、とても新鮮でした笑(語彙力)

#### 濃いグループワークができた
グループ内のメンバーのスキルが高かったのかもしれませんが、論理的に話せる人ばかりで、語彙力というか、__考えていることを言語化するスキル__ がとても高い人たちでした。
論理的に話していたり、グループ内での潤滑剤になってくれたり、とても頭の回転が早い人が多く、会話についていけないこともありました。
また、メンバーがとても個性的で、とある2人は考え方が真反対で、よく意見が合わず、対立していました笑
他にも、私含め多くのメンバーが積極的に発言していたので、話し合いで脱線することが多かったです。

そんな中でも、グループ内で意見が対立することや認識が違うことがあればしっかりと話し合うことで、全員が納得する形にしたり、全員が共通認識を持ったりすることができました。
また、誰かが理解できていないことがあれば、その都度話し合って解消していったので、会って1,2日とは思えないほど仲が良く、__お互いが遠慮なく意見を言い合える__ とても良いグループだったと思います。

普段の大学の授業のグループワークよりも、ワークの内容もメンバーも質が高かったので、脳をフル回転させていて、夕方くらいからみんな疲れていましたが、とても楽しいグループワークでした。

#### セーフィーさんの魅力を知ることができた
セーフィーさんのやられてる事業を知り、その事業の発展のさせ方が上手だと思いました。
DX化をステップとして切り分け、段階的にステップアップすることでDX化し、業界の課題を解決するという事業展開がとても面白いと思いました。

#### キャリア面での新たな知見が得られた
社員の方に、前職はエンジニアをして、セーフィーさんでは企画職?のようなことをされている方がいて、エンジニアという経験・知見を活かしてサービスを提案するというキャリアパスが私にとって新しいキャリアパスで、とても面白そうだと思いました。

## 反省点
- 事業展開やビジネスモデルを考えるということ
- 時間管理

## おまけ
- 私が田舎学生だからかエンジニア学生だからか分かりませんが、SNSの交換でTwiiterではなくインスタの交換をしたのは驚きました笑
- 良いグループに贈られる賞もあったのですが、もらえず、不満でしたが、採点基準が私たちのグループと正反対だったので、納得しました笑
- 私はサポーターズからセーフィーさんを知ってインターン応募したのですが、他のメンバーはみんなグッドファインドというサービスで知ったらしく、私はそのサービスを知らず、みんな驚いていました。逆にみんながサポーターズを知らず、私は驚きました笑
- 東京に来たのが人生で4回目で東京駅で迷子にもなりましたが、牛タンの美味しい店にグループで行ってとても美味しかったです。

# 最後に
私はセーフィーさんのインターンで多くのことを学ぶことができました。
エンジニア系ではないインターンで迷いましたが、参加してよかったと思っています。
ただ本選考落ちたのでもうセーフィーさんと関わることはないと思いますw
Dockerで検証用のubuntu環境の構築方法(備忘録)

# はじめに
Linux環境が欲しくなり、構築しようと思ったら時間がかかってしまいましたので、次必要になった時に忘れないように残しておきます。
特に、ホストとコンテナ間でディレクトリを共有して確認できる環境が欲しかったです。

# コマンド一覧
## Ubuntuイメージをpull
```
docker pull ubuntu:20.04
```

pullしたイメージ確認

```
docker images
```

## コンテナ作成コマンド

```
docker run -v [自分のPCの絶対パス]:[コンテナ側の絶対パス] -it -d --name [コンテナ名] ubuntu:20.04 bash
```

-vでホスト・コンテナ間でディレクトリ共有指定

## コンテナに入るときのコマンド

```
docker exec -it [コンテナ名] /bin/bash
```

## コンテナ停止

```
docker stop [コンテナ名]
```

## コンテナ起動

```
docker start [コンテナ名]
```

## 起動中のコンテナ確認

```
docker ps
```

## 停止中のコンテナも含めて確認

```
docker ps -a
```
【個人開発】TwitterAPIでツイート数順にランキング表示するアプリを作ってみた

暇な時間を利用して個人開発をやっています[からくり](https://twitter.com/karakuri0607)です。
今回はPythonとTwitterAPIでツイート数順にランキング表示するアプリを作成してみました。

# 開発したきっかけ
アニメの人気キャラクターや人気商品はネットで検索すれば分かりますが、実際のところ何をもとにして集計されているのかわかりません。
Twitterであればより正確に把握できるのではないのかと思い、開発に至りました。

# 開発したプログラムの紹介
今回開発したプログラム「ツイート集計」はこちらです。

CSVによる集計
![twitter-api-ranking.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944592/fc92e87a-2f82-d1f3-8605-d2097c81c426.gif)

スクレイピングによる集計
![twitter-api-ranking_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944592/e7212fdc-e8be-4cdc-ee1a-ed66a75ef6b8.gif)

CSVやスクレイピングから取得した一覧を対象にツイート数の多い順に並び替えし出力します。
ダウンロードして実行することができます。
良ければ使ってみてください。

https://github.com/karakuri0607/twitter-api-ranking-exe

# 使い道
* アニメで人気なキャラクターが知りたいとき。
* 複数の商品でどれを買うべきか迷っているとき。

# 機能について
今回開発したプログラム「ツイート集計」には以下の機能があります。
### １．検索条件の指定
タイトル、開始日、終了日を指定します。
タイトルに半角カンマ「,」を挟むことで複数指定可能です。
### ２．検索方法の指定
スクレイピングまたはCSVで一覧を取得します。
取得した一覧は検索対象になります。
### ３．集計機能
スクレイピングまたはCSVで取得した一覧をもとにTwitterAPIを通してツイート数を取得し、ツイート数の多い順に並び替えます。
### ４．出力方法の指定
集計結果をCSVまたはEXCELに出力します。
何も指定しなければ結果のみ出力します。
### ５．結果表示
集計結果を画面に出力します。

# 注意点
* 開始日、終了日は今日を含む直近の過去７日以内で指定して下さい。
* スクレイピングのリスト要素には全てのレコードに共通するクラス名を指定してください。
* 万が一、取得件数が上限に達した場合に利用できなくなる可能性があるため、config.iniにベアラートークンを指定できるようにしています。
* スクレイピングをする際にChromeDriverのバージョンを使用しているChromeのバージョンに合わせる必要があります。
本アプリケーションはバージョン107です。
こちらからダウンロードしてexeファイルの同じ階層に配置してください。

https://chromedriver.chromium.org/downloads

# 使用したライブラリまたはAPI
* ### Twitter API v2
　Twitterの操作や情報収集ができるAPI
* ### selenium
　スクレイピング、ブラウザ操作ができるライブラリ
* ### PySimpleGUI
　GUIを作成するためのライブラリ
* ### requests
  API等のURLを指定してHTTPリクエストを行い情報を取得するためのライブラリ
* ### pandas
　CSVやEXCELの読み書き、リスト作成、フィルターなどデータ操作を行うライブラリ

# 開発して思ったこと
開発期間は約１週間です。
いくつか躓いた点がありましたので共有したいと思います。

### TwitterAPIは過去７日間までのツイートしか参照できない。
TwitterAPIは今日を含む過去７日間までのツイートしか参照できません。
過去７日間より前のツイートを取得したい場合は、学術研究用のプロダクトを使用する必要があります。
利用可能な対象者は、「論文執筆中の大学院生、学位論文執筆中の博士号取得候補者、学術機関に所属しているまたは雇用されている研究員」に限られます。

https://developer.twitter.com/ja/products/twitter-api/academic-research

### TwitterAPIは取得件数に上限がある。
TwitterAPIv2にはEssential、Elevated、Academic Researchというプランがあります。
Essentialは無料で最大50万件/月まで、
Elevatedは無料で最大200万件/月まで、
Academic Researchは最大1000万件/月まで利用可能です。
本アプリケーションはElevatedです。

### ポジティブまたはネガティブな内容のツイートが指定できない？
URLに検索クエリを指定することで条件指定可能ですが、
ポジティブは「:)」、ネガティブは「:(」で指定可能なようです。
検索クエリに追加してみましたがエラーが発生したため除くことにしました。
ポジティブかネガティブか判断できなければ、ネガティブな内容も数に含まれることになるので「人気な」ランキングとは言えないかもしれません。

### スクレイピングの条件指定が難しい。
スクレイピングは、サイトのHTML構成によって条件を変える必要があります。
様々な構成に対応したプログラムにする必要がありますが、複雑なため断念しました。
今回はリスト要素に全てのレコードに共通するクラス名が指定されているものに限られます。

# まとめ
個人開発で作成したプログラム「ツイート集計」を紹介させていただきました。
今回はツイート数の多い順に並び替えるプログラムでしたが、TwitterAPIにはツイート、リツイート、いいねの操作やツイートの取得もできるのでそれらも機能に加えていきたいと思います。

また、ブログに個人開発で作成したプログラムや記事を載せていますので、よろしければ閲覧お願いいたします。

https://pg-toybox.com/

不具合や要望などありましたら、コメントもしくはブログのお問い合わせから連絡していただけると幸いです。
Vue3プロジェクトをサブドメインで使う話

結構悩みましたが擦りに擦られているネタだと解決後に判明しましたw

vue3プロジェクトを作成してそのままbuildするとdistに成果物が発生しますが、それって…

サブディレクトリでは動かないのですよ！

その対策を考えたいともいます

# Vue3プロジェクトの作成
vue3プロジェクトの作成はコマンド一発で作成されます
```
$ npm init vue@latest
 
Vue.js - The Progressive JavaScript Framework
 
- Project name: … vue-sample
- Add TypeScript? … No / Yes
- Add JSX Support? … No / Yes
- Add Vue Router for Single Page Application development? … No / Yes
- Add Pinia for state management? … No / Yes
- Add Vitest for Unit Testing? … No / Yes
- Add an End-to-End Testing Solution? › No
- Add ESLint for code quality? … No / Yes
```
すべてNoで作りましたw（コピペではアンダーバーが表示されないのかw）

# ビルドする
はい、ビルドまでは予定調和なのでさささっと書いておきます
```
$ npm install
 
added 33 packages, and audited 34 packages in 9s
 
4 packages are looking for funding
  run `npm fund` for details
 
found 0 vulnerabilities
$ npm run build
 
> vue-sample@0.0.0 build
> vite build
 
vite v3.2.2 building for production...
✓ 23 modules transformed.
dist/assets/logo.da9b9095.svg    0.30 KiB
dist/index.html                  0.41 KiB
dist/assets/index.1da8cd0c.css   3.59 KiB / gzip: 1.17 KiB
dist/assets/index.47b3536f.js    60.91 KiB / gzip: 24.12 KiB
```
これで成果物がdistに展開されますのでこれをコピーしてリリースすればOKです

がっ！　このままではNGでした

# 動作確認する
distの動作の確認はpreviewで行えます

```
$ vite preview
  ➜  Local:   http://localhost:4173/
  ➜  Network: use --host to expose
```
ブラウザでhttp://localhost:4173/ にアクセスすればサンプルページが表示されます！

これで動作確認を完了していましたが、これをサブディレクトリに展開したときに動かない！

サブディレクトリの動作は、WebStormにてindex.htmlをブラウザで開けば再現されました

`http://localhost:63343/vue-sample/dist/index.html`

はい、開かれるのはサブディレクトリ vue-sampleに展開されます。

すると…

真っ白です…

consoleを確認すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2481837/4de99975-75f7-74e2-b9c3-097a5dbd6093.png)

エラーです…

なんだか index.cssのパスが通っていない?

ソースを確認すると

```html
<script type="module" crossorigin="" src="/assets/index.47b3536f.js"></script>
<link rel="stylesheet" href="/assets/index.1da8cd0c.css">
```
はい、/とルートディレクトリを指しています。
サブディレクトリ(vue-sample)なので./vue-sample/assetsにあるので動いていません；；

問題はここにあります

# 解決方法
解決方法はシンプルでした。

viteの払い出しのbaseをいじってやればOKです

viteの設定ファイルはvite.config.jsにありますのでその中でbaseを追記します

```js
export default defineConfig({
  base: './',　// ←これを追加
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})
```
これでbuildするとパスが以下のようになって動作します

```html
<script type="module" crossorigin="" src="./assets/index.47b3536f.js"></script>
<link rel="stylesheet" href="./assets/index.1da8cd0c.css">
```
はい、./assetsになりました！

# 終いに
今回は標準のサンプルプログラムで動かないじゃないかということでメモを残しておきました。

でも、これって動きはしますが、不具合が一部あります。

不具合ってのはvue-router周りです。
現在開発はTSで行っていますが、historyだかhashだかどっちかの場合は真っ白ページになります。
RouteViewの中身が展開されません。
別の方にすれば動きますが、paramsがquerysだったりまるっきり書き方が変わりますので結構大変です。
この辺りはどうにかしたいですね

次回はもう少しvue-router周りを調べてメモを残しておきましょうかね
MacBookを新調した時用メモ

随時更新

## App Storeからインストールするアプリ
|アプリ|説明|
|-|-|
|Step Two|2段階認証用アプリ|
|Slack|チャットツール|
|Xcode||
|Sequel ace|mysqlクライアントアプリ|

## ブラウザからインストールするツール
|ツール名|説明|
|-|-|
|chrome|safariからインストール|
|[zoom](https://support.zoom.us/hc/ja/articles/203020795-macOS-%E3%81%B8%E3%81%AE-Zoom-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)|Slackに次いで優先度高|
|[Iterm2](https://iterm2.com/)|[ビープ音はうるさいので消しておく](https://suzuken.hatenablog.jp/entry/2015/08/23/154635)<br />Scrollback Bufferを1000行から無制限に変更<br />画面分割した時、分割元のカレントディレクトリを引き継ぐように変更する|
|[Visual Studio Code](https://code.visualstudio.com/download)|万能IDE|
|[dotfiles](https://github.com/sshuuu/dotfiles)|zshやvimの設定は早めにおこなっておきたい|
|[Homebrew](https://brew.sh/index_ja)|Iterm2からCLIでインストール<br />インストール直後はパスが通っていないので、標準出力に従って設定を行う|
|[Clipy](https://clipy-app.com/)|便利なクリップボード拡張ツール<br />`Cmd+Shift+v`だけ覚えておけば大丈夫<br />VSCodeでのマークダウンのプレビュー確認とホットキーが被っているのが辛い|

## Homebrewでインストールするフォーミュラ

|フォーミュラ|説明|
|-|-|
|asdf|主要な言語・ミドルウェアのバージョンを一元的に管理可能|
|nodebrew|Node.jsバージョン管理マネージャー|
|goenv|Golangバージョン管理マネージャー|
|rbenv|rubyバージョン管理マネージャー|
|jq|jsonを簡単にいい感じに整形できる|
|pt(the_platinum_searcher)|超高速で簡単に使用できるgrep|
|tree|ツリー上にディレクトリ一覧してくれる<br />https://qiita.com/koshihikari/items/0906cd8e97b931714efe|
|mysql||
|direnv|ディレクトリごとに環境変数を設定できる。ローカル開発時に便利。|

## chrome拡張

|拡張名|説明|
|-|-|
|[bitwarden](https://bitwarden.com/ja-JP/download/)|パスワード管理ツール<br />1Passwordとの検討になると思う<br />二人までの共有であれば無料で使用できる|
|DeepL|世界で一番高精度な翻訳ツール|
|keepa|Amazonの価格トラッカー|
jsTree を使ってオリジナルのデータをツリー表示する

# 利用するライブラリ

jsTree というライブラリを利用します。
他のライブラリも検討したのですが、意外に？デファクトスタンダードというものが無く、これを採用しました。

https://www.jstree.com/

ライセンスはMITとのことです。

ここでは他に bootstrap5, jquery 3.5.1 を利用しています。

# 難しかった点

サンプルを見ればツリー表示自体は難しくないのですが、むしろ「自分が表示したいデータを jsTreeのデータ形式に変換する」のが面倒でしたのでここにメモしておきます。

# Code

```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jstree-example</title>
<!-- jQuery 3.5.1 -->
<script src="https://code.jquery.com/jquery-3.5.1.js"
	integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
	crossorigin="anonymous"></script>
<!-- bootstrap 5 -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
	crossorigin="anonymous">
<!-- jstree -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>

<script type="text/javascript" class="init">
	// データ変換
	function parseTree(jstree,ptr,node){
		if(node.children != null && node.children.length > 0){
			var cc = new Array();
			if(node != null && node.children != null && node.children.length>0){
				for(var n=0;n<node.children.length;n++){
					var c = new Object();
					c.id = node.children[n].id;
					c.text = node.children[n].text;
					cc.push(c);
					// 再起呼び出し
					parseTree(jstree,c,node.children[n]);
				}
			}
			ptr.children = cc;
		}
	}
	// データ変換
	function toJsTreeNode(tree){
		var jstree = new Array();
		for(var n=0;n<tree.length;n++){
			var c = new Object();
			c.id = tree[n].id;
			c.text = tree[n].text;
			jstree.push(c);
			parseTree(jstree,c,tree[n]);
		}
		return jstree;
	}

	// 選択されたとき
	function nodeSelected(event,data){
	    console.log(data.node.id);
	}
	
	// 元のデータの例
	var originalData = [
		{
			id:"1",
			text:"aaa",
			children:[
				{id:"1-1",text:"bbb"},
				{id:"1-2",text:"ccc",
					children:[{id:"1-2-1",text:"ddd"},{id:"1-2-2",text:"eee"}]
				},
			],
		},
		{
			id:"2",
			text:"fff",
			children:[
				{id:"2-1",text:"ggg"},
				{id:"2-2",text:"hhh"},
			],
		}
	];
	
	$(document).ready(function() {
		// 初期化
		$.jstree.defaults.core.themes.variant = "large";
		$.jstree.defaults.core.themes.responsive = true;
		// データ変換
		var jstreeNode = toJsTreeNode(originalData);
		// 表示
		$('#jstree')
			// listen for event
			.on('select_node.jstree', nodeSelected)
			// create the instance
			.jstree({"core":{"multiple":false,"data":jstreeNode }});
		
	} // end of function
	); // end of .ready
</script>

</head>
<body class="m-3">
	<div class="row">
		<div class="col-12">
			<div id="jstree"><!-- ここにツリー表示 --></div>
		</div>
	</div>
</body>
</html>
```

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/e6caa2e8-7aa8-98ca-c17f-b1223d3f778b.png)

表示できました！

# ひとこと

toJsTreeNode() と parseTree() はもうちょっとシンプルに書けそうな気がしています。


以上。
DartにおけるInterfaceの扱い


Dartにおけるインターフェースの扱いを、swiftとの相違点からまとめてみました。
**get/set**については既知であるとします。
# インターフェースってなに？
まず、**インターフェース(Interface)** とは、オブジェクト指向型プログラミングによって認められた**具体的な実装を持たない抽象型**のことです。
swiftでは**protocolキーワード**を用いて実装されます。
```swift:swiftでの実装例
// Buildingプロトコルの定義
protocol Building {
    var height: Double { get }
    var area: Double { get }
    func volume() -> Double
}

// Buildingプロトコルに準拠したHouseクラス
class House: Building {
    let height: Double
    let area: Double

    init(height: Double, area: Double) {
        self.height = height
        self.area = area
    }
    
    func volume() -> Double {
        return height * area
    }
}
```
例えば、ここで`Houseクラス`で定義されている`定数area`の宣言部分を削除してみましょう。
すると、次のようなエラーメッセージが表示されます。
```sh:swiftでのerror
Type 'House' does not conform to protocol 'Building'
```
インターフェース内（swiftではプロトコル内）に定義されたものは、そのインターフェースを準拠した型の中で実装が必須となることがわかります。

# Dartにおけるインターフェース
次にDartではインターフェースがどのように実装されるかを確認します。
[公式ドキュメント](https://dart.dev/samples)を確認すると、次のような記述が見つかります。
>Dart has no interface keyword. Instead, all classes implicitly define an interface. Therefore, you can implement any class.

翻訳すると、Dart言語には**interfaceキーワード**（swiftでいうprotocol）が存在しない代わりに、全ての型において**暗黙的なインターフェース**が定義されているとのことです。
[公式ドキュメント](https://dart.dev/guides/language/language-tour#implicit-interfaces)が紹介しているプログラム例を元に確認してみましょう。
```dart:公式プログラム例
class Person {
    // interfaceが存在している
    final String _name;
    String greet(String who) => 'こんにちは、$who。私は$nameです。';
    // コンストラクタにはinterfaceは存在していない
    Person(this._name);
}

class Impostor implements Person {
    String get _name => '';
    String greet(String who) => 'こんにちは、$who。私が誰だか知っていますか？';
}
```
`implements`があるクラス（インターフェース）を準拠していることを表すものです。
`Personクラス`において定義されている`final変数 _name`と`greet関数`は、インターフェースの観点に基づき、`Impostorクラス`において再度定義され直さなければなりません。

では一般に、swiftでのprotocolキーワードのような表現をDartでするにはどうしたら良いのでしょうか？

# abstractキーワード
**abstractキーワード**とは、抽象型を作成する際にDartで用いられるものです。
Dartにおける実装例を確認してみましょう。
```dart:dartでの実装例
abstract class Building {
  final double height;
  final double area;
  Building({required this.height, required this.area});
  double? volume() {}
}

class House implements Building {
  final double height;
  final double area;
  House({required this.height, required this.area});
  double volume() {
    return this.height * this.area;
  }
}

void main() {
  final House house = House(height: 100, area: 100);
  print(house.volume());
}
```
`Buildingクラス`にabstractキーワードを付与することで、swiftのように抽象型のインターフェースとして扱うことができるようになりました。

### 参考ページ
[dart公式ドキュメント](https://dart.dev/samples)
[Dartのabstractとは？-Zenn](https://zenn.dev/joo_hashi/articles/7aa7fbc915bae2)
azure ポリシー定義・イニシアティブ定義と割り当て

●ポリシー定義
Azure Policyを使用するために、最初にポリシー定義を作成または確認する。新しいポリシー定義の作成時には、ポリシールールをJSON形式で記述する必要がある。
組み込みのポリシー定義を複製した上で部分的に変更して使用したり、GitHubからポリシ定義のサンプルをインポートして使用することもできる。

●イニシアティブ定義
単一のポリシー定義のみを使用する場合はひっすではないが、今後、使用するポリシー定義の増加が想定される様な場合には、イニシアティブ定義を使用した方が後からの変更に対応しやすい。

●割り当ての設定
ポリシー定義またはイニシアティブ定義を作成したアラ、それらの割り当てを設定する。管理グループ、サブスクリプション、リソースグループのいずれかに割り当てることができ、選択したスコープによってポリシーの内容を矯正する範囲が決定される。
macでdockerを操作する (docker desktopを使わない)

# この記事の目的

- docker desktopを使わずに、macでdocker操作できること

## 書いてること、書いてないこと

- 目的を達成するまでの手順を書いてある
- [lima](https://github.com/lima-vm/lima)を使ってdocker環境を構築している。limaの操作が書いてある
- macでdocker操作できる所までを書いてあるので、dockerを使って何かすることは書いていない

## こんな人に読んでもらいたい

- docker desktopを使えない人
- macユーザー

# 記事を書いた背景

- これまでmacでdockerを使うには、docker desktopをインストールするのが手っ取り早かった
- しかしdocker desktopが有償提供になり、利用できないケースがでてきた
    - 個人利用を除くとdocker desktopは無償利用ができない
- docker desktopなしでdockerを使えるようにする記事は多くあったけど情報がありすぎて混乱したので、自分なりに整理したかった

# 手順を実施する前の基礎知識 

- dockerが動いている仕組みと、limaというツールの基礎知識があると、後述の手順への理解が深まると思ったので記載した(理解の浅い部分があれば指摘いただると幸いです)
- docker 操作するには、docker clientとdocker server(docker engine)が必要
    - docker clientはmacでも利用可
    - docker serverはlinuxマシンでしか動かない
        - これまでdocker desktop for macがこの辺りをうまいことやってくれていたけど、docker desktopが使えない場合は代替物が必要
- [lima](https://github.com/lima-vm/lima)というツールを使って、mac上にlinuxVMを作成する
    - docker serverをlimaVMで動かす
    - lima以外にも方法はあるみたいだけど、記事が豊富なのでlimaを採用。

## 作業手順

- 本題

### 前提条件(著者の環境)

- mac monterey , v12.4

### 手順

1. macにdocker clientをインストールする
2. limaをインストールする
3. limaでVMを立ち上げる
4. macから直接docekrを操作する

##### 1. macにdocker clientをインストールする [mac上での操作]

- brewインストール

```
brew install docker
```

- インストールされたことを確認
    - インストールされていればversionが返される

```
docker -v
```


##### 2. limaをインストールする [mac上での操作]

- brewでlimaをインストールする
    - [limaのgetting started](https://github.com/lima-vm/lima#installation)
    - インストールすると`limactl`, `lima`コマンドが使えるようになる

```
brew install lima
```

- インストールされたことを確認する
    - インストールされていればversionが返ってくるはず

```
limactl --version
```

##### 3. limaでVMを立ち上げる [mac上での操作]

- [VMの設定ファイル](https://github.com/lima-vm/lima/blob/v0.7.4/examples/docker.yaml)をダウンロードする
    - もろもろ設定済みのVMイメージが公開されている。VMへのdockerインストールが省けてかなり楽

```
curl https://raw.githubusercontent.com/lima-vm/lima/v0.7.4/examples/docker.yaml > docker_example.yaml
```

- [任意] 設定ファイルにVMのスペックを追記する
    - VMのメモリ、ストレージを設定する
    - そのままだと、`cpus:4, memory:10GiB, disk: 100GiB`で立ち上がってしまうので、オーバスペックだと感じる人は編集する

```yaml
# 以下をdocker_example.yamlに追記(値は任意で変更)
cpus: 2
memory: "2GiB"
disk: "10GiB"
```

- ダウンロードした設定ファイルを元に、VMを立ち上げる

```
limactl start docker_example.yaml
```

- VMが立ち上がったことを確認する
    - `docker_example`がリストに表示されていて、ステータスがrunnningになっていればOK

```
limactl list
```

- これでlimaVM上からdocker操作が可能になった
    - ただ、docker操作するたびにlimaVMにログインすることは面倒

##### 4. macから直接docekrを操作する [mac上での操作]

- limaVM上のdocker engineを参照させるためにシンボリックリンクを貼る
    - docker操作するには、docker clientとdocker server(docker engine)が必要だが、docker serverはVM上にしかない
    - docker engineを使用するために`/var/run/sock`を参照するようになっているが、この向き先をlimaVM上で動く`docker.sock`に向ける

```
ln -nfs ~/.lima/docker_example/sock/docker.sock /var/run/docker.sock
```

- macからdockerコマンドが使えることを確認する
    - `Client:` と `Server: Docker Engine - Community`のversionが表示されていればOK。あとは自由にdocker操作を楽しむ。

```
docker version
```

--- 

### おまけ(よく使いそうな limactl, dockerコマンド)

- 上記でtくったdocker環境を保守していく上で、使いそうなコマンドを残しておくと便利だと思ったので記載

#### limaコマンド

- limaVM停止
    - `limactl stop {VM名}`
- limaVM削除
    - `limactl delete {VM名}`
- limaVMの確認
    - `limactl list`

#### dockerコマンド

- docker コンテナの停止
    - `sudo docekr stop {コンテナID}`
Moqで利用されているAvatarライブラリについて少しだけ調べてみた

# Moqで利用されているAvatarライブラリについて少しだけ調べてみた

## はじめに

C#のテストライブラリであるMoqは、インターフェイスをジェネリックで定義し、その後に振る舞いを注入できます。
具体的には、以下のテストコードの通りです。
<https://github.com/moq/moq/blob/main/src/Moq.Tests/MoqTests.cs#L112>

```cs
...
        [Fact]
        public void CanSetupMethodWithArgumentsViaReturns()
        {
            var calculator = Mock.Of<ICalculator>();

            calculator.Add(2, 3).Returns(5);

            var result = calculator.Add(2, 3);

            Assert.Equal(5, result);
        }
...

```

上記をどのような仕組みで実現しているのか？について調べ始めたら、Avatarライブラリに触れずには言及できそうにありませんでした。
そこで、Avatarライブラリについて色々調べた結果を残します。
<https://github.com/devlooped/avatar>

## Avatarとは

はじめにを機械翻訳したところ、以下の通りとなりました。
> Avatar はプロキシ・パターンを実装した最新の傍受ライブラリで、物理的な iOS デバイスやゲーム機のようにランタイムコード生成 (Reflection.Emit) が禁止または制限されている場所でも、コンパイル時のコード生成によりどこでも実行可能です。プロキシの動作は、ビヘイビアパイプラインと呼ばれるものを使ってコードで設定されます。

[Reflection.Emit](https://learn.microsoft.com/ja-jp/dotnet/api/system.reflection.emit?view=net-6.0)はリンク先の通り、動的にビルドしたりコンパイラしたりできる、といったものになります。
自分なりの理解で簡単に述べると、制限のある中でも、動的にコードの振る舞いを変更できるようにした、というものがAvatarであるという認識です。

利用方法についてもReadmeの中に記載されています。
<https://github.com/devlooped/avatar#usage>

## Avatarの内部コード

Avatarの中身を少しだけ確認してみようと思います。
利用方法の中で触れられている、以下のコードを参考に少しだけ処理内容を確認してみます。

```cs
ICalculator calc = Avatar.Of<ICalculator>();

calc.AddBehavior((invocation, next) => ...);
```

`Avatar.Of<ICalculator>()`で、振る舞いをカスタマイズ可能なICalculatorが返されます。
このとき、呼び出されるメソッドを遡っていくと`IAvatarFactory.CreateAvatar`メソッドが呼び出されます。
上記I/Fを実装しているクラスはいくつかあるのですが、まだ読みやすいStaticAvatarFactoryのCreateAvatarメソッドを例に読み込んでみます。
<https://github.com/devlooped/avatar/blob/main/src/Avatar/StaticAvatarFactory.cs#L25>

27行目：名前空間を作成します。baseTypeが`ICalculator`である場合、AvatarNaming.GetFullNameではデフォルトの名前空間と組み合わせて"Avatars.Avatar.ICalculator"のような名前が生成されます。
そしてAvatarのアセンブリを読み込み、上記の名前からインスタンスを実際に生成します。

（しかし、その場合"Avatars.Avatar.ICalculator"インスタンスを生成できる状態（Assembly内に上記のインスタンスが定義されている）でないといけないため、[DynamicAvatarFactory](https://github.com/devlooped/avatar/blob/main/src/Avatar.DynamicProxy/DynamicAvatarFactory.cs#L15)が実際には利用されているはず。なにかわかったらまた記事にします)）

その後、`AddBehavior`メソッドを用いて振る舞いを追加していきます。
追加した振る舞いは、たとえば[AnonymousBehavior](https://github.com/devlooped/avatar/blob/main/src/Avatar/AnonymousBehavior.cs#L10)として登録されますが、そのBehaviorを実行することで任意の振る舞いをさせられる仕組みなのだと思います。
（利用イメージは[テストコード](https://github.com/devlooped/avatar/blob/main/src/Avatar.UnitTests/AvatarExtensionsTests.cs#L10)からも少し理解できそうです）

## おわりに

正直不明点がまだまだ残っているので、もう少し詳しく中身を見ていく必要がありそうです。
avatarライブラリの中でcastleライブラリを利用しているようなので、そちらにも視点を向けて読み進めようと思います。
Gitlab-runnerでnodeのRunnerを作る話

今回はVue3のプロジェクト用にGitlab-Runnerを作りましたのでそのメモを残しておきたいと思います

## Gitlab-runnerを作る
これは公式ドキュメント通りに作ればOKですね
コンテナ名はgitlab-runner-npmとしています。
```sh
sudo docker run -d –name gitlab-runner-npm –restart always -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
```

公式ドキュメント : https://docs.gitlab.com/runner/install/docker.html


## Gitlab-runnerに入る

Dockerの基本なので解説しているところはないですがw
以下のコマンドでDocker内にbashシェルで入れます

```sh
sudo docker exec -it gitlab-runner-npm /bin/bash
```

## nodeをインストールする…
はい、ここでポイントです。
普通にaptにてnodeを入れるとv10が入ります…
最新がv18なので動かないパッケージがありました。
今回はviteが動きませんでした。
なので、最新のnode v18を手動で入れます

標準では入っていないことを確認…

```sh
root@cbed3782cec6:/# node -v
 bash: node: command not found 
root@cbed3782cec6:/# npm -v
 bash: npm: command not found
```
必要なパッケージをインストールします。
xzアーカイブを利用するのでxz展開ツールを使います

```sh
root@cbed3782cec6:/# apt-get update 
root@cbed3782cec6:/# apt-get install xz-utils
```

最新のnode v18を入手して、展開させればOKです

```sh
root@cbed3782cec6:/# wget https://nodejs.org/dist/v18.12.0/node-v18.12.0-linux-x64.tar.xz 
root@cbed3782cec6:/# tar -C /usr/local –strip-components 1 -xJf node-v18.12.0-linux-x64.tar.xz
```

これで /usr/local/bin/nodeでコマンドが実行されます

```sh
root@cbed3782cec6:/# node -v
 v18.12.0 
root@cbed3782cec6:/# npm -v
 8.19.2
```
はい、次にGitlab-runnerをレジストすれば使えます…

```sh
root@cbed3782cec6:/# gitlab-runner register
```
以下略

ちなみにローカル実行なのでshellで作りました。

```
Registering runner... succeeded                     runner=GR134894
Enter an executor: docker, docker-ssh, shell, ssh, virtualbox, kubernetes, custom, parallels, docker+machine, docker-ssh+machine:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 
```

## 動作確認する風のログ

gitlabのvue3のプロジェクトのパイプラインでちゃんと実行されていることをログで確認できればOKです

```
$ npm install
added 269 packages, and audited 270 packages in 10s
62 packages are looking for funding
  run `npm fund` for details
found 0 vulnerabilities
$ npm run build
> tsundere-book-hp-vue3@0.0.0 build
> run-p type-check build-only
> tsundere-book-hp-vue3@0.0.0 type-check
> vue-tsc --noEmit -p tsconfig.vitest.json --composite false
> tsundere-book-hp-vue3@0.0.0 build-only
> vite build
vite v3.2.2 building for production...
transforming...
warn - The `purge`/`content` options have changed in Tailwind CSS v3.0.
warn - Update your configuration file to eliminate this warning.
warn - https://tailwindcss.com/docs/upgrade-guide#configure-content-sources
✓ 87 modules transformed.
rendering chunks...
dist/index.html                  0.45 KiB
dist/assets/index.b778c217.css   9.10 KiB / gzip: 2.57 KiB
dist/assets/index.9642fb4b.js    111.50 KiB / gzip: 42.55 KiB
Job succeeded
```
複数のプロジェクトで型情報を使い回すためにnpmパッケージにして公開する

## 目的

- 複数のプロジェクトで TypeScript の型情報を使い回したい
- その際、以下のように import して使えるようにしたい

```App.tsx
import { FC } from "react";

const App: FC = () => (
  //
)
```

## どうやったか

npm パッケージにして公開し、それぞれのプロジェクトでパッケージを install して使うようにしました。

## 使用ライブラリのバージョン
- node: v16.x
- typescript: v4.8.x

## 何をしたか

### npmパッケージにするプロジェクトを作成
``$ mkdir npm-package-sample && cd $_``
``$ yarn init``

プロジェクト初期化の際にいろいろ質問されるので答えていきます。

最終的に package.json は以下のようになります。

```package.json
{
  "name": "npm-package-sample",
  "version": "0.0.0",
  "main": "dist/index.js",
  "license": "MIT",
  "description": "説明",
  "author": "your-name",
  "private": false,
  "files": [
    "dist"
  ]
}
```

- version はひとまず 0.0.0 にしておきます
- main はエントリーポイントになります。TypeScript を使うので build 先のディレクトリのエントリーポイントを指定します
- npm パッケージとして公開するので private は false にします
- files は公開するディレクトリを指定します。こちらも TypeScript を使うので dist にします
- name, description, author 等は適宜入力します

git を使うのであれば git init や .gitignore ファイルなどを用意します。

### TypeScriptを入れる
`$ yarn add -D typescript @types/node`
`$ yarn tsc --init`

### package.jsonにscriptsを追加
このあたりがあると良いでしょう。

```package.json
"scripts": {
  "build": "tsc",
  "prepublishOnly": "yarn build"
}
```

`prepublishOnly` を書いておけば npm publish を実行する前に build をしてくれます。

### ソースファイル作成

src ディレクトリに、ts ファイルを作成します。
src/index.ts にあるものを build し、公開する予定です。

では実際に index.ts に型定義を書いていきます。
```index.ts
type Animal = {
  name: string;
  age: number;
};

export { Animal };
```

これで build でき、dist/index.js が作成されたことが確認できたらいよいよ公開していきます。

### npmパッケージを公開する

  1. アカウントを作成
    NPMのアカウントがない場合、 [NPM](https://www.npmjs.com/) でアカウントの作成をします

  2. コマンドラインでログインする
    `npm login`
    こちらで先程作成したアカウント情報を入力しログインします。
    ログインできたかを確認するには`npm whoami` と入力すれば確認できます。

  3. ログインできたら `npm publish` のコマンド入力でパッケージを公開します
    バージョンを聞かれるのでひとまず0.1.0としておきます。
    エラーが起きず無事終了すればnpmパッケージに公開できています。

  4. npm からログアウトしておく
     `npm logout` でログアウトできるのでログアウトしておきます

### 追記
編集して再度 publish する際には package.json の versioin を変更しないとエラーになります。

6. 確認の為使ってみる
別の TypeScript プロジェクトに移動して先程公開したパッケージを `yarn add` コマンドを使ってインストールします。
`$ yarn add 作成したnpmパッケージ名`

package.json を確認すると dependencies に追加されています。
次に、適当な ts ファイルを開いて import してみます。

```sample.ts
import { Animal } from "npm-package-sample";

const animal: Animal = {
  name: "John",
  age: 6
}
```

import でき、型アノテーションがつくことを確認できました。

これで複数の TypeScript プロジェクトで同じ型を使い回すことができます。

## 終わりに

今回 npm パッケージを通して公開し、import して型を使うことにしましたが、もしかしたらもっといい方法があるのでは？とも思っています。..
もし何かご存じの方いらっしゃいましたら教えていただけますと幸いです。
その他なんでも是非コメントいただけたら嬉しいです。
サクラエディターで新規ファイル保存先のフォルダー初期値設定

# やり方

設定 ⇒ 共通設定 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/25199b1b-8072-eab6-58fd-ca87fc1a53cc.png)

編集 ⇒ ファイルダイアログの初期位置 ⇒ 指定フォルダ 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e7745287-33be-75c2-726a-01f25a40cdcc.png)

# バージョン

Windows 10 Pro 21H2 OSビルド 19044.2130
サクラエディタ v2.4.1.2849 32bit (tag v2.4.1)
Azure Fundamentals(AZ-900)：Azure の基礎: Azureの管理とガバナンスについて説明する「Azure Policy」

Microsoft Learnを用いたMicrosoft Azure Fundamentals(AZ-900)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始める方の参考になれば幸いです。

## 今回の学習内容
**◆「Azure Policy」**
◇対応するMicrosoft Learn ラーニングパス
[Azure の基礎: Azureの管理とガバナンスについて説明する](https://learn.microsoft.com/ja-jp/training/paths/describe-azure-management-governance/)
◇対応するモジュール
[Azure Policy の目的について説明する](https://learn.microsoft.com/ja-jp/training/modules/describe-features-tools-azure-for-governance-compliance/3-describe-purpose-of-azure-policy)

※前回の投稿は下記から確認できます。
[Azure Fundamentals(AZ-900)：Azure の基礎: Azureの管理とガバナンスについて説明する「Azure Blueprints」](https://qiita.com/fsd-jume/items/724472b9269450d4d15f)

## Azure Policy
**リソースを制御/監査するポリシーの作成や割り当て、管理が可能**
・リソースが評価され、ポリシーに準拠していないリソースを明示
・ポリシーに準拠していないリソースの作成を防止
・Azure DevOpsとも統合可能

### ポリシー定義
・各スコープ(個々のリソース、リソースグループ、サブスクリプション、管理グループなど)に設定可能
・親スコープに設定したポリシーは子スコープに継承
・デフォルトで使うことができる組み込みのポリシー定義がある
・ポリシー定義前に作成されたリソースも評価/監査対象
・ポリシーに準拠していないリソースや構成を自動的に修復し、準拠させることも可能
※例外フラグを設定し、特定のリソースのみ自動修復させないことも可能

### イニシアティブ定義
・関連するポリシー定義をまとめてグループ化したもの
・グループを単一の項目として操作するため、ポリシーの割り当てと管理が簡素化

## 次の学習内容
**◆リソースロック**

https://qiita.com/fsd-jume/items/86c6c4378b7fb5c7eb8c

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8
Waifu DiffusionのOpen in Colabが動かない場合の対処方法

以下のOpen in Colabが動かない場合の対処方法。

https://huggingface.co/hakurei/waifu-diffusion

# ImportError: Please install the \`accelerate\` library to use Diffusers with PyTorch. You can do so by running \`pip install diffusers[torch]\`. Or if torch is already installed, you can run \`pip install accelerate\`.

0.7.0でaccelerateが必要になった模様。

https://github.com/huggingface/diffusers/releases/tag/v0.7.0

なので、エラーメッセージのとおり `diffusers` を

```
!pip install transformers gradio scipy ftfy "ipywidgets>=7,<8" datasets diffusers
```

`diffusers[torch]` に変えてやればOK。

```
!pip install transformers gradio scipy ftfy "ipywidgets>=7,<8" datasets diffusers[torch]
```

# KeyError: 'sample'

0.3.0で、出力が "sample" から "images" に変更されている（正直、このあたりのインターフェースをコロコロ変えるのはやめてほしい）。

なので、ここを

```python:
images = pipe([prompt] * num_samples, guidance_scale=7.5)["sample"]
```

以下のように変えればOK。

```python:
images = pipe([prompt] * num_samples, guidance_scale=7.5)["images"]
```

# gradio.appのリンクが出ない

Colabの仕様変更と思われる。

ここを、

```python:
demo.launch(debug=True)
```

こうすればリンクが出るようになる。

```python:
demo.launch(debug=True, share=True)
```
プロセスが互換モードで動いているか確認する方法

How to check compatibility mode for running process.

プロセスが互換モードで動いているか確認したかったのだが、検索しても出てこなかった。

## Process Explorerで確認可能

https://atmarkit.itmedia.co.jp/ait/articles/2202/10/news029.html

Process Explorerを入れる。プロセスを右クリックして、環境変数の__COMPAT_LAYERを確認すると書いてある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656367/bdb1b24a-c8a6-9301-be31-acf6c9163c58.png)

お疲れさまでした。
S3にあるファイルを公開する方法3種

# この記事の経緯

同僚にS3にあるファイルを公開したいので、方法を教えてほしいと言われました。(知識として持っておきたいので、構築作業はご本人で実施したいとのことでした)

ぱっと思いついた方法が3つあり、口頭で説明するよりかは資料として説明した方が理解しやすいだろうと思い、かつ、外部公開しても問題ない内容なので、記事にします。

同僚への説明資料のため、詳細なやり方までは記載しておりません。各やり方のメリット、デメリットを記載していますので、ご自身の要望に沿う方法の選定に役立てて頂ければと思います。


# S3にあるファイルを公開する方法3種

今回は`S3のWEBホスティング` `CloudFront + S3` `Lambda + S3` の3パターンを考えます。
それぞれの特徴を簡単に纏めると以下となります。


項目|`S3のWEBホスティング`|`CloudFront + S3`|`Lambda + S3`
---|---|---|---
SSL|x|○|○|○
独自ドメイン|○|○|x|
手間|◎|x|△|
パフォーマンス|x|○|x|
アクセス制御|△|○|△|


では、それぞれ見ていきましょう。


# S3のWEBホスティング


S3には、そもそも今回のようなファイルを公開するようにエンドポイントを利用できます。設定で有効にするだけで使えるので簡単に利用できますが、 **HTTPS をサポートしていません**。
IPアドレスのアクセス制御などはS3に設定することで可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265134/e431d099-350c-1d3a-6e7d-35155e8a8b7c.png)




**メリット**
* 簡単！
* S3のバケット名をアクセスしたいドメイン名にすれば、任意のドメイン名でアクセスできる

**デメリット**
* HTTPS 非対応
* S3から直接ファイルを読み込むので、パフォーマンスはよくない(S3の性能があがっており、今は気にしなくてよいかも)


# CloudFront + S3
S3にHTTPSでアクセスしたいといった場合に、良く出てくるのが、このパターンです。S3の前にCloudFrontを置くことで、HTTPS でのアクセスを可能とし、CDNとしてキャッシュもできるので、パフォーマンスも素晴らしいものとなります。また、`WAF` を使えば、詳細なアクセス制御も実施可能です。ただ、構築するには、`CloudFront`、`S3`の他に `ACM` と `Route53` を使う必要があり、手間ではあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265134/09c860ae-434e-436b-e1db-69b13c8f83ae.png)


**メリット**
* HTTPS 対応
* キャッシュすれば、爆速
* 他のサービスとの組み合わせで、自由に制御できる

**デメリット**
* 構築が手間


# Lambda + S3
AWSは今年、LambdaにHTTPSエンドポイントを追加してくれました!
これを使えば、S3にあるファイルを外部公開できます。LambdaのHTTPSエンドポイントにアクセスして、Lambdaでは、S3にあるファイルを取得して返すという方法です。ただ、HTTPSは可能ですが、Lambdaのエンドポイントはこちらで指定できないので、カスタムドメインは非対応となります。また、今までの方法は、AWSコンソールでボタンをポチポチすれば、構築可能ですが、こちらLambdaを実装する必要があります。逆にいうと、アクセス制御やリダイレクトなど、Lambdaで出来ることはなんでもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265134/6c2d2499-d0fd-e1cb-8c67-7e2acd447f15.png)

**メリット**
* HTTPS 対応
* Lambdaの実装によっては、リダイレクト設定など、自由に設定できる。

**デメリット**
* カスタムドメインは不可。(API Gateway を使えば出来るが、今回は省く)
* 実装する必要がある (人によってはメリットにもなりえる)
* S3から直接ファイルを読み込むので、パフォーマンスはよくない(S3の性能があがっており、今は気にしなくてよいかも)


# おわり
S3を公開したいというに人の助けになれば幸いですし、他の方法が思いつく方は教えて頂けれると嬉しいです。
個人的には `S3のWEBホスティング` が `https` 対応してほしいです。
これだけは覚えておきたい！実務でよく使うGitコマンド

実務でよく使うGitのコマンドをまとめてみました。
初心者には参考になるかと思います。
Gitのバージョンは2.23~になります。
## ブランチの一覧表示
```
git branch
```
## ブランチの新規作成
```
git branch ブランチ名
```
## ブランチを新規作成して、作成したブランチに切り替える
```
git switch -c ブランチ名
```
-c は create の意味です
## ブランチを切り替える
```
git switch 切り替え先ブランチ名
```
## 変更をステージングに上げる
```
git add ファイル名        //指定したファイルの変更をステージングに上げる
git add .              //全ての変更をステージングに上げる
```
## コミットする
git add でステージングに変更をあげたらコミットする
```
git commit -m "ここにコミットメッセージを書く"

例
git commit -m "登録機能の不具合対応"
```
## リモートにプッシュする
```
git push origin リモートブランチ名

例
git push origin feature/hoge
```
## リモートブランチの変更を取り込む
git fetch と git merge を合わせたコマンド。
今いるローカルブランチに指定のリモートブランチの変更を取り込む
```
git pull origin リモートブランチ名

例
git pull origin develop
```
## ブランチの状態を確認する
今いるブランチで変更したファイルや状態（変更がステージされている、コミットされている等）を確認することができる
```
git status
```
## ログの確認
コミット履歴やコミットIDやらを確認することができる
```
git log
```
しかしながら、個人的に上記コマンドだと情報が少し見づらいのでこっちの方をよく使ってます
```
git log --oneline
```
オプションで--oneline をつけると情報がスッキリとした見た目になります
## 変更を退避する（スタッシュ）
実務ではさまざまな割り込み作業が発生します。
現在のブランチで作業している変更を一時的に退避する必要がある場合がよくあります。
その時に活躍してくれるコマンドです。
```
git stash save "作業内容がわかるメッセージ"

例
git stash save "登録機能"
```
## スタッシュされた内容を確認する
スタッシュを一覧表示してくれます。
また、スタッシュ番号（何番目にスタッシュされたのか）を確認できます
```
git stash list
```
## スタッシュを反映させる
一時退避した作業内容（スタッシュ）をブランチに反映させる、戻すコマンド。
```
git stash pop stash@{スタッシュ番号}

//　スタッシュ番号は git stash listコマンドを打つと確認することができます

例
git stash pop stash@{1}
```