2 * daily period in village
\r
4 * Copyright(c) 2008 olyutorskii
\r
5 * $Id: Period.java 1028 2010-05-13 10:15:11Z olyutorskii $
\r
8 package jp.sourceforge.jindolf;
\r
10 import java.io.IOException;
\r
11 import java.util.Collections;
\r
12 import java.util.HashMap;
\r
13 import java.util.HashSet;
\r
14 import java.util.LinkedList;
\r
15 import java.util.List;
\r
16 import java.util.Map;
\r
17 import java.util.Set;
\r
18 import jp.sourceforge.jindolf.corelib.EventFamily;
\r
19 import jp.sourceforge.jindolf.corelib.GameRole;
\r
20 import jp.sourceforge.jindolf.corelib.LandDef;
\r
21 import jp.sourceforge.jindolf.corelib.PeriodType;
\r
22 import jp.sourceforge.jindolf.corelib.SysEventType;
\r
23 import jp.sourceforge.jindolf.corelib.TalkType;
\r
24 import jp.sourceforge.jindolf.corelib.Team;
\r
25 import jp.sourceforge.jindolf.corelib.VillageState;
\r
26 import jp.sourceforge.jindolf.parser.DecodedContent;
\r
27 import jp.sourceforge.jindolf.parser.EntityConverter;
\r
28 import jp.sourceforge.jindolf.parser.HtmlAdapter;
\r
29 import jp.sourceforge.jindolf.parser.HtmlParseException;
\r
30 import jp.sourceforge.jindolf.parser.HtmlParser;
\r
31 import jp.sourceforge.jindolf.parser.PageType;
\r
32 import jp.sourceforge.jindolf.parser.SeqRange;
\r
36 * 村の進行の一区切り。プロローグやエピローグも含まれる。
\r
38 * 将来、24時間更新でなくなる可能性の考慮が必要。
\r
40 * 24時間以上の期間を持つPeriodが生成される可能性の考慮が必要。
\r
42 public class Period{
\r
43 // TODO Comparable も implement する?
\r
45 private static final HtmlParser PARSER = new HtmlParser();
\r
46 private static final PeriodHandler HANDLER =
\r
47 new PeriodHandler();
\r
50 PARSER.setBasicHandler (HANDLER);
\r
51 PARSER.setSysEventHandler(HANDLER);
\r
52 PARSER.setTalkHandler (HANDLER);
\r
56 * Periodを更新する。Topicのリストが更新される。
\r
58 * @param force trueなら強制再読み込み。
\r
59 * falseならまだ読み込んで無い時のみ読み込み。
\r
60 * @throws IOException ネットワーク入力エラー
\r
62 public static void parsePeriod(Period period, boolean force)
\r
64 if( ! force && period.hasLoaded() ) return;
\r
66 Village village = period.getVillage();
\r
67 Land land = village.getParentLand();
\r
68 ServerAccess server = land.getServerAccess();
\r
70 if(village.getState() != VillageState.PROGRESS){
\r
71 period.isFullOpen = true;
\r
72 }else if(period.getType() != PeriodType.PROGRESS){
\r
73 period.isFullOpen = true;
\r
75 period.isFullOpen = false;
\r
78 HtmlSequence html = server.getHTMLPeriod(period);
\r
80 period.topicList.clear();
\r
82 boolean wasHot = period.isHot();
\r
84 HANDLER.setPeriod(period);
\r
85 DecodedContent content = html.getContent();
\r
87 PARSER.parseAutomatic(content);
\r
88 }catch(HtmlParseException e){
\r
89 Jindolf.logger().warn("発言抽出に失敗", e);
\r
92 if(wasHot && ! period.isHot() ){
\r
93 parsePeriod(period, true);
\r
100 private final Village homeVillage;
\r
101 private final PeriodType periodType;
\r
102 private final int day;
\r
103 private int limitHour;
\r
104 private int limitMinute;
\r
105 // TODO 更新月日も入れるべきか。
\r
106 private String loginName;
\r
107 private boolean isFullOpen = false;
\r
109 private final List<Topic> topicList = new LinkedList<Topic>();
\r
110 private final List<Topic> unmodList =
\r
111 Collections.unmodifiableList(this.topicList);
\r
114 * この Period が進行中の村の最新日で、
\r
115 * 今まさに次々と発言が蓄積されているときは
\r
117 * ※重要: Hot な Period は meslog クエリーを使ってダウンロードできない。
\r
119 private boolean isHot;
\r
123 * この段階では発言データのロードは行われない。
\r
125 * @param homeVillage 所属するVillage
\r
126 * @param periodType Period種別
\r
127 * @param day Period通番
\r
128 * @throws java.lang.NullPointerException 引数にnullが渡された場合。
\r
130 public Period(Village homeVillage,
\r
131 PeriodType periodType,
\r
133 throws NullPointerException{
\r
134 this(homeVillage, periodType, day, false);
\r
140 * この段階では発言データのロードは行われない。
\r
141 * @param homeVillage 所属するVillage
\r
142 * @param periodType Period種別
\r
143 * @param day Period通番
\r
144 * @param isHot Hotか否か
\r
145 * @throws java.lang.NullPointerException 引数にnullが渡された場合。
\r
147 private Period(Village homeVillage,
\r
148 PeriodType periodType,
\r
151 throws NullPointerException{
\r
152 if( homeVillage == null
\r
153 || periodType == null ) throw new NullPointerException();
\r
155 throw new IllegalArgumentException("Period day is too small !");
\r
157 switch(periodType){
\r
170 this.homeVillage = homeVillage;
\r
171 this.periodType = periodType;
\r
176 this.isHot = isHot;
\r
185 public Village getVillage(){
\r
186 return this.homeVillage;
\r
193 public PeriodType getType(){
\r
194 return this.periodType;
\r
201 * エピローグは最後のゲーム進行日+1番
\r
204 public int getDay(){
\r
210 * @return 更新時刻の文字表記
\r
212 public String getLimit(){
\r
213 StringBuilder result = new StringBuilder();
\r
215 if(this.limitHour < 10) result.append('0');
\r
216 result.append(this.limitHour).append(':');
\r
218 if(this.limitMinute < 10) result.append('0');
\r
219 result.append(this.limitMinute);
\r
221 return result.toString();
\r
228 public boolean isHot(){
\r
234 * @param isHotArg Hot指定
\r
236 public void setHot(boolean isHotArg){
\r
237 this.isHot = isHotArg;
\r
242 * @return プロローグならtrue
\r
244 public boolean isPrologue(){
\r
245 if(getType() == PeriodType.PROLOGUE) return true;
\r
251 * @return エピローグならtrue
\r
253 public boolean isEpilogue(){
\r
254 if(getType() == PeriodType.EPILOGUE) return true;
\r
260 * @return 進行日ならtrue
\r
262 public boolean isProgress(){
\r
263 if(getType() == PeriodType.PROGRESS) return true;
\r
268 * このPeriodにアクセスするためのクエリーを生成する。
\r
269 * @return CGIに渡すクエリー
\r
271 public String getCGIQuery(){
\r
272 StringBuilder result = new StringBuilder();
\r
274 Village village = getVillage();
\r
275 result.append(village.getCGIQuery());
\r
278 result.append("&mes=all"); // 全表示指定
\r
279 return result.toString();
\r
282 Land land = village.getParentLand();
\r
283 LandDef ldef = land.getLandDef();
\r
285 if(ldef.getLandId().equals("wolfg")){
\r
286 result.append("&meslog=");
\r
287 String dnum = "000" + (getDay() - 1);
\r
288 dnum = dnum.substring(dnum.length() - 3);
\r
291 result.append("000_ready");
\r
294 result.append(dnum).append("_progress");
\r
297 result.append(dnum).append("_party");
\r
304 result.append("&meslog=").append(village.getVillageID());
\r
307 result.append("_ready_0");
\r
310 result.append("_progress_").append(getDay() - 1);
\r
313 result.append("_party_").append(getDay() - 1);
\r
322 result.append("&mes=all");
\r
324 return result.toString();
\r
328 * Periodに含まれるTopicのリストを返す。
\r
330 * @return Topicのリスト
\r
332 public List<Topic> getTopicList(){
\r
333 return this.unmodList;
\r
337 * Periodに含まれるTopicの総数を返す。
\r
340 public int getTopics(){
\r
341 return this.topicList.size();
\r
346 * @param topic Topic
\r
347 * @throws java.lang.NullPointerException nullが渡された場合。
\r
349 protected void addTopic(Topic topic) throws NullPointerException{
\r
350 if(topic == null) throw new NullPointerException();
\r
351 this.topicList.add(topic);
\r
356 * Periodのキャプション文字列を返す。
\r
357 * 主な用途はタブ画面の耳のラベルなど。
\r
358 * @return キャプション文字列
\r
360 public String getCaption(){
\r
368 result = getDay() + "日目";
\r
383 * このPeriodをダウンロードしたときのログイン名を返す。
\r
384 * @return ログイン名。ログアウト中はnull。
\r
386 public String getLoginName(){
\r
387 return this.loginName;
\r
391 * 公開発言番号にマッチする発言を返す。
\r
392 * @param talkNo 公開発言番号
\r
393 * @return 発言。見つからなければnull
\r
395 public Talk getNumberedTalk(int talkNo){
\r
396 if(talkNo <= 0) throw new IllegalArgumentException();
\r
398 for(Topic topic : this.topicList){
\r
399 if( ! (topic instanceof Talk) ) continue;
\r
400 Talk talk = (Talk) topic;
\r
401 if(talkNo == talk.getTalkNo()) return talk;
\r
408 * このPeriodの内容にゲーム進行上隠された部分がある可能性を判定する。
\r
409 * @return 隠れた要素がありうるならfalse
\r
411 public boolean isFullOpen(){
\r
412 return this.isFullOpen;
\r
417 * @return ロード済みならtrue
\r
419 public boolean hasLoaded(){
\r
420 return getTopics() > 0;
\r
426 public void unload(){
\r
427 this.limitHour = 0;
\r
428 this.limitMinute = 0;
\r
429 this.loginName = null;
\r
430 this.isFullOpen = false;
\r
432 this.isHot = false;
\r
434 this.topicList.clear();
\r
441 * 決着が付くまで非狼陣営には見えない。
\r
443 * @return 襲撃メッセージがあればtrue
\r
445 public boolean hasAssaultTried(){
\r
446 for(Topic topic : this.topicList){
\r
447 if(topic instanceof Talk){
\r
448 Talk talk = (Talk) topic;
\r
449 if(talk.getTalkCount() <= 0) return true;
\r
450 }else if(topic instanceof SysEvent){
\r
451 SysEvent sysEvent = (SysEvent) topic;
\r
452 SysEventType type = sysEvent.getSysEventType();
\r
453 if(type == SysEventType.ASSAULT) return true;
\r
462 * @return 処刑されたAvatar。突然死などなんらかの理由でいない場合はnull
\r
464 public Avatar getExecutedAvatar(){
\r
465 Avatar result = null;
\r
467 for(Topic topic : getTopicList()){
\r
468 if( ! (topic instanceof SysEvent) ) continue;
\r
469 SysEvent event = (SysEvent) topic;
\r
470 result = event.getExecutedAvatar();
\r
471 if(result != null) break;
\r
478 * 投票に参加したAvatarの集合を返す。
\r
479 * @return 投票に参加したAvatarのSet
\r
481 public Set<Avatar> getVoterSet(){
\r
482 Set<Avatar> result = new HashSet<Avatar>();
\r
484 for(Topic topic : getTopicList()){
\r
485 if( ! (topic instanceof SysEvent) ) continue;
\r
486 SysEvent event = (SysEvent) topic;
\r
487 result = event.getVoterSet(result);
\r
494 * 任意のタイプのシステムイベントを返す。
\r
495 * 複数存在する場合、返すのは最初の一つだけ。
\r
496 * @param type イベントタイプ
\r
499 public SysEvent getTypedSysEvent(SysEventType type){
\r
500 for(Topic topic : getTopicList()){
\r
501 if( ! (topic instanceof SysEvent) ) continue;
\r
502 SysEvent event = (SysEvent) topic;
\r
503 if(event.getSysEventType() == type) return event;
\r
512 private static class PeriodHandler extends HtmlAdapter{
\r
514 private static final int TALKTYPE_NUM = TalkType.values().length;
\r
516 private final EntityConverter converter =
\r
517 new EntityConverter();
\r
519 private final Map<Avatar, int[]> countMap =
\r
520 new HashMap<Avatar, int[]>();
\r
522 private Period period = null;
\r
524 private TalkType talkType;
\r
525 private Avatar avatar;
\r
526 private int talkNo;
\r
527 private String anchorId;
\r
528 private int talkHour;
\r
529 private int talkMinute;
\r
530 private DecodedContent talkContent = null;
\r
532 private EventFamily eventFamily;
\r
533 private SysEventType sysEventType;
\r
534 private DecodedContent eventContent = null;
\r
535 private final List<Avatar> avatarList = new LinkedList<Avatar>();
\r
536 private final List<GameRole> roleList = new LinkedList<GameRole>();
\r
537 private final List<Integer> integerList = new LinkedList<Integer>();
\r
538 private final List<CharSequence> charseqList =
\r
539 new LinkedList<CharSequence>();
\r
544 public PeriodHandler(){
\r
550 * パース結果を格納するPeriodを設定する。
\r
551 * @param period Period
\r
553 public void setPeriod(Period period){
\r
554 this.period = period;
\r
559 * 文字列断片からAvatarを得る。
\r
560 * 村に未登録のAvatarであればついでに登録される。
\r
561 * @param content 文字列
\r
562 * @param range 文字列内のAvatarフルネームを示す領域
\r
565 private Avatar toAvatar(DecodedContent content, SeqRange range){
\r
566 Village village = this.period.getVillage();
\r
567 String fullName = this.converter
\r
568 .convert(content, range)
\r
570 Avatar result = village.getAvatar(fullName);
\r
571 if(result == null){
\r
572 result = new Avatar(fullName);
\r
573 village.addAvatar(result);
\r
580 * Avatar別、会話種ごとに発言回数をカウントする。
\r
582 * @param targetAvatar 対象Avatar
\r
583 * @param targetType 対象会話種
\r
586 private int countUp(Avatar targetAvatar, TalkType targetType){
\r
587 int[] countArray = this.countMap.get(targetAvatar);
\r
588 if(countArray == null){
\r
589 countArray = new int[TALKTYPE_NUM];
\r
590 this.countMap.put(targetAvatar, countArray);
\r
592 int count = ++countArray[targetType.ordinal()];
\r
598 * @param content {@inheritDoc}
\r
599 * @throws HtmlParseException {@inheritDoc}
\r
602 public void startParse(DecodedContent content)
\r
603 throws HtmlParseException{
\r
604 this.period.loginName = null;
\r
605 this.period.topicList.clear();
\r
606 this.countMap.clear();
\r
612 * @param content {@inheritDoc}
\r
613 * @param loginRange {@inheritDoc}
\r
614 * @throws HtmlParseException {@inheritDoc}
\r
617 public void loginName(DecodedContent content, SeqRange loginRange)
\r
618 throws HtmlParseException{
\r
619 DecodedContent loginName =
\r
620 this.converter.convert(content, loginRange);
\r
622 this.period.loginName = loginName.toString();
\r
629 * @param type {@inheritDoc}
\r
630 * @throws HtmlParseException {@inheritDoc}
\r
633 public void pageType(PageType type) throws HtmlParseException{
\r
634 if(type != PageType.PERIOD_PAGE){
\r
635 throw new HtmlParseException(
\r
636 "意図しないページを読み込もうとしました。");
\r
643 * @param month {@inheritDoc}
\r
644 * @param day {@inheritDoc}
\r
645 * @param hour {@inheritDoc}
\r
646 * @param minute {@inheritDoc}
\r
647 * @throws HtmlParseException {@inheritDoc}
\r
650 public void commitTime(int month, int day, int hour, int minute)
\r
651 throws HtmlParseException{
\r
652 this.period.limitHour = hour;
\r
653 this.period.limitMinute = minute;
\r
659 * 自分へのリンクが無いかチェックする。
\r
660 * 自分へのリンクが見つかればこのPeriodを非Hotにする。
\r
661 * 自分へのリンクがあるということは、
\r
662 * 今読んでるHTMLは別のPeriodのために書かれたものということ。
\r
663 * 考えられる原因は、HotだったPeriodがゲーム進行に従い
\r
665 * @param content {@inheritDoc}
\r
666 * @param anchorRange {@inheritDoc}
\r
667 * @param periodType {@inheritDoc}
\r
668 * @param day {@inheritDoc}
\r
669 * @throws HtmlParseException {@inheritDoc}
\r
672 public void periodLink(DecodedContent content,
\r
673 SeqRange anchorRange,
\r
674 PeriodType periodType,
\r
676 throws HtmlParseException{
\r
678 if(this.period.getType() != periodType) return;
\r
680 if( periodType == PeriodType.PROGRESS
\r
681 && this.period.getDay() != day ){
\r
685 if( ! anchorRange.isValid() ) return;
\r
687 this.period.setHot(false);
\r
694 * @throws HtmlParseException {@inheritDoc}
\r
697 public void startTalk() throws HtmlParseException{
\r
698 this.talkType = null;
\r
699 this.avatar = null;
\r
701 this.anchorId = null;
\r
702 this.talkHour = -1;
\r
703 this.talkMinute = -1;
\r
704 this.talkContent = new DecodedContent(100 + 1);
\r
711 * @param type {@inheritDoc}
\r
712 * @throws HtmlParseException {@inheritDoc}
\r
715 public void talkType(TalkType type)
\r
716 throws HtmlParseException{
\r
717 this.talkType = type;
\r
723 * @param content {@inheritDoc}
\r
724 * @param avatarRange {@inheritDoc}
\r
725 * @throws HtmlParseException {@inheritDoc}
\r
728 public void talkAvatar(DecodedContent content, SeqRange avatarRange)
\r
729 throws HtmlParseException{
\r
730 this.avatar = toAvatar(content, avatarRange);
\r
736 * @param hour {@inheritDoc}
\r
737 * @param minute {@inheritDoc}
\r
738 * @throws HtmlParseException {@inheritDoc}
\r
741 public void talkTime(int hour, int minute)
\r
742 throws HtmlParseException{
\r
743 this.talkHour = hour;
\r
744 this.talkMinute = minute;
\r
750 * @param tno {@inheritDoc}
\r
751 * @throws HtmlParseException {@inheritDoc}
\r
754 public void talkNo(int tno) throws HtmlParseException{
\r
761 * @param content {@inheritDoc}
\r
762 * @param idRange {@inheritDoc}
\r
763 * @throws HtmlParseException {@inheritDoc}
\r
766 public void talkId(DecodedContent content, SeqRange idRange)
\r
767 throws HtmlParseException{
\r
768 this.anchorId = content.subSequence(idRange.getStartPos(),
\r
769 idRange.getEndPos() )
\r
776 * @param content {@inheritDoc}
\r
777 * @param textRange {@inheritDoc}
\r
778 * @throws HtmlParseException {@inheritDoc}
\r
781 public void talkText(DecodedContent content, SeqRange textRange)
\r
782 throws HtmlParseException{
\r
783 this.converter.append(this.talkContent, content, textRange);
\r
789 * @throws HtmlParseException {@inheritDoc}
\r
792 public void talkBreak()
\r
793 throws HtmlParseException{
\r
794 this.talkContent.append('\n');
\r
800 * @throws HtmlParseException {@inheritDoc}
\r
803 public void endTalk() throws HtmlParseException{
\r
804 Talk talk = new Talk(this.period,
\r
809 this.talkHour, this.talkMinute,
\r
810 this.talkContent );
\r
812 int count = countUp(this.avatar, this.talkType);
\r
813 talk.setCount(count);
\r
815 this.period.addTopic(talk);
\r
817 this.talkType = null;
\r
818 this.avatar = null;
\r
820 this.anchorId = null;
\r
821 this.talkHour = -1;
\r
822 this.talkMinute = -1;
\r
823 this.talkContent = null;
\r
830 * @param family {@inheritDoc}
\r
831 * @throws HtmlParseException {@inheritDoc}
\r
834 public void startSysEvent(EventFamily family)
\r
835 throws HtmlParseException{
\r
836 this.eventFamily = family;
\r
837 this.sysEventType = null;
\r
838 this.eventContent = new DecodedContent();
\r
839 this.avatarList.clear();
\r
840 this.roleList.clear();
\r
841 this.integerList.clear();
\r
842 this.charseqList.clear();
\r
848 * @param type {@inheritDoc}
\r
849 * @throws HtmlParseException {@inheritDoc}
\r
852 public void sysEventType(SysEventType type)
\r
853 throws HtmlParseException{
\r
854 this.sysEventType = type;
\r
860 * @param content {@inheritDoc}
\r
861 * @param contentRange {@inheritDoc}
\r
862 * @throws HtmlParseException {@inheritDoc}
\r
865 public void sysEventContent(DecodedContent content,
\r
866 SeqRange contentRange)
\r
867 throws HtmlParseException{
\r
868 this.converter.append(this.eventContent, content, contentRange);
\r
874 * @param content {@inheritDoc}
\r
875 * @param anchorRange {@inheritDoc}
\r
876 * @param contentRange {@inheritDoc}
\r
877 * @throws HtmlParseException {@inheritDoc}
\r
880 public void sysEventContentAnchor(DecodedContent content,
\r
881 SeqRange anchorRange,
\r
882 SeqRange contentRange)
\r
883 throws HtmlParseException{
\r
884 this.converter.append(this.eventContent, content, contentRange);
\r
890 * @throws HtmlParseException {@inheritDoc}
\r
893 public void sysEventContentBreak() throws HtmlParseException{
\r
894 this.eventContent.append('\n');
\r
900 * @param content {@inheritDoc}
\r
901 * @param entryNo {@inheritDoc}
\r
902 * @param avatarRange {@inheritDoc}
\r
903 * @throws HtmlParseException {@inheritDoc}
\r
906 public void sysEventOnStage(DecodedContent content,
\r
908 SeqRange avatarRange)
\r
909 throws HtmlParseException{
\r
910 Avatar newAvatar = toAvatar(content, avatarRange);
\r
911 this.integerList.add(entryNo);
\r
912 this.avatarList.add(newAvatar);
\r
918 * @param role {@inheritDoc}
\r
919 * @param num {@inheritDoc}
\r
920 * @throws HtmlParseException {@inheritDoc}
\r
923 public void sysEventOpenRole(GameRole role, int num)
\r
924 throws HtmlParseException{
\r
925 this.roleList.add(role);
\r
926 this.integerList.add(num);
\r
932 * @param content {@inheritDoc}
\r
933 * @param avatarRange {@inheritDoc}
\r
934 * @throws HtmlParseException {@inheritDoc}
\r
937 public void sysEventMurdered(DecodedContent content,
\r
938 SeqRange avatarRange)
\r
939 throws HtmlParseException{
\r
940 Avatar murdered = toAvatar(content, avatarRange);
\r
941 this.avatarList.add(murdered);
\r
947 * @param content {@inheritDoc}
\r
948 * @param avatarRange {@inheritDoc}
\r
949 * @throws HtmlParseException {@inheritDoc}
\r
952 public void sysEventSurvivor(DecodedContent content,
\r
953 SeqRange avatarRange)
\r
954 throws HtmlParseException{
\r
955 Avatar survivor = toAvatar(content, avatarRange);
\r
956 this.avatarList.add(survivor);
\r
962 * @param content {@inheritDoc}
\r
963 * @param voteByRange {@inheritDoc}
\r
964 * @param voteToRange {@inheritDoc}
\r
965 * @throws HtmlParseException {@inheritDoc}
\r
968 public void sysEventCounting(DecodedContent content,
\r
969 SeqRange voteByRange,
\r
970 SeqRange voteToRange)
\r
971 throws HtmlParseException{
\r
972 if(voteByRange.isValid()){
\r
973 Avatar voteBy = toAvatar(content, voteByRange);
\r
974 this.avatarList.add(voteBy);
\r
976 Avatar voteTo = toAvatar(content, voteToRange);
\r
977 this.avatarList.add(voteTo);
\r
983 * @param content {@inheritDoc}
\r
984 * @param voteByRange {@inheritDoc}
\r
985 * @param voteToRange {@inheritDoc}
\r
986 * @throws HtmlParseException {@inheritDoc}
\r
989 public void sysEventCounting2(DecodedContent content,
\r
990 SeqRange voteByRange,
\r
991 SeqRange voteToRange)
\r
992 throws HtmlParseException{
\r
993 sysEventCounting(content, voteByRange, voteToRange);
\r
999 * @param content {@inheritDoc}
\r
1000 * @param avatarRange {@inheritDoc}
\r
1001 * @throws HtmlParseException {@inheritDoc}
\r
1004 public void sysEventSuddenDeath(DecodedContent content,
\r
1005 SeqRange avatarRange)
\r
1006 throws HtmlParseException{
\r
1007 Avatar suddenDeath = toAvatar(content, avatarRange);
\r
1008 this.avatarList.add(suddenDeath);
\r
1014 * @param content {@inheritDoc}
\r
1015 * @param avatarRange {@inheritDoc}
\r
1016 * @param anchorRange {@inheritDoc}
\r
1017 * @param loginRange {@inheritDoc}
\r
1018 * @param isLiving {@inheritDoc}
\r
1019 * @param role {@inheritDoc}
\r
1020 * @throws HtmlParseException {@inheritDoc}
\r
1023 public void sysEventPlayerList(DecodedContent content,
\r
1024 SeqRange avatarRange,
\r
1025 SeqRange anchorRange,
\r
1026 SeqRange loginRange,
\r
1029 throws HtmlParseException{
\r
1030 Avatar who = toAvatar(content, avatarRange);
\r
1032 CharSequence anchor;
\r
1033 if(anchorRange.isValid()){
\r
1034 anchor = this.converter.convert(content, anchorRange);
\r
1038 CharSequence account = this.converter
\r
1039 .convert(content, loginRange);
\r
1041 Integer liveOrDead;
\r
1042 if(isLiving) liveOrDead = Integer.valueOf(1);
\r
1043 else liveOrDead = Integer.valueOf(0);
\r
1045 this.avatarList.add(who);
\r
1046 this.charseqList.add(anchor);
\r
1047 this.charseqList.add(account);
\r
1048 this.integerList.add(liveOrDead);
\r
1049 this.roleList.add(role);
\r
1056 * @param content {@inheritDoc}
\r
1057 * @param avatarRange {@inheritDoc}
\r
1058 * @param votes {@inheritDoc}
\r
1059 * @throws HtmlParseException {@inheritDoc}
\r
1062 public void sysEventExecution(DecodedContent content,
\r
1063 SeqRange avatarRange,
\r
1065 throws HtmlParseException{
\r
1066 Avatar who = toAvatar(content, avatarRange);
\r
1068 this.avatarList.add(who);
\r
1069 this.integerList.add(votes);
\r
1076 * @param hour {@inheritDoc}
\r
1077 * @param minute {@inheritDoc}
\r
1078 * @param minLimit {@inheritDoc}
\r
1079 * @param maxLimit {@inheritDoc}
\r
1080 * @throws HtmlParseException {@inheritDoc}
\r
1083 public void sysEventAskEntry(int hour, int minute,
\r
1084 int minLimit, int maxLimit)
\r
1085 throws HtmlParseException{
\r
1086 this.integerList.add(hour * 60 + minute);
\r
1087 this.integerList.add(minLimit);
\r
1088 this.integerList.add(maxLimit);
\r
1094 * @param hour {@inheritDoc}
\r
1095 * @param minute {@inheritDoc}
\r
1096 * @throws HtmlParseException {@inheritDoc}
\r
1099 public void sysEventAskCommit(int hour, int minute)
\r
1100 throws HtmlParseException{
\r
1101 this.integerList.add(hour * 60 + minute);
\r
1107 * @param content {@inheritDoc}
\r
1108 * @param avatarRange {@inheritDoc}
\r
1109 * @throws HtmlParseException {@inheritDoc}
\r
1112 public void sysEventNoComment(DecodedContent content,
\r
1113 SeqRange avatarRange)
\r
1114 throws HtmlParseException{
\r
1115 Avatar noComAvatar = toAvatar(content, avatarRange);
\r
1116 this.avatarList.add(noComAvatar);
\r
1122 * @param winner {@inheritDoc}
\r
1123 * @param hour {@inheritDoc}
\r
1124 * @param minute {@inheritDoc}
\r
1125 * @throws HtmlParseException {@inheritDoc}
\r
1128 public void sysEventStayEpilogue(Team winner, int hour, int minute)
\r
1129 throws HtmlParseException{
\r
1130 GameRole role = null;
\r
1133 case VILLAGE: role = GameRole.INNOCENT; break;
\r
1134 case WOLF: role = GameRole.WOLF; break;
\r
1135 case HAMSTER: role = GameRole.HAMSTER; break;
\r
1136 default: assert false; break;
\r
1139 this.roleList.add(role);
\r
1140 this.integerList.add(hour * 60 + minute);
\r
1147 * @param content {@inheritDoc}
\r
1148 * @param guardByRange {@inheritDoc}
\r
1149 * @param guardToRange {@inheritDoc}
\r
1150 * @throws HtmlParseException {@inheritDoc}
\r
1153 public void sysEventGuard(DecodedContent content,
\r
1154 SeqRange guardByRange,
\r
1155 SeqRange guardToRange)
\r
1156 throws HtmlParseException{
\r
1157 Avatar guardBy = toAvatar(content, guardByRange);
\r
1158 Avatar guardTo = toAvatar(content, guardToRange);
\r
1159 this.avatarList.add(guardBy);
\r
1160 this.avatarList.add(guardTo);
\r
1166 * @param content {@inheritDoc}
\r
1167 * @param judgeByRange {@inheritDoc}
\r
1168 * @param judgeToRange {@inheritDoc}
\r
1169 * @throws HtmlParseException {@inheritDoc}
\r
1172 public void sysEventJudge(DecodedContent content,
\r
1173 SeqRange judgeByRange,
\r
1174 SeqRange judgeToRange)
\r
1175 throws HtmlParseException{
\r
1176 Avatar judgeBy = toAvatar(content, judgeByRange);
\r
1177 Avatar judgeTo = toAvatar(content, judgeToRange);
\r
1178 this.avatarList.add(judgeBy);
\r
1179 this.avatarList.add(judgeTo);
\r
1185 * @throws HtmlParseException {@inheritDoc}
\r
1188 public void endSysEvent() throws HtmlParseException{
\r
1189 SysEvent event = new SysEvent();
\r
1190 event.setEventFamily(this.eventFamily);
\r
1191 event.setSysEventType(this.sysEventType);
\r
1192 event.setContent(this.eventContent);
\r
1193 event.addAvatarList(this.avatarList);
\r
1194 event.addRoleList(this.roleList);
\r
1195 event.addIntegerList(this.integerList);
\r
1196 event.addCharSequenceList(this.charseqList);
\r
1198 this.period.addTopic(event);
\r
1200 if( this.sysEventType == SysEventType.MURDERED
\r
1201 || this.sysEventType == SysEventType.NOMURDER ){
\r
1202 for(Topic topic : this.period.topicList){
\r
1203 if( ! (topic instanceof Talk) ) continue;
\r
1204 Talk talk = (Talk) topic;
\r
1205 if(talk.getTalkType() != TalkType.WOLFONLY) continue;
\r
1207 .isTerminated(talk.getDialog(),
\r
1208 "!\u0020今日がお前の命日だ!") ){
\r
1211 talk.setCount(-1);
\r
1212 this.countMap.clear();
\r
1216 this.eventFamily = null;
\r
1217 this.sysEventType = null;
\r
1218 this.eventContent = null;
\r
1219 this.avatarList.clear();
\r
1220 this.roleList.clear();
\r
1221 this.integerList.clear();
\r
1222 this.charseqList.clear();
\r
1229 * @throws HtmlParseException {@inheritDoc}
\r
1232 public void endParse() throws HtmlParseException{
\r
1236 // TODO 村名のチェックは不要か?
\r