2 * daily period in village
\r
4 * License : The MIT License
\r
5 * Copyright(c) 2008 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
55 private final Village homeVillage;
\r
56 private final PeriodType periodType;
\r
57 private final int day;
\r
58 private int limitHour;
\r
59 private int limitMinute;
\r
60 // TODO 更新月日も入れるべきか。
\r
61 private String loginName;
\r
62 private boolean isFullOpen = false;
\r
64 private final List<Topic> topicList = new LinkedList<Topic>();
\r
65 private final List<Topic> unmodList =
\r
66 Collections.unmodifiableList(this.topicList);
\r
70 * この Period が進行中の村の最新日で、
\r
71 * 今まさに次々と発言が蓄積されているときは
\r
73 * ※重要: Hot な Period は meslog クエリーを使ってダウンロードできない。
\r
75 private boolean isHot;
\r
80 * この段階では発言データのロードは行われない。
\r
82 * @param homeVillage 所属するVillage
\r
83 * @param periodType Period種別
\r
84 * @param day Period通番
\r
85 * @throws java.lang.NullPointerException 引数にnullが渡された場合。
\r
87 public Period(Village homeVillage,
\r
88 PeriodType periodType,
\r
90 throws NullPointerException{
\r
91 this(homeVillage, periodType, day, false);
\r
97 * この段階では発言データのロードは行われない。
\r
98 * @param homeVillage 所属するVillage
\r
99 * @param periodType Period種別
\r
100 * @param day Period通番
\r
101 * @param isHot Hotか否か
\r
102 * @throws java.lang.NullPointerException 引数にnullが渡された場合。
\r
104 private Period(Village homeVillage,
\r
105 PeriodType periodType,
\r
108 throws NullPointerException{
\r
109 if( homeVillage == null
\r
110 || periodType == null ) throw new NullPointerException();
\r
112 throw new IllegalArgumentException("Period day is too small !");
\r
114 switch(periodType){
\r
127 this.homeVillage = homeVillage;
\r
128 this.periodType = periodType;
\r
133 this.isHot = isHot;
\r
140 * Periodを更新する。Topicのリストが更新される。
\r
142 * @param force trueなら強制再読み込み。
\r
143 * falseならまだ読み込んで無い時のみ読み込み。
\r
144 * @throws IOException ネットワーク入力エラー
\r
146 public static void parsePeriod(Period period, boolean force)
\r
147 throws IOException{
\r
148 if( ! force && period.hasLoaded() ) return;
\r
150 Village village = period.getVillage();
\r
151 Land land = village.getParentLand();
\r
152 ServerAccess server = land.getServerAccess();
\r
154 if(village.getState() != VillageState.PROGRESS){
\r
155 period.isFullOpen = true;
\r
156 }else if(period.getType() != PeriodType.PROGRESS){
\r
157 period.isFullOpen = true;
\r
159 period.isFullOpen = false;
\r
162 HtmlSequence html = server.getHTMLPeriod(period);
\r
164 period.topicList.clear();
\r
166 boolean wasHot = period.isHot();
\r
168 HANDLER.setPeriod(period);
\r
169 DecodedContent content = html.getContent();
\r
171 PARSER.parseAutomatic(content);
\r
172 }catch(HtmlParseException e){
\r
173 Jindolf.logger().warn("発言抽出に失敗", e);
\r
176 if(wasHot && ! period.isHot() ){
\r
177 parsePeriod(period, true);
\r
188 public Village getVillage(){
\r
189 return this.homeVillage;
\r
196 public PeriodType getType(){
\r
197 return this.periodType;
\r
204 * エピローグは最後のゲーム進行日+1番
\r
207 public int getDay(){
\r
213 * @return 更新時刻の文字表記
\r
215 public String getLimit(){
\r
216 StringBuilder result = new StringBuilder();
\r
218 if(this.limitHour < 10) result.append('0');
\r
219 result.append(this.limitHour).append(':');
\r
221 if(this.limitMinute < 10) result.append('0');
\r
222 result.append(this.limitMinute);
\r
224 return result.toString();
\r
231 public boolean isHot(){
\r
237 * @param isHotArg Hot指定
\r
239 public void setHot(boolean isHotArg){
\r
240 this.isHot = isHotArg;
\r
245 * @return プロローグならtrue
\r
247 public boolean isPrologue(){
\r
248 if(getType() == PeriodType.PROLOGUE) return true;
\r
254 * @return エピローグならtrue
\r
256 public boolean isEpilogue(){
\r
257 if(getType() == PeriodType.EPILOGUE) return true;
\r
263 * @return 進行日ならtrue
\r
265 public boolean isProgress(){
\r
266 if(getType() == PeriodType.PROGRESS) return true;
\r
271 * このPeriodにアクセスするためのクエリーを生成する。
\r
272 * @return CGIに渡すクエリー
\r
274 public String getCGIQuery(){
\r
275 StringBuilder result = new StringBuilder();
\r
277 Village village = getVillage();
\r
278 result.append(village.getCGIQuery());
\r
281 result.append("&mes=all"); // 全表示指定
\r
282 return result.toString();
\r
285 Land land = village.getParentLand();
\r
286 LandDef ldef = land.getLandDef();
\r
288 if(ldef.getLandId().equals("wolfg")){
\r
289 result.append("&meslog=");
\r
290 String dnum = "000" + (getDay() - 1);
\r
291 dnum = dnum.substring(dnum.length() - 3);
\r
294 result.append("000_ready");
\r
297 result.append(dnum).append("_progress");
\r
300 result.append(dnum).append("_party");
\r
307 result.append("&meslog=").append(village.getVillageID());
\r
310 result.append("_ready_0");
\r
313 result.append("_progress_").append(getDay() - 1);
\r
316 result.append("_party_").append(getDay() - 1);
\r
325 result.append("&mes=all");
\r
327 return result.toString();
\r
331 * Periodに含まれるTopicのリストを返す。
\r
333 * @return Topicのリスト
\r
335 public List<Topic> getTopicList(){
\r
336 return this.unmodList;
\r
340 * Periodに含まれるTopicの総数を返す。
\r
343 public int getTopics(){
\r
344 return this.topicList.size();
\r
349 * @param topic Topic
\r
350 * @throws java.lang.NullPointerException nullが渡された場合。
\r
352 protected void addTopic(Topic topic) throws NullPointerException{
\r
353 if(topic == null) throw new NullPointerException();
\r
354 this.topicList.add(topic);
\r
359 * Periodのキャプション文字列を返す。
\r
360 * 主な用途はタブ画面の耳のラベルなど。
\r
361 * @return キャプション文字列
\r
363 public String getCaption(){
\r
371 result = getDay() + "日目";
\r
386 * このPeriodをダウンロードしたときのログイン名を返す。
\r
387 * @return ログイン名。ログアウト中はnull。
\r
389 public String getLoginName(){
\r
390 return this.loginName;
\r
394 * 公開発言番号にマッチする発言を返す。
\r
395 * @param talkNo 公開発言番号
\r
396 * @return 発言。見つからなければnull
\r
398 public Talk getNumberedTalk(int talkNo){
\r
399 if(talkNo <= 0) throw new IllegalArgumentException();
\r
401 for(Topic topic : this.topicList){
\r
402 if( ! (topic instanceof Talk) ) continue;
\r
403 Talk talk = (Talk) topic;
\r
404 if(talkNo == talk.getTalkNo()) return talk;
\r
411 * このPeriodの内容にゲーム進行上隠された部分がある可能性を判定する。
\r
412 * @return 隠れた要素がありうるならfalse
\r
414 public boolean isFullOpen(){
\r
415 return this.isFullOpen;
\r
420 * @return ロード済みならtrue
\r
422 public boolean hasLoaded(){
\r
423 return getTopics() > 0;
\r
429 public void unload(){
\r
430 this.limitHour = 0;
\r
431 this.limitMinute = 0;
\r
432 this.loginName = null;
\r
433 this.isFullOpen = false;
\r
435 this.isHot = false;
\r
437 this.topicList.clear();
\r
444 * 決着が付くまで非狼陣営には見えない。
\r
446 * @return 襲撃メッセージがあればtrue
\r
448 public boolean hasAssaultTried(){
\r
449 for(Topic topic : this.topicList){
\r
450 if(topic instanceof Talk){
\r
451 Talk talk = (Talk) topic;
\r
452 if(talk.getTalkCount() <= 0) return true;
\r
453 }else if(topic instanceof SysEvent){
\r
454 SysEvent sysEvent = (SysEvent) topic;
\r
455 SysEventType type = sysEvent.getSysEventType();
\r
456 if(type == SysEventType.ASSAULT) return true;
\r
465 * @return 処刑されたAvatar。突然死などなんらかの理由でいない場合はnull
\r
467 public Avatar getExecutedAvatar(){
\r
468 Avatar result = null;
\r
470 for(Topic topic : getTopicList()){
\r
471 if( ! (topic instanceof SysEvent) ) continue;
\r
472 SysEvent event = (SysEvent) topic;
\r
473 result = event.getExecutedAvatar();
\r
474 if(result != null) break;
\r
481 * 投票に参加したAvatarの集合を返す。
\r
482 * @return 投票に参加したAvatarのSet
\r
484 public Set<Avatar> getVoterSet(){
\r
485 Set<Avatar> result = new HashSet<Avatar>();
\r
487 for(Topic topic : getTopicList()){
\r
488 if( ! (topic instanceof SysEvent) ) continue;
\r
489 SysEvent event = (SysEvent) topic;
\r
490 result = event.getVoterSet(result);
\r
497 * 任意のタイプのシステムイベントを返す。
\r
498 * 複数存在する場合、返すのは最初の一つだけ。
\r
499 * @param type イベントタイプ
\r
502 public SysEvent getTypedSysEvent(SysEventType type){
\r
503 for(Topic topic : getTopicList()){
\r
504 if( ! (topic instanceof SysEvent) ) continue;
\r
505 SysEvent event = (SysEvent) topic;
\r
506 if(event.getSysEventType() == type) return event;
\r
515 private static class PeriodHandler extends HtmlAdapter{
\r
517 private static final int TALKTYPE_NUM = TalkType.values().length;
\r
519 private final EntityConverter converter =
\r
520 new EntityConverter();
\r
522 private final Map<Avatar, int[]> countMap =
\r
523 new HashMap<Avatar, int[]>();
\r
525 private Period period = null;
\r
527 private TalkType talkType;
\r
528 private Avatar avatar;
\r
529 private int talkNo;
\r
530 private String anchorId;
\r
531 private int talkHour;
\r
532 private int talkMinute;
\r
533 private DecodedContent talkContent = null;
\r
535 private EventFamily eventFamily;
\r
536 private SysEventType sysEventType;
\r
537 private DecodedContent eventContent = null;
\r
538 private final List<Avatar> avatarList = new LinkedList<Avatar>();
\r
539 private final List<GameRole> roleList = new LinkedList<GameRole>();
\r
540 private final List<Integer> integerList = new LinkedList<Integer>();
\r
541 private final List<CharSequence> charseqList =
\r
542 new LinkedList<CharSequence>();
\r
547 public PeriodHandler(){
\r
553 * パース結果を格納するPeriodを設定する。
\r
554 * @param period Period
\r
556 public void setPeriod(Period period){
\r
557 this.period = period;
\r
562 * 文字列断片からAvatarを得る。
\r
563 * 村に未登録のAvatarであればついでに登録される。
\r
564 * @param content 文字列
\r
565 * @param range 文字列内のAvatarフルネームを示す領域
\r
568 private Avatar toAvatar(DecodedContent content, SeqRange range){
\r
569 Village village = this.period.getVillage();
\r
570 String fullName = this.converter
\r
571 .convert(content, range)
\r
573 Avatar result = village.getAvatar(fullName);
\r
574 if(result == null){
\r
575 result = new Avatar(fullName);
\r
576 village.addAvatar(result);
\r
583 * Avatar別、会話種ごとに発言回数をカウントする。
\r
585 * @param targetAvatar 対象Avatar
\r
586 * @param targetType 対象会話種
\r
589 private int countUp(Avatar targetAvatar, TalkType targetType){
\r
590 int[] countArray = this.countMap.get(targetAvatar);
\r
591 if(countArray == null){
\r
592 countArray = new int[TALKTYPE_NUM];
\r
593 this.countMap.put(targetAvatar, countArray);
\r
595 int count = ++countArray[targetType.ordinal()];
\r
601 * @param content {@inheritDoc}
\r
602 * @throws HtmlParseException {@inheritDoc}
\r
605 public void startParse(DecodedContent content)
\r
606 throws HtmlParseException{
\r
607 this.period.loginName = null;
\r
608 this.period.topicList.clear();
\r
609 this.countMap.clear();
\r
615 * @param content {@inheritDoc}
\r
616 * @param loginRange {@inheritDoc}
\r
617 * @throws HtmlParseException {@inheritDoc}
\r
620 public void loginName(DecodedContent content, SeqRange loginRange)
\r
621 throws HtmlParseException{
\r
622 DecodedContent loginName =
\r
623 this.converter.convert(content, loginRange);
\r
625 this.period.loginName = loginName.toString();
\r
632 * @param type {@inheritDoc}
\r
633 * @throws HtmlParseException {@inheritDoc}
\r
636 public void pageType(PageType type) throws HtmlParseException{
\r
637 if(type != PageType.PERIOD_PAGE){
\r
638 throw new HtmlParseException(
\r
639 "意図しないページを読み込もうとしました。");
\r
646 * @param month {@inheritDoc}
\r
647 * @param day {@inheritDoc}
\r
648 * @param hour {@inheritDoc}
\r
649 * @param minute {@inheritDoc}
\r
650 * @throws HtmlParseException {@inheritDoc}
\r
653 public void commitTime(int month, int day, int hour, int minute)
\r
654 throws HtmlParseException{
\r
655 this.period.limitHour = hour;
\r
656 this.period.limitMinute = minute;
\r
662 * 自分へのリンクが無いかチェックする。
\r
663 * 自分へのリンクが見つかればこのPeriodを非Hotにする。
\r
664 * 自分へのリンクがあるということは、
\r
665 * 今読んでるHTMLは別のPeriodのために書かれたものということ。
\r
666 * 考えられる原因は、HotだったPeriodがゲーム進行に従い
\r
668 * @param content {@inheritDoc}
\r
669 * @param anchorRange {@inheritDoc}
\r
670 * @param periodType {@inheritDoc}
\r
671 * @param day {@inheritDoc}
\r
672 * @throws HtmlParseException {@inheritDoc}
\r
675 public void periodLink(DecodedContent content,
\r
676 SeqRange anchorRange,
\r
677 PeriodType periodType,
\r
679 throws HtmlParseException{
\r
681 if(this.period.getType() != periodType) return;
\r
683 if( periodType == PeriodType.PROGRESS
\r
684 && this.period.getDay() != day ){
\r
688 if( ! anchorRange.isValid() ) return;
\r
690 this.period.setHot(false);
\r
697 * @throws HtmlParseException {@inheritDoc}
\r
700 public void startTalk() throws HtmlParseException{
\r
701 this.talkType = null;
\r
702 this.avatar = null;
\r
704 this.anchorId = null;
\r
705 this.talkHour = -1;
\r
706 this.talkMinute = -1;
\r
707 this.talkContent = new DecodedContent(100 + 1);
\r
714 * @param type {@inheritDoc}
\r
715 * @throws HtmlParseException {@inheritDoc}
\r
718 public void talkType(TalkType type)
\r
719 throws HtmlParseException{
\r
720 this.talkType = type;
\r
726 * @param content {@inheritDoc}
\r
727 * @param avatarRange {@inheritDoc}
\r
728 * @throws HtmlParseException {@inheritDoc}
\r
731 public void talkAvatar(DecodedContent content, SeqRange avatarRange)
\r
732 throws HtmlParseException{
\r
733 this.avatar = toAvatar(content, avatarRange);
\r
739 * @param hour {@inheritDoc}
\r
740 * @param minute {@inheritDoc}
\r
741 * @throws HtmlParseException {@inheritDoc}
\r
744 public void talkTime(int hour, int minute)
\r
745 throws HtmlParseException{
\r
746 this.talkHour = hour;
\r
747 this.talkMinute = minute;
\r
753 * @param tno {@inheritDoc}
\r
754 * @throws HtmlParseException {@inheritDoc}
\r
757 public void talkNo(int tno) throws HtmlParseException{
\r
764 * @param content {@inheritDoc}
\r
765 * @param idRange {@inheritDoc}
\r
766 * @throws HtmlParseException {@inheritDoc}
\r
769 public void talkId(DecodedContent content, SeqRange idRange)
\r
770 throws HtmlParseException{
\r
771 this.anchorId = content.subSequence(idRange.getStartPos(),
\r
772 idRange.getEndPos() )
\r
779 * @param content {@inheritDoc}
\r
780 * @param textRange {@inheritDoc}
\r
781 * @throws HtmlParseException {@inheritDoc}
\r
784 public void talkText(DecodedContent content, SeqRange textRange)
\r
785 throws HtmlParseException{
\r
786 this.converter.append(this.talkContent, content, textRange);
\r
792 * @throws HtmlParseException {@inheritDoc}
\r
795 public void talkBreak()
\r
796 throws HtmlParseException{
\r
797 this.talkContent.append('\n');
\r
803 * @throws HtmlParseException {@inheritDoc}
\r
806 public void endTalk() throws HtmlParseException{
\r
807 Talk talk = new Talk(this.period,
\r
812 this.talkHour, this.talkMinute,
\r
813 this.talkContent );
\r
815 int count = countUp(this.avatar, this.talkType);
\r
816 talk.setCount(count);
\r
818 this.period.addTopic(talk);
\r
820 this.talkType = null;
\r
821 this.avatar = null;
\r
823 this.anchorId = null;
\r
824 this.talkHour = -1;
\r
825 this.talkMinute = -1;
\r
826 this.talkContent = null;
\r
833 * @param family {@inheritDoc}
\r
834 * @throws HtmlParseException {@inheritDoc}
\r
837 public void startSysEvent(EventFamily family)
\r
838 throws HtmlParseException{
\r
839 this.eventFamily = family;
\r
840 this.sysEventType = null;
\r
841 this.eventContent = new DecodedContent();
\r
842 this.avatarList.clear();
\r
843 this.roleList.clear();
\r
844 this.integerList.clear();
\r
845 this.charseqList.clear();
\r
851 * @param type {@inheritDoc}
\r
852 * @throws HtmlParseException {@inheritDoc}
\r
855 public void sysEventType(SysEventType type)
\r
856 throws HtmlParseException{
\r
857 this.sysEventType = type;
\r
863 * @param content {@inheritDoc}
\r
864 * @param contentRange {@inheritDoc}
\r
865 * @throws HtmlParseException {@inheritDoc}
\r
868 public void sysEventContent(DecodedContent content,
\r
869 SeqRange contentRange)
\r
870 throws HtmlParseException{
\r
871 this.converter.append(this.eventContent, content, contentRange);
\r
877 * @param content {@inheritDoc}
\r
878 * @param anchorRange {@inheritDoc}
\r
879 * @param contentRange {@inheritDoc}
\r
880 * @throws HtmlParseException {@inheritDoc}
\r
883 public void sysEventContentAnchor(DecodedContent content,
\r
884 SeqRange anchorRange,
\r
885 SeqRange contentRange)
\r
886 throws HtmlParseException{
\r
887 this.converter.append(this.eventContent, content, contentRange);
\r
893 * @throws HtmlParseException {@inheritDoc}
\r
896 public void sysEventContentBreak() throws HtmlParseException{
\r
897 this.eventContent.append('\n');
\r
903 * @param content {@inheritDoc}
\r
904 * @param entryNo {@inheritDoc}
\r
905 * @param avatarRange {@inheritDoc}
\r
906 * @throws HtmlParseException {@inheritDoc}
\r
909 public void sysEventOnStage(DecodedContent content,
\r
911 SeqRange avatarRange)
\r
912 throws HtmlParseException{
\r
913 Avatar newAvatar = toAvatar(content, avatarRange);
\r
914 this.integerList.add(entryNo);
\r
915 this.avatarList.add(newAvatar);
\r
921 * @param role {@inheritDoc}
\r
922 * @param num {@inheritDoc}
\r
923 * @throws HtmlParseException {@inheritDoc}
\r
926 public void sysEventOpenRole(GameRole role, int num)
\r
927 throws HtmlParseException{
\r
928 this.roleList.add(role);
\r
929 this.integerList.add(num);
\r
935 * @param content {@inheritDoc}
\r
936 * @param avatarRange {@inheritDoc}
\r
937 * @throws HtmlParseException {@inheritDoc}
\r
940 public void sysEventMurdered(DecodedContent content,
\r
941 SeqRange avatarRange)
\r
942 throws HtmlParseException{
\r
943 Avatar murdered = toAvatar(content, avatarRange);
\r
944 this.avatarList.add(murdered);
\r
950 * @param content {@inheritDoc}
\r
951 * @param avatarRange {@inheritDoc}
\r
952 * @throws HtmlParseException {@inheritDoc}
\r
955 public void sysEventSurvivor(DecodedContent content,
\r
956 SeqRange avatarRange)
\r
957 throws HtmlParseException{
\r
958 Avatar survivor = toAvatar(content, avatarRange);
\r
959 this.avatarList.add(survivor);
\r
965 * @param content {@inheritDoc}
\r
966 * @param voteByRange {@inheritDoc}
\r
967 * @param voteToRange {@inheritDoc}
\r
968 * @throws HtmlParseException {@inheritDoc}
\r
971 public void sysEventCounting(DecodedContent content,
\r
972 SeqRange voteByRange,
\r
973 SeqRange voteToRange)
\r
974 throws HtmlParseException{
\r
975 if(voteByRange.isValid()){
\r
976 Avatar voteBy = toAvatar(content, voteByRange);
\r
977 this.avatarList.add(voteBy);
\r
979 Avatar voteTo = toAvatar(content, voteToRange);
\r
980 this.avatarList.add(voteTo);
\r
986 * @param content {@inheritDoc}
\r
987 * @param voteByRange {@inheritDoc}
\r
988 * @param voteToRange {@inheritDoc}
\r
989 * @throws HtmlParseException {@inheritDoc}
\r
992 public void sysEventCounting2(DecodedContent content,
\r
993 SeqRange voteByRange,
\r
994 SeqRange voteToRange)
\r
995 throws HtmlParseException{
\r
996 sysEventCounting(content, voteByRange, voteToRange);
\r
1002 * @param content {@inheritDoc}
\r
1003 * @param avatarRange {@inheritDoc}
\r
1004 * @throws HtmlParseException {@inheritDoc}
\r
1007 public void sysEventSuddenDeath(DecodedContent content,
\r
1008 SeqRange avatarRange)
\r
1009 throws HtmlParseException{
\r
1010 Avatar suddenDeath = toAvatar(content, avatarRange);
\r
1011 this.avatarList.add(suddenDeath);
\r
1017 * @param content {@inheritDoc}
\r
1018 * @param avatarRange {@inheritDoc}
\r
1019 * @param anchorRange {@inheritDoc}
\r
1020 * @param loginRange {@inheritDoc}
\r
1021 * @param isLiving {@inheritDoc}
\r
1022 * @param role {@inheritDoc}
\r
1023 * @throws HtmlParseException {@inheritDoc}
\r
1026 public void sysEventPlayerList(DecodedContent content,
\r
1027 SeqRange avatarRange,
\r
1028 SeqRange anchorRange,
\r
1029 SeqRange loginRange,
\r
1032 throws HtmlParseException{
\r
1033 Avatar who = toAvatar(content, avatarRange);
\r
1035 CharSequence anchor;
\r
1036 if(anchorRange.isValid()){
\r
1037 anchor = this.converter.convert(content, anchorRange);
\r
1041 CharSequence account = this.converter
\r
1042 .convert(content, loginRange);
\r
1044 Integer liveOrDead;
\r
1045 if(isLiving) liveOrDead = Integer.valueOf(1);
\r
1046 else liveOrDead = Integer.valueOf(0);
\r
1048 this.avatarList.add(who);
\r
1049 this.charseqList.add(anchor);
\r
1050 this.charseqList.add(account);
\r
1051 this.integerList.add(liveOrDead);
\r
1052 this.roleList.add(role);
\r
1059 * @param content {@inheritDoc}
\r
1060 * @param avatarRange {@inheritDoc}
\r
1061 * @param votes {@inheritDoc}
\r
1062 * @throws HtmlParseException {@inheritDoc}
\r
1065 public void sysEventExecution(DecodedContent content,
\r
1066 SeqRange avatarRange,
\r
1068 throws HtmlParseException{
\r
1069 Avatar who = toAvatar(content, avatarRange);
\r
1071 this.avatarList.add(who);
\r
1072 this.integerList.add(votes);
\r
1079 * @param hour {@inheritDoc}
\r
1080 * @param minute {@inheritDoc}
\r
1081 * @param minLimit {@inheritDoc}
\r
1082 * @param maxLimit {@inheritDoc}
\r
1083 * @throws HtmlParseException {@inheritDoc}
\r
1086 public void sysEventAskEntry(int hour, int minute,
\r
1087 int minLimit, int maxLimit)
\r
1088 throws HtmlParseException{
\r
1089 this.integerList.add(hour * 60 + minute);
\r
1090 this.integerList.add(minLimit);
\r
1091 this.integerList.add(maxLimit);
\r
1097 * @param hour {@inheritDoc}
\r
1098 * @param minute {@inheritDoc}
\r
1099 * @throws HtmlParseException {@inheritDoc}
\r
1102 public void sysEventAskCommit(int hour, int minute)
\r
1103 throws HtmlParseException{
\r
1104 this.integerList.add(hour * 60 + minute);
\r
1110 * @param content {@inheritDoc}
\r
1111 * @param avatarRange {@inheritDoc}
\r
1112 * @throws HtmlParseException {@inheritDoc}
\r
1115 public void sysEventNoComment(DecodedContent content,
\r
1116 SeqRange avatarRange)
\r
1117 throws HtmlParseException{
\r
1118 Avatar noComAvatar = toAvatar(content, avatarRange);
\r
1119 this.avatarList.add(noComAvatar);
\r
1125 * @param winner {@inheritDoc}
\r
1126 * @param hour {@inheritDoc}
\r
1127 * @param minute {@inheritDoc}
\r
1128 * @throws HtmlParseException {@inheritDoc}
\r
1131 public void sysEventStayEpilogue(Team winner, int hour, int minute)
\r
1132 throws HtmlParseException{
\r
1133 GameRole role = null;
\r
1136 case VILLAGE: role = GameRole.INNOCENT; break;
\r
1137 case WOLF: role = GameRole.WOLF; break;
\r
1138 case HAMSTER: role = GameRole.HAMSTER; break;
\r
1139 default: assert false; break;
\r
1142 this.roleList.add(role);
\r
1143 this.integerList.add(hour * 60 + minute);
\r
1150 * @param content {@inheritDoc}
\r
1151 * @param guardByRange {@inheritDoc}
\r
1152 * @param guardToRange {@inheritDoc}
\r
1153 * @throws HtmlParseException {@inheritDoc}
\r
1156 public void sysEventGuard(DecodedContent content,
\r
1157 SeqRange guardByRange,
\r
1158 SeqRange guardToRange)
\r
1159 throws HtmlParseException{
\r
1160 Avatar guardBy = toAvatar(content, guardByRange);
\r
1161 Avatar guardTo = toAvatar(content, guardToRange);
\r
1162 this.avatarList.add(guardBy);
\r
1163 this.avatarList.add(guardTo);
\r
1169 * @param content {@inheritDoc}
\r
1170 * @param judgeByRange {@inheritDoc}
\r
1171 * @param judgeToRange {@inheritDoc}
\r
1172 * @throws HtmlParseException {@inheritDoc}
\r
1175 public void sysEventJudge(DecodedContent content,
\r
1176 SeqRange judgeByRange,
\r
1177 SeqRange judgeToRange)
\r
1178 throws HtmlParseException{
\r
1179 Avatar judgeBy = toAvatar(content, judgeByRange);
\r
1180 Avatar judgeTo = toAvatar(content, judgeToRange);
\r
1181 this.avatarList.add(judgeBy);
\r
1182 this.avatarList.add(judgeTo);
\r
1188 * @throws HtmlParseException {@inheritDoc}
\r
1191 public void endSysEvent() throws HtmlParseException{
\r
1192 SysEvent event = new SysEvent();
\r
1193 event.setEventFamily(this.eventFamily);
\r
1194 event.setSysEventType(this.sysEventType);
\r
1195 event.setContent(this.eventContent);
\r
1196 event.addAvatarList(this.avatarList);
\r
1197 event.addRoleList(this.roleList);
\r
1198 event.addIntegerList(this.integerList);
\r
1199 event.addCharSequenceList(this.charseqList);
\r
1201 this.period.addTopic(event);
\r
1203 if( this.sysEventType == SysEventType.MURDERED
\r
1204 || this.sysEventType == SysEventType.NOMURDER ){
\r
1205 for(Topic topic : this.period.topicList){
\r
1206 if( ! (topic instanceof Talk) ) continue;
\r
1207 Talk talk = (Talk) topic;
\r
1208 if(talk.getTalkType() != TalkType.WOLFONLY) continue;
\r
1210 .isTerminated(talk.getDialog(),
\r
1211 "!\u0020今日がお前の命日だ!") ){
\r
1214 talk.setCount(-1);
\r
1215 this.countMap.clear();
\r
1219 this.eventFamily = null;
\r
1220 this.sysEventType = null;
\r
1221 this.eventContent = null;
\r
1222 this.avatarList.clear();
\r
1223 this.roleList.clear();
\r
1224 this.integerList.clear();
\r
1225 this.charseqList.clear();
\r
1232 * @throws HtmlParseException {@inheritDoc}
\r
1235 public void endParse() throws HtmlParseException{
\r
1239 // TODO 村名のチェックは不要か?
\r