OmniAICreator/Qiita-1.07M huggingface dataset:
AWS公式資料で挑むSCS認定(4)-サービス勉強順

[前回] [AWS公式資料で挑むSCS認定(3)-対象サービス攻略](https://qiita.com/mingchun_zhao/items/3c93d2c1f39ee8badc07)

## はじめに

今回から、サービスを一つずつ理解していきますが、
その前に、それぞれの目的や依存関係を加味し、勉強順つけようと思います。
「xxxサービスを真っ先に」名人からお勧めの一言ほしい。。。

## サービスの勉強順序を決める

一旦、カテゴリ三つに分けました(あくまで個人の理解と独断です)。
サービス名は、略称または先頭の「Amazon」「AWS」を省きました。

### 超重要

自分の中で一番力を入れたいトップ3

- IAM
    - アクセス制御
    - AWSセキュリティの土台で超超超重要

- VPC
    - 仮想ネットワーク
    - サービスはVPC上で連携しながら動く、データ通信が盗聴されたら。。。

- KMS
    - 暗号化キーの作成・制御
    - 機密情報の暗号化に使うキーが攻撃者の手に渡ったら。。。

### 重要

セキュリティ対策に欠かせない、と思われるもの

- Cloudwatch
- CloudTrail
    - システムログやイベント収集
    - 操作履歴を記録しておかないと、セキュリティ始まりませんので
    - 両者の違いはなんだ?(自分の宿題)

- WAF
- Network Firewall
    - ファイアウォール
    - 入り口でサイバー攻撃を止めてくれる優れもの

- Shield
    - DDoS攻撃対策
    - 攻撃者が複数機器を乗っ取り一斉攻撃、過剰負荷でサービス停止の恐れ

- ACM
    - 証明書発行・管理
    - SSL/TLS証明書を簡単にプロビジョニング、管理、デプロイ

- Single Sign-On
- Cognito
    - 認証・認可
    - 認証が攻撃者に突破されたら、CIA(機密性・完全性・可用性)破綻の恐れ


### 普通

- Macie
- GuardDuty
- Inspector
- Detective
    - 不正アクセスの検知・監視・分析

- Audit Manager
- Security Hub
- Trusted Advisor
    - セキュリティ診断・監査

- Systems Manager
- Firewall Manager
- Config
- Organizations
    - 管理・設定ツール

- CloudHSM
    - 暗号用ストレージ
    - ハードウェアセキュリティモジュール(HSM)で暗号化キー保管や暗号化タスク実行

- Directory Service
    - Microsoft Active Directory(AD)
    - ADをAWSの他のサービスと併用したい場合

## おわりに

サービスの勉強をスムーズに進めるため、優先順位付けてみました。
各々のサービスが、AWSセキュリティ4点方針「防止、検出、対応、修復」
いずれかの実現を目的としていることも、再確認できました。
次回は、IAMの勉強に入ります。お楽しみに。

[次回] [AWS公式資料で挑むSCS認定(5)-IAM](https://qiita.com/mingchun_zhao/items/eb89dd1a4d0695dbe7cb)
なんとなく使っているカラーコードについて

色の指定方法は2通り存在する
①直接色の名前をかく
'red'
②＃で三桁または六桁で書く
'#123' '#123456'
※六桁の割合について
・最初の二桁は赤の割合
・次の二桁は緑の割合
・最後の二桁は青の割合

※三桁の割合について
'#ffffff' →　'#fff'
'#112233' →　'#123'
2桁ずつが同じであれば省略できる

色は16進数で数える→10進数では足りないから
０１２３４５６７８９abcdef
torchvisionの画像分類モデルをCoreMLに変換する

#事前トレーニング済みモデルをCoreMLの画像分類モデルに変換してiOSで使う方法です
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/f169fe57-622c-277c-e7b8-1d352563aa6a.png", width=600>

#画像分類モデルを変換したい
そのままTorchVisionの画像分類モデルを変換すると、出力は１０００の数値になります。
これを、信頼度のパーセンテージに直し、画像分類モデルとしてプレビューできるようにしたい。

#クラス名とソフトマックス層を追加する
クラス名とソフトマックス層を追加すれば、１０００クラス内のクラスごとの信頼度のパーセンテージが得られ、xcodeのプレビューも使えます。

#方法

torchvisionからモデルをダウンロード。

```python
import torchvision.models as models

regnet_y_400mf = models.regnet_y_400mf(pretrained=True)
```

%表示のためにソフトマックス層を追加したラッパーモデルクラスを作る。

```python
import torch.nn as nn 

class RegNetClassificationModel(nn.Module):
    def __init__(self):
        super(RegNetClassificationModel, self).__init__()
        self.layers = nn.Sequential(
            regnet_y_400mf,
            nn.Softmax(dim=1)
        )
    def forward(self, x):
        return self.layers(x)

model = RegNetClassificationModel().eval()
```

ImageNetのクラスラベルをダウンロードして、リストにし、リストからCoreMLのClassifierConfigを作る。

```python
import urllib
import coremltools as ct

label_url = 'https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt'
class_labels = urllib.request.urlopen(label_url).read().splitlines()
class_labels = class_labels[1:] # remove the first class which is background
assert len(class_labels) == 1000

for i, label in enumerate(class_labels):
  if isinstance(label, bytes):
    class_labels[i] = label.decode("utf8")
classifier_config = ct.ClassifierConfig(class_labels)
```

変換。

```python
ex_input=torch.randn((1,3,224,224))
traced = torch.jit.trace(model,ex_input)

mlmodel = ct.convert(traced,inputs=[ct.ImageType(shape=ex_input.shape,bias=[-0.485/0.229,-0.456/0.224,-0.406/0.225],scale=1.0/255.0/0.226)],classifier_config=classifier_config)
mlmodel.save("regnet_y_400mf.mlmodel")
```

これでXcodeでプレビューできます。

iOSでの使い方

```swift
let model = try! regnet_y_400mf(configuration: MLModelConfiguration()).model
let vnModel = try! VNCoreMLModel(for: model)
let request = VNCoreMLRequest(model: vnModel)
let handler = VNImageRequestHandler(ciImage: ci1, options: [:])
try! handler.perform([request])
let result = request.results?.first as! VNClassificationObservation
print(result.identifier,result.confidence)
```

>king penguin 0.61...

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
Pony 試乗記(８) Corral で依存管理

# はじめに

正規表現を使えるようになれば日頃 Python で書いているツールを Pony で書くこともできそうです。
[正規表現ライブラリ](https://github.com/ponylang/regex)を Corral を使って依存ライブラリとして登録できるということなので試してみます。

# Corral インストール

https://github.com/ponylang/corral の記述に従って、 Corral をインストールします:

```
$ ponyup update corral release
```

以下のようにインストールされました:

```
$ ponyup show corral
corral-release-0.5.6-x86_64-linux *
```

# プロジェクトの作成

さらに https://github.com/ponylang/corral の記述に従って、プロジェクトを作成します。

## プロジェクトディレクトリ作成と corral init 実行

プロジェクトを置くディレクトリを作成し、その上で corral init を実行します:

```
$ mkdir プロジェクト名
$ cd プロジェクト名
$ corral init
```

corral init 実行によって、ファイル corral.json および lock.json が作成されました。

## 依存の追加

libpcre2 を使った正規表現ライブラリ https://github.com/ponylang/regex を依存ライブラリとして追加しました（libpcre2-devが入っていない場合、https://github.com/ponylang/regex の記述に従ってインストールが必要です）:

```
corral add github.com/ponylang/regex.git
```

指定した URL が corral.json に追加されました:

```
$ grep regex corral.json
      "locator": "github.com/ponylang/regex.git",
```

corral update を行っておきます:

```
$ corral update
```

## プログラム作成

追加したライブラリを使用するプログラムを書いて、作成したディレクトリに置きます。

標準入力を行単位で読み取り、引数に与えられたパターンにマッチする行のみを表示する、grep 的なものを作って見ました。


```pony

"""
grep 的なプログラム
"""

use "buffered"
use "regex"

class RegexFilter is InputNotify
  let _env: Env
  let _rb: Reader
  let _r: Regex
  new create(env: Env, pattern: String) ? =>
    _env = env
    _rb = Reader
    _r = Regex(pattern)?
  fun ref apply(data: Array[U8] iso) =>
    """
    与えられたバイト列を行単位の文字列として切り出したうえで、パターン検索を行う。
    パターンにマッチする行を表示する。
    """
    _rb.append(consume data)  // 入力バイト列をバッファに追加していく
    try
      while true do
        let line: String = _rb.line()?  // バッファから行単位で取り出す
        _print_line_if_match_regex(line)  // 取り出した行を検査
      end
    end  // バッファに行がなくなったら戻る
  fun ref _print_line_if_match_regex(line: String): None =>
    """
    与えられた行文字列がパターンにマッチしたら表示する。マッチしなければ無視する。
    """
    let iterator = _r.matches(line)
    if iterator.has_next() == true then
      _env.out.print(line)
    end

actor Main
  new create(env: Env) =>
    try
      let pattern = env.args(1)?
      try
        env.input(recover RegexFilter(env, pattern)? end)
      else
        env.out.print("pattern not acceptable: " + pattern)
      end
    else
      try
        env.out.print("usage: " + env.args(0)? + " pattern")
      end
    end
```

プロジェクトディレクトリ上で以下を実行すると、依存ライブラリを解決したうえでコンパイルが行われます:

```
$ corral run -- ponyc
```

ディレクトリ名が生成されるバイナリの名前として用いられるのは ponyc コマンド投入でのコンパイルと同じです。

# まとめ

corral を使って依存ライブラリを含むプログラムをコンパイルしてみました。
Maven や Gradle みたいなものを想像していたのですが、簡単に使用することができました。
iPhoneアプリの基本Menuを作成(#1構成編)

XCode12を使用したSWRevealViewControllerによるサイドバーメニューの作成。
下記の様なスライド式のメニュー。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/84c0d3bb-8889-5dee-eaa1-013adcdfa24f.png" width="40%">
xcode内のStoryboardの構成は下記様です。
![スクリーンショット 2022-02-23 5.11.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/98e4578a-b1f4-b484-05ea-0527478bcbe4.png)
メニュー概要
AnimalNoteと言うアプリ（ペットの医療情報管理）の最小メニュー構成。
Menu1 AnimalNoteアプリ部。
Menu2 最新情報アプリの最新情報Webサイト表示部。
Menu3 アプリ利用者QR登録、及び操作マニュアルサイト表示部。
上記のような構成として作成。
参考サイト（YouTubeサイト参考に作成）
https://www.youtube.com/watch?v=EWDNScxZ0YU&t=1220s
次回は作成準備等をYouTubeにて解説。
2022/2/23主にITとかセキュリティの記事

「EC-CUBE」に脆弱性 - 危険度は「低」
https://www.security-next.com/134350

Foxit製PDF製品に複数の深刻な脆弱性 - アップデートを
https://www.security-next.com/134324

NoSQL分散データベース「Apache Cassandra」に脆弱性 - 特定構成に注意
https://www.security-next.com/134322

マット販売サイトに不正アクセス -顧客情報流出の可能性
https://www.security-next.com/134330

BONOのデザインレビューでUI設計への理解が深まった話(2/21)
https://note.com/hayashirine/n/n0e3b85af63b7

無償で使えるセキュリティソフトやサービス一覧公開、米セキュリティ当局(2/21)
https://news.mynavi.jp/techplus/article/20220221-2277152/

欧州IAB に GDPR 違反の指摘、どう対応する？：「爆弾並みの衝撃だ」(2/21)
https://digiday.jp/platforms/like-an-atomic-bomb-so-what-now-for-the-iabs-gdpr-fix-after-regulator-snafu/

Macをシャットダウンしなくていい4つの理由(2/20)
https://www.gizmodo.jp/2022/02/452114e0-a071-41a0-840f-e822d246632a.html

ワードプレス講座③：ワードプレスの魅力とメリット①(2/21)
https://agora-web.jp/archives/2055203.html

KnowBe4、セキュリティ対策の現状とアプローチの違いに関する欧米でのアンケート調査の結果を発表　〜日本企業は欧米企業に比べて数年遅れを取っている(2/21)
https://securityinsight.jp/news/13-inbrief/4934-220221-1

Wi-Fiの「外部アンテナ」はこう調整して活用しよう！ 「外付けの良さ」にこだわるTP-Linkに聞いてみた(2/21)
https://internet.watch.impress.co.jp/docs/column/shimizu/1383317.html

「知らないおじさん」は危険　警察が産業スパイ対策(2/21)
https://www.sankei.com/article/20220221-MZD5JPNELJI5LOM6QDG5M3KFC4/?ownedutm_source=owned%20site&ownedutm_medium=referral&ownedutm_campaign=ranking&ownedutm_content=%E3%80%8C%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E3%81%8A%E3%81%98%E3%81%95%E3%82%93%E3%80%8D%E3%81%AF%E5%8D%B1%E9%99%BA%20%E8%AD%A6%E5%AF%9F%E3%81%8C%E7%94%A3%E6%A5%AD%E3%82%B9%E3%83%91%E3%82%A4%E5%AF%BE%E7%AD%96

初心者必読。NFT・仮想通貨・メタバースで利益を得るための入門ガイド(2/21)
https://www.businessinsider.jp/post-250564

あなたの知らないMDM（マスターデータ管理）の世界--MDMの正しい使い方第3回：分断された世界をつなぐMDM(2/21)
https://japan.zdnet.com/article/35183676/

「ウイルスバスター for Mac」で権限昇格の脆弱性。すでにアップデートで対処済み(2/21)
https://pc.watch.impress.co.jp/docs/news/1389785.html

ロシアとウクライナの緊張に関連するサイバー脅威に勧告、NCSC-NZ(2/20)
https://news.mynavi.jp/techplus/article/20220220-2276112/

自動車データ流出を危惧する中国　地理情報を敵国に握られる恐怖＝山崎文明(2/21)
https://weekly-economist.mainichi.jp/articles/20220301/se1/00m/020/057000c

Googleも頼るテープ保存　対サイバー・省電力で再注目(2/21)
https://www.nikkei.com/article/DGXZQOUC042SO0U2A200C2000000/

Skype、米国で緊急通話発信が可能に(2/20)
https://www.zaikei.co.jp/article/20220220/661131.html

実装しやすいFigmaファイルの作り方(2/21)
https://note.com/ayahfw/n/nc58ad9336942

サイバーセキュリティの現在と未来 - 日経クロステック Special(12/3開催まとめ)
https://special.nikkeibp.co.jp/atclh/NXT/22/nri_secure0218/

EdTech がデータ文化を作り、データ プラットフォームを展開する方法(2/21)
https://cloud.google.com/blog/ja/topics/public-sector/how-edtechs-create-data-culture-and-roll-out-data-platform

ミクシィ「Git 新人研修資料」をエンジニア経験者目線でレビューしてみた(2/21)
https://news.careerconnection.jp/career/general/131346/

オンラインマナーがここ 1 年で向上、2016 年以降で最も良い結果に――マイクロソフトの最新の調査より(2/21)
https://news.microsoft.com/ja-jp/2022/02/21/220221-safer-internet-day-online-civility-improves-2022-research/

若手エンジニアの潜在力を引き出す「上司」の発想法、暗号研究の醍醐味とは？(2/22)
https://xtech.nikkei.com/atcl/nxt/column/18/01959/021700001/

メタバースは「ただの面白い技術群」で終わるのか、市場発展へ克服すべき課題(2/22)
https://xtech.nikkei.com/atcl/nxt/column/18/01953/021700010/

ニップンは第3四半期報告書も提出延長へ、21年7月に受けたサイバー攻撃の影響残る(2/22)
https://xtech.nikkei.com/atcl/nxt/column/18/00598/121500153/
暇つぶしにマインクラフトの自動マイニングツールの開発をしたという話

友人とマイクラをやることになったものの素材集めが面倒だったから作成を始め、実装した流れやコードについての説明をしていく
なお、パラメーター等調整中

## 実装方針
- W, P キー押しっぱなしで右クリックの代わりにPを利用(モジュールの都合)
- 逐次画面を取得し、グレイスケールに変換を行い輝度を取得
    - 輝度に応じて、マグマが近くにあるのか外に出そうなのか判別
        - 閾値を超えたら180度回転し、一定時間経過後右を向く
- ESCでプログラムを終了 
- 一定時間経過後にピッケルの位置を変更


## 実際のコード
```python:automation_mining.py
import time
from PIL import ImageGrab
import numpy as np
import win32gui
import cv2
import schedule
import pydirectinput as direct
import threading
import queue
import keyboard
import sys


END_MAIN = queue.Queue()
def stop_program():
	while True:
		if keyboard.is_pressed("esc"):
			print("esc")
			END_MAIN.put(1)
			break


def get_screen():
	TARGET_NAME = 'Minecraft 1.18.1'
	TARGET_NAME = "Minecraft 1.18.1 - Multiplayer (3rd-party Server)"
	try:
		handle = win32gui.FindWindow(None, TARGET_NAME)
	except :
		TARGET_NAME = 'Minecraft 1.18.1'
		handle = win32gui.FindWindow(None, TARGET_NAME)
	IS_MAGMA_SCREEN = 2550000    
	IS_NOT_MINING =   3300000
	MAGMA_WAIT_TIME = 10
	while True:
	    rect = win32gui.GetWindowRect(handle)
	    img = ImageGrab.grab(rect)
	    ocv_im = np.asarray(img)
	    ocv_im = cv2.cvtColor(ocv_im, cv2.IMREAD_GRAYSCALE)
	    img= ocv_im.astype('float')
	    img /= 255
	    sum_gray=img.sum()

	    if sum_gray > IS_NOT_MINING:
	    	END_MAIN.put(1)
	    	return

	    elif sum_gray > IS_MAGMA_SCREEN:
	    	move_behind_from_now_cursor_position()
	    	time.sleep(MAGMA_WAIT_TIME)
	    	move_right_from_now_cursor_position()
	    	time.sleep(1)



now_choose_pickaxe_position = 1
def change_pickaxe():
	schedule.every(2).minutes.do(sup_change_pickaxe)
	while True:
		time.sleep(3)
		schedule.run_pending()

def sup_change_pickaxe():
	global now_choose_pickaxe_position
	direct.press(str(now_choose_pickaxe_position))
	now_choose_pickaxe_position += 1
	if now_choose_pickaxe_position == 10:
		now_choose_pickaxe_position = 1


def push_keys():
	time.sleep(3)
	print("START PROGRAM")
	STOP_TIME = 60 * 10
	threading.Thread(target=w_key_looper, daemon=True).start()
	threading.Thread(target=click_loop, daemon=True).start()
	threading.Thread(target=circle_mining, daemon=True).start()
	direct.keyDown('w')
	while True:
		time.sleep(30)
		schedule.run_pending()
	

def w_key_looper():
	direct.keyDown('w')


def click_loop():
	direct.keyDown('p')


def move_right_from_now_cursor_position():
	direct.move(1, -525)

def circle_mining():
	count = 8
	while True:
		move_right_from_now_cursor_position()
		time.sleep(count)
		count *= 2


def move_behind_from_now_cursor_position():
	move_right_from_now_cursor_position()
	move_right_from_now_cursor_position()

def main():
	threading.Thread(target=push_keys, daemon=True).start()
	threading.Thread(target=get_screen, daemon=True).start()
	threading.Thread(target=stop_program, daemon=True).start()
	threading.Thread(target=change_pickaxe, daemon=True).start()
	while True:
		time.sleep(3)
		if END_MAIN.empty() != True:
			sys.exit()

main()

```
なお、マウス感度によってきちんと振り向ける値が変わってくる。
私のゲーム内感度だと11で横と後ろに振り向けます。
ブラウザ起動モジュールを呼び出そうとしてハマったはなし

python

Seleniumを使ったブラウザ操作をよく使用するので、立ち上げ部分をモジュールとして保存。他のファイルから呼び出し使おうとしたところハマったので備忘録として。

結論として、pythonの各種ライブラリが保管されているsite-packagesに、作成したモジュールのパスを記載したテキストを.pthとして保存したところ、スクリプトからモジュールを呼び出し、ブラウザを起動することができた。
Zabbixで21個以上グラフを表示する

## バージョンを調べる

```bash
$ zabbix_server -V
zabbix_server (Zabbix) 5.0.19
```

## グラフが20個しか表示されない

Zabbixさんは、グラフを30個表示するように組んでも、シレッと20個しか表示してくれない。
ページングすらしてくれない。検索してみると、なかなか対処法が見つからなかった。

設定ファイルで解決。

```/usr/share/zabbix/include/defines.inc.php
// Applied to tables with variable count of columns. Columns above this limit will be truncated.
define('ZBX_MAX_TABLE_COLUMNS', 50);
define('ZBX_MAX_GRAPHS_PER_PAGE', 20);
```

上記の `ZBX_MAX_GRAPHS_PER_PAGE` が表示されるグラフの数の上限。コメントにシレッと **"この制限を超える列は切り捨てられます"** と書かれている。ページングするなり、「21個以上グラフが設定されていますが、設定により20個しか表示していません」と表示するなりしてくれよ、と思う。

なお、設定ファイルを更新するだけで良く、Zabbixの再起動等は必要ない。

`PER_PAGE` とは……🤔
ポインタについて

最近Goを触り始めました。右も左も分からない状況ですが、今日学んだことをアウトプットしていきます。

## ポインタ
めちゃ大事そうだったのでまとめようとおもいます。まず、これを理解するためには**アドレス**を理解しなければなりません。
コンピュータにはメモリという作業場があって、変数はこのメモリに格納されているんですね。その格納されている場所をアドレスというんです。Goではアドレスをポインタと呼んでいます。
つまり、アドレス=ポインタ
実際にポインタを取得してみましょう
```test.go
package main

import "fmt"

func main()  {
	name := "what is golang?"
	fmt.Println(&name)
}

=> 0xc000042230
```
Printlnの後に、**&変数名**と書くことでポインタを取得できます。
それでは今度はポインタを変数に代入してみましょう。

```test.go
package main

import "fmt"

func main()  {
	name := "what is golang?"

	var testname *string = &name
	fmt.Println(testname)
}

=> 0xc000042230
```
ポインタ型変数を定義するには、データ型に「*」をつけて、&変数名を右辺に書けばオッケです。
ポインタに入れたポインタの実際の値を出力してみましょう。
```
package main

import "fmt"

func main()  {
	name := "what is golang?"

	var testname *string = &name
	fmt.Println(testname)
	fmt.Println(*testname)
}
=> 0xc000042230
   what is golang?
```

以上です。何か間違いがございましたら、ご教示いただけますと幸いです。
【参考資料】

https://prog-8.com/

https://qiita.com/tfrcm/items/e2a3d7ce7ab8868e37f7
Kustomizeのpatches(JSON Patch)において配列を扱う際の注意点

KustomizeのKustomizationファイルではKubernetesマニフェストにパッチを当てることができます。このパッチはJSON Patch(RFC6902)の仕様に基づきます。
このパッチの仕組みは便利ですが、配列の扱いがやや難しくコツが必要です。JSON Patchで配列を扱う際に気を付ける点について紹介します。

## JSON Patchで配列に複数の要素を追加する場合は複数のオペレーションを使う

下記のようなマニフェストとkustomization.yamlがある場合に、portsに複数の要素を追加したいとします。

```yaml:pod.yaml
apiVersion: apps/v1
kind: Pod
metadata:
  name: simple-app
spec:
  containers:
    - name: simple-app
      image: nginx:latest
      ports:
        - name: port1
          containerPort: 1000
```

```yaml:kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - pod.yaml

patches:
  - target:
      kind: Pod
    path: pod_patch.yaml
```

このとき、下記のように一つのオペレーション(op: add)で複数の要素を追加できないかと考えるかと思います。しかし、残念ながらJSON Patchではこのような操作はできません。

```yaml:pod_patch.yaml
# 注意：適切に動作しない例
- op: add
  path: /spec/containers/0/ports
  value:
    - name: port2
      containerPort: 2000
　　　　　　　　- name: port3
      containerPort: 3000
```

複数の要素を追加するには、下記のように複数のオペレーションを書く必要があります。

```yaml:pod_patch.yaml
# 適切に動作する例
- op: add
  path: /spec/containers/0/ports/-
  value:
    name: port2
    containerPort: 2000
- op: add
  path: /spec/containers/0/ports/-
  value:
    name: port3
    containerPort: 3000
```

## 空配列を使ってパッチを再利用可能にする

下記のマニフェストのように ports がない状態を考えます。

```yaml:pod.yaml
apiVersion: apps/v1
kind: Pod
metadata:
  name: simple-app
spec:
  containers:
    - name: simple-app
      image: nginx:latest
```

このとき、下記のように存在しないportsに要素を追加する命令を書くとエラーになります。portsは存在しないのでportsへの要素の追加はできません。

```yaml:pod_patch.yaml
# ダメな例
- op: add
  path: /spec/containers/0/ports/-
  value:
    name: port1
    containerPort: 1000
```

下記のように、portsごと追加する命令にすることで動作しますが、portsが存在しないマニフェストでしか使うことができず再利用性が損なわれます。

```yaml:pod_patch.yaml
# 動作するが再利用性が低い
- op: add
  path: /spec/containers/0/ports
  value:
    - name: port1
      containerPort: 1000
```

そこで、元となるマニフェストでportsを空配列にしておくことで、要素追加のパッチが使えるようになります。

```yaml:pod.yaml
apiVersion: apps/v1
kind: Pod
metadata:
  name: simple-app
spec:
  containers:
    - name: simple-app
      image: nginx:latest
      ports: []
```

```yaml:pod_patch.yaml
- op: add
  path: /spec/containers/0/ports/-
  value:
    name: port1
    containerport: 1000
```
もうHTML/CSSは書きたくない

# もうHTML/CSSは書きたくない
「もうHTML/CSSは書きたくない」とちょっとタイトルで釣りましたが、**最後まで読んでくれると嬉しいです！**
結論から言うと、**Amplify StudioとFigmaを連携させて、Reactのコンポーネントを作成する**と言う記事です。
StudioとFigmaを連携させる機能は、2021年の12月に発表されました。
[最小限のプログラミングでFigmaからフルスタックのReactアプリを実現](https://aws.amazon.com/jp/blogs/news/aws-amplify-studio-figma-to-fullstack-react-app-with-minimal-programming/)
実際に、インターンシップで触れる機会があったので、触れた感想や結果を書きたいと思います。

## 先に感想を
Amplify StudioとFigmaを連携させる方法は、僕以外の人も書いているので、僕の感想を先に書きます。
感想だけでいいと言う方は、ここで離脱しても大丈夫です！
### 僕のプロフィール
エンジニアインターンとして5ヶ月経ち、インターンではReactとAWSを使って開発中。
クラウドプラクティショナー取得済み。

### 実際にやってみた感想
**・ Figmaを完璧に使えこなせていないと厳しい**
Figmaの方で雑にデザインを作っていると、いざReactでUIコンポーネントとして利用したときに、ずれが起きたり、画面サイズが変わったときにデザインが崩れたりします。また、**Amplify Studioでコンポーネントとして出力させるとこうなるんだ！**ということもわかっておくと、進めやすいと思います。
**・ 全部のコンポーネントを置き換える必要は特にない**
一応プレビューの段階のため、できないこともあるようです。また、すでにコンポーネントがあるなら、わざわざ置き換えるメリットはないと思います。そのため、新しい比較的小さいコンポーネントを作成する際に少し使ってみるとかはありかもです。
**・ Amplify Studioの操作が難しい**
これについては、**慣れろよ**としか言いようがないのですが、DynamoDBからデータを引っ張ってこれたり、型定義ができたりします。AWSの機能は大体そうですが、慣れないと複雑だなーと感じることがあります。

## 先にFigmaのリンクを取得する
以下Figmaの画面の右上にある、青い**Share**ボタンを押すと、モーダルが出てきます。
そのモーダルの左下にある**Copy Link**を押して、Figmaのリンクを取得します。
**以下の画像はサンプルのため、デザインを作成していません**
![スクリーンショット 2022-02-23 0.52.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401623/d1c56d1f-c044-4f19-0d87-d12381ce841a.png)

## Amplify Studioにログインする
**ここから先は、GraphQL APIバックエンドとReactフロントエンドを持つ、サンプルReactアプリケーションをデプロイしていることを前提に、書き進めていきます。**
Amplifyがわからない方は、[Amplify SNS Workshop](https://amplify-sns.workshop.aws/ja/)を参考にしてください。
まずはマネジメントコンソールにログインして、Amplifyコンソールにある作成したアプリケーションを開きます。
その後、左のメニューのアプリの設定から、Amplify Studio Settings(設定)を選択します。
すると、以下の画面が出てくるので、**Enable Amplify Studio**をオンにして、右側にある**Invite users**を押します。
そこで、自分のメールアドレスを打ち、届いたメールに書かれているUDとパスワードで、Amplify Studioにログインします。
![スクリーンショット 2022-02-23 1.10.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401623/196808e0-fd04-46fd-ef83-f718a78a8c44.png)

## Amplify StudioとFigmaを連携させる
ログインして、以下のような画面が開ければ、右のメニューにある**UI Library**を押します。
その後、画面が変わり、真ん中に**Get started**があるので、押します。
すると、上で取得したリンクを記入する欄があるので、そこにペーストして、**Continue**を押します。
これで連携が完了です。
![スクリーンショット 2022-02-23 0.46.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401623/456d690b-3b0e-557c-c00c-84c16c461c78.png)

## ReactのUIコンポーネントとして使えるようにする。
Figmaと連携して、右上のFigmaのマークの隣にある**Sync with Figma**のボタンを押すと、Figmaで作成したコンポーネントが出てきます。
そこで、以下の画像の前に、**Reject**もしくは**Accept**ボタンが出てくるので、必要なコンポーネントのみAcceptします。
そうすると、以下の画像のようになります。
そして、この画像の右少し上にある**Configure**ボタンを押すと、画面が少し変わり、下の方に**</> Get component code**ボタンが出てきます。
それを押すと、ReactのUIコンポーネントとして使えるようにする方法が出てきます。
詳しくは進めるとわかるので、ここではざっとだけ説明すると、amplify pullして、jsxファイルが作成されるため、それを別のファイルからインポートして利用します。

![スクリーンショット 2022-02-23 1.03.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401623/10fae9b6-3d72-9540-fe95-8d5ca7ece6d5.png)

## まとめ
ここでは、最短でFigmaからReactのコンポーネントを作成する方法を書きました。
Amplify Studioには、まだまださまざまな機能が存在するため、ぜひ試してみてください。
また、もし間違えていることや追加コメントがあれば、教えてください！
.NET nanoFrameworkでマイコンプログラミング（WiFiとMQTT）

.NET nanoFrameworkのサンプルプログラム3つ目です。

今回はWifi接続とMQTTです。
使用したデバイスは M5 ATOM Matrix ですが、ESP32ボードならどれでも動作すると思います。

#ハードウェア
・M5 ATOM Matrix
・ESP32 DevkitC

#ソフトウェア
・VisualStudio2019
・ファームウェア ESP32_PICO 1.7.4-preview.54
・ファームウェア ESP32_REV0 1.7.4-preview.54

#追加するNuGetパッケージ
・nanoFramework.System.Device.WiFi 1.4.0-preview.36
・nanoFramework.M2Mqtt 5.0.2-preview.80

#プログラム
``` C#:Program.cs
using System;
using System.Diagnostics;
using System.Threading;

//追加
using nanoFramework.Networking;
using System.Text;
using nanoFramework.M2Mqtt;
using nanoFramework.M2Mqtt.Messages;

namespace NF_WiFi_MQTT
{
    public class Program
    {

        const string ssid = "YOUR SSID";
        const string password = "PASSWORD";

        public static void Main()
        {
            //Wifi接続
            ConnectWifi();

            //mqttクライアント
            var client = new MqttClient("BROKER ADDRESS");
            var clientId = Guid.NewGuid().ToString();
            client.Connect(clientId);

            //Subscribe
            client.Subscribe(new[] { "NF-mqtt/demo" }, new[] { MqttQoSLevel.AtLeastOnce });
            //イベント登録
            client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;

            //Publish
            for (int i = 0; i < 5; i++)
            {
                client.Publish("NF-mqtt/demo", Encoding.UTF8.GetBytes("=== Hello MQTT! ==="), MqttQoSLevel.AtLeastOnce, false);
                Thread.Sleep(5000);
            }

            //接続の解除
            client.Disconnect();

            Thread.Sleep(Timeout.Infinite);
        }

        private static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            Debug.WriteLine($"Message received: {Encoding.UTF8.GetString(e.Message, 0, e.Message.Length)}");
        }

        private static void ConnectWifi()
        {
            CancellationTokenSource cs = new(60000);

            //WifiでDHCP接続
            var success = WiFiNetworkHelper.ConnectDhcp(ssid, password, requiresDateTime: true, token: cs.Token);
            if (!success)
            {
                Debug.WriteLine($"Can't connect to the network, error: {WiFiNetworkHelper.Status}");
                if (WiFiNetworkHelper.HelperException != null)
                {
                    Debug.WriteLine($"ex: {WiFiNetworkHelper.HelperException}");
                }
            }
            else
            {
                Debug.WriteLine("Wifi Connected!");
            }
        }
    }
}

```
・"YOUR SSID","PASSWORD","BROKER ADDRESS"は自分の環境に合わせて変更してください。
・Brokerは色々ありますが、[shiftr.io Desktop](https://www.shiftr.io/desktop#downloads)がローカル環境で試せるのでお勧めです。
・少し前までWifi接続のためにはnanoFramework.Windows.Devices.Wifiを使っていたのですが、最新のファームウェアではnanoFramework.System.Device.WiFiを使う必要があります。他にもGPIOなどのパッケージが変更になっています。

ソースコードは[こちら](https://github.com/linyixian/NF_WiFi_MQTT)からダウンロードできます。
pip3 install torchがなぜか失敗する問題を解決した時の備忘録

ある日`pip3 install torch`するもなぜか失敗する

```bash
$ pip3 install torch
Defaulting to user installation because normal site-packages is not writeable
Collecting torch
  Downloading torch-1.10.2-cp39-cp39-manylinux1_x86_64.whl (881.9 MB)
Killed
$ python -c "import torch"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'torch'
```

色々調べるも分からない。
もしかして最新のpytorchのバージョンが上がってずれてるのかも？と思いサイトを確認すると以下で`1.10`になっているようだった。

> [https://pytorch.org/blog/pytorch-1.10-released/](https://pytorch.org/blog/pytorch-1.10-released/)
> [https://github.com/pytorch/pytorch/releases](https://github.com/pytorch/pytorch/releases)
> 22 Oct 2021 PyTorch 1.10 Release, including CUDA Graphs APIs, Frontend and compiler improvements

という事でパッケージをアップデート

```
$ pip install -U pip
```

インストール再チャレンジ

```
$ pip install torch
Defaulting to user installation because normal site-packages is not writeable
Collecting torch
  Downloading torch-1.10.2-cp39-cp39-manylinux1_x86_64.whl (881.9 MB)
     \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 881.9/881.9 MB ? eta 0:00:00
Collecting typing-extensions
  Downloading typing_extensions-4.1.1-py3-none-any.whl (26 kB)
Installing collected packages: typing-extensions, torch
  WARNING: The scripts convert-caffe2-to-onnx, convert-onnx-to-caffe2 and torchrun are installed in '/home/ubuntu/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed torch-1.10.2 typing-extensions-4.1.1
$ python -c "import torch"
```

成功した！よかった！

# 参考

[https://pytorch.org/blog/pytorch-1.10-released/](https://pytorch.org/blog/pytorch-1.10-released/)
Python リスト内にある重複している数字を取り除き、並べるプログラム

どうも、学生エンジニアのirohasです。
本日は、暇つぶしにPythonのプログラムを1つしてみたので記事にしてみました。

やることはタイトルの通り、与えられたリスト内の数値を重複している数字を取り除いて出力させるというものです。

まず、与えられているリストは以下の通りです。

```
old_list = [1,1,1,2,2,3,3,3,4,5,5,6,7,7,7,8,8,9,10,10]
```

このリストを下記のような出力にするのが目標です。

```
[1,2,3,4,5,6,7,8,9,10]
```

僕がこの問題に対して作成したコードは以下になります。

```python:remove.py
old_list = [1,1,1,2,2,3,3,3,4,5,5,6,7,7,7,8,8,9,10,10]

def remove():
    new_list = []
    for item in old_list:
        if item not in new_list:
            new_list.append(item)
    
    return new_list

print(remove())
```

まず、関数を定義し、取り除いた後の数値を入れるlistを作成します。
その後、for文を用いてold_list内の数字を回し、new_listに該当する数字が入っていなかったらnew_listに格納するようにコーディングしていきます。
あとは出力するだけです。

暇つぶしに少し競技プログラミングチックなことをしてみましたがたまにやると楽しいですね（笑）

もしよろしかったら、コメント欄で"こういうやり方もあるよ！"だったり、"自分は○○(ほかのプログラミング言語)使ってこう書いたよ！"など書き込んでください（笑）

今後も暇なときは競技プログラミングチックなことをやってみようと思います！
2月23日

2番目のpタグのフォントサイズを書き換える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524339/70200a0a-c8f8-5653-45ba-34b49ad99210.png)
テキストをブロックの中央に配置する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524339/a47dd1ed-aa3f-9f3b-f6cc-8de9ef7ef257.png)
子ブロックは親ブロックを基準にして中央に配置される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524339/4e29deb9-4b62-3c47-8984-3d873209dfd0.png)
背景がページ全体に表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524339/251515fd-a408-bfaa-b337-01029d71a928.png)
ブロックに影を付ける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524339/cdeef2e9-5ec8-d631-cce8-649f3f6d50df.png)
inputフォーマットを削除する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524339/8e7f7a83-b2b9-6455-4ffe-8c71766c98f6.png)
input type="submit"   formフォームと組み合わせて，データを送信する
input tyoe="buttom"   普通のbutton
Ubuntu Server 20.04.3 LTS トラブルシューティング#1 terminalが起動しない

障害内容:terminalが起動しない

発生日:2022/02/20

確認項目:syslog

:::note warn

21:41:55 systemd[1]: Condition check resulted in Process error reports when automatic reporting is enabled (file watch) being skipped
21:41:56 kernel : RAS: Correctable Errors collector initialized
21:41:55 systemd[1] : Staring GRUB failed boot detection...
21:41:56 systemd[1] : Finished GRUB failed boot detection
21:41:56 thermald[773] : I/O warning to load external entity "/etc/thermald/thermal-conf.xml"
21:41:56 thermald[773] : I/O warning to load external entity "/etc/thermald/thermal-conf.xml"
21:41:56 thermald[773] : I/O warning  : failed to load external entity "/etc/thermald/thermal-conf.xml"
21:41:56 thermald[773] : error: could not parse file /etc/thermald/thermal-conf.xml
21:41:56 thermald[773] : error: could not parse file /etc/thermald/thermal-conf.xml
21:41:56 thermald[773] : error: could not parse file /etc/thermald/thermal-conf.xml
21:41:56 udiskd[774] : failed to load module: libbd mdraid: libbd mdraid.so.2: cannot open shared object file: No such file or directory
21:41:56 udiskd[774] : Failed to load the 'mdraid' libblockdev plugin
21:41:57 NetworkManager[754]: <warn> [1645447317.3561] Error: failed to open /run/network/ifstate 
21:41:57 systemd[1]: maldet.service: Failed with result 'protocol'.
21:41:57 ssytemd[1]: Faild to start Linux Malware Detect monitoring - maldet.
21:41:59 /usr/lib/gdm3/gdm-wayland-session[1091]: dbus-daemon[1091]: [session uid=121 pid=1091] Activated service 'org.freedesktop.systemd1' failed: process org.freedesktop.systemctl exited with status 1
21:41:59 /usr/lib/gdm3/gdm-wayland-session[1091]: dbus-daemon[1091]: [session uid=121 pid=1091] Activated service 'org.freedesktop.systemd1' failed: Process org.freedesktop.systemd1 excited with status1
21:41:59 gnome-session-binary[1092]: Warning: Failing back to non-systemd startup procedure due to error: GDBus.Error:org.freedesktop.DBus.Error.Spawn.ChildExited: Process org.freedesktop.systemd1 excited with status 1
21:41:59 gno-me-session-binary[1092] WARNING: Falling back to non-systemd startup procedure due to error: GDBus.Error:org.freedesktop.Dbus.Error.Spawn.ChildExited: Process org.freedesktop.systemd1 excited with status 1
以下、省略
:::

ログを見てみると、gnome-terminal関連が原因でterminalが起動しないようです。
GRUB関連だとそもそも、ubuntu自体が起動しないと思いますし･･･｡
terminalを起動させないことには何も出来ないと思い、何とかしてterminalを起動できるようにするために調べてみました。

:::note
Altキー+F2でRun a Commandが表示されます。
下記のコマンドを入力
【コマンド】
gnome-terminal -e bash

terminalが起動しました。ですが、terminalのウインドウは一つのままですし、一時的に使用が出来るような状態です。
調べてみると何やらpython3が絡んでいるようです。別PCに搭載している仮想マシンで使用している同じubuntuと比較をしてもなんや違いはないと思われます。よって、python3は今回のエラーについては関係がないと考えられます。
それ以外の原因と思われます。ユーザーアカウントを作成し、そのアカウントでログインするとterminalが起動出来ることもあるようです。

【コマンド】
sudo adduser 作成するユーザー名
新しいパスワードを入力

所属や組織も入力を求められましたが、未設定で設定をしました(あくまで動作確認のために作成しましたので)
サインアウトし、作成したアカウントでログイン。terminalが普段通りに起動出来ました。
:::
取り敢えず、terminalが起動出来るようになりましたので、作成したアカウントで構築の続きを進めます。
元々のアカウントがどのような影響を受けて、terminalが起動出来なくなった原因も併せて究明しようと思います。
繰り返し使って星のらせん描いてみた。

## 亀が動くアレ作ってみた
「Pythonではじめる数学の冒険」の課題1-6の答えです。
関数（star）を最初に作って、その後にそれをループ(starSpiral)させるのですが、ずっとstarSpiralを先頭にしてしまっていたのでうまく行きませんでした。
length+=の部分や変数をあらかじめ設定しておく部分は注意です。
やっと正解にたどり着いたので備忘録的に共有。

```python
from turtle import *
shape('turtle')
speed(10)
def star(length=5):
    for i in range(5):
        forward(length)
        right(144)
def starSpiral(length):
    for i in range(60):
        length+=5
        star(length)
        right(5)
starSpiral(5)

```
動かすとこんな感じ。
![スクリーンショット 2022-02-23 0.21.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636151/eebbc276-da06-43b6-875f-f5b44acc6bca.png)


綺麗ですね、プログラムというのは」ちょっといじるだけでアートみたいになるんですな。。
また書き（描き）ます。
herokuでPostgreSQLの本番データベースをリセット

# railsチュートリアル１０章で気になったのでメモ

## 手順

```
$ heroku pg:reset DATABASE
▸    WARNING: Destructive action
 ▸    postgresql-○×△-○×△ will lose all of its data
 ▸
 ▸    To proceed, type データベースの名前？ or re-run this
 ▸    command with --confirm データベースの名前？

>ここにデータベースの名前？を入力する

# データベース再構成
$ heroku run rails db:migrate
```
本当の継承シングルトンを見せてやんよ【C#】

今回は，継承可能なシングルトン，つまり，この抽象クラスを継承すればなんでもシングルトンになれるぜ〜ってクラスを紹介します。

継承ツリーという概念と、みんな大好きジェネリックが出てきます。

# 誰しも一回は通る道

```csharp
public abstract class BaseSingleton<T>
{
    public static T Instance;

    public BaseSingleton()
    {
        Instance = (T)this;
    }
}

public class Singleton : BaseSingleton<Singleton> { }
```


これじゃコンパイラーは通しちゃくれません。なぜでしょうか。

```text
Cannot convert type 'BaseSingleton<T>' to 'T'.
```

`Instance = (T)this;`のところでひっかっています。これは`Object => BaseSingleton<T>`と`Object => T`という二つの継承ツリーが存在しており、言語仕様として別ツリーにはキャストできないからです。つまり、`T`と`BaseSingleton<T>`の関係を教えてやればいいのです。

# 結論

正解は、これ。

```csharp
public abstract class BaseSingleton<T> where T : BaseSingleton<T>
{
    public static T Instance;

    public BaseSingleton()
    {
        Instance = (T)this;
    }
}

public class Singleton : BaseSingleton<Singleton> { }
```

`where`節により、継承関係が明示されました。
継承ツリーは`Object => BaseSingleton<T> => T`となっており、これならキャスト可能です。


# 余談: UnityのMonoBehaviourをシングルトンにしてみる

同じように。

```csharp
public abstract class SingletonBehaviour<T> : MonoBehaviour where T : SingletonBehaviour<T>
{
    public static T instance;

    public SingletonBehaviour()
    {
        instance = (T)this;
    }

    private protected virtual void OnDestroy()
    {
        instance = null;
    }
}
```

# まとめ

ジェネリックってほんとにムズカシイ！けどめっちゃ楽しい！
【備忘録】docxファイルをzip展開して再びdocxに戻したらファイルが開けなくなったときは圧縮対象を疑え

# 結論

https://ameblo.jp/dosukoifreak/entry-10793351527.html

こちらのブログに救われました。

# 経緯説明

Wordの編集作業はとにかく面倒です。小説ではほぼ必須となるルビ振りとかひたすらに面倒くさい（しかもなんか行間が妙に空く）。

というわけで、[カクヨム記法](https://kakuyomu.jp/help/entry/notation)で記述したルビを処理してくれるプログラムを作ることにしました。[^1]

（※本記事執筆時点（2022年2月22日現在）では未完成）

知らない人のためにざっくりカクヨム記法について説明しておきます。

たとえば、以下のようなテキストがあるとしましょう。

```

「|猫の日《ザ・デイ・オブ・キャッツ》は《《もうすぐ終わる》》…………」

```

この文章が、閲覧時には以下のような感じで表示されます。

「<ruby><rb>猫の日</rb><rt>ザ・デイ・オブ・キャッツ</rt></ruby>は<ruby><rb>もうすぐ終わる</rb><rt>・・・・・・・</rt></ruby>…………」

つまり、`|`と`《`の間の文字列に対して`《》`内部の文字列でルビを振り、`《《`と`》》`で文字を囲むと傍点を振ってくれるわけです。

この記法は書きやすく見やすいのでとても気に入っています。

閑話休題。

このカクヨム記法を自動でWordのルビに変換するプログラムの開発を現在行っています。「docxファイルを生成するならpandoc使え」とはよく耳にしますが、生憎とpandocはカクヨム記法を処理してはくれません。

ということで自作することにしました。

## 「ファイルを開こうとして、エラーが発生しました」

まずは実験として、適当にテキストを打ち込んだdocxファイルを保存してzip展開して`word/document.xml`を加工、docxに戻してWordで開く……というのをやってみることにしました。

下の画像の`test`、`test_texted`ディレクトリはdocxファイルを解凍したものです。

![スクリーンショット 2022-02-22 234423.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/22bec67d-0da5-9527-9649-cd494d6f88c5.png)

たとえば`test`をdocxに戻してみましょう。

![スクリーンショット 2022-02-22 235302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/b5042710-8017-83fe-8980-423e604b8b61.png)

こうやって圧縮して……名前を`test.zip`から`test.docx`に変更。すると……

![スクリーンショット 2022-02-22 235446.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/453af59a-540a-683d-f466-36e936380878.png)

プレビューを表示してくれません。

![スクリーンショット 2022-02-22 235605.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/1d62fc30-ce5f-4d0d-c9cc-70a1f002ac05.png)

開こうとするとエラー。

色々ググって「セキュリティの問題だからセキュリティ設定を変更すれば解決する」などの情報も得ましたが、どうやらこのケースは別の原因のようで解決しませんでした。

プログラムの制作を進めつつ、あれこれと仮説を立てては失敗、というのを繰り返すこと数時間…………[記事冒頭に貼ったブログ](https://ameblo.jp/dosukoifreak/entry-10793351527.html)を発見し、本当の原因が判明しました。

# docxファイルが開けなかった原因

> [Content_Types].xmlよりも一段上のフォルダ（通常、元のファイル名のフォルダ）をzip圧縮しても元のdocxにはならず、再度docxを開く際、次のエラーとなるため、注意。

<small>https://ameblo.jp/dosukoifreak/entry-10793351527.html より引用</small>

はい。

つまりここ（↓）が間違いだったわけですね。

![スクリーンショット 2022-02-22 235302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/b5042710-8017-83fe-8980-423e604b8b61.png)

ただしくは、こう（↓）しないといけない。

![スクリーンショット 2022-02-23 002558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/695a25ad-5df5-ca99-ae77-d9abaa2a124e.png)

（まっしろでわかりにくいですが）無事、プレビューできました！ ファイルも開けました！

![スクリーンショット 2022-02-23 002953.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/4fbae94f-3181-1941-dbfa-c0219263fd40.png)


*****

[^1]: なぜカクヨム記法なのかと言うと筆者がカクヨムユーザーだからです。
ITの力で情報を収集・分析してシーバスを釣りたい #1

##はじめに
昨年末からシーバス釣りにはまり、割と情報の収集と分析が必要なゲームと気づきました。
せっかくIT関係のSEなのでスマートに情報を収集・分析して釣果をあげたいと思いました。
ついでにDXにもはまり中なのでそのお勉強も兼ねます。
![IMG_20220116_172421.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43851/afe819f1-8585-8dde-f3bf-56ba45f31f16.png)


##情報の収集
使うツールは以下。

 - [Twitter](https://twitter.com/tenpa_ozisan)
 - [IFTTT(イフト)](https://ifttt.com/)
 - Googleスプレッドシート

まずはTwitter上で**「シーバス釣り」**を検索キーワードとしてIFTTTで収集し、Googleスプレッドシートに落とし込みます。このあたりはGUIですべて完結するので簡単です。

![step0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43851/686d09ae-f969-4ac6-094f-43a6129a619d.png)
![step2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43851/f4bdf47e-16aa-4f5a-9d21-162c04307488.png)
![step1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43851/11e158a8-f9e8-a26e-421f-6dfe8c81c3d0.png)

結果としてGoogleスプレッドシートにツイートされた内容が保存されます。
![step3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43851/4bab47b6-dffb-da98-7768-bfde9812f2e1.png)

##情報の分析
シーバス釣りはルアーのチョイスが重要です。ですが、安い買い物でもないので慎重に購入を検討する必要があります。今回は今の時期よく呟かれてるルアーの集計をしてみます。
単純な単語の抜き出しだけなので、「釣れたルアー」という分析ではなく単に話題にあがっているという分析になります。（釣れたルアー分析はまた別途）

使うツールは以下

 - [Janome](https://mocobeta.github.io/janome/)
 - Colaboratory
 
Janomeは形態素解析エンジンで日本語をきれいに分解してくれます。
Janomeで呟きを「単語に分解」し「名詞」だけ抽出してみます。
スプレッドシートを読み込み、呟きをJanomeに食わせて名詞だけ抜き出すというシンプルなコードです。
（コードや変数名は美しくありません！）

```py
from google.colab import auth
from oauth2client.client import GoogleCredentials
from janome.tokenizer import Tokenizer
import gspread
import collections

auth.authenticate_user()
gc = gspread.authorize(GoogleCredentials.get_application_default())

ss_id = "****"
book = gc.open_by_key(ss_id)
sheet = book.worksheet("シート1")
data = sheet.get_all_records()

t = Tokenizer()
result = []

for key in data:
  content = key['body']
  list = t.tokenize(content)
  for key2 in list:
    part_of_speech = key2.part_of_speech.split(',')[0]
    if part_of_speech == "名詞":
      result.append(key2.surface)
      if key2.surface == "スネコン":
        print(key2.surface)

c = collections.Counter(result)
print(c.items())
```

試しに**スネコン**が抽出できてるかハードコーディングで出力してます。
結果は以下の通り。無事にルアーの名称も単語として抽出できています。
（2000件のうち4件呟かれていたようです）
![step4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43851/eedb29fc-48ca-5619-30c2-ea1f50193a3f.png)

ひとまずここまでデータが抜き出せたら、あとはスプレッドシートに落とし込むなりし、見やすいデータに加工するだけです。

##次回以降
このデータではルアーを買ったか、釣れたのかよく分からないデータなので、なんとかして釣果につながる分析をしてみたいと思います。
JavaScript の関数即時呼び出しでは関数文を関数式と解釈させる

# 勘違いしていたこと

JavaScript で関数を即時呼び出しするときに、以下の (A) だと SyntaxError になるので (B) のように括弧で囲みます。

```javascript
// (A) SyntaxError: Function statements require a function name
function() {
    ...
}()

// (B) OK
(function() {
    ...
})()
```

この「構文エラーになるので括弧で囲む」の理由を勘違いしていました。

# 関数文を関数式にするために括弧で囲む

結合順を制御するために括弧で囲むのだと思い込んでいたのですが、正しくは、関数文（function declaration / function statement）ではなく関数式（function expression）だと解釈させるためでした。

:::note alert
誤った理解
function(){...}() は function() と {...}() だと解釈されるため SyntaxError になる。結合順を制御するために (function(){...})() と括弧で囲むことで function(){...} と () だと解釈されるようになり、SyntaxError にならない。
:::

:::note info
正しい理解
function(){...}() は関数文だと解釈される。関数名が書かれていないので SyntaxError になる。最後の () はあっても無くても、同じ理由で SyntaxError になる。
:::

# グループ化演算子で関数文を関数式にする

「括弧で囲む」の「括弧」とは、グループ化演算子（grouping expression）のことです。

 * [グループ化演算子 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Grouping)

グループ化演算子は `(1 + 2) * 3` のように式の中の評価順を制御します。`function` は文脈によって文と式のどちらかに解釈されますが、グループ化演算子の中に置くことで式だと解釈されます。

以下のコードはどちらも同じ結果となります。

```javascript
(function(){...})()
(function(){...}())
```

# minify すると !function(){...}() になる理由

`(function(){...})()` を minify すると `!function(){...}()` になることがあります[^1]。

[^1]: 「なることがあります」と断定的な言い方をしない理由は、minify ツールに依存した結果であり、他の選択肢もあるためです。

```javascript
// minify 前
(function(){...})()

// minify 後
!function(){...}()
```

単項演算子（論理否定演算子）である `!` を用いて `function(){...}()` を関数式だと解釈させています。また、グループ化演算子を用いる（括弧で囲む）よりも 1 文字少ないです。minify するなら単項演算子が良いということですね。

# 関数文を関数式と解釈させる方法いろいろ

ここまでの内容で、関数文を関数式だと解釈させることができれば良いことが分かりました。

結局のところ、式の中に `function(){...}` を入れるだけなので、いくつもの実現方法を考えることができます。

```javascript
// グループ化演算子
(function(){...})()
(function(){...}())

// 配列リテラル
[function(){...}()]

// 単項演算子
!function(){...}()
+function(){...}()
-function(){...}()
~function(){...}()

// void, delete, typeof も単項演算子
void function(){...}()
delete function(){...}()
typeof function(){...}()

// 変数代入
x=function(){...}()

// カンマ演算子
1,function(){...}()

// テンプレートリテラル
`${function(){...}()}`
```

# アロー関数式の場合

アロー関数式（arrow function expression）の場合も、即時呼び出しするには括弧で囲む必要があります。

```javascript
// SyntaxError: Unexpected token '('
() => {...}()

// OK
(() => {...})()
```

ただし、アロー関数式は名前の通り式です。`function` のように文脈によって文になったり式になることは無いため、即時呼び出しする方法にバリエーションはありません。
bitset

bit演算を高速にしたいときに使う

bitset<長さ> bs(数値);

```c++
//<十進数>
bitset<8> bs2(131); 
// 7 ビット目から 0 ビット目への順番で、10000011 となる。

//<二進数>
bitset<8> bs3("10000011"); 
// 7 ビット目から 0 ビット目への順番で、10000011 となる。
bitset<2000> bs4("10000011"); 
// 1999 ビット目から 0 ビット目の順番で、0...010000011 となる。
```

```c++
//計算例
string A; cin >> A;
string B; cin >> B;

bitset<2000> A1(A);
bitset<2000> B1(B);
bitset<2000> ans = (A1 | B1);
```
東京産業技術大学院大学(AIIT)、第五期一般入試<不合格>でした

<h2>概要</h2>
2022年2月東京産業技術大学院大学の第五期一般入試を受験しました。
結果は、【不合格】でした。

<h2>前提</h2>
私は、2021年に新卒で都内SES事業会社に入社し、保険会社の汎用システムの保守開発に携わっています。
言語は、COBOLを使用しています。

大学時代にプログラミングに興味を持ち、プライベートではwebアプリの開発もしています。

エンジニア偏差値は40くらい…

<h2>大学院受験の経緯</h2>
<ol>
  <li>将来、海外でエンジニアをしたいので情報系大学院の学位がほしいから</li>
  <li>設計や、マネジメントを学びシステムを一から構築するために必要な知識を幅広く身に着けたいから</li>
<li>お勉強が好きだから！</li>
</ol>

将来的にアメリカのシリコンバレーでエンジニアとして、働きたいと思っています。
アメリカの優良企業に所属し、優秀なエンジニアと技術を語りながら、カフェラテでも飲んで、飽きたら起業したりする。
同窓会の招待状が来て、「あーごめん、俺いま、シリコンバレーエンジニアだから同窓会はいけないよ」と断る。
あとは、昼食においしいオードブルがある会社がいいですね。

<b>→要はせっかくエンジニアとして働くなら、トップレベルを目指したいということです。</b>
(これ話したら、親にも友達にも笑われました。どうぞみなさんも笑ってください。)


2番目は、会社に所属しているだけでは得られない知識を身に着けたいからです。
特に、設計や、マネジメント、事業面の知識ですね。
あとは、サーバーと、ネットワークやデータベースや開発手法や……

<b>→幅広く学びたいです。会社では触れる知識に偏りがでるので、</b>

<h2>なぜ、AIITか</h2>
選考基準は以下です。
<ol>
<li>働きながら通える</li>
<li>東京＆安い</li>
<li>研究よりグループワークをしたい</li>
</ol>

<h2>受験方法</h2>
AIITには以下の受験方法があります。
<ol>
<li>一般入試</li>
<li>自己推薦入試</li>
<li>社会人対象特別入試</li>
<li>高専専攻科対象推薦入試</li>
<li>企業推薦入試</li>
<li>キャリア再開開発入試</li>
</ol>

社会人の学びなおしがテーマにした専門職大学院なので、幅広い入試制度を設けています。
私は、社会人経験が少ないので、一般入試を受験しました。

<h2>受験の流れ</h2>

一般入試は以下の流れでした。
<ol>
<li>願書の提出</li>
<li>小論文の提出</li>
<li>口頭試問(面接試験)</li>
</ol>

<h3>願書の提出</h3>
・まず説明会に出ることをおすすめします。
→<a href="https://aiit.ac.jp/admission/guidance.html">AIIT説明会</a>

・願書では、志望動機や職務経歴書を提出します。
→<a href="https://aiit.ac.jp/admission/guidelines/">AIIT募集要項</a>

・志望動機を書く際に参考にしたこと
→AIITの特色について(<a href="https://aiit.ac.jp/education/pbl/interview/archive/">プロジェクトベースラーニング</a>)
→入学後の学習について(<a href="https://aiit.ac.jp/about/education/syllabus.html">シラバス</a>)
→卒業後の将来について(<a href="https://aiit.ac.jp/support/roll_model/careerdesign/">修了生のキャリアデザイン</a>)

<h3>小論文の提出</h3>
小論文では、課題文を読んで、文章の要約やキーワードと自分の経験を絡めて文章を書くことを求められます。
例年は学校で試験を行うようですが、パンデミックの影響で私はリモート試験を行いました。

過去問は教務課でもらえるので<a href="https://aiit.ac.jp/contact/">メール</a>してみてください。

<h3>口頭試問(面接試験)</h3>
20分程度の面接でした。

志望動機、小論文の回答について、ITに関する基礎知識などが問われます。
基本情報技術者資格程度の知識があれば問題ないと思います。

<h2>反省</h2>
タイトルでも書きましたが、結果不合格でした。
小論文の回答、面接での受け答えが不十分だったと思います。

受験料が払える限り受け続けるつもりなので、また勉強して再受験します。
だってシリコンバレーエンジニアになるんだもの！
大学院で勉強したいんだもの！
あきらめるって選択肢はないよ！

受験について質問がありましたら、気軽にどうぞ～

ごめんあそばせー
外部キーのテストコードが上手くいかない

簡易的なフリマアプリを作成中。

単体テストコードにて、エラーが発生。
下記ターミナル内のエラー内容。

```:ターミナル

Failures:

  1) OrderDelivery 購入者情報の保存 内容に問題がある場合 userが紐ついていなければ購入できない
     Failure/Error: expect(@order_delivery.errors.full_messages).to include( "" )
       expected [] to include ""
     # ./spec/models/order_delivery_spec.rb:81:in `block (4 levels) in <top (required)>'

  2) OrderDelivery 購入者情報の保存 内容に問題がある場合 itemが紐ついていなければ購入できない
     Failure/Error: expect(@order_delivery.errors.full_messages).to include( "Item must exist" )
       expected [] to include "Item must exist"
     # ./spec/models/order_delivery_spec.rb:86:in `block (4 levels) in <top (required)>'

```

order_deliveryモデルとuserモデル、itemモデルをそれぞれ外部キーとして設定しているが、なぜか紐ついていない様子。
（ローカルサーバーでは上手くいっているのに・・・）


```
expected [] to include
```
上記のエラー文は過去にも見たことがある。その時はバリデーションで記述したエラーメッセージと、テストコードで記述したエラーメッセージの内容が異なっていた事が原因だった。
（"can't be blank" を "can't be blanc" とスペルミスしたことでエラーになった）

今までも他のアプリで外部キーのテストコードは何回もしたが、バリデーションにエラーメッセージを記述した覚えはない。
google先生に聞いてみても、期待する回答は返ってこなかった。

もしかしたら、変数が間違っている？
何度もコードを読み返すが、間違っている様子もない。

そんな時、ふと思い付く。

__「あれ？そういえばimageも外部キーやでな？」__

models/item.rb のコードを見ると、確かにアソシエーションの記述がある。
しかもその下にはバリデーションの記述まである。

物は試しで該当のコードに追記してみる。

```Ruby:models/order_delivery.rb
class OrderDelivery
  include ActiveModel::Model
  attr_accessor :token
  attr_accessor :post_code, :address_id, :municipalities, :house_number, 
                :building, :tel, :order_id, :user_id, :item_id

  with_options presence: true do
    validates :user_id  #　追記
    validates :item_id　　　　#　追記
    validates :token
    validates :post_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "input correctly"}
    validates :municipalities
# 以下省略
    
```

__成功！！__

でもなんで？




しっかりとカリキュラムに書いていました。


``Formオブジェクトで実装したクラスはアソシエーションを定義することはできないため、バリデーションを行う事ができません。そのため、use_idに対してバリデーションを新たに設定します。``

エラー解決に２時間かかりました・・・
失敗は今しかできないと前向きに捉えて、明日からまた学習に励みます！
solidity TypeError: Integer constant expected の解決

```solidity
  Todo[] public todos;

  ...

  function updateTODO(uint _id, bool _state) public onlyMine(_id) {
    // 指定の id の TODO をアップデートする
    // アップデートは完了・非完了のみ
    Todo[_id].state = _state;
  }
```

```
Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/todo.sol

TypeError: Integer constant expected.
  --> project:/contracts/todo.sol:63:10:
   |
63 |     Todo[_id].state = _state;
   |          ^^^

```

compile err になるなぜ。

```diff
  function updateTODO(uint _id, bool _state) public onlyMine(_id) {
    // 指定の id の TODO をアップデートする
    // アップデートは完了・非完了のみ
-   Todo[_id].state = _state;
+   todos[_id].state = _state;
  }
```

こうだった。`todos` が変数じゃん・・・凡ミス
というかエラーメッセージがひどすぎる・・・。
システム開発で設計書がないあるあるを回避できるか

アジャイル開発では、ドキュメントを作らない！なんてのは言い訳で、最低限のドキュメントは必要だと思うんですよ。
『ソースコード読め』『ソースコードが正』『今ある動作しているシステムが仕様』だとテスト部隊が困ってしまう。

その時の問題点としては、テストする人のスキルによってキャッチアップできるかできないかが分かれてしまう。
テスト仕様書の期待値は明確である必要があるのです。

一方で開発部隊は実装・単体テストなどやることが多い中で、設計書にフィードバックすることの優先度が下がりがち。というのも理解できる。
問題点としては、ドキュメントが古いので結果ソースコードが正になってしまうのです。

私なりに、両方経験した身として、下記を提案していきたいなと考えています。

# 設計書の切り分け

開発にて必要な設計書を列挙しMoSCoW分析にて重要度付けを行いました。
さらに設計書の内容についても同様に重要度付けを行いました。

## MoSCoW分析定義

|MoSCoW|説明|
|:--|:--|
|Must|必須の要件。満たせない場合には、認識齟齬が生じる|
|Should|満たせないと影響が大きい要件。対応要否の影響を考慮して対応可否判断が必要な要件|
|Could|できれば対応したい要件。コストやリソースによっては対応を見送ってもよい要件|
|Won‘t|対応不要な要件。将来的なものとして先送りしても問題ない要件|

## 持論をまとめたリスト
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1588937/b79298d2-adca-5e04-62b4-839a0841378e.png" width="90%">

# あとがき
改めてまとめてみると『Must』が多いように思えますね。
『Must』を減らして気持ちを楽にするとしたら、開発側で必要なドキュメントか、テスト側で必要なドキュメントかでしょうか。

ですがそれはあまり意味がないので・・・。

- ドキュメントの記載粒度を粗くする
10人中7、8人が同じ解釈になれば、程よい粒度なんじゃないかと考えたりしてます。
内容的には齟齬が発生しやすいと思われる振る舞いなどがあれば、そこを重点的に記載することを意識しています。
『Must』の内容はエンジニアが【苦】にならない粒度感ということが重要だと考えています。

- 共同編集する
結論、エクセルなどのバージョン管理・ファイル管理は往々にして煩雑になりやすく共同編集をすることで、
そのあたりの課題感が解決できると考えています。

 - バックエンド  
OpenAPI（Swagger）や『.md(Markdown)』を使用する
※厳密にいえば共同編集ではないのですが、JsonやらYamlなのでコードと一緒にバージョン管理してしまうのがいいと思ってます  

 - フロントエンド
Notionやスプレッドシート  
ワイヤーはXDですかね？（XD使ったことないですが・・・共同編集できたような）

色々書きましたが、受託案件だと納品物として設計書を納品するでしょうから、
一概に絞れるものでもないのが現状だと思います。

ドキュメントの種類・記載内容などの方向性は、しっかり先方とすり合わせを行ってFixさせてくださいね。
（命を守る観点で大事）
【JavaScript関数ドリル】Lodash関数の実装【勉強用】_.lastIndexOf関数

#【JavaScript関数ドリル】初級編の_.lastIndexOf関数の実装のアウトプット

       
```javascript:_.lastIndexOf関数の挙動
_.lastIndexOf([1, 2, 1, 2], 2);
// => 3
 
// Search from the `fromIndex`.
_.lastIndexOf([1, 2, 1, 2], 2, 2);
// => 1
```
配列から第2引数の値を末尾から検索し、最初の値のインデックス番号を返す。
第3引数がある場合は、第3引数の値のインデックス番号の位置から先頭に向かって検索する。
##_.lastIndexOf関数の課題内容
https://youtu.be/qn8XZwXPgvg

##_.lastIndexOf関数に取り組む前の状態
- 配列をarray.length-1からデクリメントし、第2引数と一致するもののインデックス番号を返せばよさそうだ

##_.lastIndexOf関数に取り組んだ後の状態
- 初めて解答とほぼ同じコードを実装できた
- 一致するものがなければ-1を返すというLodashの説明を見落としていたため、undefinedが返ってくる
- 普段からドキュメントを読むときに英文を読み飛ばして例文しか見ないため、このようなミスが発生した
- 引数のデフォルト値の設定の仕方についてよく理解できた


##_.lastIndexOf関数の実装コード

```javascript:
const lastIndexOf = (array, value, fromIndex = array.length - 1) => {
    for (let i = fromIndex; 0 <= i; i--) {
        if (value === array[i]) {
            return i;
        };
    };
};

console.log(lastIndexOf([1, 2, 1, 2], 2));
// => 3

console.log(lastIndexOf([1, 2, 1, 2], 2, 2));
// => 1
```



##_.lastIndexOf関数の解答コード

```javascript:
function lastIndexOf(array, value, fromIndex = array.length - 1) {
  for(let i = fromIndex; 0 <= i; i--) {
    if(array[i] === value) {
      return i;
    }
  }

  return -1;
}

console.log( lastIndexOf([1, 2, 1, 2], 2) );
// => 3

// Search from the `fromIndex`.
console.log( lastIndexOf([1, 2, 1, 2], 2, 2) );
// => 1
```