/** * Colloid project * * Combat log analyzer. * * copyright: (c) 2013 by Darek <netmik12 [AT] gmail [DOT] com> * license: BSD, see LICENSE for more details */ package colloid.model.event; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; import javafx.application.Platform; import colloid.model.LogUtil; import colloid.model.event.DoesNotExist; import colloid.model.event.Combat.Event; import colloid.model.event.Combat.EventHandler; import colloid.model.event.Combat.ObservableListString; public abstract class RecountLoop implements Combat.Recount { private boolean isRunning; protected HashSet<Actor> actors= new HashSet<Actor>(); protected HashSet<Fight> fights= new HashSet<Fight>(); String combatDirPath; HashSet<EventHandler<CombatEvent>> handler = new HashSet<EventHandler<CombatEvent>>(); protected ObservableListString observableObj; String lastLine; Date currentLogTime; public RecountLoop() { } @Override public void init() { run(); } @Override public void onStart() { } @Override public void onUpdate() { } @Override public void onStop() { } protected void update() { try { compileCurrent(); } catch (InvalidCombatDirPathException e) { // TODO Auto-generated catch block e.printStackTrace(); } } class RecountThread extends Thread { public RecountThread(Runnable runnable) { super(runnable); } @Override public void run() { boolean done = false; try { super.run(); done = true; } catch (Exception ex) { interrupt(); Logger.getLogger(RecountLoop.class.getName()).log(Level.SEVERE, null, ex); } finally { if (!done) { interrupt(); restart(); } } } } void restart() { stop(); while (!isRunning) { run(); break; } } public void run() { isRunning = true; new RecountThread(new Runnable() { void runLater() { if (Platform.isFxApplicationThread()) { update(); } else { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } Platform.runLater(new Runnable() { @Override public void run() { runLater(); } }); } } @Override public void run() { onStart(); while (isRunning) { runLater(); } } }).start(); } public void stop() { isRunning = false; onStop(); } public boolean isRunning() { return isRunning; } /** * @TODO stop thread should use InterruptLoopException * @throws InterruptLoopException */ public void interrupt() throws InterruptLoopException { throw new InterruptLoopException(); } public class InterruptLoopException extends Exception { private static final long serialVersionUID = 2213013019370707528L; } public RecountLoop setCombatDirPath(String combatDirPath) { this.combatDirPath = combatDirPath; return this; } public void setObservable(Combat.ObservableListString observable) { observableObj = observable; } public String getCombatDirPath() { return combatDirPath; } @Override public void onUpdate(EventHandler<CombatEvent> handler) { this.handler.add(handler); } public class InvalidCombatDirPathException extends Exception { private static final long serialVersionUID = -346778478900727174L; } private void compileCurrent() throws InvalidCombatDirPathException { if (getCombatDirPath() == null) { throw new InvalidCombatDirPathException(); } File[] logs = Util.filesByPath(getCombatDirPath()); if (logs == null || logs.length == 0) { return; } File log = logs[logs.length - 1]; /** * @TODO */ if (log.isFile()) { String tailLines; try { tailLines = LogUtil.tail(log, 30); } catch (StringIndexOutOfBoundsException ex) { Logger.getLogger(RecountLoop.class.getName()).log(Level.SEVERE, "Invalid log combat source"); return; } String[] lines = tailLines.split("\n"); for (String line : lines) { currentLogTime = Util.parseDate(line); if (currentLogTime == null) { continue; } if (lastLine == null || !Util.isDone(currentLogTime, lastLine)) { lastLine = line; CombatEvent event = new CombatEvent(this, lastLine); if (!handler.isEmpty()) { beforeUpdate(lastLine); Iterator<EventHandler<CombatEvent>> iter = handler.iterator(); while (iter.hasNext()) { EventHandler<CombatEvent> hand = iter.next(); hand.handle(event); } } onUpdate(); } } } } /** * Executes before combat event update */ protected void beforeUpdate(String combatlog) { try { registerActor(new Actor(combatlog)); } catch (DoesNotExist e) { //do nothing } Iterator<Actor> iterActor = getActors().iterator(); while(iterActor.hasNext()) { Actor act = iterActor.next(); act.handleEvent(combatlog); } } public String getCurrentLogadata() { return lastLine; } public boolean isStateChanged() { return !Util.isDone(currentLogTime, lastLine); } public void registerActor(Actor actor) { if (!actors.contains(actor)) { actor.setOnDamage(new Combat.EventHandler<Combat.Event>() { @Override public void handle(Event event) { } }); actor.setOnHeal(new Combat.EventHandler<Combat.Event>() { @Override public void handle(Event event) { } }); actor.setOnCombatEnter(new Combat.EventHandler<CombatEnterEvent>() { @Override public void handle(CombatEnterEvent event) { // TODO Auto-generated method stub } }); actor.setOnCombatExit(new Combat.EventHandler<CombatExitEvent>() { @Override public void handle(CombatExitEvent event) { } }); actors.add(actor); } } public HashSet<Actor> getActors() { return actors; } /** * Return sorted list of actors by damage done */ public ArrayList<Actor> getActorList() { ArrayList<Actor> list = new ArrayList<Actor>(getActors()); Collections.sort(list, Collections.reverseOrder()); return list; } public ArrayList<Fight> getFightList() { ArrayList<Fight> list = new ArrayList<Fight>(getFights()); Collections.sort(list, Collections.reverseOrder()); return list; } public HashSet<Fight> getFights() { return fights; } public void setFights(HashSet<Fight> fights) { this.fights = fights; } }