diff --git a/vwowrla.core/src/vwowrla/core/parser.clj b/vwowrla.core/src/vwowrla/core/parser.clj index ef71dba..343fbe0 100644 --- a/vwowrla.core/src/vwowrla/core/parser.clj +++ b/vwowrla.core/src/vwowrla/core/parser.clj @@ -3,19 +3,35 @@ (:require [clojure.tools.logging :refer [info error warn]] [clojure.java.io :as io] + [schema.core :as s] [vwowrla.core.encounters :as encounters] [vwowrla.core.handlers :refer [handle-event]] [vwowrla.core.matchers :refer [regex-matchers]]) (:use + vwowrla.core.schemas vwowrla.core.preparsing vwowrla.core.utils)) -(defn active-encounter? - [data] +(s/defn active-encounter? :- s/Bool + [data :- RaidAnalysis] (not (nil? (:active-encounter data)))) -(defn parse-line - [^String line {:keys [log-owner-char-name] :as options}] +(defn- ->ignored-event + [parsed-line] + (assoc parsed-line + :id :ignored + :logfmt :ignored)) + +(defn ->unrecognized-event + [parsed-line] + (assoc parsed-line + :id :unknown + :logfmt :unknown + :event :unknown)) + +(s/defn parse-line :- CombatEvent + [^String line + options :- ParserOptions] (let [[timestamp stripped-line] (split-log-timestamp-and-content line) sanitized-line (-> stripped-line (undo-swstats-fixlogstring) @@ -31,30 +47,36 @@ line-metadata (select-keys matcher [:logfmt :event :id]) (apply args-fn regex-matches))] - (process-parsed-line parsed-line log-owner-char-name)) - line-metadata))) + (if (= :ignored (:event parsed-line)) + (->ignored-event parsed-line) + (process-parsed-line parsed-line (:log-owner-char-name options)))) + (->unrecognized-event line-metadata)))) -(defn handle-line - [parsed-line data] +(s/defn handle-line + [parsed-line :- CombatEvent + data :- RaidAnalysis] (handle-event parsed-line data)) -(defn- active-encounter-processing - [parsed-line data] +(s/defn ^:private active-encounter-processing + [parsed-line :- CombatEvent + data :- RaidAnalysis] (let [data (handle-line parsed-line data)] (if-let [encounter-end (encounters/detect-encounter-end parsed-line data)] (encounters/end-encounter parsed-line encounter-end data) data))) -(defn- out-of-encounter-processing - [parsed-line data] +(s/defn ^:private out-of-encounter-processing + [parsed-line :- CombatEvent + data :- RaidAnalysis] (if-let [encounter-name (encounters/detect-encounter-triggered parsed-line data)] (->> data (encounters/begin-encounter encounter-name parsed-line) (handle-line parsed-line)) data)) -(defn- parse-log* - [f options] +(s/defn ^:private parse-log* :- (s/maybe RaidAnalysis) + [f + options :- ParserOptions] (with-open [rdr (io/reader f)] (try (reduce @@ -73,7 +95,7 @@ (flush) (error ex "Parser error."))))) -(defn parse-log +(s/defn parse-log :- (s/maybe RaidAnalysis) [f options] (let [line-ending-type (detect-file-line-ending-type f)] (if-not line-ending-type diff --git a/vwowrla.core/src/vwowrla/core/schema_utils.clj b/vwowrla.core/src/vwowrla/core/schema_utils.clj new file mode 100644 index 0000000..58e9052 --- /dev/null +++ b/vwowrla.core/src/vwowrla/core/schema_utils.clj @@ -0,0 +1,11 @@ +(ns vwowrla.core.schema-utils + (:require + [schema.core :as s])) + +(def array + (s/pred + #(if % (.isArray (class %))))) + +(defn one-of [allowed-values] + (s/pred + #(boolean (some #{%} allowed-values)))) diff --git a/vwowrla.core/src/vwowrla/core/schemas.clj b/vwowrla.core/src/vwowrla/core/schemas.clj new file mode 100644 index 0000000..d5814ae --- /dev/null +++ b/vwowrla.core/src/vwowrla/core/schemas.clj @@ -0,0 +1,56 @@ +(ns vwowrla.core.schemas + (:require + [schema.core :as s]) + (:use + vwowrla.core.schema-utils)) + +;; constants + +(def damage-types [:physical :arcane :fire :frost :nature :shadow :holy]) +(def avoidance-methods [:miss :parry :dodge :block :evade :immune :resist :absorb]) +(def hit-types [:normal :glancing :crushing]) +(def resource-types [:health :mana :rage :energy :happiness]) +(def aura-types [:buff :debuff]) + +;; model schemas + +(def CombatEvent + {:id s/Keyword + :logfmt s/Keyword + :event s/Keyword + :line s/Str + :timestamp java.util.Date + (s/optional-key :source-name) s/Str + (s/optional-key :source) s/Str ; could be an entity name, a skill/talent name, or even something else + (s/optional-key :target-name) s/Str + (s/optional-key :skill) s/Str + (s/optional-key :crit?) s/Bool + (s/optional-key :damage) s/Num + (s/optional-key :damage-type) (one-of damage-types) + (s/optional-key :resisted) (s/maybe s/Num) + (s/optional-key :absorbed) (s/maybe s/Num) + (s/optional-key :blocked) (s/maybe s/Num) + (s/optional-key :avoidance-method) (one-of avoidance-methods) + (s/optional-key :hit-type) (one-of hit-types) + (s/optional-key :spell?) s/Bool + (s/optional-key :extra) s/Str + (s/optional-key :amount) s/Num + (s/optional-key :resource-type) (one-of resource-types) + (s/optional-key :special) s/Str + (s/optional-key :aura-name) s/Str + (s/optional-key :aura-type) (one-of aura-types) + (s/optional-key :stacks) (s/maybe s/Num) + (s/optional-key :faded?) s/Bool}) + +(def Encounter + {s/Any s/Any}) + +(def RaidAnalysis + {:encounters [Encounter] + :active-encounter (s/maybe Encounter)}) + +(def ParserOptions + {:log-owner-char-name s/Str + :year s/Int + :timezone java.util.TimeZone + (s/optional-key :windows?) s/Bool})