OmniAICreator/Qiita-1.07M huggingface dataset:
【Java Silver】(1Z0-815-JPN) 合格体験記

# はじめに
Java Silverに合格したので、合格までの過程を記載します。

# スペック
・Java Silver合格の約2か月前にJava Bronzeを取得
　→[Java Bronze合格時のメモ-Qiita](https://qiita.com/tt8811/items/141858ab7acfe88baa8d)
・Java開発経験なし

# 使用参考書
・徹底攻略Java SE 11 Silver問題集[1Z0-815]対応(いわゆる黒本)
　→今回は紫本は使用せず、黒本で理解できなことはググった
　　※Javaの知識がある程度あれば黒本のみで合格可能だと感じた

# 勉強時間
・勉強期間は約1か月ほどで、集中して勉強した期間は約2週間ぐらい
　→勉強を始めた最初の2週間はゆっくりと勉強を進めたことで、残りの2週間はスピードを上げて勉強を進めた

・平日は1～2時間ほど、休日も平日とほとんど差はなく1～4時間ほど
　→ぶっ通しで勉強するのでなく隙間時間を活用し合算して上記の時間になる

# 勉強方法
黒本を3周し黒本で理解できない箇所は都度検索
黒本の模擬問題は黒本を2周目後に2周した

### 黒本のカテゴリ
　第1章　簡単なJavaプログラムの作成
　第2章　Javaの基本データ型と文字列操作
　第3章　演算子と判定構造
　第4章　制御構造
　第5章　配列の操作
　第6章　インスタンスとメソッド
　第7章　クラスの継承、インターフェース、抽象クラス
　第8章　関数型インターフェース、ラムダ式
　第9章　API
　第10章　例外処理　
　第11章　モジュールシステム
　第12・13章　模擬問題(合計160問)

### 黒本の利用
2周目までは1~11章までを繰り返し、3周目から12・13章の模擬問題も実施した

◆ **黒本1周目**
　・問題の理解を軸に勉強
　　→クラスの継承、インターフェース、抽象クラス、関数型インターフェース、ラムダ式、API、例外処理、モジュールシステムを重点的に勉強
　・Java Bronzeと被る範囲は7・8割の正答率だったが、関数型インターフェース・ラムダ式・API・例外処理・モジュールシステムの範囲は4~6割程度の正答率だった
　・問題の理解が目的だったため分からない問題は回答せず解説を先に読んだ
　・1日1章を理解していく感じで約2週間で終了(このスピード感だと遅かったことを後に反省、、)

◆**黒本2周目**
　・1周目で不正解だった問題の理解の確認を軸に勉強
　　→1周目で苦手だった範囲は2周目で6・７割正答することができた
　・問題を自分で説明できるように進めた
　・1日に使える時間の中で進めるだけ勉強し約1週間で終了

◆**黒本3周目**
　・理解の再確認と記憶の定着を軸に勉強
　　→初めから7・8割取れていた範囲は9・10割正答でき、苦手だった範囲も8・9割正答することができた
　・ほとんどの章の理解はできていたが関数型インターフェースとラムダ式の範囲の理解が完璧ではなかったが、受験が迫っていたのである程度の理解で妥協した
　・ここから12・13章の模擬問題に取り組んだ(受験まで約1週間前)
　　→・模擬問題は合計で2周し、1周目は5・6割しか取れなかった(模擬問題で初めて見る内容が出題されて焦った)、取り合えず解説を頭に入れることを重視
　　　・2周目は8割正答できたが、1周目との期間がそこまで空いていなかったのが要因かもしれない

# 試験当日
・移動の時間に[【Java Silver】Java Silver SE11 試験対策メモ-Qiita](https://qiita.com/mizu4my/items/579e2c69fde35d41a146)を参考に見直した
・試験会場にギリギリ到着したので間に合うか不安になった(余裕をもって行こう)
・初めの数問が黒本には出題されてない問題で勉強した範囲を間違ったのかと思い少し思考停止
　→後半に行くほど黒本と似たよう名問題だったため安心
・時間は180分だが100分ぐらいを問題を解く時間にして約60分を見直しに割いた
　→問題内容にしては時間が長いため落ち着いて解くことができる

# 反省
・黒本1周目をゆっくり進めすぎたため2・3周目以降を焦って勉強することになってしまった
・実際にコードを書いて勉強していないため知識としか頭に入っていなのが勿体ないと感じた
　→資格勉強としては正解かもしれないがコーディン技術としてはスキルアップにはならなかった

# 最後に
時間配分が苦手なので今後の課題として取り組んでいきたいと思います
不明なことなどなにか力になれることがあればコメントください:writing_hand:

次はGoldに挑戦したいと思います
Windows で RaspberryPi 向け Qt6 クロス開発 (その3：補足編)

Qt6 のクロス開発環境ができたところで、補足編です。

# クロス開発環境構築の手順(再掲)

1. RaspberryPi 側の準備(→ [【準備編】](https://qiita.com/tkhshmsy/items/71984bc41e47eb7ed7af))
   1. OS イメージ作成と起動
   2. Qt の開発に必要なパッケージの導入
   3. 環境設定
2. Windows 側の準備
   1. Qt 開発環境の導入
   2. クロスコンパイラを導入
   3. sysroot のコピー
   4. CMake と Ninja-build を実行できるようにする
   5. pkg-config の導入と設定
   6. CMake 用の設定ファイル作成
3. Qt のビルド (→ [【ビルド＆実行編】](https://qiita.com/tkhshmsy/items/604ccf95be93ecc674c2))
   1. ソースコード取得
   2. configure
   3. ビルドとインストール
   4. RPi へのコピー
4. QtCreator の設定
   1. リモートデバイスの設定
   2. Qt キットの設定
   3. サンプルの動作確認
5. 補足 (→ この記事はここから)
   1. クロス開発環境を別の WinPC へ持ち込みたい
   2. RPi側実行環境の OS イメージを小さくしたい
   3. X Window アプリを作れるようにしたい
   4. 32bit のクロス環境を作りたい
   5. まだできていないこと

# 補足

## クロス開発環境を別の WinPC へ持ち込みたい

Qt6 のビルド結果(＝`C:\Qt\qt6-rpi\`の中身)を持ち込めます。

1. 準備編
   1. RPi の設定等は適宜
   2. Windows 側の準備 を同じように行う
      1. sysroot の内容は同じものをコピーで OK
2. ビルド＆実行編
   1.  `C:\Qt\qt6-rpi` フォルダをコピーで OK
       1.  Qt6 のソースダウンロード、configure、ビルドは不要
   2. QtCreator の設定は同じように行う

## RPi側実行環境の OS イメージを小さくしたい

準備編で大量の -dev パッケージを apt install していますが、開発用パッケージなので実行環境には不要です。

1. PRiOS Lite のイメージを作成
2. 起動して以下のパッケージを追加
    ```bash
    $ sudo apt install libgles2-mesa libdrm2 libgbm1 libinput10 libpcre2-16-0 libegl1-mesa libxkbcommon0
    ```
3. 準備編→RaspberryPi側の準備→環境設定をする
4. `/opt/qt/` に `C:\Qt\qt6-rpi` の内容をコピー

以上で、概ね動きます。  
QtCreator からのデプロイには公開鍵含むリモートデバイスの設定が必要なのでそこだけ気をつけましょう。

## X Window アプリを作れるようにしたい

Raspberry Pi 関連の記事を検索すると X Window 上で動くアプリを作る需要もそこそこありそうです。  
その場合、以下のように手順を変更します。

1. 準備編
   1. RaspberryPi側の準備
      1. sysroot を作る RPi OS を Lite ではなく Desktop で行う
         1. apt install で導入するパッケージは同じ[^1]
      2. 環境設定で追加する環境変数を変更
          ```bash
          $ echo "export LD_LIBRARY_PATH=/opt/qt/lib" >> ${HOME}/.profile
          $ echo "export QT_QPA_PLATFORM=xcb" >> ${HOME}/.profile
          $ echo "export DISPLAY=:0" >> ${HOME}/.profile
          ```
      3. pkg-config が必須なので導入
2. ビルド＆実行編
   1. Qt のビルド
      1. configure の実行を以下のように変更
      ```bash
      C:\Qt\qt6build\build> ..\qt5\configure -release -no-pch -opengl es2 -qpa xcb \ 
      -nomake examples -nomake tests -qt-host-path C:/Qt/6.5.1/mingw_64 \ 
      -extprefix C:/Qt/qt6-rpi -prefix /opt/qt -device linux-rasp-pi3-g++ \ 
      -device-option CROSS_COMPILE=aarch64-linux-gnu- -- \ 
      -DCMAKE_TOOLCHAIN_FILE=C:/Qt/qt6build/toolchain.cmake \ 
      -DQT_FEATURE_xcb=ON -DQT_FEATURE_xcb_xlib=ON -DQT_FEATURE_xlib=ON
      ```

この修正手順で作成した Qt6 には X 対応が追加になります。  
追加なので EGLFS 向けの開発も同じように可能です。

[^1]: 実はLiteで作ったsysrootにXWindow向け開発に必要なパッケージは全て含まれています。すでにLiteで作成済みでしたらそのまま使い回せます。

## 32bit のクロス環境を作りたい
手順はおそらく違いません。

* クロスコンパイラ・ツールチェインを 32bit のものに変更する
* sysroot を 32bit の RPiOS で作る
  * 64bitのものを流用しない。全く別物です
* MinGW32 の環境でビルド等を行う

ぐらいでできると思います。

:::note warn  
未確認、32bit使わないので・・・
:::

## まだできていないこと

最後にここまでの手順でできていないこと、改善したいことについて

* qmake からビルドできない
  * qmlproject の実行も対応したいです
* 作成したライブラリに rpath が効いていない
  * LD_LIBRARY_PATH の設定をなしにしたいです
* Windows 側で symlink をなんとかしたい

改善ができたら随時記事を修正していきたいです。

(以上)
VSCodeでLive Serverを使ってローカルサーバーを気軽に立てる

今回はVSCode(Visual Studio Code)でローカルサーバを立てていきたいと思います。

1.VSCodeを起動し、四角形が四つ集まっているアイコンをクリックしてください。
![スクリーンショット 2023-07-09 164003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508362/f5a954e5-74e2-0eaf-a8d8-64903b2aaaea.png)

2. クリックすると上の方に検索できるところが出てくると思うので、そこに「Live Server」と入力してください。
![スクリーンショット 2023-07-09 164032.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508362/7cd1bf16-2125-6b6e-c2b0-ae45dac6e40a.png)

3.そこで一番最初に出てきた「Live Server」をクリックして、インストールと書いている青いボタンを押します。![スクリーンショット 2023-07-09 164049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508362/8b92d481-dc68-8395-6d94-6c56b3c878e5.png)

4.しばらく待つとインストール出来るので、インストールまで待ちます。そして、以下のように右下に「Go Live」と出たらOKです。
![スクリーンショット 2023-07-09 164113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508362/f2d2ed80-3d93-2ec8-da5c-cb402132f64b.png)

5.インストール出来たら、サーバを立てて実行したいコードをVSCodeのアクティブにして、「Go Live」をクリックするとそのコードをサーバに入れたように動作します。![スクリーンショット 2023-07-09 164205.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508362/1b758c46-d8bd-8b42-583b-4e3d8423119f.png)

以上でVSCodeで簡単にローカルサーバを立てる方法を終わります。
ansibleでchrony設定

ansibleでchronyの設定を実行してみました。

今回はrole化してみました。

```
/root/ansible/roles
/root/ansible/roles/chrony
/root/ansible/roles/chrony/tasks/main.yml
/root/ansible/roles/chrony/handlers/main.yml
/root/ansible/roles/chrony/files/chrony.conf

```
やること
chrony.confを配布する。
chrony.confをユーザとグループを変更する。
chrony.confを権限を変更する。
その後、リスタートする（handlers側で）
※notifyを設定しているので、handlersが呼び出されます。

/root/ansible/roles/chrony/tasks/main.yml


```
---
- hosts: all
  tasks:
  - name: deploy chrony.conf
    template:
      src: "/root/ansible/roles/chrony/files/chrony.conf"
      dest: "/etc/chrony.conf"
      owner: root
      group: root
      mode: 0644
    notify: restart chronyd.service

```

handlersが呼び出されます。
/root/ansible/roles/chrony/handlers/main.yml

```
---
- hosts: all
  tasks:
  - name: restart chronyd.service
    systemd:
     name: chronyd.service
     state: restarted
     enabled: yes
     daemon_reload: yes

```

最初に配布したファイルは以下に格納しています。
/root/ansible/roles/chrony/files/chrony.conf



handlerに関しては、以下の記事が詳しいから
こっちを参考にします。わかりやすいです。

https://blog.katsubemakito.net/ansible/ansible-1st-3
ページネーションについて

## はじめに
今回はページネーションについてアウトプットの一環として
書いていこうと思います。

## ページネーションとは？
一つの長い文章を複数のページに分割し表示することです。
ページネートすることで以下のメリットが得られます。

* 読みやすくなる
* ページの読み込み時間を短縮できる

## kaminariのインストール
gemの`kaminari`を使用してページネーションを実装していきます。
Gemfileの最終行に、以下コードを追加して保存して下さい。

```ruby:Gemfile
gem 'kaminari'
```

Gemfileに追記をしたら以下コマンドを実行して、kaminariをインストールして下さい。
```ruby:ターミナル
$ bundle install
```

次に以下のコマンドを実行してkaminariの設定ファイルを作成します。
```ruby:ターミナル
$ rails g kaminari:config
```

最後に、kaminariがページャで利用するテンプレートを作成します。 
以下のコマンドを実行して下さい。
```ruby:ターミナル
$ rails g kaminari:views default
```
## Controller
今回はapp/controllersフォルダ内のblogs_controller.rbファイルを変更します。
`pageメソッド`を使用して1ページ分の決められた数のデータだけを
新しい順に取得するように変更していきます。

:::note info
pageメソッドはkaminariをインストールすることで使用できるメソッドです。
:::

今回は以下のように記述しました。
```ruby:app/controllers/blogs_controller.rb
@blogs = Blog.page(params[:page])
```

## View
Viewでは以下のヘルパーを追加します。
```ruby:app/views/blogs/index.html.erb
<%= paginate post_images %>
```

## Kaminari Config
最後に、ページあたりに表示させる件数の設定をconfig/initializersフォルダのkaminari_config.rbファイルに記述します。
1ページの表示件数は、デフォルトは25件ですが、今回は2件に設定します。
```ruby:config/initializers/kaminari_config.rb
Kaminari.configure do |config|
  :
  :
  # 1ページあたりのアイテムの表示数が2件
  config.default_per_page = 2
end
```
サーバーを起動してページャが問題なく機能していれば完成です！
PlatformIOでXIAO RP2040を動かす

マイコンボードも値上がりが激しい昨今ですが、そんな中でも価格も手ごろで、比較的容易に入手出来る
[Seeeduino XIAO RP2040](https://cdn-ak.f.st-hatena.com/images/fotolife/m/mnakai/20211007/20211007091356.png)をPlatformIOで動かしてみます。
![img](https://cdn-ak.f.st-hatena.com/images/fotolife/m/mnakai/20211007/20211007091356.png)

XIAO RP2040　は[こちら](https://community.platformio.org/t/support-for-seeed-xiao-rp2040/28989)にあるように、platformio.iniに
```
[env:seeed_xiao_rp2040]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = seeed_xiao_rp2040
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
framework = arduino
```
を記述することでビルド可能です。
が、Windowsだとパッケージのインストール中に```Filename too long```エラーがでて
インストールが失敗し、その結果ビルドに失敗することがあります。
その場合は、[こちら](https://myscreate.com/filename-too-long/)にあるように、
```
git config --system core.longpaths true
```
を実行し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/624805b8-55a7-62cd-f939-5d91cee1ceeb.png)
Platform Core CLIから
```
pio pkg uninstall -g -p https://github.com/maxgerhardt/platform-raspberrypi.git
pio pkg install -g -p https://github.com/maxgerhardt/platform-raspberrypi.git  
```
でインストールしなおすことでビルドが通るようになります。
【PHP】abstractについて

### abstract (抽象クラス)とは

abstractで定義された抽象クラスには以下のような性質があります
- 対象の具象クラス(※通常のクラス)にプロパティもしくはメソッドを強制的に定義させる
- 抽象クラス単体ではインスタンス化することはできない
- abstractとして定義したメソッドは具体的な処理を書くことはできない
- 抽象クラス内で具象クラス同様、具体的なメソッドを定義し、継承させることもできる


PHP公式リファレンスのコード例を引用したので、以下を見て下さい。
[抽象クラスの例](https://www.php.net/manual/ja/language.oop5.abstract.php)
```php
abstract class AbstractClass // 抽象クラス
{
    // 拡張クラスに以下のメソッドの定義を強制する
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // 通常のメソッド
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass extends AbstractClass // 具象クラス
{
    protected function getValue() { // AbstractClassで定義したabstractメソッド
        return "ConcreteClass";
    }

    public function prefixValue($prefix) { // AbstractClassで定義したabstractメソッド
        return "{$prefix}ConcreteClass";
    }
}

$class = new ConcreteClass;
$class->printOut(); // => 'ConcreteClass"'
echo $class->prefixValue('FOO_') ."\n"; // => 'FOO_ConcreteClass'
```

上記の例では、
具象クラスであるConcreteClassクラスに抽象クラスのAbstractClassクラスを継承しています。
ConcreteClassクラスでは、AbstractClassクラスで定義したメソッド3つの内、
抽象メソッドであるgetValueメソッドとprefixValueメソッドを明示的に定義しています。
また、printOutメソッドは通常の継承と同様、
具象クラス内で定義しなくても呼び出すことができています。

もし、この2つのメソッドをConcreteClassクラス内で定義しなかった場合、以下のようにエラーが発生します。

```
class ConcreteClass extends AbstractClass
{
}
// => Fatal error: Class ConcreteClass contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (AbstractClass::getValue, AbstractClass::prefixValue) in /tmp/preview on line 15
```

ただの継承であれば、明示的に定義しなくても呼び出すことができますが、
抽象クラスを継承した具象クラス内で、
abstractメソッドを定義しないとエラーが発生するため、
具象クラスに継承させることで強制的にプロパティやメソッドを明示的に定義させる必要があります。


## abstractの意義・目的
なぜ、わざわざ抽象クラスを作って具象クラスに継承させることでプロパティとメソッドを強制させるかというと、チームでの開発において有用だからです。

抽象クラスを継承した具象クラス内では必ず、抽象プロパティ・メソッドを定義しないといけないルールがあります。
そのため、共通の機能を持つ派生クラスであるということを保証、機能の漏れが減ることに繋がります。
さらに継承したクラス群はいずれも近しい機能を持ったクラスであるということが分かりやすくなるという意義もあります。

プロジェクトが大きくなり、開発する人数が増えれば増えるほど、
ファイル名やクラス名などからどういう機能を持ったものか推測することの重要性が増します。
抽象クラスにはそれを補助する役割があるわけです。


### 参考

https://www.php.net/manual/ja/language.oop5.abstract.php

https://qiita.com/aiko_han/items/e8ddce85188970fd77da
ローカルでstable diffusion web uiを起動するまでの手順メモ

かなりあちこちで使われているソフトなので、簡単に入るかと思ったが思った以上にあれこれやらないと動かなかったのでメモを残す

# 1. 本体やモデルのダウンロード
基本的には下記のページの手順に従い、webui本体やモデルをダウンロードする。下記のサイトには大変お世話になった。
本体: https://kurokumasoft.com/2023/02/06/stable-diffusion-web-ui/
モデル: https://kurokumasoft.com/2023/01/19/stable-diffusion-counterfeit/

webui本体のダウンロードは以下のURLから行った。
https://github.com/AUTOMATIC1111/stable-diffusion-webui/releases/tag/v1.0.0-pre
本体は今日(2023/07/09時点)でv1.4.0まで出てるが、zipが提供されていない。
また学習モデルのダウンロードは以下のURLから行った。
https://huggingface.co/gsdf/Counterfeit-V3.0/blob/main/Counterfeit-V3.0_fp16.safetensors
https://huggingface.co/gsdf/Counterfeit-V2.5/blob/main/Counterfeit-V2.5.vae.pt
(正直各ファイルが何なのか全く分かってない。とりあえずui動くまでのメモ)

ダウンロードしたファイルはそれぞれ以下のディレクトリに保存した。
モデル: webui\models\Stable-diffusion
VAE: webui\models\VAE

# 2. エラーの対処
参考にしたサイトに従い、run.batファイルを起動した。pythonパッケージをインストールする処理が進んだ後、以下のようなエラーが表示された。
```
cannot import name '_compare_version' from 'torchmetrics.utilities.imports'
```
どうも同梱されているpythonのバージョンが3.10.0以降になったことか、torchmetricsの新しいバージョンが公開されたために不整合を起こしているらしい。執筆時点でtorchmetricsはv1.0.0がリリースされているが、これをv0.11.4に落とすよう説明している記事が見かけられた。
https://qiita.com/Pkun/questions/fdfd081e745f4588d77b
このため、pipでtorchmetricsのバージョンをダウングレードする。このzipのwebuiはpythonのバイナリごと配布されている。python本体及びpipは以下のディレクトリに存在する。
* python: webui\system\python
* pip: webui\system\python\Scripts

pipの方を起動して以下のコマンドを実行する。
```
pip install torchmetrics==0.11.4
```

コマンド実行後、再度run.batを実行したところ、また別のエラーが表示された。
```
RuntimeError: Cannot add middleware after an application has started
```
エラーメッセージで検索したところ、以下のサイトがみつかった。
https://wikiwiki.jp/sd_toshiaki/%E3%82%A8%E3%83%A9%E3%83%BC%E8%A7%A3%E6%B1%BA%E3%83%A1%E3%83%A2#f6334aac
上記のサイトに従い、update.batを実行した。python及びライブラリの更新らしき処理が走ったので、再度run.batを実行したところ、webuiが立ちあがった。
rex0220 計算式プラグイン 作業者・上長の取得

計算式プラグインで、作業者とその上長の情報を取得してみます。

# 概要

プロセス管理の作業者情報をステータス変化のタイミングと作業者を変更したタイミングで、ユーザー選択項目に取得します。

※計算式プラグイン Ver.65 以降でサポート
※上長の情報を取得する場合、ユーザー数等が多いと画面表示の処理時間が長くなります。

![2023-07-09_15h24_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/8cb0bf40-f9c3-cad4-48ba-bdf3e74b247d.png)

# 操作例

ステータス変更によって作業者が変わった時と作業者を変更した時に、作業者コピーと上長に反映されます。

![2023-07-09_15h30_53.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/08698f18-ecfe-376e-3273-4158667502e3.gif)

# 画面フォーマット

ユーザー選択項目を追加

![2023-07-09_15h36_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/55f1ce54-a406-3a08-a959-c7c789367e62.png)

# プロセス管理

作業Aに移行時に、作業者に営業部のメンバーが割り当てられる

![2023-07-09_15h37_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/440bb0ce-ab22-89a5-70b8-5953272d543b.png)

# プロフィール項目のカスタマイズ項目設定

カスタマイズ項目に、上司を設定します。

![2023-07-09_15h41_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2d1afcfe-ca2d-2c56-bfd5-8f0858d6bc0f.png)


# 計算式プラグインの設定

オプションの「ユーザー情報」をチェックします。
UINFO 関数で、カスタマイズ項目情報を取得するには、"#boss" のように"#" を先頭に付加します。

![2023-07-09_15h22_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c9eb2361-afb2-484b-c985-b1f7597b6b7b.png)

```.js
// 作業者コピー USER_SELECT
SET_CODE(
  SEL_CODE(作業者,"array")
)

// 作業者上司 USER_SELECT
LET(a,SEL_CODE(作業者,"array"), // 作業者コード
  b,UINFO(UINFO(a,"#boss"),"code"), // 上司コード
  SET_CODE(b)
)
```
【Rust初心者】Rustの日本語ドキュメントを自分なりにまとめてみた(その3)

この記事は、2023年7月に作成したものです。

# はじめに
以前から興味があったRustを、日本語のドキュメントをもとに、学習を始めました!
自分の考えをまとめるために、記事を書いていこうと思います。

今回は、[日本語ドキュメント3.1](https://doc.rust-jp.rs/book-ja/ch03-01-variables-and-mutability.html)についてまとめていきます！

# この記事でできること
Rustでの変数宣言や変数の仕組みを学習できます。

# 環境
- macOS Monterey == 12.5
- Docker == 23.0.5
- Rust == 1.70.0
- Cargo == 1.70.0

# 変数の宣言方法
Rustの変数宣言では`let`を使用します。
~~~Rust
let x = 5;
~~~
`x`という変数を宣言して5を代入できました。

# Rustの変数の特徴
Rustでは、変数の型を注釈しなくても、型推論によって適切な型を割り振ってくれます。
ちょうど、PythonやSwiftなどと同じですね!
(※`型`については、次回の記事で詳しく解説しようと思います。)

また、Rustの変数は`不変変数`といい、何も指定しない場合値を変更することができない変数が定義されます。
~~~Rust
let x = 5;
...
x = 6    // error[cannot assign twice to immutable variable]
~~~
**これがややこしい!!**

「変数なのに変更できないなんて...」「定数と変わらないじゃないか!」などと思うでしょう。
私もそう思いました。
この仕組みの恩恵を受けるためには、もっとRustの経験を積まないといけませんね...

一方で、変数の値を変更できないことによって、不便なシチュエーションも多くあります。
そこで、変数宣言時に`mut`をつけることにより、他の言語と同じ振る舞いをする可変変数を宣言することができます。
~~~Rust
let mut y = 5;
...
y = 6;    // エラーは出ない
~~~

# シャドーイング
Rustの変数には`シャドーイング`というものがあります。
シャドーイングとは、以前に定義した変数を再定義することです。この際、新しい変数は前の変数を`覆い隠し`ます

~~~Rust
let x = 5;
println!(x)    // 5

let x = x + 2
println(x)    // 7
~~~

また、別のスコープでシャドーイングされた際、そのスコープを抜けると元の値に戻ります。
~~~Rust
let x = 5;
println!(x)    // 5
{
    let x = "シャドーイングされています";
    println!(x)    // シャドーイングされています
}

println!(x)    // 5
~~~
シャドーイングでは、上のプログラムのように変数の型が変わることが許容されています。
そのため、型ごとに変数を定義する必要がなく、変数名を使い回して開発することができます。
これはシャドーイングのメリットと言えるでしょう。

私はRustでの開発経験が浅いため、**なんとなく便利そう!**　というイメージしか今のところないです。

# 変数と定数
`Rustの変数はデフォルトでは不変変数である。`これを聞いて「定数と何が違う?」と思った方も多いでしょう。
私もそのうちの1人です。
ですが、もちろんRustでは変数と定数の区別がしっかりとあります。
>コメントより
「変数と定数の本質的な違いはいつ値が決定されるか」

ということでした!
補足ありがとうござます！

定数は**コンパイル時**つまり、`cargo build`を実行し、実行可能ファイルが生成される時点で決定されます。
それに対し変数は**ランタイム時**つまり、実行可能ファイルを実行した時に決定されます。

定数は実行される前から、既に確定している存在だそうです！
では、定数では制限されている書き方を見てみましょう。

### 型注釈の省略ができない
定数を定義する際は必ず型注釈を行う必要があります。
~~~Rust
// 定数は「const」を使用します
const DAY_HOUR: u16 = 24    // 整数型の定数を定義
const DAY_MINUTE = 14400    // 型注釈がないためエラー
~~~

### 同スコープ内でのシャドーイングができない
変数は、同スコープ内でもシャドーイングできるのに対し、定数は同スコープ内ではシャドーイングができません。
同スコープ内でシャドーイングしてしまうと、定数の不変が保証されなくなるためです。
しかし、別のスコープであればシャドーイングが可能です。
~~~Rust
const MAX_NUMBER: u32 = 100_000;
println!(MAX_NUMBER);    // 100000

const MAX_NUMBER: u32 = 200_000;    // error:定数MAX_NUMBRERは定義されているためエラー
{
    const MAX_NUMBER: u32 = 200_000;
    println!(MAX_NUMBER);    // 2000000 スコープが違うためエラーはでない
}

println!(MAX_NUMBER)    // 100000 シャドーイングから解放されたので元に戻る
~~~

# まとめ
だいぶ複雑になってきました...
変数で大事なことは以下の通りです。
- 定義する時には`let`を使用する
- 変数はデフォルトでは`不変変数`となる
- 可変変数を定義するためには`mut`を使用する
- `シャドーイング`によって変数を覆い隠すことができる
- 定数と変数は別物

自分なりにまとめていて、解釈が甘いところがありそうなので、コメントなどで意見お願いします！

# 参考文献
[The Rust Programming Lamguage 日本語版](https://doc.rust-jp.rs/book-ja/ch03-01-variables-and-mutability.html)
Cookieについて調べてみた

# はじめに
只今、Web関連について学習中です。
CookieについてはWeb関連の知識に密接に関わっているのでCookieについてどういうものかを調べた内容をアウトプットします。
# Cookieとは？
HTTPで状態を記憶するために使われる仕組みがCookieです。
サーバからクライアントのブラウザに対して送付されるデータ(Cookie)を使って、サーバーとブラウザ間でデータを交換することができます。

活用例としては、一度ログインをおこなったサイトに対して、一度そのページを離れてしまった場合でも、再度サイトに戻った時に再度ログイン作業をおこなわずともログイン状態の画面が再度表示される、といった仕組みはCookieによるものです。

実データなどをCookieに入れておくと不正アクセスされた際に情報が漏洩してしまうので
もセッションIDをCookieに含ませてサーバー側でそのセッションIDを元にセッションデータを取り出して状態を維持する方法もあります。

ちなみに、状態が維持されることを「ステートフル」、維持されないことを「ステートレス」と言います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641311/7ddbdb8f-3767-0c7f-9192-ba2d2e66cef6.png)

上記を実現するためにはSet-CookieヘッダーとCookieヘッダーを使用します。

## `Set-Cookie` ヘッダーと`Cookie` ヘッダー
HTTP の Set-Cookie レスポンスヘッダーは、サーバーがユーザーエージェントへ Cookie を送信するために使用します。単純な Cookie は次のように設定されます。
```
Set-Cookie: <cookie-name>=<cookie-value>
```
サーバーからクライアントへのcookieの組み合わせを保存するように指示するには以下のようになります。

```
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: SESSIONID=xxxxxx…
```
その後のサーバーへのリクエストは、ブラウザーに以前格納されたすべてのCookieを、Cookieヘッダーを使用してサーバーへ送信します。
```
GET /sample_page.html HTTP/2.0
Host: www.example.com
Cookie: SESSIONID=xxxxxx…
```

## Cookie スコープの定義
DomainまたはPath属性にてCookieの送信先のホストやURLなどを定義できます。

### Domain属性
`Domain` 属性はCookieの送信先ホストを指定することができます。
もし、`Domain` を指定しなかった場合はCookieを設定したホストを `Domain` として指定します。
ですが、サブドメインなどは除外されてしまいます。
例えば、example.org がドメインだとすると developer.example.org などのサブドメインは含まれません。
なので、サブドメイン間でユーザー情報などをやり取りしたい場合には役立ちます。

設定方法
```
Domain=example.org 
```
上記のように設定すると、今度はdeveloper.example.orgを含むことができます。

### Path属性
Path属性は、URLの中にこれは必ず含んで欲しいURLのパスを定義することができます。
要はドメイン名/Path ← `/` の後からのパスを定義できます。
例えば、`Path=/foo` と設定したとします。

以下のリクエストパスでCookieが使用できます。
・/foo　:white_check_mark:
・/foo/bar　:white_check_mark:

ですが、以下のリクエストパスでは使用できません。
・/foobar :x:
## Cookieの持続時間の定義
Cookieには2通りの方法で持続時間を定義できます。

### セッションCookie
セッションCookieは、ブラウザが閉じられると自動的に削除されます。
ブラウザはいつ「現在のセッション」が終わったと見なすかを定義し、ブラウザによっては再起動にセッションの復元を使用することができます。そのため、結果的にセッションCookieが無期限に持続することがあります。

### Expires属性
Expires属性は、Cookieが有効期限を指定するために使用されます。
具体的な日時と時刻を指定し、その日付と時刻を過ぎるとCookieは自動的に削除されます。

```
Set-Cookie: SESSIONID=xxxxxx…; Expires=Wed, 08 Jul 2023 12:00:00 GMT;
```
# おわりに
Cookieについてざっくりとですが記事としてアウトプットしました。
普段何となくな理解だったので設定できる属性やその役割など少し明確になったかと思います。

## 参照資料

https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies

https://ema-hiro.hatenablog.com/entry/2018/01/24/022902

https://qiita.com/hitomik/items/38befaf0d740c4b07363
npm installしたら「No inputs were found in config file」が出た

経緯
---------------------------------------
typescriptの勉強中、新しく「section2」ディレクトリを作って、
「section1」ディレクトリにあった下記のディレクトリ・ファイルを移動させた。
```:section2
/dist
/src
package.json
tsconfig.json
```
移動後、`npm install`を実行したら下記のエラーが出た。
ts.configの設定でなんか失敗したっぽい？
```
npm install

npm WARN deprecated tslint@6.1.3: TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.

> section1@1.0.0 prepublish
> npm run build


> section1@1.0.0 build
> tsc

error TS18003: No inputs were found in config file 'C:typescript/section2/tsconfig.json'. Specified 'include' paths were '["src/**/*"]' and 'exclude' paths were '["node_modules","dist"]'.


Found 1 error.

npm ERR! code 2
npm ERR! path C:typescript/section2
npm ERR! command failed
npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c npm run build

npm ERR! A complete log of this run can be found in:
```

 原因 
---------------------------------------

最初はnode_modulesフォルダが存在しないことで怒られているのかと思ったけど、
installして初めてできるものだから関係ない。

https://insider.10bace.com/2017/11/29/typescript-ts18003-error/ の記事を参考にすると、ディレクトリ内にtsファイルが存在しないとだめってことで怒られたらしい。
srcの中にダミーファイルとしてindex.tsを作り、作成された`node_modules`と`package-lock.json`を消してもう一度installを実行。
```
npm install
npm WARN deprecated tslint@6.1.3: TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.  

> section1@1.0.0 prepublish
> npm run build


> section1@1.0.0 build
> tsc

src/index.ts:1:2 - error TS1127: Invalid character.

1 {\rtf1}
 

Found 1 error in src/index.ts:1

npm ERR! code 2
npm ERR! path C:typescript/section2
npm ERR! command failed
npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c npm run build

npm ERR! A complete log of this run can be found in:

```
なんで！？って思ってよく見たらindex.tsの記述がおかしいぞってちゃんと出ていた…
ファイルの中を空にして再実行したら下記のように成功！
エラーはちゃんと読まなきゃダメだね…

```
npm install
npm WARN deprecated tslint@6.1.3: TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.  

> section1@1.0.0 prepublish
> npm run build


> section1@1.0.0 build
> tsc


added 42 packages, and audited 43 packages in 4s

5 packages are looking for funding
  run `npm fund` for details

2 moderate severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
```

今回の学び
---------------------------------------

:::note info
・npm install失敗したときは、ダミーのtsファイルが入っているか確認する
・ダミーのtsファイルは空っぽにしておくか、正しいtsコードを入れておく
・エラーはちゃんと読む
:::
【Swift】日本語化されたタイムゾーンのリストを表示したい

SwiftのTimeZone構造体には、日本語のタイムゾーン、地域名、都市名、国名が提供されていません。
そこで、[TimezonesJP](https://github.com/sugijotaro/TimezonesJP)というGitHubリポジトリを用意しました。

https://github.com/sugijotaro/TimezonesJP

# TimezonesJPとは？
このリポジトリは、Swiftの`TimeZone.knownTimeZoneIdentifiers`メソッドで取得できる全てのタイムゾーン識別子に対応した、日本語での地域名、都市名、国名を提供することを目的としています。

データは以下のURLからアクセス可能です: 
https://sugijotaro.github.io/TimezonesJP/timezones.json

# TimezonesJPの使い方

まずは、次のような構造体をSwiftで定義します。

```swift
struct TimeZoneSection: Codable {
    let region: String
    let region_ja: String
    let cities: [City]
    
    struct City: Codable {
        let timezone: String
        let city: String
        let country: String
        let city_ja: String
        let country_ja: String
    }
}
```

次に、JSONデータを非同期に読み込むメソッドを定義します。

```swift
func loadTimeZones(completion: @escaping ([TimeZoneSection]?) -> Void) {
    let url = URL(string: "https://sugijotaro.github.io/TimezonesJP/timezones.json")!
    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        if let data = data {
            let decoder = JSONDecoder()
            if let timeZones = try? decoder.decode([TimeZoneSection].self, from: data) {
                DispatchQueue.main.async {
                    completion(timeZones)
                }
            } else {
                completion(nil)
            }
        } else {
            completion(nil)
        }
    }
    task.resume()
}
```

この関数を呼び出してデータを取得します。

```swift
loadTimeZones { timeZoneSections in
    if let timeZoneSections = timeZoneSections {
        // timeZoneSectionsを利用した処理
    } else {
        // エラーハンドリング
    }
}
```

以上で、Swiftのプロジェクトでこのリポジトリの提供するJSONデータを利用できるようになります。

# タイムゾーン情報の追加・修正のリクエスト方法とコントリビュート方法
都市や国の情報を追加または修正してほしい場合や、直接的な貢献をしたい場合は、READMEに記載されている手順に従ってください。

---
iOSでのタイムゾーンの取り扱いがこれで少しでも楽になれば幸いです。私たちのリポジトリに関して質問や提案があれば、いつでも歓迎します。皆さんのフィードバックをお待ちしております！

https://github.com/sugijotaro/TimezonesJP

また、デモアプリも用意したのでこちらも参考にしてみてください。

https://github.com/sugijotaro/TimezonesJPListDemoApp

それと、この[TimezonesJP](https://github.com/sugijotaro/TimezonesJP)を使ったアプリをリリースしています。海外にいる友達の現在時刻が見れるアプリです！

https://apps.apple.com/jp/app/friendtimezone/id6450912308
Almalinux9で起動待機時間をスキップ（RHEL9系）

# 前提

まず、一言前提を記載します。システムは、

#### ファームウェア(BIOS/UEFI) → ブートローダー → カーネル → initプロセス
　　
という流れで起動します。（その間のイベント等はだいぶ端折りました）
システム起動時に、以下のような画面が表示されると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514207/b56bb09c-5da3-a7cd-54b4-9c6419950f47.png)
今回は、この画面をスキップする方法を記載します。

## 設定方法
まず前提として、起動フローのどの段階を変更するかを考えます。
結論としては、「ブートローダー」の設定を変更します。

1\. テキストエディタを使用して、GRUBの設定ファイル /etc/default/grub を編集します。
```bash: bash
$ sudo vi /etc/default/grub
```

2\. "GRUB_TIMEOUT" の値を0に設定します。既に設定されている場合でも、値を0に変更します。
デフォルトの値はコメントアウトしておくとよいでしょう。
```bash: edit file
#GRUB_TIMEOUT=5
GRUB_TIMEOUT=0
```
　　
3\. 変更を保存してエディタを終了します。
```bash: edit file
:wq
```
　　
4\. 変更を反映させるために、以下のコマンドを実行してGRUBの設定を更新します。
```bash: bash
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
```

これで、AlmaLinux 9のブートローダーの待機時間が0に設定されます。
システムを再起動した際には、ブートローダーが自動的にデフォルトエントリを選択し、待機時間が表示されなくなります。

以上。
Symfonyでよく使うコマンドまとめ

Symfonyには多くの便利な機能があります。ここでは、よく使われるコマンドを紹介します。
(自分のメモ用)

※コマンドに`make`と付いているものは `symfony/maker-bundle`のインストールが必要です。
参考: https://symfony.com/doc/current/SymfonyMakerBundle/index.html#sln

## プロジェクト作成

Symfonyプロジェクトを作成するためにはいくつかの方法があります。

### 一般的な方法

```
symfony new my-symfony-app
```

新しいSymfonyアプリケーションのベースを作成します。
基本的なファイルとディレクトリがセットアップされ、必要なライブラリがインストールされます。

### Webアプリケーションのフルセット

```bash
composer create-project symfony/webapp-pack my-symfony-app
```

Webアプリケーションを作成するのに必要な機能を一緒に含んだSymfonyプロジェクトを作成します。
例えば、データベース、セキュリティ、テンプレートエンジン、ルーティングなどの機能が最初から組み込まれています。
Webアプリケーションの開発に必要なさまざまなツールやライブラリが含まれています。

参考: https://packagist.org/packages/symfony/webapp-pack

※ 以前は`website-skeleton`というパッケージもありましたが、現在はこちらを使用してください。

### 必要最低限のアプリケーションプロジェクト

```bash
composer create-project symfony/skeleton my-symfony-app
```

最小限の構成でSymfonyプロジェクトを作成します。
基本的なファイルとディレクトリが含まれており、必要な機能を個別に追加できます。
自分でカスタマイズしたアプリケーションを構築する場合に適しています。

参考: https://packagist.org/packages/symfony/skeleton

## プロジェクト実行

```bash
symfony server:start
```

Symfonyアプリケーションをローカルサーバーで実行します。
アプリケーションの開発やテスト中に使います。

## コントローラーの作成

```bash
php bin/console make:controller
```

新しいコントローラークラスを作成します。

## エンティティの作成/更新

```bash
php bin/console make:entity
```

Doctrineエンティティクラスとリポジトリクラスを作成/更新できます。

## データベースの作成

```bash
php bin/console doctrine:database:create
```

`.env`ファイル内のデータベース接続情報を使用してデータベースを作成します。

## マイグレーションファイルの作成

```bash
php bin/console make:migration
```

## マイグレーションの適用

```bash
php bin/console doctrine:migrations:migrate
```

## ルート名とパスの関連を表示

```bash
symfony console debug:router
```

## エンティティとDBを同期する/差分を確認する

```bash
bin/console doctrine:schema:validate
```

## キャッシュのクリア

```bash
bin/console cache:clear
```
モダンアクティビティを使ってみた(Excel編Part5～VLOOKUP？苦手とか言わんとよ！～)

## はじめに
①本記事は、2023年7月開催の「UiPathブログ 発信チャレンジサマー」の9日目のブログです。
ブログの詳細、参加方法については以下のブログを参照ください。

https://note.com/shumpei_w/n/nd082bdf28853

②このブログ情報は、2023/7時点の情報です。
③UiPathはCommunity Edition、Versionは2023.6.1を使用しています。

## 前回までのおさらい
第1回、第2回目、第3回、第4回は以下をご覧ください。
・モダンアクティビティを使ってみた(Excel編)

https://qiita.com/saosao885/items/3401b0d8708cc5fb3d3c

・モダンアクティビティを使ってみた(Excel編Part2～グラフも作れるのかや？～)

https://qiita.com/saosao885/items/c27b9171317481b37530

・モダンアクティビティを使ってみた(Excel編Part3～グラフを取得？更新？知っちょん？～)

https://qiita.com/saosao885/items/b27d891e44a56418204b

・モダンアクティビティを使ってみた(Excel編Part4～最初と最後のデータ行を検索？なにそれ？～)

https://qiita.com/saosao885/items/6643c1b515091f819c09

4回目は「最初/最後のデータ行を検索」アクティビティについて学びました。
5回目もアクティビティとしては初登場？のものです。

## VLOOKUP関数とは
そもそもExcelが得意な方もそうでない方もいらっしゃると思いますが、VLOOKUP関数はどのように使うのかおさらいしましょう。

VLOOKUP関数は、検索した値から必要なデータを取得する関数です。
<b>VLOOKUP（検索値, 範囲, 列番号, 検索の型*）</b>
*検索の型は、書かなくてもOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/9e8c1f5c-249c-5fd4-c44b-78280f80d3cf.png)
上記の例では(見えていませんが)F1セルに書いた名前から、その人の出身地を当てるようにしています。
例えばF1セルに入力した"あああ"さんの出身地を当てるために、上図の右側に式の詳細を記載しました。
特にわかりにくい列番号ですが、今回の例の場合、指定した範囲の左から<b>何列目</b>の値を出すのかを設定します。
今回はB列の"出身県"を出したいので、"2"と入れています。
(範囲はA列～D列、B列は左から2列目なので)

この式だと"大分県"が出てきますね。
同じように"えええ"さんで検索しても、"長野県"が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/4ae05433-3d0a-64c3-4e1b-2b5b588c5a53.png)
これが、モダンアクティビティだとどうなるのでしょう？

## やってみよう
ではString型変数strNameに"さささ"と入れて、"さささ"という人の出身県を調べてみましょう。
以下のフローを作ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/af74a483-a8b1-a417-0b20-5fe43aa2587a.png)
VLOOKUPアクティビティは、Excelプロセススコープ、Excelファイルを使用のアクティビティの中で動きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/1ce8e9b9-09e3-3cb0-8293-04fd7eb813da.png)

プロパティの項目とVLOOKUP式を対比するとこういう感じです。
出力先は検索結果の値が入ります。String変数でOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/a0d7b42f-c936-8a3d-b5b5-547b2baf8ac8.png)
## 結果は...
ログを見ると、"東京都"と書いてあります！よかった！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/3ad9afe3-8763-fb29-759d-cd2af6f3bf20.png)
## まとめ
今回は、Excel関数でも高頻度に使う？VLOOKUPをアクティビティを使ってみました。
実は、筆者はVLOOKUP関数が得意ではないのです...(毎回列番号で迷う)。
ただ、このアクティビティでVLOOKUP関数をコードで書いたりという手間が省けるのはよいことなのかと思いました。

最後までお読みいただきありがとうございました。
君もWWAWingの開発に参加しよう！

## WWAWingとは？

https://wwawing.com/

* 公式サイトより引用
```
Welcome to WWA Wing!

WWA(World Wide Adventure)は、ブラウザで遊べるインターネットRPGです。
あなたも広大な世界を旅してみませんか？

(当サイトは, WWAを2015年に新しい技術でリメイクした非公式プロジェクトです。)
```

## WWAWingのLocalでの動かし方
基本的には公式リポジトリに記載されたWikiの手順に従えば起動できます

https://github.com/WWAWing/WWAWing/wiki/GettingStarted

## Script要素の開発について
現在こちらのブランチ（ `feat/acorn` ）にてScript要素の開発が進んでいます。

https://github.com/WWAWing/WWAWing/pull/601

Script機能についてはこちらも見てみてください

https://www.notion.so/wwawing/c0b8474fda96446f8852d36d2f411b46

### 新しい関数の追加
* こちらのcommitも参考になります

https://github.com/WWAWing/WWAWing/pull/601/commits/2425b66a320d8415743444e98478c92529ca4ade

* `packages/engine/src/wwa_expression2/converter.ts`
    * `convertCallExpression()` に新しい関数名を追加する
* `packages/engine/src/wwa_expression2/eval.ts`
    * `evalAnyFunction()` に新しい関数の動作内容を追加する
* 追加完了したらローカルサーバのWWAにアクセスして、追加した関数を実行してみよう！

### evalAnyFunction() 関数内に書ける処理について
* 引数の処理
    * `this.evalWwaNode(node.value[0])` で1番目の引数を呼び出すことが出来ます。
* `wwa_main.ts` 内で定義されたWWAクラスの関数でPublicのものであれば全て呼び出せます
    * プレイヤー速度の変更については以下の通り
        * `this.generator.wwa.setPlayerSpeedIndex(gameSpeedValue);`
    * 他にもゲーム中の各種ステータスは以下関数で呼び出せます
        * `this.generator.wwa.getGameStatus()`
    * 現状のマクロに対応する内部関数がどのように使われているかは `wwa_message.ts` の `execute()` 関数からそれぞれ辿っていって実例を参考にしてみてください
ABC309復習

# ABC309復習
[デンソークリエイトプログラミングコンテスト2023（AtCoder Beginner Contest 309） - AtCoder](https://atcoder.jp/contests/abc309)

## ■結果
* ABC3完。3完なのに茶パフォ(620)と比較的良かったので、Dは少し難しかったのかも。
* Dは復習に良さそうだったのでじっくり復習して再提出。（グラフの隣接リストを復習し、BFS幅優先探索の基本を学んだ。）

## ■Ａ問題（Nine）
隣接をb-a==1、行またぎがない事をa !=3とa !=6で判定。
汎用性は薄いがルールは間違ってないし、5分で解けたからヨシ！

```python
a,b = map(int, input().split())

if b-a == 1 and a != 3 and a !=6:
    print('Yes')
    exit()
print('No')
```

## ■Ｂ問題（Rotate）
１行目、最終行、それ以外の行で処理を場合分けした。（リストでなく文字列で扱う事、スライス等の文字列操作でずらし操作などを表現するのは自分は良く使う手。）
見通し持ってやったわけではないけど、整理しきったからヨシ！

```python
n = int(input())
m=[]

for ii in range(n):
    a = input()
    m.append(a)

for ii in range(n):
    if ii==0:
        print (m[ii+1][0],end='')
        print (m[ii][:n-1])
    elif ii== n-1:
        print (m[ii][1:n],end='')
        print (m[ii-1][n-1])
    else:
        print (m[jj][0],end='')
        print (m[ii][1:n-1],end='')
        print (m[ii-1][n-1])
```

## ■Ｃ問題（Medicine）
日数が経つほど飲む薬が減る。累積和（減少方向）的な考え方でいけそう。
であれば、なにはともあれ、日数順にソートする実装が必要。部活のOさんに習った`m_list.sort(key=lambda x: x[0])`を使う。（便利）
その日のむ薬の量を、初日のTotalから減算していくループを作って判定すればOK。（読み込み時にtotalを計算する小技も追加。）
提出してみると、飲む薬が初日からk以下で良いケースでWAが出たので、初日特化の判定を追加した。

```python
n,k = map(int, input().split())
total = 0
m_list = []

for ii in range(n):
    a,b = map(int, input().split())
    total = total + b
    m_list.append([a,b])

if total <= k:
    print(1)
    exit()

m_list.sort(key=lambda x: x[0])

num = total
for ii in range(n):
    num = num - m_list[ii][1]
    if num <= k:
        print(m_list[ii][0]+1)
        exit()
```

## ■Ｄ問題（Add One Edge）
### １）まずデータを隣接リストに取り込む。（[隣接リスト - Wikipedia](https://ja.wikipedia.org/wiki/%E9%9A%A3%E6%8E%A5%E3%83%AA%E3%82%B9%E3%83%88)）

　何故隣接リストが良いのか、隣接リストはどういう構造か、軽くグラフの演習を思い出す。
　実装上はグラフのノード番号をゼロから始めた(0-indexed)。習慣上グラフのノードは１開始で出題される模様。ぐぐると1開始のまま扱うコードもそれなりに見られるしデバッグはそちらがし易そう。0-indexedだとコードが統一的な記述で処理でき楽そう（リストの0番目の特別扱いが不要なのは楽な印象。）

### ２）次に始点からの最大距離を求める
　グラフの距離を求めるアルゴリズムだと、例えばワーシャルフロイド法が有り、任意の２ノード間の距離が求まる（全点対最短経路問題）。しかし本問題では始点以外との点間距離は不要。ワーシャルフロイド法は計算量がO($n^3$)必要でTLEすると思われるのでこの作戦は避けよう。
　特定の点（スタート）から全ての点への距離を求める問題と考えよう。それなら幅優先探索が良いと思われる。
　考え方としてはこんな感じ。[【幅優先探索】木構造（グラフ）における頂点間距離を求める【Python】| くまと梨 (kunassy.com)](https://kunassy.com/bfs-tree-distance/)　これはTreeの説明だが、幅優先探索ではvisitedを記録して次に行く層を管理するので、ループがあっても特に気にしないで良さそう。
### ３）上記の１，２を実装する。
出来るだけ基本に忠実にbfs実装する。

```python
from collections import deque

n1,n2,m = map(int, input().split())

g1 = [[] for _ in range(n1)]
g2 = [[] for _ in range(n2)]

for _ in range(m):
	a, b = map(int, input().split())
	if a <= n1:
		g1[a-1].append(b-1)
		g1[b-1].append(a-1)
	else:
		g2[a-1-n1].append(b-1-n1)
		g2[b-1-n1].append(a-1-n1)
#print(g1,g2)

def bfs(graph, start):
	distances = [-1] * len(graph)
	distances[start] = 0
	queue = deque([start])
	while queue:
		node = queue.popleft()
		for neighbor in graph[node]:
			if distances[neighbor] == -1:
				distances[neighbor] = distances[node] + 1
				queue.append(neighbor)
	return distances

d1 = bfs(g1,0)
d2 = bfs(g2,n2-1)
#print(d1, max(d1), d2, max(d2))

print(max(d1)+max(d2)+1)
```
本コードでAC
久しぶりに`docker build .`したらエラーが出た。。（the --mount option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled）

久しぶりに`docker build .`したらエラーが出た。。

```
$ docker build .
Sending build context to Docker daemon  234.5kB
Step 1/6 : FROM python:3.10-slim-bullseye
 ---> 634cac419191
...
Step 3/6 : RUN --mount=type=cache,target=/var/cache/apt,sharing=locked     apt update &&     apt upgrade -y &&     apt install -y         wget         curl         git         build-essential &&     mkdir /tetris
the --mount option requires BuildKit.
Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled
```

リンク（https://docs.docker.com/go/buildkit/ ）記載の通り、`DOCKER_BUILDKIT=1 `つけても同様、、

```
DOCKER_BUILDKIT=1 docker-compose -f docker-compose.pytorch.yaml build
Building 
...
Step 3/6 : RUN --mount=type=cache,target=/var/cache/apt,sharing=locked     apt update &&     apt upgrade -y &&     apt install -y         wget         curl         git         build-essential &&     mkdir /tetris
ERROR: Service 'tetris' failed to build: 
the --mount option requires BuildKit. 
Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled
```

エラー出たときの環境

```
$ docker-compose -v
docker-compose version 1.25.0, build unknown
$ docker -v
Docker version 20.10.12, build 20.10.12-0ubuntu2~20.04.1
```

結局、docker engineを最新に更新して、`docker compose`(`docker-compose`ではなく)を使ったらビルド成功した

```
$ docker --version
Docker version 24.0.4, build 3713ee1
$ docker compose version
Docker Compose version v2.19.1
$ docker compose -f docker-compose.pytorch.yaml build
[+] Building 0.2s (11/11) FINISHED 
```


### 以下メモ

どうやら、`Docker Engine version 23.0.0`から`docker-buildx-plugin`が分離されているようだった

https://docs.docker.com/engine/release-notes/23.0/

> https://docs.docker.com/engine/release-notes/23.0/
> From Docker Engine version 23.0.0, Buildx is distributed in a separate package: docker-buildx-plugin. In earlier versions, Buildx was included in the docker-ce-cli package. When you upgrade to this version of Docker Engine, make sure you update all packages. For example, on Ubuntu:

```
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

https://docs.docker.com/build/buildkit/

```
sudo apt update -y
sudo apt upgrade -y
```

Docker再インストール

https://docs.docker.com/engine/install/

以下の通り最新にすることができました

```
$ docker --version
Docker version 24.0.4, build 3713ee1
$ docker compose version
Docker Compose version v2.19.1
```

# 参考

https://docs.docker.com/engine/install/

https://docs.docker.com/build/buildkit/
sticky footer というテクニック

## やりたいこと
webサイトを作る時に、フッターを設置したいけど、

- 基本的にはコンテンツの一番下に配置
- コンテンツが画面の高さより小さい場合は画面の一番下に固定

というような動作だと美しいですよね。

なにも考えずにただフッターを設置すると、コンテンツが少ない時に気持ち悪くなってしまいます。

![Screenshot_20230709-132451_Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637875/b37c072f-25d3-df67-8bac-a69ed551adda.png)

↑こんな感じに

これを、「sticky footer」というテクニックを使うと、下のようにできます。

![Screenshot_20230709-132629_Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637875/84a4e3bc-77b9-8c13-9a22-4e28674bcf49.png)

↑良き例

コンテンツが画面の高さを超えるようなときは元の動作になります。

## 実装
実はこれの実装方法は色々あって、jsで画面高さを取得して調整したり、flexboxを縦向きにして画面いっぱいに広げたりという手もありますが、もっとシンプルに実装できます。

```css
html, body {
  height: 100%;
}
footer {
  position: sticky;
  top: 100vh;
  top: 100dvh;
}
```

まじでこれだけです。

`100dvh`となっているのは、`100vh`だとiOSのsafariなどで、アドレスバーなどのUIの分の高さが引かれないので、UIを引いた分の実際の表示領域を指定する新しい単位です。

まだ対応してないブラウザもあるため、先に`100vh`を指定してフォールバックしています。

あとからでも簡単に設定できるので、ぜひ試してみてください！
IT業界におけるスキルとしての英語を考える

この記事では、IT業界で活躍するためのスキル、言い換えれば武器として英語をどう活用するかを考えていきます。

## 概要

※インフラ・ネットワーク分野を通じて出てきた考え方ですので、フロントエンドの場合はまた少しシチュエーションが異なるのかもしれません。

<b>①30代以降の新規参入において、若い人材との差別化を図る為にマイナーなスキルを尖らせる</b>
└自分の場合、それが英語だった

<b>②IT英語という分野のニッチさを逆手に取る</b>
└英語を使う現場における工数を独占するチャンス

<b>③3つの軸を作る</b>
└自分の知識の三次元化要素として英語を取り入れる

## 記事を書くきっかけ - 私のバックボーン

私は某外大を卒業後、20代後半までは英語を使って様々な仕事に従事していました（英語による海外観光客への接客やテクニカルライティング等）
元々外国語を使う事に高い興味があり、業務から発生する勉強もさほど苦ではありませんでした。

30歳間近で、私は一身上の都合で引っ越しをしたのですが、その頃は、体調の関係でフルタイムの仕事ができず、約10年間、正社員からは遠い生活を送っていました。

40代に入り、その頃、（恥ずかしながら）生活が少しずつ逼迫してき始め、体を押してでも仕事を探さなければならないという状態になってしまいました。
さて困ったな、と思いながら求人を探していたところ、就職支援としてIT分野のスキルが勉強できるという情報を手に入れました。

元々、その手の分野にはあまり抵抗がなかったのもあるのですが、知り合いのエンジニアの方から「プログラミング言語も、サーバログも、あれば<b>全て機械語という外国語</b>だから、あなたには適正があるんじゃないかな」という言葉をかけて頂き、はて、機械語とはどんな言葉なのだろうという興味から、恐る恐る支援プログラムに応募してみました。

倍率がどのくらいだったのかは今でも分からないのですが、幸運にも私は支援プログラムに参加できることになり、そこで生まれて始めてネットワークという分野を知ることになります。

## 詳細

### ①について - IT業界に入り込むための手段として

<b>【ITの勉強は外国語の延長】</b>
ネットワークの勉強をやってみて思った率直な感想は、「仕組みは難しいが、とっつきにくくはない」というものでした。
何故なら、私にとって<b>コマンドやログを読むのは、少し癖のある英文を読む感覚</b>に近く、ログの読み方は英文法の勉強のようなものに思えたからです。
外国語、即ち機械語の勉強に抵抗がない、というのは、大きなアドバンテージではないかと思います。

<b>【就活のアプローチとして】</b>
就職活動では、英語で色々な案内ができるという点を大きく打ち出していきました。
40過ぎ未経験の女性が就活をするにあたって、<b>面接官の記憶に残り、尚且、ひょっとしたら活用できる人材かもしれない、と思ってもらうのが早い</b>と考えたからです。

想像通り、就活は難航し、1年程を要しました。
手当たり次第に面接を受けたので、何社受けたかも覚えていません。
ですが、当時の私には、どうしても「IT業界への入り口」が必要だったので、辛抱強く就活を続け、やっと内定とアサイン先を手に入れます。

### ②について - 英語を使う機会が少ない、即ち使う業務は独占する
<b>【現場における英語活用1】</b>
最初にアサインしたのは、外国籍の方が多く在籍する会社での社内ヘルプデスクでした。

驚いたのは、<b>意外と英語を使って案内できる人が少ない</b>という事でした。
おかげで、私は外国籍の方の関連するインシデントを引き受ける機会に恵まれ、同時に、ネットワークにおける英語表現の勉強ができる機会を得ます。

やっぱり、英語はアウトプットしないと身に付かないのですが、ヘルプデスクは否が応でもコミュニケーションを取らないといけない仕事なので、（精度はともかく）IT独特の表現方法は身に付いたのではないかと思います。

<b>【現場における英語活用2】</b>
上記の契約が終わり、私は今の現場にやってきます。

こちらで、英語を使うというスキルが最大限に活かされています。
アサイン直後、私が以前、英語を使って業務を行っていたという話を現場のプロパーさんが耳にしたらしく、いきなり海外支社へのシステム導入のお手伝いをすることになります。

しかも、周囲には英語を使える方が皆無。
必然と、海外展開関連業務は、私だけにアサインされていきます。

オンラインキックオフ、週次オンラインミーティング、説明資料作成等、いきなりヘビーなタスクだらけでしたが、<b>「英語関係 = あの人しかできない」という印象付け</b>には成功したのではないかと思います。


### ③について - 現場でユニークな人材になる為に

<b>【ITにおける3つの軸】</b>
これは、私の恩師の受け売りなのですが、IT業界において、自分を戦力へ育てる為には3つの軸を作成し、3次元的にスキルを拡大するのが良いそうです。

軸を作るには、ITに関連するものであれば何でも構わない、というルールで考えると、<b>「IT英語」は立派なスキルになり得る</b>と考えています。

もちろん、これ単体では弱いのですが、ここに異なる要素を組み合わせる事で、他にはいないユニークな人材への道とする事が可能です。
では、ここに、フロントエンドの知識を足すか、バックエンドの知識を足すか、それとも共通する環境の知識を足すか。この差異だけでも、多くのバリエーションを持たせる事ができます。


## 最後に
最初に、Qiitaの記事を書いてみませんか、とお声がけ頂いた時、正直に話すと断ろうかな、と考えもしました。
だって、私はまだ経験が浅く、他の方へシェアする知識なんかないに等しいからです。
でも、ちょっとだけ思いとどまって、稚拙であってもいいから、今の私にしかない視点を共有するだけでも自分のプラスになるのでは、と、考えを切り替えて本記事を作成してみました。

どなたかの何かしらの参考の一部になれれば幸いです。


## お知らせ
私が所属しています「TECH WOMAN KANSAI」についてご案内します。

TECH WOMAN KANSAI は関西女性エンジニア限定コミュニティで、下記のようなアクティビティを中心に活動中です。

　■オンラインもくもく会
　■オフラインイベント
　■月１交代でQiita投稿

また、メンバーが投稿した記事もありますので、こちらも読んでみて下さい

https://qiita.com/organizations/tech-woman-kansai

こちらは「compass」のコミュニティページです。

https://tech-woman-kansai.connpass.com/

関西女性エンジニアの皆さんでスクラムを組んでいますので、気軽にチェックしてみて下さい！
NFTのメタデータを基にHashLipsで画像を再作成する

ジェネラティブNFTの画像をHashLipsで作る際に以下のようなシーンがあります。
* 良い組み合わせができたけど、パーツ自体を修正したい。もう一度ビルドすると別の組み合わせになってしまう。
* どうしても狙った組み合わせが作りたい。

いずれも、用意したパーツを手動で組み合わせればできるといえばできますが、メタデータを基に再作成できれば良いのでは？ということで、コードを書いてみました。

### リポジトリ

https://github.com/two-pack/hashlips_art_engine/tree/features

### 使い方

npmスクリプトに **rebuild** を追加しています。
実行すると、**_metadata.json**を基に画像と個別のメタデータを作成し直します。

```bash
$ npm run rebuild
```

### 例

棒人間のリポジトリを例に説明します。
https://github.com/two-pack/hashlips_art_engine/tree/example_stick_figure

とりあえず、1回ビルドしてみます。
```bash
$ npm run build
```

こんな感じで画像が生成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30716/8adbd7eb-13c0-763f-a216-2387e50ea076.png)

目と口追加してみます（雑
<img width="100" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30716/2b55becd-88e8-3b7b-c9d1-69996055691b.png">

これで再作成してみます。
```bash
$ npm run rebuild
```

こんな感じで新しいパーツを基に画像が再作成されています。下が再掲の変更前のものです。手足や胴体は変わってないですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30716/2c4cd0f6-efa6-802e-5dad-3ddaefdd67a8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30716/8adbd7eb-13c0-763f-a216-2387e50ea076.png)

続いて、_metadata.jsonを変更して任意の組み合わせを作るケースです。
1.pngのメタデータは以下のようになっています。
```json
{
  "name": "Example: Stick Figure 1 #1",
  "description": "This is the first step in web3.",
  "image": "/1.png",
  "dna": "56ead44d633660346d1e8aae33a551c543922745",
  "edition": 1,
  "date": 1688874975277,
  "attributes": [
    {
      "trait_type": "Head",
      "value": "Red"
    },
    {
      "trait_type": "Body",
      "value": "Red"
    },
    {
      "trait_type": "Right Arm",
      "value": "Blue"
    },
    {
      "trait_type": "Right Leg",
      "value": "Red"
    }
  ],
  "compiler": "HashLips Art Engine"
}
```

右腕も赤にしてみることにして、**Right Arm**を**Red**に変更して、ついでに左腕と足も追加します。
```json
  {
    "name": "Example: Stick Figure 1 #1",
    "description": "This is the first step in web3.",
    "image": "/1.png",
    "dna": "56ead44d633660346d1e8aae33a551c543922745",
    "edition": 1,
    "date": 1688874975277,
    "attributes": [
      {
        "trait_type": "Head",
        "value": "Red"
      },
      {
        "trait_type": "Body",
        "value": "Red"
      },
      {
        "trait_type": "Right Arm",
        "value": "Red"
      },
      {
        "trait_type": "Right Leg",
        "value": "Red"
      },      {
        "trait_type": "Left Arm",
        "value": "Red"
      },
      {
        "trait_type": "Left Leg",
        "value": "Red"
      }
    ],
    "compiler": "HashLips Art Engine"
  }
```

上記のように_metadata.jsonを変更して再作成をすると、はいこの通り！
個別のJSONファイルも書き換わっています。
<img width="100" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30716/eaa3393d-0e93-6dd4-7787-a331327591fc.png">
ゆっくり動画作る際に参考になったURLリンクメモ

ゆっくり動画作る際に参考になったURLリンクメモ

windowsで作る場合はゆっくるMovieMakerが大変便利でありがたいです

https://manjubox.net/ymm4/

音楽は、フリー音楽を使わせて頂くと大変便利でありがたいです

https://www.youtube.com/watch?v=daKcU7mjNOQ

利用規約を参考に、公明正大に使っていきましょう

# 参考

windowsで作る場合

https://manjubox.net/ymm4/

https://www.youtube.com/watch?v=bTrtmg2MQS4

http://www.nicotalk.com/charasozai_kt.html

macで作る場合

https://www.yukumo.net/#/

https://www.youtube.com/watch?v=8mm6KkzdXbs

https://qiita.com/developer-kikikaikai/items/47a13cbcb6fdb535345a
CORSエラーと疑う前にリクエストボディの形式を再確認しよう

## 概要

Next.jsからバックエンド(laravel)に対してユーザー登録を行おうとした際に
CORSエラーが発生しました。
最終的にCORSエラーではなく、初歩的なミスによるものでした。。。
解決までに時間が掛かってしまった為、記事として記載しました。

## まず結論

Next.jsでPOSTリクエストを送る際の、bodyの形式が誤っていました・・・

```javascript
// NG
const data = {
	lastName,
	firstName,
	age,
	gender
}

// OK!
const data = {
	last_name: lastName,
	first_name: firstName,
	age: age,
	gender: gender
}
```

## なぜハマったのか

Next.jsからリクエストを送った際に返却されたエラーメッセージが
'Access-Control-Allow-Origin'ヘッダーが存在しない旨の内容であったため
CORSの設定が原因だと思い込んでしまったため。

![NextErrorMessage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630872/c1f0b7dd-5719-e5e8-9e89-6919b5c6d0de.png)

```
create:1 Access to fetch at 'http://localhost:3001/' 
(redirected from 'http://localhost:8080/api/users') from origin 'http://localhost:3001' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
```

## 最後に
自分への戒めと今後同じような内容でハマった人の為に記事を書きました。
Accessプログラム　よくある？トラブル集（Excel連携編）

### 1. 実行時エラー：-2147217900 SQLステートメントが正しくありません ###

（現象）
ExcelVBAからADO経由でAccessのクエリーを実行したときに、たまに発生するエラーです。
**「実行時エラー：-2147217900 SQLステートメントが正しくありません。　DELETE INSERT PROCEDURE SELECT または UPDATEを使用してください。」**

``` VB
Dim cmd As ADODB.Command
Dim rs1 As New ADODB.Recordset

Set con = New ADODB.Connection
con.ConnectionString = "Provider=Microsoft.ACE.OLEDB 12:Data Source=C:\test.accdb"
con.Open

Set cmd = New ADODB.Command
cmd.ActiveConnection = con
With cmd
    .CommandText = "qIs_サービス別件数・工数集計"
    Set rs1 = Execute()            ' ⇒ここでエラーになる
```

（原因）
・指定したクエリー名 or SQLの文法が間違っている。
・Nz関数など、Accessでしか使えない（⇒ADOでは使えない）関数を使っている。
意外と落とし穴ですが、ADOを介しているため、次のようにNzなどAccess固有の関数は使えません。
``` SQL:qIs_サービス別件数・工数集計
INSERT INTO tWk_集計ワーク
SELECT 'サービス別件数' As 式1,
Count([作業No]) As 作業Noのカウント,
Nz(Sum([実績時間]), 0) As 実績時間の合計    -- ⇒ここがダメ
FROM tTr_年度作業実績;
```

（対策）
・挿入処理の後で、結果対象カラムがNullであれば0に置き換える更新処理を実行。
　上の例の場合、いったん「実績時間の合計」カラムをNullのままレコード挿入する。
　その後、「実績時間の合計」ががNullであれば0に置き換えるSQL or 更新クエリーを実行する。

***
### 2. 文字列の包含検索で、指定した条件にうまくヒットしない ###
（現象）
ExcelVBAからADO経由で実行した文字列の包含検索で、指定した条件にうまくヒットしない。
``` SQL
SELECT 作業No, 件名, 実績時間
FROM tTr_年度作業実績
WHERE 件名 LIKE "*DNS*"        -- １件もヒットしない・・・
```
（原因）
これも同様の原因で、Access固有のワイルドカード指定"\*"は、ADOを介すると**半角アスタリスクの文字列**とみなされるため、意図した検索結果が返ってきません。
https://learn.microsoft.com/ja-jp/dotnet/framework/data/adonet/ef/language-reference/like-entity-sql

（対応）
ワイルドカードに"%"を指定したSQL or 選択クエリーを実行します（SQL Server等と同じ）。
``` SQL
SELECT 作業No, 件名, 実績時間
FROM tTr_年度作業実績
WHERE 件名 LIKE "%DNS%";
```
とはいえ、（過去の経緯はあるとはいえ）せめてこれくらいは、Microsoft内で融通利かせてほしいものですよね・・・:disappointed_relieved: