switch most of the rest of the functions to schema's defn

This commit is contained in:
Gered 2016-02-27 23:01:30 -05:00
parent c5b70844e9
commit 0af2cadd06
3 changed files with 157 additions and 93 deletions

View file

@ -4,8 +4,10 @@
(:require (:require
[clojure.java.io :as io] [clojure.java.io :as io]
[clojure.tools.logging :refer [info error]] [clojure.tools.logging :refer [info error]]
[schema.core :as s]
[cheshire.core :as json]) [cheshire.core :as json])
(:use (:use
vwowrla.core.schemas
vwowrla.core.utils)) vwowrla.core.utils))
(def defined-encounters (get-edn-resource "encounters.edn")) (def defined-encounters (get-edn-resource "encounters.edn"))
@ -18,11 +20,11 @@
(declare count-currently-dead) (declare count-currently-dead)
(declare get-entity-last-activity) (declare get-entity-last-activity)
(defn find-defined-encounter-name (s/defn find-defined-encounter-name :- (s/maybe s/Str)
"returns the name of a defined encounter which includes the given entity in it's "returns the name of a defined encounter which includes the given entity in it's
list of trigger entities. returns nil if there is no encounter which includes the list of trigger entities. returns nil if there is no encounter which includes the
given entity" given entity"
[entity-name] [entity-name :- (s/maybe s/Str)]
(->> defined-encounters (->> defined-encounters
(filter (fn [[_ {:keys [entities]}]] (filter (fn [[_ {:keys [entities]}]]
(->> entities (->> entities
@ -30,60 +32,69 @@
(first)))) (first))))
(ffirst))) (ffirst)))
(defn find-past-encounters (s/defn find-past-encounters :- [Encounter]
"return a list of all previously parsed encounters (successful and not) matching the encounter name" "return a list of all previously parsed encounters (successful and not) matching the encounter name"
[encounter-name data] [encounter-name :- s/Str
data :- RaidAnalysis]
(->> (:encounters data) (->> (:encounters data)
(filter #(= (:name %) encounter-name)))) (filter #(= (:name %) encounter-name))))
(defn any-successful-encounters? (s/defn any-successful-encounters? :- s/Bool
"returns true if there are any successful parsed encounters matching the encounter name" "returns true if there are any successful parsed encounters matching the encounter name"
[encounter-name data] [encounter-name :- s/Str
data :- RaidAnalysis]
(->> (find-past-encounters encounter-name data) (->> (find-past-encounters encounter-name data)
(map :wipe-or-timeout?) (map :wipe-or-timeout?)
(filter false?) (filter false?)
(empty?) (empty?)
(not))) (not)))
(defn update-active-encounter (s/defn update-active-encounter :- RaidAnalysis
"updates the active encounter using function f which will take the current active "updates the active encounter using function f which will take the current active
encounter and any supplied args, returning a new active encounter which is encounter and any supplied args, returning a new active encounter which is
'updated' in the original full parsed data and then finally returned." 'updated' in the original full parsed data and then finally returned."
[data f & args] [data :- RaidAnalysis
f & args]
(apply update-in data [:active-encounter] f args)) (apply update-in data [:active-encounter] f args))
(defn update-all-entities (s/defn update-all-entities :- Encounter
"updates all entities in the encounter using function f which takes the current "updates all entities in the encounter using function f which takes the current
entity and any supplied args, returning a new entity which is 'updated' in the entity and any supplied args, returning a new entity which is 'updated' in the
original encounter. returns the encounter with the modified entity data." original encounter. returns the encounter with the modified entity data."
[encounter f & args] [encounter :- Encounter
f & args]
(reduce (reduce
(fn [encounter [entity-name entity]] (fn [encounter [entity-name entity]]
(assoc-in encounter [:entities entity-name] (apply f entity args))) (assoc-in encounter [:entities entity-name] (apply f entity args)))
encounter encounter
(:entities encounter))) (:entities encounter)))
(defn update-all-active-encounter-entities (s/defn update-all-active-encounter-entities :- RaidAnalysis
"updates all entities in the current active encounter in the full parsed data "updates all entities in the current active encounter in the full parsed data
using function f which takes the current entity and any supplied args, returning using function f which takes the current entity and any supplied args, returning
a new entity which is 'updated' in the original encounter. returns the updated a new entity which is 'updated' in the original encounter. returns the updated
full parsed data." full parsed data."
[data f & args] [data :- RaidAnalysis
f & args]
(update-active-encounter data #(update-all-entities % f args))) (update-active-encounter data #(update-all-entities % f args)))
(defn update-entity (s/defn update-entity :- RaidAnalysis
"updates an entity in the full parsed data's active encounter using function f "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 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." which is 'updated' in the active encounter. returns the updated full parsed data."
[data entity-name f & args] [data :- RaidAnalysis
entity-name :- s/Str
f & args]
(apply update-in data [:active-encounter :entities entity-name] f args)) (apply update-in data [:active-encounter :entities entity-name] f args))
(defn update-entity-field (s/defn update-entity-field :- RaidAnalysis
"updates a specific field within an entity pointed to by ks in the full parsed "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 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. supplied args, returning the new entity which is 'updated' in the active encounter.
returns the updated full parsed data." returns the updated full parsed data."
[data entity-name ks f & args] [data :- RaidAnalysis
entity-name :- s/Str
ks f & args]
(apply update-in data (concat [:active-encounter :entities entity-name] ks) f args)) (apply update-in data (concat [:active-encounter :entities entity-name] ks) f args))
(defn- ignore-interaction? (defn- ignore-interaction?
@ -93,11 +104,12 @@
(or (contained-in? target-name ignore-entity-list) (or (contained-in? target-name ignore-entity-list)
(contained-in? source-name ignore-entity-list)))) (contained-in? source-name ignore-entity-list))))
(defn ignored-interaction-event? (s/defn ignored-interaction-event? :- s/Bool
"returns true if the given parsed combat log line is between entities that have "returns true if the given parsed combat log line is between entities that have
been specified to ignore interactions between for the purposes of detecting been specified to ignore interactions between for the purposes of detecting
an encounter trigger" an encounter trigger"
[encounter parsed-line] [encounter :- Encounter
parsed-line :- CombatEvent]
(->> (:entities encounter) (->> (:entities encounter)
(filter (filter
(fn [[entity-name entity-props]] (fn [[entity-name entity-props]]
@ -105,18 +117,20 @@
(filter (filter
(fn [[entity-name entity-props]] (fn [[entity-name entity-props]]
(ignore-interaction? entity-name (:ignore-interactions-with entity-props) parsed-line))) (ignore-interaction? entity-name (:ignore-interactions-with entity-props) parsed-line)))
(seq))) (seq)
(boolean)))
(defn- ignore-skill? (defn- ignore-skill?
[entity-name ignore-skill-list {:keys [source-name skill] :as parsed-line}] [entity-name ignore-skill-list {:keys [source-name skill] :as parsed-line}]
(and (= entity-name source-name) (and (= entity-name source-name)
(contained-in? skill ignore-skill-list))) (contained-in? skill ignore-skill-list)))
(defn ignored-skill-event? (s/defn ignored-skill-event? :- s/Bool
"returns true if the given parsed combat log line is for an encounter entity "returns true if the given parsed combat log line is for an encounter entity
that is using a skill that has been specifically indicated should be ignored that is using a skill that has been specifically indicated should be ignored
for the purposes of triggering an encounter" for the purposes of triggering an encounter"
[encounter parsed-line] [encounter :- Encounter
parsed-line :- CombatEvent]
(->> (:entities encounter) (->> (:entities encounter)
(filter (filter
(fn [[entity-name entity-props]] (fn [[entity-name entity-props]]
@ -124,17 +138,19 @@
(filter (filter
(fn [[entity-name entity-props]] (fn [[entity-name entity-props]]
(ignore-skill? entity-name (:ignore-skills entity-props) parsed-line))) (ignore-skill? entity-name (:ignore-skills entity-props) parsed-line)))
(seq))) (seq)
(boolean)))
;;; ;;;
;;; encounter start/stop ;;; encounter start/stop
;;; ;;;
(defn detect-encounter-triggered (s/defn detect-encounter-triggered :- (s/maybe s/Str)
"determines if the parsed combat log line is for an event involving any specific encounter entities which "determines if the parsed combat log line is for an event involving any specific encounter entities which
should cause an encounter to begin, returning the name of the encounter if it should begin, or nil if no should cause an encounter to begin, returning the name of the encounter if it should begin, or nil if no
encounter begin was detected" encounter begin was detected"
[{:keys [target-name source-name damage aura-name type skill] :as parsed-line} data] [{:keys [target-name source-name damage aura-name type skill] :as parsed-line} :- CombatEvent
data :- RaidAnalysis]
(if-let [encounter-name (or (find-defined-encounter-name target-name) (if-let [encounter-name (or (find-defined-encounter-name target-name)
(find-defined-encounter-name source-name))] (find-defined-encounter-name source-name))]
(if (and (not (any-successful-encounters? encounter-name data)) (if (and (not (any-successful-encounters? encounter-name data))
@ -163,10 +179,12 @@
:else :else
encounter-name))))) encounter-name)))))
(defn begin-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 "sets up a new active encounter in the parsed data, returning the new parsed data set ready to use for
parsing a new encounter." parsing a new encounter."
[encounter-name {:keys [timestamp line] :as parsed-line} data] [encounter-name :- s/Str
{:keys [timestamp line]} :- CombatEvent
data :- RaidAnalysis]
(info "Beginning encounter" (str "\"" encounter-name "\"") "detected on line:" line) (info "Beginning encounter" (str "\"" encounter-name "\"") "detected on line:" line)
(assoc data :active-encounter (assoc data :active-encounter
{:name encounter-name {:name encounter-name
@ -175,12 +193,13 @@
:skills {} :skills {}
:trigger-entities (get-in defined-encounters [encounter-name :entities])})) :trigger-entities (get-in defined-encounters [encounter-name :entities])}))
(defn detect-encounter-end (s/defn detect-encounter-end :- (s/maybe s/Keyword)
"determines if the currently active encounter should end based on the active encounter parsed data. "determines if the currently active encounter should end based on the active encounter parsed data.
returns :killed if the encounter should end due to a successful kill, :wipe-or-timeout if the returns :killed if the encounter should end due to a successful kill, :wipe-or-timeout if the
encounter was found to be over due to a raid wipe or other non-activity timeout, or nil if the 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." active encounter is not over yet."
[{:keys [^Date timestamp] :as parsed-line} data] [{:keys [^Date timestamp]} :- CombatEvent
data :- RaidAnalysis]
(let [trigger-entites (get-in data [:active-encounter :trigger-entities])] (let [trigger-entites (get-in data [:active-encounter :trigger-entities])]
(cond (cond
(every? (every?
@ -203,11 +222,13 @@
trigger-entites) trigger-entites)
:wipe-or-timeout))) :wipe-or-timeout)))
(defn end-encounter (s/defn end-encounter :- RaidAnalysis
"ends the current active encounter in the parsed data, moving it from :active-encounter and inserted it into the "ends the current active encounter in the parsed data, moving it from :active-encounter and inserted it into the
end of the :encounters list. finalizes the encounter by performing various final entity statistic calculations and end of the :encounters list. finalizes the encounter by performing various final entity statistic calculations and
marks the encounter as successful or not. returns the new parsed data set without any active encounter set." marks the encounter as successful or not. returns the new parsed data set without any active encounter set."
[{:keys [timestamp line] :as parsed-line} encounter-end-cause data] [{:keys [timestamp line]} :- CombatEvent
encounter-end-cause :- s/Keyword
data :- RaidAnalysis]
(let [wipe-or-timeout? (= encounter-end-cause :wipe-or-timeout)] (let [wipe-or-timeout? (= encounter-end-cause :wipe-or-timeout)]
(info "Ending encounter" (str "\"" (get-in data [:active-encounter :name]) "\"") "detected on line:" line) (info "Ending encounter" (str "\"" (get-in data [:active-encounter :name]) "\"") "detected on line:" line)
(if wipe-or-timeout? (if wipe-or-timeout?
@ -224,11 +245,13 @@
;;; entity manipulation ;;; entity manipulation
;;; ;;;
(defn touch-entity (s/defn touch-entity :- RaidAnalysis
"updates an entity within the current active encounter by resetting it's :last-activity-at timestamp "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 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." the new parsed data set with the updated entity information."
[data entity-name timestamp] [data :- RaidAnalysis
entity-name :- s/Str
timestamp :- Date]
(if-not (get-in data [:active-encounter :entities entity-name]) (if-not (get-in data [:active-encounter :entities entity-name])
(assoc-in data [:active-encounter :entities entity-name] (assoc-in data [:active-encounter :entities entity-name]
{:name entity-name {:name entity-name
@ -252,18 +275,15 @@
:alive-duration 0}) :alive-duration 0})
(assoc-in data [:active-encounter :entities entity-name :last-activity-at] timestamp))) (assoc-in data [:active-encounter :entities entity-name :last-activity-at] timestamp)))
(defn get-entity-last-activity (s/defn get-entity-last-activity :- (s/maybe Date)
[entity-name data] [entity-name :- s/Str
data :- RaidAnalysis]
(get-in data [:active-encounter :entities entity-name :last-activity-at])) (get-in data [:active-encounter :entities entity-name :last-activity-at]))
(defn get-entity-alive-time (s/defn get-entity-alive-time :- Long
"returns the number of milliseconds of the encounter that the entity was alive for" "returns the number of milliseconds of the encounter that the entity was alive for"
[{:keys [deaths resurrections] :as entity} {:keys [started-at ended-at] :as encounter}] [{:keys [deaths resurrections]} :- Entity
;(println (:name entity)) {:keys [started-at ended-at] :as encounter} :- Encounter]
;(println "started-at" started-at)
;(println "ended-at " ended-at)
;(println "deaths " deaths)
;(println "resurrects" resurrections)
(if (and (= 0 (count deaths)) (if (and (= 0 (count deaths))
(= 0 (count resurrections))) (= 0 (count resurrections)))
(:duration encounter) (:duration encounter)
@ -273,10 +293,8 @@
[{:status :end :at ended-at}]) x [{:status :end :at ended-at}]) x
(remove empty? x) (remove empty? x)
(sort-by :at x))] (sort-by :at x))]
;(println ">" segments)
(reduce (reduce
(fn [{:keys [total current-status from] :as result} {:keys [status at]}] (fn [{:keys [total current-status from] :as result} {:keys [status at]}]
;(println ">>" current-status from status at)
(cond (cond
; is the first state change we find a resurrect? (e.g. they were dead when the fight began) ; is the first state change we find a resurrect? (e.g. they were dead when the fight began)
(and (nil? current-status) (and (nil? current-status)
@ -320,13 +338,14 @@
:from started-at} :from started-at}
segments)))) segments))))
(defn finalize-entity-auras (s/defn finalize-entity-auras :- Entity
[entity timestamp] [entity :- Entity
timestamp :- Date]
; TODO ; TODO
entity) entity)
(defn finalize-entities (s/defn finalize-entities :- RaidAnalysis
[data] [data :- RaidAnalysis]
(update-active-encounter (update-active-encounter
data data
(fn [encounter] (fn [encounter]
@ -345,31 +364,32 @@
1000))))) 1000)))))
(update-all-entities finalize-entity-auras (:ended-at encounter)))))) (update-all-entities finalize-entity-auras (:ended-at encounter))))))
(defn calculate-encounter-stats (s/defn calculate-encounter-stats :- RaidAnalysis
[data] [data :- RaidAnalysis]
(-> data (-> data
(update-active-encounter (update-active-encounter
(fn [{:keys [started-at ended-at] :as encounter}] (fn [{:keys [started-at ended-at] :as encounter}]
(assoc encounter :duration (time-between started-at ended-at)))) (assoc encounter :duration (time-between started-at ended-at))))
(finalize-entities))) (finalize-entities)))
(defn count-currently-dead (s/defn count-currently-dead :- s/Num
[data entity-name] [data :- RaidAnalysis
entity-name :- s/Str]
(if-let [entity (get-in data [:active-encounter :entities entity-name])] (if-let [entity (get-in data [:active-encounter :entities entity-name])]
(let [num-deaths (count (:deaths entity)) (let [num-deaths (count (:deaths entity))
num-resurrects (count (:resurrections entity))] num-resurrects (count (:resurrections entity))]
(- num-deaths num-resurrects)) (- num-deaths num-resurrects))
0)) 0))
(defn update-damage-averages (s/defn update-damage-averages :- SkillStatistics
[{:keys [num-hits total-hit-damage total-crit-damage num-crits] :as totals}] [{:keys [num-hits total-hit-damage total-crit-damage num-crits] :as totals} :- SkillStatistics]
(-> totals (-> totals
(update-in [:average-hit] #(if (> num-hits 0) (int (/ total-hit-damage num-hits)) %)) (update-in [:average-hit] #(if (> num-hits 0) (int (/ total-hit-damage num-hits)) %))
(update-in [:average-crit] #(if (> num-crits 0) (int (/ total-crit-damage num-crits)) %)))) (update-in [:average-crit] #(if (> num-crits 0) (int (/ total-crit-damage num-crits)) %))))
(defn add-from-damage-properties (s/defn add-from-damage-properties :- SkillStatistics
[totals [totals :- (s/maybe SkillStatistics)
{:keys [damage damage-type hit-type crit? partial-absorb partial-resist partial-block avoidance-method] :as damage-properties}] {:keys [damage damage-type hit-type crit? partial-absorb partial-resist partial-block avoidance-method]} :- DamageProperties]
(let [damage (or damage 0)] (let [damage (or damage 0)]
(-> (or totals {:damage 0 (-> (or totals {:damage 0
:max-hit 0 :max-hit 0
@ -419,16 +439,26 @@
(update-in [:num-immune] #(if (= avoidance-method :immune) (inc %) %)) (update-in [:num-immune] #(if (= avoidance-method :immune) (inc %) %))
(update-damage-averages)))) (update-damage-averages))))
(defn entity-takes-damage (s/defn entity-takes-damage :- RaidAnalysis
[data entity-name from-entity-name {:keys [skill damage damage-type] :as damage-properties} timestamp] [data :- RaidAnalysis
entity-name :- s/Str
from-entity-name :- s/Str
{:keys [skill damage damage-type]
:as damage-properties} :- DamageProperties
timestamp :- Date]
(-> data (-> data
(update-entity-field entity-name [:damage-in-total] #(if damage (+ (or % 0) damage) %)) (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-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 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)))) (update-entity-field entity-name [:damage-in-by-entity from-entity-name skill] #(add-from-damage-properties % damage-properties))))
(defn entity-deals-damage (s/defn entity-deals-damage :- RaidAnalysis
[data entity-name to-entity-name {:keys [skill damage damage-type] :as damage-properties} timestamp] [data :- RaidAnalysis
entity-name :- s/Str
to-entity-name :- s/Str
{:keys [skill damage damage-type]
:as damage-properties} :- DamageProperties
timestamp :- Date]
(-> data (-> data
(update-entity-field entity-name [:damage-out-total] #(if damage (+ (or % 0) damage) %)) (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-totals damage-type] #(if damage (+ (or % 0) damage) %))
@ -439,8 +469,12 @@
;;; main combat log entry processing entry points ;;; main combat log entry processing entry points
;;; ;;;
(defn process-source-to-target-damage (s/defn process-source-to-target-damage :- RaidAnalysis
[source-name target-name damage-properties timestamp data] [source-name :- s/Str
target-name :- s/Str
damage-properties :- DamageProperties
timestamp :- Date
data :- RaidAnalysis]
(-> data (-> data
(touch-entity source-name timestamp) (touch-entity source-name timestamp)
(touch-entity target-name timestamp) (touch-entity target-name timestamp)
@ -448,17 +482,26 @@
(entity-deals-damage source-name target-name damage-properties timestamp)) (entity-deals-damage source-name target-name damage-properties timestamp))
) )
(defn process-entity-death (s/defn process-entity-death :- RaidAnalysis
[entity-name timestamp data] [entity-name :- s/Str
timestamp :- Date
data :- RaidAnalysis]
(-> data (-> data
(touch-entity entity-name timestamp) (touch-entity entity-name timestamp)
(update-entity-field entity-name [:deaths] #(conj % {:timestamp timestamp})) (update-entity-field entity-name [:deaths] #(conj % {:timestamp timestamp}))
(update-entity entity-name finalize-entity-auras timestamp))) (update-entity entity-name finalize-entity-auras timestamp)))
(defn process-source-to-target-cast (s/defn process-source-to-target-cast :- RaidAnalysis
[source-name target-name skill-name timestamp data] [source-name :- s/Str
target-name :- s/Str
skill-name :- s/Str
timestamp :- Date
data :- RaidAnalysis]
data) data)
(defn process-entity-cast (s/defn process-entity-cast :- RaidAnalysis
[entity-name skill-name timestamp data] [entity-name :- s/Str
skill-name :- s/Str
timestamp :- Date
data :- RaidAnalysis]
data) data)

View file

@ -1,10 +1,12 @@
(ns vwowrla.core.preparsing (ns vwowrla.core.preparsing
(:import (:import
(java.util Calendar GregorianCalendar TimeZone)) (java.util Calendar Date GregorianCalendar TimeZone))
(:require (:require
[clojure.string :as string] [clojure.string :as string]
[clojure.java.io :as io]) [clojure.java.io :as io]
[schema.core :as s])
(:use (:use
vwowrla.core.schemas
vwowrla.core.utils)) vwowrla.core.utils))
(def problem-entity-names (get-text-resource-as-lines "problem_entity_names.txt")) (def problem-entity-names (get-text-resource-as-lines "problem_entity_names.txt"))
@ -20,43 +22,45 @@
:fixed-to-problem {}} :fixed-to-problem {}}
problem-entity-names)) problem-entity-names))
(defn sanitize-entity-name (s/defn sanitize-entity-name :- s/Str
[^String entity-name] [entity-name :- s/Str]
(get-in problem-entity-name-to-fixed-name [:problem-to-fixed entity-name] entity-name)) (get-in problem-entity-name-to-fixed-name [:problem-to-fixed entity-name] entity-name))
(defn get-original-entity-name (s/defn get-original-entity-name :- s/Str
[^String potentially-sanitized-entity-name] [potentially-sanitized-entity-name :- s/Str]
(get-in problem-entity-name-to-fixed-name [:fixed-to-problem potentially-sanitized-entity-name] potentially-sanitized-entity-name)) (get-in problem-entity-name-to-fixed-name [:fixed-to-problem potentially-sanitized-entity-name] potentially-sanitized-entity-name))
(defn sanitize-entity-names (s/defn sanitize-entity-names :- s/Str
[^String line] [line :- s/Str]
(reduce (reduce
(fn [^String line [^String problem-name ^String fixed-name]] (fn [^String line [^String problem-name ^String fixed-name]]
(.replace line problem-name fixed-name)) (.replace line problem-name fixed-name))
line line
(:problem-to-fixed problem-entity-name-to-fixed-name))) (:problem-to-fixed problem-entity-name-to-fixed-name)))
(defn undo-swstats-fixlogstring (s/defn undo-swstats-fixlogstring :- s/Str
[^String line] [line :- s/Str]
(.replace line " 's" "'s")) (.replace ^String line " 's" "'s"))
(defn parse-log-timestamp (s/defn parse-log-timestamp :- Date
[^String timestamp {:keys [^long year ^TimeZone timezone windows?] :as options}] [timestamp :- s/Str
options :- ParserOptions]
(if-let [matches (re-matches #"^(\d{1,2})\/(\d{1,2}) (\d{1,2}):(\d{2}):(\d{2})\.(\d{3})$" timestamp)] (if-let [matches (re-matches #"^(\d{1,2})\/(\d{1,2}) (\d{1,2}):(\d{2}):(\d{2})\.(\d{3})$" timestamp)]
(let [c (GregorianCalendar.) (let [c (GregorianCalendar.)
[month day hour minute second millis] (rest matches)] [month day hour minute second millis] (rest matches)]
(.clear c) (.clear c)
(.setTimeZone c timezone) (.setTimeZone c (:timezone options))
(.set c year (if windows? (dec (->int month)) (->int month)) (->int day) (->int hour) (->int minute) (->int second)) (.set c (:year options) (if (:windows? options) (dec (->int month)) (->int month)) (->int day) (->int hour) (->int minute) (->int second))
(.set c Calendar/MILLISECOND (->int millis)) (.set c Calendar/MILLISECOND (->int millis))
(.getTime c)))) (.getTime c))))
(defn split-log-timestamp-and-content (s/defn split-log-timestamp-and-content :- [s/Str]
[^String line] [line :- s/Str]
(clojure.string/split line #" " 2)) (string/split line #" " 2))
(defn process-parsed-line (s/defn process-parsed-line :- CombatEvent
[{:keys [source-name target-name source] :as parsed-line} ^String log-owner-char-name] [{:keys [source-name target-name source] :as parsed-line} :- CombatEvent
log-owner-char-name :- s/Str]
(merge (merge
parsed-line parsed-line
(if source-name (if source-name

View file

@ -14,6 +14,15 @@
;; model schemas ;; model schemas
(def Milliseconds java.lang.Long)
(def UnixTimestamp java.lang.Long)
(def ParserOptions
{:log-owner-char-name s/Str
:year s/Int
:timezone java.util.TimeZone
(s/optional-key :windows?) s/Bool})
(def CombatEvent (def CombatEvent
{:id s/Keyword {:id s/Keyword
:logfmt s/Keyword :logfmt s/Keyword
@ -42,15 +51,23 @@
(s/optional-key :stacks) (s/maybe s/Num) (s/optional-key :stacks) (s/maybe s/Num)
(s/optional-key :faded?) s/Bool}) (s/optional-key :faded?) s/Bool})
; TODO
(def SkillStatistics
{s/Any s/Any})
; TODO
(def Entity
{s/Any s/Any})
; TODO
(def Encounter (def Encounter
{s/Any s/Any}) {s/Any s/Any})
; TODO
(def RaidAnalysis (def RaidAnalysis
{:encounters [Encounter] {:encounters [Encounter]
:active-encounter (s/maybe Encounter)}) :active-encounter (s/maybe Encounter)})
(def ParserOptions ; TODO
{:log-owner-char-name s/Str (def DamageProperties
:year s/Int {s/Any s/Any})
:timezone java.util.TimeZone
(s/optional-key :windows?) s/Bool})