江端さんの忘備録

以前、

Before, I wrote a diary whose title was

「ただ、条文上、メイド喫茶や深夜のバーの営業自粛は「要請」することはできても、「禁止」することはできないようです。」

However, according to the provisions, it seems that maid cafes and bar bars at midnight can be "requested" but not "prohibited"

という日記を書きました。

残念ながら、現在、「パチンコ店」で、この問題が顕在化しています。

Unfortunately, this problem is now becoming apparent at “pachinko parlors”.

具体的には、

In particular,

(1)新型コロナ感染症の感染リスクの高いパチンコ店が、営業を続けていることに対して、

(1) For pachinko stores that are at high risk of infection with new corona infections,

(2)その制裁として、自治体が「店名公表」を行い、

(2) As a sanction, the local government will "publish the store name",

(3)その結果、それらのパチンコ店に、遠方から客が殺到する

(3) As a result, those pachinko parlors are flooded with customers from afar.

という、負の連鎖が発生しています。

The negative chain happens.

-----

以前の日記にも記載したように、「自粛"要請"」から「自粛"指示"」になったところで、新型インフルエンザ等対策特別措置法には、罰則規定がありません。

As mentioned in the previous diary, there is no penal provision in the Enforcement Ordinance for the Special Measures Law for Countermeasures against New Influenza, etc., even when "self-restraint "request" changed to self-restraint "instruction".

少なくとも、この法律では、パチンコ店の営業は止められません。

At least this law doesn't stop the operation of pachinko parlors.

とすると、別の法律との「合わせ技」で対応することになりそうです。

If so, it seems that it will be handled by a "matching technique" with another law.

ざっと調べてみたところ、「行政手続法」の、第2条4項の「不利益処分」が、地方自治体の対抗手段になるのかなーと思っています ――

After a quick survey, I think it will be a countermeasure of local governments, "Disadvantageous Disposition" in Article 2.4 in the “Administrative Procedures Act”,

いわゆる「営業停止処分」です。

This is so-called “business suspension”.

しかし、パチンコ店の営業許認可は、店舗所在地の管轄の警察署にあるようです。

However, the pachinko parlor's business license seems to be at the police station that has jurisdiction over the store location.

また、今回のケースでの、営業停止処分は前例がないこともあり、そもそも法律上の解釈に関する検討は絶無です(当然ですが)。

In addition, there is no precedent for the suspension of operations in this case, so there is absolutely no need to consider legal interpretations (of course,not).

そう考えていくと、 ―― 民意はさておき ―― 行政権の濫用、という考え方もできます。

If you think so, you can think of abuse of administrative power ---- People's will aside.

-----

地方自治体:「営業停止処分」

Local government: “Business suspension”

パチンコ店:「行政不服審査法に基づく意義申立ての請求」(行服法に、即時抗告みたいなものがあるのかは、私は知りません)

Pachinko parlors: "Request for significance based on the Administrative Appeal Law" (I don't know if there is an immediate appeal in the Administrative Law)

地方自治体:「意義申立の棄却」

Local government: "Rejection of significance claim"

パチンコ店:「裁判所に対する、行政命令無効の仮処分の申立」

Pachinko parlors: "Petition for provisional disposition of administrative order against the court"

という流れになって、

Then,

「泥沼」確実。

"Mudification" will be confirmed.

(続く)

(To be continued)

2020/05,江端さんの忘備録

昨日の日記を読んで頂いた、私のプログラミングの師匠であられるところのSさんからメールを頂きました。

I received an e-mail from Mr. S, who is my programming mentor and has read the diary yesterday.

メールの要旨を抜粋させて頂きます(本人無許諾だけど、多分許して頂けると思っています)

The following is a summary of the email ((I have not given permission Mr.S , but I think that he will give it to me)

■『"Excel "で十分じゃん?(by 江端)』 まさに「これ」、かと思いました。

- "Isn't" Excel "enough? (by Ebata) ”I thought it was exactly this.

■私も、ティーンエージャー(大学生未満)はプログラムを書かないほうがよい、と考えています。

- I also think teenagers (under college) should not write programs.

-----

加えて、

In addition,

■うちの子供達には、行列と微分積分だけはどの世界に行っても必要なので手を抜かせないようにしています。

- I try to make my children study only matrices and calculus because they need to be in any world.

この最後の一文が、私の胸を貫きました。

I was impressed with this last sentence.

―― 行列と微分積分なくして、世界を理解する手段なし

"Without matrix and calculus, there is no way to understand the world"

これは、世界中のどんな優れた哲学や宗教のドグマも敵わない、絶対的真理です。

This is an absolute truth that overwhelms any great philosophical or religious dogma in the world.

-----

話を戻しますが、本当にエクセルだけで、コンピュータで行う計算のかなりの部分を網羅できるんです。

Let's get back to it. only Excel can cover a great deal of computer calculations.

「Excelで操る! ここまでできる科学技術計算」

"Operate with Excel! Scientific calculation that can be done up to here"

「はじめての人工知能 Excelで体験しながら学ぶAI」

"First artificial intelligence, AI to learn while experiencing with Excel"

には、コラム執筆の際には、大変お世話になりましたし、

These two books are very helpful to me when I wrote the column,

Sさんから紹介頂いた、

Mr. S introduceded me, the following two book.

「Excelでわかる機械学習 超入門 AIのモデルとアルゴリズムがわかる」

"Understanding machine learning, super introduction, AI models and algorithms understood in Excel"

「Excelでわかるディープラーニング超入門 【RNN・DQN編】」

"Deep Learning Super Intro to Excel [RNN / DQN Edition]"

などもあります。

これらの本の凄いところは、数式なんぞ理解できなくても、エクセルの動きを見ているだけで、計算の動きが「目で見える」ということなのです。

The great thing about these books is that even if I can't understand mathematical formulas, I can "see" the motion of calculation just by looking at the motion of Excel.

その後に数式を読むと『あ! そういうことか!!』と理解できるようになる、という点が良いのです。

After that, when I read the formula, "Ah! That kind of thing! !! It is good that I can understand.

つまり、子どもであれ、大人であれ、数式の理解の心理的な壁の高さを、限りなくゼロまで下げるのです。

In other words, whether you are a child or an adult, the height of psychological barriers to understanding mathematical formulas is lowered to zero.

-----

うん、なんか使命感に燃えてきました。

Yeah, I was burning with a sense of mission.

我が国を、世界に冠たる

In order to make Japan a world-class

「スプレッドシート(Excel)リテラシー国(×プログラミングリテラシー国)」

"spreadsheet (Excel) literacy country (not programming literacy country),"

にする為にも、

I have to write a book whose title is

『夏休みの最後の3日間で、それらしい自由研究レポートを作成する為のEXCEL入門』

"Introduction to EXCEL to create such a free research report in the last three days of summer vacation"

の執筆が急がれると、思っています ―― 勝手に。

urgently and selfishly

ネタはあります。

I have several stories.

出版業界の皆様の、お声がけをお待ちしております。

I look forward to inviting me from everyone in the publishing industry.

2020,江端さんの忘備録

以前の仕事の見直しが必要となっていますが、その作業を開始すると、その時の恐怖が再現されてきて、心臓がバクバクして、呼吸が苦しくなります。

I need to review my previous work. When you start the work, the fear at that time is reproduced, my heart beats, and breathing becomes difficult.

こういう症状が出るような場合、「初動」が大切なことは、自分でこれまで色々調べて知っていました。

I know that "initial response" is important, whenever I have such symptoms. Because I wrote about it in my columns.

すぐに、心療内科への電話予約を試みましたが、全ての医院で『初診は6月以降』と言われてしまいました。

Immediately, I tried to make a telephone reservation to several clinics of Department of Psychiatry and Internal Medicine, however at all the clinics I was told that my first visit was after June.

これも、連鎖的な医療崩壊の一端かもしれません。

This may also be part of the chain of medical collapse.

というか、

Rather, I am thinking that,

―― 国家レベルの「心の崩壊」が始まっている

The national level "disintegration of mental health" has begun

のかもしれないなぁ、と考えています。

2020,江端さんの忘備録

(昨日の続きです)

(Continuation from yesterday)

つまるところ、「人が集まらなければ、クラスターは発生することができない」のです。

After all, "If you don't get together, you can't create a cluster."

そして、今のところ、我が国に関しては、この「クラスター潰し」が、ぎりぎり有効な範囲にあります。

And so far, in Japan, this "cluster crushing" is in a marginally effective range.

もっとも、我が国でも、この「クラスター潰し」も限界に近くなってきているようです。

However, in Japan, this "cluster crushing" seems to be reaching its limit.

これが「感染経路が分からない」というものです。

This is "we cannot know the route of infection."

ちなみに、欧米では、「クラスター潰し」のフェーズを離れ、手遅れになっているのはご存知の通りです。

By the way, as you know, in Europe and the United States, it is too late to leave the "cluster-crushing" phase.

今、これから発生する数万人規模の死体収容所を作っている ―― って、どこの世界線(ディストピア)の話? と聞きたくなります

Now, they are building tens of thousands of corpses in the future. I want to ask what the worldline (dystopia) is.

-----

「クラスター潰し」の観点から、学校、会社、集会、イベントを自粛するのは、(個人の経済的事情を無視するのであれば)最適戦略です。

From a "cluster crushing" perspective, refraining from schools, companies, gatherings, and events is an optimal strategy (if you ignore the economics of an individual).

しかし、学校、会社、集会、イベントを自粛しながら「夜の歓楽街に出掛ける」という人間は、はっきり言わせて貰えば、

However, persons who "are going to the red light district at night" while restraining schools, companies, gatherings, and events,

『あんたたち、脳があるのか?』

"Do you have a brain?"

と尋ねたくなるくらい、理解不能です。

I do not understand them at all.

-----

そこで、私、経済活動をそこそこのレベルで維持しつつ、クラスター発生を防止する一つの案を提案したいと思います。

Therefore, I would like to propose a proposal to prevent clusters while maintaining economic activity at a reasonable level.

「音声コミュニケーションの絶対的な禁止命令」

"Absolute ban on voice communication"

です。

■いかなる状況であっても、対人間で会話をしてはならない(例外なし)。

- You should not speak to anyone at any place.

■コミュニケーションは、一定の距離(数メートル)を維持しながら、全て、SNS等のリアルタイムのテキストメッセージのみでで実施する。

- All communication is carried out using only real-time text messages such as SNS while maintaining a certain distance (a few meters).

■スマホが使えない人は、メッセージボードで会話をする。

- Talk on the message board if you can't use a smartphone.

■どうしても音声による会話が必要であれば、全て電話で行う、または、電話会議を実施する。

- If a voice conversation is absolutely necessary, you can use a phone or telephone conference.

これは、現時点で多くの会社で実施されています。

Many companies are currently implementing this.

この条件が満たされるのであれば、私は、バー、キャバクラ、メイド喫茶は再開しても良いと考えています。

If this condition is fulfilled, I will resume bar, cabaret club, and maid cafe.

-----

ところで、

By the way,

江端家は、一度、家族4人で、秋葉原にあるメイド喫茶なるものに行ったことがあります。

The Ebata family once went to a maid cafe in Akihabara.

待ち列に並んでいる最中、家族全員が、不快と酸欠で顔色が悪くなっていました。

While in the queue, the whole family had turned pale due to discomfort and lack of oxygen.

私が「離脱」を提案したところ、1秒後に家族全員が同意して、5秒後に店の外に敗走しました。

When I proposed "withdrawal," the whole family agreed one second later and broke out of the store five seconds later.

その時、シュタインズゲートの中に登場していた「メイド喫茶」への幻想は、私の中で、完全に破壊されました。

At that time, the illusion of a "maid cafe" that appeared in Steins Gate was completely destroyed in me.

閑話休題

Restless talk

(続く)

(To be continued)

2020,江端さんの技術メモ

江端の環境でのローカルな場所 C:\Users\ebata\Desktop\bouncy2

C:\Users\ebata>cd C:\Users\ebata\Desktop\bouncy2
cd /c/Users/ebata/Desktop/bouncy2
python3 httpsrv.py
http://localhost:8080 で起動

 

  • 2020/03/14

     

  • 背景
    • ■これからは「C/C++ → Go」と「JavaScript → Webassembly」とシフトしながら色々やっていこうと思っている■正直、どっちも難しい。そういう時は、サンプルをパクって勉強するのが正解 ―― と思っている
  • 目的
  • 環境
    • ■Windows7 or 10
    • ■Go と python3 をインストールしてある
  • やってみたこと
    • ■サンプルプログラムをダウンロードして、コンパイルしてみた
      • ~ https://github.com/stdiopt/gowasm-experiments/tree/master/bouncy
      • コマンドプロンプトからこんな感じでコンパイルできた
        • $ set GOOS=js
        • $ set  GOARCH=wasm
        • $ go build -o main.wasm main.go
        • ちなみに、bashの環境があれば、build.shでコンパイルできる
      • 実際には、コンパイルしなくても、バイナリコード(main.wasm)も、ダウンロードの中に入っているので、コンパイルは不要だったが
    • ■ローカルサーバとしては、色々試してみた
      • python3 -m http.server 8080
      • Goでサーバも作ってみた
      • Perlでもやってみた
    • ■動画がどうしても出てこない
    • ■ここから丸2日間の格闘のスタート
      • もう、色々探しまくった
  • 確認していた問題点
    • ■Google Chromoから、→ 「その他のツール」 → 「ディベロッパーツール」 → 
      • Uncaught (in promise) TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.この「Expected 'application/wasm'.」がどうにも、不味いらしい ―― が、解決方法が、どうにも見つからない
    • ■kobore.netのサーバに上げても、改善が見られず
  • ローカルサーバを作ってみた
    • ■httpsrv.pyを作った
      #!/usr/bin/env python3
      import http.server
        import socketserver
        
        PORT =
      8080
        
        Handler = http.server.SimpleHTTPRequestHandler
        Handler.extensions_map.update({
        '.wasm': 'application/wasm',
        })
        
        socketserver.TCPServer.allow_reuse_address =
      True
      with socketserver.TCPServer(("", PORT), Handler) as httpd:
        httpd.allow_reuse_address =
      True
      print("serving at port", PORT)
        httpd.serve_forever()
      
  • ■httpsrv.pyを起動した
    • $ python3 httpsrv.py
  • http://localhost:8080 で起動
    • ■動いた
      ■動かなかったら、chromo → 「設定」 → 「閲覧履歴データの削除」でキャッシュをクリアてみること

以上

httpsrv.py

#!/usr/bin/env python3

import http.server
import socketserver

PORT = 8080

Handler = http.server.SimpleHTTPRequestHandler
Handler.extensions_map.update({
    '.wasm': 'application/wasm',
})

socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", PORT), Handler) as httpd:
    httpd.allow_reuse_address = True
    print("serving at port", PORT)
    httpd.serve_forever()

main.go

//Wasming
// compile: GOOS=js GOARCH=wasm go build -o main.wasm ./main.go
package main

import (
	"fmt"
	"math"
	"math/rand"
	"strconv"
	"syscall/js"
)

var (
	width      float64
	height     float64
	mousePos   [2]float64
	ctx        js.Value    // "syscall/js"から引っ張られる
	lineDistSq float64 = 100 * 100
)

func main() {

	// Init Canvas stuff
	doc := js.Global().Get("document")
	canvasEl := doc.Call("getElementById", "mycanvas")
	width = doc.Get("body").Get("clientWidth").Float()
	height = doc.Get("body").Get("clientHeight").Float()
	canvasEl.Set("width", width)
	canvasEl.Set("height", height)
	ctx = canvasEl.Call("getContext", "2d")

	done := make(chan struct{}, 0)

	dt := DotThing{speed: 160, size: 6}

	mouseMoveEvt := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		e := args[0]
		mousePos[0] = e.Get("clientX").Float()
		mousePos[1] = e.Get("clientY").Float()
		return nil
	})
	defer mouseMoveEvt.Release()

	// Event handler for count range
	countChangeEvt := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		evt := args[0]
		intVal, err := strconv.Atoi(evt.Get("target").Get("value").String())
		if err != nil {
			println("Invalid value", err)
			return nil
		}
		dt.SetNDots(intVal)
		return nil
	})
	defer countChangeEvt.Release()

	// Event handler for speed range
	speedInputEvt := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		evt := args[0]
		fval, err := strconv.ParseFloat(evt.Get("target").Get("value").String(), 64)
		if err != nil {
			println("invalid value", err)
			return nil
		}
		dt.speed = fval
		return nil
	})
	defer speedInputEvt.Release()

	// Event handler for size
	sizeChangeEvt := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		evt := args[0]
		intVal, err := strconv.Atoi(evt.Get("target").Get("value").String())
		if err != nil {
			println("invalid value", err)
			return nil
		}
		dt.size = intVal
		return nil
	})
	defer sizeChangeEvt.Release()

	// Event handler for lines toggle
	lineChangeEvt := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		evt := args[0]
		dt.lines = evt.Get("target").Get("checked").Bool()
		return nil
	})
	defer lineChangeEvt.Release()

	// Event handler for dashed toggle
	dashedChangeEvt := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		evt := args[0]
		dt.dashed = evt.Get("target").Get("checked").Bool()
		return nil
	})
	defer dashedChangeEvt.Release()

	doc.Call("addEventListener", "mousemove", mouseMoveEvt)
	doc.Call("getElementById", "count").Call("addEventListener", "change", countChangeEvt)
	doc.Call("getElementById", "speed").Call("addEventListener", "input", speedInputEvt)
	doc.Call("getElementById", "size").Call("addEventListener", "input", sizeChangeEvt)
	doc.Call("getElementById", "dashed").Call("addEventListener", "change", dashedChangeEvt)
	doc.Call("getElementById", "lines").Call("addEventListener", "change", lineChangeEvt)

	dt.SetNDots(100)
	dt.lines = false
	var renderFrame js.Func
	var tmark float64
	var markCount = 0
	var tdiffSum float64

	renderFrame = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		now := args[0].Float()
		tdiff := now - tmark
		tdiffSum += now - tmark
		markCount++
		if markCount > 10 {
			doc.Call("getElementById", "fps").Set("innerHTML", fmt.Sprintf("FPS: %.01f", 1000/(tdiffSum/float64(markCount))))
			tdiffSum, markCount = 0, 0
		}
		tmark = now

		// Pull window size to handle resize
		curBodyW := doc.Get("body").Get("clientWidth").Float()
		curBodyH := doc.Get("body").Get("clientHeight").Float()
		if curBodyW != width || curBodyH != height {
			width, height = curBodyW, curBodyH
			canvasEl.Set("width", width)
			canvasEl.Set("height", height)
		}
		dt.Update(tdiff / 1000)

		js.Global().Call("requestAnimationFrame", renderFrame)
		return nil
	})
	defer renderFrame.Release()

	// Start running
	js.Global().Call("requestAnimationFrame", renderFrame)

	<-done

}

// DotThing manager
type DotThing struct {
	dots   []*Dot
	dashed bool
	lines  bool
	speed  float64
	size   int
}

// Update updates the dot positions and draws
func (dt *DotThing) Update(dtTime float64) {
	if dt.dots == nil {
		return
	}
	ctx.Call("clearRect", 0, 0, width, height)

	// Update
	for i, dot := range dt.dots {
		dir := [2]float64{}
		// Bounce
		if dot.pos[0] < 0 {
			dot.pos[0] = 0
			dot.dir[0] *= -1
		}
		if dot.pos[0] > width {
			dot.pos[0] = width
			dot.dir[0] *= -1
		}

		if dot.pos[1] < 0 {
			dot.pos[1] = 0
			dot.dir[1] *= -1
		}

		if dot.pos[1] > height {
			dot.pos[1] = height
			dot.dir[1] *= -1
		}
		dir = dot.dir

		ctx.Set("globalAlpha", 0.5)
		ctx.Call("beginPath")
		ctx.Set("fillStyle", fmt.Sprintf("#%06x", dot.color))
		ctx.Set("strokeStyle", fmt.Sprintf("#%06x", dot.color))
		// Dashed array ref: https://github.com/golang/go/blob/release-branch.go1.11/src/syscall/js/js.go#L98
		ctx.Call("setLineDash", []interface{}{})
		if dt.dashed {
			ctx.Call("setLineDash", []interface{}{5, 10})
		}
		ctx.Set("lineWidth", dt.size)
		ctx.Call("arc", dot.pos[0], dot.pos[1], dt.size, 0, 2*math.Pi)
		ctx.Call("fill")

		mdx := mousePos[0] - dot.pos[0]
		mdy := mousePos[1] - dot.pos[1]
		d := math.Sqrt(mdx*mdx + mdy*mdy)
		if d < 200 {
			ctx.Set("globalAlpha", 1-d/200)
			ctx.Call("beginPath")
			ctx.Call("moveTo", dot.pos[0], dot.pos[1])
			ctx.Call("lineTo", mousePos[0], mousePos[1])
			ctx.Call("stroke")
			if d > 100 { // move towards mouse
				dir[0] = (mdx / d) * 2
				dir[1] = (mdy / d) * 2
			} else { // do not move
				dir[0] = 0
				dir[1] = 0
			}
		}

		if dt.lines {
			for _, dot2 := range dt.dots[i+1:] {
				mx := dot2.pos[0] - dot.pos[0]
				my := dot2.pos[1] - dot.pos[1]
				d := mx*mx + my*my
				if d < lineDistSq {
					ctx.Set("globalAlpha", 1-d/lineDistSq)
					ctx.Call("beginPath")
					ctx.Call("moveTo", dot.pos[0], dot.pos[1])
					ctx.Call("lineTo", dot2.pos[0], dot2.pos[1])
					ctx.Call("stroke")
				}
			}
		}

		dot.pos[0] += dir[0] * dt.speed * dtTime
		dot.pos[1] += dir[1] * dt.speed * dtTime
	}
}

// SetNDots reinitializes dots with n size
func (dt *DotThing) SetNDots(n int) {
	dt.dots = make([]*Dot, n)
	for i := 0; i < n; i++ {
		dt.dots[i] = &Dot{
			pos: [2]float64{
				rand.Float64() * width,
				rand.Float64() * height,
			},
			dir: [2]float64{
				rand.NormFloat64(),
				rand.NormFloat64(),
			},
			color: uint32(rand.Intn(0xFFFFFF)),
			size:  10,
		}
	}
}

// Dot represents a dot ...
type Dot struct {
	pos   [2]float64
	dir   [2]float64
	color uint32
	size  float64
}

build.sh

#!/bin/sh

GOOS=js GOARCH=wasm go build -o main.wasm ./main.go

wasm_exec.js

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

(() => {
	// Map multiple JavaScript environments to a single common API,
	// preferring web standards over Node.js API.
	//
	// Environments considered:
	// - Browsers
	// - Node.js
	// - Electron
	// - Parcel

	if (typeof global !== "undefined") {
		// global already exists
	} else if (typeof window !== "undefined") {
		window.global = window;
	} else if (typeof self !== "undefined") {
		self.global = self;
	} else {
		throw new Error("cannot export Go (neither global, window nor self is defined)");
	}

	if (!global.require && typeof require !== "undefined") {
		global.require = require;
	}

	if (!global.fs && global.require) {
		global.fs = require("fs");
	}

	const enosys = () => {
		const err = new Error("not implemented");
		err.code = "ENOSYS";
		return err;
	};

	if (!global.fs) {
		let outputBuf = "";
		global.fs = {
			constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
			writeSync(fd, buf) {
				outputBuf += decoder.decode(buf);
				const nl = outputBuf.lastIndexOf("\n");
				if (nl != -1) {
					console.log(outputBuf.substr(0, nl));
					outputBuf = outputBuf.substr(nl + 1);
				}
				return buf.length;
			},
			write(fd, buf, offset, length, position, callback) {
				if (offset !== 0 || length !== buf.length || position !== null) {
					callback(enosys());
					return;
				}
				const n = this.writeSync(fd, buf);
				callback(null, n);
			},
			chmod(path, mode, callback) { callback(enosys()); },
			chown(path, uid, gid, callback) { callback(enosys()); },
			close(fd, callback) { callback(enosys()); },
			fchmod(fd, mode, callback) { callback(enosys()); },
			fchown(fd, uid, gid, callback) { callback(enosys()); },
			fstat(fd, callback) { callback(enosys()); },
			fsync(fd, callback) { callback(null); },
			ftruncate(fd, length, callback) { callback(enosys()); },
			lchown(path, uid, gid, callback) { callback(enosys()); },
			link(path, link, callback) { callback(enosys()); },
			lstat(path, callback) { callback(enosys()); },
			mkdir(path, perm, callback) { callback(enosys()); },
			open(path, flags, mode, callback) { callback(enosys()); },
			read(fd, buffer, offset, length, position, callback) { callback(enosys()); },
			readdir(path, callback) { callback(enosys()); },
			readlink(path, callback) { callback(enosys()); },
			rename(from, to, callback) { callback(enosys()); },
			rmdir(path, callback) { callback(enosys()); },
			stat(path, callback) { callback(enosys()); },
			symlink(path, link, callback) { callback(enosys()); },
			truncate(path, length, callback) { callback(enosys()); },
			unlink(path, callback) { callback(enosys()); },
			utimes(path, atime, mtime, callback) { callback(enosys()); },
		};
	}

	if (!global.process) {
		global.process = {
			getuid() { return -1; },
			getgid() { return -1; },
			geteuid() { return -1; },
			getegid() { return -1; },
			getgroups() { throw enosys(); },
			pid: -1,
			ppid: -1,
			umask() { throw enosys(); },
			cwd() { throw enosys(); },
			chdir() { throw enosys(); },
		}
	}

	if (!global.crypto) {
		const nodeCrypto = require("crypto");
		global.crypto = {
			getRandomValues(b) {
				nodeCrypto.randomFillSync(b);
			},
		};
	}

	if (!global.performance) {
		global.performance = {
			now() {
				const [sec, nsec] = process.hrtime();
				return sec * 1000 + nsec / 1000000;
			},
		};
	}

	if (!global.TextEncoder) {
		global.TextEncoder = require("util").TextEncoder;
	}

	if (!global.TextDecoder) {
		global.TextDecoder = require("util").TextDecoder;
	}

	// End of polyfills for common API.

	const encoder = new TextEncoder("utf-8");
	const decoder = new TextDecoder("utf-8");

	global.Go = class {
		constructor() {
			this.argv = ["js"];
			this.env = {};
			this.exit = (code) => {
				if (code !== 0) {
					console.warn("exit code:", code);
				}
			};
			this._exitPromise = new Promise((resolve) => {
				this._resolveExitPromise = resolve;
			});
			this._pendingEvent = null;
			this._scheduledTimeouts = new Map();
			this._nextCallbackTimeoutID = 1;

			const setInt64 = (addr, v) => {
				this.mem.setUint32(addr + 0, v, true);
				this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true);
			}

			const getInt64 = (addr) => {
				const low = this.mem.getUint32(addr + 0, true);
				const high = this.mem.getInt32(addr + 4, true);
				return low + high * 4294967296;
			}

			const loadValue = (addr) => {
				const f = this.mem.getFloat64(addr, true);
				if (f === 0) {
					return undefined;
				}
				if (!isNaN(f)) {
					return f;
				}

				const id = this.mem.getUint32(addr, true);
				return this._values[id];
			}

			const storeValue = (addr, v) => {
				const nanHead = 0x7FF80000;

				if (typeof v === "number") {
					if (isNaN(v)) {
						this.mem.setUint32(addr + 4, nanHead, true);
						this.mem.setUint32(addr, 0, true);
						return;
					}
					if (v === 0) {
						this.mem.setUint32(addr + 4, nanHead, true);
						this.mem.setUint32(addr, 1, true);
						return;
					}
					this.mem.setFloat64(addr, v, true);
					return;
				}

				switch (v) {
					case undefined:
						this.mem.setFloat64(addr, 0, true);
						return;
					case null:
						this.mem.setUint32(addr + 4, nanHead, true);
						this.mem.setUint32(addr, 2, true);
						return;
					case true:
						this.mem.setUint32(addr + 4, nanHead, true);
						this.mem.setUint32(addr, 3, true);
						return;
					case false:
						this.mem.setUint32(addr + 4, nanHead, true);
						this.mem.setUint32(addr, 4, true);
						return;
				}

				let id = this._ids.get(v);
				if (id === undefined) {
					id = this._idPool.pop();
					if (id === undefined) {
						id = this._values.length;
					}
					this._values[id] = v;
					this._goRefCounts[id] = 0;
					this._ids.set(v, id);
				}
				this._goRefCounts[id]++;
				let typeFlag = 1;
				switch (typeof v) {
					case "string":
						typeFlag = 2;
						break;
					case "symbol":
						typeFlag = 3;
						break;
					case "function":
						typeFlag = 4;
						break;
				}
				this.mem.setUint32(addr + 4, nanHead | typeFlag, true);
				this.mem.setUint32(addr, id, true);
			}

			const loadSlice = (addr) => {
				const array = getInt64(addr + 0);
				const len = getInt64(addr + 8);
				return new Uint8Array(this._inst.exports.mem.buffer, array, len);
			}

			const loadSliceOfValues = (addr) => {
				const array = getInt64(addr + 0);
				const len = getInt64(addr + 8);
				const a = new Array(len);
				for (let i = 0; i < len; i++) {
					a[i] = loadValue(array + i * 8);
				}
				return a;
			}

			const loadString = (addr) => {
				const saddr = getInt64(addr + 0);
				const len = getInt64(addr + 8);
				return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
			}

			const timeOrigin = Date.now() - performance.now();
			this.importObject = {
				go: {
					// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
					// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
					// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
					// This changes the SP, thus we have to update the SP used by the imported function.

					// func wasmExit(code int32)
					"runtime.wasmExit": (sp) => {
						const code = this.mem.getInt32(sp + 8, true);
						this.exited = true;
						delete this._inst;
						delete this._values;
						delete this._goRefCounts;
						delete this._ids;
						delete this._idPool;
						this.exit(code);
					},

					// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
					"runtime.wasmWrite": (sp) => {
						const fd = getInt64(sp + 8);
						const p = getInt64(sp + 16);
						const n = this.mem.getInt32(sp + 24, true);
						fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
					},

					// func resetMemoryDataView()
					"runtime.resetMemoryDataView": (sp) => {
						this.mem = new DataView(this._inst.exports.mem.buffer);
					},

					// func nanotime1() int64
					"runtime.nanotime1": (sp) => {
						setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
					},

					// func walltime1() (sec int64, nsec int32)
					"runtime.walltime1": (sp) => {
						const msec = (new Date).getTime();
						setInt64(sp + 8, msec / 1000);
						this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
					},

					// func scheduleTimeoutEvent(delay int64) int32
					"runtime.scheduleTimeoutEvent": (sp) => {
						const id = this._nextCallbackTimeoutID;
						this._nextCallbackTimeoutID++;
						this._scheduledTimeouts.set(id, setTimeout(
							() => {
								this._resume();
								while (this._scheduledTimeouts.has(id)) {
									// for some reason Go failed to register the timeout event, log and try again
									// (temporary workaround for https://github.com/golang/go/issues/28975)
									console.warn("scheduleTimeoutEvent: missed timeout event");
									this._resume();
								}
							},
							getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
						));
						this.mem.setInt32(sp + 16, id, true);
					},

					// func clearTimeoutEvent(id int32)
					"runtime.clearTimeoutEvent": (sp) => {
						const id = this.mem.getInt32(sp + 8, true);
						clearTimeout(this._scheduledTimeouts.get(id));
						this._scheduledTimeouts.delete(id);
					},

					// func getRandomData(r []byte)
					"runtime.getRandomData": (sp) => {
						crypto.getRandomValues(loadSlice(sp + 8));
					},

					// func finalizeRef(v ref)
					"syscall/js.finalizeRef": (sp) => {
						const id = this.mem.getUint32(sp + 8, true);
						this._goRefCounts[id]--;
						if (this._goRefCounts[id] === 0) {
							const v = this._values[id];
							this._values[id] = null;
							this._ids.delete(v);
							this._idPool.push(id);
						}
					},

					// func stringVal(value string) ref
					"syscall/js.stringVal": (sp) => {
						storeValue(sp + 24, loadString(sp + 8));
					},

					// func valueGet(v ref, p string) ref
					"syscall/js.valueGet": (sp) => {
						const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
						sp = this._inst.exports.getsp(); // see comment above
						storeValue(sp + 32, result);
					},

					// func valueSet(v ref, p string, x ref)
					"syscall/js.valueSet": (sp) => {
						Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
					},

					// func valueDelete(v ref, p string)
					"syscall/js.valueDelete": (sp) => {
						Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
					},

					// func valueIndex(v ref, i int) ref
					"syscall/js.valueIndex": (sp) => {
						storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
					},

					// valueSetIndex(v ref, i int, x ref)
					"syscall/js.valueSetIndex": (sp) => {
						Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
					},

					// func valueCall(v ref, m string, args []ref) (ref, bool)
					"syscall/js.valueCall": (sp) => {
						try {
							const v = loadValue(sp + 8);
							const m = Reflect.get(v, loadString(sp + 16));
							const args = loadSliceOfValues(sp + 32);
							const result = Reflect.apply(m, v, args);
							sp = this._inst.exports.getsp(); // see comment above
							storeValue(sp + 56, result);
							this.mem.setUint8(sp + 64, 1);
						} catch (err) {
							storeValue(sp + 56, err);
							this.mem.setUint8(sp + 64, 0);
						}
					},

					// func valueInvoke(v ref, args []ref) (ref, bool)
					"syscall/js.valueInvoke": (sp) => {
						try {
							const v = loadValue(sp + 8);
							const args = loadSliceOfValues(sp + 16);
							const result = Reflect.apply(v, undefined, args);
							sp = this._inst.exports.getsp(); // see comment above
							storeValue(sp + 40, result);
							this.mem.setUint8(sp + 48, 1);
						} catch (err) {
							storeValue(sp + 40, err);
							this.mem.setUint8(sp + 48, 0);
						}
					},

					// func valueNew(v ref, args []ref) (ref, bool)
					"syscall/js.valueNew": (sp) => {
						try {
							const v = loadValue(sp + 8);
							const args = loadSliceOfValues(sp + 16);
							const result = Reflect.construct(v, args);
							sp = this._inst.exports.getsp(); // see comment above
							storeValue(sp + 40, result);
							this.mem.setUint8(sp + 48, 1);
						} catch (err) {
							storeValue(sp + 40, err);
							this.mem.setUint8(sp + 48, 0);
						}
					},

					// func valueLength(v ref) int
					"syscall/js.valueLength": (sp) => {
						setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
					},

					// valuePrepareString(v ref) (ref, int)
					"syscall/js.valuePrepareString": (sp) => {
						const str = encoder.encode(String(loadValue(sp + 8)));
						storeValue(sp + 16, str);
						setInt64(sp + 24, str.length);
					},

					// valueLoadString(v ref, b []byte)
					"syscall/js.valueLoadString": (sp) => {
						const str = loadValue(sp + 8);
						loadSlice(sp + 16).set(str);
					},

					// func valueInstanceOf(v ref, t ref) bool
					"syscall/js.valueInstanceOf": (sp) => {
						this.mem.setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16));
					},

					// func copyBytesToGo(dst []byte, src ref) (int, bool)
					"syscall/js.copyBytesToGo": (sp) => {
						const dst = loadSlice(sp + 8);
						const src = loadValue(sp + 32);
						if (!(src instanceof Uint8Array)) {
							this.mem.setUint8(sp + 48, 0);
							return;
						}
						const toCopy = src.subarray(0, dst.length);
						dst.set(toCopy);
						setInt64(sp + 40, toCopy.length);
						this.mem.setUint8(sp + 48, 1);
					},

					// func copyBytesToJS(dst ref, src []byte) (int, bool)
					"syscall/js.copyBytesToJS": (sp) => {
						const dst = loadValue(sp + 8);
						const src = loadSlice(sp + 16);
						if (!(dst instanceof Uint8Array)) {
							this.mem.setUint8(sp + 48, 0);
							return;
						}
						const toCopy = src.subarray(0, dst.length);
						dst.set(toCopy);
						setInt64(sp + 40, toCopy.length);
						this.mem.setUint8(sp + 48, 1);
					},

					"debug": (value) => {
						console.log(value);
					},
				}
			};
		}

		async run(instance) {
			this._inst = instance;
			this.mem = new DataView(this._inst.exports.mem.buffer);
			this._values = [ // JS values that Go currently has references to, indexed by reference id
				NaN,
				0,
				null,
				true,
				false,
				global,
				this,
			];
			this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
			this._ids = new Map();  // mapping from JS values to reference ids
			this._idPool = [];      // unused ids that have been garbage collected
			this.exited = false;    // whether the Go program has exited

			// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
			let offset = 4096;

			const strPtr = (str) => {
				const ptr = offset;
				const bytes = encoder.encode(str + "\0");
				new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes);
				offset += bytes.length;
				if (offset % 8 !== 0) {
					offset += 8 - (offset % 8);
				}
				return ptr;
			};

			const argc = this.argv.length;

			const argvPtrs = [];
			this.argv.forEach((arg) => {
				argvPtrs.push(strPtr(arg));
			});
			argvPtrs.push(0);

			const keys = Object.keys(this.env).sort();
			keys.forEach((key) => {
				argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
			});
			argvPtrs.push(0);

			const argv = offset;
			argvPtrs.forEach((ptr) => {
				this.mem.setUint32(offset, ptr, true);
				this.mem.setUint32(offset + 4, 0, true);
				offset += 8;
			});

			this._inst.exports.run(argc, argv);
			if (this.exited) {
				this._resolveExitPromise();
			}
			await this._exitPromise;
		}

		_resume() {
			if (this.exited) {
				throw new Error("Go program has already exited");
			}
			this._inst.exports.resume();
			if (this.exited) {
				this._resolveExitPromise();
			}
		}

		_makeFuncWrapper(id) {
			const go = this;
			return function () {
				const event = { id: id, this: this, args: arguments };
				go._pendingEvent = event;
				go._resume();
				return event.result;
			};
		}
	}

	if (
		global.require &&
		global.require.main === module &&
		global.process &&
		global.process.versions &&
		!global.process.versions.electron
	) {
		if (process.argv.length < 3) {
			console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
			process.exit(1);
		}

		const go = new Go();
		go.argv = process.argv.slice(2);
		go.env = Object.assign({ TMPDIR: require("os").tmpdir() }, process.env);
		go.exit = process.exit;
		WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
			process.on("exit", (code) => { // Node.js exits if no event handler is pending
				if (code === 0 && !go.exited) {
					// deadlock, make Go print error and stack traces
					go._pendingEvent = { id: 0 };
					go._resume();
				}
			});
			return go.run(result.instance);
		}).catch((err) => {
			console.error(err);
			process.exit(1);
		});
	}
})();

2020,江端さんの忘備録

映画"Fukushima 50"を見に行くべきか、行かないべきか、で悩んでいます。

I'm wondering whether to go to the movie "Fukushima 50" or not

というのは、こんな理由があるからです。

This is because of these reasons.

-----

"NHK Special October Nightmare-Record of the Cuban Crisis and Horror of 1962 (NHK Special) (1992)" (pictures out)

この番組は、私に衝撃を与えました。

This program shocked me.

It is no exaggeration to say that this program created me today as a "simulation maker"

DVDも購入し、少なくとも30回以上は、視聴しました。

I also bought DVDs and watched them at least 30 times.

その後も「キューバ危機」については勉強を続け、今では、この事件の発生から終結まで、いつ、どこでも、誰にでも、プレゼンできる程度には知識を持っていると自負しております。

After that, I continued to study about the "Cuba Crisis" and now I am confident that I have enough knowledge to present to anyone, anywhere, anytime, from the start of this accident to the end.

問題はその後です。

However another problem occurred.

私は、ケビンコスナー主演の映画「13デイズ」(2000)を見にいって、激怒しながら、映画館から出てきたのを覚えています。

I remember coming out of the cinema, furiously, after watching the movie "13 Days" (2000) starring Kevin Costner.

深みがない、中身がない、薄っぺら、 軽薄で軽率、熟考していない、短慮で短絡 ―― ありとあらゆる罵詈雑言を唱えながら、帰宅したのを、よく覚えています。

"No depth, flimsy, frivolous rash, not contemplating, and short thought", I remember going home while saying all kinds of abusive language.

ええ、分かっています ―― 今回も、「間違っている」のは「私」です。

Yeah, I know well. Again, "I" am "wrong".

映画は、大衆向けのエンターテーメントです。

Movies are mass entertainment.

多くの人が分かりやすく、受けいれやすく、楽しいものでなければなりません。

For many, movies should be easy to understand, accept, and enjoy.

私のように、「キューバ危機」について、いつでも100ページくらいのコラムが書けそうな、「特殊」な人間をターゲットとして映画を作成したら ――

If they create a movie targeting a "special" person who can write a column of about 100 pages at any time about the "Cuba Crisis" like me,

その映画は、興行としては大失敗となっていたでしょう。

The movie would have been a huge failure for box office.

-----

さて、私、福島の原発事故については、かなり調べました。

By the way, I investigated the Fukushima nuclear accident.

おそらく直接の事故関係者ではなくて、福島原発事故調査委員会の報告書(600ページ以上)の全てに目を通した、数少ない人間の一人である、と自負しております。

I am proud to be one of the few people who have probably read the entire report (over 600 pages) of the Fukushima Nuclear Accident Investigation Commission, in spite of not directly involved in the accident.

古橋洋一さんの「カウントダウン・メルトダウン」を3回は読みなおしました。

I reread "Countdown Meltdown" by Yoichi Furuhashi three times.

(ちなみに、高村薫さんの「神の火」は、確実に100回以上は手に取り続けてきた、と断言できます)

(By the way, about Kaoru Takamura's "God's Fire", I have definitely read the book more than 100 times.)

福島原発に関するNHKスペシャルは、全て視聴しましたし、

I watched all NHK specials related to Fukushima nuclear power plant,

I am also the author of the accident commentary column from an engineer's perspective.

-----

映画「Fukushima 50」を見た結果が、「13デイズ」と同じようなこになったら、どうしよう ――

"What if the result of watching the movie "Fukushima 50" is similar to "13 Days""

そう思うと、映画館に行くことを躊躇してしまうのです。

I will hesitate to go to the movie theater.

せっかく映画を見にいくなら、楽しみたい。

If I go to a movie, I want to have fun.

映画を見にいって、腹を立てて帰宅することだけは避けたい。

I don't just want to go to the movies and get angry and go home.

-----

そこで、お願いがあります。

So I would like to ask you.

映画「Fukushima 50」が、江端にとってプロパーかどうかを、個人的に、主観的に、独善的に、教えて下さいませんでしょうか。

Could you tell me personally, subjectively and self-righteously whether the movie "Fukushima 50" is proper for Ebata?

私がこれまで記載してきた、膨大な雑文からご判断頂ければ幸いと存じます。

I hope you can judge it from the huge number of miscellaneous sentences that I have described so far.

何卒、よろしくお願い申し上げます。

I appreciate your kind cooperation.

2020,江端さんの忘備録

大学での実証実験のお手伝いを、学生さんにお願いしております。

Now, I ask some college students to help with campus field experiments.

理系の皆さんは、本当に礼儀正しくて、ロジカルで、知的で、お話していて気持ちがいいです。

The students in the science and engineering majors are polite, logical, and intelligent, so I feel good talking with them.

# ちなみに、私は理系です。

Incidentally, I am in the science and engineering majors.

-----

今回、お手伝いして頂いている学生さんの、実に6割以上が運転免許を所持していませんでした。

This time, more than 60% of the students who helped did not have a driver's license.

『運転免許取らなければ、と思っているうちに、M1(修士課程1年生)になってしまいまして・・・』

While thinking I needed a driver's license, I became "M1" (first-year master's student) ...

という話は、まるで、

I feel that this story is like that

『就職までに、TOEIC受験しなければ・・・』

"I must take the TOEIC test before getting a job..."

というノリと同じ、と感じました。

これは、私の推測の粋を出ませんが、

This is just my guess; however, they are thinking

―― 運転免許の取得が、TOEIC受験と同程度に『うっとうしい』

"Obtaining a driver's license is as annoying as taking the TOEIC test."

ということのように思えました。

-----

私、30年以上前、親に強制的に自動車運転免許を取らされました。

I was forced to get a driving license by my parents more than 30 years ago.

当時の私は、「原付の免許があれば足りる」くらいの気持ちでいましたし、今でも正直そう思っています。

At that time, I felt I only needed a motorbike license, and I still think so.

ただ、これは、大きな都市の交通網の充実しているから、そう感じるだけなのかもしれません。

However, this may only be felt because of the extensive urban transportation network.

唯一の例外は ―― 米国に赴任させられた時だけは、『車がなければ、この国では、3日で死ぬ』と思ったくらいです。

The only exception for me, when I was sent to the United States, I thought, "If I don't have a car, I will die in three days in this country."

(続く)

(To be continued)

2020,江端さんの忘備録

大学キャンパスの屋外実験に使う自動車に張る、複数の大型ステッカー(長さ1メートル)が自宅に到着しました。

Large stickers (1 meter long) on a car used for outdoor experiments have arrived at home.

ハンドキャリーで運ぶことになるので、ステッカーの重さや大きさを確認していました。

I checked the weight and size of the stickers because I would have to carry them by hand.

それを見ていた長女から、

The eldest daughter, watching my preparations, said to me

『パパ、文化祭でもやるの?』

"Dad, do you join in a school festival?"

と言われました。

-----

これが文化祭だとしたら、

If this is a school festival, I am determined that

―― もう人生で二度と関わりたくない、

I don't want to be involved in my life again

そして、

and

―― もう二度と絶対にかかわるものか、

I will never be involved again in my life

と決意している文化祭、と言えます。

さもなければ、いずれ『自分に殺される』ことになる。