diff --git a/vwowrla.core/src/vwowrla/core/encounters/analysis.clj b/vwowrla.core/src/vwowrla/core/encounters/analysis.clj index 34e0b3a..60e2918 100644 --- a/vwowrla.core/src/vwowrla/core/encounters/analysis.clj +++ b/vwowrla.core/src/vwowrla/core/encounters/analysis.clj @@ -13,15 +13,15 @@ [data :- RaidAnalysis] (not (nil? (:active-encounter data)))) -(s/defn touch-entity :- RaidAnalysis - "updates an entity within the current active encounter by resetting it's :last-activity-at timestamp - or adds a new entity under the given name to the active encounter if it does not already exist. returns - the new parsed data set with the updated entity information." - [data :- RaidAnalysis +(s/defn touch-entity :- Encounter + "updates an entity within the encounter by resetting it's :last-activity-at timestamp to the timestamp + provided, or adds a new entity under the given name to the active encounter if it does not already + exist. returns encounter with the updated entity information." + [encounter :- Encounter entity-name :- s/Str timestamp :- Date] - (if-not (get-in data [:active-encounter :entities entity-name]) - (assoc-in data [:active-encounter :entities entity-name] + (if-not (get-in encounter [:entities entity-name]) + (assoc-in encounter [:entities entity-name] {:name entity-name :added-at timestamp :last-activity-at timestamp @@ -41,12 +41,14 @@ :deaths [] :resurrections [] :alive-duration 0}) - (assoc-in data [:active-encounter :entities entity-name :last-activity-at] timestamp))) + (assoc-in encounter [:entities entity-name :last-activity-at] timestamp))) (s/defn get-entity-last-activity :- (s/maybe Date) [entity-name :- s/Str - data :- RaidAnalysis] - (get-in data [:active-encounter :entities entity-name :last-activity-at])) + encounter :- Encounter] + "returns timestamp of the given entity's last activity (that is, the timestamp of the most + recent combat event that was regarding the named entity)" + (get-in encounter [:entities entity-name :last-activity-at])) (s/defn get-entity-alive-time :- Long "returns the number of milliseconds of the encounter that the entity was alive for" @@ -112,38 +114,34 @@ ; TODO entity) -(s/defn finalize-entities :- RaidAnalysis - [data :- RaidAnalysis] - (update-active-encounter - data - (fn [encounter] - (-> encounter - (update-all-entities - #(assoc % :alive-duration (get-entity-alive-time % encounter))) - (update-all-entities - #(assoc % - :encounter-dps (Math/round ^double - (/ (:damage-out-total %) - (/ (:duration encounter) - 1000))) - :alive-dps (Math/round ^double +(s/defn finalize-entities :- Encounter + [encounter :- Encounter] + (-> encounter + (update-all-entities + #(assoc % :alive-duration (get-entity-alive-time % encounter))) + (update-all-entities + #(assoc % + :encounter-dps (Math/round ^double (/ (:damage-out-total %) - (/ (:alive-duration %) - 1000))))) - (update-all-entities finalize-entity-auras (:ended-at encounter)))))) + (/ (:duration encounter) + 1000))) + :alive-dps (Math/round ^double + (/ (:damage-out-total %) + (/ (:alive-duration %) + 1000))))) + (update-all-entities finalize-entity-auras (:ended-at encounter)))) -(s/defn calculate-encounter-stats :- RaidAnalysis - [data :- RaidAnalysis] - (-> data - (update-active-encounter - (fn [{:keys [started-at ended-at] :as encounter}] - (assoc encounter :duration (time-between started-at ended-at)))) - (finalize-entities))) +(s/defn calculate-encounter-stats :- Encounter + [encounter :- Encounter] + (let [{:keys [started-at ended-at]} encounter] + (-> encounter + (assoc :duration (time-between started-at ended-at)) + (finalize-entities)))) (s/defn count-currently-dead :- s/Num - [data :- RaidAnalysis + [encounter :- Encounter entity-name :- s/Str] - (if-let [entity (get-in data [:active-encounter :entities entity-name])] + (if-let [entity (get-in encounter [:entities entity-name])] (let [num-deaths (count (:deaths entity)) num-resurrects (count (:resurrections entity))] (- num-deaths num-resurrects)) @@ -207,27 +205,27 @@ (update-in [:num-immune] #(if (= avoidance-method :immune) (inc %) %)) (update-damage-averages)))) -(s/defn entity-takes-damage :- RaidAnalysis - [data :- RaidAnalysis +(s/defn entity-takes-damage :- Encounter + [encounter :- Encounter entity-name :- s/Str from-entity-name :- s/Str {:keys [skill damage damage-type] :as damage-properties} :- DamageProperties timestamp :- Date] - (-> data + (-> encounter (update-entity-field entity-name [:damage-in-total] #(if damage (+ (or % 0) damage) %)) (update-entity-field entity-name [:damage-in-totals damage-type] #(if damage (+ (or % 0) damage) %)) (update-entity-field entity-name [:damage-in skill] #(add-from-damage-properties % damage-properties)) (update-entity-field entity-name [:damage-in-by-entity from-entity-name skill] #(add-from-damage-properties % damage-properties)))) -(s/defn entity-deals-damage :- RaidAnalysis - [data :- RaidAnalysis +(s/defn entity-deals-damage :- Encounter + [encounter :- Encounter entity-name :- s/Str to-entity-name :- s/Str {:keys [skill damage damage-type] :as damage-properties} :- DamageProperties timestamp :- Date] - (-> data + (-> encounter (update-entity-field entity-name [:damage-out-total] #(if damage (+ (or % 0) damage) %)) (update-entity-field entity-name [:damage-out-totals damage-type] #(if damage (+ (or % 0) damage) %)) (update-entity-field entity-name [:damage-out skill] #(add-from-damage-properties % damage-properties)) @@ -237,42 +235,42 @@ ;;; main combat log entry processing entry points ;;; -(s/defn process-source-to-target-damage :- RaidAnalysis +(s/defn process-source-to-target-damage :- Encounter [source-name :- s/Str target-name :- s/Str damage-properties :- DamageProperties timestamp :- Date - data :- RaidAnalysis] - (-> data + encounter :- Encounter] + (-> encounter (touch-entity source-name timestamp) (touch-entity target-name timestamp) (entity-takes-damage target-name source-name damage-properties timestamp) (entity-deals-damage source-name target-name damage-properties timestamp)) ) -(s/defn process-entity-death :- RaidAnalysis +(s/defn process-entity-death :- Encounter [entity-name :- s/Str timestamp :- Date - data :- RaidAnalysis] - (-> data + encounter :- Encounter] + (-> encounter (touch-entity entity-name timestamp) (update-entity-field entity-name [:deaths] #(conj % {:timestamp timestamp})) (update-entity entity-name finalize-entity-auras timestamp))) -(s/defn process-source-to-target-cast :- RaidAnalysis +(s/defn process-source-to-target-cast :- Encounter [source-name :- s/Str target-name :- s/Str skill-name :- s/Str timestamp :- Date - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defn process-entity-cast :- RaidAnalysis +(s/defn process-entity-cast :- Encounter [entity-name :- s/Str skill-name :- s/Str timestamp :- Date - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) (s/defn begin-encounter :- RaidAnalysis "sets up a new active encounter in the parsed data, returning the new parsed data set ready to use for @@ -302,7 +300,7 @@ (let [data (-> data (update-active-encounter assoc :ended-at timestamp) (update-active-encounter assoc :wipe-or-timeout? wipe-or-timeout?) - (calculate-encounter-stats))] + (update-active-encounter calculate-encounter-stats))] (-> data (assoc-in [:active-encounter] nil) (update-in [:encounters] #(conj %1 (:active-encounter data))))))) \ No newline at end of file diff --git a/vwowrla.core/src/vwowrla/core/encounters/core.clj b/vwowrla.core/src/vwowrla/core/encounters/core.clj index 8f038d1..0e0fc54 100644 --- a/vwowrla.core/src/vwowrla/core/encounters/core.clj +++ b/vwowrla.core/src/vwowrla/core/encounters/core.clj @@ -69,21 +69,22 @@ f & args] (update-active-encounter data #(update-all-entities % f args))) -(s/defn update-entity :- RaidAnalysis "updates an entity in the full parsed data's active encounter using function f which takes the current entity and any supplied args, returning the new entity which is 'updated' in the active encounter. returns the updated full parsed data." - [data :- RaidAnalysis +(s/defn update-entity :- Encounter + [encounter :- Encounter entity-name :- s/Str f & args] - (apply update-in data [:active-encounter :entities entity-name] f args)) + (apply update-in encounter [:entities entity-name] f args)) -(s/defn update-entity-field :- RaidAnalysis "updates a specific field within an entity pointed to by ks in the full parsed data's active encounter using function f which takes the current entity and any supplied args, returning the new entity which is 'updated' in the active encounter. returns the updated full parsed data." - [data :- RaidAnalysis +(s/defn update-entity-field :- Encounter + [encounter :- Encounter entity-name :- s/Str ks f & args] - (apply update-in data (concat [:active-encounter :entities entity-name] ks) f args)) + (let [ks (concat [:entities entity-name] ks)] + (apply update-in encounter ks f args))) diff --git a/vwowrla.core/src/vwowrla/core/encounters/detection.clj b/vwowrla.core/src/vwowrla/core/encounters/detection.clj index 23f4daf..f49fe7f 100644 --- a/vwowrla.core/src/vwowrla/core/encounters/detection.clj +++ b/vwowrla.core/src/vwowrla/core/encounters/detection.clj @@ -94,12 +94,12 @@ encounter was found to be over due to a raid wipe or other non-activity timeout, or nil if the active encounter is not over yet." [{:keys [^Date timestamp]} :- CombatEvent - data :- RaidAnalysis] - (let [trigger-entites (get-in data [:active-encounter :trigger-entities])] + encounter :- Encounter] + (let [trigger-entites (:trigger-entities encounter)] (cond (every? (fn [[entity-name {:keys [count must-kill-count]}]] - (let [count-dead (count-currently-dead data entity-name)] + (let [count-dead (count-currently-dead encounter entity-name)] (>= count-dead (or must-kill-count count)))) trigger-entites) :killed @@ -111,7 +111,7 @@ ; and there have been no combat log lines yet for one or more of the trigger entities. ; should we have a minimum encounter length time? something like 15-30 seconds? that also feels hacky... (>= (- (.getTime timestamp) - (.getTime (or (get-entity-last-activity entity-name data) + (.getTime (or (get-entity-last-activity entity-name encounter) timestamp))) wipe-or-timeout-period)) trigger-entites) diff --git a/vwowrla.core/src/vwowrla/core/events/handlers.clj b/vwowrla.core/src/vwowrla/core/events/handlers.clj index 2b190bb..4906313 100644 --- a/vwowrla.core/src/vwowrla/core/events/handlers.clj +++ b/vwowrla.core/src/vwowrla/core/events/handlers.clj @@ -9,9 +9,9 @@ (fn [{:keys [event]} _] (keyword event))) -(s/defmethod handle-event :skill-damage-to-target :- RaidAnalysis +(s/defmethod handle-event :skill-damage-to-target :- Encounter [{:keys [source-name skill target-name damage damage-type absorbed resisted blocked crit? timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (analysis/process-source-to-target-damage source-name target-name @@ -24,11 +24,11 @@ :partial-resist resisted :partial-block blocked} timestamp - data)) + encounter)) -(s/defmethod handle-event :skill-avoided-by-target :- RaidAnalysis +(s/defmethod handle-event :skill-avoided-by-target :- Encounter [{:keys [source-name target-name skill avoidance-method timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (analysis/process-source-to-target-damage source-name target-name @@ -36,11 +36,11 @@ :actual-skill? true :avoidance-method avoidance-method} timestamp - data)) + encounter)) -(s/defmethod handle-event :damage-reflected :- RaidAnalysis +(s/defmethod handle-event :damage-reflected :- Encounter [{:keys [source-name target-name damage damage-type timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (analysis/process-source-to-target-damage source-name target-name @@ -50,11 +50,11 @@ :damage-type damage-type :crit? false} timestamp - data)) + encounter)) -(s/defmethod handle-event :melee-damage-to-target :- RaidAnalysis +(s/defmethod handle-event :melee-damage-to-target :- Encounter [{:keys [source-name target-name damage damage-type hit-type absorbed resisted blocked crit? timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (analysis/process-source-to-target-damage source-name target-name @@ -68,11 +68,11 @@ :partial-resist resisted :partial-block blocked} timestamp - data)) + encounter)) -(s/defmethod handle-event :melee-avoided-by-target :- RaidAnalysis +(s/defmethod handle-event :melee-avoided-by-target :- Encounter [{:keys [source-name target-name avoidance-method timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (analysis/process-source-to-target-damage source-name target-name @@ -80,16 +80,16 @@ :actual-skill? false :avoidance-method avoidance-method} timestamp - data)) + encounter)) -(s/defmethod handle-event :skill-interrupted-by-target :- RaidAnalysis +(s/defmethod handle-event :skill-interrupted-by-target :- Encounter [{:keys [source-name target-name skill timestamp]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :dot-damages-target :- RaidAnalysis +(s/defmethod handle-event :dot-damages-target :- Encounter [{:keys [source-name skill target-name damage damage-type absorbed resisted timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (analysis/process-source-to-target-damage source-name target-name @@ -101,37 +101,37 @@ :partial-absorb absorbed :partial-resist resisted} timestamp - data)) + encounter)) -(s/defmethod handle-event :cast-begins :- RaidAnalysis +(s/defmethod handle-event :cast-begins :- Encounter [{:keys [source-name skill spell? timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] ; don't think we really care about this ? - data) + encounter) -(s/defmethod handle-event :skill-performed-on-target :- RaidAnalysis +(s/defmethod handle-event :skill-performed-on-target :- Encounter [{:keys [source-name target-name skill spell? extra timestamp]} :- CombatEvent - data :- RaidAnalysis] - (analysis/process-source-to-target-cast source-name target-name skill timestamp data)) + encounter :- Encounter] + (analysis/process-source-to-target-cast source-name target-name skill timestamp encounter)) -(s/defmethod handle-event :cast :- RaidAnalysis +(s/defmethod handle-event :cast :- Encounter [{:keys [source-name skill spell? timestamp]} :- CombatEvent - data :- RaidAnalysis] - (analysis/process-entity-cast source-name skill timestamp data)) + encounter :- Encounter] + (analysis/process-entity-cast source-name skill timestamp encounter)) -(s/defmethod handle-event :skill-heals-target :- RaidAnalysis +(s/defmethod handle-event :skill-heals-target :- Encounter [{:keys [source-name skill crit? target-name amount timestamp]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :resource-gained :- RaidAnalysis +(s/defmethod handle-event :resource-gained :- Encounter [{:keys [target-name amount resource-type source-name skill timestamp]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :resource-lost :- RaidAnalysis +(s/defmethod handle-event :resource-lost :- Encounter [{:keys [target-name amount resource-type source-name skill timestamp]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (condp = resource-type :health (analysis/process-source-to-target-damage source-name @@ -142,42 +142,42 @@ :damage-type :physical :crit? false} timestamp - data) - data)) + encounter) + encounter)) -(s/defmethod handle-event :special-gained :- RaidAnalysis +(s/defmethod handle-event :special-gained :- Encounter [{:keys [target-name special source timestamp]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :aura-gained :- RaidAnalysis +(s/defmethod handle-event :aura-gained :- Encounter [{:keys [target-name aura-name aura-type stacks timestamp]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :aura-lost :- RaidAnalysis +(s/defmethod handle-event :aura-lost :- Encounter [{:keys [target-name aura-name faded? stacks timestamp]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :other-damage :- RaidAnalysis +(s/defmethod handle-event :other-damage :- Encounter [{:keys [target-name damage damage-type resisted absorbed source timestamp]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :death :- RaidAnalysis +(s/defmethod handle-event :death :- Encounter [{:keys [source-name timestamp]} :- CombatEvent - data :- RaidAnalysis] - (analysis/process-entity-death source-name timestamp data)) + encounter :- Encounter] + (analysis/process-entity-death source-name timestamp encounter)) -(s/defmethod handle-event :ignored :- RaidAnalysis +(s/defmethod handle-event :ignored :- Encounter [{:keys [line]} :- CombatEvent - data :- RaidAnalysis] - data) + encounter :- Encounter] + encounter) -(s/defmethod handle-event :default :- RaidAnalysis +(s/defmethod handle-event :default :- Encounter [{:keys [line]} :- CombatEvent - data :- RaidAnalysis] + encounter :- Encounter] (println "[WARN] *** UNRECOGNIZED ***" line) - data) + encounter) diff --git a/vwowrla.core/src/vwowrla/core/parser.clj b/vwowrla.core/src/vwowrla/core/parser.clj index 5bd3812..cec65f0 100644 --- a/vwowrla.core/src/vwowrla/core/parser.clj +++ b/vwowrla.core/src/vwowrla/core/parser.clj @@ -5,6 +5,7 @@ [clojure.tools.logging :refer [info error warn]] [clojure.java.io :as io] [schema.core :as s] + [vwowrla.core.encounters.core :refer [update-active-encounter]] [vwowrla.core.encounters.detection :refer [detect-encounter-end detect-encounter-triggered]] [vwowrla.core.encounters.analysis :refer [begin-encounter end-encounter active-encounter?]] [vwowrla.core.events.handlers :refer [handle-event]] @@ -61,8 +62,8 @@ ends the encounter. should only be called if an encounter is currently active in the current raid analysis data." - (let [data (handle-event event data)] - (if-let [encounter-end (detect-encounter-end event data)] + (let [data (update-active-encounter data #(handle-event event %))] + (if-let [encounter-end (detect-encounter-end event (:active-encounter data))] (end-encounter event encounter-end data) data))) @@ -76,9 +77,9 @@ should only be called if an encounter is NOT currently active in the current raid analysis data." (if-let [encounter-name (detect-encounter-triggered event data)] - (->> data - (begin-encounter encounter-name event) - (handle-event event)) + (as-> data x + (begin-encounter encounter-name event x) + (update-active-encounter x #(handle-event event %))) data)) (s/defn ^:private parse-log* :- (s/maybe RaidAnalysis)