カード一覧表をクリック→カード選択でカード画面が変化しない

カード一覧表をクリック→カード選択でカード画面が変化しない.矢印キー,カード画面のスピンボタンでは変化する.系図画面上のクリック→カード選択でも変化する.一覧表の最左セル(インジケータ列)のクリックなら変化する.⇒CardGridView_CurrentCellChangedでCardBox.GetNewCardを実行するように修正.CurrentCellChangedではマウスアップイベントとの重複動作を避けるためにSelectionProcないしSendSelectionを実行しないように修正している.

今後は,カード画面上に表示されるカードを現参照カードと呼ぶことにする.現参照カードは三図面(全体図・親族図・部分図)共通でカード選択操作によって指定されるが,↑↓キーないし,カード画面上のスピンボタン(カード番号の差左右に配置)を操作することで選択状態に変化を与えずに移動することができる.つまり,現参照カードと選択カードは独立の状態として管理される.現参照カードは一覧表の最左列をクリックするか,ないし人名カードのカード番号欄にカード番号を記入→ENTERで直接変更することもできる.

カード一覧表の最左列のクリックで現参照カードを切り替えたとき,一覧画面上のカラー表示行が更新されない.⇒CardGridView_CurrentCellChangedでインジケータ移動を処理しているブロックでChangeRowColorを実行するようにした.

一覧表の表示範囲が系図画面上のカードのとき,系図画面上に現参照カードが存在しない場合には,インジケータは消えていなくてはならないのにそうなっていない.人名カード上のスピンボタンでカード移動した場合にはそのような動作になる.カード履歴で移動した場合も一手遅れてそのような状態になる.

図面種別を切り替えたときには現参照カードがレコードに含まれているか否かをチェックしなくてはならない.また,含まれていた場合にも行が変化している可能性がある.以前はKindredMapSubの中でGetNewTableを実行していたが,現行では「図面種別変更では必ず系統並び替えが実行されるのでここでは不要」としているため,この関数内では検査ができない.同様のことは一覧表の表示範囲を切り替えたときにも起こり得るので,GetNewTableの中で検査した方がよい.

GetNewTableではUpdateSelectionを実行しているので,この中で検査できるのではないか?⇒一番確実なのはUpdateIndicatorでチェックすることだろう.いや,UpdateIndicatorの中から実行されるSetCurrentCellでは現参照用カードのレコードが存在しない場合にはインジケータをリセットしているのだが… UpdateSelectionに渡している引数が悪い.BuildNewTableの戻り値を使っているが,間違いだ.

現参照番号を渡すようにした.カード履歴で移動のときには,Z.SelectedRefnumをUpdateSelectionに渡している.SelectedRefnumは検索などのときにも使用される作業変数なので,適切ではない.Currefnumを使うべきだろう.⇒大体整理されたのではないかと思う.

親族呼称図.ZELの全体図で基準ノードの#46 義父(舅)→婿を削除しようとして,NAMEBOX::Disposeで停止した.その後,系統並び替えで多重グラフ2の節点リストが空で停止した.SIMPLEGRAPH:GetHasseDiagramで「基準ノードが空」エラーが起きる.基準ノード以外のカードの削除では特に問題は発生しない.多重グラフ1の連結成分リストには含まれている.

15  #7743 k COMPLIST 7743 {2}[0]<15> <15>CARDLINK:#629 @48妻の祖父→孫娘の婿[0] <15>CARDLINK:#638 @49妻の祖母→孫娘の婿[0]

ただし,このクラスタは親子関係を持っていないため,多重グラフ2には算入されていない.⇒多重グラフ2は親子関係による枝グラフとして生成されているが,親子関係を持っていないノードもグラフに含める必要がある.⇒最初に多重グラフ1の連結成分リストを転記して多重グラフ2の節点リストを構成しておくようにした.これでどんな多系統図でも扱えるようになったのではないか?

image

「カード削除」によって系列優先ノードが削除されることは普通に起こり得るので,OnDeleteCard中はNAMEBOX::Disposeで停止しないとしておくことにする.

同上サンプルの部分図基準ノード=#45 妻→夫の基準ノードを削除した後の動作が悪い.UNDOで戻ったとき系図画面で現参照カードの枠が消えている.他のカードをクリックするとその枠が逆に表示される.⇒UNDOを実行したとき,画面を更新する前に枠を削除していないのだろう.UNDOを実行したときには必ず系統並び替えが実行されるので,その時点でフラグをリセットする必要がある.

いや,それはやっている.どこかで余分な動作が入っているのではないか?⇒TREEVIEW::DrawControlでは冒頭で選択枠を非表示とし,出口で選択枠を再表示しているが,dispselectしか見ていなかった.DispSelectBoxは選択枠と現参照カード枠の両方を処理しているので,dispprimeを見る必要がある.⇒動作するようになった.

一覧画面上で選択操作した場合には,従来のように現参照カードにジャンプできるようにした方がよい.これまではCardBox.GetNewCardでセンタリングするようになっていたのだが,インジケータなどによる移動でもGetNewCardになるので,センタリングする場合としない場合を切り分けなくてはならない.可能だろうか?

DataGridView_MouseUpではSelectionProc()を呼び出しているが,これもどちらの場合も含んでいる.矢印キーによる移動とカード画面のスピンボタンによる移動ではSpinUpDownを呼び出している.この関数の中でもGetNewCardを使っているので,GetNewCardの外でセンタリングするようにすればよいのではないか?

以前はSelectionProcの中でCenteringCardSubを実行していたのだが… CardGridView_CurrentCellChangedの中ではインジケータ列のクリックとそうでない場合の2箇所でGetNewCardを実行している.インジケータ列のクリックでない場合にはセンタリングを実行するようにした.

HOMEキーも予定したような動作になっている.これで選択操作と現参照カードの操作はほぼ完全に整理が付いたのではないかと思う.これと類似した機能として,検索時のカード巡回とカード巡回パネルによる選択領域のカード巡回がある.チェックしておこう.

一覧表とカード画面は巡回パネルと同期しているが,系図画面のジャンプが止まっている.この操作ではGetNewCardは呼び出されていない.代わりにMakeNewCardを実行している.SetSelectCardで「カード巡回パネルのカードを更新」しているが,この中でCenteringCardSubを実行している.なぜ利かないのだろう?

一覧表でカード選択→ カード巡回パネルで「巡回の対象となる(複数の)カードがありません」のエラーが出る.このエラーはZ.SearchCountの場合に発生する.カード巡回の対象はZ.DeleteTableではなく,Z.SearchTableなので,それを転記する必要がある.TakeSearchSelectionでそれをやっているが,現在のところ止めてある.MakeSearchSelectionというその逆関数もある.

mZelkova::mGetSearchListはTakeSearchSelectionと同等のことを実施している.Zelkova1_NodeClickではmZelkova::mGetSelectListから選択カードリストを取得して,mGetSearchListで検索リストに転記している.mGetSelectListの中でつねにmGetSearchListを実行する必要はないと考えられるので,停止しておこう.その代わり,カード巡回_ClickでZ.mGetSearchListを実行するようにしてみた.

これでカード巡回はできるようになったが,スピンボタンの押下で一覧表の選択が落ちてしまった.これはおかしい.⇒SetSelectCardでUpdateSelectionを実行していたところ,「カード巡回では選択領域を変化させない」という理由でUpdateIndicatorに変えたためだ.UpdateSelectionを単独で実行すると単選択になってしまう.

CZelkovaCtrl3::CenteringCardでは引数にカード参照番号が入っているが,実際の動作ではまったく参照されていない.実際には選択カードリストを見ているため,予定したような動作にならないので,ActionCenteringの引数をACTION_CENTERからACTION_HOMEKEYに変更した.CallCenteringMoveではACTION_HOMEKEYのときは現参照カードにジャンプするようになっているので,この方が実情と整合する.

カード巡回パネルが出ているときに選択状態を変えてもテーブルが更新されない.また,一覧表で選択操作を行うとカード巡回パネルが閉じてしまう.⇒上記ではmGetSelectListの中でmGetSearchListを実行しないとしているが,修正を戻して実行するようにした.また,一覧表上の選択操作でもカード巡回パネルを閉じないようにした.

インジケータ列のクリックで選択が落ちる場合がある.⇒特定のカードで落ちているような感じもする.なぜか,#15 五宮で落ちる.かなり不思議だ.⇒以下の条件が成立してCardGridView_CurrentCellChangedから離脱している.

EditRowIndex = CardGridView.CurrentCell.RowIndex

EditRowIndexが14になっている.EditTableFlagを見ていないためだ.

▲カードと連動をオフにするとカード切り替えがオンになるが,パネルを開いたときにカードと連動オフの場合はカード切り替えはオフになったまま.また,カード切り替えボタンを押してもカード画面の内容は更新されず,パネルを閉じて終了してしまう.

▲源氏物語全系譜6.1.ZELの全体図 #1 光源氏でカード番号でソートしようとして,非参照カウントの残留が発生した.EraseTreeViewからNAMEBOX::Dispose→ RetrieveGhostで起きている.なにかの拍子にカード番号の昇順ソートが掛かってしまった.しかも,その前に選択反転のようなことも起きている.

一覧表のインジケータを選択と独立に操作

終端ノードないし孤立ノードを選択して系統並び替えを実行すると,SIMPLEGRAPH::GetHasseDiagramで「基準ノードが空」というエラーが出ていたので,BuildSameGeneMarriageGraphのステージ【4】で「複数の親を持つ終端カードを節点とする自己ループを追加する」としていたところを,「結婚を持たない終端カードを節点とする自己ループを追加する」のように変更した.これにより,すべての有効なカードが重婚クラスタグラフに含まれるようになった.

これで選択操作と図面操作が切り離され,選択状態は図面をどう改変しても変化しないようになったが,厳密に言うとまだそれが残っているところがある.一覧画面とカード画面上でカード移動を実行すると選択は単選択状態に戻ってしまう.現行では①一覧画面・カード画面上でのカードの移動,②系図画面上でのセンタリング,③カード画面に表示されるカードは完全に連動している.選択状態を維持したままカード移動を実行するとしたら,どんな仕様になるのか?考えてみよう.

  1. 一覧画面上のインジケータが移動する
  2. カード画面に表示される主選択カードが変化する
  3. 系図画面はカードの移動によっては変化しない
  4. 系図画面で主選択カードにジャンプするにはHOMEキーを押す

ということになるのではないだろうか?カード検索を実行したときに表示される「カード巡回」パネルはやや上と類似した動作になっている.ただし,検索結果に含まれるカードはすべて選択状態になっているので,①選択されたカードを巡回する,②系図画面ではセンタリングが実行されるという相違点があるが,考え方としては近いものがある.上のような仕様が実装されることになれば,カード巡回パネルの操作でも系図画面は変化しないということになるのではないだろうか?この方が操作的には軽くなり,より使い易くなるのではないかと思う.

一番の問題点は項目1の「一覧画面上のインジケータが移動する」,つまり選択とインジケータの操作を完全に分離可能かどうか?という点にある.まず,この点を確認しておこう.⇒難しいかもしれない.一覧表のクリックとUP/DOWNキーの押下は同じイベントで処理されている.いや,先にキーイベントが発生しているから,切り分けることはできるのではないか?⇒可能だ.その前に,カード移動したときセンタリングしないようにしたときの操作性がどのように変化するかを見ておこう.

センタリングしないというのでよいのではないか?実際,部分図や親族図でカードが画面上に存在しない場合などもある.つまり,カード移動では系図画面は変化しないというのでよいと思う.ただし,カード画面と一覧画面はつねに連動するものとする.

もう一つ問題がある.仮に選択状態を変化させずにカード移動ができるようになったとしても,すべてのカードを巡回しないとそのカードに到達できないのではほとんど意味がない.カード画面ではカード番号を入力→ENTERでそのカードにジャンプできるが,それと同等のことが一覧画面でもできなくてはならない.一覧表の最左列つまり,インジケータが表示されている列のセルをクリックするとそこにジャンプできるようにすることは可能だろうか?

▲カード編集:カード巡回で「巡回の対象となるカードがありません」の表示が出る.一覧画面で複数カードを選択しているのだが…

▲プレビュー画面でズーム倍率を100%に切り替えたら,Zelkova1_MoveControlでAutoPosition.X < 0 Or AutoPosition.Y < 0というエラーが起きた.また,ズーム倍率25%でウィンドウ枠をドラッグしたら何重にも線が重なって画面が壊れた.ここでズームーボタンを押したら,倍率が595%になった.

親族図:直系血族図をカード一覧表:すべてのカードに切り替えて全点で62のところが,124点に増えてしまった.TREEVIEW:CheckSelectListでカウント不一致のエラーが出ている.選択カード数は1でselectflagのカウントはゼロ.

BuildNewTableでは,テーブルを一旦空にした後,再構築しているが,このとき,行の追加によりCurrentCellChangedイベントが発生→ CurrentCell.ColumnIndex = 0→最左列のクリックと誤認してGetNewCardを実行→ MakeNewCard→ 参照番号がゼロであるため,GetNewTable(True)で新しいテーブルが追加されるという動作になっている.⇒CardGridView_CurrentCellChangedでテーブル構築中は無動作で抜けるようにした.

基準ノードの行はシアン色で表示されているが,この行を含む複数行を選択した後,他の行をクリックすると,色が落ちてしまう.⇒しかし,起こる場合と起こらない場合がある.どうも行の並びと関係があるような気がする.⇒背景色設定を共通ルーチン化することで漏れを排除するようにした.⇒解決.

▲親族図と全体図で系統並び替えの基準ノードを共有しているように思われる.これらは独立ということになっていたのではないか?部分図の基準ノードは独立しているようだが… 確かにこの仕様はバランスが悪いような気もするが,実用的にはその方が適切である場合もあり得る.全体図でカードAを基準ノードにしているときに,親族図に移動する目的は,Aの親族図が見たいという場合が多いのではないか?このとき,まったく別のカードの親族図が出ていたとすると混乱する可能性がある.

しかし,現行では系統並び替えによっても選択領域は変化しないから,カードAが選択されていれば,そのまま系統並び替えを実行すればよいということになるのではないか?部分図のように親族図も独立の基準ノードを持つとした方が,仕様的には筋が通っていると思う.また,今回の「選択領域と提示カードの分離」という方向性にも合致している.

ただし,これを実装するにはファイルのフォーマットの変更が必要となるので,右から左という訳にはゆかない.同種の課題として,全体図・親族図・部分図で独立の環境パラメータ(親族種別など)を持つという懸案もある.これも保存ファイルのフォーマットに関わるので,もしやるとすれば同時に実現した方がよい.

この件は一時保留としてもう少し片付けることにしよう.一覧表のインジケータ行とカード画面に表示される提示カード(仮称)は完全に同期するようになったが,ここまで来ると系図画面にも出さないという訳にはゆかなくなる.提示カードは従来仕様の「主選択カード」に類似しているが,選択領域に含まれていないというところが大きな違いだ.

現行では主選択カードの取り出しには2つの方法がある.①系図画面で左ボタンアップ→TREEVIEW::LButtonUpで取得,②カード画面に人名カードを表示する際に,Z.mSetPrimarySelectionでカードの参照番号を送付.どちらの場合も最終的には人名カードが更新されるので,mSetPrimarySelectionがあれば間に合いそうだ.取得した値は,TREEVIEW::selectedcardとselectednameに格納されるので,とりあえず,それを流用することにしよう.

▲主点カードはカード画面上に表示されているカードと一致しなくてはならない.従って,一覧表の表示範囲が系図画面上のカードのとき,系図画面上にそのカードが存在しない場合には,インジケータは消えていなくてはならないのにそうなっていない.人名カード上のスピンボタンでカード移動した場合にはそのような動作になっている.カード履歴で移動した場合でも,一手遅れてそのような状態になっている.

▲親族呼称図.ZELの直系血族図で基準ノードの#46 義父(舅)→婿を削除しようとして,NAMEBOX::Disposeで停止した.その後,系統並び替えで多重グラフ2の節点リストが空で停止した.全体図でも類似の障害が発生する.このケースではSIMPLEGRAPH::GetHasseDiagramで「基準ノードが空」エラーが起きる.基準ノード以外のカードの削除では特に問題は発生しない.

系統並び替えを実行しても選択が落ちない

カード選択はユーザの主体的な行動であり,システム側からユーザに押し付けるものではない.カード選択操作の場面は,①系図画面上の選択,②一覧画面上での選択,③カード画面での移動,④編集コマンドによる選択がある.③ではつねに単選択になるが,それ以外は一般に複数カードの選択が可能だ.①で系図画面上のカードをクリックないし拡張選択した場合はOCXが選択/解除されたカードないし領域をDLL側に通知する.DLL側ではそれに従い,selectcardlist->tableを更新する.

②の場合,アプリ側ではZ.DeleteTableに選択領域を設定して,GCに送り,GCではそれをDLLに伝達する.DLL側ではDeleteTableの内容をTREEVIEW::selectcardlist->tableに転記する.④には全選択/選択反転がある.全選択では「有効なカード」がすべて選択され,選択の反転では「有効なカード」ー「選択されたカード」が選択状態になる.「有効なカード」とは一覧表表示範囲:系図画面上のカードに相当する.カードテーブル上のカード(CARDLINK)はselectcardlist->tableと同期するためのフラグselectflagを持っている.DLL側でselectcardlistの更新を行っている関数には以下がある.

  1. TREEVIEW::putSelectList ←CallPutSelectList
  2. TREEVIEW::selectAll ←CallSelectAll
  3. TREEVIEW::hitSelectNode ←TREEVIEW::LButtonUp
  4. TREEVIEW::selectNode ←TREEVIEW::LButtonUp
  5. TREEVIEW::getSelectList ←CallGetSelectList
  6. TOPOLOGY::RebuildCardList ←UNDOSYSTEM::UndoProcess,UNDOSYSTEM::CommandEnd

getSelectListはputSelectList の逆関数でアプリ側にselectcardlistの内容を返す関数だが,その前にカードテーブルをスキャンしてselectflagオンのカードをselectcardlist->tableに収集してから送付している.RebuildCardList はUNDOシステムで用いられる関数でカードのselectflagからselectcardlist->tableを復元している.系図画面で拡張選択したときの動作を見てみよう.初回だけは系図画面と一覧画面が同期していたが,後が続かない.なぜか?

LbuttonUpからselectcardlistを更新するところまでは問題ない.その後,Zelkova1_NodeClickが起動され,mZelkova::mGetSelectListを呼び出してZ.DeleteTableを更新している.Z.DeleteCountの値も正しい.一覧表の更新はUpdateSelectionで実行している.どうもどこかで選択が落とされている.ただし,Z.DeleteTableの中身は変化していない.

UpdateSelectionの中で落とされている.UpdateIndicatorで単選択に戻されている.動作不良の元凶はUpdateIndicatorだ.インジケータと呼んでいるのは,一覧表の最左列に表示される右矢印を意味している.選択操作に関連するが,インジケータの操作で単選択になってしまうというのはおかしい.UpdateIndicatorを実行しなければ,系図画面と一覧画面の選択状態は完全に同期している.

UpdateIndicatorから呼ばれるSetCurrentCellで単選択に落ちている.「現在のセルを変更すると DataGridView 選択範囲が変更される場合があります」ということのようだ.設定で回避できるのだろうか?現在の設定は以下のようになっている.

.SelectionMode = DataGridViewSelectionMode.FullRowSelect ‘つねに行全体を選択
.MultiSelect = True             ‘複数行の選択を許す
.AllowUserToDeleteRows = False
.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2

Selection Modes in the Windows Forms DataGridView Control によれば,「Note that changing the value of the CurrentCell property does not alter the current selection」となっているのだが…

UpdateSelectionでは以前は選択領域設定の前にUpdateIndicatorを実行していたのだが,「引数のカード参照番号が選択されていない場合がある@20180830」という理由で現在の位置に移動している.しかし,これでは完全に誤動作してしまうので,修正前の状態に戻すことにする.選択されていない参照番号を指定した場合には余分なカードが選択された状態になり,整合が取れなくなる可能性がある.CurrentCellを非選択にできるかどうかを調べてみよう.

問題なさそうだ.これで要求を満足する動作になった.複数選択動作でまだ一つだけ不十分な点がある.一覧表でインジケータの出ている行と,カード画面に表示されているカード,および系図画面で濃紺で表示されているカードは連動しているが,系図画面上で選択を落とす操作をしたときに濃紺で表示される「主選択カード」が消えてしまう場合がある.一覧表で操作した場合には問題ないように見える.

部分図で複数選択を実行して,getSelectListでCheckSelectListのエラーが起きた.getSelectListではカードテーブルからselectcardlistを作り直している.CheckSelectListでは有効カードのみをカウントしている.getSelectListでも同様処理するようにしてエラーは解消したが,有効でないカードの選択フラグはむしろ積極的に落とす必要がある.今度はTREEVIEW::hitSelectNodeで同様エラーが出た.

上記の修正は間違っている.「選択領域はカードの有効・無効とは無関係」というのがゼルコバの木の仕様だ.ただし,全選択と選択反転は有効カードのみが対象となる.⇒対処した.

図面種別を切り替えると系図画面が無選択状態になってしまう.系図画面の切り替えでは一度選択領域をリセットして,再描画する必要がある.系統並び替えの冒頭で実行されるTREEVIEW::InitTreeViewでsetSelcount(0)が実行されている.図面種別の切り替えでは必ず系統並び替えが必要になるから,ここでリセットされたのでは対処しようがない.GCに問い合わせできれば取得可能だが,上りインタフェースは存在しない.⇒InitTreeViewではsetSelcount(0)を実行しない代わりに,COUPLING::EraseFamilyTreeでリセットするようにした.

▲系統並び替えを実行して,GetHasseDiagramで「基準ノードが空」エラーが発生する.seedはFAMILYTREE::BaseLinkを含む成分リストで多重グラフ2の節点リストで探しているのだが… 通常の手順では発生しない.複数カードを選択し,そのうちの一つをCtrl+クリックで選択解除→ Ctrl+クリックで再選択してから系統並び替えで発生する.その後は図面種別の切り替えなどでも同じ事象が起きるようになる.

グラフをダンプしてみたが,確かに入っていない.ただし,これは上のような「手順」の問題ではなく,クラスタ図自体の問題だ.つまり,現行では終端ノードは世代番号の確定に関係がないという理由で省かれている.これは確かにまずいのではないだろうか?

描画領域サイズオーバーの問題が片付いた

VAIO2に(一昨日)仕掛けてあった渋沢一族の完全木テストの結果がダンプされていたので記録しておこう.所要時間1時間57分となっているが,時計の針は少なくとも一周しているので26時間掛かっている.

包括テストI 完全木テストを完了しました.
ご協力ありがとうございました.

C:\Users\babalabo\Desktop\渋沢一族8.ZEL
サンプル点数: 829 経過時間:01:56:51 検定図面数: 7461面
計算時間:12.52 秒/面 99.81 ms/点 延べ点数: 935925点

描画領域サイズオーバーの問題が片付いた.かなりあちこち調整する必要があった.主な点を挙げてみると,

  1. ZoomListTool_SelectedIndexChanged SendKeys.Send(“{ENTER}”)を廃止し,SendKeys.Send(“{BACKSPACE}”)を実行する
  2. MDIForm_KeyDown Keys.EnterではSetZoomRateを実行し,Keys.BackではResetZoomRateを実行する
  3. SetZoomRate Zelkova1.ZoomSetを引数ZOOM_RESETで呼び出す
  4. ResetZoomRate Zelkova1.ZoomSetを引数ZOOM_NOMSGで呼び出す
  5. CZelkovaCtrl3::ZoomSet CtrlZoomSetの戻り値がERR_ZOOMOVERRANGEのときはActionCenteringを実行する
  6. CtrlZoomSet 引数がZOOM_RESETのときは,TreeView->OVERSIZEをリセット,ZOOM_NOMSGでは保持してZoomSetを実行する
  7. TREEVIEW::CheckDispSizeOver OVERSIZEがオンのときは,「この図面は~以上には拡大できません」の表示を抑制する
  8. TREEVIEW::LimitSizeOver 描画領域サイズオーバーが発生した場合には,OVERSIZEをオンにする
  9. TREEVIEW::Zoom OVERSIZEならERR_ZOOMOVERRANGEを返す
  10. TREEVIEW::ZoomIn,ZoomOut ZoomSetを呼び出す前にOVERSIZEをリセットする

要点は,①エラーコードERR_ZOOMOVERRANGEがアプリ側まで伝達されるように経路を整備(渡せないところではTREEVIEW::OVERSIZEを使う),②警告パネルが重複表示されるのを抑制,③ズーム倍率リストのテキスト変更でリターンキーが押された場合,④ズーム倍率リストのインデックスが変更された場合の動作を(外形的に)統一する.⑤エラーが発生した場合にズームタイマーを確実に止めるなど.コンボボックスのSelectedIndexChangedイベントをキャンセルできないという不都合に対処するために,キーイベントを送ってイベントハンドラで遅延処理するという仕掛けを作り込んだのは2017年頃のようだ.デバッグモードではこの操作が止めてあったため気付かなかった.

系図画面ないし一覧画面上での選択動作にいろいろと不具合がある.選択操作と部分図操作は切っても切れない関係があるので,正しく動いてくれないと甚だ都合が悪い.特に一覧画面上の動作が悪い.まず,最初に一覧画面上に表示されているレコード数をチェックできるようにしておこう.⇒ModeNameChangeの末尾で以下を実行するようにした.

CardTable.Text = TitleName + “ 《” + ModeName + “》” + “ ” + Str(CardTable.CardGridView.Rows.Count) + “点”

これでほとんどカバーできるようだ.数字も合っている.選択されているカードの数も出しておこう.CardGridView_SelectionChangedでModeNameChangeを実行するようにして同期が取れるようになった.

一覧画面上での選択操作は系図画面上の選択されたカードと同期している.また,カード画面に表示される主選択カードも同期している.問題は,系図画面上での操作が一覧画面に反映しないという点だ.カードが1点だけの場合は一覧画面にも反映される.また,選択解除も同期しているが,複数選択になるとまったくダメだ.

しかし,「まったくダメ」という訳でもない.入る場合と入らない場合がある.しかし,ほとんど入るという場合がない.親族図で複数選択して部分図に移動すると一覧画面でも複数選択になる場合がある.ただし,このとき部分図は無選択状態になっている.また,何かの拍子で選択が反転して「訳が分からない状態」になる場合もある.⇒渋沢一族ではサンプルが大き過ぎる.親族呼称図を使うことにしよう.

▲系図画面設定の動作がおかしい.結婚マークを表示する→ 人名枠線を表示するとして結婚点が下枠の高さに表示されてしまう.⇒ただし,この事象は再現しない.また,結婚マークを表示するをオン・オフしても画面に反映されない.

GetHasseDiagramの論理を見直し

岩崎彌次郎系列を選択して部分図に切り替えようとして,SIMPLEGRAPH:GetHasseDiagramで停止した.この関数を呼び出すときの引数seedが空になっている.⇒SIMPLENODE::AddOyakoEdaで枝が生成されていない.⇒「系列分解図の場合は始系列のみ処理する@20171125」となっている.これはかなりまずい.クラスタ図は婚姻と親子関係だけで構成されるので,「系列」は無関係のはずだ.

いや,そういう訳にもゆかない.確定世代番号を得ることがクラスタ図の目的だが,系列間の結婚によってそれが歪められてしまう.かなり厄介な話になってきた.系列分解図の場合は重婚クラスタ検定はパスするというのが現実的であるような気がするが,この問題は棚上げして,部分図の場合はつねに系列分解図オフとすることで逃げることにしよう.

渋沢一族が5つのブロックに分解している事情を解明する手がかりとして,岡部長景の傍系親族図と渋沢栄一の傍系親族図の接点となっている尾高豊作@22の傍系親族図を取ってみた.246人を収容するかなり大きな親族図だ.尾高豊作は尾高 惇忠(藍香)の子どもの尾高次郎と大内ふみの間の子で,尾高家は渋沢一族の中でも渋沢家に次ぐ大きな氏族だ.尾高豊作の配偶者の岡部豊子は岡部長景とは異母兄弟に当たる.

尾高豊作の娘尾高泰子からすると,岡部長発は直系血族,岡部長景は傍系血族に当たるから現行アルゴリズムでもトレース可能なはずなのだが… クラスタ図の枝は親子関係だが,婚姻関係は1個の節点(クラスタ)として集約されているので,尾高豊作→ 岡部長景のパスが検出できないということは考え辛い.SIMPLEGRAPH::GetHasseDiagramの論理を見直してみよう.

確かに,現行では到達できないパスが発生するのは避けられないように思われる.現行アルゴリズムは以下のようなフローになっている.

  1. 起点から上流/下流検定を実施する
  2. すべての先祖ノードから下流検定を実施する
  3. すべての末裔ノードから上流検定を実施する

この論理では傍系に到達できない可能性がある.書き直してみよう.先祖ノードからの下流検定と末裔ノードからの上流検定を一体化して,下流検定→ 上流検定→ 下流検定を反復する必要がある.⇒解決した.

MARGBOX::CheckMargBoxChangedで@20渋沢市郎右衛門の先祖リンク不良が反復発生するのはなぜか?⇒該当する結婚枠が複数存在するためだ.⇒ダンプを抑制した.

現行では重婚クラスタ検定の入口で多重カードをカウントし,多重カードゼロの場合は重婚クラスタ図を生成しないようになっているが,つねに生成するようにすべきではないか?⇒多重カードゼロのサンプルは比較的単純なものが多いのでクラスタ検定を実施してもそれほど負荷が掛かる訳ではないのでやった方がよいと思う.やらなくても弊害はほとんどないとは思われるが,やっておいた方が安全だ.

画面サイズオーバーの問題が出ているので調べておこう.

系列分解図で栄一の系列を選択→新規部分図で部分図に切り替えようとして,TREEVIEW:CheckDispSizeOverのエラーになった.系列分解図でズーム倍率46%のとき,尾高磯五郎系列のカードを拡張選択して部分図:新規部分図で「現在の選択範囲を部分図に設定」した後,「部分図モードに切り替えますか?」→「はい」を押して,TREEVIEW:Zoom→ SetOuterFrameでエラーが発生する.OuterFrameには系図外枠が入っているが,幅が上限の32000を超えている.

しかし,選択された部分図の領域はそれほど大きなものではないので,全体図の領域と間違えているものと思われる.「部分図に設定」しただけでは描画領域は確保されず,部分図モードに切り替えて系統並び替えが実行されて初めて部分図の領域が確定するので,ZoomSetが掛かるタイミングが早過ぎる.ズーム倍率は描画に先立って切り替えておく必要があるが,適用される領域が間違っている(まだ計算されていない).

TREEVIEW::CheckDispSizeOverはGetTitlePositionから呼び出されているが,GetTitlePositionの呼び元は2つある.①CallGetTitlePositionと②SetOuterFrameだ.前者はという外部関数から呼び出されているが,後者はLButtonUp, SetDispParm, SetTitleBox, UpdateDiagram, Zoomなどいろいろなところから呼び出されている.

TREEVIEW::ZoomSetにはapplyという引数があって,Zoomを実行するか否かを選択できるようになっている.これをオフにして呼び出せばよいのではないか?TREEVIEW::ZoomSetは,CtrlZoomSet, MakeLeastWindow, ZoomIn, ZoomOutから呼び出されている.今の場合は,CtrlZoomSetからの呼び出しだが,この関数ではモードがZOOM_RESETとZOOM_KINDREDの場合にのみ,ZoomSetを呼び出している.ZOOM_KINDREDは今の場合のような「図面種別の切り替えに伴うズーム倍率の変更」だからapplyオフでよい.ZOOM_RESETはVBのSetZoomRateで呼び出されるケースだが,これもオフでよいのではないかと思う.⇒これでこの問題は一応片付いたのではないかと思う.

しかし,今度はTRIBELIST::ShiftDirectAbsoluteでエラーが出るようになってしまった.先祖ノードのシフトを実行して,確定世代番号と人名枠の物理世代番号の不一致が起きている.下図は尾高磯五郎系列の「一部」を部分図としたもので,4系統に分離している.

image

関係の一部がカットされたために系列がバラバラになるのはやむを得ないというより,当然だが,出力がかなりおかしい.それぞれ独立系統なので先祖ノードが物理世代ゼロに配置されるのは当然だが,下流系との間にギャップが出来てしまっている.各カードに表示された確定世代番号を見ると,画面上の垂直位置と一致しているので,確定世代番号に従っていると言える.カード数は全76点だ.

GetHasseDiagramで距離数を確定世代番号に変換するところで失敗しているのだろう.系統ごとに基準点が異なるので一括して処理したのでは正しい値にならない.どうすればよいか?SIMPLEGRAPH:GetHasseDiagramの中で系統ごとに処理が閉じるようにしなくてはならないだろう.この修正は結構クリティカルなので,一度バックアップを取って最近の修正をフィックスしてから着手することにしよう.

  1. RetrieveGhostではCHAOTICSTATEまではノーマル処理する@20210301 1件
  2. CHAOTICSTATEまではつねにノーマル処理する@20210302 12箇所
  3. NOMULTICARDを廃止する@20210303 12箇所
  4. 仮修正 1箇所,暫定 2箇所,#if 0 4箇所

SIMPLENODEにはすでに使われなくなったdownwardとupwardという2つの変数があるのでこれらを廃止して,代わりにstrain(系統)という変数を導入することにする.⇒実装した.動作している.

image

渋沢一族の系列分解図は横幅が上限を超えてしまうため,「92.2%以上には拡大できない」が,その動作があまりよくない.ズーム倍率リストで100%以上を指定しても拡大されないが,警告も出ない上,画面が崩れる場合がある.倍率表示は100%,200%などになっている.ズームトグルボタンで100%に戻そうとすると初めてメッセージが出て92%に自動調整されるが,画面は左端に移動してしまう.ズームインボタンで拡大しようとしたときの動作はトグルボタンの場合と同じだ.⇒ズームリストツールを操作したときのコマンドが,ZOOM_RESETだ.

しかし,ズームトグルの場合のように自動調整は実行されず,メッセージも出ない.ざっと見た限りではトグルとリストツールで動作には差異がないように見える.どちらもTREEVIEW::Zoomを呼び出しているだけだ.VB側の動作もZView.Zelkova1.ZoomSetを実行した後,UpdateZoomRateしているだけだ.どこかで書き戻されているようだ.⇒これは結構難しい.ズーム倍率リストのSelectedIndexChangedイベントの中でテキストを書き換えても上書きされてしまう.ComboBoxではe.Cancelのような方法が使えない.

渋沢一族のクラスタ図が5つに分離している

開発機とVAIO2で並行して渋沢一族の完全木テストを実行していたのだが,開発機の方はスリープから立ち上がれずに電源の再投入になってしまったため結果は分からない.VAIO2の方は遅々として進んでおらず,まだ全体図をやっている.開発機はZT Acvanced,VAIO2はZT Basicだが,どちらも遅い.開発機ではREFERENCECONTROLを止めた状態で走らせているが,それでも一面当たり15秒くらい掛かっている.

リリース版でテストするということも考えられるが,現行ではSTOP文をほとんどDEBUG_NEVERマクロに置き換えているので,リリースモードでは細かいエラーはほとんど捕捉できないのではないかと思う.開発ステージ的にはすでに「致命的ではないエラーはすべて無視」という段階に入っているのかもしれないが…

▲VAIO2で実行中の渋沢一族の完全木テストで例外が発生している.

例外がスローされました: ‘System.ArgumentOutOfRangeException’ (System.Windows.Forms.dll の中)

親族図:すべてのカード 基準ノード=#759 佐藤菊子だ.エラーを無視して続行は可能.ZT Basicをリビルドしてテストしてみたが,再現できない.このエラーはVBで出しているものと思われが,スリープ中のアプリを起こしたときに何か画面上の操作が入ったのではないだろうか?

「RetrieveGhostではCHAOTICSTATEまではノーマル処理する@20210301」というオプションを拡張して,「CHAOTICSTATEまではつねにノーマル処理する」としてみよう.

渋沢一族で部分図(中の家)を選択してNAMEBOX:RestoreExtractBoxで停止した.PartialMapCommand実行後の系統並び替え→ EraseTreeViewで系列枠不在が発生している.NAMEBOXのデストラクタに入ってきた時点ですでに系列枠への参照を失っている.TREEVIEW::EraseTreeViewでは無差別に描画要素を削除しているので,NAMEBOXより先にTRIBEBOXが削除されているのだろう.⇒フェーズがCHAOTICSTATE以下では系列枠不在を無視するようにした.

▲渋沢一族は完全に連結だと思っていたが,GetHasseDiagramのダンプで見ると,5つの系統に分離している.①渋沢 栄一@1,②岡部 長景@191,③吉阪 俊蔵@770,④正田 建次郎@624,⑤末松 謙澄@793だ.本当にそうなっているのかどうか確認する必要がある.⇒一見した限りではすべてのノードはどこかしらで連結しているように見える.

ゼルコバの木には「系統」という概念ないしオブジェクトは存在しないので,「系統を色別表示」などのことは直ちにはできないが,始系列は色別表示できるのでそれを見れば判定できるだろう.明らかに始系列は1個しかない.つまり,系図図面は連結でなくてはならない.ということは,重婚クラスタ分解に穴があるということを意味する.

渋沢一族の系列分解図を取ろうとして,TRIBELIST::MakeUpTreeで停止した.非始系列で系列優先実ノードを持たない系列がある.⇒いや,これはノーマルな状態だ.系列分解図ではすべての系列が優先実ノードを持たない状態になっている.つまり,始系列と非始系列を区別する意味がない.MakeUpTreeにはこのようなブロックが複数あるのですべて停止した.また,TribeRelocationで実行される

EstablishMajorTribeChainも系列分解図では不用なのでパスするようにした.これでようやく系列分解図が出力できるようになった.渋沢一族8には系列が107個入っている.つまり,先祖ノードが少なくとも107人登録されている.上記5系統の代表ノードから先祖ノードを探すと,

  1. 渋沢 栄一@1 → 渋沢 市郎右衛門@20
  2. 岡部 長景@191 → 岩崎 彌次郎@343
  3. 吉阪 俊蔵@770 → 箕作 秋坪@387
  4. 正田 建次郎@624 → 正田 貞一郎@625
  5. 末松 謙澄@793 → 伊藤 助左衛門@661

とりあえず,これらの系列の部分図を作ってみよう.

▲系列分解図で栄一の系列を選択→新規部分図で部分図に切り替えようとして,TREEVIEW::CheckDispSizeOverのエラーになった.系図外枠が35025x1489になっている.上限は32000x32000なので明らかにオーバーしている.「この図面は 91.4% 以上には拡大できません.」という警告が出されている.しかし,部分図画面で100%に切り替えても特に問題は発生しない.500%まで拡大することもできる.どうも,部分図と全体図を取り違えているのではないだろうか?

渋沢市郎右衛門系列には165名収容されている.

▲岩崎彌次郎系列を選択して部分図に切り替えようとして,SIMPLEGRAPH::GetHasseDiagramで停止した.この関数を呼び出すときの引数seedが空になっている.tajugraph2の節点リストが空になっている.⇒エラーを無視して描画できたが,内容がかなりおかしい.

image

これは明らかに系列分解図としての出力だ.確かに現在の親族図の設定では「系列分解図」となっているが,それが部分図まで影響するというのは想定外だ.「特殊レイアウト」で「系列分解図」をオフにすれば図面は正常に戻るが,その代わり,全体図でも系列分解図オフとなり,図面が変化してしまう.全体図・親族図・部分図のそれぞれで図面モードを持つというのもかなり厄介だが,そうするしかないのではないだろうか?まぁ,これは後で考えることにしよう.

岩崎彌次郎系列を系列分解図で切り取るとき,矩形領域選択しているはずだが,余分なカードが付いて来てしまっている.栄一系列の先祖ノードの渋沢市郎右衛門だ.もう一度取り直ししてみよう.今度は渋沢市郎右衛門は含まれていない.シフトキーを押していればこのようなことも起こり得るかもしれないが…

岩崎彌次郎系列は23点だ.

image

箕作秋坪系列は43点.

image

正田貞一郎系列は12点.これには,正田建次郎の子ども3人は含まれていない.この三人は平山信系列の平山多美の預かりになっている.

image

伊藤助左衛門系列は25名収容だ.

image

これで5つの系列は取り終わった.後はこれらの接点を探すだけだ.いや,それは別に難しいことではない.全体図を系列分解すればすぐに分かる.たとえば,岩崎彌次郎系列の場合,系列分解図で彌次郎系列のすべてのカードを選択し,外部系列で選択状態になっているカードを見つければよい.岩崎弥太郎の娘岩崎磯路@347は木内重四郎系列に入っている.岩崎弥太郎の孫娘加藤悦子の配偶者岡部長景と弥太郎の弟弥之助の孫娘岩崎妙子の配偶者岡部長章はともに,岡部長発の孫だ.弥之助の孫の岩崎英二郎の配偶者北原篁子は北原白秋の三人の配偶者の一人佐藤菊子との間にできた子ども,などなど… しかし,これでは埒が明かないので,岡部長景の傍系親族図を取ってみよう.

image

岡部長景の傍系親族図は40点だ.これも部分図として登録しておこう.

EraseTreeView中,NAMEBOX::RestoreExtractBoxで停止した.(PHASE > INITIALIZING && !tywbox->IsExtractOrTooYoung()) という理由だ.tywboxのownerはすでに空になっている.⇒NAMEBOX::RestoreYoungWifeと同等の修正を入れた.

吉阪俊蔵の傍系親族図は37点

image

正田建次郎の傍系親族図は27点.

image

末松謙澄の傍系親族図は30点

image

渋沢栄一の傍系親族図も取っておこう.全239点だ.

image

岡部長景の傍系親族図と渋沢栄一の傍系親族図の接点が見つかった.尾高豊作@22だ.手順は以下の通り.

  1. 一覧表表示範囲を「系図画面上のカード」に設定
  2. 岡部長景の傍系親族図を部分図で開き,全選択する
  3. 渋沢栄一の傍系親族図を部分図で開く
  4. 一覧表をスクロールして選択状態になっているカードを見つける

吉阪俊蔵の傍系親族図と渋沢栄一の傍系親族図には接点はない.

▲カード選択の動作がおかしい.部分図で全選択状態のまま選択が落ちない.選択と非選択が反転しているように思われる.部分図に切り替えて全選択した場合の動作もおかしい…

正田建次郎の傍系親族図と栄一の傍系親族図にも接点はない.末松謙澄の傍系親族図も同様.

▲全体図で表示を更新すると選択が落ちてしまう.⇒「選択を反転」→「選択を反転」で選択状態を復元することはできる.

吉阪俊蔵の親族図と栄一の親族図には直接の接点はないが,下図のように他系列との接点は存在する.

image

吉阪俊蔵の親族図と正田建次郎の親族図には接点がある.共通カードとして,坪井正道@390,坪井信子@391,坪井直道@392がある.この三人は坪井誠太郎+平山百合の子で,平山と正田は正田建次郎+平山多美で繋がっている.吉阪俊蔵の配偶者箕作花子は箕作佳吉の娘,箕作佳吉の姉箕作直子の子が坪井誠太郎だ.また,吉阪俊蔵の子吉阪隆正は箕作佳吉の弟箕作元八の孫娘甲野富久子と結婚している.

image

伊藤博文の傍系親族図を部分図で開いて全選択→ 末松謙澄の傍系親族図を部分図→ 選択を反転でTREEVIEW::selectAllのエラーが出た.(!selectedcard || !selectedname)のとき,(topology->ActiveList->count)が起きている.

CHAOTICSTATEまではノーマル処理する

軟体動物3.zelを開き,①マキガイとニマイガイを合体,②カタツムリとイカとタコを合体させて,RetrieveGhostのエラー「すでに廃棄中のノード対」が発生する.もう少し簡単な手順があるかもしれないが,少なくともこの方法で確実に再現できる.障害はCOUPLING:TopologicalSort冒頭のEraseTreeViewで起きている.フェーズはCHAOTICSTATEに入っているので,エラーを無視してもよいのかもしれないが,どういうフローになっているのか調べておこう.

UNDOありでゴミ箱なしというエディションだ.カタツムリとタコのカード合併でこれらが保持するノード対がClearPairBoxでパージされる.その後,系統並び替え→EraseTreeViewですべての描画要素が削除され,NAMEBOX #357 カタツムリ(0)が削除されている.このとき,PAIRBOX #406:#376 カタツムリ(1)→#357(0)がRetrieveGhostの対象となる.PAIRBOX #406はClearPairBoxですでにRetrieveGhostで処理されている.RetrieveGhostではこのノード対にdisableのマークを付けた後,(PHASE<=CLEARTABLE)という理由でゼロ復帰している.

RetrieveGhostはかなり複雑で大きな処理なので不用な摩擦を避けるために離脱することにしているものと思われるが,削除しようとしているノード対を放置したまま復帰というのは明らかにまずい.ゼルコバの木では基本的に「混沌とした状態」というのを認めないというのが方針であり,目標でもあるので,できる限りのことは実行すべきであると思う.フェーズはINITIALIZED=CHAOTICSTATEにあるので,この段階では処理を省略できないとしてみよう.また,仮に離脱する場合でも少なくともPAIRBOXを破棄してから離脱すべきだろう.最初にPAIRBOXを破棄してから離脱するようにしてみよう.⇒これでエラーは解消した.

CHAOTICSTATEまではノーマル処理するとしてみよう.ここまでできると「完全にクリーンなシステム」までは後一歩というところに達する.RetrieveGhostというのはこの種の処理としては最大で,それがこなせるとなればほとんどの場合はクリアできると考えられるからだ.⇒問題なく動作した.CHAOTICSTATE=INITIALIZEDの前には,INITIALIZING→ INITIALSTATE→ GROUNDZEROしかない.

これらのフェーズはアプリ起動時と終了時にしか通過しない完全な「初期状態」ないし「初期化中フェーズ」と考えられるので,システム的な整合性が崩れるのはある程度までは避けられない.ゴミ箱を復活させてUNDOシステムとの整合性をチェックしておこう.⇒問題なさそうだ.かなりよい動きになってきたので,リリース版を作り直しておくことにする.⇒源氏物語全系譜6.1.ZELが完了した.実行環境は開発機,デバッグモード,エディションはZT BASIC.

image

ZT BASICで渋沢一族を開いてみた.描画までに8.1秒掛かっている.多重カードが2件ある.①#224 穂積万亀子と②#691 井上光貞だ.穂積万亀子は穂積八束+浅野総一郎の娘浅野松の子で,栄一の子星野 辰雄の妻だ.万亀子の2つのカードはとんでもなく離れている上,世代差もあるので,多重になるのも仕方ないという感じはするが,「重婚クラスタ循環」は発生していないので,不可避の多重という訳ではない.

井上光貞は桂太郎の孫で,井上三郎+千代子の子であり,北白川宮能久親王の孫の二荒明子の配偶者だ.井上光貞のカード2枚は比較的近接しているので消去できそうにも見えるのだが… リリース版(ZT ADVANCED)ではどちらも解決して,多重ゼロになっている.これが,ZT BASICとZT ADVANCEDの力の差と見てよいのではないだろうか?井上光貞の場合はこんな↓感じだ.

image

穂積万亀子の場合は左に伸びる親子連結線が限りなく長いので追い切れないが,連結線を選択できるようになればそれも改善されるだろう.

image

従って,ZT BASICに求められるのは,これ以上の機能向上ではなく,障害で停止しないような安全な運用が可能であることにあると言ってよいと思う.渋沢一族の完全木テストを試してみよう.⇒早速障害が出た.ただし,これは開発機ではなく,リリース版の障害だ.

image

渋沢一族8.zelをただ開いただけでは発生しない.デスクトップ上に反例サンプルが複数できている.これらを開くとエラーが起きる.

BUG21-03-01 21-37-57.ZELを開いて,結婚参照番号不整合というエラーが起きる.また,CARDLINK::CheckCardLinkでvsprintf_sのエラーも起きている.このエラーは「父母ページ数の調整」をダンプしようとして起きている.⇒最終的には描画まで進んだが,中身はごく一部を除いて完全にバラバラになってしまっている.反例サンプルは全部で9つある.これらがどのタイミングで生成されたのか分からないが,その手順が分からないとバグを追跡できない.リリース版と同じ構成でビルドし直すところから始めるしかない.

新規ファイルの状態から,渋沢一族8.zelを開こうとして,nodule:Connectでエラーが起きる.TRASHCAN::ReuseWasteでオブジェクトを再利用するために,nodl_floatしようとしているところだ.Connect関数は付け替えをするときに,そのスロットの先住者を上書きする動作になっているためエラーが起きている.昨日の修正でnodule:nodl_floatを書き直しているが,ミスっていた.

接続元がIsAliveのときはスロットを開けるようにしているが,そうでない場合には放置している.これは「死亡しているノードは仮想関数SLOTが使えない@20210111」という理由だが,ゴミ箱に入っているノードはDELETED == DEADになっているため処理されないことになる.DEFINETRASHCANの場合にはつねにスロットを空けるようにした.

渋沢一族は完全に連結だと思っていたが,GetHasseDiagramのダンプで見ると,5つの系統に分離している.①渋沢 栄一@1,②岡部 長景@191,③吉阪 俊蔵@770,④正田 建次郎@624,⑤末松 謙澄@793だ.本当にそうなっているのかどうか確認する必要がある.

渋沢一族をリリース版で開いたときの状況は多重カードの位置を確認することが目的だったので,基本的には系統並び替えその他のデータ操作は一切行っていないつもりなのだが,実際には障害が発生しているのだから,何かしらのデータ操作を行っていたと考えるしかない.何をやるとこのようなことが起こるのか?ともかく少し動かしてみよう.⇒いや,障害が発生していたのはリリース版ではなく開発機のZT BASICではなかったのか?リリース版では多重が発生していないから,ほとんど操作らしい操作をやった記憶がない.

しかし,開発機でデバッグ中には反例サンプルは生成されないのだから,机上に反例が残っているとしたら,アプリで生成されたと考えるしかないだろう.開発機上でリリースモードでテストしていたという可能性はないだろうか?完全木テストを開始しようとした時点で問題が起き始めたのだから,完全木テストをやってみればよいのではないか?上のような派手な障害なら必ず引っかかるはずだ.

参照番号200近くまで走らせたが,エラーは発生していない.当初のエラーの原因はおそらくnodl_floatの書き換えミスだったのではないかと思う.しかも,それを開発機上でリリースモードで走らせていたのだろう.開発実機のデバッグモードで渋沢一族の1面を描画するのに約8~10秒近く掛かっている.これでは一晩掛かっても終わらないのでVAIO2に移すことにした.VAIO2ではさらに遅く倍速1面で20秒くらい掛かっているが,仕方ない.やらせておくことにしよう.

開発実機で標準版をデバッグモードで走らせて,渋沢一族を開き,完全テストに入ったところでRestoreYoungWifeで停止した.(PHASE > INITIALIZING && !tywbox->IsExtractOrTooYoung())という理由だ.完全木テストに入る前に参照番号でテーブルの並び替えを実行している.その処理が完了した後の系統並び替えでエラーが起きている.

系統並び替え冒頭のEraseTreeViewを実行しているところで,NAMEBOXのデストラクタからRetrieveGhost→ RestoreYoungWifeの呼び出しが掛かっている.フェーズはCHAOTICSTATE = INITIALIZEDでINITIALIZINGよりも大きいために停止している.上記で「CHAOTICSTATEまではノーマル処理」としたためだ.

問題のTYW枠はMARGBOX #130718:+→#37005 井上博邦(0)でこの結婚枠のTOOYOUNGWIFE属性が落ちてしまっているという点だ.⇒NAMEBOX::Dispose→ clearmarchainでMARGBOX:ReleaseMargBox→ ResetTooYoungWifeが実行されている.つまり,この結婚枠のオーナーとともに殉死しているということだろう.⇒結婚枠のオーナーが空ないし削除処理中の場合は停止しないようにした.

ゼルコバの木普及版 Zelkova Tree Basic

ゼルコバの木の普及版として公開を予定しているZekova Tree Basic バージョンの実現可能性が高くなった.テクニカルな問題はほぼクリアできたような気がする.ZT BASIC はゼルコバの木標準版(Zelkova Tree Advanced)から以下の機能を外したものだ.

  1. ゴミ箱(リサイクルシステム)
  2. UNDO/REDO 機能
  3. 抽象グラフ検証系(重婚クラスタ検定,端点共有ノード対の循環検査)
  4. 完全参照リスト管理

記録ページやカード写真イメージなどは普及版でもサポートされる.一般の個人ユーザが作成する50~100人程度の比較的単純なツリー構造の系図であれば,上記のような高度の機能を用いなくても十分作成できるだろう.ゼルコバの木を使うと100人程度の系図なら一週間程度で完成してしまうし,一旦作成してしまうと大概のユーザはそこで飽きてしまうので,高価な専用ソフトを購入しても宝の持ち腐れになってしまう.ゼルコバの木普及版の予価は2千円くらいを予定しているが,このくらいなら捨てる気持ちで支出できるのではないだろうか?

データ保存機能を持たないビューアはこれまで通り無償配布してゆきたいが,そうなるとどのバージョンのビューアを公開するかという問題が出てくる.ZT Advancedのビューアが無償で使えるということになると,普及版(ZT Basic)で作成した系図を高機能版のビューアで見るという使い方ができるようになり,誰も標準版を買う人がいなくなってしまうのではないか?普及版でビューアを出すならもちろんそういう問題は発生しないが,それも少しせこいような気もする… 場合によっては,ビューアの配布もユーザ会会員限定とすることも考えられる…

普及版では「部分図」という機能も不用かもしれない.部分図を止めるにはVB側で関係するコマンドを「不能」状態にするだけでも済むが,「部分図機能」に関わるモジュールをブロックとして切り出しておくことはシステム構成上意味がある.普及版から余分な機能を削ぎ落とすとしたら,①ファイル:追加読み込み,②一覧表のインポート/エクスポート,③親族図:軸線図法,④親族図:純血統図,⑤テーマの選択/登録なども対象になる可能性はある.というか,③はグラフ検証系を使っているので,もともと普及版には含まれていないと思う.

ともかく,完成させないことには始まらない.

▲カード写真を削除したとき,系図画面が更新されていない

▲「7」キーで「HOME」キーを代用するときの問題

▲軟体動物3.zelを閉じて,ZTシステム構成図7.ZELを開こうとして,freeblock::_releaseall_で停止.軟体動物3.zelではカード合併などの操作を行っている.テストバージョンは,UNDOサポート,ゴミ箱未サポート.軟体動物3.zelを開いて,閉じるだけで再現する.nodule:operator deleteでPHASE≦CHAOTICSTATEの場合はすべて削除としてある程度処理できるようになったが,totalblockが10個まで減少したところで,「**mptr** が 0xDDDDDDDD」という例外が発生した.

▲軟体動物3.zelを使ってカード合併のテスト中,RetrieveGhostで「すでに廃棄中のノード対」というエラーが出た.UNDO/REDO中には発生しない.マキガイとニマイガイを合体し,カタツムリとイカとタコを合体させて,カード数全20枚のところ,17枚になっている.

ニマイガイとマキガイをカード合併した図

UNDOシステムを搭載していないZT BASIC版で源氏物語全系譜6.1.ZELの全体図を#235 常陸介の前の北の方で開き,浮舟の母の配偶者欄で「常陸介」→「7777常陸介」のように変更して「登録」すると,系統並び替え中TOPOLOGY::MakeActiveListでエラーが発生する.treeview->validcardとActiveList->countのカウントが一致していない.「7777常陸介」という新しいカードが生成されているので,有効なカード数は318から1増えて319になっているはずだが,ActiveList->countは318のままになっている.treeview->validcardはSetKinshipから得ているが,TOPOLOGY::validcardnumとも同期している.validcardnumはTOPOLOGY::HideNameboxでカウントされている.

ActiveListはTOPOLOGY::MakeActiveListで生成されているが,ここではPDB()->lookup->tableを使ってカードにアクセスしている.lookup->countが318のままになっている.CARDTABLE::makelinkでは以前はMakingLookUpを実行していたが,@2018-02-1に 廃止された.同様に廃止された箇所が2箇所ある.MakingLookUpはルックアップテーブルを1から作り直す関数で,カードテーブルへのリンクの挿入と削除に際しては実行される必要がある.UNDOBASE:UndoProcessとCommandEndではつねにMakingLookUpが実行される.

MakingLookUpでテーブルの作り直しをしているのなら,個別にメンテナンスするより,系統並び替えで一度だけ更新するというのが早いのではないか?そうすれば,1箇所だけで済むようになるはずだ.それでもよいとは思われるが,現状を追認して,CARDTABLEとMARGTABLEのmakelink,FAMILYTREE::callSendCardで復活させることにする.削除の場合も必要になると思われるが,CARDTABLE:deletelinkの末尾で実行しているdecmaxrecnでMakingLookUpを実行するようにしたら,却ってエラーが出るようになってしまった.

image

これはVB側で出しているエラーだ.UpdateMaxCardはステータスバーを更新するための関数で,Z.RecordCountとZ.ActiveCountを比較している.Z.ActiveCountはおそらくActiveListのカウントに対応するものと思われるが,更新されていないため319になっている.Z.RecordCountはmaxRecordCountで取得された値で,lookupテーブルのカウントが入っている.MakingLookUpを実行しないようにすると,エラーは発生しないが,ステータスバーのカード数は319/319のまま更新されていない.つまり,誤った数字が表示されている.

問題は2つある.①MakingLookUpの実行後,Z.RecordCountとZ.ActiveCountで不一致が生じる,②系統並び替えを実行してActiveCountが更新されてもUpdateMaxCardが実行されない(ステータスバーが更新されない)⇒lookupテーブルはActiveListや部分図リスト構築のために使われているので,系統並び替えで一度だけ更新するというのでよいのではないか?まず,この修正を入れてみたい.バックアップを取ってからやることにしよう.

同上サンプルで常陸介を含む十数点のカードを選択→ 常陸介を削除で被参照カウントの残留が発生した.参照カウントが4残留している.参照はすべてMARGBOX[22]で「所属系列の先祖ノード人名リンクへの参照」が入っている.常陸介を単独削除しても同様事象が発生する.CARDLINK::DisposeではTRIBEBOX::CleanSansyoで先祖ノードからの参照をクリーンアップしているはずなのだが… これらの結婚枠はおそらくなんらかの事情で系列移籍が実行されたものではないかと思われる.所属系列の先祖と結婚枠が保持する先祖リンクが一致しない.

MARGBOX::CheckMargBoxChangedでこのような先祖リンクは積極的に解除するようにした.また,TRIBEBOX::CheckTribeでは「結婚リンクの先祖不在」を無視するようにした.実際,大半の結婚枠の先祖リンクは空になっている.⇒「7777常陸介」のカードが追加されたとき,一覧表が更新されていない.やはり,「系統並び替えで一度だけ更新」というのはダメのようだ.コマンド実行に対応するVB側の動作は「コマンド処理」のスコープで実行されなくてはならない.系統並び替えはそれと非同期に実行されるものなので,タイミング的に遅れてしまう.

元の論理に戻して,CARDTABLE::deletelinkとMARGTABLE:deletelinkでそれぞれMakingLookUpを実行するようにした.「UpdateMaxCard 不正なカード数」エラーが発生する件に関しては,maxcount < Z.ActiveCount に付け加えて Z.mSpanTreeNode() = 0 を見るようにした.これでエラーは回避できるようになった.

カード合併時には記録ページのマージが実行される.UNDOをサポートしていないシステムでこの辺りがどのような動作になっているのかが気になるところだ.⇒UNDOがサポートされていないシステムでは削除されたオブジェクトが復活するということはあり得ないから,特に何の問題も起きないと考えられる.2021年2月27日 のログではUNDOの問題が起きているが,この版の素性が問題だ.

UNDOをテストしているのだから,UNDOは実装されていたはずだが,ゴミ箱は外してあったのではないだろうか?多分,DEFINEUNDOSYSTEMだけがオンになっていたはずだ.ゴミ箱がなくても基本的にUNDOは動作する.Shadow付きのオブジェクトは削除されないからだ.しかし,写真や記録ページのようなfreeblockオブジェクトは削除されているはずだ.だとすれば明らかにUNDO/REDOで不具合が起きても不思議はない.まず,反例を確保する必要がある.

逆にZT Basicでは写真や記録ページをサポートしないという仕様も考えられるのだが… それも少しわびしい気持ちがする…

DEFINEUNDOSYSTEMをオン,それ以外のZT BASICでサポートされない(ゴミ箱を含む)機能をすべてオフにした版で軟体動物3.zelの動作を見てみたが,やはりUNDO/REDOはできない.ゴミ箱がある場合には,freeblockオブジェクトはゴミ箱に残っているので,それを参照するオブジェクトが復活した場合にも問題なく動作するが,メモリから完全にパージされてしまえばそれもできなくなる.しかし,ゴミ箱に入っているオブジェクトはリサイクルに回る可能性があるから,運が悪ければ同じようなエラーが起きる可能性はあると考えなくてはならない.

従って,UNDOをサポートしている場合には,ゴミ箱のあるなしに関わらず,freeblockオブジェクトをパージしないようにする必要があると考えられる.ゴミ箱に入らない場合にはフロート状態のオブジェクトとしてNリングに連結されるはずだ.freeblockオブジェクトにはカード記録ページやカード写真イメージの他に,データベースの作業域その他に用いるバッファ類やタイトル情報などがある.

多分タイトル情報はUNDOの対象になっていないはずだから,保護しなくてはならないfreeblockオブジェクトはMM_NOTEPAGEとMM_CARDIMAGEだけではないかと思われる.まず,これらのオブジェクトをパージしないという仕掛けを作ってみよう.⇒うまく行ったようだ.下図は,ニマイガイとマキガイをカード合併した図だ.

image

ニマイガイの下にマキガイの類が混載状態になっている.記録ページも両方のページを合体したものになっている.この動作はゴミ箱のあるなしに関わりなく,どちらでも動作するものになっている.これで一昨日出ていたバグは解決しているのではないかと思う.ま,まずい.UNDO/REDOの動作は確認したつもりだが,UNDOで戻ろうとしてエラーになった.ニマイガイの方はUNDOで戻ると記録ページも復元されているが,マキガイの方は写真も記録も消えてしまう.オブジェクト本体は残っているので,その限りではUNDOにはなっているが…

image

ビットマップはやや難しいところがあるので,記録ページのRTFの方を追いかけてみよう.⇒CARDLINK.CARDBASE.bitmapinfoとnotepageは空になっている..cBitmapには値は残っているがパージされた状態になっている.まず,ゴミ箱付きのときの動作を確認してみよう.UNDOはうまく行ったが,REDOがおかしい.処理の途中でバックアップタイマーの割り込みが入って,作業域のためのメモリ要求が出されて記録ページが使われそうになっている.

このオブジェクトのsnumは131だが,NODULE.sizeが179603240というとんでもない数字になっている.その他の部分は概ねまともなので,どこかで書き込みが発生している可能性がある.というか,ここで例外が発生しているので,このアドレス自体すでにパージされている可能性がある.再起動して,バックアップタイマーを止め,ファイルをクローズしようとしてTRASHCAN::throwCanで停止した.

delete wasteで例外が発生している.NODULE.sizeは215179560という値になっている.このオブジェクトのsnumは232だ.⇒クリーンビルドで作り直したら動作するようになった.しかし,2回目のUNDOでまた引っかかった.freeblock::_delmem_でdelete mblockを実行しようとして例外が発生した.やはり,sizeに大きな数が書き込まれている.CARDBASEのデストラクタではcBitmapをdeleteし,bitmapinfoとnotepageをfreeblock::_delmem_している.

これでは写真や記録を復元することなどできないのではないだろうか?むしろ,これまで動いていたとすればその方が不思議という感じもする… 古いバージョンでは~CARDBASEでビットマップの破棄などをやっていなかったのではないだろうか?⇒~CARDBASEを無動作で抜けるようにして動作するようになった.

Mouse Without Bordersでファイルを別マシンにドラッグ&ドロップできる!

源氏物語全系譜6.1.ZELの全体図を#5 紫の上(若紫)で開いて,NAMEBOX::IsPossibleBTWLeftHand Sc=884 左手本人が不可視で停止した.障害ノードは #15496 明石中宮(1)で消去された仮ノード.ゼロ復帰しないとしたらどのような動作になるのか確認しておこう.⇒「右手配偶者カードリンク不一致」でゼロ復帰している.右手結婚枠はMARGBOX #1098:#1225 明石中宮(0)+#1277 今上(0)→#1234 春宮(0)で,左手本人と右手本人が同一というシチュエーションだ.「左手本人が不可視」の検査を検査ルーチンの末尾に置いてみよう.

同上サンプルを#235 常陸介の前の北の方で開いてTRIBEBOX:hasPhysicalConnectionで停止した.(primenod->bigamist != realnode)というエラーが起きている.障害が起きているのは系列枠:snum=1544 primetype=3:婚姻関係 senzo=#424 一院 @10で,優先仮ノードはNAMEBOX #1382 浮舟の母(0).優先実ノードはNAMEBOX #1732 常陸介(1)だ.浮舟の母(0)はBTW右手配偶者,常陸介(1)はBTW左手本人だが,primenod->bigamistには浮舟の母(1)が入っている.これはかなりおかしい.

確かにMARGBOX #1150:#1777 浮舟の母(1)+#1778 常陸介(2)→#1398 蔵人右近将監(0)というBTWは成立している.逆に常陸介(1)が左手本人となるBTWは見当たらない.いや,#1778 常陸介(2)が右手配偶者となるBTWは発生している.このとき,#1732 常陸介(1)は左手本人になっている.とすれば,間違っているのはむしろ浮舟の母(0)がBTW右手配偶者ということになるのではないだろうか?いや,このBTWも存在している.#1382 浮舟の母(0)が右手配偶者,#1777 浮舟の母(1)が左手本人だ.このときの右手枠はMARGBOX #1082:#1270 八宮(0)+#1382 浮舟の母(0)→#1291 浮舟(0)だ.

この結婚枠は後から,もう一度BTWになっている.どこかで解除されているのだろうか?浮舟の母(1)はMARGBOX #1150:#1777 浮舟の母(1)+#1778 常陸介(2)→#1398 蔵人右近将監(0)のときには右手本人になっている.つまり,浮舟の母(1)は左手本人だが,右手本人でもある.何が問題となっているのだろう?右手本人と左手本人は複数のBTWに関係し得るが,右手配偶者の関わるBTWは一つしかないと考えられる.実際,浮舟の母(0)が右手配偶者となる結婚は#1082:#1270 八宮(0)+#1382 浮舟の母(0)であり,常陸介とは直接関わりはない.

優先仮ノードの浮舟の母(0)は右手配偶者で一院系列,その左手本人である浮舟の母(1)は大臣(橋姫)系列で同時に右手本人,その右手配偶者の常陸介(2)の左手本人が優先実ノードの常陸介(1)で,所属系列は常陸介の前の北の方だ.浮舟の母(0)のbigamistつまり左手本人は浮舟の母(1),浮舟の母(1)の右手配偶者の常陸介(2)のbigamistが優先実ノードの常陸介(1)になる.系列接続種別は婚姻関係となっているが,現行ルールではこのようなルーズな接続を認めている.ただし,それを正当化するのは難しい.今の場合で言えば

  • 優先仮ノードがBTW右手配偶者で,その左手本人が優先実ノードでない場合でも,もし,その左手本人が同時に右手本人であるとすれば,
  • その右手配偶者の左手本人が系列優先実ノードであれば正当と言える

のような感じになる.右手配偶者が同時に左手本人ないし,右手本人となる場合はあるだろうか?右手配偶者は原則として消去されているはずであり,逆に左手本人ないし右手本人は可視でなくてはならないと考えられるから,右手配偶者・左手本人ないし右手配偶者・右手本人ということはあり得ないと考えてよいはずだ.従って,優先仮ノードが右手配偶者で,その左手本人が優先実ノードでない場合には,左手本人が同時に右手本人である可能性を考えるのは妥当であるように思われる.

優先仮ノードが右手配偶者で優先実ノードが右手配偶者というケースはあり得るだろうか?一般には優先仮ノードは不可視,優先実ノード可視がノーマルな状態と考えられるので,実ノードが右手配偶者となるケースは除外してよいように思われる.従って,上の例外規則を適用すればある程度まではカバーできるのではないかと思われる.多少ややこしいが,実装してみよう.⇒動作している.

▲上記サンプルの画面で浮舟の母のカード画面上の子ども氏名欄で浮舟をダブルクリックしてTOPOLOGY::MakeActiveListのエラーが出た.(treeview->validcard != ActiveList->count)というエラーだ.validcard=319に対し,ActiveList->count=318になっている.氏名欄のダブルクリックで系統並び替えが発生するというのもおかしい.⇒再現しないが,ダブルクリックで新規カードを発行した後,UNDOで戻ると同じエラーが出る.浮舟の母の配偶者氏名欄に「7777常陸介」というのが入っているので,どこかで誤操作した可能性がある.

確かに,浮舟の母の配偶者氏名欄を「7777常陸介」のように書き換えて「登録」すると似たような事象が起きる.この後,UNDOしても元の状態には戻らない.これはUNDOの不備に依るものと思われるが,カウント不一致と合わせて別の機会に調べることにする.⇒この操作を行った後,ファイルを一旦閉じてもう一度開こうとしてハングする.freeblock::_releaseall_で失敗しているようだ.これはUNDOの不良と関係あるように思われる.⇒この版(ZT BASIC)ではUNDOをサポートしていないのにUNDOボタンが作動するというのがそもそも問題だ.

源氏物語全系譜6.1.ZELの直系親族図を#3 桐壷の更衣で開いて,「無効カードの仮ノード取り出し」エラーが起きた.⇒TRIBEBOX:GetAlternativePrimeNodeで無効カードを弾いていない.⇒対処した.

同上Z木家系図を#5 紫の上(若紫)で開いて,出口検査のTRIBELIST::CheckTribeListで,TRIBEBOX::CheckTribeのエラーが発生した.結婚リンク無効/結婚リンクの先祖不在が発生している.10系列でこのようなエラーが発生している.⇒GetAlternativePrimeNodeで無効結婚リンクを弾いていない.⇒対処した.

源氏物語全系譜6.1.ZELの完全木テストが完了した.Basicエディションを開発機上でテストした.

image

この後は舞台をVAIO2に移してテストすることにする.Mouse Without BordersではLAN上の別のマシーンにドラッグ&ドロップでファイルをコピーできる.これはすごい!他のマシンのデスクトップ上にドラッグするとMouseWithoutBordersという名前のフォルダを作ってそこに放り込んでくれる.…残念ながら,フォルダごとコピーすることはできない.「ZELKOVA 2021-02-26-1 – Folder is not supported, zip it first!」ZIPで圧縮しないとダメだと言われてしまった.⇒それでも,ZIPして解凍の方がLAN上(WiFi)でファイル転送より速い.最近の修正をフィックスしておこう.

  1. 系列のSPOUSESENZO属性を廃止する@20210224 25箇所
  2. 仮修正 1箇所,#if 0 5箇所,#if 1 3箇所

上記の「7777常陸介」という問題を調べておこう.最初に「カード登録」で(treeview->validcard != ActiveList->count)のエラーが発生するが,その後のUNDOの問題を先に見ておこう.VB側ではZ.mUndoStatusの値を読み取ってそれを表示しているだけだ.mZelkova::mUndoStatusではCallGetUndoStatで状態を取り出している.⇒CallGetUndoStatでUNDO未サポートの場合は,引数のUNDOSTAT *undoの内容をゼロクリアして返すようにした.

以前,Ctrl+ZでUNDOが誤動作していたので,チェックしておこう.Ctrl+Zが押されると,CardUndoRedoが引数FALSEで呼び出される.Ctrl+Yが押されるとCardUndoRedoが引数TRUEで呼び出される.この関数では状態に関わりなくZ.mUndoRedoを呼び出しているが,状態を判定してから実行するように改めておこう.⇒対処した.併せて,UNDOSTATの定数を整備した.

▲上記サンプルでUNDO/REDOの操作を実行していて,freeblock:_delmem_で例外が発生した.freeblock *mblockの値がおかしい.REDOを実行中で,delete unode->addressで削除操作を実行しようとしたところだ.unode->addressに入っているオブジェクトは正常であるように見える.障害は~CARDLINK→ ~CARDBASEで起きている.記録ページを解放しようとしているところだ.

削除しようとしているカードは@176の常陸介でこの人名リンクのcardbase.notepageの内容がおかしいようだ.カード合併などもやっているので,その影響があるかもしれない.オリジナルのZELファイルでは常陸介の記録ページは白紙になっている.というか,UNDOシステムはゴミ箱が整備されていないと正しく動作しないのではないだろうか?カードの削除や追加などは一応動作しているようではあるが…

freeblockにはShadowというのがないのでストレートに削除されている可能性がある.この問題は別途調べることにしたいが,再現できるだろうか?以下の手順を試してみたが,再現できなかった.

  1. 浮舟の母の配偶者欄で7777常陸介を登録→ 7777常陸介の新規カード
  2. 浮舟の母の配偶者欄で7777常陸介→常陸介→登録→ 常陸介新規カード
  3. 常陸介の新規カードとオリジナルの常陸介をカード合併
  4. 常陸介と7777常陸介をカード合併
  5. UNDO→UNDO→UNDO→UNDO→REDO→…

7777常陸介というカードが発生した原因は数字キーの7をHOMEのつもりで押していたためだ.テキストボックスにフォーカスがない場合には「7」キーでHOMEキーを代用できるのだが… 間違い易いかもしれない… この辺りも少し調べる必要がある.(treeview->validcard != ActiveList->count)のエラーが起きるのはUNDOシステムを実装していない場合に限られるようだ.

VAIO2でZTシステム構成図7.ZELの完全木テストが完了している.

image

このサンプルは開発環境では7.1.ZELの名前になっているので,リネームしておこう.ZTシステム構成図7.ZELをVAIO2にコピーしてテスト開始したところ,早速エラーが出た.

▲ZTシステム構成図7.ZEL 親族図:すべてのカード 基準ノード=#11 extraslot2を開いて,TRIBEBOX::DecidePrimaryNodeで停止した.系列優先仮ノードが空になっている.