2 * daily period in village
4 * License : The MIT License
5 * Copyright(c) 2008 olyutorskii
8 package jp.sfjp.jindolf.data;
10 import java.io.IOException;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.LinkedList;
15 import java.util.List;
18 import java.util.logging.Level;
19 import java.util.logging.Logger;
20 import jp.sfjp.jindolf.net.HtmlSequence;
21 import jp.sfjp.jindolf.net.ServerAccess;
22 import jp.sfjp.jindolf.util.StringUtils;
23 import jp.sourceforge.jindolf.corelib.EventFamily;
24 import jp.sourceforge.jindolf.corelib.GameRole;
25 import jp.sourceforge.jindolf.corelib.LandDef;
26 import jp.sourceforge.jindolf.corelib.PeriodType;
27 import jp.sourceforge.jindolf.corelib.SysEventType;
28 import jp.sourceforge.jindolf.corelib.TalkType;
29 import jp.sourceforge.jindolf.corelib.Team;
30 import jp.sourceforge.jindolf.corelib.VillageState;
31 import jp.sourceforge.jindolf.parser.DecodedContent;
32 import jp.sourceforge.jindolf.parser.EntityConverter;
33 import jp.sourceforge.jindolf.parser.HtmlAdapter;
34 import jp.sourceforge.jindolf.parser.HtmlParseException;
35 import jp.sourceforge.jindolf.parser.HtmlParser;
36 import jp.sourceforge.jindolf.parser.PageType;
37 import jp.sourceforge.jindolf.parser.SeqRange;
41 * 村の進行の一区切り。プロローグやエピローグも含まれる。
43 * <p>将来、24時間更新でなくなる可能性の考慮が必要。
45 * 24時間以上の期間を持つPeriodが生成される可能性の考慮が必要。
48 // TODO Comparable も implement する?
50 private static final HtmlParser PARSER = new HtmlParser();
51 private static final PeriodHandler HANDLER =
54 private static final Logger LOGGER = Logger.getAnonymousLogger();
57 PARSER.setBasicHandler (HANDLER);
58 PARSER.setSysEventHandler(HANDLER);
59 PARSER.setTalkHandler (HANDLER);
62 private final Village homeVillage;
63 private final PeriodType periodType;
64 private final int day;
65 private int limitHour;
66 private int limitMinute;
68 private String loginName;
69 private boolean isFullOpen = false;
71 private final List<Topic> topicList = new LinkedList<>();
72 private final List<Topic> unmodList =
73 Collections.unmodifiableList(this.topicList);
77 * この Period が進行中の村の最新日で、
78 * 今まさに次々と発言が蓄積されているときは
80 * ※重要: Hot な Period は meslog クエリーを使ってダウンロードできない。
82 private boolean isHot;
87 * この段階では発言データのロードは行われない。
89 * @param homeVillage 所属するVillage
90 * @param periodType Period種別
92 * @throws java.lang.NullPointerException 引数にnullが渡された場合。
94 public Period(Village homeVillage,
95 PeriodType periodType,
97 throws NullPointerException{
98 this(homeVillage, periodType, day, false);
104 * この段階では発言データのロードは行われない。
105 * @param homeVillage 所属するVillage
106 * @param periodType Period種別
107 * @param day Period通番
108 * @param isHot Hotか否か
109 * @throws java.lang.NullPointerException 引数にnullが渡された場合。
111 private Period(Village homeVillage,
112 PeriodType periodType,
115 throws NullPointerException{
116 if( homeVillage == null
117 || periodType == null ) throw new NullPointerException();
119 throw new IllegalArgumentException("Period day is too small !");
134 this.homeVillage = homeVillage;
135 this.periodType = periodType;
147 * Periodを更新する。Topicのリストが更新される。
149 * @param force trueなら強制再読み込み。
150 * falseならまだ読み込んで無い時のみ読み込み。
151 * @throws IOException ネットワーク入力エラー
153 public static void parsePeriod(Period period, boolean force)
155 if( ! force && period.hasLoaded() ) return;
157 Village village = period.getVillage();
158 Land land = village.getParentLand();
159 ServerAccess server = land.getServerAccess();
161 if(village.getState() != VillageState.PROGRESS){
162 period.isFullOpen = true;
163 }else if(period.getType() != PeriodType.PROGRESS){
164 period.isFullOpen = true;
166 period.isFullOpen = false;
169 HtmlSequence html = server.getHTMLPeriod(period);
171 period.topicList.clear();
173 boolean wasHot = period.isHot();
175 HANDLER.setPeriod(period);
176 DecodedContent content = html.getContent();
178 PARSER.parseAutomatic(content);
179 }catch(HtmlParseException e){
180 LOGGER.log(Level.WARNING, "発言抽出に失敗", e);
183 if(wasHot && ! period.isHot() ){
184 parsePeriod(period, true);
195 public Village getVillage(){
196 return this.homeVillage;
203 public PeriodType getType(){
204 return this.periodType;
222 public String getLimit(){
223 StringBuilder result = new StringBuilder();
225 if(this.limitHour < 10) result.append('0');
226 result.append(this.limitHour).append(':');
228 if(this.limitMinute < 10) result.append('0');
229 result.append(this.limitMinute);
231 return result.toString();
238 public boolean isHot(){
244 * @param isHotArg Hot指定
246 public void setHot(boolean isHotArg){
247 this.isHot = isHotArg;
252 * @return プロローグならtrue
254 public boolean isPrologue(){
255 if(getType() == PeriodType.PROLOGUE) return true;
261 * @return エピローグならtrue
263 public boolean isEpilogue(){
264 if(getType() == PeriodType.EPILOGUE) return true;
272 public boolean isProgress(){
273 if(getType() == PeriodType.PROGRESS) return true;
278 * このPeriodにアクセスするためのクエリーを生成する。
281 public String getCGIQuery(){
282 StringBuilder result = new StringBuilder();
284 Village village = getVillage();
285 result.append(village.getCGIQuery());
288 result.append("&mes=all"); // 全表示指定
289 return result.toString();
292 Land land = village.getParentLand();
293 LandDef ldef = land.getLandDef();
295 if(ldef.getLandId().equals("wolfg")){
296 result.append("&meslog=");
297 String dnum = "000" + (getDay() - 1);
298 dnum = dnum.substring(dnum.length() - 3);
301 result.append("000_ready");
304 result.append(dnum).append("_progress");
307 result.append(dnum).append("_party");
314 result.append("&meslog=").append(village.getVillageID());
317 result.append("_ready_0");
320 result.append("_progress_").append(getDay() - 1);
323 result.append("_party_").append(getDay() - 1);
332 result.append("&mes=all");
334 return result.toString();
338 * Periodに含まれるTopicのリストを返す。
342 public List<Topic> getTopicList(){
343 return this.unmodList;
347 * Periodに含まれるTopicの総数を返す。
350 public int getTopics(){
351 return this.topicList.size();
357 * @throws java.lang.NullPointerException nullが渡された場合。
359 protected void addTopic(Topic topic) throws NullPointerException{
360 if(topic == null) throw new NullPointerException();
361 this.topicList.add(topic);
366 * Periodのキャプション文字列を返す。
370 public String getCaption(){
378 result = getDay() + "日目";
393 * このPeriodをダウンロードしたときのログイン名を返す。
394 * @return ログイン名。ログアウト中はnull。
396 public String getLoginName(){
397 return this.loginName;
402 * @param talkNo 公開発言番号
403 * @return 発言。見つからなければnull
405 public Talk getNumberedTalk(int talkNo){
406 if(talkNo <= 0) throw new IllegalArgumentException();
408 for(Topic topic : this.topicList){
409 if( ! (topic instanceof Talk) ) continue;
410 Talk talk = (Talk) topic;
411 if(talkNo == talk.getTalkNo()) return talk;
418 * このPeriodの内容にゲーム進行上隠された部分がある可能性を判定する。
419 * @return 隠れた要素がありうるならfalse
421 public boolean isFullOpen(){
422 return this.isFullOpen;
427 * @return ロード済みならtrue
429 public boolean hasLoaded(){
430 return getTopics() > 0;
436 public void unload(){
438 this.limitMinute = 0;
439 this.loginName = null;
440 this.isFullOpen = false;
444 this.topicList.clear();
453 * @return 襲撃メッセージがあればtrue
455 public boolean hasAssaultTried(){
456 for(Topic topic : this.topicList){
457 if(topic instanceof Talk){
458 Talk talk = (Talk) topic;
459 if(talk.getTalkCount() <= 0) return true;
460 }else if(topic instanceof SysEvent){
461 SysEvent sysEvent = (SysEvent) topic;
462 SysEventType type = sysEvent.getSysEventType();
463 if(type == SysEventType.ASSAULT) return true;
472 * @return 処刑されたAvatar。突然死などなんらかの理由でいない場合はnull
474 public Avatar getExecutedAvatar(){
475 Avatar result = null;
477 for(Topic topic : getTopicList()){
478 if( ! (topic instanceof SysEvent) ) continue;
479 SysEvent event = (SysEvent) topic;
480 result = event.getExecutedAvatar();
481 if(result != null) break;
488 * 投票に参加したAvatarの集合を返す。
489 * @return 投票に参加したAvatarのSet
491 public Set<Avatar> getVoterSet(){
492 Set<Avatar> result = new HashSet<>();
494 for(Topic topic : getTopicList()){
495 if( ! (topic instanceof SysEvent) ) continue;
496 SysEvent event = (SysEvent) topic;
497 result = event.getVoterSet(result);
504 * 任意のタイプのシステムイベントを返す。
505 * 複数存在する場合、返すのは最初の一つだけ。
506 * @param type イベントタイプ
509 public SysEvent getTypedSysEvent(SysEventType type){
510 for(Topic topic : getTopicList()){
511 if( ! (topic instanceof SysEvent) ) continue;
512 SysEvent event = (SysEvent) topic;
513 if(event.getSysEventType() == type) return event;
522 private static class PeriodHandler extends HtmlAdapter{
524 private static final int TALKTYPE_NUM = TalkType.values().length;
526 private final EntityConverter converter =
527 new EntityConverter();
529 private final Map<Avatar, int[]> countMap =
532 private Period period = null;
534 private TalkType talkType;
535 private Avatar avatar;
537 private String anchorId;
538 private int talkHour;
539 private int talkMinute;
540 private DecodedContent talkContent = null;
542 private EventFamily eventFamily;
543 private SysEventType sysEventType;
544 private DecodedContent eventContent = null;
545 private final List<Avatar> avatarList = new LinkedList<>();
546 private final List<GameRole> roleList = new LinkedList<>();
547 private final List<Integer> integerList = new LinkedList<>();
548 private final List<CharSequence> charseqList =
554 public PeriodHandler(){
560 * パース結果を格納するPeriodを設定する。
561 * @param period Period
563 public void setPeriod(Period period){
564 this.period = period;
570 * 村に未登録のAvatarであればついでに登録される。
572 * @param range 文字列内のAvatarフルネームを示す領域
575 private Avatar toAvatar(DecodedContent content, SeqRange range){
576 Village village = this.period.getVillage();
577 String fullName = this.converter
578 .convert(content, range)
580 Avatar result = village.getAvatar(fullName);
582 result = new Avatar(fullName);
583 village.addAvatar(result);
590 * Avatar別、会話種ごとに発言回数をカウントする。
592 * @param targetAvatar 対象Avatar
593 * @param targetType 対象会話種
596 private int countUp(Avatar targetAvatar, TalkType targetType){
597 int[] countArray = this.countMap.get(targetAvatar);
598 if(countArray == null){
599 countArray = new int[TALKTYPE_NUM];
600 this.countMap.put(targetAvatar, countArray);
602 int count = ++countArray[targetType.ordinal()];
608 * @param content {@inheritDoc}
609 * @throws HtmlParseException {@inheritDoc}
612 public void startParse(DecodedContent content)
613 throws HtmlParseException{
614 this.period.loginName = null;
615 this.period.topicList.clear();
616 this.countMap.clear();
622 * @param content {@inheritDoc}
623 * @param loginRange {@inheritDoc}
624 * @throws HtmlParseException {@inheritDoc}
627 public void loginName(DecodedContent content, SeqRange loginRange)
628 throws HtmlParseException{
629 DecodedContent loginName =
630 this.converter.convert(content, loginRange);
632 this.period.loginName = loginName.toString();
639 * @param type {@inheritDoc}
640 * @throws HtmlParseException {@inheritDoc}
643 public void pageType(PageType type) throws HtmlParseException{
644 if(type != PageType.PERIOD_PAGE){
645 throw new HtmlParseException(
646 "意図しないページを読み込もうとしました。");
653 * @param month {@inheritDoc}
654 * @param day {@inheritDoc}
655 * @param hour {@inheritDoc}
656 * @param minute {@inheritDoc}
657 * @throws HtmlParseException {@inheritDoc}
660 public void commitTime(int month, int day, int hour, int minute)
661 throws HtmlParseException{
662 this.period.limitHour = hour;
663 this.period.limitMinute = minute;
670 * 自分へのリンクが見つかればこのPeriodを非Hotにする。
672 * 今読んでるHTMLは別のPeriodのために書かれたものということ。
673 * 考えられる原因は、HotだったPeriodがゲーム進行に従い
675 * @param content {@inheritDoc}
676 * @param anchorRange {@inheritDoc}
677 * @param periodType {@inheritDoc}
678 * @param day {@inheritDoc}
679 * @throws HtmlParseException {@inheritDoc}
682 public void periodLink(DecodedContent content,
683 SeqRange anchorRange,
684 PeriodType periodType,
686 throws HtmlParseException{
688 if(this.period.getType() != periodType) return;
690 if( periodType == PeriodType.PROGRESS
691 && this.period.getDay() != day ){
695 if( ! anchorRange.isValid() ) return;
697 this.period.setHot(false);
704 * @throws HtmlParseException {@inheritDoc}
707 public void startTalk() throws HtmlParseException{
708 this.talkType = null;
711 this.anchorId = null;
713 this.talkMinute = -1;
714 this.talkContent = new DecodedContent(100 + 1);
721 * @param type {@inheritDoc}
722 * @throws HtmlParseException {@inheritDoc}
725 public void talkType(TalkType type)
726 throws HtmlParseException{
727 this.talkType = type;
733 * @param content {@inheritDoc}
734 * @param avatarRange {@inheritDoc}
735 * @throws HtmlParseException {@inheritDoc}
738 public void talkAvatar(DecodedContent content, SeqRange avatarRange)
739 throws HtmlParseException{
740 this.avatar = toAvatar(content, avatarRange);
746 * @param hour {@inheritDoc}
747 * @param minute {@inheritDoc}
748 * @throws HtmlParseException {@inheritDoc}
751 public void talkTime(int hour, int minute)
752 throws HtmlParseException{
753 this.talkHour = hour;
754 this.talkMinute = minute;
760 * @param tno {@inheritDoc}
761 * @throws HtmlParseException {@inheritDoc}
764 public void talkNo(int tno) throws HtmlParseException{
771 * @param content {@inheritDoc}
772 * @param idRange {@inheritDoc}
773 * @throws HtmlParseException {@inheritDoc}
776 public void talkId(DecodedContent content, SeqRange idRange)
777 throws HtmlParseException{
778 this.anchorId = content.subSequence(idRange.getStartPos(),
779 idRange.getEndPos() )
786 * @param content {@inheritDoc}
787 * @param textRange {@inheritDoc}
788 * @throws HtmlParseException {@inheritDoc}
791 public void talkText(DecodedContent content, SeqRange textRange)
792 throws HtmlParseException{
793 this.converter.append(this.talkContent, content, textRange);
799 * @throws HtmlParseException {@inheritDoc}
802 public void talkBreak()
803 throws HtmlParseException{
804 this.talkContent.append('\n');
810 * @throws HtmlParseException {@inheritDoc}
813 public void endTalk() throws HtmlParseException{
814 Talk talk = new Talk(this.period,
819 this.talkHour, this.talkMinute,
822 int count = countUp(this.avatar, this.talkType);
823 talk.setCount(count);
825 this.period.addTopic(talk);
827 this.talkType = null;
830 this.anchorId = null;
832 this.talkMinute = -1;
833 this.talkContent = null;
840 * @param family {@inheritDoc}
841 * @throws HtmlParseException {@inheritDoc}
844 public void startSysEvent(EventFamily family)
845 throws HtmlParseException{
846 this.eventFamily = family;
847 this.sysEventType = null;
848 this.eventContent = new DecodedContent();
849 this.avatarList.clear();
850 this.roleList.clear();
851 this.integerList.clear();
852 this.charseqList.clear();
858 * @param type {@inheritDoc}
859 * @throws HtmlParseException {@inheritDoc}
862 public void sysEventType(SysEventType type)
863 throws HtmlParseException{
864 this.sysEventType = type;
870 * @param content {@inheritDoc}
871 * @param contentRange {@inheritDoc}
872 * @throws HtmlParseException {@inheritDoc}
875 public void sysEventContent(DecodedContent content,
876 SeqRange contentRange)
877 throws HtmlParseException{
878 this.converter.append(this.eventContent, content, contentRange);
884 * @param content {@inheritDoc}
885 * @param anchorRange {@inheritDoc}
886 * @param contentRange {@inheritDoc}
887 * @throws HtmlParseException {@inheritDoc}
890 public void sysEventContentAnchor(DecodedContent content,
891 SeqRange anchorRange,
892 SeqRange contentRange)
893 throws HtmlParseException{
894 this.converter.append(this.eventContent, content, contentRange);
900 * @throws HtmlParseException {@inheritDoc}
903 public void sysEventContentBreak() throws HtmlParseException{
904 this.eventContent.append('\n');
910 * @param content {@inheritDoc}
911 * @param entryNo {@inheritDoc}
912 * @param avatarRange {@inheritDoc}
913 * @throws HtmlParseException {@inheritDoc}
916 public void sysEventOnStage(DecodedContent content,
918 SeqRange avatarRange)
919 throws HtmlParseException{
920 Avatar newAvatar = toAvatar(content, avatarRange);
921 this.integerList.add(entryNo);
922 this.avatarList.add(newAvatar);
928 * @param role {@inheritDoc}
929 * @param num {@inheritDoc}
930 * @throws HtmlParseException {@inheritDoc}
933 public void sysEventOpenRole(GameRole role, int num)
934 throws HtmlParseException{
935 this.roleList.add(role);
936 this.integerList.add(num);
942 * @param content {@inheritDoc}
943 * @param avatarRange {@inheritDoc}
944 * @throws HtmlParseException {@inheritDoc}
947 public void sysEventMurdered(DecodedContent content,
948 SeqRange avatarRange)
949 throws HtmlParseException{
950 Avatar murdered = toAvatar(content, avatarRange);
951 this.avatarList.add(murdered);
957 * @param content {@inheritDoc}
958 * @param avatarRange {@inheritDoc}
959 * @throws HtmlParseException {@inheritDoc}
962 public void sysEventSurvivor(DecodedContent content,
963 SeqRange avatarRange)
964 throws HtmlParseException{
965 Avatar survivor = toAvatar(content, avatarRange);
966 this.avatarList.add(survivor);
972 * @param content {@inheritDoc}
973 * @param voteByRange {@inheritDoc}
974 * @param voteToRange {@inheritDoc}
975 * @throws HtmlParseException {@inheritDoc}
978 public void sysEventCounting(DecodedContent content,
979 SeqRange voteByRange,
980 SeqRange voteToRange)
981 throws HtmlParseException{
982 if(voteByRange.isValid()){
983 Avatar voteBy = toAvatar(content, voteByRange);
984 this.avatarList.add(voteBy);
986 Avatar voteTo = toAvatar(content, voteToRange);
987 this.avatarList.add(voteTo);
993 * @param content {@inheritDoc}
994 * @param voteByRange {@inheritDoc}
995 * @param voteToRange {@inheritDoc}
996 * @throws HtmlParseException {@inheritDoc}
999 public void sysEventCounting2(DecodedContent content,
1000 SeqRange voteByRange,
1001 SeqRange voteToRange)
1002 throws HtmlParseException{
1003 sysEventCounting(content, voteByRange, voteToRange);
1009 * @param content {@inheritDoc}
1010 * @param avatarRange {@inheritDoc}
1011 * @throws HtmlParseException {@inheritDoc}
1014 public void sysEventSuddenDeath(DecodedContent content,
1015 SeqRange avatarRange)
1016 throws HtmlParseException{
1017 Avatar suddenDeath = toAvatar(content, avatarRange);
1018 this.avatarList.add(suddenDeath);
1024 * @param content {@inheritDoc}
1025 * @param avatarRange {@inheritDoc}
1026 * @param anchorRange {@inheritDoc}
1027 * @param loginRange {@inheritDoc}
1028 * @param isLiving {@inheritDoc}
1029 * @param role {@inheritDoc}
1030 * @throws HtmlParseException {@inheritDoc}
1033 public void sysEventPlayerList(DecodedContent content,
1034 SeqRange avatarRange,
1035 SeqRange anchorRange,
1036 SeqRange loginRange,
1039 throws HtmlParseException{
1040 Avatar who = toAvatar(content, avatarRange);
1042 CharSequence anchor;
1043 if(anchorRange.isValid()){
1044 anchor = this.converter.convert(content, anchorRange);
1048 CharSequence account = this.converter
1049 .convert(content, loginRange);
1052 if(isLiving) liveOrDead = Integer.valueOf(1);
1053 else liveOrDead = Integer.valueOf(0);
1055 this.avatarList.add(who);
1056 this.charseqList.add(anchor);
1057 this.charseqList.add(account);
1058 this.integerList.add(liveOrDead);
1059 this.roleList.add(role);
1066 * @param content {@inheritDoc}
1067 * @param avatarRange {@inheritDoc}
1068 * @param votes {@inheritDoc}
1069 * @throws HtmlParseException {@inheritDoc}
1072 public void sysEventExecution(DecodedContent content,
1073 SeqRange avatarRange,
1075 throws HtmlParseException{
1076 Avatar who = toAvatar(content, avatarRange);
1078 this.avatarList.add(who);
1079 this.integerList.add(votes);
1086 * @param hour {@inheritDoc}
1087 * @param minute {@inheritDoc}
1088 * @param minLimit {@inheritDoc}
1089 * @param maxLimit {@inheritDoc}
1090 * @throws HtmlParseException {@inheritDoc}
1093 public void sysEventAskEntry(int hour, int minute,
1094 int minLimit, int maxLimit)
1095 throws HtmlParseException{
1096 this.integerList.add(hour * 60 + minute);
1097 this.integerList.add(minLimit);
1098 this.integerList.add(maxLimit);
1104 * @param hour {@inheritDoc}
1105 * @param minute {@inheritDoc}
1106 * @throws HtmlParseException {@inheritDoc}
1109 public void sysEventAskCommit(int hour, int minute)
1110 throws HtmlParseException{
1111 this.integerList.add(hour * 60 + minute);
1117 * @param content {@inheritDoc}
1118 * @param avatarRange {@inheritDoc}
1119 * @throws HtmlParseException {@inheritDoc}
1122 public void sysEventNoComment(DecodedContent content,
1123 SeqRange avatarRange)
1124 throws HtmlParseException{
1125 Avatar noComAvatar = toAvatar(content, avatarRange);
1126 this.avatarList.add(noComAvatar);
1132 * @param winner {@inheritDoc}
1133 * @param hour {@inheritDoc}
1134 * @param minute {@inheritDoc}
1135 * @throws HtmlParseException {@inheritDoc}
1138 public void sysEventStayEpilogue(Team winner, int hour, int minute)
1139 throws HtmlParseException{
1140 GameRole role = null;
1143 case VILLAGE: role = GameRole.INNOCENT; break;
1144 case WOLF: role = GameRole.WOLF; break;
1145 case HAMSTER: role = GameRole.HAMSTER; break;
1146 default: assert false; break;
1149 this.roleList.add(role);
1150 this.integerList.add(hour * 60 + minute);
1157 * @param content {@inheritDoc}
1158 * @param guardByRange {@inheritDoc}
1159 * @param guardToRange {@inheritDoc}
1160 * @throws HtmlParseException {@inheritDoc}
1163 public void sysEventGuard(DecodedContent content,
1164 SeqRange guardByRange,
1165 SeqRange guardToRange)
1166 throws HtmlParseException{
1167 Avatar guardBy = toAvatar(content, guardByRange);
1168 Avatar guardTo = toAvatar(content, guardToRange);
1169 this.avatarList.add(guardBy);
1170 this.avatarList.add(guardTo);
1176 * @param content {@inheritDoc}
1177 * @param judgeByRange {@inheritDoc}
1178 * @param judgeToRange {@inheritDoc}
1179 * @throws HtmlParseException {@inheritDoc}
1182 public void sysEventJudge(DecodedContent content,
1183 SeqRange judgeByRange,
1184 SeqRange judgeToRange)
1185 throws HtmlParseException{
1186 Avatar judgeBy = toAvatar(content, judgeByRange);
1187 Avatar judgeTo = toAvatar(content, judgeToRange);
1188 this.avatarList.add(judgeBy);
1189 this.avatarList.add(judgeTo);
1195 * @throws HtmlParseException {@inheritDoc}
1198 public void endSysEvent() throws HtmlParseException{
1199 SysEvent event = new SysEvent();
1200 event.setEventFamily(this.eventFamily);
1201 event.setSysEventType(this.sysEventType);
1202 event.setContent(this.eventContent);
1203 event.addAvatarList(this.avatarList);
1204 event.addRoleList(this.roleList);
1205 event.addIntegerList(this.integerList);
1206 event.addCharSequenceList(this.charseqList);
1208 this.period.addTopic(event);
1210 if( this.sysEventType == SysEventType.MURDERED
1211 || this.sysEventType == SysEventType.NOMURDER ){
1212 for(Topic topic : this.period.topicList){
1213 if( ! (topic instanceof Talk) ) continue;
1214 Talk talk = (Talk) topic;
1215 if(talk.getTalkType() != TalkType.WOLFONLY) continue;
1217 .isTerminated(talk.getDialog(),
1218 "!\u0020今日がお前の命日だ!") ){
1222 this.countMap.clear();
1226 this.eventFamily = null;
1227 this.sysEventType = null;
1228 this.eventContent = null;
1229 this.avatarList.clear();
1230 this.roleList.clear();
1231 this.integerList.clear();
1232 this.charseqList.clear();
1239 * @throws HtmlParseException {@inheritDoc}
1242 public void endParse() throws HtmlParseException{
1246 // TODO 村名のチェックは不要か?