4 * License : The MIT License
5 * Copyright(c) 2008 olyutorskii
8 package jp.sourceforge.jindolf.archiver;
10 import java.util.regex.Matcher;
11 import java.util.regex.Pattern;
12 import jp.osdn.jindolf.parser.EntityConverter;
13 import jp.osdn.jindolf.parser.HtmlAdapter;
14 import jp.osdn.jindolf.parser.HtmlParseException;
15 import jp.osdn.jindolf.parser.PageType;
16 import jp.osdn.jindolf.parser.SeqRange;
17 import jp.osdn.jindolf.parser.content.DecodedContent;
18 import jp.sourceforge.jindolf.corelib.DisclosureType;
19 import jp.sourceforge.jindolf.corelib.EventFamily;
20 import jp.sourceforge.jindolf.corelib.GameRole;
21 import jp.sourceforge.jindolf.corelib.LandDef;
22 import jp.sourceforge.jindolf.corelib.PeriodType;
23 import jp.sourceforge.jindolf.corelib.SysEventType;
24 import jp.sourceforge.jindolf.corelib.TalkType;
25 import jp.sourceforge.jindolf.corelib.Team;
26 import jp.sourceforge.jindolf.corelib.VillageTag;
31 public class Handler extends HtmlAdapter{
33 private static final Pattern MURDER_PATTERN =
34 Pattern.compile("^(.*)\u0020!\u0020今日がお前の命日だ!$");
36 private final EntityConverter converter = new EntityConverter();
38 private VillageData villageData = null;
39 private String pageTitle = null;
41 private PeriodData currentPeriod = null;
42 private PeriodResource currentResource = null;
44 private TalkData currentTalk = null;
45 private EventData currentEvent = null;
57 * @param villageDataArg 村情報
59 public void initVillageData(VillageData villageDataArg){
60 this.villageData = villageDataArg;
61 this.currentPeriod = null;
62 this.pageTitle = null;
68 * @param resource リソース情報
70 public void initPeriodResource(PeriodResource resource){
71 this.currentResource = resource;
77 * @param content {@inheritDoc}
78 * @throws HtmlParseException {@inheritDoc}
81 public void startParse(DecodedContent content) throws HtmlParseException{
82 if(this.villageData == null) throw new HtmlParseException();
84 new PeriodData(this.villageData, this.currentResource);
90 * @param content {@inheritDoc}
91 * @param titleRange {@inheritDoc}
92 * @throws HtmlParseException {@inheritDoc}
95 public void pageTitle(DecodedContent content, SeqRange titleRange)
96 throws HtmlParseException{
97 DecodedContent title = this.converter.convert(content, titleRange);
98 if(this.pageTitle == null){
99 this.pageTitle = title.toString();
101 if( ! this.pageTitle.contentEquals(title) ){
102 throw new HtmlParseException();
110 * @param content {@inheritDoc}
111 * @param loginRange {@inheritDoc}
112 * @throws HtmlParseException {@inheritDoc}
115 public void loginName(DecodedContent content, SeqRange loginRange)
116 throws HtmlParseException{
117 DecodedContent account = this.converter.convert(content, loginRange);
118 this.currentPeriod.setLoginName(account);
124 * @param type {@inheritDoc}
125 * @throws HtmlParseException {@inheritDoc}
128 public void pageType(PageType type) throws HtmlParseException{
129 if(type != PageType.PERIOD_PAGE) throw new HtmlParseException();
135 * @param content {@inheritDoc}
136 * @param villageRange {@inheritDoc}
137 * @throws HtmlParseException {@inheritDoc}
140 public void villageName(DecodedContent content, SeqRange villageRange)
141 throws HtmlParseException{
143 this.converter.convert(content, villageRange).toString();
144 String fullName = this.villageData.getFullName();
145 if(fullName.length() <= 0){
146 if( ! this.pageTitle.endsWith(vName) ){
147 throw new HtmlParseException();
149 Pattern ptn = Pattern.compile("^([^0-9]*)([0-9]+)\\s+(\\S+)$");
150 Matcher matcher = ptn.matcher(vName);
151 if( ! matcher.matches() ) throw new HtmlParseException();
152 String prefix = matcher.group(1);
153 String vid = matcher.group(2);
154 String vtag = matcher.group(3);
155 LandDef landDef = this.villageData.getLandDef();
156 if( ! prefix.equals(landDef.getLandPrefix()) ){
157 throw new HtmlParseException();
159 if( Integer.parseInt(vid) != this.villageData.getVillageId() ){
160 throw new HtmlParseException();
163 if(VillageTag.lookingAtVillageTag(matcher) == null){
164 throw new HtmlParseException();
166 this.villageData.setFullName(vName);
168 if( ! vName.equals(fullName) ) throw new HtmlParseException();
176 * @param month {@inheritDoc}
177 * @param day {@inheritDoc}
178 * @param hour {@inheritDoc}
179 * @param minute {@inheritDoc}
180 * @throws HtmlParseException {@inheritDoc}
183 public void commitTime(int month, int day, int hour, int minute)
184 throws HtmlParseException{
185 int commitHour = this.villageData.getCommitHour();
186 int commitMinute = this.villageData.getCommitMinute();
189 this.villageData.setCommitHour(hour);
191 if(hour != commitHour) throw new HtmlParseException();
194 if(commitMinute < 0){
195 this.villageData.setCommitMinute(minute);
197 if(minute != commitMinute) throw new HtmlParseException();
200 this.currentPeriod.setCommitMonth(month);
201 this.currentPeriod.setCommitDay(day);
202 this.currentPeriod.setCommitHour(hour);
203 this.currentPeriod.setCommitMinute(minute);
210 * @param content {@inheritDoc}
211 * @param anchorRange {@inheritDoc}
212 * @param periodType {@inheritDoc}
213 * @param day {@inheritDoc}
214 * @throws HtmlParseException {@inheritDoc}
217 public void periodLink(DecodedContent content,
218 SeqRange anchorRange,
219 PeriodType periodType,
221 throws HtmlParseException{
222 if(anchorRange.isValid()){
223 DisclosureType newType;
225 if(periodType == null){
226 newType = DisclosureType.COMPLETE;
227 }else if( periodType == PeriodType.EPILOGUE
228 && this.currentResource.getPeriodType()
229 != PeriodType.EPILOGUE){
230 newType = DisclosureType.COMPLETE;
231 }else if( periodType != PeriodType.PROLOGUE
232 && this.currentResource.getPeriodType()
233 == PeriodType.PROLOGUE){
234 newType = DisclosureType.COMPLETE;
236 newType = DisclosureType.UNCOMPLETE;
239 this.currentPeriod.setDisclosureType(newType);
244 if(periodType != this.currentResource.getPeriodType()){
245 throw new HtmlParseException();
248 if(periodType == PeriodType.PROGRESS
249 && day != this.currentResource.getDay()){
250 throw new HtmlParseException();
253 this.currentPeriod.setDisclosureType(DisclosureType.HOT);
260 * @throws HtmlParseException {@inheritDoc}
263 public void startTalk() throws HtmlParseException{
264 this.currentTalk = new TalkData();
270 * @param content {@inheritDoc}
271 * @param avatarRange {@inheritDoc}
272 * @throws HtmlParseException {@inheritDoc}
275 public void talkAvatar(DecodedContent content, SeqRange avatarRange)
276 throws HtmlParseException{
277 DecodedContent avatarName =
278 this.converter.convert(content, avatarRange);
279 AvatarData avatar = this.villageData.getAvatarData(avatarName);
280 this.currentTalk.setAvatarData(avatar);
286 * @param content {@inheritDoc}
287 * @param urlRange {@inheritDoc}
288 * @throws HtmlParseException {@inheritDoc}
291 public void talkIconUrl(DecodedContent content, SeqRange urlRange)
292 throws HtmlParseException{
293 DecodedContent faceIcon = this.converter.convert(content, urlRange);
294 this.currentTalk.setFaceIconUri(faceIcon.toString());
300 * @param content {@inheritDoc}
301 * @param idRange {@inheritDoc}
302 * @throws HtmlParseException {@inheritDoc}
305 public void talkId(DecodedContent content, SeqRange idRange)
306 throws HtmlParseException{
307 DecodedContent xname = this.converter.convert(content, idRange);
308 this.currentTalk.setXName(xname.toString());
314 * @param hour {@inheritDoc}
315 * @param minute {@inheritDoc}
316 * @throws HtmlParseException {@inheritDoc}
319 public void talkTime(int hour, int minute) throws HtmlParseException{
320 this.currentTalk.setHour(hour);
321 this.currentTalk.setMinute(minute);
327 * @param type {@inheritDoc}
328 * @throws HtmlParseException {@inheritDoc}
331 public void talkType(TalkType type) throws HtmlParseException{
332 this.currentTalk.setTalkType(type);
338 * @param content {@inheritDoc}
339 * @param textRange {@inheritDoc}
340 * @throws HtmlParseException {@inheritDoc}
343 public void talkText(DecodedContent content, SeqRange textRange)
344 throws HtmlParseException{
345 DecodedContent line = this.converter.convert(content, textRange);
346 this.currentTalk.addLine(line);
352 * @throws HtmlParseException {@inheritDoc}
355 public void talkBreak() throws HtmlParseException{
356 this.currentTalk.addBreak();
362 * @throws HtmlParseException {@inheritDoc}
365 public void endTalk() throws HtmlParseException{
366 String faceIcon = this.currentTalk.getFaceIconUri();
367 if(this.currentTalk.getTalkType() == TalkType.GRAVE){
368 this.villageData.setGraveIconUri(faceIcon);
370 AvatarData avatar = this.currentTalk.getAvatarData();
371 if(avatar.getFaceIconUri() == null){
372 avatar.setFaceIconUri(faceIcon);
376 TalkType currentTalkType = this.currentTalk.getTalkType();
377 int talkLineNum = this.currentTalk.getLineNum();
379 boolean hasNotMurder = ! this.currentPeriod.hasMurderResult();
380 boolean isWolfTalk = currentTalkType == TalkType.WOLFONLY;
381 boolean isOneLineTalk = talkLineNum == 1;
383 boolean maybeAssaultEvent =
384 hasNotMurder && isWolfTalk && isOneLineTalk;
386 if(maybeAssaultEvent){
387 DecodedContent line1st = this.currentTalk.get1stLine();
388 Matcher matcher = MURDER_PATTERN.matcher(line1st);
389 if(matcher.matches()){
390 String avatarName = matcher.group(1);
392 this.villageData.getAvatarData(avatarName);
393 EventData event = buildAssaultEvent(target);
394 this.currentPeriod.addTopicData(event);
395 this.currentTalk = null;
400 this.currentPeriod.addTopicData(this.currentTalk);
401 this.currentTalk = null;
410 private EventData buildAssaultEvent(AvatarData target){
411 DecodedContent line1st = this.currentTalk.get1stLine();
413 String xname = this.currentTalk.getXName();
415 int hour = this.currentTalk.getHour();
416 int minute = this.currentTalk.getMinute();
418 AvatarData byWhom = this.currentTalk.getAvatarData();
419 String iconUri = this.currentTalk.getFaceIconUri();
420 if(byWhom.getFaceIconUri() == null){
421 byWhom.setFaceIconUri(iconUri);
424 EventData event = new EventData();
426 event.setEventType(SysEventType.ASSAULT);
427 event.addLine(line1st);
428 event.addAvatarData(byWhom);
429 event.addAvatarData(target);
430 event.addDecodedContent(new DecodedContent(xname));
431 event.addInteger(hour);
432 event.addInteger(minute);
433 event.addDecodedContent(new DecodedContent(iconUri));
440 * @param eventFamily {@inheritDoc}
441 * @throws HtmlParseException {@inheritDoc}
444 public void startSysEvent(EventFamily eventFamily)
445 throws HtmlParseException{
446 this.currentEvent = new EventData();
452 * @param type {@inheritDoc}
453 * @throws HtmlParseException {@inheritDoc}
456 public void sysEventType(SysEventType type) throws HtmlParseException{
457 this.currentEvent.setEventType(type);
463 * @param content {@inheritDoc}
464 * @param contentRange {@inheritDoc}
465 * @throws HtmlParseException {@inheritDoc}
468 public void sysEventContent(DecodedContent content,
469 SeqRange contentRange)
470 throws HtmlParseException{
471 DecodedContent line = this.converter.convert(content, contentRange);
472 this.currentEvent.addLine(line);
478 * @param content {@inheritDoc}
479 * @param anchorRange {@inheritDoc}
480 * @param contentRange {@inheritDoc}
481 * @throws HtmlParseException {@inheritDoc}
484 public void sysEventContentAnchor(DecodedContent content,
485 SeqRange anchorRange,
486 SeqRange contentRange)
487 throws HtmlParseException{
488 DecodedContent line = this.converter.convert(content, contentRange);
489 this.currentEvent.addLine(line);
495 * @throws HtmlParseException {@inheritDoc}
498 public void sysEventContentBreak() throws HtmlParseException{
499 this.currentEvent.addBreak();
505 * @param content {@inheritDoc}
506 * @param entryNo {@inheritDoc}
507 * @param avatarRange {@inheritDoc}
508 * @throws HtmlParseException {@inheritDoc}
511 public void sysEventOnStage(DecodedContent content,
513 SeqRange avatarRange)
514 throws HtmlParseException{
515 DecodedContent avatarName =
516 this.converter.convert(content, avatarRange);
517 AvatarData avatar = this.villageData.getAvatarData(avatarName);
518 this.currentEvent.addAvatarData(avatar);
519 this.currentEvent.addInteger(entryNo);
525 * @param role {@inheritDoc}
526 * @param num {@inheritDoc}
527 * @throws HtmlParseException {@inheritDoc}
530 public void sysEventOpenRole(GameRole role, int num)
531 throws HtmlParseException{
532 this.currentEvent.addGameRole(role);
533 this.currentEvent.addInteger(num);
539 * @param content {@inheritDoc}
540 * @param avatarRange {@inheritDoc}
541 * @throws HtmlParseException {@inheritDoc}
544 public void sysEventMurdered(DecodedContent content,
545 SeqRange avatarRange)
546 throws HtmlParseException{
547 DecodedContent avatarName =
548 this.converter.convert(content, avatarRange);
549 AvatarData avatar = this.villageData.getAvatarData(avatarName);
550 this.currentEvent.addAvatarData(avatar);
556 * @param content {@inheritDoc}
557 * @param avatarRange {@inheritDoc}
558 * @throws HtmlParseException {@inheritDoc}
561 public void sysEventSurvivor(DecodedContent content,
562 SeqRange avatarRange)
563 throws HtmlParseException{
564 DecodedContent avatarName =
565 this.converter.convert(content, avatarRange);
566 AvatarData avatar = this.villageData.getAvatarData(avatarName);
567 this.currentEvent.addAvatarData(avatar);
573 * @param content {@inheritDoc}
574 * @param voteByRange {@inheritDoc}
575 * @param voteToRange {@inheritDoc}
576 * @throws HtmlParseException {@inheritDoc}
579 public void sysEventCounting(DecodedContent content,
580 SeqRange voteByRange,
581 SeqRange voteToRange)
582 throws HtmlParseException{
585 if(voteByRange.isValid()){
586 DecodedContent voteBy =
587 this.converter.convert(content, voteByRange);
588 avatar = this.villageData.getAvatarData(voteBy);
589 this.currentEvent.addAvatarData(avatar);
592 DecodedContent voteTo =
593 this.converter.convert(content, voteToRange);
594 avatar = this.villageData.getAvatarData(voteTo);
595 this.currentEvent.addAvatarData(avatar);
602 * @param content {@inheritDoc}
603 * @param voteByRange {@inheritDoc}
604 * @param voteToRange {@inheritDoc}
605 * @throws HtmlParseException {@inheritDoc}
608 public void sysEventCounting2(DecodedContent content,
609 SeqRange voteByRange,
610 SeqRange voteToRange)
611 throws HtmlParseException{
614 DecodedContent voteBy =
615 this.converter.convert(content, voteByRange);
616 avatar = this.villageData.getAvatarData(voteBy);
617 this.currentEvent.addAvatarData(avatar);
619 DecodedContent voteTo =
620 this.converter.convert(content, voteToRange);
621 avatar = this.villageData.getAvatarData(voteTo);
622 this.currentEvent.addAvatarData(avatar);
629 * @param content {@inheritDoc}
630 * @param avatarRange {@inheritDoc}
631 * @throws HtmlParseException {@inheritDoc}
634 public void sysEventSuddenDeath(DecodedContent content,
635 SeqRange avatarRange)
636 throws HtmlParseException{
637 DecodedContent avatarName =
638 this.converter.convert(content, avatarRange);
639 AvatarData avatar = this.villageData.getAvatarData(avatarName);
640 this.currentEvent.addAvatarData(avatar);
646 * @param content {@inheritDoc}
647 * @param avatarRange {@inheritDoc}
648 * @param anchorRange {@inheritDoc}
649 * @param loginRange {@inheritDoc}
650 * @param isLiving {@inheritDoc}
651 * @param role {@inheritDoc}
652 * @throws HtmlParseException {@inheritDoc}
655 public void sysEventPlayerList(DecodedContent content,
656 SeqRange avatarRange,
657 SeqRange anchorRange,
661 throws HtmlParseException{
662 DecodedContent avatarName =
663 this.converter.convert(content, avatarRange);
664 AvatarData avatar = this.villageData.getAvatarData(avatarName);
665 this.currentEvent.addAvatarData(avatar);
668 if(anchorRange.isValid()){
669 uri = this.converter.convert(content, anchorRange);
671 uri = new DecodedContent("");
673 Win31j.supplyWin31jChar(uri);
674 this.currentEvent.addDecodedContent(uri);
676 DecodedContent account =
677 this.converter.convert(content, loginRange);
678 Win31j.supplyWin31jChar(account);
679 this.currentEvent.addDecodedContent(account);
681 if(isLiving) this.currentEvent.addInteger(1);
682 else this.currentEvent.addInteger(0);
684 this.currentEvent.addGameRole(role);
691 * @param hour {@inheritDoc}
692 * @param minute {@inheritDoc}
693 * @param minLimit {@inheritDoc}
694 * @param maxLimit {@inheritDoc}
695 * @throws HtmlParseException {@inheritDoc}
698 public void sysEventAskEntry(int hour, int minute,
699 int minLimit, int maxLimit)
700 throws HtmlParseException{
701 this.currentEvent.addInteger(hour);
702 this.currentEvent.addInteger(minute);
703 this.currentEvent.addInteger(minLimit);
704 this.currentEvent.addInteger(maxLimit);
710 * @param hour {@inheritDoc}
711 * @param minute {@inheritDoc}
712 * @throws HtmlParseException {@inheritDoc}
715 public void sysEventAskCommit(int hour, int minute)
716 throws HtmlParseException{
717 this.currentEvent.addInteger(hour);
718 this.currentEvent.addInteger(minute);
724 * @param content {@inheritDoc}
725 * @param avatarRange {@inheritDoc}
726 * @throws HtmlParseException {@inheritDoc}
729 public void sysEventNoComment(DecodedContent content,
730 SeqRange avatarRange)
731 throws HtmlParseException{
732 DecodedContent avatarName;
733 avatarName = this.converter.convert(content, avatarRange);
734 AvatarData avatar = this.villageData.getAvatarData(avatarName);
735 this.currentEvent.addAvatarData(avatar);
741 * @param winner {@inheritDoc}
742 * @param hour {@inheritDoc}
743 * @param minute {@inheritDoc}
744 * @throws HtmlParseException {@inheritDoc}
747 public void sysEventStayEpilogue(Team winner,
748 int hour, int minute)
749 throws HtmlParseException{
752 case VILLAGE: role = GameRole.INNOCENT; break;
753 case WOLF: role = GameRole.WOLF; break;
754 case HAMSTER: role = GameRole.HAMSTER; break;
755 default: throw new IllegalArgumentException();
758 this.currentEvent.addGameRole(role);
759 this.currentEvent.addInteger(hour);
760 this.currentEvent.addInteger(minute);
767 * @param content {@inheritDoc}
768 * @param guardByRange {@inheritDoc}
769 * @param guardToRange {@inheritDoc}
770 * @throws HtmlParseException {@inheritDoc}
773 public void sysEventGuard(DecodedContent content,
774 SeqRange guardByRange,
775 SeqRange guardToRange)
776 throws HtmlParseException{
777 DecodedContent avatarName;
779 avatarName = this.converter.convert(content, guardByRange);
780 AvatarData guardBy = this.villageData.getAvatarData(avatarName);
781 this.currentEvent.addAvatarData(guardBy);
783 avatarName = this.converter.convert(content, guardToRange);
784 AvatarData guardTo = this.villageData.getAvatarData(avatarName);
785 this.currentEvent.addAvatarData(guardTo);
792 * @param content {@inheritDoc}
793 * @param judgeByRange {@inheritDoc}
794 * @param judgeToRange {@inheritDoc}
795 * @throws HtmlParseException {@inheritDoc}
798 public void sysEventJudge(DecodedContent content,
799 SeqRange judgeByRange,
800 SeqRange judgeToRange)
801 throws HtmlParseException{
802 DecodedContent avatarName;
804 avatarName = this.converter.convert(content, judgeByRange);
805 AvatarData judgeBy = this.villageData.getAvatarData(avatarName);
806 this.currentEvent.addAvatarData(judgeBy);
808 avatarName = this.converter.convert(content, judgeToRange);
809 AvatarData judgeTo = this.villageData.getAvatarData(avatarName);
810 this.currentEvent.addAvatarData(judgeTo);
817 * @param content {@inheritDoc}
818 * @param avatarRange {@inheritDoc}
819 * @param votes {@inheritDoc}
820 * @throws HtmlParseException {@inheritDoc}
823 public void sysEventExecution(DecodedContent content,
824 SeqRange avatarRange,
826 throws HtmlParseException{
827 DecodedContent avatarName;
828 avatarName = this.converter.convert(content, avatarRange);
829 AvatarData avatar = this.villageData.getAvatarData(avatarName);
830 this.currentEvent.addAvatarData(avatar);
833 this.currentEvent.addInteger(votes);
841 * @param content {@inheritDoc}
842 * @param avatarRange {@inheritDoc}
843 * @throws HtmlParseException {@inheritDoc}
846 public void sysEventCheckout(DecodedContent content,
847 SeqRange avatarRange)
848 throws HtmlParseException{
849 DecodedContent avatarName;
850 avatarName = this.converter.convert(content, avatarRange);
851 AvatarData avatar = this.villageData.getAvatarData(avatarName);
852 this.currentEvent.addAvatarData(avatar);
858 * @param content {@inheritDoc}
859 * @param avatarRange {@inheritDoc}
860 * @throws HtmlParseException {@inheritDoc}
863 public void sysEventVanish(DecodedContent content,
864 SeqRange avatarRange)
865 throws HtmlParseException{
866 DecodedContent avatarName;
867 avatarName = this.converter.convert(content, avatarRange);
868 AvatarData avatar = this.villageData.getAvatarData(avatarName);
869 this.currentEvent.addAvatarData(avatar);
875 * @throws HtmlParseException {@inheritDoc}
878 public void endSysEvent() throws HtmlParseException{
879 this.currentPeriod.addTopicData(this.currentEvent);
880 this.currentEvent = null;
886 * @throws HtmlParseException {@inheritDoc}
889 public void endParse() throws HtmlParseException{
890 this.villageData.addPeriodData(this.currentPeriod);
891 this.currentPeriod = null;