OmniAICreator/Qiita-1.07M huggingface dataset:
Nanp Pi NEOセットアップ

## 付属のSDカードで起動した場合のSSH ##
user=pi, password=pi

32bit OSの模様。
```
$ uname -a
Linux NanoPi-NEO 4.14.52 #93 SMP Thu Jun 28 17:46:52 CST 2018 armv7l armv7l armv7l GNU/Linux
```

とりあえずいつもの
```
$ sudo apt update
$ sudo apt upgrade
```
尚、GLIBCのバージョンが低かったのでこのイメージで進めるのは辛い。

## Armbianを新規インストール ##

下記サイトからNanopiNeo用のBusterをダウンロード。

https://www.armbian.com/nanopi-neo/

[balenaEtcher](https://www.balena.io/etcher/)などを使ってmicroSDに焼く。

### ssh ###
root/1234でuserとしてログインし、いわれるがままにrootのパスワードとuserを作成。その後いろいろ聞かれるが、languageはen_US.UTF-8を、タイムゾーンはAsia/Japanで設定。終わったら一旦exit。

### update/upgrade ### 
作成したユーザーでログインしなおして、updateとupgrade。

```
$ sudo apt update
$ sudo apt upgrade
$ sudo apt dist-upgrade
```
ちょっとエラーが出たけど気にしないで進む。
```
E: The repository 'https://apt.armbian.com bullseye Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
N: Repository 'http://deb.debian.org/debian bullseye InRelease' changed its 'Version' value from '11.2' to '11.3'
```
gccやgitは既に入っていて、GLIBCのバージョンは2.31だった。
```
$ ldd --version
ldd (Debian GLIBC 2.31-13+deb11u2) 2.31
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
```

### WiFi内蔵ではない ###
WiFiを使うにはUSBのWiFiアダプタが必要。

https://www.jh1lhv.tokyo/entry/2017/08/21/213816

### JUCEの開発に必要なライブラリを入れる ###
```
$ sudo apt-get install clang freeglut3-dev g++ libasound2-dev libcurl4-openssl-dev libfreetype6-dev libjack-jackd2-dev libx11-dev libxcomposite-dev libxcursor-dev libxinerama-dev libxrandr-dev mesa-common-dev webkit2gtk-4.0-dev -y
```

### デスクトップ環境をインストール ###

```
$ sudo apt install task-xfce-desktop
```

VNCサーバーも。
```
$ sudo apt install tightvncserver -y
```

### 内臓オーディオを有効にする ###
```
$ sudo armbian-config
```
で、System->Hardwareでanalog-codecを有効にする。複数のアプリから同時に鳴らしたい場合はPulse Audioも。

```
$ sudo apt install pulseaudio -y
```

### GPIO ###
OLED Hatについてるボタンを使いたいのでGPIO…と思って探したらこちらがビンゴ。

https://qiita.com/nanbuwks/items/071e775e77acebdebc80

```
$ git clone git clone https://github.com/wertyzp/WiringNP.git
$ cd WiringNP
$ chmod 755 build
$ sudo ./build
$ gpio readall
```
root権限でビルドする必要があった。
SwiftUIでAppStoreカードを表示する

# AppStoreカードとは何か？
正式な名前が分からないので勝手に名前を付けさせてもらいました！
(多分正式名称は「SKOverlay」だと思います。)
まだ浸透してないと思うので検索に引っかかるようにタイトルはそのままにしておきます笑

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a1ae535c-2b84-477e-10bb-936b93cd334e.jpeg" width="300"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/882beada-3620-940a-ba19-22027140c30a.jpeg" width="300">
これです！

これをSwiftUIで実装していこうと思います。

# 実装
```ContentView.swift
import SwiftUI
import StoreKit

struct ContentView: View {
    @State var isShowSKOverlay: Bool = false
    var body: some View {
        VStack {
            Text("Hello, world!")
                .padding()
        }
        .onAppear() {
            isShowSKOverlay = true
        }
        .onDisappear() {
            isShowSKOverlay = false
        }
        .appStoreOverlay(isPresented: $isShowSKOverlay) {
            SKOverlay.AppConfiguration(appIdentifier: "{アプリのID}", position: .bottom)
        }
    }
}
```
これだけです
簡単ですね〜

# 収益化できる！？
収益化できるSDKを発見しました
ただ現時点では運営会社に問い合わせないとダメみたいです
通常のバナー広告より広告感がないのでUXが向上しそうです

もし「SKOverlay」が収益化できたら新しく記事書こうと思います。

https://vungle.com/jp/vungle-sdk/

https://vungle.com/blog-jp/what-is-skoverlay-jp/

https://vungle.com/blog-jp/vungle-sdk6-10-ios14-5/
ubuntu 18.04 / RTX 3090 でtensorflow-gpuを使うまでの話

## cuda11.2とtensorflow2.4の相性の悪さにハマる (windowsでもハマった)
[tensorflow 公式](https://www.tensorflow.org/install/gpu?hl=ja)は、RTX3090に対応したcudaを落とせないので、適宜読み替える必要があるが、細かいverの違いにはまったので。`tensorflow.device_lib.list_local_devices()`で認識できるまでにしたことをメモ。

そもそも、カスタムビルドで納品された環境がpython3.6系列だったので、クリーンインストールしなければいけなかったのが問題(その時の話は別記事で)。

## 実際にやったこと
- apt でインストールできるライブラリ周り
~~~
# nvidia driverの追加
sudo apt install nvidia-driver-470

# repo 追加
wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
sudo apt install ./nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
sudo apt-get update

# もろもろのインストール
sudo apt install cuda-toolkit-11-2
sudo apt install libcudnn8=8.1.1.33-1+cuda11.2
sudo apt install libcudnn8-dev=8.1.1.33-1+cuda11.2
sudo apt install libnvinfer8
sudo apt install libnvinfer-dev
sudo apt install libnvinfer-plugin8

# pathの追加
export LD_LIBRARY_PATH=/usr/local/cuda-11.2/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
~~~
※注意: apt内に`nvidia-cuda-toolkit` というライブラリがあり、思わずとびつくとver 9.1のcudaが入ってしまうので注意
※NOTE: 今回driversを470にしたことで、cuda11.4にすることもできるが、昨年設定した別端末との環境を揃える必要があったため、cudaは11.2をあえて指定しています。libnvinfer8はこの時点では、ver11.0-11.4に対応しているということで、特にバージョン指定はしていません。参考:`libnvinfer8=8.2.3-1+cuda11.4`



## 案の定認識されない `libcudart.so.11.0`
これは、windowsのときにも直面したが、やはりはっせいする。とりあえず、シンプルにシンボリックリンクを作成することで対応。
windowsのときは、ファイル名変えろというのを真面目に信じて実行して結局ドツボにはまった。
~~~
sudo ln -s /usr/local/cuda-11.2/lib64/libcusolver.so.11 /usr/local/cuda-11.2/lib64/libcusolver.so.10
~~~
※インストールパスを変更している場合は適宜よみかえてください。


### 以上でとりあえず認識はします。
~~~
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
~~~
の実行結果一部
~~~
name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 22721529088
locality {
  bus_id: 1
  links {
  }
}
incarnation: 12540486796505853533
physical_device_desc: "device: 0, name: NVIDIA GeForce RTX 3090, pci bus id: 0000:65:00.0, compute capability: 8.6"
~~~

### その他
bashなどの読み込み設定は、適宜調整してください。
C＃を使用してExcelでデータを検索、置換する方法

Excelを使用してデータを処理する場合、ワークシートに多くのコンテンツが含まれているため、データを1行ずつ手動で検索すると、かなり面倒なことになり、時間も無駄にして、効率的にも名案とは言えませんから、困りますよね。Microsoft Excelは、非常に強力なデータ処理機能（検索と置換）を提供しています。この機能により、求めるデータをすばやく検索し、一度に1つ以上のセルのデータを変更したりまたは更新したりもできます。だけど、開発のために、プログラムで実装する場合もあります。この記事では、無料版のSpire.XLS for .NETというコンポーネントをダウンロードしてから、C＃を使用してExcelの検索と置換機能を実装する方法について説明します。

これは操作するExcel文書のスクリーンショット
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/0d11c3e8-7366-2433-cf85-3f77482d8bee.png)

これからはA5およびA6の「カナダ」を「イギリス」に置換します。
## 詳細な手順

まず、新しいVisual C＃コンソールプロジェクトを作成し、参照を追加して、次の名前空間を使用します。
```
using System.Drawing;
using Spire.Xls;
```
ステップ1：新しいWorkbookクラスのオブジェクトを作成し、Excelドキュメントを読み込みます。
```
Workbook workbook = new Workbook();
workbook.LoadFromFile("C:\\Users\\Administrator\\Desktop\\sample.xlsx");
```
ステップ2：テキストを置き換える必要のあるワークシートを取得します。これが最初のワークシートです。
```
Worksheet sheet = workbook.Worksheets[0];
```
ステップ3：テキスト「カナダ」を検索し、Worksheet.FindAllString()メソッドを呼び出してすべてを「イギリス」に置き換えます。ここでは、置き換えられたデータを簡単かつ迅速に見つけるために、ハイライトの色も設定します。
```
CellRange[] ranges = sheet.FindAllString("カナダ", false, false);
foreach (CellRange range in ranges)
{
    range.Text = "イギリス";
    range.Style.Color = Color.LawnGreen;
}
```
ステップ4：ファイルを保存して再度開きます。
```
workbook.SaveToFile("replace.xlsx");
System.Diagnostics.Process.Start("replace.xlsx");
```
結果は以下のようになります
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/edb3cf24-d861-6525-eb5b-954bb6f9dc5f.png)


## 完全なるコード
```
using System.Drawing;
using Spire.Xls;

namespace Excel find and replace data
{
    class Program
    {
        static void Main(string[] args)
        {
            Workbook workbook = new Workbook();
            workbook.LoadFromFile("C:\\Users\\Administrator\\Desktop\\sample.xlsx");

            Worksheet sheet = workbook.Worksheets[0];
            CellRange[] ranges = sheet.FindAllString("カナダ", false, false);
            foreach (CellRange range in ranges)
            {
                range.Text = "イギリス";
                range.Style.Color = Color.LawnGreen;
            }

            workbook.SaveToFile("replace.xlsx");
            System.Diagnostics.Process.Start("replace.xlsx");
        }
    }
}
```
今回のExcelでデータを検索、置換する方法は以上でした、最後まで読んでいただきありがとうございました。
Strapi v4でAPIのレスポンスに一部のフィールドが含まれない場合

Strapi のバージョン4系でREST APIから返却されたJSONに一部のフィールドが含まれない現象が起きた。その解決方法を書く。

# `populate`を指定する
`Media`タイプや`Relation`タイプのフィールドは明示的に指定しないとデフォルトでは含まれないとのこと。含めたい場合は`populate`で指定する。（[参考](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/populating-fields.html)）

全てのフィールドを含めたい場合は以下。

```
https://exmaple.com/restaurants?populate=*
```

特定のフィールドのみを含めたい場合は以下。

```
https://exmaple.com/restaurants?populate=top_image,categories
```

上記の場合、`top_image`（`Media`タイプ）と`categories`（`Relation`タイプ）を含める。デフォルトで表示されるフィールドはここで指定しなくても勝手に含まれる。

`populate`にはもっと複雑な指定ができるので詳しくは[公式サイト](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/populating-fields.html)を参照。

# 権限を確認する
`Relation`タイプのフィールド限定だが、関係先のテーブルの読み取り権限がないと表示されない。`populate`で指定しても単純に無視される。まあ忘れてただけな訳だが私はこれで結構悩んだ。
[React,TypeScript]無限import編が起きてしまった時の解決策

### はじめに
Reactのアプリを開発している時に以下の様なエラーを吐いてコンパイルできなくなってしまったので、その解決法を記しておきます

### エラー内容
```
Dependency cycle detected ...
```
このエラーを調べてみるとimportし続けてしまう連鎖が起きているらしい

### エラーの解説
1.chatDataSlice.tsからRootStateをimportする
2.reduxType.tsからstoreをimportする
3.store.tsからchatDataReducerをimportする

この一連の流れがループしていることでエラーが発生している
``` chatDataSlice.ts
/* packages */
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
/* hooks */
import { useAppSelector } from "../../hooks/useAppselector";
/* types */
import { chatData } from "../../types/chatData";
import { RootState } from "../types/reduxType";

const initialState: chatData[] = [];

export const chatDataSlice = createSlice({
  name: "chatData",
  initialState,
  reducers: {
    setChatData: (state, action: PayloadAction<chatData[]>) => action.payload,
  },
});

// reducer
export const chatDataReducer = chatDataSlice.reducer;

// action
export const { setChatData } = chatDataSlice.actions;

// selector
export const useChatDataSelector = () => {
  const chatDataSelector = useAppSelector((state: RootState) => state.chatData);
  return chatDataSelector;
};
```

``` reduxType.ts
/* store */
import { store } from "../store";

export type RootState = ReturnType<typeof store.getState>;

export type AppDispatch = typeof store.dispatch;
```

``` store.ts
/* packages */
import { configureStore } from "@reduxjs/toolkit";
/* slice */
import { chatDataReducer } from "./slices/chatDataSlice";

export const store = configureStore({
  reducer: {
    chatData: chatDataReducer,
  },
});
```

### 原因
importしたファイルはmoduleではないかとコンパイラ側は認識してしまっているから無限import編が始まっている

### 解決策
importの後ろに***type***を明記することでエラーは無くなった
明記することでmoduleではなくtypeだと認識し、依存関係から除外されているのでは??

```chatDataSlice.ts
import type {RootState} from "../types/reduxType";
```

## 参考

https://stackoverflow.com/questions/63923025/how-to-fix-circular-dependencies-of-slices-with-the-rootstate
【AWS】今までの学習で学んだ用語をまとめてみた。

## AWS API
AWSが提供しているAPIでこれを使用することで、CLI上からコマンドをAWSに送信し、クラウドのリソースを操作することができます。
また、このAPIを実行するために用意されたCLIが<b>AWS CLI</b>
です。

## ARN 
ARN(Amazon Resource Name)はAWSのリソースに付けられた固有の名前のことです。ホームページで言うとURLに近いですね。

例えばS3の場合は"arn:aws:s3:::my_buckets/"のような形のものです。
このARNが存在することによって特定のバケットやインスタンスを指定し、参照することが可能になります。

## CloudFormation
CloudFormationはAWSの静的リソースを管理するための仕組みのことです。

静的リソースとは、S3のバケットやEC2のインスタンス、DBのテーブルといったデプロイ時に1度だけ実行されるリソースのことです。

逆に、S3のバケットにデータを書き込むといった、繰り返し又は、操作するために実行される操作のことを動的な操作といいます。

少し話が反れましたが、CloudFormationでは、インスタンスのスペックや、そのアクセス権限などを記述及び管理することができます。

## VPC
VPC(Virtual Private Cloud)はクラウド内で使える仮想的なネットワークのことを指します。VPC内に配置することで、リソースをVPC単位に分離することができます。

EC2のインスタンスを立てるケースを例に出すと、複数のサーバーを連動させたり、そのために互いのアドレスを管理させたりする際に有用です。

※インスタンスを立てる際には必ずVPC内に配置しなければならないという制約があります。

## Security Group
EC2インスタンスに付与することが出来る仮想的なファイアーウォールのことです。
これを用いることでインスタンス内にアクセスできるIPアドレスを制限、操作することができます。

## まとめ
今回は以上です、次回は5章以降の機械学習をAWSで実践した箇所で学んだ用語について書いていこうと思います。
AWSを使う

# 参考

https://qiita.com/kazokmr/items/754169cfa996b24fcbf5

# 
https://qiita.com/yamanashi7474/items/979084e0532f5633c010

# putty-gen

ppk->pemの相互変換。
　→　Putty-genで可能（一度ロードしてから保存）
　　　またはConvertボタン
     https://qiita.com/naka46/items/3297242f3386b5f9e3dc

# ssh接続の仕方

AWS、インスタンス、接続ボタンを押すと、次の画面下に接続用コマンドが表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/9f99fae3-bc29-20ee-0f7d-839de8947935.png)

[インスタンスに接続]ダイアログの右下の接続ボタンでWEB経由でコンソールにログインできる。


# sshトンネル/ssh転送設定
https://blog.y-yuki.net/entry/2021/04/16/230000

ssh {ssh接続用ユーザ}@{踏み台サーバのホスト} -i {秘密鍵のパス} -L {待ち受けするポート}:{転送先のホスト}:{転送先ホストのポート}

#  sshトンネル/ssh転送設定 -> teraterm

port 9999 とする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/8e047c4c-369b-fc7c-57f1-4618af040bc5.png)

# トラブルシューティング
windowsの場合、コマンドプロンプトのsshから接続する（pemに変換する）

AWSの無料インスタンスは遅すぎて学習効率悪いので有料インスタンスを使った方がよい。


# jupyter 
version : jupyter-notebook --version

```

import torch
torch.cuda.is_available()

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("使用デバイス", device)


```

# GPUでディープラーニングやるならAWSよりFloydHub
https://qiita.com/alchemist/items/83c50712d9cf0e51e750

# AWS GPUインスタンスのスペック・価格比較
https://qiita.com/m0ch1m0ch1/items/81b136b8eac1395c82ba#%E3%80%87-p%E7%B3%BB%E3%81%AE%E3%82%B9%E3%83%9A%E3%83%83%E3%82%AF%E4%BE%A1%E6%A0%BC%E6%AF%94%E8%BC%83%E8%A1%A8


#コマンドラインからpytorchでgpuが使えるかどうか確認する
https://qiita.com/seigot/items/4fa4737d6ae439cbd1c4

```
python -c "import torch; print(torch.cuda.is_available())"

```
Scalaの勉強はじめました 9 〜関数型プログラミング編 エラー処理の続き〜

## はじめに
N予備校で「Scala応用」コースを受講しています。

## Either
`Option`型の場合、エラーの種類までは取得できない。
2つの値のどちらかを表現するデータ型。
`Left`にはエラー、`Right`には正常の値を入れる。

```scala
sealed trait LoginError
case object InvalidPassword extends LoginError
case object UserNotFound extends LoginError
case object PasswordLocked extends LoginError

case class User(id: Long, name: String, password: String)

object LoginService {
  def login(name: String, password: String): Either[LoginError, User] = {
    (name, password) match {
      case ("taro", "Password1") => Right(User(1, name, password))
      case ("taro", _) => Left(InvalidPassword)
      case (_, _) => Left(UserNotFound)
    }
  }
}
```

呼び出し

```scala
LoginService.login(name = "taro", password = "Password1") match {
  case Right(user) => println(s"id: ${user.id}")
  case Left(InvalidPassword) => println(s"Invalid Password!")
  case Left(UserNotFound) => println(s"User Not Found!")
  case Left(PasswordLocked) => println(s"Password Locked!")
}
```

## Try
`Success`と`Failure`の2つのデータ型を持つ。

```scala
import java.lang.Runtime
import scala.util.{Failure, Success, Try}

object TryTest {

  def isCat(animal: String): Boolean = {
    Try {
      if (animal == "Cat")
        true
      else {
        throw new Exception
        false
      }
    } match {
      case Success(_) =>
        println("ねこだよ")
        true
      case Failure(_) =>
        println("ねこじゃないよ")
        false
    }
  }
}
```
`Try`で引っかかる例外は`NoFatal`なものだけ。
引数に`String`以外のものを入れても`Failure`に入るわけじゃない。

## まとめ
使い分けとして、

Nullを使う場合 => Option
Optionでは情報が不足している、エラー状態が定義されている => Either
例外を値として扱いたい場合 => Try

が目安になるみたい。
SQLAlchemy: MariaDB のデータを削除 (Delete)

## プログラム

```py:maria_delete.py
#! /usr/bin/python
#
#	maria_delete.py
#					Sep/03/2024
#
# ----------------------------------------------------------------
import sys
from time import localtime,strftime
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
#from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# ----------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
key_in = sys.argv[1]
print(key_in)
#
host='localhost'
data_base = 'city'
user ='scott'
password = 'tiger123'
db_url = "mysql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
city_a = session.query(City).filter_by(id=key_in).first()
if city_a != None:
	session.delete(city_a)
	sys.stderr.write(key_in + " is deleted.\n")
session.commit()
#
sys.stderr.write("*** 終了 ***\n")
#
# ----------------------------------------------------------------
```

## 実行コマンド

```bash
./maria_delete.py t3325
```

## 確認したバージョン

```text
$ python --version
Python 3.11.3
```
SQLAlchemy: MariaDB のデータを更新 (Update)

## プログラム

```py:maria_update.py
#! /usr/bin/python
#
#	maria_update.py
#					Sep/03/2024
#
# ----------------------------------------------------------------
import sys
from time import localtime,strftime
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# ----------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
key_in = sys.argv[1]
population_in = int(sys.argv[2])
print("%s\t%d" % (key_in, population_in))
#
host='localhost'
# host='10.39.166.1'
data_base = 'city'
user ='scott'
password = 'tiger123'
db_url = "mysql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
try:
	city_a = session.query(City).filter_by(id=key_in).first()
	if city_a != None:
		city_a.population = population_in
		city_a.date_mod = strftime("%Y-%m-%d",localtime ())
		sys.stderr.write(key_in + " is updated.\n")
except Exception as ee:
	sys.stderr.write(str(ee) + "\n")
session.commit()
#
sys.stderr.write("*** 終了 ***\n")
#
# ----------------------------------------------------------------
```

## 実行コマンド

```bash
./maria_update.py t3328 89145700
```

## 確認したバージョン

```text
$ python --version
Python 3.11.3
```
エンジニア×非エンジニアにおける1on1のやり方


## はじめに

みなさんの会社や組織では1on1は実施していますか？

導入をされているところも多いかと思いますが、相手（上司や部下または同僚）が非エンジニアであるパターンもあるかと思います。

今回は非エンジニアとの1on1について、うまく機能させるには？という観点で記事を書いてみたいと思います。

ちなみに私は非エンジニアの立場として10年以上、色々な職種の方たちと1on1を毎週やっています。（対エンジニア、対デザイナー、対ビジネスサイド）




## 非エンジニアとの1on1のコツ
**目次**

* [知っておいて欲しい専門用語はあえて使う](#知っておいて欲しい専門用語はあえて使う)
* [0か1かで話しすぎない](#0か1かで話しすぎない)
* [相手の言葉に置き換える](相手の言葉に置き換える)
* [相手の専門領域に興味を持つ](#相手の専門領域に興味を持つ)
* [最後に](#最後に)


## 知っておいて欲しい専門用語はあえて使う
相手が非エンジニアの場合、エンジニア同士で使うような専門用語が通じない時ってありますよね？
その場合基本的には分かるような言葉で会話することが望ましいのですが、「相手に知っておいて欲しい場合」についてはあえて会話の中で使うことをおすすめします。

1on1を実施しているということは、前提としてその人同士が理解を深めること、関係性を構築することが組織にとってプラスになるということだと思います。

例えば「**オンプレ**」という単語を使わずに「**サーバやDBを自社内で構築運用すること**」と伝えてあげることは丁寧ですが、相手はずっとその単語を知らないままになるかもしれません。

オンプレの意味はさすがに知っておいてくれよ・・・という話は置いておいて、一緒に仕事をするにあたって相手に知っておいて欲しい言葉は、あえて使う意識を持つことをおすすめします。

相手も子供では無いので、知らなかったら調べるかあなたに聞くかすると思います。

それもせずに知ったかぶりをするような相手であれば、それはまた別の話になってきます。


## 0か1かで話しすぎない
これはエンジニアとビジネスサイドで話す時に起こりがちな話です。（あくまで私の経験上です）

業務の特性上、エンジニアよりもビジネスサイドの方がいわゆる**ゆらぎ**があることが多いです。

例えばある技術的な仕様の話をしている時に、ビジネスサイドの相手から「これって出来ますか？」と聞かれたとします。
相手が言う要件を100%実現するのが難しい場合に「無理ですね」と答えたとします。

この時、ビジネスサイドの人間は「**だいたいこのような状態になっていれば良い**」と想像していることが多い（あくまでエンジニアの思考と比較して）のですが、エンジニアの立場からすると色々な要素を考えて整合性を含めて判断出来てしまうので、結果「無理」という結論が出てしまいます。

こういう場合、エンジニアとしては「**そのままでは実現出来ないけど、こうすれば目的は達成出来るかもしれない**」という視点でぜひ話してみることをおすすめします。
そうすることによって、より生産的な話が出来るかもしれません。


## 相手の言葉に置き換える
最初の話と一部矛盾をしてしまいますが、概念的な話をする際にはこれをおすすめします。

例えば、masterブランチにmergeする作業の重要さを営業のメンバーに伝えるとき。
* **長い間準備してきた超重要なクライアント相手に商談をするようなもの。**

みたいな例えを用いるとイメージが掴みやすくなります。

そうすると営業のメンバーは
**「そんな重要な仕事であればもちろん提案資料はみんなの事前チェックが必要だ（レビュー）」**
**「プレゼン担当は入念にロープレして様々な反応やストーリーを準備しないと（テスト）」**

このように自分たちの仕事に置き換えることが出来るので、温度感をより共有しやすくなると思います。


## 相手の専門領域に興味を持つ
異なる職種間でのコミュニケーションで一番重要かもしれません。

もしあなたが非エンジニアに対して「エンジニアに関することに全く興味を持ってくれない」と思っていたら、まず相手に興味を持つことをおすすめします。
本当に初歩的な質問でも何でも良いので相手の領域について聞いてみることをおすすめします。




## 最後に
非エンジニアと仕事を進める際に関する記事も書いてますのでご興味あればぜひ御覧ください。

https://qiita.com/Kensuke_Shibata/items/613fbe58fd615cec6ea5

https://qiita.com/official-events/3f21c92121aa125807b4
SQLAlchemy: MariaDB のデータを読む (Read)

## プログラム

```py:maria_read.py
#! /usr/bin/python
#
#	maria_read.py
#					Sep/03/2024
#
# ----------------------------------------------------------------
import sys
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# ----------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
host='localhost'
data_base = 'city'
user ='scott'
password = 'tiger123'
db_url = "mysql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
#

session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
cities = session.query(City).all()
for city in cities:
	print(f'{city.id}\t{city.name}\t{city.population}\t{city.date_mod}')

sys.stderr.write("*** 終了 ***\n")
#
# ----------------------------------------------------------------
```

## 実行コマンド

```bash
./maria_read.py
```

## 確認したバージョン

```text
$ python
Python 3.12.3 (main, Jul 31 2024, 17:43:48) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.50'
```
SQLAlchemy: MariaDB のデータを作成 (Create)

Arch Linux で必要なライブラリーをインストール

```bash
sudo pacman -S python-sqlalchemy
sudo pacman -S python-mysqlclient
```

Ubuntu で必要なライブラリーをインストール

```bash
sudo apt install python3-sqlalchemy
sudo apt install python3-mysqldb
```

## プログラム

```py:maria_create.py
#! /usr/bin/python
#
#	maria_create.py
#
#					Sep/03/2024
#
# --------------------------------------------------------
import	sys
import	string
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# --------------------------------------------------------
def dict_append_proc(dict_aa,key,name,population,date_mod):
	dict_aa[key] = {'name':name,'population':population,'date_mod':date_mod}
#
	return dict_aa
#
# --------------------------------------------------------
def	data_prepare_proc():
#
	dict_aa = {} 
#
	dict_aa = dict_append_proc(dict_aa,'t3321','岡山',519476,'2003-3-20')
	dict_aa = dict_append_proc(dict_aa,'t3322','倉敷',291835,'2003-5-15')
	dict_aa = dict_append_proc(dict_aa,'t3323','津山',863754,'2003-8-18')
	dict_aa = dict_append_proc(dict_aa,'t3324','玉野',469172,'2003-1-9')
	dict_aa = dict_append_proc(dict_aa,'t3325','笠岡',237451,'2003-3-4')
	dict_aa = dict_append_proc(dict_aa,'t3326','井原',518397,'2003-5-21')
	dict_aa = dict_append_proc(dict_aa,'t3327','総社',248156,'2003-7-23')
	dict_aa = dict_append_proc(dict_aa,'t3328','高梁',778294,'2003-10-26')
	dict_aa = dict_append_proc(dict_aa,'t3329','新見',463751,'2003-12-15')
#
	return	dict_aa
#
# --------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
dict_aa = data_prepare_proc()
#
host ='localhost'
data_base = 'city'
user ='scott'
password = 'tiger123'
#
db_url = "mysql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
#
session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
City.__table__.drop(engine, checkfirst=True)
#
session.commit()
#
Base.metadata.create_all(bind=engine)
#
for key in dict_aa:
	print(key)
	unit = dict_aa[key]
	city_a = City(id=key, name=unit['name'], population=unit['population'], date_mod = unit['date_mod'])
	session.add(city_a)
#
session.commit()
#
sys.stderr.write("*** 終了 ***\n")
#
# --------------------------------------------------------
```

## 実行コマンド

```bash
./maria_create.py
```

## 確認したバージョン

```text
$ python
Python 3.12.3 (main, Jul 31 2024, 17:43:48) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.50'
```
【カンタン】PHPで改行を反映させる

# [<font color="#333">改行させて登録した文章を反映させる</font>](#-改行させて登録した文章を反映させる)

こんな感じで改行付きでコメントを登録
![スクリーンショット (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920917/dab42642-33b7-b240-adb3-dc3825480eb9.png)

こんな感じでちゃんと改行させて出力
![スクリーンショット (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920917/40d61b1b-8df5-ac4f-9610-125fe3b6d395.png)



例えばLaravelで普通に出力
これだと改行は反映されない
```app.php
 <p>{{$user->comment}}</p>
```

こう書く
```app.php
 <p>{!! nl2br($user->comment) !!}</p>
```

以上です。

と思いきや、コメントを頂きました。
これだとエスケープされず、悪意のあるスクリプトが実行される恐れがあるそう。
以下に修正が必要
```app.php
 <p>{!! nl2br(htmlspecialchars($user->comment)) !!}</p>
//またはCSSのみ
 <p style="whitespace: pre-line;">{{$user->comment}}</p>
```

@tadsan様からのご指摘です。
ありがとうございました。
自分の無知を知ることが出来る。
Windows Terminal のおすすめ設定2022年4月版

Windows環境のターミナルとしては、Windows Terminalが力をつけてきてる。使いやすい設定を作ってるので、そのメモを残しておく。

### 2022年4月時点ではプレビュー版を使う

ターミナルへのファイルのドラッグ＆ドロップでWSLのパスに変換してくれるのはプレビュー版の機能なので、プレビュー版(バージョン: 1.13.10734.0)を使う。

通常版のWindowsターミナルでWSLに接続した状態で、ターミナル対してファイルをドラッグ＆ドロップすると、

```
$ less C:\Users\yugoy\Downloads\test.rb
```

こんな風にWindowsのパスのまま展開されるけど、プレビュー版では

```
$ less /mnt/c/Users/yugoy/Downloads/test.rb
```

と、WSLのパスに変換してくれる。lessにしろvimにしろ、Linux上のコマンドでWindows上のファイルをいじりたいときには便利な機能なので、プレビュー版を使った方がいい。

プレビュー版はストアからダンロードして入る。

### ペンギンアイコンとUbuntuアイコンの二つのプロファイルがあるけど、ペンギンアイコンを使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53489/0bb21f26-adfa-780a-adff-8887e143c301.png)

Ubuntu20をマーケットから入れると、Windowsターミナルから二つのUbuntuが見える。違いは何かというと、Ubuntu20をWSL2上でインストールすると、Ubuntu20.exeというWindows上の実行ファイルが作られる、それがUbuntu20アイコンのプロファイル。ペンギンアイコンは、wsl.exe経由でUbuntu20のディストリビューションに繋がる経路。

ドラッグ＆ドロップでファイルのパスをLinuxパスに変換してくれるのは、wsl.exe経由（ペンギンアイコン）なので、Ubuntuアイコンのプロファイルは使わない。

設定上に「ドロップダウンからプロファイルを非表示にする」という機能があるので、これをONにすれば、Ubuntuアイコンのプロファイルは非常時になる。

### デフォルトのプロファイルをWSLにする

ターミナルを立ち上げたら最初からWSL上のUbuntuがいい。これも設定(settings.json)で変えれるので、デフォルトプロファイルのGUIDを、WSLのGUIDにしておく（下記は私の例）

```
   "defaultProfile": "{f184b75f-6c82-5ea5-9b3e-3203d66c5f82}",
```

### ショートカットキーを足しておく

タブの移動がctrl+tabしかないので、ctrl+pageDown ctrl+PageUp でタブの左右の移動をしやすくする。

```
        { "command": "prevTab", "keys": "ctrl+pageup" },
        { "command": "nextTab", "keys": "ctrl+pagedow"}
```

これを、settings.json の actionに入れる。

### wsl-terminal はどう？

Windows Terminal を使う前は、WLS1上でwsl-terminalを使っていたんだけど、WSL1とWSL2を共存させた環境だと接続先をうまく切り替える設定ができなくて（調べきれてなくて）、あとは情報もぐっとすくなくなって断念。Windowsパスをwslパスに変換する機能がWindows Terminalプレビューにできたので乗り換えたという経緯です。
【Atom】AtomでAnaconda Powershell Promptを使う

## 環境
+ Microsoft Windows 10.0.22000.613（21H2）
+ Windows PowerShell 5.1.22000.613
+ conda 4.12.0
+ Atom 1.60.0


## 準備
+ Anaconda Powershell Prompt を右クリック →「プロパティ」→「ショートカット」のタブを開く →「リンク先」に書かれているものをコピーしておく。
```:例
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass -NoExit -Command "& 'C:\Users\name\.pyenv\pyenv-win\versions\Anaconda3\shell\condabin\conda-hook.ps1' ; c
```

:::note
「%windir%」を「C:\Windows」に変えないとエラーが出たが、環境によるかもしれない
:::
+ PowerShell のパスをコピーしておく
```:例
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe
```
## 手順
### 1. Platformio Ide Terminal をインストール
https://atom.io/packages/platformio-ide-terminal
#### apm 経由でインストールする場合
```posh:terminal
apm install platformio-ide-terminal
```
#### 検索する場合
`Ctrl`+`,` で Settings を開き、Install タブから `platformio-ide-terminal` を検索

### 2. 設定を開く
Packages タブから `platformio-ide-terminal` を検索し、設定を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/6795c38e-b4ae-79d2-4371-cdcdddf652f7.png)

### 3. コマンドを設定する
Auto Run Command に最初にコピーしたものを、Shell Override にもう一方を貼り付ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/bc192af8-6a26-a0c4-8e50-fdc8eb599be4.png)
Settings を閉じる。

### 4. 確認
画面左下の `+` からターミナルを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/7bf2676a-0d88-de2a-845c-5bb8b32dc2c4.png)
`conda info` と打って情報が確認できれば OK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/bf5789d9-d961-eceb-a300-d661086662a8.png)
Kuramoto-Sivashinsky方程式の紹介(蔵本シバシンスキー方程式)

今回は、Kuramoto-Sivashinsky方程式(蔵本シバシンスキー方程式と表記)について紹介したいと思います。
蔵本シバシンスキー方程式自体、英語の文献が多い印象があり、勉強する際にやや苦労しました。そういった背景があり日本語の記事があったほうが助かるなぁーと思い、今回記事にしようと思いました。


蔵本シバシンスキー方程式は以下の偏微分方程式で表されます。
　
```math
\displaystyle \frac{\partial u}{\partial t}+  \frac{1}{2}\frac{\partial u^{2}}{\partial x}+ \frac{\partial^{2} u}{\partial x^{2}}+ \frac{\partial^{4} u}{\partial x^{4}}=0　　\cdots(1) \\
u(x,t) = u(x+L,t),　u(x,0)=g(x)　　 \cdots(2)
```
　
式(2)は,周期条件と呼ばれるものです。$t=0$の時なので、$g(x)$は初期値関数です。
式(2)に含まれている$L$の値が小さい時は周期的な解が得られますが、$L$の値が大きくなると解が複雑化していきます(カオスともいう)[1]。
$L=2\pi$未満の時は解が0に収束することがわかっています[1]。
以下には$L=22$の場合の解を示している。横軸は時間t、縦軸は領域xを表している。
u(x,t)の値を色で表している。解が複雑化していることがわかる。

![L=22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/07fb875e-2e17-a24e-2470-e3d8609767d0.png)


$L=\pi,1.9\pi,2\pi,2.1\pi,11,15,22,44$の場合の図を一番下に記載してあります。もし良ければご覧ください。$L=2\pi$未満の時は解が0に収束することがわかっており[1]、図からも確認できる。

参考・引用文献
[1]　M.A. Bucci, O.Semeraro, A.Allauzen, G.Wisniewski, L.Cordier, and L.Mathelin,　Control of chaotic systems by deep reinforcement learning
　
　
　

以下$L=\pi,1.9\pi,2\pi,2.1\pi,11,15,22,44$の場合の図になります。
![L=pai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/867366b6-f5af-fea5-65cb-9ea8220e67e5.png)
![L=1.9pai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/f7d73f95-9800-2a11-1f26-874171d68bd8.png)
![L=2pai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/b152d51f-07e5-0032-3602-4eeac0fab7b8.png)
![L=2.1pai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/71898889-e4af-5c59-4354-f6f329853633.png)
![L=11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/cb3bfac5-f644-d067-5bf5-79f5b9a9b375.png)
![L=15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/06802ff9-42d1-25ec-561e-e37ece8bc270.png)
![L=22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/85c0ddd0-5097-e447-e337-794d42626604.png)
![L=44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2594605/2f03e474-32fb-b659-c252-3d19af237896.png)
事件は会議室で起こっているんじゃない、警視庁ホームページで起こっているんだ！

前回は[神奈川県警のホームページがダサい](https://qiita.com/NagayamaToshiaki/items/cda3f4c35b81b78bdada)という話だったが、今回はちょっとだけ触れた警視庁のホームページを検証してみる。

## 問題点・HTML編

### その1：推奨環境が異様に古い

IE9、Safari5がベースラインとなっている。いずれも10年以上前であり、この時点で**警視庁のWebページに対する意識の低さ**が垣間見れる。今は亡きFlashについての情報も載っているし（更新日時が2020年12月なので、Flash廃止に関する情報の更新があった気がするんだけれど）…故に以降の問題があると言っても過言では無い。

### その2：HTML4.01を使っている

なんと、令和4年になってもまだdoctypeがHTML4.01である。HTML5すら過去のものとなって久しいのに。ただ、styleでメディアクエリなどを利用したりしているので、可能な限り新しくしようとしている部分はある？　`class="slider_wp"`とあるからWordPressで作っているみたいだけれど（CSSは4Uwebだが、2009年のものなので昔使っていたものの居抜き？）、バージョン更新ができてないんだろうなあ。

しかし、推奨環境である**IE9の段階でHTML5対応は進んでいる**ので、何故すでにロートルなHTML4でコードを作ったのかは謎である。せめてXHTMLにしようよ。

### その3：`<meta name="viewport">` が2回も設定されている

設定自体は`<meta name="viewport" content="width=device-width,initial-scale=1.0">` なので問題無いが、なぜ多重定義されているのかは不明である。「大事なことなので」というやつか？

### その4：jQueryのバージョンが古い

1.8.2である。今はバージョン3.6.0が最新であるが、バージョン1の最終版である1.12.4ですらない。警視庁はセキュリティ意識をちゃんと持っているのだろうか？　そりゃあ遠隔操作事件で(ry

### その5：スペーサーGIFが使われている

もはや過去の遺物であるスペーサーを利用しているだけでなく、`<a>`要素に`id`や`name`（今や非推奨）を使うなど、古いページの痕跡を感じさせる。値が大文字だし。

Tabでナビゲーションする際も、余計な場所にフォーカスが移動するため、何も知らないユーザーには混乱しか生まない。

また、ヘッダー（LSHTMLじゃないので`<header>`要素が使えない！）には、わざわざ「サイトメニューここまで」というのを示すスペーサーGIFが設定されており、トホホである。セマンティックHTMLさえあればすべて解決するのに！

### その6：過剰なclearfix

clearfix（もちろん`content: "."`とやり方が古い）も、今やflexやgridなどを使えば不要なものであるが、ヘッダー`#headbg`では、左右に要素を配置するわけでもないものにclearfixをかけており、単にコードの無駄である。

また、過剰な入れ子が発生しているうえに、それぞれの要素にclearfixをかけているなど、コード自体に手慣れていない感が満ちている[^1]。デザイン的にはちゃんと外部に発注しているのは分かるけど、なんでこんなつたないコーディングなの？

### その7：`id`の重複

PC用検索フォームとスマフォ用検索フォームで検索キーワード要素のidが重複している（ちなみに`id="kensaku"`）。これはうっかりやりがちなミスなので我々も気を付けたい。

もっとも、データ量的には同じ要素をレスポンシブで表示を切り分けるのがベターであるが。

### その8：ボタンライクリンクのコードが奇々怪々

なんと、`<a>`要素の周りを3つの`<div>`が囲んでいる。それぞれ下、上、`<a>`を囲む形でスタイリングされており、特に最後のやつは省略できる！　デザイナーはスタイルを作って、コードが適当である。透明な背景もついているし（当然データの無駄！）。

### その9：新着情報とお知らせでマークアップが一貫していない

新着情報は`<ul>`を使ったリストであり、お知らせは`<div>`内に`<p>`を使う形式だ。当然前者の方がベターだ。わざわざマークアップを変える必要はあったのだろうか？

## 問題点・CSS編

### その1：要素の連結がある

たとえば、`div#head1bg`という指定があるが、これではリファクタリングの際に`id="head1bg"`という要素のセマンティクスに基づく最適化ができなくなってしまう。このような書き方はいたずらに詳細度を高めるだけなので、改めるべきである。

### その2：検索画面の`font-family`がメイリオ

Macのデフォルトに入っている日本語フォントが全く指定されておらず、考慮が足りていない。

### その3：メイン画像の横幅が大きい

百歩譲って、レスポンシヴデザインを採用していないのは認めよう。しかしなんで横に画像がはみ出てるんだ？　しかも幅が1440pxだ。おかげで小さい画面だとせっかくの画像が隠れてしまうではないか！

[^1]: レイアウト的に境界線は全幅必要だけど、中身は幅を狭めたいという場合の致し方ない（どうせならCSSで解決できないかな）`<div>`の入れ子は存在する。本来は`<hr>`を使うべきなんだろうけど。

## 良い点

フォントサイズを決め打ちしていないので、ブラウザのフォントサイズ変更にも柔軟に対応できる。割と見過ごされている問題で、これからのWebではきっちり対応する（もしくはあえて避ける）必要がある。しかし、横幅がpx指定なので、デザインが破綻する可能性は高い。できればremを使ったページ作りに変更していきたい。

## まとめ

神奈川県警よりも面白みが無い記事になった。CMSを使って作っているらしく、正直jQueryとHTMLのフォーマットを最新化してセマンティックに作り直し、不要な`<div>`囲いを外すくらいしか改善点を見いだせない。古臭いけど、あんまりデザインを変えても混乱するだけだしなあ。
CPU

復習回数1
## CPU
<font color = 'blue'>CPU(プロセッサ)</font> - 制御装置と演算装置を合わせたもの。
　　　　　　　　　性能は主に、クロック周波数とバス幅で表される。<br>
## クロック周波数
コンピュータ内部で発生する規則性を持つ電圧で、一定間隔の「高」「低」を繰り返す信号
これがコンピュータの動作の基準となる、<font color = 'blue'>クロック信号(クロックパルス)</font> 。
クロック信号の「高」「低」のサイクルが１秒間に繰り返される回数を<font color = 'blue'>クロック周波数</font> という。
単位として<font color = 'blue'>Hz(ヘルツ)</font>が使用される。

CPU内部のクロック周波数は<font color = 'blue'>内部クロック</font>、CPUと主記憶などの周辺回路を結ぶ伝送路のクロック周波数は<font color = 'blue'>外部クロック</font>という。
内部クロックは外部クロックの数倍の速度で動作する。
一般的に、<font color = 'blue'>同一種類のCPUであればクロック周波数が高いほど処理能力が高くなる。しかし、主記憶やハードディスクなどの性能も関係してくるため、クロック数を2倍にすれば、システム全体の2倍になるわけではない。</font>

## バス
CPUや主記憶、キャッシュメモリなどで、お互いがデータの送受信するための伝送路のことを<font color = 'blue'>バス</font>という。
一般的に、<font color = 'blue'>バス幅が広く、クロック周波数が大きいほど、高速にデータを送受信することができる</font>



<br>
参考文献 : イメージ＆クレバー方式でよくわかる 栢木先生の基本情報技術者教室
vuejs 배열에서 항목삭제하기

기존방식같기는 하지만 부모컴포넌트에서 자식컴포넌트에 이벤트를 전달하는 방식
```vuejs:HomeVue.vue
<template>
  <v-container>
    <v-col>
      <ListView
        :todolist="todolist"
        @statusControl="statusControl"
        @deleteItem="deleteItem"
        @editItem="editItem"
      />
    </v-col>
    <v-col>
      <ListAdd @listAdd="listAdd" />
    </v-col>
  </v-container>
</template>

<script>
import ListAdd from '@/components/ListAdd.vue';
import ListView from '@/components/ListView.vue';
export default({
  name: 'HomeView',
  components: {
    ListAdd,
    ListView

  },
  data() {
    return {
      todolist : [],
    }
  },
  methods : {
    deleteItem(index){
      this.todolist.splice(index,1)
    },
  }
});
</script>

```
Vuex store 를 활용해서 배열삭제하기
1. 삭제할 배열을 담을 items[]선언한다.
2. mutation 에서 delItem(state, index) 함수를 만든다,.
3. mutation 에서 만든 함수를 action 애서 불러온다. 

```vuejs
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);
Vue.config.devtools = true;
export default new Vuex.Store({
  namespaced: true,
  state: {
    //data 삭제할 아이템을 담는 배열 선언
    items: [],
  },
  mutations: {
    delItem(state, index) {
      state.items.splice(index, 1);
    },
  },
  actions: {
    delItem({ commit }, id) {
      commit("delItem", id);
    },
  },
});
```

실제 장바구니에 담긴 상품을 삭제하는 component

```vuejs:CartList.vue
<template>
  <div>
    <div class="header-cart header-dropdown">
      <ul class="header-cart-wrapitem">
        <template v-for="(item, index) in items">
          <li :key="index" class="header-cart-item">
            <div class="header-cart-item-img" @click="delItem(index)">
              <img :src="item.image" alt="IMG" />
            </div>
          </li>
        </template>
      </ul>     
    </div>
  </div>
</template>

<script>
import { mapState, mapGetters } from "vuex";

export default {
  computed: {
    ...mapState(["items"]),
    ...mapGetters(["totalPrice", "totalQty"]),
  },
  created() {},
  methods: {
//스토어에 접근해서 dispatch를 통해서 스토어에 있는 함수 delItem을 불러온다.
    delItem(index) {
      this.$store.dispatch("delItem", index);
    },
  },
};
</script>
```
Rのインストール時に気をつけること

## 自分の環境
OS: Windows 11 Home
R version: 4.1.3
Rstudio RStudio 2022.02.1+461

## 症状
新しいPCにRとRstudioを入れたのち、Rstudioでパッケージをインストールしようとしたら、次のような警告が出た。
```error.R
Warning message:
In normalizePath(path.expand(path), winslash, mustWork) :
  path[1]="C:/Users/XXX/OneDrive/??????": ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。
```
パッケージ自体はちゃんとインストールできていた。そして次の別のコマンド（ライブラリ読み込みなど）からはこの警告は出て来ない。
ただ、別のパッケージをインストールすると同じ警告が出てくる。

## 解決策
ネットで調べてみたら、同じ症状の方がいたので、そこで貼られていたリンク先の通りにやったら解決した。

https://teratail.com/questions/367214

要は、Rはデフォルトでホームディレクトリを「ドキュメント」に指定していて、この「ドキュメント」は全角日本語なので警告が出ると、いうことだと理解した。

C:\Users\XXXX　に新しいフォルダ（XXXXはユーザ名。新フォルダの名前は何でもいいが、"R_setting"にした）を作って、
Windowsの環境変数R_USERをC:\Users\XXXX\R_settingにして作成してやると、上の警告は出なくなった。

ホームディレクトリはR_settingに設定されているので、現在のディレクトリを表示すると当然
```ex2.R
> getwd()
[1] "C:/Users/XXXX/R_setting"
```
になる。

## 他に気をつけること
ちなみに・・
そもそも、上のリンク先の記事いわく、RをWindowsのC:\Program Filesにインストールすること自体避けたほうがいいみたい。管理者権限が必要になるといろいろ面倒だから（→追記へ）。
私は、この症状が出たときはProgram FilesにRをインストールしていたので、
RとRstudioを一旦アンインストールして、
C:\Users\XXXX　に再度インストールしてからこの手順を踏んだ。
Program FilesにRをインストールした状態でこれを試したことはないが、環境変数を設定するだけなので大丈夫だと思う。

追記
C:\Program Filesにインストールした状態でRのパッケージをインストールしようとすると「書き込む権限がない」と注意され「代わりにここに書き込むけどええかの？」と聞いてきた先のフォルダ名が日本語（OneDrive内の「ドキュメント」）で、そのせいでエラーが出て結局パッケージがインストールできない、というのが、私の最初の問題だった。この問題はこちらで詳しく解説されていて、

https://qiita.com/Maki-Daisuke/items/0378626c9bf9971f3822

その解決策としてライブラリのパスを設定したりしている。がそもそもProgram FilesにRをインストールしなければ「書き込む権限がない」と怒られる問題は発生しないのだった。
[Ubuntu 20.04] gpg-agentを利用してsvnのパスワードを保存する

# 筆者の環境の説明
- 筆者は、ローカルにあるWindows端末からLinux端末（Ubuntu）にSSH接続し、開発を行っている。
- さらに、ソースコードなどを保存するリポジトリとしてsubversion（svn）を利用している。

# 問題発生の経緯
- 先日まで、Ubuntuのバージョンは18.04を利用していた。
- 18.04を利用していたときは、「gnome-keyring」にsvnのパスワードを保存していて、`$ svn up`などのコマンドを実行する際に、「gnome-keyring」のパスワードを入力する必要があった。
    - ただし、「gnome-keyring」のパスワードの入力は毎回必要なわけではなかった。
    - （おそらく）ログインした後の初回にのみ必要な感じで、SSH接続したターミナルで一度認証すれば、それ以降にパスワードの入力は不要であったため、少々煩わしさはあったがこの状態で運用していた。
- 先日、Ubuntuのバージョンを18.04から20.04にアップグレードした。
- すると、`$ svn up`するたびに毎回「svn」のパスワードが求められるようになってしまった。
- さすがに毎回「svn」のパスワード入力するのは煩わしすぎたため、問題に対処することにした。
- 原因を探っていくと、どうやら「gnome-keyring」に保存されているパスワード情報を上手く利用できていないようであることがわかった。
    - `$ seahorse`コマンドで「パスワードと鍵」を立ち上げると、パスワードがロックされている状態で、これを解除することができなかった。（パスワードの削除は可能、作成は不可だった。）
    - この原因はよくわからなかった。どこかで設定したセキュリティポリシーの影響もあるかもしれないし、SSH接続では解除できない仕様になったのかもしれない。
    - ちなみに`$ sudo seahorse`を実行して立ち上げた「パスワードと鍵」では、パスワードを保存することができた。
        - `$ sudo svn up`とsudoを付けてコマンド入力した場合のユーザーやアドレス情報は、このrootの「パスワードと鍵」に保存されるようだ。

# 解決策
- どう頑張ってもリモート接続している限りは「gnome-keyring」の問題を解決できそうになかったので、「gpg-agent」によるパスワードの保存を利用することを考えた。
- 理由は、svnの設定などが`~/.subversion/`に保存されているのだが、`~/.subversion/config`を見ると、以下のようにLinuxの場合は3つから選べるようになっていたためである。
    - 後になってわかったことだが、使用しているUbuntu-20.04では「gpg-agent」が利用できない状態だった（インストールされていなかった）ため、次点の「gnome-keyring」が利用されていたようである。
```text:~/.subversion/config
[auth]
### Set password stores used by Subversion. They should be
### delimited by spaces or commas. The order of values determines
### the order in which password stores are used.
### Valid password stores:
###   gnome-keyring        (Unix-like systems)
###   kwallet              (Unix-like systems)
###   gpg-agent            (Unix-like systems)
###   keychain             (Mac OS X)
###   windows-cryptoapi    (Windows)
# password-stores = gpg-agent,gnome-keyring,kwallet
```

- 具体的な解決方法は以下を参考にした：
    - https://www.dhiller.de/2018/10/04/svn-gpg-agent.html
- まず、「gnupg-agent」をインストールする。
```
$ sudo apt install gnupg-agent
```
- 次に「pinentry-tty」をインストールし、これが利用されるように構成する。
```
$ sudo apt install pinentry-tty
（略）
$ echo "pinentry-program /usr/bin/pinentry-tty" >> ~/.gnupg/gpg-agent.conf
$ gpg-connect-agent reloadagent /bye
OK
```
- `~/.bashrc`に以下の内容を記載する。
```bash:~/.bashrc
GPG_TTY=$(tty)
export GPG_TTY
## 参考先には、以下も記載されていたが、ログイン時に
##「gpg-agent: gpg-agentは既に実行されています - 新しいものをスタートさせません」と表示されたので、
## おそらく不要だと思われる。以下の動作確認でもコメントアウトした状態で動作した。
# eval $(gpg-agent --daemon)
```
- `~/.subversion/config`の該当箇所を以下のように編集する。
```text:~/.subversion/config
[auth]
password-stores = gpg-agent
```
- `~/.subversion/servers`の該当箇所を以下のように編集する。
```text:~/.subversion/servers
[global]
store-passwords = yes
store-plaintext-passwords = no
```
- ここまで完了したら、既にチェックアウトしてあるローカルのディレクトリのどこかで`$ svn up`を実行する。
- すると、初回の認証情報が求められるが、以降は求められなくなり、無事問題は解決された。
抽象度を上げて業務で得た知識を外部にアウトプットしよう！

## はじめに

https://fortee.jp/phperkaigi-2022/proposal/5989fb95-cea8-4785-91d1-90e94fdd9193

本記事はPHPerKaigi2022のプロポーザルに提出し不採択となった
「抽象度を上げて業務で得た知識を外部にアウトプットしよう！」
についての記事です。
開発メンバーにこの話をしたら「その話単純に興味ある」って言われたので不採択ではありましたが記事にすることにしました。

## 概要

成長するためにアウトプットというのは非常に重要ですが僕のまわりでは
* プライベートで開発ほとんどしてないからネタがない
* 公開できるようなネタがない
* とにかくネタがない

ということが非常に多いです。

僕も最近はプライベートで開発できてないので、めちゃくちゃ気持ち分かります。
でも我々は日々業務で技術に触れていますし、日々学んでいますよね？
だったらそれをアウトプットすればいいのです！

もちろん業務で得た知識をそのまま一般公開することはできませんし危険です。
外部に出してはいけない情報もあるでしょうし、場合によっては情報漏えいにも繋がります。
そういう知識をアウトプットするには「抽象化する」ことがとても重要です。

本記事では「知識の抽象化」の仕方を実際に僕が経験したことを例に説明します。
この記事で少しでもアウトプットへのハードルが下がると嬉しいです！

## 抽象とは

> 事物または表象からある要素・側面・性質をぬきだして把握すること。⇔具象／具体。→捨象
[weblio辞書より](https://www.weblio.jp/content/%E6%8A%BD%E8%B1%A1)

ある業務上で得た知識があったとします。
それの要素・側面・性質だけに着目し「ここの知識は普遍的」という部分を見つける力のことです。

## 例1

ある問い合わせ調査でログを見たとします。
あなたはログのあるサーバーには初めて入りました。
ログのある場所も分からず先輩に教えてもらいながらログに辿り着き、ログの見方を教えてもらい、「この時間にこのログが出てるから原因はこれだね」ということで調査が完了しました。
あなたが得た業務知識としては
1. ログのあるサーバーの場所
1. ログサーバーへの入り方
1. ログファイルが置いてある場所
1. ログの見方
1. ログからその調査で必要な情報の得方

などが挙げられると思います。
この例で言うと1~5全て外に出してはいけない情報です。
業務で使っているプロダクトのサーバーなので秘匿情報ですし、入り方を教えてはいけません。
これは具体的な知識に該当します。

ではこれを抽象化して外に出していい知識とは何でしょうか？
例えば2に関して。
そのログサーバーへの入り方は教えてはいけませんが「単純にサーバーに入る」ということに関しては普遍的な話なのでアウトプットして問題ありません。
「sshコマンドの使い方」というまとめ方でもいいでしょうし
「.ssh/configの書き方」でも良いと思います。
（当然具体的なhostnameやUser, Portは伏せて）

4に関してもログを見るためのコマンドの使い方でまとめてもいいでしょう。
tailなのかcatなのかlessなのか。
もしくはgrepなのかzgrepなのか。
そういう「ファイルを開くコマンドの使い方」「重いファイルを開かずに該当の部分だけを探し出す方法」とか。
こういう側面を見つけてあげるのが抽象化です。

## 例2

僕が実際に記事にアウトプットしたこの記事を例にします。

https://qiita.com/yamamoto_hiroya/items/f6924fff88ca402164ba

これは元々Googleスライドで作成し所属部署のLTにて共有したネタでした。
中身では自分がその時に開発していた実際の案件を例にしていました。
まず開発のコツについて。
「こういう開発要件で、まずファーストコミットはこんな感じで…」
と自分が開発していった順序を説明するスライドでした。
もちろん実際のプロダクトコードは外に公開できません。
ただ今回のケースですと「開発手順やコツ」は抽象化され、外に出して良い情報となります。
その結果、その手順とコツを示すために似たような例で別の架空のサンプルコードを作成し、それに対する開発手順を説明する記事となりました。

ソースレビューのコツの方も同様です。
その時実際の業務でレビュー担当していた案件を例に取り上げています。
それをそのまま公開することはできませんが、「レビューの仕方や工夫したところ」は公開できます。
今回はレビュー時に気になった部分はコメント文でガンガン書いていく、という点が工夫点なのでこれが公開できます。
例のごとくレビューする対象ソースは架空のサンプルコードに置き換えています。
（この時はモンハンにハマっていたのでモンハンの例に変えたサンプルコードになっていますね）

こうすることで実際の業務で得た知識を外部にアウトプットすることができるようになります。

## 抽象化のコツ

経験といえば経験なんですが、コツとしては「**次の案件/他の案件でも使える知識かどうか？**」を考えるのが良いかと思います。
今の目の前の業務や類似の業務だけでなく、全く違う次の業務でも使える知識かどうかは普遍的な知識であることが多いです。
また、サンプルコードを多く書くことも大事ですね。
これが書けると具体的なプロダクトコードから話したい部分にフォーカスしたサンプルコードの生成ができるようになります。
この力はアウトプットのためだけではなく、不具合やバグの再現するための最小コードを生成する時などにも役に立ちます。

## まとめ

アウトプットとは何か特別なネタが必要なものではありません。
日々インプットされた技術や知識を、どういう形で外に出すか、という話です。
という訳でタイトル回収です。
**抽象度を上げて業務で得た知識を外部にアウトプットしよう！**
構造屋(architect）になるための訓練

# はじめに

新入生、新人が構造屋(architect）になるための訓練という趣旨と、
自分が本当に構造屋かという確認のための訓練という２つの意味がある。

データをいろいろつける予定です。

新人プログラマ応援 - みんなで新人を育てよう！

https://qiita.com/official-events/3f21c92121aa125807b4

今、Qiitaでは、「データに関する記事を書こう！」という行事をやっている。

https://qiita.com/official-events/30be12dd14c0aad2c1c2

この文章は、テーマ2『データに関する記事を書こう！』参加記事でもあります。

# 構造屋(architect）

体系的な設計ができるようになるには、
物事を３つ以上の視点で見えるか、
３つ以上の測定項目で計測可能であることが大事である。

ここでは、９つの視点を提供する。
仕事で従事してきた内容か、その分野のソフトウェアに関係してきた知見を整理する枠組みである。

９つの分野を、それぞれにさらに同じ分野で再分類するという二重構造を設定する。
自分が従事した分野に限定して記載しており、他の分野、分類が価値がないというわけではない。

自分が積極的に関係した分野を整理していくと、どの分野のシステムは、どういう構造がいいかが見えてくる。

ありとあらゆる分野で共通な枠組みを作る努力は貴重である。
特定の分野に限定した枠組みづくりと、交互に行うとよいかもしれない。

一つの分野の構造が、他の分野でも相似で有用な場合があるかもしれない。
３つ以上の分野を経験しなくても、天才なら大丈夫かもしれない。

凡人は天才、秀才と違うことをして生きていく

https://qiita.com/kaizen_nagoya/items/0502aebb7610fef584f5


秀才は３つ、凡才は９つということにしてみた。


| |水道|食糧|医療|確率|離散|教育|組織|国際|規格|
|:----|:----|:----|:----|:----|:----|:----|:----|:----|:----|
|水道|1|11|20|29|38|47|56|65|74|
|食糧|2|10|21|30|39|48|57|66|75|
|医療|3|12|19|31|40|49|58|67|76|
|確率|4|13|22|28|41|50|59|68|77|
|離散|5|14|23|32|37|51|60|69|78|
|教育|6|15|24|33|42|46|61|70|79|
|組織|7|16|25|34|43|52|55|71|80|
|国際|8|17|26|35|44|53|62|64|81|
|規格|9|18|27|36|45|54|63|72|73|


Aという分野のBという視点と、Bという分野のAという視点が、同じことを指すかもしれない。

構造屋（アーキテクト）になるための訓練は、土木・建築関係がいいという意見がある。

これから、８１項目の記事を書く予定。ひとまず、最初の９つのみだしごとに何か書くかURLをつける。



# 1. 水道と衛生
水道事業に１０年従事した。
水道、下水道などの水に関する事業は衛生事業の一つである。
大気、振動、騒音などの公害の区分の一つでもある。

# 2. 食糧と機械
農業、水産業、牧畜などでは、農業機械、食品機械事業の設計環境の構築を主に担当した。
DSPの利用、GPUの利用に伴うコンパイラ、ライブラリの整備などである。

# 3. 医療と技術
遺伝子解析、機械学習など、医療に関する技術の基礎的なシステムを考える。

「DNAと遺伝情報の物理」伏見譲。統計と確率(20)

https://qiita.com/kaizen_nagoya/items/150646f72c55a36f8c39

# 4. 確率と統計

確率論及統計論輪講。仮説(95) 統計と確率(9)

https://qiita.com/kaizen_nagoya/items/89d0a91a56d33529e85c

# 5. 離散と連続

連続と離散、時間と空間、物理量と生物量。統計と確率(2)

https://qiita.com/kaizen_nagoya/items/d0980c6bf9d3079aa98d

# 6. 教育と育児

時間外は子育て。「 10年後のために今勉強しておきたい技術」は勤務時間内だけで。

https://qiita.com/kaizen_nagoya/items/0ad5c118a5be4d36b4d8

# 7. 組織と経済

プログラマが違和感を感じたときにするとよいこと。仮説（148）

https://qiita.com/kaizen_nagoya/items/f32ae742655621b309fb

# 8. 国際社会と歴史

アメリカ留学、アメリカ就職の代わりに行ったこと。行なっていること。英語(33) 仮説(111)

https://qiita.com/kaizen_nagoya/items/9f8e791bd6be3bed34bb

# 9. 規格と安全
（IT）業界における国際規格等の利用。仮説（22）

https://qiita.com/kaizen_nagoya/items/0e2ab72fbddc391d4f41

安全（0）安全工学シンポジウムに向けて

https://qiita.com/kaizen_nagoya/items/c5d78f3def8195cb2409

# 参考資料

@torifukukaiou【毎日自動更新】新人プログラマ応援 - みんなで新人を育てよう！（2022年04月） LGTMランキング！

https://qiita.com/torifukukaiou/items/18dad64ba99aa5a40f95

@torifukukaiou 【毎日自動更新】データに関する記事を書こう！ LGTMランキング！

https://qiita.com/torifukukaiou/items/b10fa94764aaaa2c6db1
Flutter path_provider + _firebaseMessagingBackgroundHandler でエラー

もぉぉぉ

Flutter path_provider + _firebaseMessagingBackgroundHandler でExceptionのエラーが出た場合の対処法ですが

_firebaseMessagingBackgroundHandler の中に、下記を追記

if (Platform.isAndroid) PathProviderAndroid.registerWith();
if (Platform.isIOS) PathProviderIOS.registerWith();

で直りました。yamlに

  path_provider: ^2.0.9
  path_provider_android: ^2.0.12
  path_provider_ios: ^2.0.8

の追加も必須。
await を使わず node-fetch をつかって、画像をダウンロードして Base64 Data URI として取得する方法

# 概要

**await を使わずに**、node-fetch をつかって、画像をダウンロードして **Base64 Data URI** として取得する方法 　です。

（async ついてない関数内でやらないといけないシチュエーションにて）

## 環境
- ES6～
- Node.js v14～
- node-fetch v2～

# コード例

```js
import fetch from "node-fetch";

const url = 'https://example.com/something.jpg';

fetch(url)
    .then(response => {
        return new Promise((resolve, reject) => {
            if (!response.ok) {
                // - サーバーエラーが発生
                reject(new Error(`Server Error, status:${response.status} statusText:${response.statusText}`));
            }
            const contentType = response.headers.get('content-type');
            response.arrayBuffer().then(data => {
                resolve({contentType, buffer: Buffer.from(data)});
            }).catch(reject);
        });
    })
    .then(data => {
        const {contentType, buffer} = data;
        const base64str = buffer.toString('base64');
        return `data:${contentType};base64,${base64str}`
    })
    .then(dataURI => {
        console.log(dataURI);
    })
    .catch(error => {
        // エラーのハンドリングをする
        console.log(`Error occurred`, error);
    });


```