Java tutorial
/* * Copyright 2014. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ramidore.logic.system; import lombok.Getter; import org.apache.commons.lang3.StringUtils; import org.ramidore.Const; import org.ramidore.bean.GvLogTable; import org.ramidore.core.PacketData; import org.ramidore.util.RamidoreUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * GV????. * * @author atmark */ public class GuildBattleLogic extends AbstractSystemMessageLogic { /** * Logger. */ private static final Logger LOG = LoggerFactory.getLogger(GuildBattleLogic.class); /** * ???. * <p> * 1????? */ private static final String UNIT_PATTERN = "380069120000(..)00(....)0000(....)0000(....)0000" + Const.BASE_PATTERN + "00(?:CC)*" + Const.BASE_PATTERN + "00(?:CC)*"; /** * ?????. */ private static final String PATTERN = "^(?:.{2})+(" + UNIT_PATTERN + ")(?:.{2})*$"; /** * ?????. */ private static final String START_PATTERN = "^..002811CDCDCDCD..00000008001012000001FF58006A120000" + Const.BASE_PATTERN + "00(?:CC)+" + Const.BASE_PATTERN + "00(?:CC)+0000000000000000CDCDCCCC(?:.{2})*$"; /** * ??????. */ private static final String RESULT_PATTERN = "4400F1110000(....)" + Const.BASE_PATTERN + "00(?:.{2})+(?:CC)+(?:....)CCCC....0000..00(..)00(..)00(..)00(....)(..)00..00CCCC"; /** * ???????. */ private static final String NAME_PATTERN = "FFFFFFFFCCCC" + Const.BASE_PATTERN + "00(?:CC)+"; /** * ??. */ private static Pattern unitPattern = Pattern.compile(UNIT_PATTERN); /** * ??. */ private static Pattern pattern = Pattern.compile(PATTERN); /** * ??. */ private static Pattern startPattern = Pattern.compile(START_PATTERN); /** * ??. */ private static Pattern resultPattern = Pattern.compile(RESULT_PATTERN); /** * ??. */ private static Pattern namePattern = Pattern.compile(NAME_PATTERN); /** * . */ private Date startDate = null; /** * ????. */ private Set<String> nameSet; /** * K/D???. */ private Set<String> killDeathNameSet; /** * ??. */ private DuplicateChecker dupChecker; /** * ??. */ private PointChecker pointChecker; /** * ??. * <p> * ???? */ @Getter private ConcurrentLinkedQueue<GvLogTable> logDataQ; /** * ?. */ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss"); /** * . */ public GuildBattleLogic() { logDataQ = new ConcurrentLinkedQueue<GvLogTable>(); nameSet = new HashSet<String>(); killDeathNameSet = new HashSet<String>(); logDataQ.clear(); dupChecker = new DuplicateChecker(); pointChecker = new PointChecker(); } @Override public boolean execute(PacketData data) { /* ?????? */ Matcher nameMatcher = namePattern.matcher(data.getStrData()); // ???????? // ???????????????? if (startDate != null && nameMatcher.find()) { String name = RamidoreUtil.encode(nameMatcher.group(1), Const.ENCODING); nameSet.add(name); } /* ?????? */ Matcher matcher = pattern.matcher(data.getStrData()); if (matcher.matches()) { if (startDate == null) { // ????????????????? startDate = data.getDate(); } Matcher unitMatcher = unitPattern.matcher(data.getStrData()); while (unitMatcher.find()) { int order = RamidoreUtil.intValueFromAscHexString(unitMatcher.group(1)); int point = RamidoreUtil.intValueFromDescHexString(unitMatcher.group(2)); int point0 = RamidoreUtil.intValueFromDescHexString(unitMatcher.group(3)); int point1 = RamidoreUtil.intValueFromDescHexString(unitMatcher.group(4)); String srcName = RamidoreUtil.encode(unitMatcher.group(5), Const.ENCODING); String dstName = RamidoreUtil.encode(unitMatcher.group(6), Const.ENCODING); if (!dupChecker.check(data.getDate(), point0, point1)) { continue; } // ?????? killDeathNameSet.add(srcName); killDeathNameSet.add(dstName); // GvLogTable logRow = new GvLogTable(); logRow.setDate(DATE_FORMAT.format(data.getDate())); logRow.setSrcCharaName(srcName); logRow.setDstCharaName(dstName); logRow.setGuildName(order); logRow.setPoint(point); logRow.setPoint0(point0); logRow.setPoint1(point1); // logDataQ.add(logRow); LOG.info(logRow.toLogFormat()); pointChecker.check(data.getDate(), logRow); } return true; } /* gv?????? */ Matcher startMatcher = startPattern.matcher(data.getStrData()); if (startMatcher.matches() && startDate == null) { // 0 vs 0? GvLogTable log0 = new GvLogTable(); startDate = data.getDate(); log0.setDate(DATE_FORMAT.format(startDate)); String gName0 = RamidoreUtil.encode(startMatcher.group(1), Const.ENCODING); String gName1 = RamidoreUtil.encode(startMatcher.group(2), Const.ENCODING); log0.setStrictGuildName0(gName0); log0.setStrictGuildName1(gName1); logDataQ.add(log0); LOG.info(DATE_FORMAT.format(startDate) + "\t : " + gName0 + " vs " + gName1); return true; } /* gv?????? */ Matcher resultMatcher = resultPattern.matcher(data.getStrData()); if (resultMatcher.find()) { String gCode = resultMatcher.group(1); String gName = RamidoreUtil.encode(resultMatcher.group(2), Const.ENCODING); int winCnt = RamidoreUtil.intValueFromAscHexString(resultMatcher.group(3)); int loseCnt = RamidoreUtil.intValueFromAscHexString(resultMatcher.group(4)); int drawCnt = RamidoreUtil.intValueFromAscHexString(resultMatcher.group(5)); int winPoint = RamidoreUtil.intValueFromDescHexString(resultMatcher.group(6)); String resultCode = resultMatcher.group(7); String result = StringUtils.EMPTY; if ("00".equals(resultCode)) { result = "?????"; } else if ("01".equals(resultCode)) { result = "????"; } else if ("02".equals(resultCode)) { result = "?????"; } LOG.info(DATE_FORMAT.format(data.getDate()) + "\t : ?[" + gCode + "]??" + gName + "???" + result); LOG.info(winCnt + "? " + loseCnt + " " + drawCnt + " ?? " + winPoint); // ????????kill/death????????? nameSet.removeAll(killDeathNameSet); LOG.info("00LA(???????)"); if (nameSet.isEmpty()) { LOG.info("?"); } else { for (String name : nameSet) { LOG.info(name); } } return true; } return false; } /** * ??. */ private class DuplicateChecker { private static final String FORMAT = "%d:%d"; private Set<String> set = new HashSet<String>(); public DuplicateChecker() { set.add(String.format(FORMAT, 0, 0)); } public boolean check(Date date, int p1, int p2) { String val = String.format(FORMAT, p1, p2); if (set.contains(val)) { LOG.warn(DATE_FORMAT.format(date) + "\t???? : " + p1 + " - " + p2); return false; } else { set.add(val); return true; } } } ; /** * ???. * * @author atmark */ private class PointChecker { private int[] p; private int[] diff; public PointChecker() { p = new int[] { 0, 0 }; diff = new int[] { 0, 0 }; } public void check(Date date, GvLogTable t) { this.p[t.getGuildName()] += t.getPoint(); if (this.p[0] - t.getPoint0() != diff[0]) { diff[0] = this.p[0] - t.getPoint0(); LOG.warn(DATE_FORMAT.format(date) + "\t??? : " + diff[0]); } else if (this.p[1] - t.getPoint1() != diff[1]) { diff[1] = this.p[1] - t.getPoint1(); LOG.warn(DATE_FORMAT.format(date) + "\t??? : " + diff[1]); } } } }