2021年8月31日火曜日

JSONのフォルダ構造への変換

 node.jsにjsondirというのがあったので試した。

https://stackoverflow.com/questions/28256945/creating-a-folder-structure-from-definitions-on-a-json-file

var jsondir = require('jsondir');

jsondir.json2dir({
    "-path": 'dir',
    "myfile": {
        "-content": 'Hello world!'
    },
    "mydir": {
        "a": {
            "b": {
                "c": {
                    "-type": 'd'
                }
            }
        },
        "1": {
            "2": {
                "3": {}
            }
        }
    }
}, function(err) {
    if (errthrow err;
});


jsondirTest$ tree dir
dir
├── mydir
│   ├── 1
│   │   └── 2
│   │       └── 3
│   └── a
│       └── b
│           └── c
└── myfile

6 directories, 2 files

うん!

これ、全然使えないね?

例も酷いけど、結果も酷いんで、これは参考にしかならないとして諦めます。

それと、日本語入れたら動かなかったよ

まぢ使えない


まず、{}はフォルダにするべき

3がファイルになってるのはどういうポリシーだ?

dが消えてる

cフォルダの下にuuidフォルダ作って中に、"-type":"d"って書くべきだろ?


アルゴリズムにポリシーが無いので、バグってるようなもんだわ

誰にもメンテされずに消えるわけですね

発掘する価値も無かった




2021年8月30日月曜日

Golangのプラグインに関する考察

プラグインとして Go から外部スクリプトを実行するのが、

遅くて仕方ないのではないかと思えてきた。

https://github.com/d5/tengo

Go Nativeは、やはり早い

Pythonはまぁ遅いほうだわな(PerlやRubyよりは早いと思うが)

Ottoがめちゃくちゃ遅い

で、tengoが早いかと言うと、Go Nativeよりは比較にならないくらい遅い

ということで、SOファイル作って呼び出す形にした方が良さげだ

Linux系しか動かない作りになるが、まぁ別に問題ないだろ


気になったのでフィボナッチでベンチマークを探してみた。

https://ma-tech.centurysys.jp/doku.php?id=mae3xx_tips:test_fib_benchmark:start

Nimはえーな、まぢかよこれ


フィボナッチのベンチマークをもっと探してみた

https://github.com/drujensen/fib

おや?Nim遅くなってんぞ?

Pascal早いな

え、Haskellどうなってんのこれ?

ASMより早いんだけど?

え、Golang遅いな


まぁ、大体こんなもんだろうな・・・

アセンブラをガリガリ書いて、

ゲームのVSyncやHSync割り込みで動くようなものを作っていた身としては、

外部スクリプトなんか使いたくねぇなって気分になってきた。

2021年8月29日日曜日

GolangとJavaScript

GolangからJavaScriptを呼んで、JavaScriptからGolangの関数を呼ぶってことが出来るらしい

Ottoというパッケージがあって、EcmaScript5までらしいんだけど、

JSONをJavaScriptで扱ったり、Golang側に返したりするのもできる。

↓JavaScriptからGolang関数の呼び出し部はやってないけど一応の例

https://play.golang.org/p/KY8d9OsaA-q


2021年8月26日木曜日

golang BuntDB まぢすげーわ

 これすげーよ

JSONとか入れられるし、インデックス作れるし、キーで取得できるし、mongoDBよりいいんじゃねぇ?

俺が作ろうとした機能が全部ある

というかなんでみんなこれ使わないの?

https://pkg.go.dev/github.com/tidwall/buntdb

これとGoで作られてるJavaScript

https://pkg.go.dev/syscall/js


それと定番のnet/http

https://pkg.go.dev/net/http


これらを組み合わせたらバックエンドサーバ立てて、

受け取ったJSONをJSのJavaScriptに投げ、

JavaScriptからクエリを処理するGolang関数を呼び出し、

結果をJavaScript側で受け取って、Golangサーバに戻し、

Golangサーバからフロントに戻すプログラムが作れるよね

つまり、MEAN的なものが、上記組み合わせでつくれるわけっすよね?


まぁ俺、AngularJS嫌いなんで、

フロントは普通にJQueryでいいんじゃね?と思うけどね?

てか、V8が早いって言ってもgolangのJSのが早いよ

それとNode.jsごときでサーバ作るくらいならGolangのサーバのが早い

桁違うほど早いと思うよ


2021年8月17日火曜日

MyDNSさんのletsencrypt用ツールで助かった・・・

letsencryptを使いやすくするためのcertbotというものがあるんだけど

apt installしたものとsnapしたもので競合してたので、

apt purgeしたらcertファイルも綺麗に消えてしまった。


焦ってsnap版certbotを入れて、

.well-known/acme-challengeを80でアクセスできるようにして、

その時は/usr/share/nginx/htmlをrootにしたんだけど、

どうしても--webrootも--nginxも動かない・・・

あれこれ試して、manual の dns TXTレコードを使った方法へ移行した。


独自ドメインを取って、MyDNSで設定してるんだけど、

MyDNSさんは、gitにツールを置いててそれを使わせてもらった。

https://github.com/disco-v8/DirectEdit

ここから頂いてきてReadmeの通りやってみたら、

fullchain.pemとprivkey.pemが出来上がってくれた。


TXTレコードを扱えないとだめなので、

DDNSNowさんだとこの手も使えない。


いやーHTTPSに対応させるのすっげー大変だわ

なんでこんなにやり方が変わるんだろう?

まぁ、無駄に3つも認証キー作ってたから、

今回yachiyo.techと*.yachiyo.techを作って、

キーを統一できたのは良かったかもしれない。

問題はこれが certbot renewで素直に更新できるかどうかなんだよなぁ

2021年8月15日日曜日

ZOSI ZR08AN rebooting randomly

It was cause of wrong formatting procedure.

  1. Put out all cameras first
  2. shutdown system and eject power plug
  3. replace HDD
  4. plug power and boot up
  5. Format HDD
  6. reboot after succeeded for formatting HDD
That’s all

I was connecting camera while formatting.

I tried changing camera, check connection, changed power supply location, but I can’t figure out problems.

But reason is very simple.
Don’t connect camera while formatting.

ZOSI ZR08AN の再起動を繰り返す症状

ハードディスクのフォーマットの仕方が悪かったようだ。

  1. 最初にカメラを外す
  2. マウスだけ繋ぐ状態でシャットダウン
  3. ハードディスクを付け替える
  4. 起動する
  5. フォーマットする
  6. 成功したら再起動させる
以上だ
自分はカメラを繋ぎっぱなしでフォーマットしていた。
カメラが悪いのかと、何度もカメラを付け替えたり、一台ずつ試した、、配線も見直し、コンセントの給電も確かめたがダメだったのだ。

カメラを全く繋がない状態で動かしていたら再起動しなかったので、カメラが原因と思い込んでしまった。

2021年8月14日土曜日

昔結構大きめのタイトルのゲームを作っていた時の話

ゲームボーイだったんだが、ほぼ二か月でシミュレーションRPGを作ったことがある。

二か月家に帰れず、大量のデバッグシートが発行され、重複バグの山で、シートの整理でも時間がかかり、仮眠3時間しか取れず、近くのアパートの一室へ仮眠に行くのだが、二段ベッドが山の様に並んでて、各ベッドに目覚ましが付いてる。

コーディングしている最中はずっと、俺の真後ろで腕組みしてパイプ椅子に社長が座って、寝たり起きたりしながら俺の事を監視していた。

ある日久しぶりに家に帰ってテレビつけたら地下鉄サリン事件起こってて、俺巻き込まれるところだった。

俺、よく生き残ってこれたよ・・・

2021年8月11日水曜日

掲示板と言うか何というか

SF混じりに徒然と書くが、、、
先に書いておこう
オチは無い

で、ここから本題
マインドマップ式掲示板を大昔から考えていた

これは個人の思考の限界を打破するための案だった
それに、集合知の一つの完成系を目指したい気持ちもあった

集合知に行き着いたのは書物に対する限界を感じた事も一因だった

ある書物が技術書や図鑑などであったとして、書物の内容が間違っている事は多々ある

それなのに100年もそれが信じられ人類の発展に悪影響を与える事がある

そう言う過ちを集合知であれば、打開できる可能性がある。
人類をアップデートするには、本では足りない。

マインドマップ式掲示板の機能としてはブラウザ上に議論の中心を据え、その周囲に吹き出し状に発言が追加される
発言には別の発言を付け加えられる
人の発言には評価を付けられる
評価によっては、その発言はツリーの下に落ちて消える

ここまで考えて、「荒らし」や「思想の偏り」対策が思いつかなかったので、作るのをやめてしまっていた

対策として、高度な意味論を解釈できるAIに管理させるくらいしか思いつかないのだが、日本語は意味ベクトルを単語の連続性だけで判断できない
英語は単語の並びによって意味ベクトルを設定する事は可能だ。
確か、ある単語に続く単語の現れる可能性を列挙した研究があった。
論文だったかな、単語の連続率をタングラムと表現していた

日本語は単語の並びに副詞、各助詞、形容詞、否定などわりと自由に出てくるので、意味が分からなくなる。
日本語まぢ困ったもんである。

もしAIによる判定機能が実装できれば、発言同士の繋がりや、人間の発言に対する評価さえそのAIに任せることができる

Yahooのコメント見ると、思想の偏ったコメントの妙な連帯感を感じる。同じ思想を持つコメンテーター同士が馴れ合っていて、読んでいて違和感と不快感を感じる
その場にそぐわない意見は容赦なく攻撃される
もはや偏った思想集団による一種の攻撃に他ならない
マイノリティの意見は間違いなく抹殺される

ここにAIの判定という、公平な(?)判定が介入出来るなら、マインドマップの幅はだいぶ広がって行くとも考えた

しかし、AIの判定にも罠がある。
もはやそれは、人の思考ではなくなる可能性がある

AIが言うなら正しいという勘違いにもつながってしまう

AIではない超人なら、多くの意見がぶら下がるツリーを見て、評価の低いものも汲み取り、ツリー全体を上手いこと文章にすることもできるだろう。

だが、それをAIにやらせる事は今の技術レベルでは多分無理だ

これらを考えていたのは俺がゲーム業界時代

2chとかが流行り始めた時に考えていた事だ

当時に比べAIの分野で技術的な発展は見られるが、まだまだ全然足りない。
AIは犬や猫どころか、昆虫の行動にさえ追いついていない

あんな動きができるAI搭載ロボットはまだ存在しない

生物すげーよ
さっぱり仕組みがわからない
どうしたらまともなAIが作れるのやら、、、

2021年8月4日水曜日

Sedna XML Database用XQueryの外部関数(ひらがな→カタカナ変換)

 Sedna XML Databaseは XQueryの機能拡張をするために外部関数を作れるようになっている。今後このあたりも真似していきたいものだ。


ソースのコアな部分を乗せておく

コードはまだ少し危険な書き方をしているけど、まぁ動くし問題ないかな

unionなんて久しぶりに使った。

リトルエンディアンで並び順を迷った跡がうかがえて笑える。


食品成分表のデータで先頭の項目であるアマランサスを検索する際に、ひらがなで「あまらんさす」としているのだが、

今回作ったhirakata外部関数で、カタカナに変換され、検索文字列として使用される。




クエリは以下のような実装になっている。
declare function で今回作成したhirakata外部関数の呼び出し定義をしている。

declare function se:hirakata($a as xs:string*) as xs:string external;

<DATA TYPE='JSON' OUTPATH="//DATA/LIST" FORCEARRAY="//LIST/FOOD">
(: 複数のFOODを返す場合には、その上位にラッパーを作り、OUTPATHに指定をする :)
(: FORCEARRAYはのラッパーの下位のFOODが1件の場合でもJSON配列で返すために指定する :)
<LIST>
{
(:PARAMS:)
let $searchstr := se:hirakata($id)

for $food in doc('test2.db')//FOODS/FOOD
where contains($food/SEARCH_NAME,$searchstr) or contains($food/ADDITIONAL,$searchstr) or $food/@FOOD_ID=$searchstr
order by $food/@FOOD_ID
return
  <FOOD>
    {$food/JP_DISP_NAME}
    {$food/ENERC_KCAL}
    {$food/PROT-}
    {$food/FAT-}
    {$food/CHOCDF-}
    {$food/VITA_RAE}
    {$food/TOCPHA}
    {$food/NE}
    {$food/ADDITIONAL}
    {$food/SEARCH_NAME}
  </FOOD>
  }
</LIST>
</DATA>


2021年8月3日火曜日

Saraswatiの今後の開発

 golangで開発中のSaraswatiバックエンドフレームワークだが、今後の開発では、サーバーサイドに接続したプリンタ制御を考えている。

機能としては、フォルダにPDF出力して、別プログラムがプリントし、プリント終わったらアーカイブするだけの機構だ。


それと、XQueryに変わるXML DB制御言語の開発、そして、その言語で動くXML データベースの開発。

おそらくXMLデータベースは作れる。

アイデアでは、SQLiteのXML版みたいな位置付けの物だ。

問題は制御言語だか、golangの関数にしてしまえば良いだろうか?

それなら言語なんて仰々しいものを考えなくて良いし、そもそもわたしには言語を開発するセンスは無い

過去に俺様言語ならいくらでも作ってきたが、いつもその場でのやっつけで終わってきた。

7年前か?iPhone、iPadの開発でも俺様言語で開発して、SEGAに納品した

オリンパスで組み込み向けのターミナルで動く俺様言語も作った。

今回も似たノリでいいのかも知んない

2021年8月2日月曜日

食品成分表2021のサンプル

 Saraswatiで食品成分表2021から作ったXMLデータからデータ拾って表示のサンプル

よく使われる食材って、検索文字列入れると沢山ひっかかるんだけど、はんぺんは2つしかひっかからなくて、たまご検索したら大量に出てきた。 やっぱ、たまごって色々使われるんね?


XMLの中にHTMLリンクを混在

ようやく形になった。

この程度で苦労してしまったが、自前で実装していたEscape4JSONが間違ってて、ダブルクォートのエスケープを間違っていただけだった。

どうもこういうのに自分はハマるときがある。

頭の中でできてるつもりなのが災いしているようだ。

XMLにHTMLを入れるにはCDATAセクションにしないといけないのだが、

JSONからXMLへ変換し、変数へバインドし、XQueryでINSERTする際には特に、CDATAの意識をしなくても良いことがわかった。

これは、SEDNAの機能なのだけど、XQueryで特定のタグはCDATA扱いする機能がある。

すると、自前で実装したXML2JSONでも、CDATA内のHTML混じりの文字列がXMLではなく文字列として取得できるので、あとはこれをEscape4JSONで変換して、戻り値としてあげればよい。

ぶっちゃけ、治すのに”は¥¥”にしないといけなかったのに、¥”にしていたから、だめでしたってだけの話だった。

あほすぎる・・・



2021年8月1日日曜日

作成中のバックエンドフレームワークSaraswati

 今Golangで作っているSaraswatiの機能をまとめておく

SaraswatiはSedna XML Database をミドルウエアに使用したバックエンドフレームワークだ。

1.サーバの起動

 go run Saraswati

2.クエリの準備

Sarawsatiのあるフォルダ以下、

queryRoot/etc/qr/query.txtに以下を記述

queryRootはHTTPアクセスされた際の起点となるルートフォルダとなる。

開発時はlocalhost:5000で開発しているので、

フロントから、http:localhost:5000/etc/qrをアクセスした際に実行されるクエリとなる。


query.txtは見て分かる通りXQueryだ。

このXQueryはSaraswatiがミドルウェアに使っている Sedna XML Databaseで実行される。

クエリ内の(:PARAMS:)はXMLではタダのコメントだが、SaraswatiはフロントからJSONで渡ってきたデータをこの位置にバインドする。ちなみに、se:qrは今回C++でSedna XML Database用に作成したQRコード作成プラグインだ。このようにSedna XML DatabaseはXQueryに元から無い機能でも、後からプラグインとして実装が可能な仕組みを提供している。

 declare function se:qr($a as xs:string*) as xs:string external; (:PARAMS:) (: convert $text input to qr image :) (: size as pixel for image size :) let $a := doc('test1.db')//pages let $qr := se:qr($text) return <DATA TYPE='JSON' OUTPATH="//DATA/QRIMG"> <QRIMG>{$qr}</QRIMG> </DATA>

ちょっと引っかかるのは、let $aの部分だが、実はダミーとしてtest1.dbに対してクエリを実行するために書かれている。
クエリはどのDBに対して実行するのかという指定が必要なため、QRコードのような、本来DBアクセスをしないクエリであってもダミーとして実行対象のDBが必要となる。

ただし、現在のバージョンのSaraswatiでは、ダミーが無くとも適当なデータベースをダミーとして実行できるようになっている。

3.フロントの準備

クエリを呼び出して、結果を表示するためのフロントをJQueryで作成する

http:localhost:5000/etc/qrを呼び出し、

$(".qimg").attr('src','data:image/png;base64,' +myArray.QRIMG)で、戻ってきたJSONのQRIMGをイメージとして設定するだけだ。


4.実行

以下はSedna XML Database の吐き出したログ

Saraswatiは(:PARAMS:)の部分にフロントから渡されたJSONがXMLの変数として記述し、Sedna XML Databaseに渡して実行、その後、Sedna XML Databaseからの出力(XMLでなければならない)をJSONに変換してフロントへ戻す

ただし、このバインドの仕方は今後変わる予定で、強制的に全体を<VAL>で囲うことになると思う

let $text := <VALあいうえおかきくけこ</VAL>のようになる予定

---   declare function se:qr($a as xs:string*) as xs:string external;
---   let $text := 'あいうえおかきくけこ'
---   
---   (: convert $text input to qr image :)
---   (: size as pixel for image size :)
---   
---   let $a := doc('test1.db')//pages
---   let $qr := se:qr($text)
---   return
---   <DATA TYPE='JSON' OUTPATH="//DATA/QRIMG">
---     <QRIMG>{$qr}</QRIMG>
---   </DATA>
---   


5.出力結果

フロント側でレスポンスを見てみると、このようにQRIMGにはBase64エンコードされた画像が含まれている。

フロントはこれを使って表示すればよい


6.食品成分表からのデータ取得

クエリはqueryRoot/foodinfo/nutrients/query.txtに以下の内容で用意する

(:PARAMS:) let $a := doc('test2.db')//FOODS/FOOD[@FOOD_ID=$id] return <DATA TYPE='JSON' OUTPATH="//DATA/FOOD"> <FOOD> {$a/JP_DISP_NAME} {$a/ENERC_KCAL} {$a/PROT-} {$a/FAT-} {$a/CHOCDF-} {$a/VITA_RAE} {$a/TOCPHA} {$a/NE} </FOOD> </DATA>

FOOD_IDでしか検索しない場合のクエリだ

let $id :='2002'を入れて、実行するとSaraswatiは上記XMLの出力内容を以下のようなJSONに変換してフロントに戻す。

ちなみに2002は食品成分表の通し番号になっている。


{
    "FOOD": {
        "NE""1.1",
        "JP_DISP_NAME""さつまいも(塊根:皮なし:生)",
        "ENERC_KCAL""126",
        "PROT-""1.2",
        "FAT-""0.2",
        "CHOCDF-""31.9",
        "VITA_RAE""2",
        "TOCPHA""1.5"
    }
}


これを表示するフロントを作れば、一応の完成だ


7.さらなる改良

これだとIDでしか検索できないので、データ全件検索できるようにする。

IDだと結果は一件だったのだが、

名称などで検索すると、複数件の結果を返さなければならない。

以下のように複数件の検索結果を返すようにクエリを修正する。

<DATA TYPE='JSON' OUTPATH="//DATA/LIST" FORCEARRAY="//LIST/FOOD">
(: 複数のFOODを返す場合には、その上位にラッパーを作り、OUTPATHに指定をする :)
(: FORCEARRAYはのラッパーの下位のFOODが1件の場合でもJSON配列で返すために指定する :)
<LIST>
{
(:PARAMS:)

for $food in doc('test2.db')//FOODS/FOOD
where contains($food/SEARCH_NAME,$id) or contains($food/ADDITIONAL,$id) or $food/@FOOD_ID=$id
order by $food/@FOOD_ID
return
  <FOOD>
    {$food/JP_DISP_NAME}
    {$food/ENERC_KCAL}
    {$food/PROT-}
    {$food/FAT-}
    {$food/CHOCDF-}
    {$food/VITA_RAE}
    {$food/TOCPHA}
    {$food/NE}
  </FOOD>
  }
</LIST>
</DATA>

この時、適当な検索文字列(さつまいも)で検索した結果は以下の様になる。

{
    "LIST": {
        "FOOD": [
            {
                "JP_DISP_NAME""さつまいも(塊根:皮なし:生)",
                "ENERC_KCAL""126",
                "PROT-""1.2",
                "FAT-""0.2",
                "CHOCDF-""31.9",
                "VITA_RAE""2",
                "TOCPHA""1.5",
                "NE""1.1"
            },
            {
                "JP_DISP_NAME""さつまいも(塊根:皮なし:蒸し)",
                "ENERC_KCAL""131",
                "PROT-""1.2",
                "FAT-""0.2",
                "CHOCDF-""31.9",
                "VITA_RAE""2",
                "TOCPHA""1.5",
                "NE""1.1"
            },
            {
                "NE""1.3",
                "JP_DISP_NAME""さつまいも(塊根:皮なし:焼き)",
                "ENERC_KCAL""151",
                "PROT-""1.4",
                "FAT-""0.2",
                "CHOCDF-""39.0",
                "VITA_RAE""1",
                "TOCPHA""1.3"
            },
            {
                "FAT-""0.6",
                "CHOCDF-""71.9",
                "VITA_RAE""(0)",
                "TOCPHA""1.3",
                "NE""2.4",
                "JP_DISP_NAME""さつまいも(蒸し切干)",
                "ENERC_KCAL""277",
                "PROT-""3.1"
            },
            {
                "JP_DISP_NAME""さつまいもでん粉",
                "ENERC_KCAL""340",
                "PROT-""0.1",
                "FAT-""0.2",
                "CHOCDF-""82.0",
                "VITA_RAE""0",
                "TOCPHA""-",
                "NE""Tr"
            },
            {
                "VITA_RAE""(0)",
                "TOCPHA""(0)",
                "NE""0",
                "JP_DISP_NAME""はるさめ(普通はるさめ:乾)",
                "ENERC_KCAL""346",
                "PROT-""0",
                "FAT-""0.2",
                "CHOCDF-""86.6"
            },
            {
                "PROT-""0.9",
                "FAT-""0.5",
                "CHOCDF-""33.1",
                "VITA_RAE""3",
                "TOCPHA""1.0",
                "NE""0.8",
                "JP_DISP_NAME""さつまいも(塊根:皮つき:生)",
                "ENERC_KCAL""127"
            },
            {
                "NE""0.9",
                "JP_DISP_NAME""さつまいも(塊根:皮つき:蒸し)",
                "ENERC_KCAL""129",
                "PROT-""0.9",
                "FAT-""0.2",
                "CHOCDF-""33.7",
                "VITA_RAE""4",
                "TOCPHA""1.4"
            },
            {
                "PROT-""1.4",
                "FAT-""6.8",
                "CHOCDF-""38.4",
                "VITA_RAE""5",
                "TOCPHA""2.6",
                "NE""1.0",
                "JP_DISP_NAME""さつまいも(塊根:皮つき:天ぷら)",
                "ENERC_KCAL""205"
            }
        ]
    }
}

あとはこれを表示するフロントを作ればよい

こんな感じに表示すればよいだろうか?

もちろん、成分表をDIVやCANVASを使って棒グラフにしてもよい



8.まとめ

このようにSaraswatiを使った開発では、フロント開発者が、自分の都合のいいようにクエリを編集できる。

SaraswatiはJSONで渡ってきたデータをXML化し、XQueryにバインドし、結果XMLをJSONに戻す仕組みを提供する。

この際、Saraswatiそのものは停止する必要が無く、コンパイルし直したりデプロイし直したりする必要もなく、動かしっぱなしでクエリを編集すればいい。

ところで、Saraswatiにはドメイン層が無い。

無いは言い過ぎかもしれない。

取得したデータの計算などはXQueryで行う仕組みだ。

既存DBでもPL/SQLなどで実現していることと同じことをXQueryで行えばいい。


また、Sednaには連続してデータの更新をするような機能はないが、Saraswatiはその機能を提供する。

今回、連続したDBの更新など、データの更新についてはここで記述しなかったが、Saraswatiは<DATA>タグ以外に<SEDNA><PROCS><PROC>というエンベロープで包むことにより、連続データの更新が出来るようになっている。

//SEDNA/PROCS/PROCに複数のデータ更新系クエリを記述できる。

PROCS/PROCが全部正常に実行されればコミットされ、

途中で失敗したらロールバックという仕組みになっている。

つまり、データ更新に於いてもクエリを編集すれば良い