Skip to content

Commit 4a29cee

Browse files
authored
Merge pull request #46 from MastodonC/feature/apply-modify-transitions-to-any-transition
Refactor build-states-to-change
2 parents ec376b5 + f28f678 commit 4a29cee

File tree

5 files changed

+94
-30
lines changed

5 files changed

+94
-30
lines changed

src/clj/witan/send/model.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
:witan/version "1.0.0"
5353
:witan/type :function
5454
:witan/fn :send/prepare-send-inputs
55-
:witan/params {:modify-transition-by 1
55+
:witan/params {:which-transitions? nil
56+
:modify-transition-by 1
5657
:splice-ncy nil
5758
:filter-transitions-from nil}}
5859
{:witan/name :run-send-model

src/clj/witan/send/schemas.clj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,6 @@
202202
:setting-cost-lookup SettingCostLookup
203203
:valid-setting-academic-years ValidSettingAcademicYears
204204
:transition-matrix TransitionCounts})
205+
206+
(def transition-type
207+
(s/maybe [s/Str]))

src/clj/witan/send/send.clj

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,20 @@
197197
{} a)
198198
b))
199199

200-
(defn generate-transition-key [cy ay need setting]
201-
(vector cy ay :NONSEND (states/state need setting)))
200+
(defn generate-transition-key [{:keys [transition-type cy ay need setting move-state]}]
201+
(when (not= move-state (states/state need setting))
202+
(case transition-type
203+
"joiners"
204+
(vector cy ay :NONSEND (states/state need setting))
205+
206+
"leavers"
207+
(vector cy ay (states/state need setting) :NONSEND)
208+
209+
"movers-to"
210+
(vector cy ay move-state (states/state need setting))
211+
212+
"movers-from"
213+
(vector cy ay (states/state need setting) move-state))))
202214

203215
(defn update-ifelse-assoc [m k arithmetic-fn v]
204216
(if (contains? m k)
@@ -260,28 +272,28 @@
260272
:mover-beta-params (p/beta-params-movers valid-states valid-transitions transition-matrix)
261273
:mover-state-alphas (p/alpha-params-movers valid-states valid-transitions transition-matrix)}))))
262274

263-
(defn build-states-to-change [settings-to-change valid-needs ages years]
264-
(if (= :nil (-> settings-to-change
265-
ds/row-maps
266-
first
267-
:setting-2))
268-
(let [states (->> settings-to-change
269-
ds/row-maps
270-
(map #(vector (:setting-1 %))))]
271-
(vec (mapcat (fn [year]
272-
(mapcat (fn [age]
273-
(mapcat (fn [need]
274-
(map (fn [setting] (vector (generate-transition-key year age need (first setting))))
275-
states)) valid-needs)) ages)) years)))
276-
(let [state-pairs (->> settings-to-change
277-
ds/row-maps
278-
(map #(vector (:setting-1 %) (:setting-2 %))))]
279-
(vec (mapcat (fn [year]
280-
(mapcat (fn [age]
281-
(mapcat (fn [need]
282-
(map (fn [setting] (vector (generate-transition-key year age need (first setting))
283-
(generate-transition-key year age need (second setting))))
284-
state-pairs)) valid-needs)) ages)) years)))))
275+
(defn build-states-to-change [input valid-needs valid-settings ages years transition-type]
276+
(let [to-maps (ds/row-maps input)
277+
settings-to-change (if (= :nil (-> to-maps
278+
first
279+
:setting-2))
280+
(map #(vector (:setting-1 %)) to-maps)
281+
(map #(vector (:setting-1 %) (:setting-2 %)) to-maps))]
282+
(->> (for [year years
283+
age ages
284+
need valid-needs
285+
setting valid-settings
286+
setting-to-change settings-to-change]
287+
(let [keys {:transition-type transition-type :cy year :ay age
288+
:need need :move-state (states/state need setting)}]
289+
(if (= :nil (-> to-maps
290+
first
291+
:setting-2))
292+
(vector (generate-transition-key (merge keys {:setting (first setting-to-change)})))
293+
(vector (generate-transition-key (merge keys {:setting (first setting-to-change)}))
294+
(generate-transition-key (merge keys {:setting (second setting-to-change)}))))))
295+
(remove #(nil? (first %)))
296+
distinct)))
285297

286298
(defworkflowfn prepare-send-inputs-1-0-0
287299
"Outputs the population for the last year of historic data, with one
@@ -294,7 +306,8 @@
294306
:transition-matrix sc/TransitionCounts
295307
:setting-cost sc/NeedSettingCost
296308
:valid-setting-academic-years sc/ValidSettingAcademicYears}
297-
:witan/param-schema {:modify-transition-by s/Num
309+
:witan/param-schema {:which-transitions? sc/transition-type
310+
:modify-transition-by s/Num
298311
:splice-ncy (s/maybe sc/AcademicYear)
299312
:filter-transitions-from (s/maybe [sc/CalendarYear])}
300313
:witan/output-schema {:standard-projection sc/projection-map
@@ -303,7 +316,7 @@
303316
:settings-to-change sc/SettingsToChange}}
304317
[{:keys [settings-to-change initial-send-population transition-matrix population
305318
setting-cost valid-setting-academic-years]}
306-
{:keys [modify-transition-by splice-ncy filter-transitions-from]}]
319+
{:keys [which-transitions? modify-transition-by splice-ncy filter-transitions-from]}]
307320
(let [original-transitions transition-matrix
308321
ages (distinct (map :academic-year (ds/row-maps population)))
309322
years (distinct (map :calendar-year (ds/row-maps population)))
@@ -314,7 +327,7 @@
314327
valid-states (states/calculate-valid-states-from-setting-academic-years initialise-validation)
315328
valid-year-settings (states/calculate-valid-year-settings-from-setting-academic-years initialise-validation)
316329
states-to-change (when (not= 1 modify-transition-by)
317-
(build-states-to-change settings-to-change valid-needs ages years))
330+
(mapcat (fn [transition-type] (build-states-to-change settings-to-change valid-needs valid-settings ages years transition-type)) which-transitions?))
318331
transition-matrix (ds/row-maps transition-matrix)
319332
modified-transition-matrix (when (not= 1 modify-transition-by)
320333
(let [convert (-> transition-matrix

test/witan/send/acceptance/workspace_test.clj

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,21 @@
5555
5656
:transitions-file - csv containing list of settings to modify by :transition-modifier (optional)
5757
58+
:which-transitions? - vector of either one or more transition type strings i.e. \"joiners\", \"movers-to\",
59+
\"movers-from\" or \"leavers\", used in conjunction with :transition-modifier and :transitions-file (optional)
60+
5861
:modify-transitions-from - set a year to start modifying transitions from when :transition-modifier & :transitions-file are set (optional)
5962
6063
:filter-transitions-from - sets a year or year range as a vector to filter historic transitions by for :splice-ncy (optional)
6164
6265
:splice-ncy - sets a national curriculum year to ignore transitions of prior to :filter-transitions-from year (optional)"
63-
[{:keys [iterations output? transition-modifier transitions-file modify-transitions-from filter-transitions-from splice-ncy]}]
66+
[{:keys [iterations output? transition-modifier transitions-file which-transitions?
67+
modify-transitions-from filter-transitions-from splice-ncy]}]
6468
(report/reset-send-report)
6569
(report/info "Input Data: " (report/bold (str/replace (str/join "" (drop-last inputs-path)) #"/" " ")))
6670
(report/info "Number of iterations: " (report/bold iterations))
6771
(report/info "Output charts produced: " (report/bold output?))
72+
(report/info "Modifying " (report/bold (if (nil? which-transitions?) "None" (str/join ", " which-transitions?))))
6873
(report/info "Transitions modifier: " (report/bold (if (nil? transition-modifier) "None" transition-modifier)))
6974
(report/info "Transitions file: " (report/bold (if (nil? transitions-file) "None" transitions-file)))
7075
(report/info "Modify transitions from: " (report/bold (if (nil? modify-transitions-from) "None" modify-transitions-from)))
@@ -80,7 +85,9 @@
8085
(map #(assoc-in % [:witan/params :output] output?)))
8186
prep-catalog2 (if (nil? transition-modifier)
8287
prep-catalog1
83-
(map #(assoc-in % [:witan/params :modify-transition-by] transition-modifier) prep-catalog1))
88+
(->> prep-catalog1
89+
(map #(assoc-in % [:witan/params :modify-transition-by] transition-modifier))
90+
(map #(assoc-in % [:witan/params :which-transitions?] which-transitions?))))
8491
prep-catalog3 (if (nil? modify-transitions-from)
8592
prep-catalog2
8693
(map #(assoc-in % [:witan/params :modify-transitions-from] modify-transitions-from) prep-catalog2))]

test/witan/send/send_test.clj

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,43 @@
199199
(is (= 2 (:foo (update-ifelse-assoc {:foo 1 :bar 2} :foo + 1)))))
200200
(testing "if key not present, insert key with val"
201201
(is (= 1 (:foo (update-ifelse-assoc {:baz 1 :bar 2} :foo + 1))))))
202+
203+
(deftest generate-transition-key-test
204+
(testing "generate joiner state transition"
205+
(is (= [2013 5 :NONSEND :CI-MSSOB]
206+
(generate-transition-key {:transition-type "joiners" :cy 2013 :ay 5
207+
:need :CI :move-state :CI-MSSIB
208+
:setting :MSSOB}))))
209+
(testing "generate leaver state transition"
210+
(is (= [2013 5 :CI-MSSOB :NONSEND]
211+
(generate-transition-key {:transition-type "leavers" :cy 2013 :ay 5
212+
:need :CI :move-state :CI-MSSIB
213+
:setting :MSSOB}))))
214+
(testing "generate joiner state transition"
215+
(is (= [2013 5 :CI-MSSIB :CI-MSSOB]
216+
(generate-transition-key {:transition-type "movers-to" :cy 2013 :ay 5
217+
:need :CI :move-state :CI-MSSIB
218+
:setting :MSSOB}))))
219+
(testing "generate joiner state transition"
220+
(is (= [2013 5 :CI-MSSOB :CI-MSSIB]
221+
(generate-transition-key {:transition-type "movers-from" :cy 2013 :ay 5
222+
:need :CI :move-state :CI-MSSIB
223+
:setting :MSSOB})))))
224+
225+
(deftest build-states-to-change-test
226+
(let [input (ds/dataset [{:setting-1 :MMSOB :setting-2 :MMSIB}])]
227+
(testing "move MSSOB joiners to MSSIB"
228+
(is (= [[2013 5 :NONSEND :CI-MMSOB] [2013 5 :NONSEND :CI-MMSIB]]
229+
(first (build-states-to-change input [:CI] [:MSSOB] [5] [2013] "joiners")))))
230+
(testing "move MSSOB leavers to MSSIB"
231+
(is (= [[2013 5 :CI-MMSOB :NONSEND] [2013 5 :CI-MMSIB :NONSEND]]
232+
(first (build-states-to-change input [:CI] [:MSSOB] [5] [2013] "leavers")))))
233+
(testing "move MSSOB movers-to to MSSIB"
234+
(is (= [[2013 5 :CI-MSSOB :CI-MMSOB] [2013 5 :CI-MSSOB :CI-MMSIB]]
235+
(first (build-states-to-change input [:CI] [:MSSOB] [5] [2013] "movers-to")))))
236+
(testing "move MSSOB movers-from to MSSIB"
237+
(is (= [[2013 5 :CI-MMSOB :CI-MSSOB] [2013 5 :CI-MMSIB :CI-MSSOB]]
238+
(first (build-states-to-change input [:CI] [:MSSOB] [5] [2013] "movers-from")))))
239+
(testing "return nil when move to and from state the same"
240+
(is (= nil
241+
(first (build-states-to-change input [:CI] [:MMSOB] [5] [2013] "movers-to")))))))

0 commit comments

Comments
 (0)