https://mermaid-js.github.io/mermaid
https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid
江端智一のホームページ
https://mermaid-js.github.io/mermaid
https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid
をGo言語に移植してみました。
で、できるだけ、
に近づけてみました。
コメントのPrint分は、C++のを残しています(面倒だったので)。あとenum型がないので、テキトーに文字列を使うことにしました。
以前のコードには、豪快なバグがありましたので、ソックリ差し替えします。
設定条件は以下の通りです(テーブルの内容は、負荷量です)
package main
import (
"fmt"
"os"
)
func max_2(a, b float64) float64 {
if a > b {
return a
} else {
return b
}
}
func min_2(a, b float64) float64 {
if a > b {
return b
} else {
return a
}
}
type condition_MF3 struct { // condition_MF3の基底クラス
center float64
width float64
express string
}
func new_condition_MF3(_center, _width float64, _express string) *condition_MF3 {
c3 := new(condition_MF3)
c3.center = _center
c3.width = _width
c3.express = _express
return c3
}
// 前件部メンバーシップ関数(山3つ)クラス
func (c3 *condition_MF3) func_X(_x float64) float64 {
// x,yは、メンバーシップ関数上の座標を示す
x := _x
y := 0.0 // yの値は、必ず0以上1以下になる
if c3.express == "LESS" {
if x <= c3.center-c3.width {
y = 1.0
} else if x <= c3.center {
y = -1.0 / c3.width * (x - c3.center)
} else {
y = 0.0
}
} else if c3.express == "COMMON" {
if x <= c3.center-c3.width {
y = 0.0
} else if x <= c3.center {
y = 1.0/c3.width*(x-c3.center) + 1.0
} else if x <= c3.center+c3.width {
y = -1.0/c3.width*(x-c3.center) + 1.0
} else {
y = 0.0
}
} else if c3.express == "MORE" {
if x <= c3.center {
y = 0.0
} else if x <= c3.center+c3.width {
y = 1.0 / c3.width * (x - c3.center)
} else {
y = 1.0
}
} else {
fmt.Println("MF3: wrong expression")
os.Exit(1)
}
return y
}
type condition_MF5 struct { // condition_MF5の基底クラス
center float64
width float64
express string
}
func new_condition_MF5(_center, _width float64, _express string) *condition_MF5 {
c5 := new(condition_MF5)
c5.center = _center
c5.width = _width
c5.express = _express
return c5
}
func (c5 *condition_MF5) func_X(_x float64) float64 {
// 前件部メンバーシップ関数(山5つ)クラス
// x,yは、メンバーシップ関数上の座標を示す
x := _x
y := 0.0 // yの値は、必ず0以上1以下になる
if c5.express == "LESSLESS" {
if x <= c5.center-2.0*c5.width {
y = 1.0
} else if x <= c5.center-c5.width {
y = -1.0/c5.width*(x-(c5.center-2.0*c5.width)) + 1.0
} else {
y = 0.0
}
} else if c5.express == "LESS" {
if x <= c5.center-2.0*c5.width {
y = 0.0
} else if x <= c5.center-c5.width {
y = 1.0/c5.width*(x-(c5.center-c5.width)) + 1.0
} else if x <= c5.center {
y = -1.0/c5.width*(x-(c5.center-c5.width)) + 1.0
} else {
y = 0.0
}
} else if c5.express == "COMMON" {
if x <= c5.center-c5.width {
y = 0.0
} else if x <= c5.center {
y = 1.0/c5.width*(x-c5.center) + 1.0
} else if x <= c5.center+c5.width {
y = -1.0/c5.width*(x-c5.center) + 1.0
} else {
y = 0.0
}
} else if c5.express == "MORE" {
if x <= c5.center {
y = 0.0
} else if x <= c5.center+c5.width {
y = 1.0/c5.width*(x-(c5.center+c5.width)) + 1.0
} else if x <= c5.center+2.0*c5.width {
y = -1.0/c5.width*(x-(c5.center+c5.width)) + 1.0
} else {
y = 0.0
}
} else if c5.express == "MOREMORE" {
if x <= c5.center+c5.width {
y = 0.0
} else if x <= c5.center+2.0*c5.width {
y = 1.0/c5.width*(x-(c5.center+2.0*c5.width)) + 1.0
} else {
y = 1.0
}
} else {
fmt.Println("MF5 func_X(): wrong expression")
os.Exit(1)
}
return y
}
/////////////////////////////
type action_MF5 struct { // condition_MF5の基底クラス
center float64
width float64
express string
x float64
y float64
}
func new_action_MF5(_center, _width float64, _express string) *action_MF5 {
a5 := new(action_MF5)
a5.center = _center
a5.width = _width
a5.express = _express
if a5.express == "LESSLESS" {
a5.x = a5.center - 2.0*a5.width
} else if a5.express == "LESS" {
a5.x = a5.center - a5.width
} else if a5.express == "COMMON" {
a5.x = a5.center
} else if a5.express == "MORE" {
a5.x = a5.center + a5.width
} else if a5.express == "MOREMORE" {
a5.x = a5.center + 2.0*a5.width
} else {
fmt.Println("new_action_MF5: wrong scale expression")
os.Exit(-1)
}
a5.y = 0.0
return a5
}
// 後件部メンバーシップ関数(山3つ)クラス
func (a5 *action_MF5) func_Y() float64 {
// x,yは、メンバーシップ関数上の座標を示す
return a5.y
}
func (a5 *action_MF5) func_Max(b float64) {
a5.y = max_2(b, a5.y)
}
func (a5 *action_MF5) func_X() float64 {
return a5.x
}
func complain_reasoning(dis, age float64) float64 {
// Walking(前件部)
Walk_Less := new_condition_MF3(1.4, 0.4, "LESS")
Walk_Common := new_condition_MF3(1.4, 0.4, "COMMON")
Walk_More := new_condition_MF3(1.4, 0.4, "MORE")
// Age(前件部)
Age_LessLess := new_condition_MF5(42, 15, "LESSLESS")
Age_Less := new_condition_MF5(42, 15, "LESS")
Age_Common := new_condition_MF5(42, 15, "COMMON") // 中央が 42歳
Age_More := new_condition_MF5(42, 15, "MORE")
Age_MoreMore := new_condition_MF5(42, 15, "MOREMORE")
// Complain(後件部)
Complain_LessLess := new_action_MF5(0.5, 0.25, "LESSLESS") // 不満の中央値が0.5 0.0/0.25/0.50/0.75/1.00 の5段階
Complain_Less := new_action_MF5(0.5, 0.25, "LESS")
Complain_Common := new_action_MF5(0.5, 0.25, "COMMON")
Complain_More := new_action_MF5(0.5, 0.25, "MORE")
Complain_MoreMore := new_action_MF5(0.5, 0.25, "MOREMORE")
// [ルール00] 歩行距離:少0 年令:子供0
Rule00 := min_2(Walk_Less.func_X(dis), Age_LessLess.func_X(age))
Complain_LessLess.func_Max(Rule00) // 後件部は上書きされていく
//fmt.Println("Rule00", Rule00)
// [ルール01] 歩行距離:少0 年令:若年1
Rule01 := min_2(Walk_Less.func_X(dis), Age_Less.func_X(age))
Complain_LessLess.func_Max(Rule01) // 後件部は上書きされていく
//fmt.Println("Rule01", Rule01)
// [ルール02] 歩行距離:少0 年令:壮年2
Rule02 := min_2(Walk_Less.func_X(dis), Age_Common.func_X(age))
Complain_Common.func_Max(Rule02) // 後件部は上書きされていく
//fmt.Println("Rule02", Rule02)
// [ルール03] 歩行距離:少0 年令:高齢3
Rule03 := min_2(Walk_Less.func_X(dis), Age_More.func_X(age))
Complain_Common.func_Max(Rule03) // 後件部は上書きされていく
//fmt.Println("Rule03", Rule03)
// [ルール04] 歩行距離:少0 年令:老齢4
Rule04 := min_2(Walk_Less.func_X(dis), Age_MoreMore.func_X(age))
Complain_More.func_Max(Rule04) // 後件部は上書きされていく
//fmt.Println("Rule04", Rule04)
// [ルール10] 歩行距離:普通1 年令:子供0
Rule10 := min_2(Walk_Common.func_X(dis), Age_LessLess.func_X(age))
Complain_LessLess.func_Max(Rule10) // 後件部は上書きされていく
//fmt.Println("Rule10", Rule10)
// [ルール11] 歩行距離:普通1 年令:若年1
Rule11 := min_2(Walk_Common.func_X(dis), Age_Less.func_X(age))
Complain_Less.func_Max(Rule11) // 後件部は上書きされていく
//fmt.Println("Rule11", Rule11)
// [ルール12] 歩行距離:普通1 年令:壮年2
Rule12 := min_2(Walk_Common.func_X(dis), Age_Common.func_X(age))
Complain_Common.func_Max(Rule12) // 後件部は上書きされていく
//fmt.Println("Rule12", Rule12)
// [ルール13] 歩行距離:普通1 年令:高齢3
Rule13 := min_2(Walk_Common.func_X(dis), Age_More.func_X(age))
Complain_More.func_Max(Rule13) // 後件部は上書きされていく
//fmt.Println("Rule13", Rule13)
// [ルール14] 歩行距離:普通1 年令:老齢4
Rule14 := min_2(Walk_Common.func_X(dis), Age_MoreMore.func_X(age))
Complain_MoreMore.func_Max(Rule14) // 後件部は上書きされていく
//fmt.Println("Rule14", Rule14)
// [ルール20] 歩行距離:多2 年令:こども0
Rule20 := min_2(Walk_More.func_X(dis), Age_LessLess.func_X(age))
Complain_Less.func_Max(Rule20) // 後件部は上書きされていく
//fmt.Println("Rule20", Rule20)
// [ルール21] 歩行距離:多2 年令:若年1
Rule21 := min_2(Walk_More.func_X(dis), Age_Less.func_X(age))
Complain_Common.func_Max(Rule21) // 後件部は上書きされていく
//fmt.Println("Rule21", Rule21)
// [ルール22] 歩行距離:多2 年令:壮年2
Rule22 := min_2(Walk_More.func_X(dis), Age_Common.func_X(age))
Complain_More.func_Max(Rule22) // 後件部は上書きされていく
//fmt.Println("Rule22", Rule22)
// [ルール23] 歩行距離:多2 年令:高齢3
Rule23 := min_2(Walk_More.func_X(dis), Age_More.func_X(age))
Complain_MoreMore.func_Max(Rule23) // 後件部は上書きされていく
//fmt.Println("Rule23", Rule23)
// [ルール24] 歩行距離:多2 年令:老齢4
Rule24 := min_2(Walk_More.func_X(dis), Age_MoreMore.func_X(age))
Complain_MoreMore.func_Max(Rule24) // 後件部は上書きされていく
//fmt.Println("Rule24", Rule24)
// 推論計算
numerator :=
Complain_LessLess.func_X()*Complain_LessLess.func_Y() +
Complain_Less.func_X()*Complain_Less.func_Y() +
Complain_Common.func_X()*Complain_Common.func_Y() +
Complain_More.func_X()*Complain_More.func_Y() +
Complain_MoreMore.func_X()*Complain_MoreMore.func_Y()
denominator :=
Complain_LessLess.func_Y() +
Complain_Less.func_Y() +
Complain_Common.func_Y() +
Complain_More.func_Y() +
Complain_MoreMore.func_Y()
complain := numerator / denominator
return complain
}
江端の環境でのローカルな場所 C:\Users\ebata\Desktop\bouncy2
C:\Users\ebata>cd C:\Users\ebata\Desktop\bouncy2cd /c/Users/ebata/Desktop/bouncy2python3 httpsrv.pyhttp://localhost:8080 で起動
2020/03/14
#!/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
#!/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);
});
}
})();
Windows10 マウス ウインドウ サイズ 変更 端 握る
映像の切り出しをするだけなら、aviutl(現在立ち上げ不調) ではなく avidemux を試してみなさい > 私
私の作るエージェントプログラムは、エージェントが数千~数万回のレベルで発生ー消滅をするものなので、エジェントの消滅時に、確実にgoroutineを消滅させる必要があります。
しかし無限ループでイベント待ちをしているgoroutineを止める方法で、苦慮してきたのですが、問答無用でgoroutineを潰す、context.Contextというものを見つけて ―― 『これまでの苦労は一体なんだったんだ』と思っています。
まあ、こういうことって、結構ありますけどね。
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go loop(ctx)
// 2.5秒待つ
time.Sleep(2500 * time.Millisecond)
// ここで loop() を止める
cancel()
// 2回呼び出しても大丈夫
cancel()
println("finish")
}
// 無限ループする関数
func loop(ctx context.Context) {
for {
fmt.Println("test")
time.Sleep(time.Second)
}
}
親から子どもを一斉に消滅させる方法については、明日、片付けます。
なお、こっちの defer cancel()を使う方がスマートです。
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go loop(ctx)
defer cancel()
// 2.5秒待つ
time.Sleep(2500 * time.Millisecond)
println("finish")
}
// 無限ループする関数
func loop(ctx context.Context) {
for {
fmt.Println("test")
time.Sleep(time.Second)
}
}
ホストのPCでは"No"を選択
"No"を押した後の情報をメモっておく
クライアントPCの方は"yes"を選択する。
ホストの方で示された情報を入力する。
うーん、ラクチン。
昨夜windows7を使ったら、その反応の早さに驚いたので、windows10はやっぱり遅いんだなと思ったが、ちゃんとチューニングしたらいきなり快適になりました。
ただ、このあと問題が出てきたのは、デスクトップに表示される文字がガタガタになる、ということでした。
これは耐えられなかったので、ClearTypeというものを適用されることで解決しました。
「Windows10はやっぱり遅い」と決めつけずに、ちょっとした工夫で、ストレス解消になりますので、お勧めます。
あと、https://ygkb.jp/4475 の内容を参照させて頂いた
「無効」を推奨
ActiveX Installer (AxInstSV)
Application Management
BranchCache
Certificate Propagation # これは残した 個人的なプログラムで認証作業をやっているので
Connected User Experiences and Telemetry
Data Collection Publishing Service
Distributed Link Tracking Client
Distributed Transaction Coordinator
Downloaded Maps Manager
Fax
Function Discovery Provider Host
Function Discovery Resource Publication
Geolocation Service
Home Group Listener
Home Group Provider
Internet Connection Sharing (ICS)
Microsoft App-V Client
Microsoft iSCSI Initiator Service
Net.Tcp Port Sharing Service
Offline Files
Peer Name Resolution Protocol
Peer Networking Grouping
Peer Networking Identity Manager
PNRP Machine Name Publication Service
Portable Device Enumerator Service
Print Spooler
Printer Extensions and Notifications
Remote Registry
Routing and Remote Access
Shared PC Account Manager
Smart Card
Smart Card Device Enumeration Service
Smart Card Removal Policy
SNMP Trap
SSDP Discovery
UPnP Device Host
Windows Media Player Network Sharing Service
Windows Remote Management (WS-Management)
WinHTTP Web Proxy Auto-Discovery Service
Xbox Live Auth Manager
Xbox Live セーブ データ
Xbox Live ネットワーキング サービス
タイムゾーンの自動更新機能
ユーザー エクスペリエンス仮想化サービス
市販デモ サービス
SensorDataService
Sensor Monitoring Service
Sensor Service
「手動」を推奨
AllJoyn Router Service
Application Identity
BitLocker Drive Enctyption Service
Block Level Backup Engine Service
Bluetooth Handsfree Service
Bluetooth サポート サービス
Diagnostic Policy Service
Diagnostic Service Host
Diagnostic System Host
SensorDataService
Sensor Monitoring Service
Sensor Service
Telephony
Windows Image Acquisition (WIA)
/*
gcc -g ql_test.cpp -o ql_test
強化学習(Q-Learning)を理解する為に、中学→高校→大学の学歴を使ってみた
*/
#include <stdio.h>
#include <stdlib.h>
typedef enum period{
BIRTH = 0, JUNIOR_HIGH = 1, HIGH = 2, COLLEGE = 3, SUPER_COLLEGE = 4
}PERIOD;
typedef struct state{
struct state* future_state[2]; // 未来へのパス(取り敢えず2つほど)
PERIOD period;
int q;
}STATE;
STATE* change_state(STATE* p_state)
{
if ((double)rand()/RAND_MAX < 0.3){ // ε:0.3
if ((double)rand()/RAND_MAX < 0.5){ // 半々
return p_state->future_state[0];
}
else{
return p_state->future_state[1];
}
}
else {
if (p_state->future_state[0]->q > p_state->future_state[1]->q){
return p_state->future_state[0];
}
else{
return p_state->future_state[1];
}
}
}
void q_renewal(STATE* p_state)
{
int dummy_q;
if (p_state->period == SUPER_COLLEGE){
p_state->q += 0.1 * (1000- p_state->q); // α:0.1 報酬の源泉:年収1000万円
}
else if (p_state->period != COLLEGE){
if (p_state->future_state[0]->q > p_state->future_state[1]->q){
dummy_q = p_state->future_state[0]->q;
}
else {
dummy_q = p_state->future_state[1]->q;
}
p_state->q += 0.1 * (0.9 * dummy_q - p_state->q); // α:0.1 γ:0.9
}
return;
}
void q_display(STATE* p_state)
{
for (int i =0; i < 15 ; i++){
printf("%d,", p_state->q);
p_state++;
}
printf("\n");
return;
}
int main()
{
srand(13);
// 初期設定
//STATE* state;
STATE state[15];
state[0].period = BIRTH;
state[0].future_state[0] = &(state[1]);
state[0].future_state[1] = &(state[2]);
state[1].period = JUNIOR_HIGH;
state[1].future_state[0] = &(state[3]);
state[1].future_state[1] = &(state[4]);
state[2].period = JUNIOR_HIGH;
state[2].future_state[0] = &(state[5]);
state[2].future_state[1] = &(state[6]);
state[3].period = HIGH;
state[3].future_state[0] = &(state[7]);
state[3].future_state[1] = &(state[8]);
state[4].period = HIGH;
state[4].future_state[0] = &(state[9]);
state[4].future_state[1] = &(state[10]);
state[5].period = HIGH;
state[5].future_state[0] = &(state[11]);
state[5].future_state[1] = &(state[12]);
state[6].period = HIGH;
state[6].future_state[0] = &(state[13]);
state[6].future_state[1] = &(state[14]);
state[7].period = COLLEGE;
state[8].period = COLLEGE;
state[9].period = COLLEGE;
state[10].period = SUPER_COLLEGE;
state[11].period = COLLEGE;
state[12].period = COLLEGE;
state[13].period = COLLEGE;
state[14].period = COLLEGE;
for (int i = 0; i < 15; i++){
state[i].q = (int)rand() % 100;
}
printf("誕生,A中学,B中学,C高校,D高校,E高校,F高校,G大学,H大学,I大学,J大学,K大学,L大学,M大学,N大学\n");
STATE* s = state;
//q_display(s);
q_display(state);
for (int i = 0; i < 1000; i++){ // 300:学習回数
STATE* s = state; // 初期値に戻しているだけ
do{
s = change_state(s);
q_renewal(s);
}while( (s->period != COLLEGE) && (s->period != SUPER_COLLEGE));
q_display(state);
}
printf("\n[after]\n");
//q_display(s);
q_display(state);
}