有効結婚リンク判定の重複処理を削減する

複数のバグをクリアできたので安定版として確保しておこう.Version 2.2.0.013 Release 2020-10-31となる.20201031-MTHOANBというパッケージを作った.⇒おかしい.インストールして走らせてみたが,ヘルプで出るバージョン番号が古い.⇒Program Files(x86)\babalaboで見ると,EXEやその他のDLLは最新版に差し替わっているが,OCXだけは元のままだ.おそらくOCXもバージョンを更新しないと差し替えてくれないのだろう.公式版のリリース手順は結構面倒くさいので,今日のところはアンインストール→再インストールしておこう.⇒アンインストール中以下のエラーが出た.

image

エラーは出たがアンインストールは完了している.⇒多分このパネルはアンインストールとは無関係だと思う.エクスプローラでその場所を開いていたために出されたものだろう.⇒今度はうまくいった.昨日の修正で予定していた「有効結婚枠判定の厳格化@20201030」というオプションの導入は不要ということになったが,処理が重複していると見られるところがあるので整理しておこう.「有効結婚リンク判定の重複処理削減@20201031」で切り分けることにする.

修正した.問題なく動作しているが,一つ致命的な欠陥が出てきた.Ancesty.zelのシンメトリが崩れてしまった.この修正はトポロジーには影響を与えないはずなので,もっと前から起きていたのかもしれない.⇒確かにそのようだ.この手戻りがどこで始まったのか突き止める必要がある.10月25日リリースの20201025-KGWZMZCでは正常動作していた.10月28日版も動作している.29日バックアップまではOKだ.おそらく10月29日の修正で何かやらかしたのに違いない.ログのタイトルは「ZTシステム構成図の構築が予想外に手間取っている」だ.

結婚枠間ギャプを取るようにしたことでSUWが発生するようになり,その原因がCheckInnerSplitであることが突き止められて,CheckGeneSplitの処理対象を人名枠から結婚枠に変更している.この修正は「METRIX:margvhを増加させる@20201028」で行っているので元に戻してみよう.⇒ダメだ.復旧しない.どこかに「METRIX:margvhを増加させる@20201028」を付けない修正が入っていたのではないか?少なくとも20201029の修正はあと, deltaを1増加させる@20201029というのがあるだけだ.これはdelta++するだけの軽微な修正だ.かなりまずいことになってきた.ここまで戻して回復しないとしたら,29日の始業時パッケージに戻るしかない.

その前にWinMergeで比較してみよう.修正の入っているソースファイル20本を目視でチェックしてみたが,有意差は認められなかった.⇒2箇所NOTHINGで止めているブロックがある.これはチェックしてみた方がよいかもしれない.念のためZELKOVA 2020-10-29をクリーンビルドして動作を確認しておこう.⇒確かに動いている.⇒CheckGeneSplitとSolveGeneSplitの論理をNOTHINGで書き換えている部分を復活させたら動作した.この修正を「系列内スプリット検査でGリングを使う@20201029」で切り分けるようにした.

系列内スプリット検査が必要となった主な理由は「フロート婚(TYW婚ないしシンメトリ婚)の存在」にあったと考えられる.Ancestryはその典型例であり,この処理がなければ壊れる,必須論理だ.もう少し垢抜けた方法があってもよいとは思われるが現状はこれで手を打つしかないだろう.⇒この版は保全しておいた方がよい.バージョンを繰り上げて差し替えることにする.Version 2.2.0.014を20201031-CQDZPJCとして保存した.この前の20201031-MTHOANBは廃棄しておこう.これでやっと一歩前進というところだ.

ファイルを保存したとき,修復が必要な「不完全データファイル」として保存されるという問題を考えておこう.最新版は問題となったZTシステム構成図(ERR11).ZELを開くことができるので,これを保存しても不完全ファイルにはならない.プログラムはサンプルファイルのエディションとバージョン番号が一致するかより大きくなければならないので,このような問題が発生するとすれば,バージョンより新しいエディションのファイルを読み込んだときに限定されるように思われる.一応動作を確認してみよう.(ERR11).ZELとして保存し問題なく読み込むことができる.ただし,ZTシステム構成図3.ZELを読み込んだ場合は出口検査でInvestigateHSplitsが検出されている.⇒一箇所スプリットが出ている.このスプリットは系列間スプリットで系列内スプリットではない.

このエラーはこれまでにも出ていたのに無視されていた可能性がある.念のため2020-10-29版で確認してみよう.⇒この版では系列間スプリットは発生しない.⇒逆に現行版でも29日以降の修正を全部復旧させれば解消する.主な修正3件を個別に復活させてチェックしてみよう.「deltaを1増加を廃止@20201029」を復活させると発生する.スプリットは「親参照リスト」と「所属グループ」の間で起きている.「deltaを1増加を廃止」以外のすべての修正は無害だ.この修正はTREEVIEW::InvestigateHSplitsに入っている.いま問題になっている検査ルーチンそのものだ.deltaは検査のモジュール単位だから,この値以下のスプリットは見逃されることになるが,値が小さい方がより精度の高い検査になるはずなのに,逆にスプリットが発生するという結果になっている.偶然ということもあるのかもしれないが…

スプリットが発生しない論理でdeltaの現在値は16になっている.インクリメントしなかったとすれば,15という値で検査していたことになる.delta値は標準フォント幅と結婚枠間ギャップの大きい方の値を採用することになっているが,現在の仕様では結婚枠間ギャップ=標準フォント幅=15になっている.InvestigateHSplitsを系列間スプリット検査と呼ぶのは当たっていない.この検査は広域検査で結婚枠や系列枠の存在とは無関係に描画関数を直接(仮想的に)呼び出して「(描画オブジェクトが)何も描画されていない区間」を検査するものだ.この意味では修正論理で検出しているのは「結婚枠間のギャップの幅15の区間」に相当する.それが一箇所しか検出されていないのは区間の座標がぴったり一致することが稀だからと言える.

この検定方式では最大で30の幅のスプリットが検出できない可能性があるが,少なくともそれ以上のスプリットの発生は抑制可能と言えるだろう.しかし,結婚枠間ギャップをスプリットと誤認するというのは論外なのでやはり,この論理は戻しておくしかないと思う.さて,本題に戻ろう.MAXPARENTSはCARDBASEでは親番号配列サイズを決めているが,保存データでは参照されていないのでMAXPARENTSが増減してもその範囲内のデータまでは安全に読み込むことができる.しかし,PERSONALとCARDDATAおよびMARGBASEは保存されたデータがそのまま読み込まれるので不整合が発生する可能性がある.

現行版はMAXPARENTS=32でビルドされている.8に落とした版を作ってみよう.⇒「不完全データファイル」に関して少し勘違いしていた.下のパネルはファイルを読み込んだときに表示される.

image

従って,ここで保存してもう一度読み直してもエラーは発生しない.ただし,サポート範囲外のデータは破棄されている.実際,noduleの父母ページ数は8に変化している.これをZTシステム構成図 MAX=8.ZELとして保存して読み直せばエラーは発生しない.つまり,読み込んだときにはすでに補修されているので,保存時に整合性検査を行う必要はない.もちろん,これをたとえばMAX=4の版で読めば同じことが繰り返されるが,動作的にはこれで十分だ.言い換えれば,保存時に「不完全データファイル」として保存されることは起こり得ないと言える.

「可変長配列」が使えればこのような問題も一掃されてしまうのだが,宿題としておこう.NODULEの派生クラスにはARRAYという任意サイズの配列を持つクラスもあるが,この配列はnodule*の配列で一般のデータ型を扱うものではない.気になる点はまだ残っているような気がするが,MAXPARENTSを32に変更してデータ入力に戻るとしよう.

構成図5.zelを開いて,部分図「GENEBOX」に切り替えて,多重カードを検出.「不可避の多重」はゼロなのでこれは明らかな障害だ.⇒※解決

系列枠背景色が基準カード色と連動してしまう.かなりおかしい.系列枠背景色はBGColorTribeBox,基準ノード背景色はBGColorBaseNodeでCOUPLINGの系図画面カラー設定ではそれぞれColorTribeBoxとColorBaseNodeとい変数名で使われている.どうもVB側で誤っているのではないかという気がする.いや,これは仕様かもしれない.TRIBEBOX::Drawに以下の行がある.

if (primetype == PRIME_START) BGColor = metrix->col->BGColorBaseNode;

つまり,始系列を他の系列から区別するために背景色を基準ノード色で塗りつぶしている.しかし,始系列というのは1個しかないはずだから明らかにこの動作はどこかで間違っている.

部分図で閉じたときは再読み込みしたとき部分図が開くはずなのにそのような動作になっていない.⇒いや,保存しないで終了しているのだから当然だ.⇒※単なる勘違い.

image

GENELISTは系列GENELISTの優先ノードで先祖ノードでもあるように思われるが,原図ではbaselistとともにcoupling系列の一部となっている.部分図にはbaselistとGENELISTしか含まれていないのだから,baselistの単身先祖配偶者とならなくてはならないはずのところ,あくまで独立の存在を主張している.TRIBELIST::MakeUpTreeには,「単身先祖配偶者→系列を廃棄」という手順が組まれているから本来ならここで系列は破棄されていなくてはならないところなのだが…「始系列は削除されない」というルールから除外されている.場合によっては始系列でも削除される場合があるということだろうか?⇒先行系列と完全に縁が切れていれば始系列となり得るが,GENELISTの場合は先行系列とつながりがあるので,このノードがPRIME_STARTという属性を持っていること自体誤りと考えられる.

初期状態ではすべての系列はPRIME_START属性を付与される.どうも錯綜として状況を掴みきれないので,primetypeをprivateに設定してアクセス関数を使うことにしよう.関数の引数でprimetypeの参照を渡して直接書き込んでいるところがある.SearchLaterFosterChild,SearchLaterPrimeNodeの2つだ.ここで使われているprimetypeはTribeDecompositionのローカル変数だ.まぎらわしいのでPRIMETYPEとしておく.TribeDecompositionの中で一度もsetprimetypeが実行されていないように思われる.これはかなり奇妙だ.⇒いや,実行されている.GENELISTの系列は2回設定が回ってくるが毎回PRIME_STARTで呼び出されている.初回はMakeTribeBoxで系列枠オブジェクトを生成するために初期化しているだけだ.

「有効結婚リンク判定の重複処理削減@20201031」を復活させると動作に少し変化が現れたが,描画はできない(白紙になってしまう).現行版では先祖リストには2個のエントリがあるが,重複処理削減版では先祖は1人しかいない.また,validcard=2, validmarg=1となっている.これが正常だ.現行版ではこれが,validcard=2, validmarg=88になっている.これでは解けるはずがない!いや,そもそもCountValidMargが呼び出されていない!⇒TribeDecompositionはFilteringKinshipの中で実行されている.⇒修正に誤りがあった.これで有効なカードリンクと結婚リンクの数は正しい値にセットされたが,まだ描画できる状態になっていない.

あちこちでcheckブロックに不備があり,例外が発生していたためと考えられる.ロジックを整理して通るようになった.

image

この部分図はGENEBOXというタイトルが付いているが,baselistとGENELISTしか登録されていない.おそらくGENEBOXのクラス構成を見ようとしていると思われるので,GENEBOXの直系血族図を取ってみた.これはかなりよい説明図になっているのではないだろうか?

image

GENEBOXから名前でアクセスできるメンバー変数は出揃っているし,それに関係するクラスもすべて表記されている.クラスの継承関係も明瞭だ.この図でGENEBOXが先祖ということは,GENEBOXを基本クラスとする派生クラスが存在しないことを意味する.Bobjectの直系血族図を見てみよう.これもわかり易い図だ.

image

Bobjectの上にはBobjectの派生クラスが6つ並んでいる.

imagePAIRBOXの出方はかなり違う.構成木のルートのcouplingまで繋がっている.なぜだろう?また,PAIRBOXはBobjectの派生クラスであるのにそれが展開されていない.原因は分かった.PAIRBOXという名前で2つの要素が登録されている.男性型と女性型だ.この図は男性型つまり,実装としてのPAIRBOXだ.女性型を選べば上のGENEBOXなどと類似のパターンになる.PAIRBOXではなく小文字でpairboxとしておけばよかったのかもしれないが,pairboxという実装名はおそらく使われていないのではないかと思う.

PAIRBOXはPAIRLISTのリスト要素として使われているが,PAIRLISTはNLIST < LISTNODE, CID>の派生クラスで引数のLISTNODEでPAIRBOXをクラス名として指定しているが,内部要素であるPAIRBOXのインスタンスには名前は付いてない.まぁ,これはこれでよいだろう.

全体図で見ると蜘蛛の巣を張ったように見えるが,個別にソートするとそれなりの図が出てくるところを見ると,この図面の制作意図はかなり的中しているように思われる.多分まだあちこち欠陥はあると思われるが,大雑把に見てかなりいい線をいっていると思われるので今回はこの辺りで一旦手仕舞いすることにしておこう.

設定を親族図:直系血族図にしておいて,検索パネルで検索→系統並び替えを繰り返し実行することでいろいろなクラスやクラスのインスタンスの構成図を見ることができる.直系血族図だけでなく,Z木家系図というのもおもしろい.この図では直系血族の配偶者まで出てくるのでもう少し詳しい情報が得られる.たとえば,上記PAIRBOX(実装)のZ木家系図はこんな感じだ.

image

親族図から全体図に移ろうとしてTOPOLOGY::topologicalSortで (treeview->validmarg != validmargnum) というエラーが出た.treeview->validmargが10でTOPOLOGY::validmargnumが…ということは同期が取れていないということになる.なぜだろう?HideNameboxの呼び出しが (CHARTTYPE) ※のときしか掛かってこないためだ.⇒このエラーは解消したが,まだ何かある.

※(CHARTTYPE)は(CHARTTYPE != DISP_ALLCARD)の意⇒修正した

PAIRBOX(♂)の直系血族図から全体図に切り替えて,CARDLINK:DownStreamで (mywife && mywife->Invalidated && CHARTTYPE == DISP_ALLCARD)になった.mywifeはPAIRBOX(♀)だ.全体図では隠蔽されているカードはないはずだから,HideNameboxの動作に何か問題があることになる.⇒TOPOLOGY::HideNameboxではカードテーブルで処理するのではなく,cardQという待ち行列を使って有効無効の判定をしている.このQは親族範囲の検定に使われている.全体図のときはこの処理をやっていないため不足が発生するのだろう.いや,FilteringKinshipもHideNameboxも実行されているように見える.

修正ミスがあった.全体図のときHideNameboxが呼び出されてた.TOPOLOGY::ClearTableではすべてのカードと結婚リンクを有効に初期化している.しかし,全体図の場合にも「親族範囲の検定」は必要になる.つまり,親族範囲とカードの有効無効は必ずしも一致しない.このため全体図の場合はHideNameboxを実行しないというのが正しい.

現在システム構成図には36個のクラスと153個のオブジェクトが登録されている.この資料をクラスの直系血族図をすべて部分図として登録しようとすると,部分図のMAXをオーバーしてしまう.部分図MAXは32個しかないからだ.これは部分図が互いに排他的ではない(複数の部分図に重複登録できる)ために集合論的に扱う必要があるからだ.

ゼルコバの木のクラスにはアルファベットの一文字を割り当てているので記号を入れても128というのが最大登録数ということになるが,CID(クラス識別子)は排他的なので短整数で間に合う.現在のマシンの長整数は64ビットだから,部分図を128個まで扱えるようにするにはCARDBASE::partialbitsをULONGに延長すればよい.

全体図は込み入り過ぎて通常は開くこともないが,もっぱら部分図ないし親族図で調べものをするという使い方はゼルコバの木の適切な用法であるような気がする.名前さえ分かれば親族図でソートするという方法があるので,いまのところは部分図MAX32でもしばらくはしのげるだろう.大きなデータベースが使えるようになると通常は標準家系図や法定親族図のようなものがもっぱら使われるようになるのではないか?

「系列内スプリット問題」は解決した

「系列内スプリット問題」は解決した.ここで一度リリース版を起こしておくことにしよう.”Version 2.2.0.012 Release 2020-10-30 今回も手順を省略した簡易手順の所内版としておく.リリース版更新の手順リストを作っておきたいが,プリンタがインク切れになっているので後日またということにしよう.⇒おかしい.ライセンスコードが合わない.⇒ライセンスファイルの内容は正しい.リリース版の方が間違っている.しかし,Version 2.2.0.012 は合っている.よくわからないが,アンインストール→再インストールで一致した.

ZTシステム構成図(ERR11).ZELの部分図でズームの動作がおかしい.この不良はリリース版でも起きる.全体図,親族図では問題なく動作しているので,部分図に限った不良だ.これは最近になってからの事象と思われるが,古いバージョンで動作を確認してみよう.⇒V2.2.0.008_R20201014を走らせてみたが問題なく動作する.⇒V2.2.0.011 R2020-10-25ではすでに不良が発生している.V2.2.0.0010 R2020-10-17は動作する.これはZELKOVA 2020-10-24に入っていたものだが,2020-10-23のデバッグ版でも動作している.⇒これはプログラムではなく,データの問題ではないかと思う.

アプリケーションのバージョン情報

現行版ではMAXPARENTS=32になっているが,以前のバージョンでは4になっていたので,MAXPARENTS=8という版を作成してみた.サンプルを読み込ませるとこの版でも障害は発生する.別に保存してMAXPARENTS=32で開いてみたが,動作は変わらない.このデータの部分図で「画面上のカードを保存」し,再度開いてみたところ,不良は発現しなくなった.オリジナルをMAX=8版で読み込むと,「修復しました」が出るのでまったく同じデータとは言えないが,外形的には同じ.オリジナル版の部分図をMAX=32バージョンで部分図をファイルに保存したサンプルはMAX=32版でも正常にズーム操作できる.このときも「修復しました」が出ている.どこを「修復した」のかが問題だ.

「同一親ページの重複を検出」で停止.treeviewが①pagesetupの単身婚,②pagesetup+PAGESETUPを持っていることが原因と思われる.部分図にはPAGESETUPは含まれないので父pagesetupのページが2つになってしまったものと思われる.⇒確かにオリジナルでもPAGESETUPを母から取り除いて父母ページ3にしてしまえば事象は解消する.父ないし母を複数持つということはあり得るが,同じ人名が複数のページで同時に父ないし母になるということはあり得るだろうか?

ある人物が子どもを持っていて,後妻を持ち(後妻が)その子どもと養子縁組するということはあり得るのではないか?このとき,父+後妻→子どもではなく,後妻→子どもという関係を成立させるのは不自然だ.とすれば,父が複数ページに現れるのは避けられないということになる.問題を2つに分けて考えよう.

  1. 画面上のカードを保存では生成されるファイルは誤りを含まない正規データでなくてはならない
  2. 父ないし母が複数ページに存在するときの描画上の不具合,ないし,部分図で実質的に項目1のような状態になっているときの対処法

ファイルを読み込んだときに行っている整合性検査をファイル書き込みに先立って実施すべきだろう.可能だろうか?現行では部分図を操作するとき,独立のデータテーブルを使わずに,オリジナルのテーブルの上でやりくりしている.方式的には独立のテーブルを使って既存論理だけで操作するというのが一番わかり易いが,不整合が発生する可能性があるため,現行方式となっている.

部分図では表示するカードが削減されるだけで,関係はすべて温存される.これには利点もあれば,欠点もある.部分図の2つのノードの親等を表示したときに,経路が変化していれば親等が変化することも避けられない(これは事実に反する).いまの場合は本人の母が部分図で非在になった結果,父だけの結婚ページが複数生じるという事態になっているのだが,これを検出できるだろうか?なんらかの方法でこれが検出できればその結婚を非表示にすることで対処できる.実際,部分図を生成する論理では初期化の段階でそれを実施しているはずなのだが…

部分図の場合,ExtractPartialCardで有効なカードと結婚を抽出している.しかし,上記のような矛盾を回避するためにはより厳格な検査が必要になる.FilteringKinshipでは表示モード(祖系図,血統図,親族図,単式図など)に従ってフィルタリングを行う.フィルタリングではカードリンクを削減しているので,この段階でも上記のような矛盾が生じる可能性はあると考えられる.TribeDecompositionが系統並び替えの本体だが,この前に片付けておく必要がある.FilteringKinshipの後でCountValidMargを実施しているので,ここで有効な結婚枠が確定するものと考えられる.FilteringKinship→HideNameboxでも結婚枠の有効性チェックを実施している.

「有効結婚枠判定の厳格化@20201030」というオプションで修正を入れることにしよう.以下のような修正が必要だ.

  1. CountValidMargとHideNameboxの処理は重複しているのでHideNameboxに統一する 
  2. ExtractPartialCardで結婚リンクを無効化しているが,これも不用と思われるのでHideNameboxで一括処理する
  3. HideNameboxでは親ページの重複を検査する この検査は有効な父と母が同じ結婚リンクを重複とみなし,いずれかを削減する

ただし,項目3はやや微妙なところがある.3に該当するのは父ないし母のみのケースに限定すると考えられるが,たとえば,父だけが2つの結婚に残った場合には父の子ども枠では2つの結婚の子どもが合併されなくてはならない.⇒いや,それほど単純なものではない.もし,子どもが残っているとすればその結婚は母方に表示される可能性もある.父方に残った場合には拡張子ども枠として処理されるからそれ自体はおそらく問題にならないはずだ.以下のような場合を考える.

image

この関係の直系血族図は

image

のようになる.異母兄弟は拡張子ども枠として処理されている.妻1と妻2が同じこどもを参照している場合には,以下のようになる.これも問題ない.

image

直系親族図を出すと

image

特に問題なく描画できている.では何が問題なのか?子1を夫の単身婚の子どもとして追加しても特に問題は生じない.夫→子1,夫+妻1→子1,夫+妻2→子1の3つの結婚があるときに,直系血族図を出すと上の図とまったく同じになるが,結婚枠は3つ表示されている.ただし,そのうちの2つは子ども数ゼロで不可視になっている.

おかしい.障害が再現できなくなってしまった.途中で保存してしまったかもしれない.⇒一つだけ残っている.「系列内スプリット MAXPARENTS=4.ZEL」というファイルだ.サンプルは基本的にすべて読み取り専用に設定しておく必要がある.デスクトップ上のサンプルだけでも読み取り専用に設定しておこう.

障害はいろいろなズーム倍率を与えたときに画面が再描画されないという症状だが,一度表示→系図画面の更新を実行するとその後は問題なく動作するようになる.この不良は特定のサンプルでしか起きていないようだが,上記の解析で見ているような問題ではなさそうだ.

反例サンプルでpagesetup(0)→treeview(0)が2つあり,しかもどちらも可視というのはやはりかなりイレギュラーだ.出口検査では多重ゼロとなってはいるが…確かに同じカードに入っているから,多重の定義には当たらないが,本来ならどちらかを消去しなくてはならないところだ.結婚が2つあるとすれば当然仮ノードを2つ生成しなくてはならないのだから,それが同じ仮ノードを指しているというところがそもそも間違っている.⇒読み違えていたかもしれない.pagesetup(0) →treeview(0)という結婚は一つしかない.

TREEVIEW::DrawControlの問題のように思われる.この関数の出口で必ずRefreshを実行するようにしたら,問題なく再描画できた.⇒updatebitmap1が立っていないと画面は更新されない.⇒updatebitmap1は立っているが,TREEVIEW::BuildBitMapで「系統並び替えで遅延処理されるためここではパス」という理由で抜けている.しかし,ズームの場合には通常系統並び替えは実行されない.

系統並び替えが実行されるか否かはFAMILYTREE::spantreenodeで判定される.通常画面が再描画されたときにはspannodcountはクリアされるはずだから,このカウントが間違っていることになる.TREEVIEW::RefreshかないしDrawControlでリセットされなくてはならないはずだが,残ったままになっている.⇒TOPOLOGY:topologicalSortではリセットしている.TREEVIEW::DrawControlでリセットするというのが適切ではないか?系統並び替えを実行して画面がそれに同期した時点で落とすというのは理に適っている.実際,そのような論理に変更して再描画が掛かるようになった.

最後の系統並び替えでリセットされているとすれば,その後どこでセットしているのかは調べておく必要がある.OpenFileProc →InitializeDisplayでChangeTitleDate→<PARTIALMAPS.PARTIAL_UPDATE>→PARTIALNAME::partialRegisterが実行される.partialRegisterでは部分図モードのときはupdatespannodを実行する.部分図のタイトル情報の更新で系統並び替えが実行されるというのは明らかに誤りだ.PARTIAL_UPDATEというのは「日付のみの登録更新」なのでこのケースではupdatespannodするべきではない.しかし,partialRegisterには情報が渡されないので判定のしようがない.PARTIALNAMEにコマンドというメンバー変数を置くのが早い.※

※コマンド処理の入口で設定するのがベストだが,実装ではコマンドごとに個別に更新が必要か否かを判定している.戻り値でこの値を返すことも考えられるが,戻り値では別の値を返している.

TREEVIEW::DrawControlの出口でリセットするというのはやはり問題がある.DrawControlでは描画を遅延処理する場合があるので,フラグが落ちると系統並び替えが掛からなくなる可能性がある.⇒この事象が初回だけ起きるというのはこの日付の登録がファイルオープン時にしか起こらないためと考えられる.⇒ダメだ.まだ画面の更新ができない.⇒抜けがあった.複数箇所で設定している.

これで問題は解決した.バックアップを取っておこう.

縦長い図面のとき,画面に合わせてズームと縦幅に合わせてズームで微妙に高さが違うのはなぜか?⇒理由は分かった.縦幅の場合はスクロールバーが出ることがあるので,それを見込んでいるためだ.フル画面ではスクロールバーもたないので,縦幅よりやや広くなる.フル画面の場合もやや狭めて一致させてもよいが…現状でもよいような気はする…「つねにスクロールバー幅を減じる@20170510」というコメントが残っている.しばらくこれ(画面に合わせると縦幅/横幅に合わせるを一致させる)で様子を見ることにしよう.

ファイルを閉じようとするとき,ときどき下記のパネルが出る.

image

検索文字列.txtには検索履歴が入っているはずだ.現在14個テキストが入っている.アクセスを拒否される理由が分からない.停止しているのはCOUPLING::SaveFamilyTreeでASSERT_NEVER (!undosys)によりSTOPしているようだが,デバッグモードではただ止まるだけのはずなのだが…そもそもERRORCLOSEDという文字列はこのシステムには存在しない.いや,あった.MDIFormCloseのエラートラップだ.MDIFormCloseで以下を実行したときに起きる.⇒StringReaderを使ったままにしていたからではないだろうか?どうもそういうことのようだ.いままでこのようなことはなかったような気がするのだが…

ZTシステム構成図の構築が予想外に手間取っている

ZTシステム構成図の構築が予想外に手間取っているが,まるきり無駄なことをしているというものでもない.相当数のバグが出ているが,これらの大部分(99%くらい)は意図的に停止しているもので無害な動作と言ってよい.これらのSTOP文がなぜ各所に設置されているかというと,そのほとんどは過去の障害履歴と何らかの関係があるものと考えられる.これらはある種の免疫系を構築し,類似サンプルを見つけると停止するようになっているが,目的は希少な障害サンプルの収集にあり,防禦対策の効果を測定する「新薬開発時の治験」に相当する.

ゼルコバの木のテストでは自動生成されたサンプルを含め膨大な数のテスト用サンプルを使っているが,このところほとんど発現しなかったものばかりがぞろぞろ出てきているということは,このサンプルが相当程度難易度が高くZTシステムの堅牢性を検証する上での極めて効果的な検体になっていることを意味する.これまでに発生した致命的な障害は昨日のSUWくらいしかないが,これも当日の修正の結果に依るものであることは明らかなので,逆にゼルコバの木の健全性は相当なレベルで保証されたとも言える.このバグはそれほど(重要ではあるが)深刻なものではないのでそこそこの時間内にシューティングできるだろう.

直接の原因が結婚枠間ギャプをゼロからある数値に変えたことにあることは確かだが,どのような機序で衝突が発生しているのかは解明されなくてはならない.衝突が発生している時期にSUWで強制描画すると下図のような状態になっている.

image

この時点ではLDRは1本のLDR束にまとめられpagesetupの親子連結線とtreeviewの親子連結線は同じパイプを通っている.エラーを無視して強制描画した昨日の図ではLDRを2本個別に取ることによって解決しているが,これは本来の作図法ではない.衝突の当事者ノードはpagesetupの入っている箱#741とその隣にある垂線格納用の結婚枠#745だ.LDR束の移動は先頭LDRを移動することによって実施されるので移動対象はpagesetup(1)になるが,それに繋がるpagesetup(0)の入った結婚枠がpagesetup(1)を親参照しているため,連動してしまい.結局衝突は回避できないという状態が反復している.

LDR束の移動を実施しているMoveLongTailは「LDR束代表ノードを主語として呼び出され,LDR束全体を指定量moveだけ移動する」としているのだから,明らかにこのような事態が発生することを予定していない.ただし,この関数の中ではLDRの下流に連結されたTYW結婚枠だけはこの移動から除外している.類似した動作を行う関数としてMoveBundledLDRとMoveInvisibleBoxがある.

前者は「LDR束のLDRがすべてフローティングLDR(直下にTYW枠を持つLDR)の場合にはこの束を結婚枠内で隣接ノードと接触するまで前方ないし後方に移動する」としている.MoveLongTailの場合は除外対象となるのは直下のTYW婚1個だが,MoveBundledLDRでは下流のすべてのTYW婚を除外して移動を実行する.後者のMoveInvisibleBoxは不可視結婚枠を単体で移動するための関数で下流の結婚枠を一旦親参照パスから切断した後,移動を実行する.この他MoveNeutralという関数は相対矩形領域を直接操作することで移動を実施する.ただし,下流にある不可視の結婚枠とLDRではない不可視の人名枠は一緒に移動する.

MoveLongTailの動作を拡張して,下流にあるすべての可視の結婚枠を除外するようにすればよいのではないだろうか?いや,少し違う.MoveLongTailはoriginateを使わないで相対矩形領域を用いた相対移動を行っている.これなら影響は出ないはずだ.それも違う. LDR代表ノードは相対移動しているが,dummyboxの原点移動を行っている.もしこの結婚枠がダミー枠を親参照しているのならダミー枠の親参照リストから除外すればよいのではないか?あるいはLDRが入っている結婚枠を参照しているのかもしれない.

上の図を見るとpagesetupの結婚枠はTYW枠になっているように見える.だとすればMoveLongTailで処理できてもよいのではないか?・・確かに,margboxCollisionの後は衝突は解消している.ということはどこかでまた蒸し返しているということになる.つまり,MoveLongTailは問題なく動作していると言ってよさそうだ.

image

どこでそれを壊しているのだろう?この処理はMakePairListClean →BuildCompleteTreeの中にある.この中で解決されていることは昨日の段階で分かっている.確かに壊しているのは昨日見た通りCheckMargBoxChangedだ.[結婚枠]:#233と#89で「不可視枠を移動」が起きている.2つともpagesetupの空枠だ.前者は「ZTYW本人を参照する仮ノードが存在する元の親枠」+「親ノードに結合する(連結代表)子ども枠」で後者は普通の結婚枠だ.衝突は#741と#745で起きている.この不良はすでにCheckMargBoxChangedに入る前に起きる.つまり,結婚枠とその中の人名枠にずれが出ている.

image

結婚枠は人名枠の位置とサイズによって事後的に計算されているはずだから,悪いのはこの人名枠の位置ということになる.どこかでpagesetupとtreeviewを動かしている.⇒TRIBELIST:CheckInnerSplitだ.下位関数のTRIBEBOX::CheckInnerSplitでは系列枠のsplitlist(スプリット検定用リスト)を使って系列内に不正規に生じたスプリットを人名ノード間の区間を計算して計測している.

しかし,このsplitlistはかなり危ない使い方をしているような気がする.なぜこんなことをしているのか理解できない.splitlist のクラスはLISTであり,LISTはDATALISTの派生クラスだ.DATALISTはnoduleオブジェクトを数珠つなぎにした単純な線形リストで,そこまではよいが,noduleの固有データ部に無名の(型を持たない)ポインタを使ってCPointの読み書きをやろうとしている.これはどう考えてもかなり悪質だ.リンクされているオブジェクトがnoduleの派生クラスなら固有データ部は(通常)実在するが…

DATALISTのコンストラクタは引数を持つものもあり,そこでdatasizeを指定することができる.リスト要素を生成するときはそのようなdatasizeを持ったリスト要素を生成しているのだろう.しかし,どこでそれをやっているのだろう?小文字のsplitlistは小さくて探し難いのでSplitListにリネームしておこう.SplitListの出現箇所が少な過ぎる.⇒TRIBEBOX::TRIBEBOXに以下があった.

new (this, TRIBEsSLIST) LIST(sizeof(CPoint))

確かにこれでデータサイズがsizeof(CPoint)のリストが作れるだろう.SPLITLISTというクラスを作っておけばよいものをかなりひどい手抜きだ.LISTはデータポインタとしてvoid*を返すような作りになっているので,元々そういう設計だったのかもしれないが…

原因は単純だ.区間検査は結婚枠矩形領域を使って計算されているが,結婚枠間ギャップが加味されていない.marghgapはMARGBOX::heapBranchでは参照されているが,スプリット検定ではまるきり無視されている.TRIBEBOX::CheckGeneSplitのロジックを見ると結婚枠ではなく人名枠の区間を見ている.「ダミー枠を対象に加える@20170418」というコメントが入っているが,人名ノードしか取り出していないのでまるきり動作していない.ただし,ダミー枠の中には人名枠が入っているのでとりあえずこれでも動いている…

人名枠でなく結婚枠で問題ないと思われるのだが,何か不都合があるのだろうか?そもそも,スプリットを検出したときどういう方式で補修しているのだろう?⇒TRIBEBOX::SolveGeneSplitというところで処理されている.スプリットが検出された区間より右にあるものを(論理的には左)にあるすべてのオブジェクトをMoveNeutralで移動しているだけだ.これでなぜ人名枠と結婚枠にずれが生じるのかという理由もわかる.ここは結婚枠を対象に書き換えた方がよいと思う.

結婚枠を対象とするように書き換えただけでギャップを加算していないのに動作するようになった.結婚枠の相対矩形には元々ギャップが加味されている.⇒それではheapBranchの計算は間違っているのだろうか?いや,この計算は人名枠をヒープして結婚枠矩形を計算するものだから,これでよい.結婚枠を基準にすると先祖ノードが落ちこぼれる可能性がある.どうしたらいいだろう.

TRIBEBOX::stackTribeGeneでは系列世代枠リストを用いて集積している.この論理を踏襲するのがもっとも確実なのだが…この関数ではIsNameBoxVisibleとValidMargBoxを使ってそれぞれ人名枠と結婚枠の有効性を判定している.結婚枠をスキャンするにはringを使うのが一番効率がいい.そのために作られているのだから…

◎InvestigateHSplits,CheckInnerSplitなどは公式版では停止する.⇒SOKUDOSAIYUSENというフラグがある.

ズームの動作がおかしい.+をクリックして拡大する代わりに上に動いたり…画面に合わせてズームなども不調.⇒ShowUnderWearで強制描画しているためではないか?いや,違う.画面が更新されていない.部分図でだけ起きているように思われる.全体図・親族図では起きない.これまでは問題なく動いていたはずなのだが…と言っても少し前から不調には気付いていたが…最初からではないと思う.

TRIBEBOX::SolveGeneSplitもstackTribeGeneに合わせて書き換えることにする.⇒SolveGeneSplitの動作をチェックするにはスプリットを発生させなくてはならない.⇒やってみた.問題なさそうだ.これで系列内スプリット問題は全面解決した.

抽象クラスのクラス要素はクラス内部でオブジェクトとして展開する

一応ZTシステム構成図の作図規則は決定しているはずなのだが,実際に描画してみると難点が見えてくる.一番大きな欠陥は配置がフラットになってBobjectのような重要なクラスの内部構造が見えなくなってしまうという点だ.これを改善するために次のような方式変更を考えた.

  1. 基本クラス要素をオブジェクトの子オブジェクトとして表示する
    【オブジェクト】→【基本クラスオブジェクト】
  2. 基本クラス要素はクラスと基本クラスオブジェクトの結婚によって産出される子オブジェクトとして表示する
    【基本クラス】+【基本クラスオブジェクト】→【基本クラス要素】
  3. 上記クラス要素の子オブジェクト展開は抽象クラスに限定する

この方式の利点はクラスの記述がその中で完結しているという点にある.つまり,クラスのブロックを作ってしまえばあとはそれを参照するだけになる.しかし,【基本クラスオブジェクト】というオブジェクトは実装上は存在しないものだから,そのようなものを導入することの当否には議論の余地がある.また,基本クラス要素は基本クラスと基本クラスオブジェクトの結婚の産物なので基本クラスオブジェクトが複数存在する場合には図面が不要に煩雑なものになる可能性もある.

これを避けるためにはこのようにクラス内でオブジェクトを展開する対象クラスを抽象クラスに限定するということが考えられる.現システムには(抽象クラスとして実装されている訳ではないので観念的には)抽象クラスとみなされるものは3種存在している.①NODULE,②DATALIST,③Bobjectだ.これらを整理するだけでもかなり見易くなるのではないだろうか?すでにBobjectについてはこの方向で修正を入れているので最後までやってみることにする.

▲人名カード記入中カードを移動する場合はデフォルトで登録した方がよい.キャンセルは右クリックメニュー→再読み込みでできる.

▲ファイルを保存しようとしてMARGLINK::getOnumで(!margbase.otto)により停止した.このあと,例外が発生した.

image

続行不能のため落とすしかない.再起動後バックアップを開いてエラーが出る.このファイルは開けない.

NAMEBOXとMARGBOX定義を入れ直さなくてはならない.context.hで marghgap = framevgap としてみた.⇒全然効いていない!⇒2箇所修正する必要があった.

▲カード入力中フィールドを移動するたびにIMEの文字種が(全角に)変わるのはうれしくない.

▲子ども欄に記入中ページフルになると強制登録して本人タブに移るが,次ページに移れるようにしたい.

▲SUW(Show Under Wear)が出てしまった.(ERR9)として保存したが再現できるだろうか?undoで戻ってもSUWになる.主選択ノードはghostnodeで,基準ノードはcoupling.全体図から部分図に遷移するタイミングで起きた.このファイルは開いただけでSUWになる.

原本の構成図4はエラーの起きる2分前に保存されている.これが開ければよいのだが…開けた.構成図5として保存しておこう.このファイルから部分図に移動するだけで障害が発生する.このバグを取り除かないと作業にならないのではないか?TRIBELIST::MakePairListCleanでMPLCループカウントオーバーが起きている.

SUWを止めて画面は表示できた.このファイルを(ERR10)として保存してみる.どうも部分図自体が不良という感じだ.不可視ノードの座標補正というダンプが出ている.TRIBELIST::DetectCollision 衝突を検出.反例サンプルは136点というかなり大きなものだが,問題点を切り出すために28点までカットした.

image

かなり関係が錯綜しているので一種の「複雑骨折」のような状況に堕ちているのではないかと思われる.もっと削減可能かもしれないが,このくらいでトレースしてみることにしよう.

▲一覧表の並び替えをしただけで系図画面の再描画が発生する.これはまずいと思う.一覧表の順位がトポロジーに影響するということはあり得るが,それも問題だ.父母数はMDBとtreeviewが4,PDBとanodが3であとはcouplingを除いてすべて1だ.結婚を持たないノードが5つある.これを外してみよう.これで23点になった.婚姻を持たないノードが新たに4点発生した.これは子どもを削除されたために単身になったためだろう.19点になったがまだ障害は発生する.結婚を持たないノードはゼロになった.tribelist, pagesetup,  topology, namesort, treeviewが結婚を2づつ持っている他はすべて1だ.いや,おかしい.婚姻数には画面外の関係も含まれているようだ.ともかく16点まで削減できた.10点まで削減して再現する.

image

coupling→treeviewの切れ切れになった垂線辺りが悪いのではないかという気がするのだが…おそらくこれは障害を再現するミニマムなサンプルだろう.coupling直下のfamilytreeは削減できるかもしれない.⇒できた.9点になった.もうこれ以上は無理なのではないか?もう1点削除できた.8点だ.いや,まだいける!6点→5点になった.

image

これ以上削減するのは無理なようだ.これで見ると問題はtribelistとpagesetupの間にある垂線にあるように思われる.本来ならここには不可視の結婚枠が通っていなくてはならないのだが,線分の引き方を見ると座標がずれているように思われる.いや,結婚枠は存在している.

image

結婚枠は8個描画されている.goodsonのいる結婚枠が5つ,なしの結婚枠が3つだ.goodsonは,tribelist,topology,pagesetup,treeview(5),treeview(0).赤で塗りつぶされているのが可視の結婚枠,小さな黄色いボックスは不可視結婚枠だ.

▲カードをクリックしただけで系統並び替えが発生している.⇒この動作で結婚枠オブジェクトのリサイクルが起きている.⇒これではトレース不能なので暫定的に系統並び替えを抑制しておく.

原因は分かった.今日の修正が影響している.marghgapをふかした分の衝突が起きている.連結垂線を通している結婚枠幅と通常の結婚枠幅に差異が出ている.marghgap = 0とすればエラーは発生しない.

image

これは衝突検定の方に問題があるのかもしれない…実際よりふかして交叉を見ているのではないだろうか?いや,違うのではないか?最終出力では衝突は起きていない.どこで調整しているのだろう?

インテリセンスのファイル格納場所の変更

BuildCompleteTreeで衝突は一旦解決し,CheckMargBoxChangedで再発する.「不可視枠を移動」を実行している.これが元凶だ.実行関数はMoveInvisibleBox.⇒応急措置として不可視枠の移動では結果を無視するということにしてみよう.⇒いや,それは動作には関係ない.どこかで何かが競合しているのではないかと思う.

ZTシステム構成図の作図方式を決定する

もう少しZTシステム構成図の入力を続けることにしよう.クラスとオブジェクトを婚姻させるという仕様に方式転換したので,修正が必要な箇所が残っている.これを点検するために,まず婚姻数をチェックしてあぶれが出ていないことを確認する.実装を持たない(抽象)クラス以外ではすべてのクラス(女性)は少なくとも結婚を1持たなくてはならない.実装を持たないクラスでは配偶者を持たない結婚枠を作り,その中に(必要なら)抽象メンバー(女性)を表示することにする.

いや,そういうことはできないと思う.クラスの単身婚の子どもはそのクラスの基本クラスでなくてはならない.従って,もしクラスの抽象メンバーを女性ノードとして表示するとすれば同じ箱の中に入れるしかない.これはやり過ぎだと思う.オブジェクト(男性)はすべていずれかのクラスに属するはずだから,本来なら必ずクラス配偶者を持つことになるが,図面が混み合ってしまう可能性があるので,別に実装がある場合にはとりあえず単身のまま残すことにする.

CARDLINKオブジェクトの場合,実装はCARDTABLE *PDBに格納されることになる.実際,CARDLINKがこれ以外の場所で生成されることはない.このカードリンクにPDBをポインタとしてアクセスするときの構文は

CARDLINK *CARD = (CARDLINK*)(*PDB)[k];

のようになっている.これはNODULEの基本機能に備わっているoperator[]によってアクセスしているものでnodule *&operator [](int x); のように定義されている.取り出される配列要素の型はnodule*なので使う側ではいちいちキャストする必要があるが,仮想的にはCARDTABLE PDBをCARDLINK*の配列とみなしてよい.

▲BASETABLE<CARDLINK, MAXPDB>の本人タブの氏名をダブルクリックして「検定続行不能エラー」が発生した.

image

処理は続行できるのでUNDOして反例サンプルを取ってみよう.いや,ダブルクリック自体はイベントとして保存されていないので現状のまま保存でよい.(ERR7)としておく.保存したあとの動作が悪い.CARDLINK::ScootParentPageで (PHASE <= INITIALSTATE) が発生して抜けられなくなってしまった.PHASE = INITIALSTATEになっている.⇒なんとか抜けてきた.多分このエラーは再現できるだろう.

▲TREEVIEW::GetViewSizeで(!_size->cx || !_size->cy) 描画領域空エラーで停止した.かなり不調だ.系図画面をクリックしても反応しない.ZTシステム構成図2.ZELを開いただけでまだ特に何もしていないと思われるのだが…ファイルを閉じるときにもTRIBEBOX:setTribeRealnodeで停止する.おかしい.どこか書き換えてしまったのだろうか?作業を中断して食事を終えて席に戻ったところなのだが…

▲ZTシステム構成図(ERR7).ZELを開こうとしてTRIBELIST::GoDownStreamで(marg && !marg->Invalid() && (!marg->margbox || !marg->margbox->ISSETTLED()))により停止,その後続行して以下を出してエラー終了.

image

「修復されました」を出した後もエラーが続き,新規カードを開いた.つまり,(ERR7).ZELは開けない.構成図2.zelは開ける.

どうも作図がかなり難しい.構成規則をもう少し厳密に定義する必要がある.

  1. +を婚姻関係,→を親子関係,【】を結婚枠とする
  2. 【クラス】→【下位クラス(基本クラス),クラス要素…】
    クラス要素とはクラス内で定義されたメンバー変数であり型名(クラス名)ではないが,女性形で表示する
  3. 【オブジェクト+オブジェクトのクラス】→【下位オブジェクト…】
  4. ただし,下位オブジェクトが描画されない場合は結婚関係を省略して【オブジェクト】を終端ノードする
  5. 下位オブジェクトがメンバーとして属するクラスがオブジェクトのクラスより下位にある場合:
    【下位オブジェクト】→【下位クラス要素】
  6. クラスにはクラス名は付けないが,クラス要素には所属:クラス名を付ける
  7. オブジェクトには所属:クラス名を付ける
  8. テンプレートクラスには肩書:テンプレート引数を付ける
  9. 要素構成木のルートcouplingはオブジェクトである
  10. オブジェクトとクラスの婚姻による子どもはオブジェクトである
  11. クラス継承木のルートはNODULEクラスである
  12. クラスないしクラス要素の親はクラスである
  13. クラスの子どもは基本クラス(長女)かないしクラス要素(次女以下)である
  14. 配列要素は配列の子どもである 配列要素と配列要素の型(クラス)の結婚によってその型の内部構成を展開できる

これで矛盾なく描画できるのではないだろうか?

▲配偶者のいない2つの結婚ページにそれぞれ子どもが1人づつ記入されているとき,登録では1ページに合併するはずだが,そのような動作になっていない.BASETABLEにARRAY<bnum>とlookupをそれぞれ登録されているが2ページのままだ.

オブジェクトPDBはオブジェクトanod[]とlookupを構成要素として持っている.これとCARDLINKをどのように結びつければよいか?BASETABLEはテンプレートクラスで引数として<CARDLINK, bnum>を渡されている.これとCARDLINKを結婚させた子どもをCARDLINKのインスタンスとすればよいのではないか?あるいは,anodとCARDLINKを結婚させてCARDLINKのインスタンスとするか?

【配列】+【クラス】→【クラス型の配列要素】

でもよいのではないか?⇒便宜的にそうしておくことにしよう.いずれにしても,CARDLINK型のオブジェクトはCARDLINKと結婚しなくてはならないのだから,配列の下位オブジェクトとして配列要素を産出し,それとCARDLINKを結婚させるというのが順当だろう.

▲おかしい.子ども並び替えパネルが出てこない.⇒別モニターに出ていた.

おそらく一番厄介なPDBとMDBのところが一応終わった.まず,クラス部分図を出してみよう.

image

孤立ノードが6つある.うち2つはBASETABLEのテンプレートのインスタンスで不用になっているので削除できるが,それら以外が孤立してしまった理由が分からない.かなり荒っぽい修正をやっているので多少の補修が生じるのはやむを得ない…残り4つはいずれもクラス木的には終端ノードなので接続は容易だが,特にCARDLINKが孤立しているのが解せない.TREEVIEWのところは接続が間違っているので後から直すことにする.TRIBEBOXも配偶者がBobjectというのは間違いだ.クラス同士の婚姻はここでは定義されていない.Bobjectと言っても男性形だ.

▲部分図から親族図に切り替えようとしてPAIRBOX::CalcPairBoxでASSERT_NEVER (nocommon) エラーになった.⇒再現できる.この状態で保存しておこう.(ERR8)とする.このファイルを開いた場合にも同じエラーが出る.

BASETABLEにならって,NLISTのテンプレートも整理しておこう.NLISTは2つの引数を持ったテンプレートクラスだが,たとえば,NLIST<SIMPLEEDGE, ‘E’> のようなクラスは独立には存在しない.

▲NLISTの母をEDGELISTに付け替えて,CARDLINK::ScootParentPageで停止した. (!OnImportEnd && !APPENDFILE && !PrimaryMergeCard && !OnDeleteCard) 同一親ページの重複を検出.

クラス木は一応図式的には整った.

image

一応すべてのノードの接続関係をチェックしておこう.クラスノードは全部で43個ある.クラスノードは基本クラスとは単身婚で接続するという規則になっている.これに反しているのは結構ありそうだ.ただし,付け替えてもクラス木のトポロジーには変化はない.⇒失敗した.途中で並び替えしてしまったのでどこまでチェックしたか分からなくなってしまった.あと少しだったのに…

▲先祖並び替えで先祖ノードを複数選択して移動できると便利なのだが…ないし,ドラッグ移動して並び替えが実行できるとさらによい.

Bobjectの主要派生クラスであるNAMEBOXが落ちている.これなら木に見えるだろう.

image

さて,要素木の方はどうなっているだろう?現状はこんな風になっている.

image

孤立カードが7点出ている.完全に孤立しているカード5点はおそらくゴミと思われる.

▲カードが削除されたとき,別のカードにジャンプする動作はあまりうれしくない.むしろ単純にその場所で再描画してもらった方がよいのだが…⇒カードが操作されたときにはトポロジーが変化するのでどうしても系統並び替えを実施する必要がある.また,再描画のときの基準点を選択されたカードに置いているため,カード操作のたびに選択カードの位置に戻ってしまう.この動作でよい場合もあるとしても,予期していない動作になる場合が多い.むしろ,基準点(不動点)をたとえば現在の画面中心位置などに置くことが考えられる.かなり大きな方式変更になる可能性があるが,編集ストレス軽減のためには必要な修正だ.

仕掛りの部分に関しては接続関係はおおむねできているようだ.いや,まだおかしな点がある.PDBが3つも親を持っている.PDBの本籍はTOPOLOGYのはずだが,linktableとnamesort+NAMESORTの子どもになっている.確かにどちらからも参照されている.参照の場合はクラス配偶者を持たないとしておこう.

▲pagesetup→treeviewとcoupling→treeviewの2つのtreeviewを合併するとtreeviewがcouplingからpagesetupに移動してしまう.couplingは基準ノードなのに消去されてしまうというのは望ましくない.この図面は一系列なので系列優先ノードには関わりはないが,基準ノードの子ども枠内のノードは保護されるべきだろう.いや,treeviewはtribelistの子ども枠の中にいる.⇒treeviewの血統軸線図にすればcouplingの直下に配置される.とりあえず現状ではそれ以上の対応策はない.

まだBobjectの実装が入っていない.また,TREEVIEWの内部コンポーネントのリンクも途切れている.TREEVIW自身がBobjectなのでtreeviewの位置で実装したはずなのだが…TREEVIEWのBobjctの部分が配偶者なしになっていた.

▲所属グループの親ページからtreeview+TREEVIEWを除去して,PAIRBOX::repairCommonEndPointでDEBUG_NEVER (CheckSamePoint())が起きる.

ゼルコバの木システム構成図の仕様変更

相当数のバグが検出されているが,一番悪質なのは部分図の登録/削除画面での操作だ.かなり惨めな状態になっている.一覧表には選択されたカードだけを表示するというオプションは存在しないが,部分図を使えばそれができる.カードを(属性に従って)個別にカラー表示したり,隠蔽したりすることも部分図の拡張機能として考えられる.(個別に隠蔽することは現在も可能だ)部分図はもっともっと活用されなくてはならないので,部分図のロジックはもっと鍛える必要がある.

システム構成図の下半分はほぼ仕上がったとみてよい.きれいな(と言えるかどうかは別として)倒立した木になっている.上半分の部分図を正立した木として表示することができれば,一応システム構成図としては完成したことになる.どういう図柄になるのか?楽しみだ.

▲GENEBOXの父にbaselistを登録しようとしてMakePairListClean中PAIRBOX::getLocationで停止した.その後の操作でも同様エラーが生じる.GENEBOXとbaselistの間には下記のような関係がある.

image

つまり,母であるGENELISTはGENEBOXの異母兄弟となっている.多分上のエラーはこのような状況を反映したものではないかと推定されるが,図面からこの関係を読み取ることは難しい.このエラーは描画のたびに発生すると考えられるので一時的に停止しておくことにする.⇒今日はバックアップを取らずに始めてしまった.仕方ない.いまからでも取っておこう.サンプルは構成図7とした.

▲構成図7を開き,上図の部分図を再現しようとしてSIMPLEGRAPH:TightenHasseDiagramで「孤立ノードが存在する」エラーが発生した.このサンプルは障害サンプルフォルダにコピーしておく.

▲部分図から親族図に戻ったとき,選択されたカードが画面内に入っていない.⇒全体図→部分図→親族図のように遷移したものと思われる.全体図では選択カードは見えている.

おかしい.BASETABLE<CARDLINK, MAXPDB>はクラス(女性)だが,父がCARDTABLEになっている.CARDTABLEは女性のはずだ.⇒確かにそうなっている.いくらレインボーカラーと言ってもこれは流石にまずいのではないか?しかし,同性婚→養子縁組なら起こり得る事象だ.本来ゼルコバの木では異性婚しか認めていなかったが,現在は緩和して同性関係を許容するようになってはいるが,父母の性別はチェックしていなかったのだろうか?anodも父BASETABLEを持っている.

▲カード履歴の動作がおかしい.一度も訪問していないcouplingが中間に入ってしまう.選択状態は全体図・親族図・部分図共通であったはずだが…⇒図面種別を切り替えたとき強制的に基準ノードが選択されているのではないか?⇒図面種別の切り替えでは再描画のため系統並び替えが必ず実行される.カード履歴では系統並び替えの基準ノードを履歴として記録している.(系統並び替え履歴はカード移動履歴に含まれる)

▲UNDOで戻ったときにも「孤立ノードが存在する」が発生した.ここからREDOでも同じエラーになるので状況が再現できているということだけは言える.つまり,UNDO/REDOは概ね動作している.

▲UNDO/REDOでは図面種別の切り替えまでは再現されるが,人名カードの表示は変わらない.⇒仕様的にはやむを得ないとは思われるが…UNDO/REDOはDLLに送ったコマンドが保存されているだけで,カードの切り替えなどには関知しない…これは仕様である.

▲女性カードが父となっているのは子どもカード生成ないしリンク時の動作が誤っていた可能性が高い.クラスノードを親とするほとんどのノードにこの誤りが起きている.

▲部分図でtoplistの父がDATALISTだったのを母に移動して登録したら,新しい女性カードのDATALISTが生成された.これはまずいのではないか?⇒多分DATALISTはtoplistの子どもだったのだろう.このようなケースでは自動的に新規カードを生成する.これが意図しない動作だった場合にはカード合併で修正すればよい.このようなことが起こるのは実際にはレアケースだと思う.

◎現行では系図画面では右クリックしてもメニューは出ない.これは系図画面を出しているのがアプリではなく,バックグラウンドで動作するDLLであるためだが,DLLの持っている情報だけでも出せるものはあるのではないだろうか?系図画面で右クリックメニューが出ればかなり使い易くなると思う.ただし,カード削除一つ取っても単独では実行できない.VBでカード削除パネルを出すなどの動作が必要になる.DLLからVBにコマンドを発出する機構があれば,それも可能となるのだが…

toplistの母氏名にDATALISTを記入するとグリーンになるのは,実在するDATALISTカードを押さえているためと考えられるのに,実動作では新規カードが生成されるというのはどこかに誤りがあるためと考えられる.おそらく,このカードDATALISTが部分図画面上にないことが誤動作の原因になっているのではなかと考えられる.⇒実際,全体図に移ってから登録を実行すると正しいDATALISTにリンクされている.

一応システム構成図の上半分の要素包含図ができた.couplingをルートとする完全な木になっている.

image

もう一方の下半分クラス継承図も再掲してみよう.こちらはNODULEをルートとする倒立した木だ.

image

この2つを合体させたらどうなるか?こんな感じになった.

image

あまりわかり易い図とは言えないかもしれないが,システム全体の構成を一応網羅的に表現しているものと言って差し支えない.ある意味で「何だこんなものか」と思われる向きもおられるだろう.出口検査で出しているダンプを見ると

★出口検査 重婚同類循環=3 系列数=1 非連結=0 多重カード=1 避けられない多重=1 SYM=0 TYW=0 ZTYW=0 ROUND=3 表示数=4 基準ノード=CARDLINK:#338 @33baselist[0]

となっているが,多重カード1というのは明らかに間違っている.少なくともMDBとPDBは多重カードだ.tribelistも多重だし,NLISTも多重だ.当然避けられない多重1とは思われない.重婚同類循環が3もあれば多重が多発するのは避けられないだろう.図面が間違っているのか?計数が間違っているのか?図面もカウントも間違っている可能性もある.サンプルはゼルコバの木モジュール構成図8.ZELとして保存した.

この図面にはミスが相当含まれていると思われるが,欠落もかなり残っているのではないかという気がする.メモリ管理をやっているブロックがそっくり欠けている.タイトル設定に関するクラスも抜けていた.システム機能のうちnoduleで直接サポートしている部分は完全に隠蔽されている.それでも全体を把握するのには多少は役に立つだろう.さて,そろそろ本線に戻らなくてはならない.どこからこんな脇道に紛れ込んだのだろう?描画セグメントを管理するDrawingObjectの本体をどこに配置するのが適切か?という疑問から始まったような気もするが…

▲treeviewの出現は2つあるが,2番目の出現は配偶者であるはずなのに頭に垂線が入っているのはおかしい.これではTREEVIEWの子どものように見える.treeviewの親はcouplingとtribelistだからそこから入ってくるのならわかるが…treeviewの親はtreeviewの最初の仮ノードで受けているから,ここでは親からの連結線は入らないというのが正しい.

image

この図面の煩雑さから得られる教訓は「結婚枠には任意のカードを登録できるようにするべきだった」という反省だ.この点に関しては設計時かなり悩んだが,問題になったのは「先祖ノードを結婚枠に入れるべきか否か」という点だった.と言うのは「婚姻関係とは本人と配偶者と子どもからなる関係であり,これら当事者のうちの少なくとも2つの関係が成立する場合を結婚とする」と定義していたためだ.しかし,だとすれば少なくとも配偶者が存在すれば結婚は成立する.結婚が成立しているのならそれを表象する結婚枠は表示されるべきなのではないか?

image

これはおそらく結婚枠というオブジェクトを実装する中で結婚枠=子ども枠という考え方が固まっていったためではないかと思われる.実際子ども枠の中に存在するのは本来子ども(兄弟)のみであり,配偶者はある種の転入者と考えられていた.人は父と母を持たなければこの世に生存するを得ない.つまり,人に取って父と母は唯一無二の絶対的な存在である.親が無二であることから子ども枠(結婚枠)は親の結婚枠からリンクされることによって(グラフ理論的にも)結婚木を構成する.

当初設計の時点で方針転換していれば,「先祖ノードだけの結婚枠」というのが実装されていた可能性もあるが,そのときは「先祖ノードはかなり特殊な存在であり,結婚枠を持たないのは不自然ではない」という見方をしていたため実装を見送った.しかし,これを拡張して,「結婚枠の中には誰が入ってもよい」としたらどういうことになっていただろう?多分構図の自由度は格段に増したものと思われる.

結婚枠≒FAMILYと考えてよいが,「結婚枠の中には誰が入ってもよい」と再定義したときの「結婚枠」はむしろ「家庭」というより「世帯」ないし「家」という考え方に近いものになる.実際わたしが子どものころ家は相当貧しかったが,孤児(長兄の同級生)を一人預かっていたことがある.むしろこれはよりリアルな生態を表現できる可能性がある.親子関係がなくても結婚枠の中に入れられるようにすると,一般のダイアグラムを描くのにはかなり好都合だ.現行の構成規則を維持しながら,ここまで拡張することは不可能ではないように思われるのだが…

▲この図には確かにかなりの欠陥があるような気がする.下図ではnoduleが選択されているが,多重出現している.これは回避可能な多重であり,本来解決されるべきものだ.なぜこの状態で残ってしまったのか理由はよく分からないが精査する必要がある.

image

▲tajugraph2の子ども氏名欄をクリックしただけで,以下のようなパネルが出る.まったく意味不明だ.他のテキストボックスをクリックした後は収まった.登録されていない名前なら黙って新規カードを作ればよいし,空白氏名のカードを生成することは禁止されている(カード画面の本人タブで氏名を空欄にしてもよい).

image

不用カードを1枚削除した他は何もしていなかったと思う.ダブルクリックで新規カードを生成するという動作はあったかもしれないが…

▲一覧表で所属欄が見えなくなってしまった.また,列幅ゼロの列は可視に切り替えても見えない.⇒原因は分かった.横スクロールすれば見えるようになる.

image

▲NAMEBOX::IsPossibleBTWLeftHandでASSERT_NEVER (rightwife->IsLeftHandBox())により停止した.treeviewの父母ページで母氏名をCOUPLINGとして登録しようとしたところ.UNDOで戻して(ERR4)で保存.kakeizuでも起こる.

▲TRIBEBOX::SetMinorTribeで(primary->getrelation() == REL_SPOUSE)により停止した.starttribeから子どものTRIBEBOXを削除して配偶者に付け替えようとしたところ.UNDOで戻して(ERR5)で保存した.topUndo,UndoCurptrなどでも起こる.

ここまでのところをZTシステム構成図1として保存.longtable RecordListとBASETABLE<CARDLINK, MAXPDB> が孤立ノードになっている.前者はlongtableの配偶者,後者はBASETABLEの子どもとしておこう.いや,その逆だ.BASETABLE<CARDLINK, MAXPDB>がダブってしまった.後からできた方は削除しておこう.

▲一覧表で行クリックするたびに画面を更新しているようだ.

▲couplingの結婚ページで配偶者COUPLINGのページが2あるなかで最初のページが空のままになっている.(ERR6)で保存しておく.⇒読み直しても空白ページは残っている.⇒これはエラーではない.COUPLINGという同一名の配偶者を2人持っていただけだ.

これまではオブジェクトOのクラスCをオブジェクトの子どもとして配置し,その箱の中にクラスメンバーMを格納するというやり方をしてきた.この方式ではクラス名CはクラスメンバーMの入った箱のラベルという感じになる.クラス木の方はこれでうまく作れるが,構成要素木を作ろうとするとかなり無理な形になってくる.クラス間に多段の派生関係がある場合下位オブジェクトMは一つ上のクラスCupperの子どもになっているので,オブジェクトOはCupperと婚姻関係を結ぶことになるが,CupperはオブジェクトOの子孫でもあるので矛盾が生じる.描画は可能だが,クラスCupperの位置にオブジェクトOの仮ノードが配置され不可避的な多重カードが発生してしまう.

以前に試みたことのあるクラスオブジェクトOとクラスCを婚姻させるという方式を復活させてみたところ,うまくゆくことが分かった.なぜこれがうまくゆくのかという理由は下記のような解釈として与えられる.

「システム構成図は構成要素の包含関係図であると同時にクラス関係継承図でもあることを意図して作図される.構成要素は実体(男性)だが,クラス(女性)は抽象でその中のメンバーもまた抽象である.これを調和させるためにクラスとオブジェクトの婚姻という関係を導入する.クラスという抽象はオブジェクトという実体と婚姻することによりメンバーオブジェクトという実体を産出するという構成だ.」

システム構成図の構成規則は二転三転しているが,多分この方式の方が自然な木を構成し易いのではないかと思う.実際,大分形が変わってきた.これまでよりずっといい感じだ.

image

tamo2さんからもう一つのVAIOが届く

やっと動いた.VB→プロパティ→参照タブでパスの見つからないCOMが2つ上の方に隠れていた.これでやっと参照を操作できるようになった.やれやれ…しばらくデバッグ環境でZTを走らせてモジュール構成図の入力を続けることにする.

▲ウィンドウのドッキングでウィンドウ境界に隙間ができてしまう.これは生成されている実際のウィンドウと理論値に差があるためと考えられる.ウィンドウサイズが変わってしまうのと類似した現象だ.

上半分のモジュール構成図と下半分のクラス継承図をすり合わせるために,以下のような方式を考えた.①オブジェクトを男性,クラスはすべて女性とする.②クラスメンバーはオブジェクトとして扱い,一つの結婚枠の中でクラスを長女とし,メンバーを男子兄弟とする.多分これですべてが解決するのではないかと思う.やってみよう.以前の案はクラスを配偶者として配置するというものだったが,図式的に見てこちらの方が構成し易いのではないかと思う.このようなクラス名とメンバーが表示された結婚枠をクラス枠と呼んでおこう.

あるオブジェクトOがクラスCに属する場合にはOはCを子どもとして持つ.クラスAがクラスBの派生クラスである場合には,BはAの子どもとなる.⇒確かに理屈ではこれでよいのだが,実際動作としてはゼルコバの木では多重を解消することを最大のポイントとしているため,思ったような図式にならない.また,STOPのたびにブレークが掛かるので作業の妨げになる.やはりテストにはリリース版を起こした方がよい.

▲名前を付けて保存したあと,終了して再起動するとリネーム後のファイルが立ち上がってくる.これはリネームした後で編集対象のファイルが変わっていると考えられるので,その時点でタイトルバーの表示を変えるべきだろう.⇒しばらくすると変わるようだ…

tamo2さんからもう一つのVAIOが届いた.普通は受け取りのサインが必要なところ,今日の配達員は「要らない」と言って置いていった.

image

中を開けるとお米が入っていたので,ああ,今度はお米を送ってくださったのだな~と思ったら,その下にノートが入っていた.超薄手のスマートな 2 in 1でキーボードと本体は無線でつながっていて,本体と離れていてもキーボードが使える.(というか,使用時には本体とドッキングするようにはなっていない.サブ機に使っているタブレットはキーボードを持っているが,装着しているときしか使えない).これもVAIOなの?と思えるほどまるきり別ものだが,それを同じVAIOと呼び続けるところにSONYの美学を感じる.

一時は泣きが入るほど追い込まれていたが,ようやくリリース版がビルドできたので安定版として確保しておこう.⇒「すべてのドキュメントを閉じる」を実行しようとしただけでVSがアボートしてしまった.最近のVSはクラッシュする代わりに一度アボートしてまた立ち上がってくる.バージョン番号を変えるとあちこち変更が必要になってくるが所内版の場合はそこまで厳密管理しないで,これまで通りLicenseCode.h を書き換えるだけにしておく.ZelkovaTreeSetup.2.2.0.011-64.msi,パッケージは20201025-KGWZMZCとした.

■部分図を使えばカードを個別に隠蔽することはできる.

▲検索ボックスでテキストを全選択してDELキーで「削除する対象カードを選択してください」が出る.OKでテキストはそのまま残っている.BSで一文字づつ消すことはできる.

Bobject::saveparentの位置を上に上げて,親参照パス操作の区分に移動する.また,getsaveparentというアクセス関数を作った.treeviewオブジェクトはcouplingとpagesetupから参照されている.(本来はcouplingが所有しているのだが…)

image

couplig→treeviewは連結線を引き回して描画されているが,pagesetup→treeviewをリンクすると下図のようにpagesetupはtreeviewのボックスから飛び出してしまう.

image

この場合もtreeviewと同じように,pagesetupを下げなくても(抽出枠を作らなくても)描画できそうな気はするのだが…一般に婚姻による理由以外では下流の子どもとの連結のために抽出枠を作る必要はないように思われるのだが…

▲カード一覧表の表示範囲はもっと広げてよい.たとえば不可視カードなど.選択されたカードというのも表示できればよいのだが… カード一覧表には表示されているカードの点数を(タイトルバーに)表示してほしい.多分部分図に落とせば一覧表に表示され,カウントも取れるとは思うが…⇒選択範囲を部分図として一時的に登録してカード一覧表→一覧表表示範囲→部分図に含まれるカードの操作はそれほど手間の掛かるものではない.部分図を使い倒すというのも一つの方向性だ.

大分まとまって来た.

image

まだ主要コンポーネントのNAMEBOX, MARGBOX, TRIBEBOXやその上のCARDLINKやMARGLINKなどは登場していないが,それらが出揃えば大方仕上がった図になる.一度バックアップを取っておこう.

▲結婚枠間にもう少しギャプがあった方がよい.⇒ただし,そうすると結婚枠内の人名間ギャップも(場合によっては)拡がることになる…

▲氏名同定のあいまい探索は確かに便利ではあるが,危険でもある.該当が1件の場合登録で無条件で確定するが,そのときに名前を補充している.少なくとも名前を補充した場合には,一度保留して「再登録」を待つべきだろう.氏名が厳密一致していないときはイエロー表示でもよいのではないか?⇒あいまい探索は機能としては残した方がよい.

▲子ども12人を登録して子ども数が11のままになっている.

▲カード検索パネルが出てこない.昨日は出ていたような気がするのだが…⇒通常は正常動作している.マルチスクリーンで作業していたことが影響しているのではないか?

▲一覧表でカードを選択してDELで削除パネルが出ない.メニューからは実行できる.

198点まで入力した.うちクラス要素が47個ある.クラス要素だけを部分グラフにするとまだ全然ツリーになっていない.クラス要素だけで逆向きのツリーにならなくてはならないのだが…しかし,この線が入るといきなり見難くなると思われるので,一度バックアップしておこう.現状はこんな感じになっている.

image

クラス要素部分図が細切れになっている理由は中間に一般ノードが入るためもあるのではないか?現状はこんな感じだ.

image

終端はnoduleクラスだが,クラスの大部分は基本クラスがnoduleなので,現在の設定では間に合わない.父母ページ数を大幅に増やさなくてはならない.30個くらいあれば間に合うだろう.MAXPARENTS=32としてみた.⇒起動してすぐ異常終了してしまう.メモリ不足だろうか?nodule::Sansyoで参照カウント負が起きている.TREEVIEW→Bobjectのコンストラクタでcleanを実行しているところだ.以前関数参照木グラフを作っているときにMAXPARENTS=12で動かしたことがある.⇒MAXPARENTS=12でも同じエラーになった.

どうもどこか壊してしまったのではないかという気がする.Dドライブが早くも容量不足に陥ってしまった.10個くらいバックアップを取っただけで満杯だ.と言っても1個で2.4GBもあるので…⇒作業開始前にバックアップした20201025-KGWZMZCは問題なく動いている.WinMergeで比較してみたが,修正を行った箇所以外にはゴミの混入は見られない.修正は以下の3点だ.

  1. Bobject::saveparentのクラス内での位置を上げてprivate領域に移した
  2. saveparentにアクセスするための関数getsaveparentsを導入した
  3. MAXPARENTSを4から8に引き上げた

もしかするとDドライブの容量不足がこの時点ですでに発生していた可能性も考えられる.ファイル転送が終わったら,もう一度修正版をテストしてみよう.どうもバッファ不足が発生していたのではないかという気がする.CARDBASEのサイズはMAXPARENTSによって増減するが,MAXPARENTS=8の状態でsizeof(CARDBASE)は2560にもなっている.現状MAXSTRBUF=2048だが,この値は sizeof(CARDBASE)=1240x2を基準に設定されている.いや,データベースの書き込み時に使うバッファサイズはランタイムに計算している.

下記のエラーが実行時に毎回出る.そのたびにVSを再起動しているが,かなりおかしい.VSを単独で走らせているだけなのにEXEが使えないというのはどういうことだろう?EXEを使っているのはVSだけだ…

image

▲結婚枠データの保存でMAXMARRIAGEでループしている.

image

いずれにしてもこのパッケージは放棄するしかないかもしれない.もう一度バックアップから入れ直してみよう.MAXSTRBUFは4096に増量した.⇒作り直してみたが,やはりMAXPARENTSを32まで増やすと同じような状況になる.どこか分からないが,何かしらまずいことが起きているように思われる.データサイズを大きくしているので,どこかで脚が出ているのに違いない.しかし,アプリのエラーならまず捕捉できないということはないと思われるのだが…MAX=8なら問題ない.あるいは,システムから与えられたヒープを使い切っているということも考えられる.MAX=16でも障害が生じる.

◎VAIOが2台も入ってきたので,分散処理が組めるのではないだろうか?ただし,incredibuildは有償だったはずだ.⇒2万円くらいだ.買えない値段ではない.いや,違う.それは「Acceleration Solutions」の価格で端末にインストールする「Agent」は4コアでも87,000円だ.

MAX=12なら動く.⇒「EXEを開始できない」というエラーは出るが,VSを再起動してやればMAX=32でも動作する.原因はまったく不明だが,もう少し動かしてみよう.noduleの親の登録数が13を超えてから,noduleを子どもとして登録しようとすると氏名欄が赤色表示され,別カードとして新規登録されてしまう.カード合併してやれば父母数を増やすことができる.VBでブレークポイントが効かない.⇒リリース版でテストしていた.⇒NAME_PAGEOVERが発生している.⇒MAXPARENTSがVBでは12になっている!VBではヘッダファイルを読めないのでInportExport.hで記述した内容を転記しなくてはならない!

▲VBとC++で定数が一致していることを確認する.

大体できた!ゼルコバの木システム構成図の下半身だ.

image

とりあえず,ゼルコバの木ではこれ以上にはならない.

▲クラス部分図を全選択→反転してTREEVIEW::selectAllで (topology->ActiveList->count) という理由で停止した.

▲クラス部分図で全選択→反転→部分図登録で作った部分図に女性カードのCOUPLINGが入っていた.

▲部分図をリネームして登録したのに部分図が3つになってしまった.そのうちの一つを削除して部分図の選択メニューが壊れてしまった.

image

▲ここまでのところを構成図6で保存した.このファイルを開き直そうとして,nodule::Sansyoで停止した.previous->Refcount()–;を実行していて例外が発生している.previousが無効になっている模様だ.対象オブジェクトはPARTIALNAME.枝番号は2.このスロットはlongtable *SavePartialListと思われる.この障害はPARTIALNAMEのデストラクタの中でCleanSlotを実行中に発生している.アプリアボート後,再起動してこのファイルを開いたところ,一部不具合がありましたが,修復しましたが出た.部分図は1個だけ残っている.

▲要素包含図で全選択したのに一覧画面ではごく一部のカードしか選択されていない.今度は動くようになった.

男性ノードの要素部分図はまだバラバラで木になっていない.

image

ゼルコバの木システム構成図を入力する

ランニングテストを兼ねて「ゼルコバの木システム構成図」を作っているところだが,いろいろと不具合が検出されている.これらのデバッグないし改善は後回しにして,もう少しデータ入力を続けることにしよう.ゼルコバの木システム構成図の上半分は①COUPLING(系図システムオブジェクト)を頂点とするコンポーネント(実体を持ったオブジェクト)の包含関係図,下半分は②NODULEクラスを基底クラスとするクラスの継承関係図になるということが分かった.当面は両者を無理やり結びつけるのではなく,2つの独立した図面として描画してみるというところから始めてみたい.①はすでに半分まで出来上がっているので,あとは基本クラスを要素として追加するだけだ.

図面①ではオブジェクトの接続関係を実親子関係とし,参照関係を養親子関係として表記することにする.これはメモリ上に配置されたオブジェクトはそのオブジェクトが所属する親オブジェクトを一つだけ持っているという実態に即したものだ.下位オブジェクトへのポインタを格納するスロットにはオブジェクトへのリンクが格納されている.これは接続の場合も参照の場合も同じ.異なるのは子オブジェクトには親オブジェクトへのリンクがあるという点だけだ.「ルート以外のすべての節点が親節点を一つだけ持つ閉路を持たない有向グラフは木になる」のでこの図面は階層的な木を構成する.

スロットに格納されるリンクには二つの場合がある.単体のオブジェクトを参照する場合と,リストのようなオブジェクトの複合体を参照する場合だ.これを図示できないと全体の構図を把握することができないので何らかの工夫が必要になる.ここでは名前の後ろに※を付けることで「集合オブジェクト(一般にはリスト,つまり単純な順序集合)」であることを示すようにしてみよう.また,複数のスロットを使って複数の「集合オブジェクト」を操作しているような場合には,その機能を日本語で表示するノードを説明的に挿入するということにする.

また,ゼルコバの木では性別をカラー表示できるので要素オブジェクトを男性,要素クラスを女性としておこう.要素クラス(基本クラス)はオブジェクトの中に実体があるので実子関係になるものと思われる.しかし,この図面ではたとえばnoduleクラスというのは基本クラスとしてどこにでも出てくるのでそれを同一ノードとみなしたときにはゼルコバの木はそれを強引に描画しようとして相当無理な図面になってしまうことが考えられるので,とりあえず,同一名の別オブジェクトとして登録しておくことにする.

▲kakeizuの子どもにnoduleを入力して登録→すでにcouplingの子どもとしてnoduleを登録してあるので2つのnoduleを同一ノードとして図示→kakeizuの子ども欄でnoduleをnodule1にリネームして登録で下のパネルが出た.

image

このパネルを複数回出したあと正常動作に戻ったが,noduleはフロート状態になり,couplingは子どもを失った状態になった.この後couplingの子どもにnodule(女性)を追加して登録では新たなカードが生成された.本来ならフロート状態のnoduleとリンクされなくてはならないところだが,kakeizuの子ども欄はイエローになっていた.これは複数の候補があることを示すものだが,状況からしておかしい.UNDOで戻ってもう一度確認してみよう.ヒントには

image

とあるが,半ば意味不明だ.これは,氏名入力欄に名前を入力したときの同定カード探索では「あいまい検索」していることが原因だ.ダブルクリックするとカード巡回パネルが出て子ども氏名欄はショッキングピンクに変わる.これで確定選択ボタンを押せば,このカードが登録されるということになるので操作的にはこれでよいと思われる.

image

ヒントの「ダブルクリックして子どものカードに移動」はよいとして,次の「未入力の場合は新規カードを作成」は意味不明だ.確かに子ども氏名欄が未入力の場合はダブルクリックで新規カードを作成するという動作になっているが,記入されている氏名欄の上で出されるヒントとしては不適切だ.⇒いくつか改善項目が考えられる.①あいまい氏名(イエロー表示)が残っている場合には登録時に注意を促すプロンプトを表示すべきではないか?できるだけパネルの表示頻度を減らしたいという意図と思われるが…②ヒントの用語はですます調の方がよい.

言い切りだとコマンドのように聞こえる.たとえば,「子どもの名前を入力して既存カードにリンク」ではユーザはどこからどこまで自分でやればよいのか分からない.「子どもの名前を入力して既存カードにリンクします」なら,(ここでは)操作の主たる目的が「既存カードにリンクすること」だということが(何となく)わかる.このヒントは「一般の場合」のヒントで氏名入力中のヒントにはなっていない.氏名欄の状態によって表示内容を変える方が望ましい.色については①のプロンプトで説明できるかもしれないが…

couplingにnoduleを再登録するときも子ども欄はイエローになったが,ダブルクリックして確定選択でフロート状態のカードにリンクできた.

▲マルチスクリーンで作業しているとき,削除パネルなどが別のモニターに出るのはよくない.現在のスクリーンに表示すべきだ.⇒コマンドを受け付けたウィンドウがどのスクリーンにあるかを特定する必要がある.ただし,パネルは前回表示した場所に開くという原則もある.

考えてみるとゼルコバの木のオブジェクトはすべてnoduleの派生クラスなので個別にnoduleを子どもとして持たせる必要はないのではないか?その方が図面もわかり易い.ほとんどのクラスはnoduleから直接派生している.noduleの孫クラスというのはかなり少ないと思う.Bobjectはその一つだが,何か他にあるだろうか?BASETABLEにはCARDTABLEとMARGTABLEという2つの派生クラスがある.Bobjectの派生クラスはNAMEBOXを初めとしていろいろある.

▲PARTIALMAPがクラス名とCARDCOMMANDのコマンド識別子として使われているが避けた方がよい.⇒いや,間違えた.クラス名はPARTIALNAMEだ.⇒単なるミスタイプと思われる.

▲人名カードでテキストボックスをダブルクリックしてテキストを全選択状態にしようとして戻ってしまう.

あるオブジェクトの基本クラスをそのオブジェクトの下位要素として配置するのはよいとしても,同じクラスに属する複数のオブジェクトが存在する場合にはどこかにクラスの代表ノードが存在しないとあまりに冗長になってしまう.これを避けるため,所属クラスを配偶者ノードとして表示することを考えてみる.これが通用すればクラスノードは一箇所に一度だけ出現するので図面をかなりコンパクトにできる.

たとえば,クラスSIMPLEGRAPHにはnodelist, edgelist, complistの子どもがあり,子どものいない配偶者としてgraph1, graph2, graph3, tajugraph1, tajugraph2, tajugraph3, tempgraph, copygraph, keisengraphがあるという具合だ.子どもたちは単身婚のこどもとしてクラスノードの直下に配置する.⇒いや,これもあまり素敵とは言えない.むしろそのオブジェクトの下に配置した方がましな気がする.複数のオブジェクトと養子縁組すればよいのではないか?

ゼルコバの木では循環が発生するような矛盾した直系血族間の結婚を配偶者同定探索対象からあらかじめ弾いているようで,graph1の配偶者SIMPLEGRAPHをカットして,子ども欄に貼り付けてもボックスはグリーンにならず,登録で新しいカードを生成する.

▲複数のグラフオブジェクトの配偶者SIMPLEGRAPHを子どもに移す付け替えをやっていて下記のエラーになった.tajugraph2の操作を行っているところでエラーが起きた.

image

UNDOで戻したものを反例サンプル(ERR2)として保全しておく.⇒残念ながら再現しない.いや,次のtajugraph3で出た.前回出なかったのは女性→男性に変更していなかったためと思われる.⇒ひなアイコンをクリックしたタイミングでパネルが出ている.登録は実行できる.

▲SIMPLEGRAHPHの父母ページで4ページ目に移動するとエラーパネルが出る.登録ページ数は4.

image

このサンプルを(ERR3)で保存しておく.SIMPLEGRAPHは親を8人持ち,そのすべてを上の操作で登録したつもりだったが,4人しか入っていない.⇒4ページ目で出るのではなく,4ページのあとの空白ページに移動しようとしてエラーになっている.父母ページ数の上限が4になっていたのだろうか?確かに4になっている.MAXPARENTS=8に変更してビルドしたものを再インストールしてみる.

▲リリース版をビルドしたが,OCXが認識されない.VB→参照の追加で該当バージョンのOCXへの参照を追加しようとすると,

image

のようなパネルが出る.VB→プロパティ→参照にはOCXは何も登録されていない.ツールボックスには残っていた.ツールボックスに残っているOCXを削除し,ツール→ツールボックスアイテムの選択からOCXを選択しOKでも同様のエラー↓になる.

image

他に参照を操作できる場所は存在しない…今度はツールボックスへの追加で以下のようなエラーになった.

image

どうも何かが決定的にこじれてしまったような感じがする.もはやこうなったら,Visual Studioを再インストールするか,Windows 10を再インストールするか,あるいは,モジュール名をすべて付け替えるか?の三択しかないような気がする.なぜこんなことになってしまうのか?まったく理解に苦しむ.昨日まではVSを2つ立ち上げてそれぞれを個別に同時実行できていたのが,急に一つも動かなくなるというのはどういうことなのか?誰か説明してほしい…リリース版はともかくデバッグ版まで走らないというのは考え難い.⇒バックアップに戻ってビルドし直した.ビルドは通ったが,実行時エラーになった.

image

HRESULT = 0x80040111は前にも出たことがあると思うが,どう対処したのだろう?クリーンビルドしたら却って悪化した.ビルドが通らなくなってしまった.多分このあとは同じだろう.デバッグモードでビルドできないのだから,セットアップの問題ではない.OCXの参照の問題であることは確かだが,何が障壁になっているのかその辺りの見当がつかない.テスト版に切り替えて動作を見てみよう.⇒ダメだ!再開始スタート版の前まで戻ってみたが状況はまったく変わらない.このようなときには大概奥の手が効いたものだが,それが効かないというのが致命的だ.もやは打つ手なしという感じになっている.

リリース版のOCXをregsvr32で登録しようとしてみたが,下記エラーになった.HRESULT = 0x80040200

image

レジストリが壊れているとしたらWindowsを再インストールするしかないかもしれない…regsvr32でレジストリの登録解除ができる.Zelkova for Test 2.0をアンインストールするためZelkovaForTestから/uを実行してみたが,HRESULT=0x80040201エラーになった.regsvr32 /uを実行するには管理者権限が必要だが,管理者権限で実行してもまだエラーになる.

image

打ち間違えていないはずなのだが,ZELKOVAとZELKOVAFORTESTの両方で実行してみたがどちらも効かなかった.どちらもdebugフォルダにはOCXが生成されている.CCleanerを導入してレジストリのクリーンアップもやってみたが効果はなかった.VB→プロジェクト→参照の追加→COMではZelkovaZ3.ocxが3つレジストリ登録された状態になっている.Zelkova For Test 2.1, 2.2, 3.0だ.⇒ようやく一つ消せた.あとは3.0を消すだけだ.PowerShellを使い,C:\Windows\Syswow64に移動してregsvr32を実行して成功できた.これもうまく行った.

OCXがレジストリ登録時と同じフォルダにあることが必須条件であるのかないのかは分からないが,念のため登録時のバイナリがある場所で登録解除した.あれ,おかしい.まだゼルコバの系図エンジン for TEST 2.1というのが残っている.消したつもりだったが…⇒失敗した.テスト版を作っている.今度はうまくゆくと思ったが,まだ参照追加できない.⇒パワーシェルからレジストリ登録して成功しているのに参照追加できない.どうも完全にいかれてしまったようだ.こうなると最後の手段としてはモジュール名の付け替えしかないように思われる.

絶対世代番号に関わる整理が完了した

Visual Studioは一つのマシンで複数のインスタンスを同時実行することができるが,これらが同一のOCXを参照している場合などにはうまくゆかない.この不都合を回避するためにコンパイルオプションでOCXのuuidとversionを切り替えるようにして並列実行を可能とすることができるようになった.修正前のバージョンと修正後のバージョンを同時実行して,1本のファイルを開くまでの間に200万回くらい呼び出されるような呼び出し頻度の高い汎用関数の呼び出し回数が両者で厳密に一致することが確認されたので,修正の正当性は高度に保証された.このオプションは今後大いに役立ってくれるだろう.

一つ気になっている点としてMARGBOX::nodegeneは不用なのではないかと推測しているのだが…不用なロジックは可能な限り排除しておきたい.MARGBOX::nodegeneが不用と考える根拠は,書き込まれてはいるが,読み出されていないように思われるからだ.単純にMARGBOX::nodegeneを隠蔽してコンパイルエラーを見ることにしよう.まず,最初にMARGBOX::getnodegeneを止めてみた.コンパイルエラーは発生していないが,SIMPLEGRAPH::TightenHasseDiagramのループでMINMOVが不定値になってしまう.つまり,動作が変化している.どういうことだろう?

NAMEBOX::nodegeneでは確かに修正ミスを冒していたが,その原因はNAMEBOXの場合には多少あいまいな点があったためだ.MARGBOXの場合は誤りようがないように思われるのだが…⇒原因は分かった.サンプルが源氏に切り替わっていた.源氏には「避けられない多重」が6個もあるので多重グラフ検定を打ち切ってループの外に出る必要がある.ここで停止するのは意図的にそうしているのだから問題ない.これで懸案の一つは片付いた.ここでバックアップを取っておこう.

これで次に進めるのではないだろうか?ゼルコバの木では人名枠の配置を大きく垂直検定と水平検定に区分している.重婚同類グラフ検定は前者を担当し,メインループで後者を処理していると言ってよい.ただし,例外的にメインループの中で垂直方向の操作を行うことも一部認められている.さて,ぼちぼちと始めることにしよう.連結線の途切れをチェックするための検査を系線グラフ検定,そのために使うグラフを系線接続関係グラフと呼んでおこう.

系線グラフの節点は線分端点の座標,枝は座標の対であるとする.系線グラフが一旦構築されると,今度はそれを描画に用いることもできるようになるが,系線には色や太さなどの属性を持たせなくてはならないのでその辺りはまた後日ということにしておこう.既存のグラフはすべてTOPOLOGY(系図解析木クラス)が管理している.この方がわかり易い上に安全なのでこの方式を踏襲することにする.グラフの本体は人名テーブルや結婚テーブルを保持しているLINKTABLEが所有する.グラフ処理の一般的手順は以下の通り.

  1. グラフの生成 TOPOLOGY::initialize→new
  2. グラフを初期化 TOPOLOGY::ResetExperiment→initialize
  3. ノードリストを生成 ノードリストは枝リスト生成時に自動生成される
  4. 枝リストを生成 両端点を指定して枝を生成 SIMPLEGRAPH::add
  5. 連結リストを生成 DecompConnectedComponent
  6. グラフ処理 ...
  7. 参照カウントの調整 TakeRemainSansyo
  8. グラフを廃棄 delete

描画オブジェクトを扱うクラスとしてDrawingObjectクラスを新設する.DrawingObjectのインスタンスはTreeViewが管理する.座標値は内部ではCPointとして表現されているので,任意長のCPointテーブルを扱えるようにする必要がある.固定サイズのlongテーブルを扱うlongtableというクラスはあるが,これではカバーできない.線描画関数には座標対と線の属性が渡される.DrawingObjectクラスの中に座標対と属性を保持するテーブルを持つということも考えられる.これがあれば,DrawingObjectが単独で系線の描画を実行できるようになる.これは描画を高速化する効果があるだろう.まず,DrawingObject.h, DrawingObject.cppという2つのファイルを作ってみよう.

TREEVIEWはTRIBELISTの下にあり,TOPOLOGYはTRIBELISTの上にある.いや,少し違うのではないか?最上層はCOUPLINGであり,その下にKAKEIZU, FAMILYTREE, TREEVIEW, PAGESETUPがある.参照と接続を区別しなくてはならない.KAKEIZUは系図データベース,FAMILYTREEは系図木構築,TREEVIEWは系図画面出力,PAGESETUPは印刷出力に関係する.FAMILYTREEの下にはUNDOSYSTEM,TOPOLOGY,LINKTABLE,NAMESORT,PARTIALNAME,COUPLINGがある.最後のCOUPLINGは追加読み込み用スロットだ.

開発機にインストールされているゼルコバの木を起動したらエラーになってしまった.再開発スタート版というバージョンをインストールしておこう.インストールされている版はZelkova-Tree 2021となっている.この版をアンインストールしようとしたら,「WindowsにZelkova-Tree 2021を設定しています 必要な情報を集めています」でハングしてしまった.かなりまずいのではないか?

image

キャンセルボタンを押しても終了しない.再起動しかないようだ.再起動したら以下のパネルが出た.

image

11178c24.msiなんてどこから来たのだろう?放置しておいたら,別のパネルが出た.

image

Administratorではないかもしれないが,管理者権限を持ったユーザとしてログインしているのだが…OKでようやくすべて閉じた.ともかく再起動しておこう.⇒多分このトラブルは一つ上のパネルが下に隠れているのに気付かなかったというケアレスミスだろう.今度は簡単にアンインストールできた.⇒とりあえず問題なく起動できた.しばらくゼルコバの木を使っていなかったので準備運動を兼ねて,ゼルコバの木プログラムのモジュール構成図を作ってみることにする.

▲子ども並び替えでドラッグ移動が効かない.カーソルキー操作はできる.⇒これは操作の仕様が変わっているのに説明文が改訂されていないためではないか?ドラッグはできないが,その代わり上下のスピンボタンが表示されている.⇒説明文を改訂する

▲人名枠氏名欄の左側に説明文を出したい.できれば任意配置できるとさらによい.表示項目の範囲を広げて取捨選択できるようにしたい.

▲pagesetupはTREEVIEWを参照しているだけなのに,子ども欄に記入したらCOUPLING→TREEVIEWの親子関係が切れてしまった.確かにこの方が便利な場合もあるが…画面設定→カード画面設定→既定で養子チェックオンというのがあるが,これで親子関係の自動切断動作を回避できるのだろうか?⇒確かにそうなっている.これはこれで便利ではあるが,養子チェックをいちいち外すのは厄介だ.むしろ,実子関係がすでに存在している場合には実親を切り替えるのではなく,養子関係で接続するという方がよい.この操作法をオプションとして提供し,①対象ノードがすでに外部に実子関係を持っているときは養子関係で接続,②対象ノードを実子として登録する場合にはそのノードがすでに実子関係を持っている場合にはその関係を切断するの中から選択できるようにするとさらによい.養子チェックは氏名を入力したあとでないと入力できない仕様になっているが,これでは上のような誤動作を避けることができない.空行を敢えて入力不可とする必要はないのではないか?裏技として,一文字入力して消すと使えるようにはなるが…そこのところは,これでも間に合わないことはないとして…⇒実子関係を切断する前に警告パネルを出すというのが実際的かもしれない.

▲「画面設定」メニューは「設定」とした方がよい.

▲人名カード画面の子ども氏名欄でホイールでスクロールしたときのスクロール量が大き過ぎる.ページスクロールの動作になっているようだが,次行に書き込めない.最小限一行分のダブリが必要だ.

▲子どもが親を2つ以上持っているとき,必ずしも実親の直下に配置されることにはならないが,その方がバランスがよい場合もある.直下に配置することを指定できてもよいような気がする(できない場合があるかもしれないが).しかし,実親を基準ノードでソートしているのに直下に来ないというのはかなりおかしい.⇒ある意味でそれを実現しているのが,「血統軸線図」と言えないこともないが…

▲血統軸線図で下図になるのはおかしいのではないか?UndoChainが軸線上に来ない理由がわからない.⇒これはバグと言ってよいと思う.

image

作りかけのゼルコバの木プログラムのモジュール構成図.ほんの気まぐれで作り始めたのだが,どうもかなり大きなものになりそうだ.実際のところゼルコバの木ではすべてのオブジェクトは1本の木を構成しているので,これを最後までやるとかなり大きなものになることは間違いない.途中でtreeviewという名前のカードが2つできてしまったので,カード合併を実行したところで「親子連結線の途切れ」が出現した.

image

しばらく動かしていなかったので多少とまどいはあったが,少し動かしていると慣れてきて,「ストレスなく入力できる」というキャッチフレーズも(上記の実子関係が切断されてしまうという点を除けば)あながち誇張と言うほどのものではない.UNDOで合併前の状態まで戻れることを確認しておこう.UNDO/REDOは動作しているようだが,REDOでそのまま続けてREDOしていたら,エラーパネルが出て止まらなくなってしまった.操作する直前にバックアップを取っているのでデータは失われないが,UNDOの不良動作を再現できるかどうかは分からない.

image

どこかでループしているもののように思われる.タスクマネージャで落とすしかなさそうだ.このアプリはZelkova Tree 2019(32ビット)(2)という名前で登録されている.デスクトップ上には大量の反例サンプルが発生しているが,すべて同内容なので一つを残して削除しておこう.これらのファイルを開くと以下のパネルが出る.

image

反例サンプルを開くと余分の白紙カードが生成されている.

image

オリジナルは66点なのに対し,反例サンプルは67点なので白紙カードと枚数が合わないが,オリジナルから消えているカードが2枚あるので一応帳尻は合っている.もう少しデータ入力を続けよう.

▲検索ボックスに名前を入力して虫眼鏡をクリックしてもジャンプしない.⇒無選択状態ならジャンプできる.これはかなりおかしい.確かに選択状態を変化させずにジャンプしたい場合はあるかもしれないが…無選択状態のときはそのカードにジャンプしてそのカードが選択された状態になる.人名カードはカード選択と同期しているから,ジャンプしたときカード選択が移るのはやむを得ないと思われるが,無動作というのはまずいと思う.⇒つねにジャンプでよいのではないか?

▲純血統図では養親子関係のノードは無色カードとして表示されているが,むしろ非表示の方が用途があるのではないだろうか?実際,いま作成しているモジュール構成図では「接続関係」が「実子関係」,「参照関係」が「養子関係」に対応すると考えるとうまく表現できるのだが,「構成図」の場合には純粋な(参照関係の系線を省いた)木としての表現が見たいので,「養親子関係は非表示」とした方がフィットする.

image

coulingを基準ノードとして親族図→直系血族図を描画しても思ったような図が出てこない.treeviewには親が3つあるが,実親は頂点のcouplingなのでこの図面ではcoupligの直下にあることを期待しているのだが,tribelistの下に配置されている.これは図面範囲を直系血族図としたとき,図面に配置される人名ノードの範囲は直系血族になっているが,表示されているカード間の関係はすべて温存されているために起こっている.確かに,この図面では表示されているカードの関係情報はすべて網羅されているが,ユーザが期待しているのは別のことなのではないだろうか?それができれば,登録時にはすべての情報を登録しても,表示するときには単純な木として表示することができるようになるのだが…純血統図では(養親系を除く)と表示されている.これを文字通り理解すれば,(養親系の関係は表示しない)となるはずであり,その方がわかり易いような気がする.このオプションの動作をそのように変更すれば,他のところをいじらなくても要求されているような図式を出力することが可能になると思われるのだが…

■カード番号の左右のスピンボタンで移動するとき,飛び番になることがある.これはスピンボタンの動作が一覧表の順序になっているためで,不良ではない.

ともかく,入力を続けることにしよう.

▲カードに個別に色を付けることができるというオプションもあっていいと思う.また,個別に「関係を非表示する」ことができるとさらによい.⇒カードに任意の属性を与え,それを色別表示することが考えられる.⇒部分図という概念があるが援用できないだろうか?ある部分図に属すること=ある属性を持つことという解釈だ.

▲カード一覧表でいくつかの列を非表示にしたあと,一覧表セル幅→均等分割するとまたもとの全列表示状態に戻ってしまう.これはうれしくない.⇒表示領域は現在のウィンドウの横幅とし,現在表示されている列で均等分割するというのがよいのではないか?

この図面は人名枠左に説明を表示できるようになってから,その部分の日本語テキストを補充することを考えているので,今回の入力では実親関係データだけを入力するということにしてみよう.あるいは,全データを入力しておいて,その派生版として複数親を持つノードだけ修正したバージョンを作ることも考えられる.複数の親を持つノードはそれほど多くないので原本としてまずすべてのデータを入力しておこう.

▲#33 baselistの子ども氏名欄に「NLIST <GENEBOX, ‘g’>」と入力→登録でエラーが発生した.この欄にはNLISTという名前が登録されていたが,それを上書きして登録でエラーになった.

image

UNDOで元の状態に戻せる.この状態で一度保存しておこう.(ERR1)とした.UNDOではエラーは発生しなかった.UNDOの種が切れるとメニューは不能状態になるのでそれ以上のUNDOはできない.CTRL+Yを押しても反応しない.とすると,上のエラーはかなり特殊ケースだったのかもしれない.⇒このエラーはゼルコバの木モジュール構成図(ERR1).ZELで再現できる.⇒上書き入力だけでなく,baselistの子どもNLISTを抹消登録だけで再現する.他のノードでも起きる場合がある.extraslot2の子どもCOUPLINGを削除しても同じエラーになった.1人だけの子どもを削除しようとしたときに発生するようだ.エラーパネルが出なくなった後は,エラーなしでUNDO/REDOできる.⇒この障害は子どもが一人だけになったときには確実に発生する.⇒このエラーは子どものカードで親を抹消したときにも発生する.

▲UNDOメニューがすでに不能状態になっているときにCTRL+Zを押してエラーになった.

image

どうもメニューではリミットが検出されているのに,CTRL+Z/Yのキーが入ってしまうことがあるような気がする.OKで次のパネルが出た.

image

これを2, 3回反復してパネルは消えた.メニューではUNDO/REDOのどちらも使える状態になっている.ただし,CTRL+Zを押しても画面上には変化が現れない.CTRL+Yではエラーが出た.スクリーンショットは取らなかったが,「配偶者不在」のようなパネルもあった.そのあと,CTRL+Yで以下が出た.

image

どうもUNDOシステムが壊れてしまったようだ.CTRL+Yを押すたびに上のパネルが出る.一度終了してもう一度始めることにする.クローズボタンで警告なしにアプリが閉じてしまった.最後の状態がなんであれ,ファイルを修正しているのだから,保存しますか?が出なければおかしい.⇒「配偶者データがありません」のあとは正常に動作する.

VS2017を再起動→ソリューションを開いて,変なパネルが出た.

image

確かにVS2017を2つ開いてしまっている.キャンセルしてアプリを落としておこう.どうも細部はまだ完成にはほど遠い状況だが,入力を続けよう.下図まで入力して気付いたのだが,この図には2つの因子が混在している.一つはcouplingを頂点とするオブジェクトの実体的な包含関係,もう一つは実体を持たないクラスの親子関係だ.

image

上の図の赤枠はインスタンス(オブジェクト)で実体として存在するもの,白枠はクラスで実体を持っていないか,あるいは実体を統括した表象とでも言うべきものだ.この図ではコンポーネント(名前を持った実体)はすでにすべて描画されている.しかし,このシステムがそんなに単純なものであるはずがない.それはなぜかと言えばこれ以外にも名前を持たない無数のオブジェクトが存在しているためだ.言ってみれば上図は「骨格図」であり,すべてのサンプルの共通部分と言えるが,それに付随して無数のオブジェクトがさまざまなトポロジーによってリンクされている.そのような実態を一枚の図で描画することは不可能に近いが,上の図にはまだ決定的に不足している部分がある.

それはあるコンポーネントが保持する下位要素にはそのコンポーネントの基本クラスの要素がすべて含まれているという点だ.上図で白枠で表示されている部分はこのような下位要素の一部を展開したものと言える.従って,もし,この図が完成されたとすれば,頂点にはcouplingがあり,真ん中から下の白い領域にも最下層の頂点としてNODULEが来るという構成になるはずだ.これは図式的に見ると「束(lattice)」と呼ばれているものにかなり似ている(意味はまったく違うが…).

image

現状のゼルコバの木を使ってこの意味での「完全な構成図」を描くというのは不可能に近いという気もするが,ゼルコバの木のような複雑なシステムをもし仮に一枚の図式で示すことができるとしたら,それはかなりすごいのではないかと思う.原理的にはそれほど難しくないし,もしそのような図面が手元にあればプログラムのデザインや実装のときに大いに重宝するのではないかと思う.

ゼルコバの木を使ってゼルコバの木システムを図式化するという試みは以前も(途中まで)やったことがある.このときの対象は「関数の呼び出し関係」つまり,「関数木」を作ろうとしていた.Visual Studioには「呼び出し階層」というツールがあってある程度このような関係を図式化できるようになっているが,あまり使い勝手がよいものではない…「ゼルコバの木システム構成図」がどんなものになるかというイメージがつかめたところでまた明日ということにしよう.

■以前は実親は親ページの先頭に配置されていたはずだが,現行ではどのページでも実親として設定できるようになっている.

▲これから手直しというのも大変だが,先祖ノードに結婚枠を与えなかったというのは敗因であったような気がする.結婚枠は背景色のべた塗りしかできないが,枠線というものがあってもよかった気がする.

下図は実親子関係だけを抽出した派生バージョンだが,システム構成図としてはこれが正しい.上半分のピンクは完全な木になっている.

image

この図にはシステムの大きな構成要素である描画オブジェクトリストのようなものは出てこない.なぜか?描画リストはBobjectの4つのスロットを使った三元木として構成されている.TREEVIEWクラスの基本クラスはBobjectだが,上の図のtreeviewにはそれが含まれていない.Bobjectはほとんど抽象クラスだが※,その派生クラスは当然オブジェクトとしての実体がある.上の図ではそれが見えてこない.⇒たとえば代表的な描画オブジェクトクラスとしてNAMEBOXとMARGBOXの場合を考えると,NAMEBOXはCARLINKに保持されている.CARDLINKのnamboxスロットにはNAMEBOXのリストがリンクされる.MARGBOXも同様MARGLINKのmargboxスロットにリンクされる.

※BobjectやNODULEを「抽象クラス」として再定義してみるがよい.

MARGLINKとMARGBOXは一対一に対応するが,CARDLINKとNAMEBOXは一対多の関係になる.CARDLINK自体は上の図で言えばPDBという名前のCARDTABLEに格納されているし,MARGLINKはMDBというMARGTABLEに格納される.従って,上の図をもう少し詳細化すれば基本的にはシステム全図を(一枚の図面として)描くことが可能になると考えられる.(原理的にはゼルコバの木でもそれを描画可能だが,見易い図面にはならないだろう)

デバッグ用のツールなどどこにあるのか上の図からは見えない※.⇒デバッグ用のツールというオブジェクトは存在しない.デバッグ用ツールはほとんどすべてさまざまなクラスの関数で,それを適宜コードに挿入して使っているに過ぎない.たとえば,ShowUnderWearというのはマクロで,例外を発生してあるエラートラップにジャンプしているだけだ.関数の依存関係は関数木として表現できる.ゼルコバの木はアラン・ケイのオブジェクト志向とは真逆の発想だけど,誰か世界中に一人くらいそれを継承しようなんて突飛な人はいないものだろうか…たとえ人間国宝になれたとしても,継承者がいなければ何の意味もない.

※いや,たとえば現在取り組んでいる「抽象グラフ検証系」などはオブジェクトとしての実体がある.現行ではこれらはTOPOLOGYのスロットに格納されているから,詳細化すれば図面にも出てくる.

tamo2さんへの応答

早朝tamo2さんからメールが入っていた.babalabos@outlook.jp アカウントはわたしの公式アカウトとして「テント村」に表示してあるものだが,これはマイクロソフトアカウントでもあるのでほとんどチェックしていなかった.今回Thunderbirdを整理したついでにサブ機でも受信できるようにしたので受け取れたが,危うくのところだった.現在の作業に関わるテクニカルな内容なのでログ上に転記しておくことにする.

tamo2氏からのメール本文:

VAIOのWindows7、Windows8 及びエイサーのWindows7の機種についてはWindows10にアップデートすればゼルコバの木がインストール可能でした。但しWindows10をクリーンインストールしたら、インストール不可能。私が考えるにはVAIOのPCには古い .net 2.0 VisualStadioが温存されているのでは推測してます。以前にWindows10 の機種でゼルコバの木をインストールしようとして.net2.0をインストールして下さいのエラーなった記憶があります。又エイサーのタブレットでWindows10にインストールしていたがSSDの容量少なくVisualStadioをアンインストールしたら動かなくなった。

こちらからの返信:(tamo2氏から送られてきた VAIO にはゼルコバの木ベータ2がインストールされている)

tamo2 さま

お世話になります.

tamo2さんの推理のポイントは .NET 2.0の有無というところですね!?大いに考えられます.

>VAIOのWindows7、Windows8 及びエイサーのWindows7の機種については Windows10にアップデートすればゼルコバの木がインストール可能でした。

Windows 10以前は.NETはオプションだったが,10以降は必須になったためというご理解ですね?

>但しWindows10をクリーンインストールしたら、インストール不可能。

この現象は他のユーザからも報告があります.→新しいバージョンのWindows 10にはもはや .NET 2.0は常備されていないためというお考えですね.

>私が考えるにはVAIOのPCには古い .net 2.0 Visual Studioが温存されているのでは推測してます。

お送り頂いたVAIOで新規ユーザ名でゼルコバの木を実行しようとするとエラーになります.アンインストールすればインストールできる可能性はありますが,アンインストールしてしまうと折角の「ゼルコバの木ベータが根付いている64ビット機」が失われてしまう可能性があるので,いまのところペンディングしています.ただし,インストールが失敗したときの代替手段として,「EXEを直接実行することは可能」ということが分かりましたので,思い切ってやってみようと思います.

>以前にWindows10 の機種でゼルコバの木をインストールしようとして .net2.0をインストールして下さいのエラーなった記憶があります。

.NET 2.0をインストールしてくださいというメッセージは.NETがすでにインストールされているPCでも起こることがあります.これは環境設定で.NETが無効化されている場合に起きますが,「Windowsの機能」というところで有効化できます.検索ボックスなどで「Windows Features」と入力してエンターキーを押すとWindowsの機能パネルが開きます.また,それと反対に,すでに .NET 2.0以上がインストールされているPCにダウンロードしてインストールしようとすると,このPCにはすでに上位バージョンがインストールされていますと言って弾かれます.

>又エイサーのタブレットでWindows10にインストールしていたがSSDの容量少なく Visual Studioをアンインストールしたら動かなくなった。

VAIOにはVisual Studioはインストールされていないように見えますが,Visual Studio 8のパッケージがProgram Files (x86)に入ってますね.Visual Studio にはそのときの .NETのバージョンが入っているはずなので,それをアンインストールしたため動かなくなるということは考えられます.今朝目を覚ましたら画面に隠れて以下のようなパネルが出ているのを見つけました.どのタイミングで出たものかよくわかりませんが,おそらくインストール画面を閉じたあとに出されていたのではないかと思います.

image

まだ試していませんが,→の行をクリックするとオンライン・ヘルプにジャンプするのでしょう.「互換性の設定」という話はどこかで聞いたことがあるので,うまくゆけばインストール時のトラブルがすべて解決できる可能性があります(多分そううまくはゆかないだろうとは思いますが…)以下について調べてみたいと思います.

  1. VAIOに新規ユーザとしてログインしてゼルコバの木をアンインストール→これでOwnerがゼルコバの木を使えなくなるとすればマイクロソフトの「落ち度」と考えられる しかし,新規ユーザとしてゼルコバの木を起動したときの動作から考えると,「すべてのユーザ」を指定していても実際には個別ユーザごとにインストールしていて共有しているのはmsiインストーラだけということも考えられる(実際の動きはそういう感じになってます)
  2. VAIOの新規ユーザでゼルコバの木ベータをインストール→成功した場合,保説の蓋然性が高くなる
  3. VAIOに.NET 2.0がインストールされているかどうかを調べる(昔はコントロールパネル→プラグラムと機能でインストールされている.NETのバージョンがずらずらと出てきたのですが…)
  4. すでに上位バージョンがインストールされているPCに.NET 2.0(ないし下位バージョンの.NET)をインストールする方法を調べる C++のディストリビューションをインストールするという手があるかもしれない
  5. 「プログラム互換性アシスタント」の動作と「互換性の設定」について調べる 可能ならばそれを使ってインストールを試す
  6. 他の機種でも「EXEを実行して直接起動」が動作するかどうかを確認する
  7. ゼルコバの木の直近バージョンで古いサンプルが開けることを確認する(EXEから起動したゼルコバの木ベータで*.QDBを含む2012年以前の古いファイルが開けることは確認済み)

ゼルコバの木ベータで.NET 2.0が必要になるというのはゼルコバの木の根っこがVB6(Visual Basic 6)にあるためとも考えられます.VB6の機能はいまでも使っていますが,コード的には変換されているので .NET 2.0は不要ということになったのではないかと思います.貴重な情報のご提供ありがとうございました.大変参考になりました.

馬場 英治

早速にも上記項目のチェックに入りたいところだが,仕掛りになっている本線が思わぬところで難渋しているので,そちらを先に片付けてしまいたい.修正は32箇所で完全に特定できている.コードは何度も読み直してどこにもミスはないと思っているのだが,思ったように動いてくれない.Visual Studioのコンパイラが誤動作しているのではないかとさえ考えてしまうような状況なので,もはや「本格的なデバッグ」に入るしかないのではないかと判断しているのだが…さて,今日中にこのトラップから脱出できるだろうか?

ありゃ,おかしい.tamo2さんへの返信で添付したはずの画像がメールに入っていない.入れ忘れたのだろうか?画像はVAIOのスクリーンショットだが,Mouse Without Borders で受け渡ししたあと消してしまったのでどこにも残っていない…あ,パネルはまだ閉じていなかった.以下のようなメッセージ※だ.

※この画像はメール本文の位置に移動した

setnodegeneの呼び出しでは「NODULE:nodegeneを廃止する@20201021」がオンのときとオフのときの相違はあるが,すべてTESTABSOLUTEGENERATIONのブロック内のコードで,現在テスト中の環境では「NODULE:nodegeneを廃止」がオンのときもオフのときもTESTABSOLUTEGENERATIONブロック内のコードは実行されないようになっているので,動作に変化がある可能性はないはずなのだが…TribeRelocationの【5】重婚同類グラフ検定の中でSTOPCARDSHIFTがオンになっている.つまり,絶対番号不一致が解決していない.これは実質的に検定が失敗したことを意味している. 異世代多重カウントオーバーが発生している.現行ではこのループカウントは最大でも1しか認められていない.オリジナル版ではこの事象は起きていない.

オリジナルの場合,当初はmultigenes=28, multicount=50だが,重婚同類検定後はいずれもゼロになっている.修正版でも当初は28, 50だが,最初のループで13, 13に減少したあと変化が止まってしまうため,強制終了しているようだ.オリジナル版と修正版を並行してテストできるようにVS2017のインスタンスをもう一つ立ち上げることにしよう.⇒ダメだ.開発パッケージはコピーを用意したが,OCXを参照できない.以下のようなエラーになる.

image

どうすればよいか?OCXは多分,uuidとversionで識別しているはずなので,これを変えてみよう.⇒対処した.デバッグモードでテスト環境と開発環境で独立にアプリを走らせることができるようになった.ただし,どうしてもVBからOCXへの参照が通らないので奥の手(プロジェクトに新しいWindowsフォームを追加してテストツールから直接貼り込むという方法)を使って決めた.一つだけ問題がある.VBのプロジェクト→参照の追加→COMでバージョンの異なるOCXが独立に表示されるようにはなったが,一つのOCXをチェックすると同時に複数のコンポーネントにチェックが入ってしまう.これはおそらく同じ名前のモジュールを作っているためと思われるが,もう少し落ち着いてから対処する.

オリジナル版ではループを一度で抜けている.重婚同類グラフ検定の出口ではmulticountはまだ50のままだが,事後処理のTribeGhostNameで19まで減少し,BetweenTwoWomenで残りを一掃している.今回の修正は重婚同類グラフ検定でそれ以外の部分には影響はないはずなのだが,何かしら副作用が出ているのではないか?TribeGhostNameでは「系列枠の範囲内で消去可能な仮ノードを消去する」処理を実行している.ここでは天皇系列だけで仮ノードを60個消去している.

一方の修正版では50→23→7→13→7→13→7→13…を繰り返して結局13でブレークする.TribeGhostNameでは23点になり.次のBetweenTwoWomenで7まで減少するが,MakePairListCleanで13に戻って以下同じパターンを繰り返す.TribeGhostNameではEraseGhostNameで可視の人名ノードを対象に消去を試みている.これがうまく動作していないものと思われる.最初のループでTribeGhostNameは28個の仮ノードを消去している.オリジナルでは31個消去しているが,その差はそれほど大きくはない.

修正版ではTRIBEBOX::adjustGenerationRangeで「先祖ノードが系列世代範囲を逸脱」が起きている.オリジナルでは起きていない.この差異が大きいのではないか?問題が起きているのは蘇我倉麻呂系列と藤原不比等系列,つまり天皇系列以外はすべてということになる.この関数はmin=28, max=31で呼び出されている.なぜだろう?オリジナルではこの関数では天皇系列しか処理されていない.TRIBELIST::ShiftDirectAbsoluteの絶対世代番号不一致→カードシフトでsc=54までは歩調を揃えているが,そのあとから大幅に狂い始める.

これはTribeRelocationのステージ【5.1】絶対世代番号に基づいてカードシフトで重婚同類グラフ検定のメインの処理に当たる.オリジナルではsc=79まで停止しないが,修正版ではsc=58で停止する.この処理は多重グラフ1の連結リストをベースに実行されている.これはハッセ図ではなく,最初の多重グラフ1ができそこなっているのではないか?多重グラフ1はいわゆる重婚同類グラフで,子どもないし配偶者のいない単身者は対象から除外されている.まず,このグラフを比較してみよう.目視で追いかけるより,グラフをダンプしてそれをファイルに格納し,WinMergeで比較するというのが一番速いのではないか?

グラフ1のノードは人名カード,枝は配偶関係で,連結リストには重婚多重集合のリストが生成されている.グラフとしては完全に一致している.それではなぜ動作に差異が見られるのか?⇒どうもフローが少し違うのではないかという気がする.TRIBELIST::ShiftDirectAbsoluteでscount=58のとき停止しているが,オリジナルは五百城入彦皇子で停止し,修正版ではその次の仲哀天皇で停止している.COMPLIST:DumpComplistのscountは前者が59に対し,後者は61だ.両道入姫で絶対世代番号不一致→カードシフトが発生したときにオリジナルではNAMEBOX::ShiftGenerationで余分なダンプが出ている.

修正版ではAbsoluteGeneGapが真になったため復帰している.なるほど原因は分かった.やはり,一箇所手抜きしたところだ.この関数では!getnodegeneが未設定の間は偽で復帰するようになっていたが,現行の人名枠オブジェクトはnodegeneを持っていないため通常処理して真を返しているものと思われる.TestAbsoluteGenerationでは人名枠のnodegeneを設定しているが,この処理全体がコメントアウトされている.AbsoluteGeneGapを呼び出しているのはCardShiftDirectだけだ.CardShiftDirectを呼び出しているのはShiftDirectAbsoluteはこの位置から呼び出されるのが唯一の出現だ.

!解決した!TOPOLOGY::CountMultiCardが11回しか呼び出されていないということは超速で収束しているという意味だ.最も頻繁に呼び出されている関数の中からMARGBOX::GetUpperNodeを選んで実行カウントを数えてみよう.⇒ダンプの量が多過ぎて一晩では終わらないかもしれない.どこかにグローバル変数を作ってカウントした方がよいかもしれない.⇒いや,完了した.修正版の呼び出し回数は2,156,353回だ.200万回以上実行されている.オリヂナル版のカウントとも正確に一致する.これで2つのバージョンの互換性はほぼ確証できたと言えるだろう.(不一致の可能性は10^6分の1以下とみてよい)

結論的にはAbsoluteGeneGapという関数はまったく不用だったということになる.NAMEBOXだけでなく,MARGBOXのgenenodeも不用なのではないかと思っているのだがどうだろう?⇒これはまた明日ということにしておこう.現状で天皇家を描画するまでに4.7秒くらい掛かっている.渋沢で6秒だ.⇒渋沢でTightenHasseDiagramを実行中MINMOV不定で停止した.このサンプルは避けられない多重が6あるのでやむを得ないものと思われる.いや,渋沢ではなく源氏だった.