So-net無料ブログ作成
検索選択

助十郎 Ver.0.2.1 リリース [Zaurus]

延々と自分用のメモにしかなっていないデバグの様子をアップしてきましたが、併設しているぐうたラボで、助十郎バージョン0.2.1をようやくリリースしました。

次の点を修正しました。

  • 1か月画面の今月のスケジュール表示内で期間スケジュールのタイトル表示位置がおかしいものがあったのを修正。
  • 1か月画面の今月のスケジュール表示内で期間スケジュールの期間を示すバーの表示位置を画面をより有効利用できる様に修正。
  • 1か月画面の翌月のスケジュール表示内と6か月画面でスケジュールのタイトル表示位置がおかしいものがあったのを修正。
  • 春分の日、秋分の日が正しく表示されない場合があったのを修正。
  • 期間スケジュールの色を変更
  • データリロード時、休日関連データも読み込む様に修正


最近、期間スケジュールを多用し始めたんですが、多数の期間スケジュールを登録すると、ちょっと使えないレベルな気がしたので、修正することにしました。もう2年ぶりなんですよね。いまさらですが、期間スケジュールの表示に関しては、かなりましになったと思います。後、独自データベースに切り替えてスケジュールの登録もできるようにしたいとは思ってるんですが、まあ、放置状態です・・。

この2年の間、スマートフォンは出てますが、PDAはもうまったく出てこないですね~。ネットブックは出てますが、あれでもでかすぎますし、電池の持ちからしてPDAとは違いますしね・・。Android搭載の端末がキャリアの縛りなし(というか個人的には公衆網はなくていいんですが・・)で出てくればうれしいんですが、日本のメーカーからはそれもないですかね・・。そろそろZaurusの電源スイッチの当たりが怪しくなってきているんで、代替の機種が欲しいんですけどねぇ・・・。

ちなみに、前回の記事で放置すると決めたバグですが、割と簡単に発生しますね・・。また出ました。と言う事で、どうしようかな〜。


1ヶ月画面での期間スケジュールの表示の修正 Part 6 [Zaurus]

前回の記事の修正でやっとリリースできると思ってリリース準備を進めていたんですが、使っているとまた不具合がでました・・・。もう、見なかった事にしようかと思いましたが、また、2年もほっとくとなると、気になって仕方がなくなりそうなので、一応追って行きます・・・。

ちなみに、不具合はこんな感じ。

sukejuro_bug6.png
ある公爵夫人の生涯購入・・・


わかりますでしょうか? って、見たらすぐに気がつくと思いますが、2段目で期間スケジュールのタイトルがかぶってしまっています。タイトルの重なりの検出に失敗してるんですかねぇ・・。「ある公爵夫人の生涯」が上に来ているので、その下の「〜購入」と言うスケジュールの方が先に位置が決まってしまっていると思われます。他のスケジュールと合わせてみると「ある公爵夫人の生涯」は表示場所が無くて、ここになってしまった感じがありますね・・。これ、解決できるんかな・・??

さて、期間スケジュールのタイトルの位置は、「skmonth.rb」の中の「SkMonth#getTitlePos」で決定しています。で、中を見て行くと重複がある場合は、さらに「SkMonth#makeTitlePosCandidates」に遷移して行く様です。ここでoverlapを見てますね。また、これの扱いが怪しそうです。とりあえず「SkMonth#makeTitlePosCandidates」の中身をいちいち見て行く事にします。

まず、冒頭です。

  # 初期化
  pos = PeriodTitlePos.new(info.event.description, false, info.level)
  pos.x = startFrame.x


まず、タイトルの表示位置(pos)を生成していますね。ちなみに、PeriodTitlePosの定義は下記の通りです。

 # 構造体
 PeriodTitlePos = Struct.new(:title, :conflict, :level, :x, :y, :titleWidth, :periodWidth)  # 期間スケジュールタイトル描画位置


で、その後、重複のチェックとやらをやってます。これ、何をやってるんでしょう?? if文の条件式の意味もわかりません。

  if (overlap[info.start] != 1) then
   pos.conflict = isConflict(info.start, info.level, overlap)   # 重複チェック
  end


まず、overlapって何でしょう? たどってみると、SkFixedPeriodDataの@overlapメンバの様です。各日付のスケジュールが入っているハッシュのようですが、それだとこの比較はおかしいですね・・・。「overlap[info.start].size != 1」とでもしたかったんでしょうか?

で、条件に当てはまるときに呼ばれているのが、こちら「SkMonth#isConflict」です。

 def isConflict(day, level, overlap)
  ret = false
  
  targetLevel = level + (((level % 3) == 1) ? 1 : (-1))	  # 重複対象レベル
  overlap[day].each { |item|
   if (item.level == targetLevel) then
    ret = true
    break
   end
  }
  
  return ret
 end


ちょっと、意味不明でしたが、今、注目しているデータと重複対象(段内で今見ているデータのレベルが1ならば2のデータ、レベルが2ならば1のデータ)になるデータのレベルを「targetLevel」と言う変数に落とし込んで、そういうデータがこの日の中に存在しているのかどうかを確認しているようですね。

となると、先ほどの条件文の中の式はどうなんでしょうね・・・? まず、このメソッドに来るデータは期間内のいずれかの日に他の期間スケジュールと重複があるデータです。で、各日付で重複があるかどうかを調べる必要があるのは今のデータ以外のデータが存在する日。ですね。だから、条件式の中の式は「overlap[info.start].size != 1」でよさそうです。取りあえず、それは修正。


次は、期間の2つ日目から最終日までをなめて行って、重複している箇所と重複の無い箇所のそれぞれを分割して行っている様です。

  # 期間の分類
  ret = Array.new
  cx = pos.x    # 現在の日付のフレーム座標
  week = 0    # 開始週からの週差
  (info.start + 1).upto(info.fin) { |n|
   wday = Time.mktime(@date.year, @date.month, n).wday
   if (wday == 0) then						# 新しい週に入った


・・・ん〜、ソースを眺めていたら、どうやらこの関数は以前に掲載した期間スケジュールのタイトルの位置に関するルールに従って、表示位置の候補を優先順位順に抽出してるだけですね。

で、呼び出し元の「SkMonth#getTitlePos」では、何も考えずに一番優先順位の高いものを選択しています。そもそも、ここには現在注目している一つの期間スケジュールのみが来ているので、他のデータとの比較、位置調整をしようと思ったらちょっと大事ですね・・・。ここ、バグと言うよりかは手抜きレアケースのための割り切り仕様と言ったところでしょうか・・。どうしましょうかねぇ・・・。


ん〜〜〜〜・・・、と悩みましたが、もうこれはこのままにしとくことにします。

助十郎のデータリロード時の休日データ読み込み [Zaurus]

前回、リリース作業に入るとか書きましたが、もう一点、データをリロードする際に休日データの読み込みを忘れていた点を修正しておきます。前々から気にはなっていたので、ついでです。

リロードの処理は「Sukejuro#procReloadSignal」で実行されています。ここから「SkData#reloadData」を呼び出していますね。一方、起動時は「SkData#initialize」で「SkHolidays.new」を呼び出しており、ここでメンバ変数「@holidays」に休日のデータを読み込んで完了となっています。

 @holidays = SkHolidays.new    # 祝日情報


一番簡単なのは、リロード実行時に呼び出される「SkData#reloadData」で初期化時と同様、「@holidays」へ新規に生成した「SkHolidays」のインスタンスを設定する事ですね。休日データのみをリロードできるようにしたい気もしますが、今回はこれだけにしときます。


以上。

助十郎のサイドスケジュールの修正 Part 3 [Zaurus]

内容が横道にそれまくっていますが、この記事で決着をつけたいですねぇ・・・。

今回、気になっている現象は次の様にスケジュールのタイトルが期間スケジュールの線でつぶされてしまっている現象です。

sukejuro_bug4.png
左に寄り過ぎ


ちなみに、これもバグじゃあないかと思っています。

sukejuro_bug5.png
やや右に寄り過ぎ


本来は、こうあるべきだと思います。

sukejuro_sample1.png
線にぴったり


スケジュールの表示位置を決める値は「skcompactmonth.rb」の「SkCompactMonth#getDisplayData」で設定されている様です。下記の様に決められていますね。

 level = periodData.overlap[period.start].size  # 線の数


単純に線の数で位置を決めていますが、今回の修正で線の位置が左に戻る事もあるため、ちゃんと各日付の最大levelを見る必要がありますね。って、これ、修正前でもこの決め方じゃあだめですね。と思って、過去の動作を見てみたら、やっぱりだめでした。あんまり気にしてなかっただけか・・。

と言う事で、ここで各日付の最大レベルを見る様にしましたが、概ねうまく言っている様に見えますが、完全にはうまくいっていません。よく見てみたら期間の開始日だけで判断していました。さらにこの関数をよく見てみましたが、なんか処理に無駄がありそうな気がします。この関数の処理を見直す事にしました。

今のSkCompactMonth#getDisplayDataの処理はおおざっぱに書いて、下記の様な感じです。

sukejuro_algo1.png
無駄とバグあり


無駄と感じているのは右側のループの中。「level決定」と「該当期間のlevel設定」です。また、これがバグの原因となっています。ここは各期間スケジュールについて、スケジュールタイトルの位置を決定するのが主目的ですが、ここでlevel設定もしているので、この期間のスケジュールは、重複しているスケジュールの回数分level設定されている事になります。ちなみに、動作上、同じlevelが何回も設定されていると思われます。

これをこんな感じに修正しようかと思います。

sukejuro_algo2.png
バグは消えるけど・・。


2回ループを回しているので、効率が良くなっているのかどうかわからないんですが、取りあえず、無駄はなくなったと思います。ついでにバグも無くなりました。

sukejuro_fix2.pngsukejuro_fix3.png
ぴったり!ぴったり!



と言う事で、今度こそリリースに移ります。

助十郎のサイドスケジュールの修正 Part 2 [Zaurus]

前回、予想外に「春分の日」「秋分の日」の設定内容が反映されない件についての修正ができました。ほんとは、一か月画面横にある翌月のスケジュール内の通常スケジュールの表示を修正したいんですが、前回の修正の後、また落ちる現象が出てきました。今度は、nilに対して、何か操作しようとしていると怒られています。

 ./skcompactmonth.rb:359: in `getDisplayData': undefined method `year' for nil:NilClass (NoMethodError)


ログを取ってみたところ、末尾に妙なデータがついてますね。2つ付いてたんですが、片方は終了日が無く、片方は開始日がありません。また、双方とも該当日は該当月から外れています。

・・・そういえば、そういうデータの存在も検討した様な記憶がありますね。どういう扱いにするんでしたっけ?? その前にデータを良く見てみたら、これらのデータはこの月にしか入っていない様です。また、開始日のみの方はその開始日が2007/8/22、終了日のみの方は終了日が2007/1/31。今月のデータを見ていたので、ここにこれらのデータが紛れ込んでるのが、そもそもおかしいですね。

この現象は、なんとなく今回触ったところとは何の関係もなさそうな気がします。助十郎の期間スケジュール表示の修正 Part 3でちらっと書きましたが、今は現在の最新ソース(ローカルでいろいろ触ってたソース)に対して、バグ修正を施して行ってるんですが、この最新ソースは何か機能追加をしようとした痕跡があるんですよね。って、私がしようとしてしたんですが、記憶に全くありません。ファイルのタイムスタンプを見たら、2年前くらいに何かしようとしてた様です。で、たぶん途中で飽きてほったらかしたと言う感じですね。ど〜しようかなぁ。

・・・と考えましたが、せっかく書き足したコードを消すのももったいないですし、今更古いソースとの差分を見ながら差分を当て直すのも面倒なので、このまま最新ソースを修正して行く事にします。ただし、追加していた機能は抑制する方向で修正して行きます。収拾が付かなくなりそうなので・・・(というか、たぶん収拾がつかなくなって放置した様な気もする)。と言う事で、今後の記事(とこれより前の記事)に転記しているソースは、既に配布しているソースとは中身が異なってる可能性もありますので、ご了承願います(って、たぶん見てる人はいないと思いますが・・)。

さて、最新ソースを見ていると「skdata.rb」の中身がかなりいじられています。今回、関係ありそうなのはこのファイル内の「SkData#getScheduleOfTheMonth」なのですが、ここに影響してそうな追加があったので、それをコメントアウトしてみました。


で、落ちなくなりました。横道にそれまくりですが、直ったので、次から本題の修正に入ります。

つづく。



助十郎のサイドスケジュールの修正 [Zaurus]

前回の修正でリリースしようと思ったんですが、実は1か月画面横に表示されている翌月のスケジュール(このパーツは6か月画面でも使用されています)の通常スケジュールの表示もおかしい点があったので、ついでに直そうかと言う気になりました。で、データを取ろうと思って動作させていたところ・・、落ちてしまいました。エラーメッセージは下記の通りです。次々にバグが出ますねぇ・・・。

./skcompactmonth.rb:301:in `drawData': undefined method `-' for "20":String (NoMethodError)


該当箇所は「skcompactmonth.rb」に定義されている「SkCompactMonth#drawData」の中。下記の様になっています。

 y = @topMargin + @frameHeight * (title.day - 1) + 1


「title.day」がInteger型である事が想定されているのに、String型になっている様ですね・・。このtitleを設定しているのは、「SkCompactMonth#getDisplayData」の様です。titleに設定されているデータの型は下記の通りに定義されています。

 SkCmonthData = Struct.new(:day, :level, :title, :holiday, :period)


各要素は順に「日にち、タイトルの左マージン、タイトル、休日フラグ、期間データフラグ」となっています。

さて、「SkCompactMonth#getDisplayData」の中身を見ていると、処理としては「該当月のスケジュールデータの取得」→「通常データと期間データの振り分け」→「通常データのタイトル設定」→「休日データの設定」→「期間データの設定」と言う感じで進んでいます。

「通常データのタイトル設定」の所のソースは下記の様な感じです。

 dayEvent.each { |event|
  if (titles[event.start.day] == nil) then
   title = SkCmonthData.new(event.start.day, 0, event.description, false)
   titles[event.start.day] = title   # タイトル設定
  end
 }


「event.start.day」は普通に読み込んできた値が入っているので、String型に変わる場合が良くわかりません。ちなみに、先ほどのエラーは毎回出ている訳ではなく、今回操作していたら突然発生したものですので、全データがそうなっている訳ではなく、特定のデータがそうなっていた様です。

コードを見てもわからないので、ログを仕込んで動かす事にします。デバッガが無いので面倒です・・。

*
ターミナルで日本語が化け化けです。以前、設定した様な気がするんですけどねぇ・・。と言う事で、どのスケジュールが問題を引き起こしているのかは、わからないんですが、問題が出ている日付に通常スケジュールが存在していません。仕方が無いので、ログをファイルに落として確認したところ、「春分の日」が入ってました・・・。なんで、春分の日??

他の月のデータも見てみたら、祝日は入っています。祝日が入る事自体は問題ない様ですね。で、他の月の祝日のデータは問題が発生していないので、問題は「春分の日」にあるんだと思われます。実は、「春分の日」と「秋分の日」はその年によって日が異なるため、別の設定ファイルを読み込んで日を決定しています。

そういえば、今年の春分の日はそのファイルの設定が反映されてなかったですね・・。「あ〜、なんかずれてるなぁ。」と思いつつ、放置していました。でも以前は反映はされないものの特に落ちる事はなかったんですが、なんで今回は落ちる様になったのかが良くわかりません。

その春分の日のデータを読み込んでいるところは、「skholidays.rb」内の「SkHolidays#readDataFile」です。

 def readDateFile(fname, year)
  # ファイルには各行に年度と日にちがスペースで区切られた状態で記載されている
  day = nil
  
  # 該当年度の日付読み込み
  File.open(fname, 'r') { |file|
   file.each_line { |line|
    dayInfo = line.split(' ')
    if (dayInfo[0].to_i == year) then
     day = dayInfo
     break
    end
   }
  }
  
  # 戻り値設定
  if (day == nil) then
   ret = nil
  else
   ret = day[1]
  end
  
  return ret
 end


下の方の「戻り値設定」の所で、day[1]をIntegerに変換するのを忘れてますね・・。上の方でyearと比較しているところはちゃんとIntegerに変換してるのに・・。

   ret = day[1].to_i


戻り値を Integer に変換する事により、問題はなくなりました。

これから、気になっていたスケジュールの表示の修正に入ります。って、またなんか出そうで嫌ですねぇ。適当に作ったんで仕方が無いと言えば、仕方が無いですが・・。今、直して行ってるのも、かなり適当ですが・・・。

・・・と書いているうちに、また落ちました。今度はなんだ??

つづく・・・。

助十郎の通常スケジュール表示の修正 [Zaurus]

前回の記事で期間スケジュールの配置は修正できましたが、実行してみると、通常スケジュールの配置に変な現象が出てしまいました。

sukejuro_bug3.png
期間スケジュールの線と重なってしまった・・


モザイクをかけてしまってるのでわかりにくいかもしれませんが、期間スケジュールの線の部分に通常スケジュールがかぶさってしまっています。

通常スケジュールの描画は「skmonth.rb」の「SkMonth#drawSchedule」で行われていました。描画位置の決定はこの辺りですね。

   # 単発スケジュール描画
   painter.setFont(QFont.new('lcfont', FONT_SIZE_DAY))   # ペインタ準備
   dayEvent.each { |event|    
    # 描画位置決定
    frame = getFramePosition(event.start.day)
    if (counter[event.start.day] == nil) then
     counter[event.start.day] = 1
    else
     counter[event.start.day] += 1
    end    


「counter[]」という変数が鍵の様ですが、この変数には各日付の一番下にあるスケジュールの位置を格納しようとしている様です。当初はスケジュールの個数にしようとしてたんですかね。現在、名前と内容が異なってますね・・・。

同じ関数内の下記の場所で「counter[]」を設定しています。

  periodData.overlap.each { |day, overlap|  # counter更新
   counter[day] = overlap.last.level / 3 + 1
  }


ここがまずいですね。「preodData」は前回のエントリで見ていたSkFixedPeriodData型のインスタンスです。ここから、各日付に設定されているスケジュールをひっぱってきていますが、これも前回同様「overlap.last」しか見ていません。最後の要素が一番下に来ていると言う前提ですね。前回の修正で、期間スケジュールの表示位置は、上にスペースが空いている場合、上に移動させる様にしたので、最後の要素が一番下とは限りません。一番下の位置をちゃんと探さないとだめですね。と言う事は、潜在してたんじゃなくて、修正したために出て来たデグレですね・・・。

ここで、全部チェックする様に変更するか、期間スケジュールの配置を決める際に修正前と同じ様に最後の要素が一番下である事を保証する様に変更するか、どっちがいいですかねぇ・・。

前者の場合は、各日付の counter を設定する際に、その日付の最下位のスケジュールの位置を判定する事になりますね。後者の場合、全ての期間スケジュールの位置が決まってから、overlap の各要素をソートをするのが効率良さそうですが、そうすると、overlap の中身は常にソートされているとは限らないと言う事になりますね。仕様的には overlap の各要素は順不同と言う事になってしまいます。

前者も後者も処理を行う位置と処理量にはそれほど差がある様に思えませんが、後者の場合は仕様的にいまいちな感じがする(順不同なのにここではソートされている前提で処理している)ので、前者でいく事にします。overlap の中身は順不同と言うのが仕様ですね。

と言う事で、上記の処理内容を下記の様に変えます。ループに渡される要素「overlap」は何となくややこしい気がしたので、「info」に変えました(それでも、余り妥当でないかも・・)。

  periodData.overlap.each { |day, info| # counter更新
   largestLevel = info.max { |a, b|
        a.level <=> b.level
       }
   counter[day] = largestLevel.level / 3 + 1
  }



以上で、取りあえず今気にしているところは直ったので、リリース作業にうつろうかと思います。

助十郎の期間スケジュール表示の修正 Part 5 〜重複判定修正編 [Zaurus]

まず、今回解析する部分('skfixedperioddata.rb' - SkFixedPeriodData#addSchedule内)のソースを載せておきます。

  # 重複レベルの設定
  # 重複は重複なし、重複上段、重複下段で表し、
  # info.level は0, 3, 6 が段内で重複なしになる
  info.start.upto(info.fin) { |day|
   if (@overlap[day] == nil) then              # 重複なし
    @overlap[day] = Array.new
    @overlap[day].push(info)
   elsif ((info.level == 0) 
       && (info.level <= @overlap[day].last.level)) then # 重複あり(チェック未)
    # 既存レベル更新
    level = @overlap[day].size            # 該当日の重複レベル
    if (((level % 2) == 1) 
        && ((@overlap[day].last.level % 3) == 0)) then # 重複なしデータあり
     @overlap[day].last.level += 1
    end
    
    # レベル決定
    if (((level % 2) == 1) 
         && ((@overlap[day].last.level % 3) == 2)) then # 重複データが下側
     info.level = @overlap[day].last.level - 1
    else
     info.level = @overlap[day].last.level + 1
    end
    
    @overlap[day].push(info)
   else                            # 重複あり(チェック済)
    @overlap[day].push(info)
   end
  }


ちなみに、気にしている箇所の現象は、こんな感じです。

sukejuro_bug2.png
右端に注目!


わかりますでしょうか? この「東京国際ブックフェア」は「歯医者」の日にはまだ終了していません。Part 4の記事の5番目のスケジュールにあたります。この「歯医者」の日の前日から2つのスケジュールが開始されているんですが、その線(ピンクと緑)が「東京国際ブックフェア」とかぶってしまっています。本来なら「東京国際ブックフェア」とピンクの線がペアになり、緑の線はもう一段下になるべきです。ちなみに、この「東京国際ブックフェア」のある位置は3段目です。

この期間、1段目は既にスケジュールがないため、「東京国際ブックフェア」とピンクの線が1段目、緑の線が単独で3段目に来るのが理想的だと思います。これも考慮に入れつつ、解析して行きます。

まずはこのループ。注目しているスケジュール「info」の期間内の他のスケジュールの状況を見つつ「info.level」を決定している様です。重複をチェックするために使用されているのが「@overlap[]」変数。これは、各日付に存在するスケジュールが格納されているハッシュの様ですね。

「重複なし」の処理は問題無さげです。「重複あり(チェック未)」って、何がチェック未なのかわかりませんが、ここの処理、「@overlap[]」のサイズと最後の要素しか見てないし、その要素以外は更新してませんね。これが原因な気がします。

このif文、最初に「info.level == 0」を評価しています。「チェック未」の意味はまだ重複が検出されていないスケジュールと言う意味ですね。コメント変えとこ・・。それはさておき、「@overlap[]」の最後の要素しか見ていないと言うことで、おそらく、「東京国際ブックフェア」の要素は重なっているピンクと緑のスケジュールの重複をチェックする際は「@overlap[]」の最後の要素ではないんですかね? と思ったけど、そんなパターンあり得るんかな?

これ、「info.level == 0」の時しか重複のチェックをしてないですね・・。ピンクと緑のスケジュールの位置が決まった後に「東京国際ブックフェア」の位置を決めようとしてるけど、その初日で「info.level == 6」と決まったので、次の日からのピンク(info.level == 7)と緑(info.level == 8)のスケジュールとの重複を見てないと言うパターンの様な気がします。だから、ちゃんと処理してたら、ピンクと緑はそのままで、「東京国際ブックフェア」が4段目(info.level == 9)になるべきと言う感じですかね。誤りは「info.level == 0」の時しかチェックしていないと言う点ですね。

さて、どうすれば、誤判定をなくせるかな〜と、考えようかと思いましたが、このループを見てたら、何となく誤判定の解消だけでなく、理想の配置にも持って行けそうな気がします。実現するには、

「期間中、空いている最小のレベルを選択」→「同段内のスケジュールの位置調整」の2段階で処理する必要がありますね。

  # 重複レベルの設定
  # 重複は重複なし、重複上段、重複下段で表し、
  # info.level は0, 3, 6 が段内で重複なしになる
  counter = Array.new(1)   # 空きレベルサーチ用
  info.start.upto(info.fin) { |day|
   if (@overlap[day] == nil) then
    @overlap[day] = Array.new
   else
    @overlap[day].each { |data|
     counter[data.level] = 1
     if ((data.level % 3) != 0) then
      counter[data.level - (data.level % 3)] = 1
     end
    }
   end
   @overlap[day].push(info)
  }
  
  info.level = counter.index(nil)
  if (info.level == nil) then
   info.level = counter.size
  end
  
  if ((info.level % 3) == 1) then
   # 期間内に (level % 3) == 0 のスケジュールがあれば、2の位置に移動させる
   searchLevel = info.level - 1
   info.start.upto(info.fin) { |day|
    @overlap[day].each { |data|
     if (data.level == searchLevel) then
      data.level += 2
     end
    }
   }
  end


ベタに期間をなめて空き領域を探す方法をとってみました。重複レベルを探索した後に、各段の level0 のスケジュールを移動させてるのは大丈夫か?と思いましたが、0のスケジュールは元々重複が無いので大丈夫ですね。重なりが多い時にちょっとループが多くなりそうですが・・・。ま、一応直りました。


sukejuro_fix1.png
2段までに収まりました


さ〜、これでリリースしようかなぁ・・・、と思ったら、また変な現象が出てます。これは今回の修正のせいではなく、元々潜んでた現象の様ですね・・・。


と言う事で、つづく。

助十郎の期間スケジュール表示の修正 Part 4 〜重複判定解析編 [Zaurus]

前回の記事でタイトル表示については何となく直ったので、次は重複の誤判定について、解析して行きます。

状況整理の記事で整理したスケジュールの状況を再度掲載します。

1234567891011121314151617
1
2
3
4
5
6
7


このうち、1、2のスケジュールが1段目、3、4のスケジュールが2段目、5、6、7のスケジュールが3段目に表示されています。5、6が重複スケジュールとして、3段目に表示されるべきだと思われるのに、5が重複なしのスケジュールとして3段目に表示され、さらに6、7のスケジュールが重複スケジュールとして同じく3段目に重ねて表示されているので、おかしな表示になっています。

ちょっと、状況を見ただけでは、なんで、こうなっているのかは良くわかりませんね。ソースを見て行くことにします。また、「skmonth.rb」です。

期間スケジュールの位置を決めている変数は例えば「SkMonth#drawPeriodLine」を見てみると、「info.level」と言う変数の様です。これは記憶では重複するスケジュールがあるたびにプラス1して、0〜2だと1段目に表示、3〜5だと2段目に表示・・・・、と言う風な処理をしようとしてたと思います。これのカウントアップの状況を見ればいいですかね。

と思って、ちょっと見てみたんですが、かなりデータ構造もアルゴリズムもごちゃごちゃしてますね・・・。仕方が無いので、整理しながら追ってみます。

「SkMonth#drawPeriodLine」に渡されている「info」は、「SkMonth#drawPeriodSchedule」内の「periodData.data(これはArray)」の各要素となっていますね。で、この「periodData」は「SkMonth#drawSchedule」内で「SkFixedPeriodData」型のインスタンスとして生成されています。

さて、「SkFixedPeriodData」クラスですが、「skfixedperioddata.rb」で定義されています。名前が妥当かどうかちょっと微妙な気もしますが、期間スケジュールの調整用のクラスの様です。

期間スケジュールデータは、「SkMonth#drawSchedule」内で、「SkMonth#drawPeriodLine」が呼び出される前に、「periodData.addSchedule」メソッドに渡されています。この「periodData.addSchedule」メソッドの中で「FixedPeriodInfo」型のインスタンスが生成されていますが、このインスタンスが最初に出てきた「SkMonth#drawPeriodLine」メソッドの「info.level」と言う変数の実体の様です。この「info.level」は、このメソッド内で他のスケジュールとの重複をチェックして決定されています。

「FixedPeriodInfo」は、「sktools.rb」に下記の通りに定義されています。

FixedPeriodInfo = Struct.new(:event, :level, :start, :fin)


この「SkFixedPeriodData#addSchedule」で行われている重複のチェック処理にバグがあるんでしょうね。ついでに、Part 2のところで言ってた理想の表示についても、ここの処理を修正することで、実現できそうな気がします。何となく、ワクワクしてきましたねっ! と言うか、予想が外れてたらかなり萎えるんですけどね・・。その前に、ソースを提示しないと、ここで何を書いているんか全くわからないですね。まあ、次回提示します。


と言うことで、つづく。

助十郎の期間スケジュール表示の修正 Part 3 〜タイトル表示位置は直った編 [Zaurus]

さて、再び「skmonth.rb」を見て行きます。

とりあえず前回の記事であげた問題の一つ目「タイトルの位置が変」と言うのを見て行きます。タイトル表示位置のうち、横方向の位置は特に問題なさそうです。縦方向の位置の部分の計算が間違えている様なので、そこに焦点を当ててみて行きます。

この一連の記事の最初の記事で見ていた「SkMonth#getTitlePos」の中を見ていると、「重複なし」の場合はこの関数で縦方向の位置を決めていますが、「重複あり」の場合はさらに「SkMonth#makeTitlePosCandidates」を呼び出して、そこで位置を決めているみたいです。ちなみにその結果を「candidates」変数に反映させている様ですが、下記の様な反映のさせ方をしています。・・・なんか意味があるんでしょうか? 後で見とこうと思います。

candidates += makeTitlePosCandidates(info, overlap, startFrame, finFrame, titleWidth)


さて、縦位置を決めるところを見ていると、「SkMonth#getTitlePos」と「SkMonth#makeTitlePosCandidates」で差分がありました・・。

「SkMonth#getTitlePos」の方は・・、

pos.y = startFrame.y + @frameHeight * n + (1 + info.level / 3) * FONT_SIZE_DAY + FRAME_TOP_MARGIN


一方、「SkMonth#makeTitlePosCandidates」の方は・・・、

pos.y = startFrame.y + @frameHeight * week + FONT_SIZE_DAY + FRAME_TOP_MARGIN


後者の方、FONT_SIZE_DAYに(1 + info.level / 3)をかけていませんね。これで、段数の反映ができていないだけの様な気がします。3カ所ありますが、全てに差分修正を反映して、実行してみると・・・。

直りました。う〜ん、ちゃんとソースを見てませんが、現象が直ったので、結果オーライとして、これはこれで完了にしときます。だめなデバグのパターンですね・・。

ちなみに、最新ソースの方を修正して試したんですが、表示結果を見てみると、なんか期間スケジュールの色が変わっている上に、ツールボタンが追加されている・・・。全然覚えてませんが、これ、どうしようかな・・・。

それはさておき、次は問題の2つ目「重複があるのに重複なしと判断されているスケジュールがある」についても見とこうと思います。


つづく。

ブログを作る(無料) powered by So-netブログ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。