一覧表のインポートで白紙カードが発生

一覧表ファイルのインポートで白紙カードが発生してしまうという事象が起きている.原因はインポートに先立って新規ファイルをオープンしているためだ.コード上ではこのカードは直ちに削除されているが,削除カウントゼロの状態で実行されているため,実際には効いていない.カウントを立てて削除を実行すると,今度は基準ノードが空というエラーが発生してしまう.新規ファイルをオープンするとき,同時に新規カードを自動的に生成するというのは仕様であり,変更することはできない.ただし,部分図ではカードゼロという状態が認められている.部分図は既存カード(の一部)を登録するものなので,勝手に新規カードを作るという訳にはいかないからだ.

インポートの手順はDLLとVBの間で1レコードずつ受け渡しするというプロトコルになっており,まず,最初に「インポート開始」,最後に「インポート完了」という通知を送ることになっているので,DLL側では現在インポート中ということを認識することは可能だから,なんらかの対策を講じることはできるだろう.ただし,現行では開始通知が送られるのは新規ファイルをオープンしたあとになっているので,この時期を早める必要がある.現行では,インポート中であることを示すフラグを持っていない.LINKTABLE::ImportStartではImportFileNameにファイル名を格納しているだけだ.

部分図と同じ扱いにしたいので,CHARTTYPE:図面種別にDISP_IMPORTという定数を新設することにした.インポート完了時には,元の図面種別に戻すのではなく,全体図に切り替えるのがよいのではないか?図面種別というのは(実行時に切り替えることは可能だが)ファイルに固有の値であり,インポートファイルはその情報を持っていないのだから,全体図表示が正しいと思う.現行ではインポートしても図面種別は切り替わらないという動作になっている.

このバグはかなりクセが悪い.ようやく押さえ込んだと思ったが,こんどは参照番号2という新規カードが作られている.⇒FAMILYTREE:DeleteCardDataではカード削除でカード数ゼロとなった場合には自動的に新規カードを作るようになっている.⇒ようやく収まった.以下の修正が必要になった.

  1. FAMILYTREE::ChangeKindredでCHARTTYPEとkparm.CHARTTYPEを設定
  2. インポート時,FAMILYTREE::DeleteCardDataでカードゼロのとき新規カードを生成しない
  3. LINKTABLE::ImportStartでChangeKindred(DISP_IMPORT)を実行
  4. LINKTABLE::ImportEndでChangeKindred(DISP_ALLCARD)を実行
  5. LINKTABLE::ImportEndでテーブル先頭カードの参照番号を返す論理を変更し,PDB->lookupを見るようにした
  6. 外部関数UpdateCardBaseでインポート中は基準ノード空で停止しない
  7. FAMILYTREE::RestoreBaseCardでインポート中ないし部分図モードのときは,BaseLink空で停止しない
  8. COUPLING::OpenFamilyBaseでInitKeizuParmを実行しない→暫定
  9. OpenFamilyBaseの出口でインポート中はSetKeizuParmを実行しない→暫定
  10. COUPLING::InitializeHeaderでkparm.initializeを実行しない→暫定
  11. VBのImportTableFuncで,①SetKindred(DISP_IMPORT)を実行,②Z.mDeleteCardを実行する前にZ.DeleteTableとZ.DeleteCountを設定,③SetKindred(DISP_ALLCARD)を実行

上記修正のうち,暫定の付いている8, 9, 10の3修正はそれぞれ,InitKeizuParm,SetKeizuParm,kparm.initializeで対処するように変更する.項目1で新規カードを削除しているが,最初からカードを発行しない方がよい.また,LINKTABLE::ImportEndでデータ不整合があるときのパネルも出さないようにした.新設したGetLongestChainはほとんど仕上がっていると思っていたが,まだまだだ.その後の処理も悪い.GetLongestChainでは出口で各節点に割り当てられている「距離」を「世代番号」に変換して戻るようにした.世代番号は0から始まる通番だ.また,戻り値を先祖ノードから最長鎖の長さに変えた.

MakeAntiChainListには引数で先祖ノードと末裔ノードを渡していたが,これらを廃止して,GetLongestChainが返す最長鎖の長さを渡すようにした.MakeAntiChainListの戻り値はwidthでこれは反鎖リストの最大サイズを返している.つまり,GetLongestChainは与えられたADGの高さを,MakeAntiChainListはADGの幅を返すものになっている.⇒FindJikusenAncestorでは,MakeAntiChainListのループを抜けた後の処理を省いて直ちに復帰するようにした.FindJikusenAncestorの論理はもう少し肉付けしなくてはならないが,当面はこれだけで間に合う.これで動作は大分まともになったが,まだエラーが出ている.

AFTERCUTEDGE.ZELを血統軸線図で開いて,TOPOLOGY:FindJikusenAncestor→ DeleteIsolatedNodeで節点を削除しているとき,CleanSansyo→ TakeRemainSansyoでリスト末尾不一致エラーが発生する.⇒deleteで削除していたところを.NODELIST:deleteElementを使うようにして解決した.

BEFORESTAGE6.ZELを開いて,MakeAntiChainListが幅0を返してくる.GetLongestChainの戻り値もゼロだ.このサンプルはカード数9だが,基準カードの#1が孤立ノードになっている.孤立ノードは除去されるようになっているが,基準ノードだけは残すべきではないか?⇒GetLongestChainの引数の基準ノードが空になっている.⇒確かに現行論理ではそのようになるだろう.現行ではノードを直接登録するのではなく,枝を登録するときに付随して登録されるようになっている.つまり,枝を持たないノード,言い換えると親も子もいないノードは登録されない.FindJikusenAncestorの冒頭で事前登録するようにした.

どうも,jikusenというプロパティがどこかで落とされてしまっているようなのだが,なぜだろう?ソースコードの大規模修正が入って,砲撃を受けた市街地のような様相になっている.一度整理してから進めることにしよう.オプションは以下の2つだけだが,広大な領域が,#if 0で止めてある.これを整理すると大分見易くなるだろう.

  1. GetLongestChainを使う@20210205 1箇所
  2. インポートではCHARTYPEをDISP_IMPORTに切り替える@20210206 17箇所

Jikusenzu.cppだけで687行削除した.⇒細かい修正がかなり必要になったが,軸線グラフの最長鎖を求める部分に関してはほぼ完全と言える状態になった.ただし,軸線図はまだ正しく描画できていない.基準ノードと先祖ノード,末裔ノードを(暫定)確定できるようになったので,次の段階に進もう.下図で見るようにCARDLINKのレベルでは完全に軸線が通っているのだが,図面上の具体的なオブジェクトであるNAMEBOXとMARGBOXへの設定に手抜かりがあるように思われる.

image

どこかで軸線グラフの枝を完全に失っている.⇒系統並び替えのSETRELATIVEフェーズでRemoveDeadEndBranch「行き止まりノードの枝をグラフから削除」をやっていた.従来論理では先祖ノードと末裔ノードにロックが掛かっていたので,それでよかったのだが,現行では反鎖リストの生成に掛かる前にロックを解除しているため,すべての枝が削除されてしまう.このブロックは全面的に廃止でよい.

image

ここまで来れば軸線図はほぼ仕上がったも同然ではないだろうか?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA