OmniAICreator/Qiita-1.07M huggingface dataset:
ROS講座129 Unityプロジェクトをgit管理する

# 環境
この記事は以下の環境で動いています。

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Windows | 10 |
| unity | 2020.3(LTS) |

# 概要

ROS講座でUnityのプログラムが出てきます。Unityのプログラムをgitで管理する方法を記します。またサンプルProjectをgitでダウンロードして使用する方法も解説します。

# Unityのgit管理
## github for unityのインストール
 * Asset Storeで「github for unity」をダウンロードします。
 * PackageManagerで上記をImport

![github_for_unity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/b536a61a-f608-3658-d7a2-ef2d7f53d1f1.png)

## 設定をする

* メニューバーの「Window」->「GitHub」をクリック
* 「setting」タブに移り、出てくるページの「Name」と「Email」に適当な値を入れます。この情報はcommitメッセージに入るだけで、githubの登録アドレスと違っても、実在しなくても大丈夫です。

## 初期化をする

* 「Initialize」タブに移り、「Initialize a git repository for this project」というボタンを押す。ここで.gitignoreなどが自動で作られて、それらのファイルのみのInitial commitが作られます。
* 「Assets」などのフォルダはまだコミットされていません。「Changes」タブに移って、一覧からcommitしたいファイル（全部チェックで大丈夫です）をチェックして、画面下部の「Commit Summary」と「Commit Description」を埋めて「commit to [master]」を押しましょう

# githubと連携する
## remote repositoryを作る
githubの使用するアカウントで新たにリポジトリを作ります。

## sshキーの登録
どうやらPCの「/c/Users/[user名]/.ssh/」にssh鍵が必要な見たいです。今回はgitbashを使いました。

* gitbashを起動
* ディレクトリ移動：cd ~/.ssh/
* 鍵の作成： ssh-keygen.exe -t rsa（あとは指示に従って）
* ~/.ssh/id_rsa.pubをgithubに登録

## リモートリポジトリの設定&ログインをする&Push

Unityに戻ります

* リモートリポジトリの設定
    * メニューバーの「Window」->「GitHub」をクリック
    * 出てくるウィンドウで「Setting」タブを開く
    * 「Remote: origin」の欄にリポジトリのアドレスを入れる（例：git@github.com:project-srs/ros_lecture_unity_app.git）
* ログイン
    *  画面右上の「Log In」を押す
    *  出てくる画面で「Sign in with your blowser」を押す。
    *  出てくる画面でgithubの連携のために認証をする
* pushをする
    * ウィンドウ上部の「Push」を押します。 

# githubからcloneしたProjectを使用する
例えば当プロジェクトの「https://github.com/project-srs/ros_lecture_unity_app」を使用する場合の手順です。

## リポジトリのclose
外部ツールでcloseする必要があります。今回はgitbashで~/に移動して「git clone git@github.com:project-srs/ros_lecture_unity_app.git」します。

## Unity hubで開く
Unity Hubを開き「リストに追加」を押して上記のディレクトリを開きます。

# コメント
* Unity Teamを使って構成管理をするのがUnityの正式のようです。
* 昔はmetaファイルが隠しファイルかそうでないかの選択があったそうですが、今はなくなっています（.metaファイルが普通のファイルとして出来ます）またバイナリ形式かテキスト形式かを選択できるのですが、現在はデフォルトがテキスト形式のようです。
* 最初のコミット時点で500kBほどでした。最初に.gitattributeが設定されているのでgit LFSに対応していているようです（未確認ですが）。

# 参考
* https://qiita.com/toRisouP/items/97c4cddcb735acde2f03

# 目次ページへのリンク
[ROS講座の目次へのリンク](https://qiita.com/srs/items/5f44440afea0eb616b4a)
ジョブの種類についてまとめる

ジョブとは
-
ターミナルが実行している作業のこと。

localhostサーバーを動かす、ログを出力する、ファイルをコピーするなどの操作は全てジョブと呼ばれる。

ジョブの種類
-
ジョブには大きく分けて3つの種類があり、それぞれ`フォアグラウンドジョブ`、`バックグラウンドジョブ`,`サスペンドジョブ`と呼ばれる。

フォアグラウンドジョブ
-
フォアグラウンドジョブは出力結果がターミナル上に表示されるもののことを言う。

例えばファイルの中身を表示する`cat`コマンドは結果がターミナルに表示されるのでフォアグラウンドジョブにあたる。

オプションを指定せずに実行したジョブは基本的にフォアグラウンドで処理される。

ターミナルを用いた出力を行うという都合上、処理が完了するまでは他のジョブを実行できないという欠点がある。

バックグラウンドジョブ
-
処理は行われているものの結果はターミナルに表示されず、裏側で動き続けているジョブのこと。

`-d`オプションをつけてサーバーを起動した場合などがこれにあたる。

サスペンドジョブ
-
一時的に処理が中断されているジョブのこと。

再開されるまでの間は処理が止まった状態になるが、それまでターミナルを占有していたジョブがなくなるので他の処理を実行できるようになる。

サスペンドジョブに関するコマンド一覧
-

```shell:現在実行しているジョブの停止
% Ctrl + z
```
```shell:サスペンド中のジョブの一覧表示
% jobs
# 結果
[1]   Stopped                 ping 172.17.0.3
[2]+  Stopped                 ping 172.17.0.3
[3]-  Stopped                 ping 172.17.0.2
```
左端はジョブのID

```shell:ジョブの再開
% fg ジョブID
# ID省略時は+となっているものが実行される
```

```shell:ジョブのバックグラウンド再開
% bg ジョブID
# ID省略時の挙動はfgと同じ
```

fgやbgで指定されたジョブが起動中だった場合には起動方法の変更のみが行われる（bg⇄fg)。

ジョブの停止に関する注意点
-
フォアグラウンドジョブに関しては`Ctrl + z`で停止可能。

バックグラウンドジョブに関しては`Ctrl + z`で停止することはできないので、一旦`fg ID`でフォアグラウンドに切り替えた後に`Ctrl + z`で停止させる。

ジョブの実行方式の切り替えに関する注意点
-
最後に停止またはフォアグラウンドで起動したジョブに関しては`+`状態となり、ID指定なしでも起動ができるようになる。

しかしバックグラウンド起動したジョブに関しては最終起動ジョブであっても`+`状態とならない（既に+のジョブをbg起動した場合は除く）。

このため、bg起動しているジョブを停止させる目的で`fg`とID指定なしで入力すると、bg起動ジョブが`+`でなかった場合にはジョブの二重起動となってしまうことになる。
Prefabを一定間隔でランダムな場所に生成

HDRPでも動くこと確認済み。
蝶々の.vfxで試したのでバタフライメイカーという名前になってます
もう少し使いやすく改良します、いずれ

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ButterFliesMaker : MonoBehaviour
{

    public GameObject butterFliesPrefab;
    float span = 1.0f;
    float delta = 0;

    void Update()
    {
        this.delta += Time.deltaTime;
        if(this.delta > this.span)
        {
            this.delta = 0;
            GameObject birth = Instantiate(butterFliesPrefab);
            int px = Random.Range(-7, 6);
            birth.transform.position = new Vector3(px, 5.0f,0.0f);
        }
    }
}
推しからおはようメッセージを受け取るBOTを作ったよ

# 注釈
[こちら](https://technowanko.com/posts/program/bot/linebot/)に移動しました。

# はじめに
python初学者です。
楽しくpythonを学習できる方法はないかと模索していると、bot開発が楽しそうなので試してみました。
どうせなら推しから毎朝、自動メッセージが送信されるように作成してみました！

#実行環境
python : 3.8
github actions

今回の環境は、自前でサーバを用意することなくサーバレスに実行できる構成です。

#ファイル
* info.json
* main.py

この２つだけ！

#ソースコード
```python:main.py
import json
from linebot import LineBotApi
from linebot.models import TextSendMessage

file = open('info.json', 'r')
info = json.load(file)

CHANNEL_ACCESS_TOKEN = info['CHANNEL_ACCESS_TOKEN']
line_bot_api = LineBotApi(CHANNEL_ACCESS_TOKEN)

def main():
    USER_ID = info['USER_ID']
    messages = TextSendMessage(text="おはよう〜　みなみだよ❤︎ \n今日も１日頑張ろうね！")
    line_bot_api.push_message(USER_ID,messages=messages)

if __name__ == "__main__":
    main()
```


```json:info.json
{
    "CHANNEL_ACCESS_TOKEN": "~~~~~~~~~",
    "USER_ID": "~~~~~~~~"
}

```

info.jsonに記載されている変数をmain.pyから参照しています。

Line-Developperでチャンネルを作成する方法は、[こちら](https://developers.line.biz/ja/docs/liff/getting-started/)。

チャンネル作成後に、
"CHANNEL_ACCESS_TOKEN"は、「Messaging API settings」タブから
"USER_ID"は、「Basic settings」タブからそれぞれ取得できます。

#githubへpush
```shell
$ git init
$ git remote add origin https://~~~.git
$ git add .
$ git commit -am "first commit"
$ git push origin maseter
```

#github action の設定

#####Actionsから設定を行います
![スクリーンショット 2021-11-27 16.50.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2097948/4ac868bc-1ba6-80f0-3778-f6f4fe3c1cec.png)

後続の作業とyamlファイルの記述方法は、下記youtubeを参考にさせていただきました。

https://youtu.be/T0KAE2kq2Xo

実際のyamlファイルはこんな感じ

```yaml

name: hello_chatbot

on:
#   push:
  schedule:
    - cron: '55 20 * * *'

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python 3.8
        uses: actions/setup-python@v1
        with:
          python-version: 3.8
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install line-bot-sdk
      - name: Run script
        run: |
          # main.pyの実行
          python main.py
```

github actionsのcronの時刻はUTCらしいので、起動させたい時刻からマイナス９した値を設定する必要があります。
私の場合は、毎朝6時にメッセージを受け取りたいので、AM6:00から-９してPM9:00に設定していたのですが、
ビルドに時間がかかるのでさらに５分早めに起動させています。

```yaml
  schedule:
    - cron: '55 20 * * *'
```

#完成
![スクリーンショット 2021-11-27 17.07.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2097948/1b623977-1a8a-8dc4-9019-1db102a9b9c6.png)
最高やないかい！！！（キモいとか言わないで。）
gradleがpublishするpom.xmlにdependencyを入れる

gradleでライブラリとしてjarをpublishしたときpom.xmlにdependenciesが含まれてなくてあれ？　となった失敗談。その場合は、というか、基本的には```publications```で```artifact jar```ではなく```components.java```を使用する。

# 環境
* gradle 7.3

# ソースコードなど
まず適当な```dependency```を含む適当な```build.gradle```を作成する。

```gradle
plugins {
  id 'java-library'
  id 'maven-publish'
}

group = 'kagamihoge.example'
version = '0.0.1-SNAPSHOT'

repositories {
  mavenCentral()
}

dependencies {
  implementation 'com.google.guava:guava:31.0.1-jre'
}

publishing {
  publications {
    mavenJava(MavenPublication) {
      artifact jar
    }
  }
}

```

上記の通り```artifact jar```で```gradlew publishToMavenLocal```をする。するとlocalのmaven-repositoryに以下の```pom.xml```がpublishされる。

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>kagamihoge.example</groupId>
  <artifactId>app</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</project>
```

今回はここに```guava```が入っていて欲しいけど入ってない。そうしたい場合、以下のように```artifact jar```ではなく```from components.java```を使用する。

```gradle
publishing {
  publications {
    mavenJava(MavenPublication) {
      //artifact jar
      from components.java
    }
  }
}

```

こうすると以下のように入ってくれる。

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <!-- This module was also published with a richer model, Gradle metadata,  -->
  <!-- which should be used instead. Do not delete the following line which  -->
  <!-- is to indicate to Gradle or any Gradle module metadata file consumer  -->
  <!-- that they should prefer consuming it instead. -->
  <!-- do_not_remove: published-with-gradle-metadata -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>kagamihoge.example</groupId>
  <artifactId>app</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>31.0.1-jre</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</project>

```

マニュアルによると、

> components.java
A SoftwareComponent for publishing the production JAR created by the jar task. This component includes the runtime dependency information for the JAR.
> https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_plugin_publishing

This component includes the runtime dependencyてことらしい。
【Vue.js】ハンバーガーメニュー開閉時にスクロール制御する方法

#はじめに
こんにちは。
こちらの記事では、クリックイベント発生時にスクロールの制御を行う方法を記しています。
誤っている点がございましたらコメントいただけると幸いです。

##実装手順

###1. スマホのときに表示するハンバーガーボタンを作成する
レスポンシブ対応時に、ヘッダーにボタンを配置する。
`isOpen`の初期値にfalseを設定しているので、クリックされて`toggleScroll`イベントが発火すると、真偽値が反転する処理を記述する。

```html:template
<header>
  <button @click="toggleScroll">
</header>
```

```javascript:script
data: function () {
  return {
    isOpen: false,
  };
},
methods: {
    toggleScroll() {
      this.isOpen = !this.isOpen;
    }
}
```

###2. イベントの発生を制御する関数を定義
この後使用するスクロールを制御を実装するために、`preventDefault()`メソッドを定義します。


```javascript:script
function scroll_control(event) {
  event.preventDefault();
}

export default {
}
```

###3. 真偽値を判別してスクロールの制御を行う
`isOpen`がtrueのときは、PCでのスクロール（mousewheel）とスマホでのタッチスクロール（touchmove）を無効にし、falseのときは無効にしたイベントを解除する処理を実装します。

```javascript:script
methods: {
  toggleScroll() {
    this.isOpen = !this.isOpen;
    if (this.isOpen === true) {
      document.addEventListener("mousewheel", scroll_control, {
        passive: false,
      });
      document.addEventListener("touchmove", scroll_control, {
        passive: false,
      });
    } else {
      document.removeEventListener("mousewheel", scroll_control, {
        passive: false,
      });
      document.removeEventListener("touchmove", scroll_control, {
        passive: false,
      });
    }
  },
}
```
2.で定義した`scroll_control()`の中で`preventDefault()`が実行されています。また、`preventDefault()`でスマホでのタッチスクロール（touchmove）を無効にする場合は、`passive:false`を設定しないと正常な挙動にならないので注意が必要です。


##参考

* [Event.preventDefault()](https://developer.mozilla.org/ja/docs/Web/API/Event/preventDefault)
* [【javaScript】でスクロールを禁止にする（PC、スマホ対応）](https://programming.sincoston.com/no-scroll-pc-mobile/)
* [マウスによるスクロールやスマホのスワイプを制御するjs(passive: false)](https://reiwinn-web.net/2018/05/21/%E3%83%9E%E3%82%A6%E3%82%B9%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B9%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AB%E3%82%84%E3%82%B9%E3%83%9E%E3%83%9B%E3%81%AE%E3%82%B9%E3%83%AF%E3%82%A4%E3%83%97%E3%82%92%E5%88%B6/)


<br>


#おわりに
ここまでクリックイベント発生時にスクロールの制御を行う方法についてまとめました。
Vue.jsでの実装されている記事がなかったので、このように実装してみましたが、こんな方法もあるよ！などがあればコメントいただけると助かります！

以上、最後まで読んでいただきありがとうございました！
よければLGTMを押してくれると嬉しいです！
Rapsberry Piのvimでclipboard内のテキストをペーストする

年に数回Rapsberry Piを新規セットアップして使うことがあるのですが、いつもvimでテキストをペーストしようとして躓くので備忘録。

# Rapsberry PiのOSを最新状態にした後まずやること

```bash
$ sudo apt install vim-nox  # +clipboardのvimをインストール
$ echo "set mouse=" >> ~/.vimrc  # vimでマウスは使わない派なのでoffに
```
【Flutter】AnimationControllerを使ってクロック回路を実装する

##概要##

Flutterで``AnimationController``を使用して、
周期的に状態ONOFFが切り替わる回路(クロック回路)
を実装できましたので、紹介致します。

参考になれば幸いです。

##サンプルアプリ##
今回実装したクロック回路を使って画像の切り替わるアプリを作成しました。
下のツイート内の動画のように動作します。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Flutter AnimatedControllerを使ってクロック回路を実装しました。<br>1秒おきに状態が切り替わります。 <a href="https://t.co/OIl6Rru3Tc">pic.twitter.com/OIl6Rru3Tc</a></p>&mdash; Aoi.Umigishi🎮Indie App Developer＠Flutter (@iNw17r8YHWThqgC) <a href="https://twitter.com/iNw17r8YHWThqgC/status/1464476999083192330?ref_src=twsrc%5Etfw">November 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こちらのアプリのコードは以下のGitHubにあげています。
気軽にクローンしてください。

https://github.com/Umigishi-Aoi/ClockWithAnimatedController


##サンプルコード##

実装の``State``クラスの部分だけ抜き出しで紹介します。

```dart
//1
class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {

  final duration = const Duration(seconds: 1);
  late AnimationController _ctrl;

  bool _flag = true;

  static const double _widthRatio = 0.7;

  @override
  void initState() {
    super.initState();
    //2
    _ctrl = AnimationController(duration: duration, vsync: this)
      //3
      ..forward()
      //4
      ..addStatusListener((status) {
        //5
        if (status == AnimationStatus.completed) {
          _ctrl.reverse();
          setState(() {
            _flag = false;
          });
        } else if (status == AnimationStatus.dismissed) {
          _ctrl.forward();
          setState(() {
            _flag = true;
          });
        }
      });
  }

  @override
  void dispose() {
    _ctrl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
//省略//
  }
}
```
##ポイント##

//1
``SingleTickerProviderStateMixin``をmixinしています。
``AnimationController``の``vsync``を設定するのに使用しています。
忘れずにmixinしましょう。

//2
``initState``内で``AnimationController``の初期化を行なっています。

//3
``forward()``でアニメーションの再生を指示しています。
このアニメーションはアニメーション関連の``Widget``の実装ありなし関係なく、内部で再生されます。

//4
``addStatusListener``で追加するメソッドは、アニメーションの``status``が変化する毎に呼び出されます。
この``status``はアニメーションが終了すると``completed``に、
巻き戻しが終わりきると、``dismissed``になります。

//5
今回の実装のキモです。
``addStatusListener``で追加するメソッドで``completed``の状態の時に巻き戻し``(reverse)``、
``dismissed``の状態の時に再生``(forward)``をするよう指示すると、
``duration``で設定した秒数毎に``completed``と``dismissed``を往復します。
ここに``completed``の時に``false``に、``dismissed``の時に``true``になるよう、状態を設定すれば、
``duration``で設定した秒数毎に``true,false``の切り替わるクロック回路の完成となります。
ただし、``setState``を呼ばないとリビルドされませんので、忘れずに追加しましょう。

以上、読んでいただきありがとうございました。
興味深いと思っていただけたら、LGTMいただけますと嬉しいです。

##参考##

https://medium.com/flutter-jp/transition-9c57528c84b8

https://www.raywenderlich.com/26483389-flutter-canvas-api-getting-started?utm_content=buffer3b494&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer
OSS-DB Silver試験に合格しました

# OSS-DB Silver試験とは
https://oss-db.jp/

平たく言うと、PostgreSQLの資格試験です。

# なぜ受けようと思ったのか
- データベースの知識が基本情報レベルしか無かったので、改めてしっかりと勉強したくなった
- ちょうど仕事で使っていたのがPostgreSQLだった

# 勉強方法
- [OSS教科書 OSS-DB Silver Ver2.0対応](https://www.amazon.co.jp/OSS%E6%95%99%E7%A7%91%E6%9B%B8-OSS-DB-Silver-Ver2-0%E5%AF%BE%E5%BF%9C-%E7%A6%8F%E5%B2%A1-ebook/dp/B07XBWVBMT/ref=mp_s_a_1_3?crid=XG4NLGZZXBX7&keywords=ossdb+silver&qid=1637998761&sprefix=ossdb%2Caps%2C478&sr=8-3)でインプット
- [内部構造から学ぶPostgreSQL](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88-%E5%86%85%E9%83%A8%E6%A7%8B%E9%80%A0%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6PostgreSQL-%E8%A8%AD%E8%A8%88%E3%83%BB%E9%81%8B%E7%94%A8%E8%A8%88%E7%94%BB%E3%81%AE%E9%89%84%E5%89%87-Software-Design/dp/4297100894/ref=mp_s_a_1_2?keywords=postgresql&qid=1637998897&sr=8-2)で更なるインプット
    - この本はどちらかと言うと興味で読んだので、資格対策的にはオーバースペックかもです
- [徹底攻略OSS-DB Silver問題集［Ver.2.0］対応](徹底攻略OSS-DB Silver問題集［Ver.2.0］対応)で問題演習
    - Ping-tより問題が少ないので、正直無くてもよかったかも
- [Ping-t](http://ping-t.com)で問題演習
- [公式ドキュメント](https://www.postgresql.jp/document/11/html/)を読みながらLinuxへのインストールをやってみる

# 結果
スコア84%で合格(ラインは64%)

# 所感
- 問題のレベルはほぼPing-tと同じ
- 数問、Ping-tより難しい(というか細かい)問題があったが、そういう問題は諦めてOK
- 試験勉強を通じてPostgreSQLに少し詳しくなれて嬉しい
- もちろんこれで終わりではないので、引き続き勉強したり、実務の中で経験を積んだりしていきたい
viの使い方

<h1>①viの起動</h1>
ファイルを編集する場合
`$ vi ファイル名`

<h1>②viの終了</h1>
:q　	viの終了　(何も書き込まずに終了したい場合)
:wq　	ファイルに書込んだものを上書き保存してviを終了
:q!　	編集結果をファイルに書込まずに終了
:wq!　	リードオンリーのファイルに強制的に書き込んで終了

<h1>③カーソルの移動</h1>
h　	カーソルを1文字左へ
j　	カーソルを1行下へ
k　	カーソルを1行上へ
l　	カーソルを1文字右へ
o　	カーソルを行頭へ
$　	カーソルを行末へ

<h1>④文字の挿入方法</h1>
i　	入力モードに移行。カーソル位置の前に文字を挿入
a　	入力モードに移行。カーソル位置の後に文字を追加
A　	入力モードに移行。行の終わりに文字を追加
O　	入力モードに移行。現在の行の前に文字を挿入
R　	入力モードに移行。カーソル位置の文字を上書き

<h1>⑤文字の削除</h1>
x　	カーソル位置の文字を削除
dd　	１行削除
xdd　	x行削除（例：3ddと入力すると３行削除）
J　	次の行を、現在カーソルのある行の末尾に追加（行末文字の削除)

<h1>⑥行のコピー&ペースト</h1>
Y　	カーソルのある行をコピー
yy　	カーソルのある行をコピー(Yと同じ意)
p　	コピーした行をペースト
yyp　	カーソルのある行をコピーし、その行の下にペースト(Ypも同じ意)

<h1>⑧検索</h1>

/sample　	sampleという文字列をファイルの末尾に向かって検索
?sample　	sampleという文字列をファイルの先頭に向かって検索
n　	　　　　　次の候補を検索

<h1>⑨UNDO</h1>
u　	直前の操作を取りやめる
U　	行全体の操作を取りやめる

※ :w(保存) で保存してから :wq(保存と終了)
　:q(保存しなで終了)　:q!
Windowsコマンドをコンパイル環境なしでexeにする。

以前の記事でなんとかExe化までに至ったが、cscでのコンパイルが必要になるのと
特定のpythonコマンドラッパーしか作れないといった点が気に食わなかった。 

https://qiita.com/kirin123kirin/items/10a23fb02df5382b2858

# で今回C++でexeを作るexeを作った。
#### 名前はmkexe.exe

”えぐぜ”だらけで何言ってるのかわけわからん。

今回のはWindowsコマンドプロンプトで実行できるものはexe化できる。

mkexe.exe の引数に覚えさせたいコマンドを渡せば、RenameMe.exeというexeが新しくできるので、
実行すると引数のコマンドを覚えてて、実行してくれる。
要するにこんな感じ、、

# Example1.
```powershell
mkexe.exe "echo foo bar"
.\RenameMe.exe # <-出来上がったファイルを実行
foo bar
```

# Example2.
```powershell
mkexe.exe "start http://example.com"
.\RenameMe.exe # <-出来上がったファイルを実行
## ⇒デフォルトブラウザが起動し、http://example.comにアクセスする。
```

# Example3.
```powershell
mkexe.exe "cd C:\temp" "echo hoge > hoge.txt" "notepad.exe hoge.txt"
.\RenameMe.exe # <-出来上がったファイルを実行
## ⇒C:\tempにhoge.txtのファイル名でhogeと書き込み、そのファイルをメモ帳で開く。
```

## わからんが発想はこんな感じ、こんな強引でよいのか？

* まずシステムコマンドを実行できるプログラムとして、a.exeを作った。
* a.exeをひな型に、バイナリの中からシステムコマンド文字列部分を、引数入力されたコマンド文字列に
置き換えて、新しいexeを作る。

* 文字列を置き換えてるだけなので、コンパイル環境がなくても、、、という感じ
* mkexe.exe単体で機能する。もちろん出力結果のRenameMe.exeも単体で機能する。


#### Windows10 64bit 環境でコンパイル済みのmkexe.exeを保存した。

https://github.com/kirin123kirin/mkexe/releases

#### 恥ずいソース

https://github.com/kirin123kirin/mkexe.git
RedmineをプレイブックでOracleLinuxに入れるときに躓いたこと

#概要
Redmineの検証でプレイブックを使ってインストールをしようとしたところ、どうしても躓くところがあった。
プレイブック：https://github.com/farend/redmine-centos-ansible

作業環境：Oracle Linux 8.4
#致命的な"アレ"がない
rootで入りプレイブックをクローンし、ansibleを走らせると必ずこのエラーが出てしまう。

>TASK [system : powertoolのインストール] ***************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "dnf config-manager --set-enabled powertools", "delta": "0:00:00.961142", "end": "2021-11-27 15:25:06.259012", "msg": "non-zero return code", "rc": 1, "start": "2021-11-27 15:25:05.297870", "stderr": "エラー: 修正用の一致する repo はありません: powertools.", "stderr_lines": ["エ ラー: 修正用の一致する repo はありません: powertools."], "stdout": "", "stdout_lines": []}


読んでもらえればわかるがPowertoolsのリポジトリがないと出てきてしまう。
それもそのはず、**Oracle LinuxにはPowerToolsは同梱されていない**。

#じゃあどうすればいいのか
PowerToolsの使用用途はImage Magickインストールするためのものだった。
調べたらOracle　LinuxではCodeReady BuilderがPowerToolsに該当するみたいだった。


とりあえず、有効にする。
※手癖の都合、yumで記載してます。ご了承ください。
>yum config-manager --set-enabled ol8_codeready_builder

有効にしたはいいがこのままではPowerToolsを参照してしまい結局エラーが出てしまう。
かといって手動でインストールもやりたくない。

そのため、site.ymlが入っているディレクトリ（redmine-centos-ansible）からさらに移動して、

>～（省略）/redmine-centos-ansible/roles/system/tasks/main.yml

をVimまたはEmacsで開く。(宗教戦争のための配慮)

その後以下の記載を削除する。
>- name: powertoolのインストール
  shell: dnf config-manager --set-enabled powertools warn=no

保存し、site.ymlが入っているディレクトリまで戻り、プレイブックの手順通り以下のコマンドを実行し、インストール作業が無事始まる。
>ansible-playbook -i hosts site.yml

#おまけ
デスクトップ(フルパス：/home/test/**デスクトップ**)で作業してたら文字コードの変換でエラーが出て当然の如く止まってしまった。

解決方法は言うまでもない。

やはり日本語ディレクトリは悪い文化である。
VBAでFor文のループ条件を途中で変更できない

VBAでForループをj回実行するときに、For文内でjの値を変更しても、ループ回数に反映されません。


```VB:test
Sub ボタン1_Click()
    Dim i As Integer
    Dim j As Integer
    
    j = 10
    For i = 0 To j-1 Step 1
        j = 20
    Next i
    
    Call MsgBox(i, vbOKOnly)    
End Sub

```

```:VBAの結果
10
```

上の例では、Forループ内でjを10から20に変更しても、Forループは10回しか実行しません。


なお、Cの場合、for文内でjの値を変更すると、ループ回数に反映されます。

```C:test.c
#include <stdio.h>

void main(void){
	int i;
	int j=10;

	for(i=0;i<j;i++)
	{
		j=20;
	}

	printf("%d\n",i);
}

```

```:test.cの結果(gcc)
20
```

上の例では、forループ内でjを10から20に変更すると、forループは20回実行されます。



Javaは、Cと同様です。

```Java:Sample.java
class Sample
{     
    public static void main(String[] args)
    {         
        int i,j=10;

        for(i=0;i<j;i++)
        {
            j=20;
        }

        System.out.println(i);       
    }     
}

```

```:Sample.javaの結果(javac)
20
```
shellスクリプトの確認処理とfor文を組み合わせた際の注意！

##概要
shellスクリプトのfor文で発生するスキップされて2行目が表示されないという問題。
理由はいたってシンプルで「標準入力」だから。
お作法は下記で勉強できます。

### 詳細や参考
[シェルスクリプトを書くときに気をつける9箇条](https://qiita.com/b4b4r07/items/9ea50f9ff94973c99ebe)


### 解決法
・リスト化してfor文を使用する

```shell
# データの内容をファイルをリスト変数に格納
list-code=$(cat ./data.txt)
#ループ処理を実行
for X in ${list-code}
do
      	read -p "${X} : ok? (y/n):" yn
	case "$yn" in
	  [yY]*)
	    # この行に実行したい処理を記載する。
	  ;;
	  *) echo "skip"
          ;;
        esac
done
```


### まとめ
while文を使用すると発生します。
様々なループ処理を使用できるとエラーが発生した際に
解決する時間がない場合に方法を切り替えることも手段です。
screensフォルダを作成する

# Vueでのviewsフォルダのようにscreensフォルダを作成

プロジェクト直下のsrcの中にscreensフォルダを作成する。
このフォルダにはvuejsでのviewsフォルダのような役割のフォルダ。

# App.jsxをさらにシンプルにする。
## 現在App.jsxは下記の通り。

```jsx
import React from 'react';
import { StyleSheet, View } from 'react-native';

import AppBar from './src/components/AppBar';
import CircleButton from './src/components/CircleButton';
import MemoList from './src/components/MemoList';

// eslint-disable-next-line react/function-component-definition
export default function App() {
  return (
    <View style={styles.container}>
      <AppBar />
      <MemoList />
      <CircleButton>+</CircleButton>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FCE4EC',
  },
});
```
これをよりスッキリさせる。

## screensフォルダの中にMemoListScreen.jsxファイルを作成する。
App.jsxに記述されていた内容を移植してくる。
MemoListScreen.jsx

```jsx
import React from 'react';
import { View, StyleSheet } from 'react-native';

import AppBar from '../components/AppBar';
import CircleButton from '../components/CircleButton';
import MemoList from '../components/MemoList';

// eslint-disable-next-line react/function-component-definition
export default function MemoListScreen() {
  return (
    <View style={styles.container}>
      <AppBar />
      <MemoList />
      <CircleButton>+</CircleButton>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FCE4EC',
  },
});
```

## App.jsxにMemoListScreen.jsxを読み込む
App.jsx

```jsx
import React from 'react';

import MemoListScreen from './src/screens/MemoListScreen';

// eslint-disable-next-line react/function-component-definition
export default function App() {
  return (
    <MemoListScreen />
  );
}
```

App.jsxがよりスッキリさせることができた。
GitHubのsshキー設定エラーについて。

<h1>GitHubに公開鍵を設定しよう</h1>
*<p>$ ssh-keygen -t rsa -b 4096 -C "メールアドレス"</p>*

 # -t 暗号化方式を指定
 # -b 暗号化強度を指定
 # -C コメントを設定 

・パスワード２回入力

<h1>公開鍵をクリップボードにコピーする</h1>

*<p>$ pbcopy < pbcopy < /Users/yuya/.ssh/id_rsa.pub</p>*

<h1>gitgubの設定画面を表示する</h1>

![スクリーンショット 2021-11-27 15.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495496/f5f2a22d-8091-2e25-072d-bd232da8febf.png)

![スクリーンショット 2021-11-27 16.03.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495496/046df35e-f919-242c-7ccf-81f79d1b25a5.png)

![スクリーンショット 2021-11-27 16.03.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495496/9a9fa9f0-4213-41f7-89b3-7b19401fb631.png)

*<p>確認コマンドを入力　$ ssh -T git@github.com </p>*

※それでもできない場合は、cat ~/.ssh/id_rsa.pub をターミナルで実行して公開キーを貼り付ける。
AIでツイッターユーザーの年代や性別、職業・年収等を判定するサービス「あの人どんな人？」をリリース


# はじめに
### 概要
AIで直近ツイート２００件から
ツイッターユーザーを解析できるサービスです
年代や性別、職業・年収・既婚/未婚など１０項目以上の判定可能です

https://user-attribute.web.app


### 発端
COTOHA API というのを見つけて、リファレンスを読んでみると
「ユーザ属性推定(β)」という面白そうなものがあったからです
>twitterにおけるユーザのtweetやprofileの入力を前提とするようにチューニングをしています。

とあるので、ツイートをAPIに投げ込めば良さげなものが作れそうと思いました

https://api.ce-cotoha.com/contents/reference/apireference.html#user


# 技術スタック
- フロントエンド
typescript
React
Firebase Hosting

- バックエンド
C#
Heroku

- データベース
Firebase RealtimeDatabase

# 開発に関して
特に新しいことをやるわけではなかったので
いつも通り既存のリソースを活かしてサクッと作りました

下記２つは新しい試みだったので楽しかったです

- COTOHAPIのライブラリを作れたこと
- Reactを使えたこと


# 副産物
pythonかC#で作ろうと考えていましたが
調べてみるとサンプルコードが少なそうだったのでC#で作ることにしました
また、作るにあたってライブラリにしたら、みんな使えてみんな良いと思い、ライブラリにしました
どうぞお使いください

https://github.com/HawkClaws/COTOHALib
Git CUIに慣れよう（初心者編）

# はじめに
SVNを最近使用しているが、Gitにも慣れておく必要があると常々感じている。今まではSourceTreeやTortoiseGitなどのGUIを使用していたが、そろそろCUIへの苦手意識を克服したい！！！

そこでここでは、(自分用に)ローカルリポジトリの作成からリモートリポジトリへのプッシュまでの基本的な流れについてまとめる。


# 学習目的
 - Git CUI苦手意識を取り除く
 - コマンド操作になれる
 - バージョン管理システムを用いた開発に慣れる（今後を意識して）

# 環境
 - MacOS BigSur ver11.6
 - Git:2.29.2

ターミナルを使用

# Gitに慣れよう！！！

ここでは、以下のサイトを参考に進めていく]
Gitのインストールがまだの方はインストールを。

https://tech-blog.rakus.co.jp/entry/20200529/git

## 1.ローカルリポジトリの作成
ローカルリポジトリを作りたいディレクトリまで移動して、以下のコマンドを実行


```
//ディレクトリ作成
mkdir study

//作成したディレクトリに移動
cd study

//ローカルリポジトリの作成
git init
```

`Initialized empty Git repository in ディレクトリパス` のようなメッセージが表示され、ディレクトリ内に`.git`というディレクトリが作成されていればOK



## 2.ローカルリポジトリにコミットをする
1.で作成したディレクトリ内で適当にファイルを作成します。
例）index.html

ここで一回`git status`で現在の状況を確認します。

```
//git statusコマンドで状況を確認
git status

//コマンド実行結果
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	index.html

nothing added to commit but untracked files present (use "git add" to track)
```

`Untraced files`のところに、index.htmlがあることがわかる。これはまだ追跡されていないファイルということである。

状況がわかったため、インデックスへ追加しコミットをする。
※インデックスとは、コミット前に変更内容を一時的に保存する領域のこと。インデックスに追加されたファイルがコミットの対象となる。

```
//インデックスへ追加(追加するファイルを指定する場合)
git add ファイル名
例）git add index.html 

//インデックスへ追加(カレントディレクトリにある全てのファイルを追加する場合)
git add .


//-mオプションで、コミットメッセージをつけることができる。
git commit -m コミットメッセージ
例）git commit -m "Add:first commit"
```

コミットできているか確認するには、`git log`コマンドで確認できる。

```
$ git log
commit コミットハッシュ (HEAD -> master)
Author: ユーザー名　<メールアドレス>
Date:   Sat Nov 27 14:15:59 2021 +0900

    Add:first commit
```

## 3.リモートリポジトリの作成とプッシュ
ローカルリポジトリの変更をリモートリポジトリに反映させる。
まずは、リモートリポジトリを作成する。

Github上で作成する。作成したら、ローカルリポジトリとリモートリポジトリを紐づける。

Github上のリポジトリのページにある「Code>HTTPS」に記載のURL(https://github.com/ユーザ/○○.git)　
をコピーする。そして以下のコマンドを実行することで紐付けができる。

```
//ローカルとリモートのリポジトリを紐づける
git remote add origin https://github.com/ユーザ/○○.git

//ローカルの内容をリモートリポジトリに反映させる
git push origin master
```

git push を行うとGithubのユーザー名とパスワードが求められる。
しかし、2021年8月よりパスワードの認証ではなくアクセストークンによる認証になった。
脆弱性防止のためとのこと。

> remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.

ということで、以下の記事を参考にアクセストークンを作成する。
作成できたら、再度pushを行いユーザー名と作成したアクセストークンを入力することでpush完了。

https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token


※追記
GitHubでは、デフォルトのブランチがmasterからmainに変わっている。
ただ、git initで生成する際はmasterで生成されている。

生成される際のデフォルトをmainにしたり、GitHub上のデフォルトをmasterにするなどすると良さそう

https://chiroru-memo.hatenablog.com/entry/2020/10/12/234906

https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/changing-the-default-branch


# まとめ
今回は、GitCUIの初歩の初歩についてまとめた。
正直自宅でのちょっとした開発であれば、自分だけしか見ないのでバージョン管理するまでもないといえばそうである。ただ、いきなり業務で使うにはハードルが高いので、こういった間違えても問題ない自宅学習で慣れておくことが大事だと思う。

とりあえず、学習の一環でChromeの拡張機能でも作ってみようと思っているのでついでにめんどくさがらずgitで管理もしようと思います。

以上


# 参考
https://tech-blog.rakus.co.jp/entry/20200529/git

https://zenn.dev/yuri0427/articlesg
【Swift】タイトルのフォントと文字サイズと文字色を同時指定する方法

SwiftでNavigationBarのタイトルのフォントと文字サイズと文字色を同時指定する方法。

同時指定する方法を解説している記事がなかったのでメモとして残しておきます。

## 実装コード

```swift
self.title = "タイトル"
self.navigationController?.navigationBar.titleTextAttributes = [
    NSAttributedString.Key.font:  UIFont.systemFont(ofSize: 40),
    .foregroundColor: UIColor.white
]
```
## 参考
https://developer.apple.com/documentation/uikit/uinavigationbar/1624953-titletextattributes

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
Vue.js よく使うディレクティブとコンポーネント 簡単

Vue.js [3]の学習備忘録

### Vue.jsをインストール
https://v3.ja.vuejs.org/guide/installation.html#%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%8E%E3%83%BC%E3%83%88

<strong>ディレクティブを学ぶ</strong>
-

* v- で始まる特別な属性のこと
* derective(司令)という名前の通り、Vue.jsに何らかの指示を行う仕組み

（ディレクティブ例）

* v-bind(属性のデータバインディング)
* v-if（条件分岐）
* v-for（オブジェクトの繰り返し描画）
* v-on（イベント処理）
* v-model（双方向データバインディング）



<strong>コンポーネント</strong>
-

* 名前付きの再利用可能なインスタンス
* ページを構成するUI部品
* テンプレートとそのロジックから構成
* よく使うコンポーネント化<br>
→再利用性が高くなる<br>
→コードの見通しが良くなる

＝＝＝＞ 開発効率UP！
ファイルの圧縮と展開についてまとめてみた

今回のお題
-
今回のお題はファイルの圧縮と展開です。

Linuxコマンドを用いてファイルの圧縮・展開を行う方法、及びそれらを取り巻く細かな仕様について調べた範囲でまとめます。

なお、ファイルの圧縮・展開に関してはたくさんのオプションがあるようですが、今回は基本となる`cvzf`と`xvzf`にしか触れません。

その点についてはご了承ください。

ファイルの圧縮の方法
-

```shell
# tar cvzf "作成する圧縮ファイル名" "元にするファイル"
% tar cvzf test1.php.tar.gz test.php
```

ファイルの展開方法
-

```shell
# tar xvzf "展開するファイルのパス"
% tar xvzf test1.php.tar.gz
```

ファイルの展開先
-
ファイルを展開した際には、圧縮作業を行ったディレクトリではなく、その時点でのカレントディレクトリに展開後のファイルが作られる。

```shell:ディレクトリ例
|-- dir1
|    |-- test1.txt
|
|-- dir2
```

```shell
% cd dir1
% tar cvzf test1.txt.tar.gz test1.txt
% ls 
>> test1.txt test1.txt.tar.gz
# dir2に移動
% cd ../dir2
# dir2で展開作業を実行
% tar xvzf test1.txt.tar.gz
% ls 
# 展開を行ったdir2にtest1.txtが作成される
>> test1.txt
% ls ../dir1
# 展開を行っても圧縮ファイルは削除されない
>> test1.txt test1.txt.tar.gz
```

展開後のファイル名について
-

```shell
# 展開後のファイル名は圧縮前と同じ
% cd dir1
% tar cvzf test1.txt.tar.gz test1.txt
% ls 
>> test1.txt test1.txt.tar.gz
# dir2に移動
% cd ../dir2
# dir2で展開作業を実行
% tar xvzf test1.txt.tar.gz
% ls 
# 展開を行ったdir2にtest1.txtが作成される
>> test1.txt # ファイル名は圧縮前と同じ
# dir1に移動
% cd ../dir1
% ls
>> test1.txt test1.txt.tar.gz
# dir1内でtest1.txtを展開
% tar xvzf test1.txt.tar.gz
% ls
# 展開後のtest1.txtで元々あったtest1.txtが上書きされるので、見た目上は同じ（もしtest1.txtに何か変更が加わっていた場合には、圧縮前の状態に戻る）。
>> test1.txt test1.txt.tar.gz
```

圧縮ファイルの作成先
-

```shell
# 圧縮ファイル名を単純にファイル名にした場合にはカレントディレクトリに圧縮ファイルが作られる
% tar cvzf test1.txt.tar.gz test1.txt
# カレントディレクトリにtest1.txt.tar.gzが作られる

# 圧縮ファイル名としてパスを与えた場合にはそのパスに対応した箇所に圧縮ファイルが作られる
% tar cvzf /var/www/html/test1.txt.tar.gz test1.txt
# /var/www/html/にtest1.txt.tar.gzが作られる
# パスは相対・絶対のどちらも可能だが、存在しないディレクトリは指定不可（＝圧縮ファイルと同時に親ディレクトリを作成することはできない）。
```

カレントディレクトリ以外のファイルを圧縮する場合
-
元にするファイル名の代わりにパスを指定することでカレントディレクトリに存在しないファイルを圧縮することも可能だが、その場合には末端のファイルだけではなくパス全体が展開される。

```shell
% cd ..
# dir1のtest1.textを圧縮し、dir2に保存
% tar cvzf dir2/test1.txt.tar.gz dir1/test1.txt
# dir2に移動
% cd dir2
# ファイルを展開
% tar xvzf test1.txt.tar.gz
# dir2の中にdir1が、その中にtest1.txtが作られる
% ls
>> dir1
% ls dir1
>> test1.txt
```
Webの勉強はじめてみた その4 ～JavaScript編 宣言と指数表現～

今日は1コマだけ。

<h2>今日やったこと</h2>
:::note
JavaScriptのデータ型、計算、変数
:::

<h2>気付いたこと</h2>
:::note
1. 指数表現
2. 変数
:::
<h3>1. 指数表現</h3>
:::note
Xe + Y
:::

初めて知った表現。
X × 10 の Y 乗 ( X×10**Y ) 
コンソールなんかで、値が大きすぎるとこういう表示になるらしい。
そういえばエクセルでも同じだったような気がする。

`1.5e+20 ⇒ 1.5 × 10**20`

::: note warn
Xにあたる数字は桁数を増やさずに小数で表現するのが一般的？
15e+10 ⇒ 1.5e11
:::

<h3>2. 変数</h3>
:::note 
var let の違い
:::

https://techacademy.jp/magazine/14872

const は名前的にも定数では？
と思うものの、var と let の違いはなんとなく。
letで宣言したほうがチームでの開発とかでは無難なのかも。
【図解解説】JOI2021-2022 一次予選 第2回 問題2 短針

## 図解解説シリーズ
競技プログラミングを始めたばかりでAtCoderの解説やJOIの解説ではいまいちピンと来ない…という人向けに、図解を用いて解説を行います。

## 問題文
### 情報オリンピック日本委員会に掲載されている問題

https://www.ioi-jp.org/joi/2021/2022-yo1/2022-yo1b-t2.html

### AtCoderに掲載されている問題
入出力など実際に確認して自分の作成したプログラムを採点することができます。

https://atcoder.jp/contests/joi2022yo1b/tasks/joi2022_yo1b_b

## 図解解説
今年度の一次予選のB問題は、以下の３つのスキルを確認する問題になっています。
１．入力・出力を正しく利用できる
２．算術演算子を正しく利用できる
３．条件分岐（if）を正しく利用できる

問題文を整理するために、具体的な数字を用いて、図示して考えてみます。
![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2211017/511f15eb-6279-1b11-41c3-df4b0feb9d0b.png)
入力例１のA=９時を使って、B時間後に何時になるか表を作成してみます。すると、1～12の数字が周期的に出てくることを確認することができます。

そこで、表の中にA+Bの計算結果を入れてみます。12時間ごとに変わるので、A+Bを12で割った余りを書き加えてみます。すると、余りが0のとき時刻は一致しませんが、それ以外の時刻は一致することが確認できます。そこで、A+Bを12で割った余りが0のときは答えが12、それ以外のときは答えがA+Bを12で割った余りを表示するようにプログラムを作成します。

![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2211017/3c09eac1-a9db-57e4-c9cc-b2ab672284ed.png)
場合分けをせずに答えを出す方法を考えてみます。1時～12時の周期が、12で割った余りの0～11の周期と一致するように計算を調整します。そのためにA+B-1を計算し、この値(A+B-1)を12で割った余りを求めると周期が一致します。余りに1を加えると1～12となり、1時～12時の値と一致します。

## 解答例
### 余りが0のときとそれ以外のときで場合分けをしたプログラム

```b1.py
A = int(input())
B = int(input())
#A時のB時間後が何時になるか計算を行う
#A+Bを計算し12で割った余りが0のときは、12時
#A+Bを計算し12で割った余りが0でないときは、余り
if (A+B)%12==0:
  print(12)
else:
  print((A+B)%12)
```
[採点サイトに提出したプログラム](https://atcoder.jp/contests/joi2022yo1b/submissions/27507912)

### 余りを調整して、if文を使用せずに作成したプログラム

```b2.py
A = int(input())
B = int(input())
#A時のB時間後が何時になるか計算を行う
#A+B-1を計算し12で割った余りに1を加えたのが答え
print((A+B-1)%12+1)
```
[採点サイトに提出したプログラム](https://atcoder.jp/contests/joi2022yo1b/submissions/27508048)

## イラスト
スライド内で使用しているイラストはすべて「[いらすとや](https://www.irasutoya.com/)」の素材を利用しています。
propsを受け取るコンポーネント

# ボタンコンポーネントをchildrenを受け取れるようにする
丸いボタンを再利用するために、
ボタンの中に表示するものはpropsとして親から受け取れるようにする。

```jsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
// eslint-disable-next-line import/no-extraneous-dependencies
import { string } from 'prop-types';

// eslint-disable-next-line react/function-component-definition
export default function CircleButton(props) {
  const { children } = props;
  return (
    <View style={styles.circleButton}>
      <Text style={styles.circleButtonLabel}>{children}</Text>
    </View>
  );
}

CircleButton.propTypes = {
  children: string.isRequired,
};

const styles = StyleSheet.create({
  circleButton: {
    backgroundColor: '#C51162',
    width: 65,
    height: 65,
    borderRadius: 32,
    justifyContent: 'center',
    alignItems: 'center',
    position: 'absolute',
    right: 40,
    bottom: 40,
    /* shadowはiphoneにしか効かないCSS */
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 8 },
    shadowOpacity: 0.35,
    shadowRadius: 5,
    /* elevationはAndroid用のCSS */
    elevation: 8,
  },
  circleButtonLabel: {
    color: '#fff',
    fontSize: 32,
    lineHeight: 32,
    fontWeight: 'bold',
  },
});
```

export default function　の引数にpropsをとる。
propsの中のchildrenを受け取るために、const { children } = props;として、ボタンの中にchildrenを渡す。

```jsx
<Text style={styles.circleButtonLabel}>{children}</Text>
```

propsで受け取るものに、typeを設定する。
import { string } from 'prop-types';をインポートして、

```js
CircleButton.propTypes = {
  children: string.isRequired,
};
```
isRequiredは必須で渡されるものにつける。
もしisRequiredでない場合は、
デフォルト値を指定する。

```js
CircleButton.defaultProps = {
  children: '',
};
```

App.jsxも変更して、親からchildrenをボタンコンポーネントに渡す。

```jsx
import React from 'react';
import { StyleSheet, View } from 'react-native';

import AppBar from './src/components/AppBar';
import CircleButton from './src/components/CircleButton';
import MemoList from './src/components/MemoList';

// eslint-disable-next-line react/function-component-definition
export default function App() {
  return (
    <View style={styles.container}>
      <AppBar />
      <MemoList />
      <CircleButton>+</CircleButton>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FCE4EC',
  },
});

```
ktlint を導入した話

## はじめに

今更ながら ktlint を導入する機会があったので、その手順などをまとめました。

> 参考：ktlint とは？

ざっくり、[Kotlin Style Guide](https://developer.android.com/kotlin/style-guide) を元にコードスタイルのチェックをしてくれたり、lint で検出した部分にフォーマットをかけてくれたりしてくれる Kotlin 用の静的コード解析ツールになります。

> 公式ページ

[ktlint HP](https://ktlint.github.io/)

> サンプルソース

- GitHub
[simple-ktlint-android](https://github.com/ngkr327/simple-ktlint-android)

## 導入

### 1. 準備

Android Studio: `3.4.1`
ktlint: `0.4.0`

### 2. 導入

（ktlint の [README](https://github.com/pinterest/ktlint/blob/master/README.md) のとおり）Gradle へ依存関係の追加と、ktlint を実行するためのタスクを追加します。

```app/build.gradle

configurations {
    ktlint
}

dependencies {
    ktlint "com.pinterest:ktlint:0.40.0"
}

task ktlint(type: JavaExec, group: "verification") {
    description = "Check Kotlin code style."
    classpath = configurations.ktlint
    main = "com.pinterest.ktlint.Main"
    args "src/**/*.kt"
}
check.dependsOn ktlint

task ktlintFormat(type: JavaExec, group: "formatting") {
    description = "Fix Kotlin code style deviations."
    classpath = configurations.ktlint
    main = "com.pinterest.ktlint.Main"
    args "-F", "src/**/*.kt"
}
```

プロジェクトのルートディレクトリで

```
$ ./gradlew ktlint
```

を実行すると結果が出力されます。また、

```
$ ./gradlew ktlintFormat
```

を実行すると、lint で検出されたコードにフォーマットをかけてくれます。

### Option #1

チェックにひっかかっても途中で終了させないようにするために `ignoreExitValue true` を設定します。

```
task ktlint(type: JavaExec, group: "verification") {
    ignoreExitValue true
}

task ktlintFormat(type: JavaExec, group: "formatting") {
    ignoreExitValue true
}
```

### Option #2

ビルド時にフォーマットをしたいので以下も追加します。

```app/build.gradle

tasks.whenTaskAdded { task ->
    task.dependsOn ktlintFormat
}
```

これにより毎回コマンドを実行しなくても、ビルド時にフォーマットしてくれるようになります。コミット後のフォーマットの修正漏れの予防にもなります。
Numpyの整数と浮動小数点数の最大値と最小値

numpy.iinfo()で整数，numpy.finfo()で浮動小数点数の情報を得る．

```python3
>>> import numpy as np

>>> np.iinfo(np.int64)
iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)
>>> np.iinfo(np.int32)
iinfo(min=-2147483648, max=2147483647, dtype=int32)
>>> np.iinfo(np.int16)
iinfo(min=-32768, max=32767, dtype=int16)
>>> np.iinfo(np.int8)
iinfo(min=-128, max=127, dtype=int8)

>>> np.finfo(np.float128)
finfo(resolution=1.0000000000000000715e-18, min=-1.189731495357231765e+4932, max=1.189731495357231765e+4932, dtype=float128)
>>> np.finfo(np.float64)
finfo(resolution=1e-15, min=-1.7976931348623157e+308, max=1.7976931348623157e+308, dtype=float64)
>>> np.finfo(np.float32)
finfo(resolution=1e-06, min=-3.4028235e+38, max=3.4028235e+38, dtype=float32)
>>> np.finfo(np.float16)
finfo(resolution=0.001, min=-6.55040e+04, max=6.55040e+04, dtype=float16)
```

簡単な四則演算ではfloat系ではfloat32が早く，int系は割り算が遅いらしい．
参考[【python】numpyの型の違いによる計算速度差を見てみる](https://www.haya-programming.com/entry/2017/02/13/183952)
sveltekitの.json.tsファイルでinterfaceで定義されたオブジェクトを返す

sveltekitでは，routeディレクトリ内の.json.tsファイルでサーバーでの処理を記述でき，そこからjsonレスポンスを取得することができます．getメソッドの定義ではjsonに変換できるオブジェクトならなんでもbodyとして返すことができます．
今回は，その返り値にinterfaceを定義したオブジェクトを利用するときに少しハマったのでメモしておきます．  
以下のように`[slug].json.ts`でマークダウンファイルを読み込み，ページのメタ情報とhtmlの文字列を返すgetメソッドを定義したいとします．

```typescript:[slug].json.ts
import type { RequestHandler } from '@sveltejs/kit';
import fs from "fs"
import {mdToHtml} from '$lib/convert_markdown';
import type {HtmlWithMeta} from '$lib/convert_markdown';

const ARTICLES_DIR_PATH = "contents/articles";  // 記事のあるディレクトリのパス

export const get: RequestHandler = async ({params}) => {
    const md_str = fs.readFileSync(ARTICLES_DIR_PATH + "/" + params.slug + ".md").toString();
    const html_with_meta: HtmlWithMeta = mdToHtml(md_str);
    return {body: html_with_meta}
}
```
ここで，`mdToHtml`はマークダウンの文字列を`HtmlWithMeta`インターフェースのオブジェクトに変換する関数です．インターフェースは以下のように定義されているとします．

```typescript:convert_markdown.ts
/** メタ情報を含んだhtmlの情報 */
interface HtmlWithMeta {
    content: string,  // htmlの文字列
    meta_property: MetaProperty,  // 記事のメタ情報
    use_katex: boolean,  // 数式を使うかどうか
    use_code: boolean  // コードを使うかどうか
}

/** ページのメタ情報 */
interface MetaProperty {
    title: string,  // ページのタイトル
    page_path: string,  // ページの相対パス
    page_desc: string,  // ページの概要
    og_image_url: string  // OGP 画像のurl・パス
}
```

しかし上のget関数はコンパイルが通りません．これは`HtmlWithMeta`インターフェースが[公式ドキュメントで定義されている型](https://kit.svelte.dev/docs#routing-endpoints)に変換できないためだと思われます．そこで以下のように一度JSONを通すことでコンパイルが通るようになります．

```typescript:[slug].json.ts
return {body: JSON.parse(JSON.stringify(html_with_meta))}
```

スプレッド構文を利用することもできますが`HtmlWithMeta`のようにインターフェースがネストしている場合は，以下のようにネストしている部分を後からスプレッド構文で置き換える必要があります．

```typescript:[slug].json.ts
return {
    body:{
        ...html_with_meta,
        meta_property:{...html_with_meta.meta_property},
    }
}
```

クライアント側の`[slug].svelte`では通常と同じように利用できます．

```vue:[slug].svelte
<script context="module" lang="ts">
    import type { Load } from '@sveltejs/kit'
    import type {HtmlWithMeta} from "$lib/convert_markdown";

    const ARTICLE_URL = "/articles"
    export const load: Load = async({page, fetch}) => {
        const html_with_meta_res = await fetch(ARTICLE_URL + "/" + page.params.slug + ".json");
        if (html_with_meta_res.ok) {
            let html_with_meta: HtmlWithMeta = await html_with_meta_res.json();
            return {props: {html_with_meta}}
        }
    };
</script>

<script lang="ts">
    export let html_with_meta: HtmlWithMeta;
</script>
```
【図解解説】JOI2021-2022 一次予選 第2回 問題1 立方体

## 図解解説シリーズ
競技プログラミングを始めたばかりでAtCoderの解説やJOIの解説ではいまいちピンと来ない…という人向けに、図解を用いて解説を行います。

## 問題文
### 情報オリンピック日本委員会に掲載されている問題

https://www.ioi-jp.org/joi/2021/2022-yo1/2022-yo1b-t1.html

### AtCoderに掲載されている問題
入出力など実際に確認して自分の作成したプログラムを採点することができます。

https://atcoder.jp/contests/joi2022yo1b/tasks/joi2022_yo1b_a

## 図解解説
今年度の一次予選のA問題は、以下の２つのスキルを確認する問題になっています。
１．入力・出力を正しく利用できる
２．算術演算子を正しく利用できる

![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2211017/f99bfe3e-87b0-31c4-e18f-6df5d1ed121d.png)
立方体の体積を計算する問題です。計算方法についてはいくつかの方法があります。

掛け算で計算：　X*X*X
〇乗で計算：　X**3　または　pow(X,3)

どの表現方法で解答しても問題ありません。

## 解答例

```a1.py
X = int(input())
print(X*X*X)
```
[採点サイトに提出したプログラム](https://atcoder.jp/contests/joi2022yo1b/submissions/27507346)

```a2.py
X = int(input())
print(X**3)
```
[採点サイトに提出したプログラム](https://atcoder.jp/contests/joi2022yo1b/submissions/26726686)

```a3.py
X = int(input())
print(pow(X,3))
```
[採点サイトに提出したプログラム](https://atcoder.jp/contests/joi2022yo1b/submissions/27507371)

## イラスト
スライド内で使用しているイラストはすべて「[いらすとや](https://www.irasutoya.com/)」の素材を利用しています。
GitHub Actions で Error: Gradle Wrapper Validation Failed!

[GradleでのJavaのビルドとテスト](https://docs.github.com/ja/actions/automating-builds-and-tests/building-and-testing-java-with-gradle) を元にGitHub Actionsを設定をしたら、以下のようなエラーが出たので解消メモ。

```
Run gradle/wrapper-validation-action@v1
  with:
    min-wrapper-count: 1
    allow-snapshots: false
  env:
    JAVA_HOME: /opt/hostedtoolcache/Java_Adopt_jdk/11.0.11-9/x64
Error: Gradle Wrapper Validation Failed!
  See https://github.com/gradle/wrapper-validation-action#reporting-failures
✗ Other validation errors:
  Expected to find at least 1 Gradle Wrapper JARs but got only 0
```

実際に引っかかってるコードは以下。

https://github.com/gradle/wrapper-validation-action/blob/12b3fff2c3f403a0378d0412d0d7dc82747886b6/src/validate.ts

https://github.com/gradle/wrapper-validation-action/blob/12b3fff2c3f403a0378d0412d0d7dc82747886b6/src/find.ts

gradle-wrapper.jarをバージョン管理してなかったので、.gitignoreを修正して解消。

```
gradle/wrapper/gradle-wrapper.jar
```
ESP32で複数Wi-Fiアクセスポイント自動切替えする方法

# はじめに
初めまして、のすけと申します。
研究室の配属が決まり、ESP32-WROOM-32を実験で使用する事になりました。
<img width="400" alt="ESP32" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766945/1b987a6a-73fe-379b-3ef5-f2bd2665de08.jpeg">
現在、私は多くのESP32に囲まれて興奮しております。

ESP32を大学や自宅、実家など移動して使用する事がよくありますが、
移動する度にシリアル通信を行い、SSIDとPASSWORDを設定するのは大変です。

<img width="400" alt="ESP32" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766945/e5323621-27ef-b1c4-a1ff-721a33c8dbc0.png">

そこで、今回は複数の接続情報から自動でWiFi圏内のネットワークに接続するプログラムを作成したので紹介します。

この記事では以下の環境で動作確認をしております。
MicroPython：v1.14
ハードウェア：ESP32-DevKitC

# 単一の接続先情報から接続するサンプルプログラム
[MicroPython reference (Networking)](https://micropython-docs-ja.readthedocs.io/ja/latest/esp8266/tutorial/network_basics.html)を閲覧すると、  以下のようなプログラムが記載されています。

```python:boot.py
SSID = ""
PASSWORD = ""

def do_connect():
    import network
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print('connecting to network...')
        sta_if.active(True)
        sta_if.connect(SSID, PASSWORD)
        while not sta_if.isconnected():
            pass
    print('network config:', sta_if.ifconfig())

if __name__ == "__main__":
    do_connect()
```
このプログラムを元に複数の接続情報から自動的に接続するプログラムに変更していきたいと思います。

# 複数の接続先情報から接続するサンプルプログラム
以下のプログラムは複数の接続先情報から自動的に接続します。

```python:boot.py
WIFI_CONFIG = [("SSID1","PASS1")
            ,("SSID2","PASS2")
            ,("SSID3","PASS3")]

def do_connect(wifi_config):
    import network
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print('connecting to network...')
        sta_if.active(True)

        scandata = sta_if.scan() 

        for scan in scandata:
            for config in wifi_config:
                if(scan[0].decode() == config[0]):
                    sta_if.connect(config[0], config[1])

        while not sta_if.isconnected():
            pass
    print('connected: ' , sta_if.config('essid'))
    print('network config:' , sta_if.ifconfig())

if __name__ == "__main__":
    do_connect(WIFI_CONFIG)
```

配列**WIFI_CONFIG**に格納した、SSIDとPASSWORDのタプルを使用して接続を行います。

[MicroPython reference (network configuration)](https://micropython-docs-ja.readthedocs.io/ja/latest/esp8266/tutorial/network_basics.html)を閲覧すると、 周囲のWIFIをスキャンする事ができる事が記載されています。
そこで、`scandata = sta_if.scan()`の部分でESP32周辺のWiFiをスキャンし配列とスキャン内容に同じSSIDがあった場合のみ接続試行を行うというものになります。

# 終わりに
これで、場所を変更してもESP32-WROOM-32が複数の接続情報から自動で接続するようになりました。　　
皆さんも良いESP32ライフをお送りください！
最後まで閲覧ありがとうございました。

参考になりましたら、LGTMを押していただけるととてもうれしいです(^^)/。
vue serve しようと思ったら digital envelope routines::unsupported が出た

#はじめに
エラーメッセージ

```
Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:67:19)
    at Object.createHash (node:crypto:130:10)
    at module.exports (/Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/webpack/lib/util/createHash.js:135:53)
    at NormalModule._initBuildHash (/Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/webpack/lib/NormalModule.js:417:16)
    at handleParseError (/Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/webpack/lib/NormalModule.js:471:10)
    at /Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/webpack/lib/NormalModule.js:503:5
    at /Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/webpack/lib/NormalModule.js:358:12
    at /Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/loader-runner/lib/LoaderRunner.js:373:3
    at iterateNormalLoaders (/Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/loader-runner/lib/LoaderRunner.js:214:10)
    at Array.<anonymous> (/Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/loader-runner/lib/LoaderRunner.js:205:4)
    at Storage.finished (/Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:55:16)
    at /Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:91:9
    at /Users/~~~~~~~/.nvm/versions/node/v17.1.0/lib/node_modules/@vue/cli-service-global/node_modules/graceful-fs/graceful-fs.js:123:16
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) {
  opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}

Node.js v17.1.0

```

#調査
Node を v17.0.1 にアップデートし、cliでプロジェクトを作って、vue serveをしたら出てきてしまうらしい。
https://github.com/vuejs/vue-cli/issues/6770
https://github.com/webpack/webpack/issues/14532

OpenSSLのバージョンが3.0になったことに起因している問題みたいですね。
https://medium.com/the-node-js-collection/node-js-17-is-here-8dba1e14e382


# 対策

>If you hit an ERR_OSSL_EVP_UNSUPPORTED error in your application with Node.js 17, it’s likely that your application or a module you’re using is attempting to use an algorithm or key size which is no longer allowed by default with OpenSSL 3.0. A new command-line option, --openssl-legacy-provider, has been added to revert to the legacy provider as a temporary workaround for these tightened restrictions.

https://medium.com/the-node-js-collection/node-js-17-is-here-8dba1e14e382

OpenSSL3.0が使われる前に用いられていたもの（プロバイダー？）に戻すオプションがあるので、一時的にはこれを使うのがいい。

```
export NODE_OPTIONS=--openssl-legacy-provider 
```

いけたぁ